This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Harald Welte gerrit-no-reply at lists.osmocom.orgReview at https://gerrit.osmocom.org/2211 sua: Extend address parsing with GT, RI and IPv4 support Change-Id: I186df77cbdbedfe1a60b855be3626b6766f4681c --- M src/sua.c 1 file changed, 104 insertions(+), 129 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/11/2211/1 diff --git a/src/sua.c b/src/sua.c index 36032ff..e81bce7 100644 --- a/src/sua.c +++ b/src/sua.c @@ -690,117 +690,54 @@ /*********************************************************************** - * Mandatory IE checking - ***********************************************************************/ - -#define MAND_IES(msgt, ies) [msgt] = (ies) - -static const uint16_t cldt_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_PROTO_CLASS, SUA_IEI_SRC_ADDR, - SUA_IEI_DEST_ADDR, SUA_IEI_SEQ_CTRL, SUA_IEI_DATA, 0 -}; - -static const uint16_t cldr_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_CAUSE, SUA_IEI_SRC_ADDR, - SUA_IEI_DEST_ADDR, 0 -}; - -static const uint16_t codt_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_DATA, 0 -}; - -static const uint16_t coda_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, 0 -}; - -static const uint16_t core_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_PROTO_CLASS, SUA_IEI_SRC_REF, - SUA_IEI_DEST_ADDR, SUA_IEI_SEQ_CTRL, 0 -}; - -static const uint16_t coak_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_PROTO_CLASS, SUA_IEI_DEST_REF, - SUA_IEI_SRC_REF, SUA_IEI_SEQ_CTRL, 0 -}; - -static const uint16_t coref_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_CAUSE, 0 -}; - -static const uint16_t relre_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_SRC_REF, - SUA_IEI_CAUSE, 0 -}; - -static const uint16_t relco_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_SRC_REF, 0 -}; - -static const uint16_t resre_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_SRC_REF, - SUA_IEI_CAUSE, 0 -}; - -static const uint16_t resco_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_SRC_REF, 0 -}; - -static const uint16_t coerr_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_DEST_REF, SUA_IEI_CAUSE, 0 -}; - -static const uint16_t coit_mand_ies[] = { - SUA_IEI_ROUTE_CTX, SUA_IEI_PROTO_CLASS, SUA_IEI_SRC_REF, - SUA_IEI_DEST_REF, 0 -}; - -static const uint16_t *mand_ies_cl[256] = { - MAND_IES(SUA_CL_CLDT, cldt_mand_ies), - MAND_IES(SUA_CL_CLDR, cldr_mand_ies), -}; - -static const uint16_t *mand_ies_co[256] = { - MAND_IES(SUA_CO_CODT, codt_mand_ies), - MAND_IES(SUA_CO_CODA, coda_mand_ies), - MAND_IES(SUA_CO_CORE, core_mand_ies), - MAND_IES(SUA_CO_COAK, coak_mand_ies), - MAND_IES(SUA_CO_COREF, coref_mand_ies), - MAND_IES(SUA_CO_RELRE, relre_mand_ies), - MAND_IES(SUA_CO_RELCO, relco_mand_ies), - MAND_IES(SUA_CO_RESRE, resre_mand_ies), - MAND_IES(SUA_CO_RESCO, resco_mand_ies), - MAND_IES(SUA_CO_COERR, coerr_mand_ies), - MAND_IES(SUA_CO_COIT, coit_mand_ies), -}; - -static int check_all_mand_ies(const uint16_t **mand_ies, struct xua_msg *xua) -{ - uint8_t msg_type = xua->hdr.msg_type; - const uint16_t *ies = mand_ies[msg_type]; - uint16_t ie; - - for (ie = *ies; ie; ie = *ies++) { - if (!xua_msg_find_tag(xua, ie)) { - LOGP(DSUA, LOGL_ERROR, "SUA Message %u:%u should " - "contain IE 0x%04x, but doesn't\n", - xua->hdr.msg_class, msg_type, ie); - return 0; - } - } - - return 1; -} - - -/*********************************************************************** * Receiving SUA messsages from SCTP ***********************************************************************/ -static int sua_parse_addr(struct osmo_sccp_addr *out, - struct xua_msg *xua, - uint16_t iei) +/*! \brief Decode SUA Global Title according to RFC3868 3.10.2.3 + * \param[out] gt User-allocated structure for decoded output + * \param[in] data binary-encoded data + * \param[in] datalen length of \ref data in octets + */ +int sua_parse_gt(struct osmo_sccp_gt *gt, const uint8_t *data, unsigned int datalen) { - const struct xua_msg_part *param = xua_msg_find_tag(xua, iei); + uint8_t num_digits; + char *out_digits; + unsigned int i; + + /* 8 byte header at minimum, plus digits */ + if (datalen < 8) + return -EINVAL; + + /* parse header */ + gt->gti = data[3]; + num_digits = data[4]; + gt->tt = data[5]; + gt->npi = data[6]; + gt->nai = data[7]; + + /* parse digits */ + out_digits = gt->digits; + for (i = 0; i < datalen-8; i++) { + uint8_t byte = data[8+i]; + *out_digits++ = osmo_bcd2char(byte & 0x0F); + if (out_digits - gt->digits >= num_digits) + break; + *out_digits++ = osmo_bcd2char(byte >> 4); + if (out_digits - gt->digits >= num_digits) + break; + } + *out_digits++ = '\0'; + + return 0; +} + +/*! \brief parse SCCP address from given xUA message part + * \param[out] out caller-allocated decoded SCCP address struct + * \param[in] param xUA message part containing address + \returns 0 on success; negative on error */ +int sua_addr_parse_part(struct osmo_sccp_addr *out, + const struct xua_msg_part *param) +{ const struct xua_parameter_hdr *par; uint16_t ri; uint16_t ai; @@ -808,16 +745,15 @@ uint16_t par_tag, par_len, par_datalen; uint32_t *p32; - if (!param) - return -ENODEV; + memset(out, 0, sizeof(*out)); - LOGP(DSUA, LOGL_DEBUG, "sua_parse_addr(IEI=%d) (%d) %s\n", - iei, param->len, + LOGP(DSUA, LOGL_DEBUG, "%s(IEI=0x%04x) (%d) %s\n", __func__, + param->tag, param->len, osmo_hexdump(param->dat, param->len)); if (param->len < 4) { - LOGP(DSUA, LOGL_ERROR, "SUA IEI %d: invalid address length: %d\n", - iei, param->len); + LOGP(DSUA, LOGL_ERROR, "SUA IEI 0x%04x: invalid address length: %d\n", + param->tag, param->len); return -EINVAL; } @@ -827,16 +763,29 @@ ai = ntohs(*(uint16_t*) ¶m->dat[pos]); pos += 2; - if (ri != SUA_RI_SSN_PC) { - LOGP(DSUA, LOGL_ERROR, "SUA IEI %d: Routing Indicator not supported yet: %d\n", - iei, ri); + switch (ri) { + case SUA_RI_GT: + out->ri = OSMO_SCCP_RI_GT; + break; + case SUA_RI_SSN_PC: + out->ri = OSMO_SCCP_RI_SSN_PC; + break; + case SUA_RI_SSN_IP: + out->ri = OSMO_SCCP_RI_SSN_IP; + break; + case SUA_RI_HOST: + default: + LOGP(DSUA, LOGL_ERROR, "SUA IEI 0x%04x: Routing Indicator not supported yet: %d\n", + param->tag, ri); return -ENOTSUP; } if (ai != 7) { - LOGP(DSUA, LOGL_ERROR, "SUA IEI %d: Address Indicator not supported yet: %x\n", - iei, ai); +#if 0 + LOGP(DSUA, LOGL_ERROR, "SUA IEI 0x%04x: Address Indicator not supported yet: %x\n", + param->tag, ai); return -ENOTSUP; +#endif } /* @@ -853,8 +802,8 @@ par_len = ntohs(par->len); par_datalen = par_len - sizeof(*par); - LOGP(DSUA, LOGL_DEBUG, "SUA IEI %hu pos %hu/%hu: subpart tag %hu, len %hu\n", - iei, pos, param->len, par->tag, par->len); + LOGP(DSUA, LOGL_DEBUG, "SUA IEI 0x%04x pos %hu/%hu: subpart tag 0x%04x, len %hu\n", + param->tag, pos, param->len, par_tag, par_len); switch (par_tag) { case SUA_IEI_PC: @@ -872,12 +821,22 @@ out->presence |= OSMO_SCCP_ADDR_T_SSN; break; case SUA_IEI_GT: - /* TODO */ + if (par_datalen < 8) + goto subpar_fail; + sua_parse_gt(&out->gt, par->data, par_datalen); out->presence |= OSMO_SCCP_ADDR_T_GT; break; + case SUA_IEI_IPv4: + if (par_datalen != 4) + goto subpar_fail; + p32 = (uint32_t*)par->data; + /* no endian conversion, both network order */ + out->ip.v4.s_addr = *p32; + out->presence |= OSMO_SCCP_ADDR_T_IPv4; + break; default: - LOGP(DSUA, LOGL_ERROR, "SUA IEI %d: Unknown subpart tag %hd\n", - iei, par_tag); + LOGP(DSUA, LOGL_ERROR, "SUA IEI 0x%04x: Unknown subpart tag %hd\n", + param->tag, par_tag); goto subpar_fail; } @@ -887,9 +846,25 @@ return 0; subpar_fail: - LOGP(DSUA, LOGL_ERROR, "Failed to parse subparts of address IEI=%d\n", - iei); + LOGP(DSUA, LOGL_ERROR, "Failed to parse subparts of address IEI=0x%04x\n", + param->tag); return -EINVAL; +} + +/*! \brief parse SCCP address from given xUA message IE + * \param[out] out caller-allocated decoded SCCP address struct + * \param[in] xua xUA message + * \param[in] iei Information Element Identifier inside \ref xua + \returns 0 on success; negative on error */ +int sua_addr_parse(struct osmo_sccp_addr *out, struct xua_msg *xua, uint16_t iei) +{ + const struct xua_msg_part *param = xua_msg_find_tag(xua, iei); + if (!param) { + memset(out, 0, sizeof(*out)); + return -ENODEV; + } + + return sua_addr_parse_part(out, param); } static int sua_rx_cldt(struct osmo_sccp_link *link, struct xua_msg *xua) @@ -906,8 +881,8 @@ osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION, upmsg); - sua_parse_addr(¶m->called_addr, xua, SUA_IEI_DEST_ADDR); - sua_parse_addr(¶m->calling_addr, xua, SUA_IEI_SRC_ADDR); + sua_addr_parse(¶m->called_addr, xua, SUA_IEI_DEST_ADDR); + sua_addr_parse(¶m->calling_addr, xua, SUA_IEI_SRC_ADDR); param->in_sequence_control = xua_msg_get_u32(xua, SUA_IEI_SEQ_CTRL); protocol_class = xua_msg_get_u32(xua, SUA_IEI_PROTO_CLASS); param->return_option = protocol_class & 0x80; @@ -953,8 +928,8 @@ /* fill conn */ conn = conn_create(link); - sua_parse_addr(&conn->called_addr, xua, SUA_IEI_DEST_ADDR); - sua_parse_addr(&conn->calling_addr, xua, SUA_IEI_SRC_ADDR); + sua_addr_parse(&conn->called_addr, xua, SUA_IEI_DEST_ADDR); + sua_addr_parse(&conn->calling_addr, xua, SUA_IEI_SRC_ADDR); conn->remote_ref = xua_msg_get_u32(xua, SUA_IEI_SRC_REF); /* fill primitive */ -- To view, visit https://gerrit.osmocom.org/2211 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I186df77cbdbedfe1a60b855be3626b6766f4681c Gerrit-PatchSet: 1 Gerrit-Project: libosmo-sccp Gerrit-Branch: master Gerrit-Owner: Harald Welte <laforge at gnumonks.org>