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 (#5).

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, 147 insertions(+), 76 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/73/73/5

diff --git a/include/sccp/sccp.h b/include/sccp/sccp.h
index 36b424f..37a3b61 100644
--- a/include/sccp/sccp.h
+++ b/include/sccp/sccp.h
@@ -46,36 +46,35 @@
        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; */
-};
-
-/*
- * parsed structure of an address
- */
-struct sccp_address {
-       struct sccp_called_party_address    address;
-       uint8_t                     ssn;
-       uint8_t                     poi[2];
-
-       uint8_t                     *gti_data;
-       int                         gti_len;
 };

 struct sccp_optional_data {
@@ -103,6 +102,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 +123,7 @@
 int sccp_connection_free(struct sccp_connection *connection);

 /**
- * internal.. 
+ * internal..
  */
 int sccp_connection_force_free(struct sccp_connection *conn);

@@ -157,6 +158,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;
@@ -177,8 +179,8 @@
  * Below this are helper functions and structs for parsing SCCP messages
  */
 struct sccp_parse_result {
-       struct sccp_address called;
-       struct sccp_address calling;
+       struct sockaddr_sccp called;
+       struct sockaddr_sccp calling;

        /* point to the msg packet */
        struct sccp_source_reference *source_local_reference;
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 <osmocom/core/endian.h>

+/* 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..d756b8d 100644
--- a/src/sccp.c
+++ b/src/sccp.c
@@ -43,7 +43,28 @@
 /* global data */
 const struct sockaddr_sccp sccp_ssn_bssap = {
        .sccp_family    = 0,
-       .sccp_ssn       = SCCP_SSN_BSSAP,
+       .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 {
@@ -51,11 +72,14 @@
        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 {
@@ -103,13 +127,15 @@
 /*
  * parsing routines
  */
-static int copy_address(struct sccp_address *addr, uint8_t offset, struct msgb 
*msgb)
+static int copy_address(struct sockaddr_sccp *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,54 @@
                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) { \
+                       addr->use_poi = 1; \
+                       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) { \
+                       addr->use_ssn = 1; \
+                       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 (sccp_variant[sccp_system.variant].pc_first) {
+               PARSE_POI;
+               PARSE_SSN;
+       } else {
+               PARSE_SSN;
+               PARSE_POI;
        }

-       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;
-       }
+       addr->gti_ind = ((ai & sccp_variant[sccp_system.variant].ai_gti_ind) >> 
2);
+       addr->route_ind = ai & sccp_variant[sccp_system.variant].ai_route_ind;
+       addr->national = ai & sccp_variant[sccp_system.variant].ai_national;

        /* copy the GTI over */
-       if (party->global_title_indicator) {
-               addr->gti_len = length - read - 1;
-               addr->gti_data = &party->data[read];
+       if (addr->gti_ind) {
+               addr->gti_len = length - read;
+               addr->gti_data = &data[read];
        }

-       addr->address = *party;
        return 0;
 }

@@ -173,7 +217,6 @@

                uint8_t length = msgb->l2h[offset + read + 1];
                read += 2 + length;
-

                if (room <= read) {
                        LOGP(DSCCP, LOGL_ERROR,
@@ -486,32 +529,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 +1283,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 +1418,7 @@
        if (!sock)
                return -2;

-       cb = _find_ssn(sock->sccp_ssn);
+       cb = _find_ssn(sock->ssn);
        if (!cb)
                return -1;

@@ -1378,7 +1441,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..8d430d9 100644
--- a/tests/sccp/sccp_test.c
+++ b/tests/sccp/sccp_test.c
@@ -305,7 +305,7 @@
 };

 static const uint8_t it_test[] = {
-0x10, 0x01, 0x07, 
+0x10, 0x01, 0x07,
 0x94, 0x01, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00 };

 static const uint8_t proto_err[] = {
@@ -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],
@@ -919,7 +919,7 @@

 const struct sockaddr_sccp sccp_poi_bssap = {
        .sccp_family    = 0,
-       .sccp_ssn       = SCCP_SSN_BSSAP,
+       .ssn            = SCCP_SSN_BSSAP,
        .poi            = {0x01, 0x00},
        .use_poi        = 1,
 };
@@ -934,10 +934,10 @@

 const struct sockaddr_sccp sccp_gti_bssap = {
        .sccp_family    = 0,
-       .sccp_ssn       = 7,
+       .ssn            = 7,
        .gti_ind        = 4,
        .gti_len        = ARRAY_SIZE(gti_dat),
-       .gti            = gti_dat,
+       .gti_data       = gti_dat,
 };

 static uint8_t gti_out[] = {

-- 
To view, visit https://gerrit.osmocom.org/73
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Ia17eef8c9b7d8e1092c587f469b4a68aa9702651
Gerrit-PatchSet: 5
Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Owner: Arran Cudbard-bell <[email protected]>
Gerrit-Reviewer: Arran Cudbard-bell <[email protected]>
Gerrit-Reviewer: Holger Freyther <[email protected]>
Gerrit-Reviewer: Jenkins Builder

Reply via email to