diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-05-11 18:30:37 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-05-11 18:30:37 +0200 |
commit | e5117da715f4f654671e39c36b9085a3a1c3141f (patch) | |
tree | c379756b8fc6a62b53b0aa39e90339156eb74f64 /openbsc/src/gprs/gprs_ns.c | |
parent | f69c059a0ebf9a5b1e5f11bff8527a8ba9ed0a16 (diff) |
[gprs] gb-proxy: We might receive a NS-RESET for a NS-VC that we already know
In this case, don't blindly allocate a new NS-VC but rather use the NSEI
to lookup the 'struct gprs_nsvc' for it.
Diffstat (limited to 'openbsc/src/gprs/gprs_ns.c')
-rw-r--r-- | openbsc/src/gprs/gprs_ns.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/openbsc/src/gprs/gprs_ns.c b/openbsc/src/gprs/gprs_ns.c index bd9791afa..3d05dd0ff 100644 --- a/openbsc/src/gprs/gprs_ns.c +++ b/openbsc/src/gprs/gprs_ns.c @@ -483,6 +483,8 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, /* look up the NSVC based on source address */ nsvc = nsvc_by_rem_addr(nsi, saddr); if (!nsvc) { + struct tlv_parsed tp; + uint16_t nsei; /* Only the RESET procedure creates a new NSVC */ if (nsh->pdu_type != NS_PDUT_RESET) { LOGP(DNS, LOGL_INFO, "Ignoring NS PDU type 0x%0x " @@ -491,10 +493,25 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, //gprs_ns_tx_reset(nsvc, NS_CAUSE_NSVC_UNKNOWN); return -EIO; } - LOGP(DNS, LOGL_INFO, "Creating NS-VC for BSS at %s:%u\n", - inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port)); - nsvc = nsvc_create(nsi, 0xffff); - nsvc->ip.bts_addr = *saddr; + rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, + msgb_l2len(msg), 0, 0); + if (!TLVP_PRESENT(&tp, NS_IE_CAUSE) || + !TLVP_PRESENT(&tp, NS_IE_VCI) || + !TLVP_PRESENT(&tp, NS_IE_NSEI)) { + /* FIXME: respond with NS_CAUSE_MISSING_ESSENT_IE */ + LOGP(DNS, LOGL_ERROR, "NS RESET Missing mandatory IE\n"); + return -EINVAL; + } + nsei = ntohs(*(uint16_t *)TLVP_VAL(&tp, NS_IE_NSEI)); + /* Check if we already know this NSEI, the remote end might + * simply have changed addresses, or it is a SGSN */ + nsvc = nsvc_by_nsei(nsi, nsei); + if (!nsvc) { + LOGP(DNS, LOGL_INFO, "Creating NS-VC for BSS at %s:%u\n", + inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port)); + nsvc = nsvc_create(nsi, 0xffff); + nsvc->ip.bts_addr = *saddr; + } } else msgb_nsei(msg) = nsvc->nsei; |