aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/bsc_nat.h4
-rw-r--r--openbsc/src/nat/bsc_mgcp_utils.c79
-rw-r--r--openbsc/src/nat/bsc_nat.c3
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c30
4 files changed, 116 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index e41849652..cb85ce0e4 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -200,5 +200,9 @@ int bsc_mgcp_init(struct bsc_nat *nat);
struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
struct msgb *bsc_mgcp_rewrite(struct msgb *msg, const char *ip, int port);
+void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
+
+int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]);
+int bsc_mgcp_extract_ci(const char *resp);
#endif
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
index 24f66a14f..0899cec8e 100644
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -173,6 +173,85 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
return MGCP_POLICY_DEFER;
}
+/*
+ * We have received a msg from the BSC. We will see if we know
+ * this transaction and if it belongs to the BSC. Then we will
+ * need to patch the content to point to the local network and we
+ * need to update the I: that was assigned by the BSS.
+ */
+void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
+{
+ struct msgb *output;
+ struct bsc_endpoint *bsc_endp = NULL;
+ struct mgcp_endpoint *endp = NULL;
+ int i, code;
+ char transaction_id[60];
+
+ /* Some assumption that our buffer is big enough.. and null terminate */
+ if (msgb_l2len(msg) > 2000) {
+ LOGP(DMGCP, LOGL_ERROR, "MGCP message too long.\n");
+ return;
+ }
+
+ msg->l2h[msgb_l2len(msg)] = '\0';
+
+ if (bsc_mgcp_parse_response((const char *) msg->l2h, &code, transaction_id) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to parse response code.\n");
+ return;
+ }
+
+ for (i = 1; i < bsc->nat->mgcp_cfg->number_endpoints; ++i) {
+ if (bsc->nat->bsc_endpoints[i].bsc != bsc)
+ continue;
+ if (strcmp(transaction_id, bsc->nat->bsc_endpoints[i].transaction_id) != 0)
+ continue;
+
+ endp = &bsc->nat->mgcp_cfg->endpoints[i];
+ bsc_endp = &bsc->nat->bsc_endpoints[i];
+ break;
+ }
+
+ if (!bsc_endp) {
+ LOGP(DMGCP, LOGL_ERROR, "Could not find active endpoint: %s\n", transaction_id);
+ return;
+ }
+
+ /* free some stuff */
+ talloc_free(bsc_endp->transaction_id);
+ bsc_endp->transaction_id = NULL;
+
+ /* make it point to our endpoint */
+ endp->ci = bsc_mgcp_extract_ci((const char *) msg->l2h);
+ output = bsc_mgcp_rewrite(msg, bsc->nat->mgcp_cfg->source_addr, endp->rtp_port);
+ if (!output) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to rewrite MGCP msg.\n");
+ return;
+ }
+
+ if (write_queue_enqueue(&bsc->nat->mgcp_queue, output) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
+ msgb_free(output);
+ }
+}
+
+int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60])
+{
+ /* we want to parse two strings */
+ return sscanf(str, "%3d %59s\n", code, transaction) != 2;
+}
+
+int bsc_mgcp_extract_ci(const char *str)
+{
+ int ci;
+ char *res = strstr(str, "I: ");
+ if (!res)
+ return CI_UNUSED;
+
+ if (sscanf(res, "I: %d\r\n", &ci) != 1)
+ return CI_UNUSED;
+ return ci;
+}
+
/* we need to replace some strings... */
struct msgb *bsc_mgcp_rewrite(struct msgb *input, const char *ip, int port)
{
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index a0115df69..b135bfec6 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -430,6 +430,9 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
goto exit2;
break;
}
+ } else if (parsed->ipa_proto == NAT_IPAC_PROTO_MGCP) {
+ bsc_mgcp_forward(bsc, msg);
+ goto exit2;
} else {
LOGP(DNAT, LOGL_ERROR, "Not forwarding unknown stream id: 0x%x\n", parsed->ipa_proto);
goto exit2;
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index c3b86c060..10b876b37 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -456,6 +456,35 @@ static void test_mgcp_rewrite(void)
msgb_free(input);
}
+static void test_mgcp_parse(void)
+{
+ int code, ci;
+ char transaction[60];
+
+ fprintf(stderr, "Test MGCP response parsing.\n");
+
+ if (bsc_mgcp_parse_response(crcx_resp, &code, transaction) != 0) {
+ fprintf(stderr, "Failed to parse CRCX resp.\n");
+ abort();
+ }
+
+ if (code != 200) {
+ fprintf(stderr, "Failed to parse the CODE properly. Got: %d\n", code);
+ abort();
+ }
+
+ if (strcmp(transaction, "23265295") != 0) {
+ fprintf(stderr, "Failed to parse transaction id: '%s'\n", transaction);
+ abort();
+ }
+
+ ci = bsc_mgcp_extract_ci(crcx_resp);
+ if (ci != 1) {
+ fprintf(stderr, "Failed to parse the CI. Got: %d\n", ci);
+ abort();
+ }
+}
+
int main(int argc, char **argv)
{
struct debug_target *stderr_target;
@@ -470,6 +499,7 @@ int main(int argc, char **argv)
test_mgcp_ass_tracking();
test_mgcp_find();
test_mgcp_rewrite();
+ test_mgcp_parse();
return 0;
}