diff --git a/openbsc/include/sccp/sccp.h b/openbsc/include/sccp/sccp.h index 643479adc..604a2ac72 100644 --- a/openbsc/include/sccp/sccp.h +++ b/openbsc/include/sccp/sccp.h @@ -94,7 +94,7 @@ struct sccp_connection { * call sccp_system_incoming for incoming data (from the network) * sccp will call outgoing whenever outgoing data exists */ -int sccp_system_init(int (*outgoing)(struct msgb *data, void *ctx), void *context); +int sccp_system_init(void (*outgoing)(struct msgb *data, void *ctx), void *context); int sccp_system_incoming(struct msgb *data); /** @@ -105,6 +105,11 @@ int sccp_connection_send_it(struct sccp_connection *connection); int sccp_connection_close(struct sccp_connection *connection, int cause); int sccp_connection_free(struct sccp_connection *connection); +/** + * internal.. + */ +int sccp_connection_force_free(struct sccp_connection *conn); + /** * Create a new socket. Set your callbacks and then call bind to open * the connection. diff --git a/openbsc/src/sccp/sccp.c b/openbsc/src/sccp/sccp.c index b1da2c721..e0fd02e0e 100644 --- a/openbsc/src/sccp/sccp.c +++ b/openbsc/src/sccp/sccp.c @@ -45,7 +45,7 @@ const struct sockaddr_sccp sccp_ssn_bssap = { struct sccp_system { /* layer3 -> layer2 */ - int (*write_data)(struct msgb *data, void *context); + void (*write_data)(struct msgb *data, void *context); void *write_context; }; @@ -91,9 +91,9 @@ static struct sccp_data_callback *_find_ssn(u_int8_t ssn) } -static int _send_msg(struct msgb *msg) +static void _send_msg(struct msgb *msg) { - return sccp_system.write_data(msg, sccp_system.write_context); + sccp_system.write_data(msg, sccp_system.write_context); } /* @@ -499,7 +499,6 @@ static int _sccp_send_data(int class, const struct sockaddr_sccp *in, { struct sccp_data_unitdata *udt; u_int8_t *data; - int ret; if (msgb_l3len(payload) > 256) { DEBUGP(DSCCP, "The payload is too big for one udt\n"); @@ -533,10 +532,8 @@ static int _sccp_send_data(int class, const struct sockaddr_sccp *in, data[0] = msgb_l3len(payload); memcpy(&data[1], payload->l3h, msgb_l3len(payload)); - ret = _send_msg(msg); - msgb_free(msg); - - return ret; + _send_msg(msg); + return 0; } static int _sccp_handle_read(struct msgb *msgb) @@ -627,7 +624,6 @@ static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause) struct msgb *msgb; struct sccp_connection_refused *ref; u_int8_t *data; - int ret; msgb = msgb_alloc_headroom(SCCP_MSG_SIZE, SCCP_MSG_HEADROOM, "sccp ref"); @@ -643,9 +639,8 @@ static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause) data = msgb_put(msgb, 1); data[0] = SCCP_PNC_END_OF_OPTIONAL; - ret = _send_msg(msgb); - msgb_free(msgb); - return ret; + _send_msg(msgb); + return 0; } static int _sccp_send_connection_confirm(struct sccp_connection *connection) @@ -653,7 +648,6 @@ static int _sccp_send_connection_confirm(struct sccp_connection *connection) struct msgb *response; struct sccp_connection_confirm *confirm; u_int8_t *optional_data; - int ret; if (assign_source_local_reference(connection) != 0) return -1; @@ -677,11 +671,9 @@ static int _sccp_send_connection_confirm(struct sccp_connection *connection) optional_data = (u_int8_t *) msgb_put(response, 1); optional_data[0] = SCCP_PNC_END_OF_OPTIONAL; - ret = _send_msg(response); - msgb_free(response); - + _send_msg(response); _sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_ESTABLISHED); - return ret; + return 0; } static int _sccp_send_connection_request(struct sccp_connection *connection, @@ -691,7 +683,6 @@ static int _sccp_send_connection_request(struct sccp_connection *connection, struct sccp_connection_request *req; u_int8_t *data; u_int8_t extra_size = 3 + 1; - int ret; if (msg && (msgb_l3len(msg) < 3 || msgb_l3len(msg) > 130)) { @@ -741,10 +732,8 @@ static int _sccp_send_connection_request(struct sccp_connection *connection, llist_add_tail(&connection->list, &sccp_connections); _sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_REQUEST); - ret = _send_msg(request); - msgb_free(request); - - return ret; + _send_msg(request); + return 0; } static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb *_data) @@ -753,7 +742,6 @@ static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb struct sccp_data_form1 *dt1; u_int8_t *data; int extra_size; - int ret; if (msgb_l3len(_data) < 2 || msgb_l3len(_data) > 256) { DEBUGP(DSCCP, "data size too big, segmenting unimplemented.\n"); @@ -777,17 +765,14 @@ static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb data[0] = extra_size - 1; memcpy(&data[1], _data->l3h, extra_size - 1); - ret = _send_msg(msgb); - msgb_free(msgb); - - return ret; + _send_msg(msgb); + return 0; } static int _sccp_send_connection_it(struct sccp_connection *conn) { struct msgb *msgb; struct sccp_data_it *it; - int ret; msgb = msgb_alloc_headroom(SCCP_MSG_SIZE, SCCP_MSG_HEADROOM, "sccp it"); @@ -803,9 +788,8 @@ static int _sccp_send_connection_it(struct sccp_connection *conn) it->sequencing[0] = it->sequencing[1] = 0; it->credit = 0; - ret = _send_msg(msgb); - msgb_free(msgb); - return ret; + _send_msg(msgb); + return 0; } static int _sccp_send_connection_released(struct sccp_connection *conn, int cause) @@ -813,7 +797,6 @@ static int _sccp_send_connection_released(struct sccp_connection *conn, int caus struct msgb *msg; struct sccp_connection_released *rel; u_int8_t *data; - int ret; msg = msgb_alloc_headroom(SCCP_MSG_SIZE, SCCP_MSG_HEADROOM, "sccp: connection released"); @@ -832,10 +815,8 @@ static int _sccp_send_connection_released(struct sccp_connection *conn, int caus data[0] = SCCP_PNC_END_OF_OPTIONAL; _sccp_set_connection_state(conn, SCCP_CONNECTION_STATE_RELEASE); - ret = _send_msg(msg); - msgb_free(msg); - - return ret; + _send_msg(msg); + return 0; } /* @@ -982,7 +963,6 @@ static int _sccp_send_connection_release_complete(struct sccp_connection *connec { struct msgb *msgb; struct sccp_connection_release_complete *rlc; - int ret; msgb = msgb_alloc_headroom(SCCP_MSG_SIZE, SCCP_MSG_HEADROOM, "sccp rlc"); @@ -995,8 +975,7 @@ static int _sccp_send_connection_release_complete(struct sccp_connection *connec memcpy(&rlc->source_local_reference, &connection->source_local_reference, sizeof(struct sccp_source_reference)); - ret = _send_msg(msgb); - msgb_free(msgb); + _send_msg(msgb); /* * Remove from the list of active connections and set the state. User code @@ -1004,8 +983,7 @@ static int _sccp_send_connection_release_complete(struct sccp_connection *connec */ llist_del(&connection->list); _sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_RELEASE_COMPLETE); - - return ret; + return 0; } /* connection released, send a released confirm */ @@ -1118,7 +1096,7 @@ found: } -int sccp_system_init(int (*outgoing)(struct msgb *data, void *ctx), void *ctx) +int sccp_system_init(void (*outgoing)(struct msgb *data, void *ctx), void *ctx) { sccp_system.write_data = outgoing; sccp_system.write_context = ctx; @@ -1220,6 +1198,17 @@ int sccp_connection_free(struct sccp_connection *connection) return 0; } +int sccp_connection_force_free(struct sccp_connection *con) +{ + if (con->connection_state > SCCP_CONNECTION_STATE_NONE && + con->connection_state < SCCP_CONNECTION_STATE_RELEASE_COMPLETE) + llist_del(&con->list); + + con->connection_state = SCCP_CONNECTION_STATE_REFUSED; + sccp_connection_free(con); + return 0; +} + struct sccp_connection *sccp_connection_socket(void) { return talloc_zero(tall_sccp_ctx, struct sccp_connection); diff --git a/openbsc/tests/sccp/sccp_test.c b/openbsc/tests/sccp/sccp_test.c index eb41d3eaf..0c2adc83f 100644 --- a/openbsc/tests/sccp/sccp_test.c +++ b/openbsc/tests/sccp/sccp_test.c @@ -354,14 +354,14 @@ int sccp_read_cb(struct msgb *data, unsigned len, void *context) return 0; } -int sccp_write_cb(struct msgb *data, void *ctx) +void sccp_write_cb(struct msgb *data, void *ctx) { int i = 0; const u_int8_t *got, *wanted; if (test_data[current_test].response == NULL) { FAIL("Didn't expect write callback\n"); - return -1; + goto exit; } else if (test_data[current_test].response_length != msgb_l2len(data)) { FAIL("Size does not match. Got: %d Wanted: %d\n", msgb_l2len(data), test_data[current_test].response_length); @@ -374,12 +374,14 @@ int sccp_write_cb(struct msgb *data, void *ctx) if (got[i] != wanted[i]) { FAIL("Failed to compare byte. Got: 0x%x Wanted: 0x%x at %d\n", got[i], wanted[i], i); - return -1; + goto exit; } } write_called = 1; - return 0; + +exit: + msgb_free(data); } void sccp_c_read(struct sccp_connection *connection, struct msgb *msgb, unsigned int len) @@ -409,7 +411,7 @@ int sccp_accept_cb(struct sccp_connection *connection, void *user_data) return 0; } -static int sccp_udt_write_cb(struct msgb *data, void *context) +static void sccp_udt_write_cb(struct msgb *data, void *context) { const u_int8_t *got, *wanted; int i; @@ -419,7 +421,7 @@ static int sccp_udt_write_cb(struct msgb *data, void *context) if (send_data[current_test].length != msgb_l2len(data)) { FAIL("Size does not match. Got: %d Wanted: %d\n", msgb_l2len(data), send_data[current_test].length); - return -1; + goto exit; } got = &data->l2h[0]; @@ -429,12 +431,14 @@ static int sccp_udt_write_cb(struct msgb *data, void *context) if (got[i] != wanted[i]) { FAIL("Failed to compare byte. Got: 0x%x Wanted: 0x%x at %d\n", got[i], wanted[i], i); - return -1; + goto exit; } } matched = 1; - return 0; + +exit: + msgb_free(data); } static void test_sccp_system(void) @@ -504,11 +508,11 @@ static int sccp_udt_read(struct msgb *data, unsigned int len, void *context) return 0; } -static int sccp_write_loop(struct msgb *data, void *context) +static void sccp_write_loop(struct msgb *data, void *context) { /* send it back to us */ sccp_system_incoming(data); - return 0; + msgb_free(data); } static void test_sccp_udt_communication(void)