diff options
author | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2016-04-13 19:08:18 +0200 |
---|---|---|
committer | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2016-09-27 17:14:53 +0200 |
commit | fe97ae7955f95e5959db856e2501b89ba88450d2 (patch) | |
tree | dcccfd1727e77853ff161f0b78d9a10f801d82a4 | |
parent | d08d0e9f52e152092df72c886a4643dead836412 (diff) |
parse SCCP src+dst addresses
In order to receive a Paging command with a valid RANAP SSN, decode the SCCP
source and destination address IEs. This is used by hnbgw to forward a Paging
from CN to RNC.
This may be done more generally as soon as more IEs need parsing of their sub
parts. For now, iterate the higher level IE's data chunk and obtain the address
sub part IEs without storing sub part locations.
-rw-r--r-- | src/sua.c | 87 |
1 files changed, 85 insertions, 2 deletions
@@ -177,7 +177,7 @@ static int xua_msg_add_sccp_addr(struct xua_msg *xua, uint16_t iei, const struct if (!tmp) return -ENOMEM; - msgb_put_u16(tmp, 2); /* route on SSN + PC */ + msgb_put_u16(tmp, SUA_RI_SSN_PC); /* route on SSN + PC */ msgb_put_u16(tmp, 7); /* always put all addresses on SCCP side */ if (addr->presence & OSMO_SCCP_ADDR_T_GT) { @@ -729,12 +729,95 @@ static int sua_parse_addr(struct osmo_sccp_addr *out, uint16_t iei) { const struct xua_msg_part *param = xua_msg_find_tag(xua, iei); + const struct xua_parameter_hdr *par; + uint16_t ri; + uint16_t ai; + uint16_t pos; + uint16_t par_tag, par_len, par_datalen; + uint32_t *p32; if (!param) return -ENODEV; - /* FIXME */ + LOGP(DSUA, LOGL_DEBUG, "sua_parse_addr(IEI=%d) (%d) %s\n", + iei, 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); + return -EINVAL; + } + + pos = 0; + ri = ntohs(*(uint16_t*) ¶m->dat[pos]); + pos += 2; + 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); + return -ENOTSUP; + } + + if (ai != 7) { + LOGP(DSUA, LOGL_ERROR, "SUA IEI %d: Address Indicator not supported yet: %x\n", + iei, ai); + return -ENOTSUP; + } + + /* + * FIXME: this parses the encapsulated T16L16V IEs on the go. We + * probably want to have a separate general parsing function storing + * the subparts in xua_msg_part. But before we do, we should find more + * users of this subpart parsing and be aware of the performance + * tradeoff. + */ + + while (pos + sizeof(*par) < param->len) { + par = (struct xua_parameter_hdr *) ¶m->dat[pos]; + par_tag = ntohs(par->tag); + 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); + + switch (par_tag) { + case SUA_IEI_PC: + if (par_datalen != 4) + goto subpar_fail; + p32 = (uint32_t*)par->data; + out->pc = ntohl(*p32); + out->presence |= OSMO_SCCP_ADDR_T_PC; + break; + case SUA_IEI_SSN: + if (par_datalen != 4) + goto subpar_fail; + /* 24 zero bits, then 8 bits SSN */ + out->ssn = par->data[3]; + out->presence |= OSMO_SCCP_ADDR_T_SSN; + break; + case SUA_IEI_GT: + /* TODO */ + out->presence |= OSMO_SCCP_ADDR_T_GT; + break; + default: + LOGP(DSUA, LOGL_ERROR, "SUA IEI %d: Unknown subpart tag %hd\n", + iei, par_tag); + goto subpar_fail; + } + + pos += par_len; + } + return 0; + +subpar_fail: + LOGP(DSUA, LOGL_ERROR, "Failed to parse subparts of address IEI=%d\n", + iei); + return -EINVAL; } static int sua_rx_cldt(struct osmo_sccp_link *link, struct xua_msg *xua) |