From dd1c83c52d66c28583e06ba3b930883b488689ea Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 13 May 2010 13:58:08 +0200 Subject: [GPRS] NS: Fix segfault when receiving message from unknown NS-VC In the previous code we used a static fake_nsvc structure in case we needed to send a message to an unknown NSVC for which we don't have a real 'struct nsvc'. However, since we now have a rate_ctr_group hanging off the nsvc, the fake structure didn't have that. So now we keep a nsi->unknown_nsvc around to be used whenever we need a nsvc but don't have a real one. The gprs_ns_vty.c code explicitly does not list that NSVC in 'show ns' --- openbsc/include/openbsc/gprs_ns.h | 3 +++ openbsc/src/gprs/gprs_ns.c | 25 +++++++++++++++++-------- openbsc/src/gprs/gprs_ns_vty.c | 2 ++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h index 34b1b62d..4ccf4c7b 100644 --- a/openbsc/include/openbsc/gprs_ns.h +++ b/openbsc/include/openbsc/gprs_ns.h @@ -125,6 +125,9 @@ struct gprs_ns_inst { /* linked lists of all NSVC in this instance */ struct llist_head gprs_nsvcs; + /* a NSVC object that's needed to deal with packets for unknown NSVC */ + struct gprs_nsvc *unknown_nsvc; + uint16_t timeout[NS_TIMERS_COUNT]; /* which link-layer are we based on? */ diff --git a/openbsc/src/gprs/gprs_ns.c b/openbsc/src/gprs/gprs_ns.c index 2853600d..50ab8203 100644 --- a/openbsc/src/gprs/gprs_ns.c +++ b/openbsc/src/gprs/gprs_ns.c @@ -44,6 +44,14 @@ * Those mappings are administratively configured. */ +/* This implementation has the following limitations: + * o Only one NS-VC for each NSE: No load-sharing function + * o NSVCI 65535 and 65534 are reserved for internal use + * o Only UDP is supported as of now, no frame relay support + * o The IP Sub-Network-Service (SNS) as specified in 48.016 is not implemented + * o There are no BLOCK and UNBLOCK timers (yet?) + */ + #include #include #include @@ -633,17 +641,16 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, uint16_t nsei; /* Only the RESET procedure creates a new NSVC */ if (nsh->pdu_type != NS_PDUT_RESET) { - struct gprs_nsvc fake_nsvc; - LOGP(DNS, LOGL_INFO, "Ignoring NS PDU type 0x%0x " + /* Since we have no NSVC, we have to use a fake */ + nsvc = nsi->unknown_nsvc; + LOGP(DNS, LOGL_INFO, "Rejecting NS PDU type 0x%0x " "from %s:%u for non-existing NS-VC\n", nsh->pdu_type, inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port)); - /* Since we have no NSVC, we have to create a fake */ - fake_nsvc.nsvci = fake_nsvc.nsei = 0; - fake_nsvc.nsi = nsi; - fake_nsvc.ip.bts_addr = *saddr; - fake_nsvc.state = NSE_S_ALIVE; - return gprs_ns_tx_status(&fake_nsvc, + nsvc->nsvci = nsvc->nsei = 0xfffe; + nsvc->ip.bts_addr = *saddr; + nsvc->state = NSE_S_ALIVE; + return gprs_ns_tx_status(nsvc, NS_CAUSE_PDU_INCOMP_PSTATE, 0, msg); } @@ -766,6 +773,8 @@ struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb) nsi->timeout[NS_TOUT_TNS_ALIVE] = 3; nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES] = 10; + nsi->unknown_nsvc = nsvc_create(nsi, 0xfffe); + return nsi; } diff --git a/openbsc/src/gprs/gprs_ns_vty.c b/openbsc/src/gprs/gprs_ns_vty.c index 08b0076c..8f0628af 100644 --- a/openbsc/src/gprs/gprs_ns_vty.c +++ b/openbsc/src/gprs/gprs_ns_vty.c @@ -109,6 +109,8 @@ static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats) struct gprs_nsvc *nsvc; llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + if (nsvc == nsi->unknown_nsvc) + continue; vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s", nsvc->nsei, nsvc->nsvci, nsvc->remote_end_is_sgsn ? "SGSN" : "BSS", -- cgit v1.2.3