aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/src/sccp/sccp.c108
1 files changed, 60 insertions, 48 deletions
diff --git a/openbsc/src/sccp/sccp.c b/openbsc/src/sccp/sccp.c
index 4c59acc04..2d43aac26 100644
--- a/openbsc/src/sccp/sccp.c
+++ b/openbsc/src/sccp/sccp.c
@@ -199,9 +199,54 @@ static int _sccp_parse_optional_data(const int offset,
return -1;
}
-int _sccp_parse_connection_request(struct msgb *msg, struct sccp_parse_result *result)
+int _sccp_parse_connection_request(struct msgb *msgb, struct sccp_parse_result *result)
{
- return -1;
+ static const u_int32_t header_size =
+ sizeof(struct sccp_connection_request);
+ static const u_int32_t optional_offset =
+ offsetof(struct sccp_connection_request, optional_start);
+ static const u_int32_t called_offset =
+ offsetof(struct sccp_connection_request, variable_called);
+
+ struct sccp_connection_request *req = (struct sccp_connection_request *)msgb->data;
+ struct sccp_optional_data optional_data;
+
+ /* header check */
+ if (msgb_l2len(msgb) < header_size) {
+ DEBUGP(DSCCP, "msgb < header_size %u %u\n",
+ msgb_l2len(msgb), header_size);
+ return -1;
+ }
+
+ /* copy out the calling and called address. Add the offset */
+ if (copy_address(&result->called, called_offset + req->variable_called, msgb) != 0)
+ return -1;
+
+ if (check_address(&result->called) != 0) {
+ DEBUGP(DSCCP, "Invalid called address according to 08.06: 0x%x 0x%x\n",
+ *(u_int8_t *)&result->called.address, result->called.ssn);
+ return -1;
+ }
+
+ result->source_local_reference = &req->source_local_reference;
+
+ /*
+ * parse optional data.
+ */
+ memset(&optional_data, 0, sizeof(optional_data));
+ if (_sccp_parse_optional_data(optional_offset + req->optional_start, msgb, &optional_data) != 0) {
+ DEBUGP(DSCCP, "parsing of optional data failed.\n");
+ return -1;
+ }
+
+ if (optional_data.data_len != 0) {
+ msgb->l3h = &msgb->l2h[optional_data.data_start];
+ result->data_len = optional_data.data_len;
+ } else {
+ result->data_len = 0;
+ }
+
+ return 0;
}
int _sccp_parse_connection_released(struct msgb *msg, struct sccp_parse_result *result)
@@ -413,7 +458,7 @@ static void _sccp_set_connection_state(struct sccp_connection *connection, int n
connection->state_cb(connection, old_state);
}
-static int _sccp_send_refuse(struct sccp_connection_request *req, int cause)
+static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
{
struct msgb *msgb;
struct sccp_connection_refused *ref;
@@ -426,7 +471,7 @@ static int _sccp_send_refuse(struct sccp_connection_request *req, int cause)
ref = (struct sccp_connection_refused *) msgb_put(msgb, sizeof(*ref));
ref->type = SCCP_MSG_TYPE_CREF;
- memcpy(&ref->destination_local_reference, &req->source_local_reference,
+ memcpy(&ref->destination_local_reference, src_ref,
sizeof(struct sccp_source_reference));
ref->cause = cause;
ref->optional_start = 1;
@@ -640,39 +685,17 @@ static int _sccp_send_connection_released(struct sccp_connection *conn, int caus
*/
static int _sccp_handle_connection_request(struct msgb *msgb)
{
- static const u_int32_t header_size =
- sizeof(struct sccp_connection_request);
- static const u_int32_t optional_offset =
- offsetof(struct sccp_connection_request, optional_start);
- static const u_int32_t called_offset =
- offsetof(struct sccp_connection_request, variable_called);
+ struct sccp_parse_result result;
struct sccp_data_callback *cb;
- struct sccp_connection_request *req = (struct sccp_connection_request *)msgb->data;
- struct sccp_address called;
struct sccp_connection *connection;
- struct sccp_optional_data optional_data;
- /* header check */
- if (msgb_l2len(msgb) < header_size) {
- DEBUGP(DSCCP, "msgb < header_size %u %u\n",
- msgb_l2len(msgb), header_size);
+ if (_sccp_parse_connection_request(msgb, &result) != 0)
return -1;
- }
- /* copy out the calling and called address. Add the offset */
- if (copy_address(&called, called_offset + req->variable_called, msgb) != 0)
- return -1;
-
- if (check_address(&called) != 0) {
- DEBUGP(DSCCP, "Invalid called address according to 08.06: 0x%x 0x%x\n",
- *(u_int8_t *)&called.address, called.ssn);
- return -1;
- }
-
- cb = _find_ssn(called.ssn);
+ cb = _find_ssn(result.called.ssn);
if (!cb || !cb->accept_cb) {
- DEBUGP(DSCCP, "No routing for CR for called SSN: %u\n", called.ssn);
+ DEBUGP(DSCCP, "No routing for CR for called SSN: %u\n", result.called.ssn);
return -1;
}
@@ -690,28 +713,18 @@ static int _sccp_handle_connection_request(struct msgb *msgb)
* and send a connection confirm, otherwise we will send a refuseed
* one....
*/
- if (destination_local_reference_is_free(&req->source_local_reference) != 0) {
+ if (destination_local_reference_is_free(result.source_local_reference) != 0) {
DEBUGP(DSCCP, "Need to reject connection with existing reference\n");
- _sccp_send_refuse(req, SCCP_REFUSAL_SCCP_FAILURE);
+ _sccp_send_refuse(result.source_local_reference, SCCP_REFUSAL_SCCP_FAILURE);
talloc_free(connection);
return -1;
}
connection->incoming = 1;
- connection->destination_local_reference = req->source_local_reference;
-
- /*
- * parse optional data.
- */
- memset(&optional_data, 0, sizeof(optional_data));
- if (_sccp_parse_optional_data(optional_offset + req->optional_start, msgb, &optional_data) != 0) {
- DEBUGP(DSCCP, "parsing of optional data failed.\n");
- talloc_free(connection);
- return -1;
- }
+ connection->destination_local_reference = *result.source_local_reference;
if (cb->accept_cb(connection, cb->accept_context) != 0) {
- _sccp_send_refuse(req, SCCP_REFUSAL_END_USER_ORIGINATED);
+ _sccp_send_refuse(result.source_local_reference, SCCP_REFUSAL_END_USER_ORIGINATED);
_sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_REFUSED);
talloc_free(connection);
return 0;
@@ -723,7 +736,7 @@ static int _sccp_handle_connection_request(struct msgb *msgb)
if (_sccp_send_connection_confirm(connection) != 0) {
DEBUGP(DSCCP, "Sending confirm failed... no available source reference?\n");
- _sccp_send_refuse(req, SCCP_REFUSAL_SCCP_FAILURE);
+ _sccp_send_refuse(result.source_local_reference, SCCP_REFUSAL_SCCP_FAILURE);
_sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_REFUSED);
llist_del(&connection->list);
talloc_free(connection);
@@ -734,9 +747,8 @@ static int _sccp_handle_connection_request(struct msgb *msgb)
/*
* If we have data let us forward things.
*/
- if (optional_data.data_len != 0 && connection->data_cb) {
- msgb->l3h = &msgb->l2h[optional_data.data_start];
- connection->data_cb(connection, msgb, optional_data.data_len);
+ if (result.data_len != 0 && connection->data_cb) {
+ connection->data_cb(connection, msgb, result.data_len);
}
return 0;