diff options
-rw-r--r-- | openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c | 77 | ||||
-rw-r--r-- | openbsc/tests/bsc-nat/bsc_nat_test.c | 2 |
2 files changed, 66 insertions, 13 deletions
diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c index 17dc659bb..1b0abf371 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c @@ -663,19 +663,38 @@ static void free_chan_downstream(struct mgcp_endpoint *endp, struct bsc_endpoint mgcp_release_endp(endp); } +/*! Check MGCP parameter line (string) for plausibility. + * \param[in] endp pointer to endpoint (only used for log output) + * \param[in] line single parameter line from the MGCP message + * \returns 1 when line seems plausible, 0 on error */ +static int bsc_mgcp_check_param(const struct mgcp_endpoint *endp, const char *line) +{ + const size_t line_len = strlen(line); + if (line[0] != '\0' && line_len < 2) { + LOGP(DLMGCP, LOGL_ERROR, + "Wrong MGCP option format: '%s' on 0x%x\n", + line, ENDPOINT_NUMBER(endp)); + return 0; + } + + /* FIXME: A couple more checks wouldn't hurt... */ + + return 1; +} + static void bsc_mgcp_osmux_confirm(struct mgcp_endpoint *endp, const char *str) { unsigned int osmux_cid; - char *res; + const char x_osmux_prefix[] = "X-Osmux: "; + const size_t x_osmux_prefix_len = strlen(x_osmux_prefix); - res = strstr(str, "X-Osmux: "); - if (!res) { + if (!str || strncasecmp(str, x_osmux_prefix, x_osmux_prefix_len)) { LOGP(DMGCP, LOGL_INFO, - "BSC doesn't want to use Osmux, failing back to RTP\n"); + "BSC doesn't want to use Osmux, failing back to RTP (str=%s)\n", str); goto err; } - if (sscanf(res, "X-Osmux: %u", &osmux_cid) != 1) { + if (sscanf(str + x_osmux_prefix_len, "%u", &osmux_cid) != 1) { LOGP(DMGCP, LOGL_ERROR, "Failed to parse Osmux CID '%s'\n", str); goto err; @@ -713,6 +732,10 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg) struct mgcp_endpoint *endp = NULL; int i, code; char transaction_id[60]; + char *save; + char *line = NULL; + char *line_osmux = NULL; + char *line_ci = NULL; /* Some assumption that our buffer is big enough.. and null terminate */ if (msgb_l2len(msg) > 2000) { @@ -752,14 +775,42 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg) return; } - endp->ci = bsc_mgcp_extract_ci((const char *) msg->l2h); + save = alloca(msgb_l2len(msg) + 1); /* +1 -> null char appended */ + memcpy(save, msg->l2h, msgb_l2len(msg) + 1); + for_each_line(line, save) { + + if (!bsc_mgcp_check_param(endp, line)) + continue; + + switch (line[0]) { + case 'I': + case 'i': + line_ci = line; + break; + case 'X': + case 'x': + if (strncasecmp(line, "X-Osmux: ", strlen("X-Osmux: ")) == 0) + line_osmux = line; + /* Ignore unknown X-headers */ + break; + case '\0': + /* Reached SDP section, we are done parsing header */ + goto mgcp_header_done; + break; + default: + break; + } + } +mgcp_header_done: + + endp->ci = bsc_mgcp_extract_ci((const char *) line_ci); if (endp->ci == CI_UNUSED) { free_chan_downstream(endp, bsc_endp, bsc); return; } if (endp->osmux.state == OSMUX_STATE_NEGOTIATING) - bsc_mgcp_osmux_confirm(endp, (const char *) msg->l2h); + bsc_mgcp_osmux_confirm(endp, line_osmux); /* If we require osmux and it is disabled.. fail */ if (nat_osmux_only(bsc->nat->mgcp_cfg, bsc->cfg) && @@ -806,14 +857,16 @@ int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]) uint32_t bsc_mgcp_extract_ci(const char *str) { unsigned int ci; - char *res = strstr(str, "I: "); - if (!res) { - LOGP(DMGCP, LOGL_ERROR, "No CI in msg '%s'\n", str); + const char ci_prefix[] = "I: "; + const size_t ci_prefix_len = strlen(ci_prefix); + + if (!str || strncasecmp(str, ci_prefix, ci_prefix_len)) { + LOGP(DMGCP, LOGL_ERROR, "No CI in line '%s'\n", str); return CI_UNUSED; } - if (sscanf(res, "I: %x", &ci) != 1) { - LOGP(DMGCP, LOGL_ERROR, "Failed to parse CI in msg '%s'\n", str); + if (sscanf(str + ci_prefix_len, "%x", &ci) != 1) { + LOGP(DMGCP, LOGL_ERROR, "Failed to parse CI in line '%s'\n", str); return CI_UNUSED; } diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index 4bee60d8c..f6cf8b081 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -675,7 +675,7 @@ static void test_mgcp_parse(void) abort(); } - ci = bsc_mgcp_extract_ci(crcx_resp); + ci = bsc_mgcp_extract_ci(strstr(crcx_resp, "I: ")); if (ci != 0x0F) { printf("Failed to parse the CI. Got: %d\n", ci); abort(); |