diff options
-rw-r--r-- | openbsc/include/openbsc/bsc_nat.h | 4 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_mgcp_utils.c | 79 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat.c | 3 | ||||
-rw-r--r-- | openbsc/tests/bsc-nat/bsc_nat_test.c | 30 |
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 0f9f08cd3..e8a6b199b 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; } |