From patchwork Mon May 23 22:01:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gerrit-no-reply@lists.osmocom.org X-Patchwork-Id: 625415 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.osmocom.org (lists.osmocom.org [IPv6:2a01:4f8:191:444b::2:7]) by ozlabs.org (Postfix) with ESMTP id 3rDCD65QdKz9t5q for ; Tue, 24 May 2016 08:01:10 +1000 (AEST) Received: from lists.osmocom.org (lists.osmocom.org [144.76.43.76]) by lists.osmocom.org (Postfix) with ESMTP id 3C34A63B6; Mon, 23 May 2016 22:01:09 +0000 (UTC) X-Original-To: openbsc@lists.osmocom.org Delivered-To: openbsc@lists.osmocom.org Received: from 127.0.1.12 (unknown [127.0.1.12]) by lists.osmocom.org (Postfix) with ESMTPA id 96C8F63B0; Mon, 23 May 2016 22:01:07 +0000 (UTC) Date: Mon, 23 May 2016 22:01:07 +0000 From: Arran Cudbard-bell X-Gerrit-MessageType: newpatchset Subject: [PATCH] libosmo-sccp[master]: Add selector for ANSI or ITU variant X-Gerrit-Change-Id: Ia17eef8c9b7d8e1092c587f469b4a68aa9702651 X-Gerrit-ChangeURL: X-Gerrit-Commit: 15139e2a5d3682f9e458b528f352b0baf39d32ab In-Reply-To: References: MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/2.12.2-31-gb331dbd-dirty X-BeenThere: openbsc@lists.osmocom.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "Development of OpenBSC, OsmoBSC, OsmoNITB, OsmoCSCN" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: a.cudbardb@freeradius.org Errors-To: openbsc-bounces@lists.osmocom.org Sender: "OpenBSC" Message-Id: <20160523220109.3C34A63B6@lists.osmocom.org> Hello Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/73 to look at the new patch set (#4). Add selector for ANSI or ITU variant Change-Id: Ia17eef8c9b7d8e1092c587f469b4a68aa9702651 --- M include/sccp/sccp.h M include/sccp/sccp_types.h M src/sccp.c M tests/sccp/sccp_test.c 4 files changed, 135 insertions(+), 59 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/73/73/4 diff --git a/include/sccp/sccp.h b/include/sccp/sccp.h index 36b424f..4b0bbd3 100644 --- a/include/sccp/sccp.h +++ b/include/sccp/sccp.h @@ -46,21 +46,32 @@ SCCP_CONNECTION_STATE_SETUP_ERROR, }; -struct sockaddr_sccp { - sa_family_t sccp_family; /* AF_SCCP in the future??? */ - uint8_t sccp_ssn; /* subssystem number for routing */ +struct sccp_variant { + uint8_t ai_national; /* National or reserved bit */ + uint8_t ai_gti_ind; /* GTI mask */ + uint8_t ai_pc_ind; /* Point code indicator mask */ + uint8_t ai_ssn_ind; /* SSN indicator mask */ + uint8_t ai_route_ind; /* Route type mask */ + uint8_t pc_len; /* Point code length */ + uint8_t pc_first; /* whether the pointcode comes before the SSN */ +}; - /* TODO fill in address indicator... if that is ever needed */ +struct sockaddr_sccp { + sa_family_t sccp_family; /* AF_SCCP in the future??? */ + + uint8_t use_poi : 1, /* Include Point Code */ + use_ssn : 1, /* Include SSN */ + gti_ind : 4, /* Any of SCCP_TITLE_IND_* */ + route_ind : 1, /* Route on SSN instead of GTI */ + national : 1; /* National address format in ANSI, national usage/reserved in ITU */ + + uint8_t poi[3]; /* Allows ITU 14bit and ANSI 24bit */ + + uint8_t ssn; /* SubsSystem number for routing */ /* optional gti information */ - uint8_t *gti; + uint8_t *gti_data; int gti_len; - - /* any of SCCP_TITLE_IND_* */ - uint8_t gti_ind; - - int use_poi; - uint8_t poi[2]; /* not sure about these */ /* uint8_t sccp_class; */ @@ -70,9 +81,8 @@ * parsed structure of an address */ struct sccp_address { - struct sccp_called_party_address address; uint8_t ssn; - uint8_t poi[2]; + uint8_t poi[3]; /* Allows ITU 14bit and ANSI 24bit */ uint8_t *gti_data; int gti_len; @@ -103,6 +113,8 @@ int incoming; }; +extern struct sccp_variant sccp_variant[]; + /** * system functionality to implement on top of any other transport layer: * call sccp_system_incoming for incoming data (from the network) @@ -122,7 +134,7 @@ int sccp_connection_free(struct sccp_connection *connection); /** - * internal.. + * internal.. */ int sccp_connection_force_free(struct sccp_connection *conn); @@ -157,6 +169,7 @@ int sccp_set_read(const struct sockaddr_sccp *sock, int (*read_cb)(struct msgb *msgb, unsigned int, void *user_data), void *user_data); +void sccp_set_variant(int variant); /* generic sock addresses */ extern const struct sockaddr_sccp sccp_ssn_bssap; diff --git a/include/sccp/sccp_types.h b/include/sccp/sccp_types.h index 986de0d..cd60c25 100644 --- a/include/sccp/sccp_types.h +++ b/include/sccp/sccp_types.h @@ -26,6 +26,12 @@ #include +/* Which variant of SCCP we're using */ +enum { + SCCP_VARIANT_ITU, + SCCP_VARIANT_ANSI +}; + /* Table 1/Q.713 - SCCP message types */ enum sccp_message_types { SCCP_MSG_TYPE_CR = 1, diff --git a/src/sccp.c b/src/sccp.c index e6c538d..2c52839 100644 --- a/src/sccp.c +++ b/src/sccp.c @@ -46,16 +46,40 @@ .sccp_ssn = SCCP_SSN_BSSAP, }; +struct sccp_variant sccp_variant[] = { + [SCCP_VARIANT_ITU] = { + .ai_national = 0x80, + .ai_gti_ind = 0x3c, + .ai_pc_ind = 0x01, + .ai_ssn_ind = 0x02, + .ai_route_ind = 0x40, + .pc_len = 2, + .pc_first = 1 + }, + [SCCP_VARIANT_ANSI] = { + .ai_national = 0x80, + .ai_gti_ind = 0x3c, + .ai_pc_ind = 0x02, + .ai_ssn_ind = 0x01, + .ai_route_ind = 0x40, + .pc_len = 3, + .pc_first = 0, + } +}; + struct sccp_system { /* layer3 -> layer2 */ void (*write_data)(struct sccp_connection *conn, struct msgb *data, void *gctx, void *ctx); void *write_context; + + int variant; }; static struct sccp_system sccp_system = { .write_data = NULL, + .variant = SCCP_VARIANT_ITU }; struct sccp_data_callback { @@ -105,11 +129,13 @@ */ static int copy_address(struct sccp_address *addr, uint8_t offset, struct msgb *msgb) { - struct sccp_called_party_address *party; - int room = msgb_l2len(msgb) - offset; + + uint8_t *data; uint8_t read = 0; uint8_t length; + uint8_t ai; + uint8_t pc_len = sccp_variant[sccp_system.variant].pc_len; if (room <= 0) { LOGP(DSCCP, LOGL_ERROR, "Not enough room for an address: %u\n", room); @@ -122,36 +148,48 @@ return -1; } + data = msgb->l2h + offset + 1; + ai = data[0]; + read++; - party = (struct sccp_called_party_address *)(msgb->l2h + offset + 1); - if (party->point_code_indicator) { - if (length <= read + 2) { - LOGP(DSCCP, LOGL_ERROR, "POI does not fit %u\n", length); - return -1; - } +#define PARSE_POI \ + do { \ + if (ai & sccp_variant[sccp_system.variant].ai_pc_ind) { \ + if (length < (read + pc_len)) { \ + LOGP(DSCCP, LOGL_ERROR, "POI does not fit %u\n", length); \ + return -1; \ + } \ + memcpy(&addr->poi, &data[read], pc_len); \ + read += pc_len; \ + } \ + } while (0) +#define PARSE_SSN \ + do { \ + if (ai & sccp_variant[sccp_system.variant].ai_ssn_ind) { \ + if (length < (read + 1)) { \ + LOGP(DSCCP, LOGL_ERROR, "SSN does not fit %u\n", length); \ + return -1; \ + } \ + addr->ssn = data[read]; \ + read += 1; \ + } \ + } while (0) - memcpy(&addr->poi, &party->data[read], 2); - read += 2; - } - - if (party->ssn_indicator) { - if (length <= read + 1) { - LOGP(DSCCP, LOGL_ERROR, "SSN does not fit %u\n", length); - return -1; - } - - addr->ssn = party->data[read]; - read += 1; + if (sccp_variant[sccp_system.variant].pc_first) { + PARSE_POI; + PARSE_SSN; + } else { + PARSE_SSN; + PARSE_POI; } /* copy the GTI over */ - if (party->global_title_indicator) { - addr->gti_len = length - read - 1; - addr->gti_data = &party->data[read]; + if (ai & sccp_variant[sccp_system.variant].ai_gti) { + addr->gti_len = length - read; + addr->gti_data = &data[read]; } - addr->address = *party; return 0; } @@ -173,7 +211,6 @@ uint8_t length = msgb->l2h[offset + read + 1]; read += 2 + length; - if (room <= read) { LOGP(DSCCP, LOGL_ERROR, @@ -486,32 +523,47 @@ int sccp_create_sccp_addr(struct msgb *msg, const struct sockaddr_sccp *sock) { uint8_t *len, *ai, *gti; + uint8_t *poi; + uint8_t pc_len = sccp_variant[sccp_system.variant].pc_len; len = msgb_put(msg, 1); ai = msgb_put(msg, 1); + if (sock->gti_data) ai[0] = (sock->gti_ind & 0x0f) << 2; + if (sock->route_ind || !sock->gti_data) ai[0] |= sccp_variant[sccp_system.variant].ai_route_ind; - if (sock->gti) - ai[0] = 0 << 6 | (sock->gti_ind & 0x0f) << 2 | 1 << 1; - else - ai[0] = 1 << 6 | 1 << 1; + /* National/reserved bit */ + if (sock->national) ai[0] |= sccp_variant[sccp_system.variant].ai_national; - /* store a point code */ - if (sock->use_poi) { - uint8_t *poi; + /* Pointcode ind */ + if (sock->use_poi) ai[0] |= sccp_variant[sccp_system.variant].ai_pc_ind; - ai[0] |= 0x01; - poi = msgb_put(msg, 2); - poi[0] = sock->poi[0]; - poi[1] = sock->poi[1]; + /* SSN ind */ + ai[0] |= sccp_variant[sccp_system.variant].ai_ssn_ind; + +#define ADD_POI \ + do { \ + if (sock->use_poi) { \ + poi = msgb_put(msg, pc_len); \ + if (!poi) return -1; \ + memcpy(poi, &sock->poi[0], pc_len); \ + } \ + } while (0) + +#define ADD_SSN \ + msgb_v_put(msg, sock->ssn) + + if (sccp_variant[sccp_system.variant].pc_first) { + ADD_POI; + ADD_SSN; + } else { + ADD_SSN; + ADD_POI; } - - /* copy the SSN */ - msgb_v_put(msg, sock->sccp_ssn); /* copy the gti if it is present */ gti = msgb_put(msg, sock->gti_len); - memcpy(gti, sock->gti, sock->gti_len); + memcpy(gti, sock->gti_data, sock->gti_len); /* update the length now */ len[0] = msg->tail - len - 1; @@ -1225,6 +1277,11 @@ return 0; } +void sccp_set_variant(int variant) +{ + sccp_system.variant = variant; +} + /* oh my god a real SCCP packet. need to dispatch it now */ int sccp_system_incoming(struct msgb *msgb) { @@ -1355,7 +1412,7 @@ if (!sock) return -2; - cb = _find_ssn(sock->sccp_ssn); + cb = _find_ssn(sock->ssn); if (!cb) return -1; @@ -1378,7 +1435,7 @@ if (!sock) return -2; - cb = _find_ssn(sock->sccp_ssn); + cb = _find_ssn(sock->ssn); if (!cb) return -1; diff --git a/tests/sccp/sccp_test.c b/tests/sccp/sccp_test.c index 6043cff..f3155d3 100644 --- a/tests/sccp/sccp_test.c +++ b/tests/sccp/sccp_test.c @@ -873,15 +873,15 @@ if (parse_result[current_test].dst_ssn != -1 && parse_result[current_test].dst_ssn != result.called.ssn) { - FAIL("Called SSN is wrong..\n"); + FAIL("Called SSN is wrong...\n"); } if (parse_result[current_test].src_gti_len != result.calling.gti_len) { - FAIL("GTI length is wrong: %d\n", result.calling.gti_len); + FAIL("GTI length is wrong: Expected %d, got %d\n", parse_result[current_test].src_gti_len, result.calling.gti_len); } if (parse_result[current_test].dst_gti_len != result.called.gti_len) { - FAIL("GTI length is wrong: %d\n", result.called.gti_len); + FAIL("GTI length is wrong: Expected %d, got %d\n", parse_result[current_test].dst_gti_len, result.called.gti_len); } if (memcmp(&parse_result[current_test].dst_gti_data[0],