summaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2019-05-22 20:09:49 +0200
committerHarald Welte <laforge@gnumonks.org>2019-05-26 09:26:14 +0000
commit6a61bc3089e229b575851ca5d99e893c81f59562 (patch)
tree61baee5a6937eb3ddfdfaadf8a73a50b4b359aa4 /openbsc
parente1077526c22d0ffd5a8a29b1200f58750ac42677 (diff)
mgcp: Handle CI and X-Osmux param name as case insensitiveHEADmaster
RFC3435 states most text (except SDP) must be handled as case insensitive. Since we are no longer using strstr(msg->l2h), we need to iterate per line and call related extract/handle function for that line. Call to bsc_mgcp_osmux_confirm() is left at the end because it needs to be called too in case no matching line is found. In that case, it will release the CID. Similar stuff ocurrs for bsc_mgcp_extract_ci(). Related: OS#4001 Change-Id: Iadc004064a5a237c93009f242cb943ebc4d2d7e6
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c77
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c2
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 17dc659..1b0abf3 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 4bee60d..f6cf8b0 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();