From 1afe7c7fe5e79435a1ebe9aff622ca20b901d923 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 4 Oct 2015 11:11:11 +0200 Subject: osmux: Remember the allocated CID and make sure it is released There appears to be a leak of CIDs: <000b> mgcp_osmux.c:544 All Osmux circuits are in use! There are paths that a CID had been requested and never released of the NAT. Remember the allocated CID inside the endpoint so it can always be released. It is using a new variable as the behavior for the NAT and MGCP MGW is different. The allocated_cid must be signed so that we can assign outside of the 0-255 range of it. Fixes: OW#1493 --- openbsc/include/openbsc/mgcp_internal.h | 2 ++ openbsc/include/openbsc/osmux.h | 2 ++ openbsc/src/libmgcp/mgcp_osmux.c | 13 +++++++++++++ openbsc/src/libmgcp/mgcp_protocol.c | 4 ++++ openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c | 18 +++++++++--------- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 1f836595b..db22bcfda 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -192,6 +192,8 @@ struct mgcp_endpoint { /* Osmux state: disabled, activating, active */ enum osmux_state state; /* Allocated Osmux circuit ID for this endpoint */ + int allocated_cid; + /* Used Osmux circuit ID for this endpoint */ uint8_t cid; /* handle to batch messages */ struct osmux_in_handle *in; diff --git a/openbsc/include/openbsc/osmux.h b/openbsc/include/openbsc/osmux.h index 88d045b78..82b8fa35b 100644 --- a/openbsc/include/openbsc/osmux.h +++ b/openbsc/include/openbsc/osmux.h @@ -14,6 +14,8 @@ int osmux_init(int role, struct mgcp_config *cfg); int osmux_enable_endpoint(struct mgcp_endpoint *endp, int role, struct in_addr *addr, uint16_t port); void osmux_disable_endpoint(struct mgcp_endpoint *endp); +void osmux_allocate_cid(struct mgcp_endpoint *endp); +void osmux_release_cid(struct mgcp_endpoint *endp); int osmux_xfrm_to_rtp(struct mgcp_endpoint *endp, int type, char *buf, int rc); int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp); diff --git a/openbsc/src/libmgcp/mgcp_osmux.c b/openbsc/src/libmgcp/mgcp_osmux.c index 30a81cbc3..2d39b2c5e 100644 --- a/openbsc/src/libmgcp/mgcp_osmux.c +++ b/openbsc/src/libmgcp/mgcp_osmux.c @@ -492,6 +492,19 @@ void osmux_disable_endpoint(struct mgcp_endpoint *endp) osmux_handle_put(endp->osmux.in); } +void osmux_release_cid(struct mgcp_endpoint *endp) +{ + if (endp->osmux.allocated_cid >= 0) + osmux_put_cid(endp->osmux.allocated_cid); + endp->osmux.allocated_cid = -1; +} + +void osmux_allocate_cid(struct mgcp_endpoint *endp) +{ + osmux_release_cid(endp); + endp->osmux.allocated_cid = osmux_get_cid(); +} + /* We don't need to send the dummy load for osmux so often as another endpoint * may have already punched the hole in the firewall. This approach is simple * though. diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index e2bda3aff..42ce8bb2f 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -1314,6 +1314,7 @@ int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg) return -1; for (i = 0; i < tcfg->number_endpoints; ++i) { + tcfg->endpoints[i].osmux.allocated_cid = -1; tcfg->endpoints[i].ci = CI_UNUSED; tcfg->endpoints[i].cfg = tcfg->cfg; tcfg->endpoints[i].tcfg = tcfg; @@ -1354,6 +1355,9 @@ void mgcp_release_endp(struct mgcp_endpoint *endp) if (endp->osmux.state == OSMUX_STATE_ENABLED) osmux_disable_endpoint(endp); + /* release the circuit ID if it had been allocated */ + osmux_release_cid(endp); + memset(&endp->taps, 0, sizeof(endp->taps)); } diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c index bd1d96523..0105c7e3d 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c @@ -515,7 +515,6 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int struct nat_sccp_connection *sccp; struct mgcp_endpoint *mgcp_endp; struct msgb *bsc_msg; - int osmux_cid = -1; nat = tcfg->cfg->data; bsc_endp = &nat->bsc_endpoints[endpoint]; @@ -555,8 +554,9 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* Allocate a Osmux circuit ID */ if (state == MGCP_ENDP_CRCX) { if (nat->mgcp_cfg->osmux && sccp->bsc->cfg->osmux) { - osmux_cid = osmux_get_cid(); - if (osmux_cid < 0 && nat_osmux_only(nat->mgcp_cfg, sccp->bsc->cfg)) { + osmux_allocate_cid(mgcp_endp); + if (mgcp_endp->osmux.allocated_cid < 0 && + nat_osmux_only(nat->mgcp_cfg, sccp->bsc->cfg)) { LOGP(DMGCP, LOGL_ERROR, "Rejecting usage of endpoint\n"); return MGCP_POLICY_REJECT; @@ -567,7 +567,8 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* we need to generate a new and patched message */ bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length, sccp->bsc_endp, mgcp_bts_src_addr(mgcp_endp), - mgcp_endp->bts_end.local_port, osmux_cid, + mgcp_endp->bts_end.local_port, + mgcp_endp->osmux.allocated_cid, &mgcp_endp->net_end.codec.payload_type, nat->sdp_ensure_amr_mode_set); if (!bsc_msg) { @@ -587,10 +588,10 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* Annotate the allocated Osmux CID until the bsc confirms that * it agrees to use Osmux for this voice flow. */ - if (osmux_cid >= 0 && + if (mgcp_endp->osmux.allocated_cid >= 0 && mgcp_endp->osmux.state != OSMUX_STATE_ENABLED) { mgcp_endp->osmux.state = OSMUX_STATE_ACTIVATING; - mgcp_endp->osmux.cid = osmux_cid; + mgcp_endp->osmux.cid = mgcp_endp->osmux.allocated_cid; } socklen_t len = sizeof(sock); @@ -612,7 +613,7 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* libmgcp clears the MGCP endpoint for us */ if (mgcp_endp->osmux.state == OSMUX_STATE_ENABLED) - osmux_put_cid(mgcp_endp->osmux.cid); + osmux_release_cid(mgcp_endp); return MGCP_POLICY_CONT; } else { @@ -681,8 +682,7 @@ static void bsc_mgcp_osmux_confirm(struct mgcp_endpoint *endp, const char *str) osmux_cid); return; err: - osmux_put_cid(endp->osmux.cid); - endp->osmux.cid = -1; + osmux_release_cid(endp); endp->osmux.state = OSMUX_STATE_DISABLED; } -- cgit v1.2.3