diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 1698fa47f..4baaa8280 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -270,6 +270,7 @@ struct bsc_nat { struct mgcp_config *mgcp_cfg; uint8_t mgcp_msg[4096]; int mgcp_length; + int mgcp_ipa; /* msc things */ struct llist_head dests; @@ -463,6 +464,9 @@ struct bsc_nat_barr_entry { int bsc_nat_barr_adapt(void *ctx, struct rb_root *rbtree, const struct osmo_config_list *); int bsc_nat_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu); +void bsc_nat_send_mgcp_to_msc(struct bsc_nat *bsc_nat, struct msgb *msg); +void bsc_nat_handle_mgcp(struct bsc_nat *bsc, struct msgb *msg); + struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat, int port); void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending); int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg); diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c index 1436ebd35..480a8f6d1 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c @@ -62,7 +62,7 @@ #include #include -static void mgcp_queue_for_call_agent(struct bsc_nat *nat, struct msgb *output) +static void send_direct(struct bsc_nat *nat, struct msgb *output) { if (osmo_wqueue_enqueue(&nat->mgcp_cfg->gw_fd, output) != 0) { LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n"); @@ -70,6 +70,14 @@ static void mgcp_queue_for_call_agent(struct bsc_nat *nat, struct msgb *output) } } +static void mgcp_queue_for_call_agent(struct bsc_nat *nat, struct msgb *output) +{ + if (nat->mgcp_ipa) + bsc_nat_send_mgcp_to_msc(nat, output); + else + send_direct(nat, output); +} + int bsc_mgcp_nr_multiplexes(int max_endpoints) { int div = max_endpoints / 32; @@ -656,6 +664,38 @@ copy: return output; } +/* + * This comes from the MSC and we will now parse it. The caller needs + * to free the msgb. + */ +void bsc_nat_handle_mgcp(struct bsc_nat *nat, struct msgb *msg) +{ + struct msgb *resp; + + if (!nat->mgcp_ipa) { + LOGP(DMGCP, LOGL_ERROR, "MGCP message not allowed on IPA.\n"); + return; + } + + if (msgb_l2len(msg) > sizeof(nat->mgcp_msg) - 1) { + LOGP(DMGCP, LOGL_ERROR, "MGCP msg too big for handling.\n"); + return; + } + + memcpy(nat->mgcp_msg, msg->l2h, msgb_l2len(msg)); + nat->mgcp_length = msgb_l2len(msg); + nat->mgcp_msg[nat->mgcp_length] = '\0'; + + /* now handle the message */ + resp = mgcp_handle_message(nat->mgcp_cfg, msg); + + /* we do have a direct answer... e.g. AUEP */ + if (resp) + mgcp_queue_for_call_agent(nat, resp); + + return; +} + static int mgcp_do_read(struct osmo_fd *fd) { struct bsc_nat *nat; @@ -705,21 +745,10 @@ static int mgcp_do_write(struct osmo_fd *bfd, struct msgb *msg) return rc; } -int bsc_mgcp_nat_init(struct bsc_nat *nat) +static int init_mgcp_socket(struct bsc_nat *nat, struct mgcp_config *cfg) { - int on; struct sockaddr_in addr; - struct mgcp_config *cfg = nat->mgcp_cfg; - - if (!cfg->call_agent_addr) { - LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n"); - return -1; - } - - if (cfg->bts_ip) { - LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n"); - return -1; - } + int on; cfg->gw_fd.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0); if (cfg->gw_fd.bfd.fd < 0) { @@ -765,6 +794,31 @@ int bsc_mgcp_nat_init(struct bsc_nat *nat) return -1; } + return 0; +} + +int bsc_mgcp_nat_init(struct bsc_nat *nat) +{ + struct mgcp_config *cfg = nat->mgcp_cfg; + + if (!cfg->call_agent_addr) { + LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n"); + return -1; + } + + if (cfg->bts_ip) { + LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n"); + return -1; + } + + /* initialize the MGCP socket */ + if (!nat->mgcp_ipa) { + int rc = init_mgcp_socket(nat, cfg); + if (rc != 0) + return rc; + } + + /* some more MGCP config handling */ cfg->data = nat; cfg->policy_cb = bsc_mgcp_policy_cb; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index 792d33c23..e70f54952 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -333,6 +333,12 @@ static void send_mgcp_reset(struct bsc_connection *bsc) bsc_write_mgcp(bsc, mgcp_reset, sizeof mgcp_reset - 1); } +void bsc_nat_send_mgcp_to_msc(struct bsc_nat *nat, struct msgb *msg) +{ + ipaccess_prepend_header(msg, IPAC_PROTO_MGCP_OLD); + queue_for_msc(nat->msc_con, msg); +} + /* * Below is the handling of messages coming * from the MSC and need to be forwarded to @@ -820,8 +826,11 @@ static int ipaccess_msc_read_cb(struct osmo_fd *bfd) initialize_msc_if_needed(msc_con); else if (msg->l2h[0] == IPAC_MSGT_ID_GET) send_id_get_response(msc_con); - } else if (hh->proto == IPAC_PROTO_SCCP) + } else if (hh->proto == IPAC_PROTO_SCCP) { forward_sccp_to_bts(msc_con, msg); + } else if (hh->proto == IPAC_PROTO_MGCP_OLD) { + bsc_nat_handle_mgcp(nat, msg); + } msgb_free(msg); return 0; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 7bbc89059..32e5106ae 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -143,6 +143,8 @@ static int config_write_nat(struct vty *vty) write_acc_lst(vty, lst); llist_for_each_entry(pgroup, &_nat->paging_groups, entry) write_pgroup_lst(vty, pgroup); + if (_nat->mgcp_ipa) + vty_out(vty, " mgcp-through-msc-ipa%s", VTY_NEWLINE); return CMD_SUCCESS; } @@ -657,6 +659,20 @@ DEFUN(cfg_nat_ussd_local, return CMD_SUCCESS; } +DEFUN(cfg_nat_mgcp_ipa, + cfg_nat_mgcp_ipa_cmd, + "mgcp-through-msc-ipa", + "This needs to be set at start. Handle MGCP messages through " + "the IPA protocol and not through the UDP socket.\n") +{ + if (_nat->mgcp_cfg->data) + vty_out(vty, + "%%the setting will not be applied right now.%s", + VTY_NEWLINE); + _nat->mgcp_ipa = 1; + return CMD_SUCCESS; +} + /* per BSC configuration */ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "BSC configuration\n" "Identifier of the BSC\n") @@ -1086,6 +1102,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element(NAT_NODE, &cfg_nat_ussd_query_cmd); install_element(NAT_NODE, &cfg_nat_ussd_token_cmd); install_element(NAT_NODE, &cfg_nat_ussd_local_cmd); + install_element(NAT_NODE, &cfg_nat_mgcp_ipa_cmd); /* access-list */ install_element(NAT_NODE, &cfg_lst_imsi_allow_cmd); diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index 66b4ff5a7..3b5c24e36 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -1242,3 +1242,9 @@ int main(int argc, char **argv) printf("Testing execution completed.\n"); return 0; } + +/* stub */ +void bsc_nat_send_mgcp_to_msc(struct bsc_nat *nat, struct msgb *msg) +{ + abort(); +}