diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-04-07 22:54:07 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-04-07 22:54:07 +0200 |
commit | 91b5a31a2ce73b988fa1c7f28e3a2cc2c8b77b90 (patch) | |
tree | 794f00fa8e4afc237af410733f15dee769399b01 /openbsc/src | |
parent | 54fa7991295d64a01a39f7863f585ff8ab08ed13 (diff) | |
parent | 575b89585f7fa7cb4104eeb9f853561af16603d3 (diff) |
Merge branch 'on-waves/mgcp'
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/mgcp/mgcp_main.c | 60 | ||||
-rw-r--r-- | openbsc/src/mgcp/mgcp_network.c | 22 | ||||
-rw-r--r-- | openbsc/src/mgcp/mgcp_protocol.c | 85 | ||||
-rw-r--r-- | openbsc/src/mgcp/mgcp_vty.c | 35 |
4 files changed, 121 insertions, 81 deletions
diff --git a/openbsc/src/mgcp/mgcp_main.c b/openbsc/src/mgcp/mgcp_main.c index 147a765f0..5e337e902 100644 --- a/openbsc/src/mgcp/mgcp_main.c +++ b/openbsc/src/mgcp/mgcp_main.c @@ -38,8 +38,11 @@ #include <openbsc/gsm_data.h> #include <osmocore/select.h> #include <openbsc/mgcp.h> +#include <openbsc/mgcp_internal.h> #include <openbsc/telnet_interface.h> +#include <vty/command.h> + #include "../../bscconfig.h" /* this is here for the vty... it will never be called */ @@ -51,8 +54,9 @@ void subscr_put() { abort(); } #warning "Make use of the rtp proxy code" static struct bsc_fd bfd; -static int first_request = 1; static struct mgcp_config *cfg; +static int reset_endpoints = 0; + const char *openbsc_version = "OpenBSC MGCP " PACKAGE_VERSION; const char *openbsc_copyright = "Copyright (C) 2009-2010 Holger Freyther and On-Waves\n" @@ -74,10 +78,10 @@ static void print_help() printf(" -c --config-file filename The config file to use.\n"); } -static void print_version() +static void print_mgcp_version() { printf("%s\n\n", openbsc_version); - printf(openbsc_copyright); + printf("%s", openbsc_copyright); } static void handle_options(int argc, char** argv) @@ -105,7 +109,7 @@ static void handle_options(int argc, char** argv) config_file = talloc_strdup(tall_bsc_ctx, optarg); break; case 'V': - print_version(); + print_mgcp_version(); exit(0); break; default: @@ -115,12 +119,21 @@ static void handle_options(int argc, char** argv) } } +/* simply remember this */ +static int mgcp_rsip_cb(struct mgcp_config *cfg) +{ + reset_endpoints = 1; + + return 0; +} + static int read_call_agent(struct bsc_fd *fd, unsigned int what) { struct sockaddr_in addr; socklen_t slen = sizeof(addr); struct msgb *msg; struct msgb *resp; + int i; msg = (struct msgb *) fd->data; @@ -136,18 +149,6 @@ static int read_call_agent(struct bsc_fd *fd, unsigned int what) return -1; } - if (first_request) { - first_request = 0; - resp = mgcp_create_rsip(); - - if (resp) { - sendto(bfd.fd, resp->l2h, msgb_l2len(resp), 0, - (struct sockaddr *) &addr, sizeof(addr)); - msgb_free(resp); - } - return 0; - } - /* handle message now */ msg->l2h = msgb_put(msg, rc); resp = mgcp_handle_message(cfg, msg); @@ -157,6 +158,16 @@ static int read_call_agent(struct bsc_fd *fd, unsigned int what) sendto(bfd.fd, resp->l2h, msgb_l2len(resp), 0, (struct sockaddr *) &addr, sizeof(addr)); msgb_free(resp); } + + if (reset_endpoints) { + LOGP(DMGCP, LOGL_NOTICE, "Asked to reset endpoints.\n"); + reset_endpoints = 0; + + /* is checking in_addr.s_addr == INADDR_LOOPBACK making it more secure? */ + for (i = 1; i < cfg->number_endpoints; ++i) + mgcp_free_endp(&cfg->endpoints[i]); + } + return 0; } @@ -186,6 +197,8 @@ int main(int argc, char** argv) if (rc < 0) return rc; + /* set some callbacks */ + cfg->reset_cb = mgcp_rsip_cb; /* we need to bind a socket */ if (rc == 0) { @@ -217,11 +230,11 @@ int main(int argc, char** argv) if (bsc_register_fd(&bfd) != 0) { - DEBUGP(DMGCP, "Failed to register the fd\n"); + LOGP(DMGCP, LOGL_FATAL, "Failed to register the fd\n"); return -1; } - DEBUGP(DMGCP, "Configured for MGCP.\n"); + LOGP(DMGCP, LOGL_NOTICE, "Configured for MGCP.\n"); } /* initialisation */ @@ -235,3 +248,14 @@ int main(int argc, char** argv) return 0; } + +struct gsm_network; +int bsc_vty_init(struct gsm_network *dummy) +{ + cmd_init(1); + vty_init(); + + mgcp_vty_init(); + return 0; +} + diff --git a/openbsc/src/mgcp/mgcp_network.c b/openbsc/src/mgcp/mgcp_network.c index b76ca4732..cd10d2a8c 100644 --- a/openbsc/src/mgcp/mgcp_network.c +++ b/openbsc/src/mgcp/mgcp_network.c @@ -25,6 +25,7 @@ #include <string.h> #include <unistd.h> #include <endian.h> +#include <errno.h> #include <sys/socket.h> #include <arpa/inet.h> @@ -90,6 +91,9 @@ static void patch_payload(int payload, char *data, int len) if (len < sizeof(*rtp_hdr)) return; + if (payload < 0) + return; + rtp_hdr = (struct rtp_hdr *) data; rtp_hdr->payload_type = payload; } @@ -119,16 +123,14 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what) rc = recvfrom(fd->fd, &buf, sizeof(buf), 0, (struct sockaddr *) &addr, &slen); if (rc < 0) { - LOGP(DMGCP, LOGL_ERROR, "Failed to receive message on: 0x%x\n", - ENDPOINT_NUMBER(endp)); + LOGP(DMGCP, LOGL_ERROR, "Failed to receive message on: 0x%x errno: %d/%s\n", + ENDPOINT_NUMBER(endp), errno, strerror(errno)); return -1; } /* do not forward aynthing... maybe there is a packet from the bts */ - if (endp->ci == CI_UNUSED) { - LOGP(DMGCP, LOGL_ERROR, "Unknown message on endpoint: 0x%x\n", ENDPOINT_NUMBER(endp)); + if (endp->ci == CI_UNUSED) return -1; - } /* * Figure out where to forward it to. This code assumes that we @@ -146,7 +148,9 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what) /* We have no idea who called us, maybe it is the BTS. */ if (dest == DEST_NETWORK && (endp->bts_rtp == 0 || cfg->forward_ip)) { /* it was the BTS... */ - if (!cfg->bts_ip || memcmp(&addr.sin_addr, &cfg->bts_in, sizeof(cfg->bts_in)) == 0) { + if (!cfg->bts_ip + || memcmp(&addr.sin_addr, &cfg->bts_in, sizeof(cfg->bts_in)) == 0 + || memcmp(&addr.sin_addr, &endp->bts, sizeof(endp->bts)) == 0) { if (fd == &endp->local_rtp) { endp->bts_rtp = addr.sin_port; } else { @@ -159,6 +163,12 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what) } } + /* do this before the loop handling */ + if (dest == DEST_NETWORK) + ++endp->in_bts; + else + ++endp->in_remote; + /* dispatch */ if (cfg->audio_loop) dest = !dest; diff --git a/openbsc/src/mgcp/mgcp_protocol.c b/openbsc/src/mgcp/mgcp_protocol.c index f7ef5470d..76eb7c2a0 100644 --- a/openbsc/src/mgcp/mgcp_protocol.c +++ b/openbsc/src/mgcp/mgcp_protocol.c @@ -80,11 +80,6 @@ enum mgcp_connection_mode { } -struct mgcp_msg_ptr { - unsigned int start; - unsigned int length; -}; - struct mgcp_request { char *name; struct msgb *(*handle_request) (struct mgcp_config *cfg, struct msgb *msg); @@ -98,6 +93,7 @@ static struct msgb *handle_audit_endpoint(struct mgcp_config *cfg, struct msgb * static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg); static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg); static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg); +static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg); static int generate_call_id(struct mgcp_config *cfg) { @@ -119,12 +115,6 @@ static int generate_call_id(struct mgcp_config *cfg) return cfg->last_call_id; } -/* FIXIME/TODO: need to have a list of pending transactions and check that */ -static unsigned int generate_transaction_id() -{ - return abs(rand()); -} - /* * array of function pointers for handling various * messages. In the future this might be binary sorted @@ -135,6 +125,9 @@ static const struct mgcp_request mgcp_requests [] = { MGCP_REQUEST("CRCX", handle_create_con, "CreateConnection") MGCP_REQUEST("DLCX", handle_delete_con, "DeleteConnection") MGCP_REQUEST("MDCX", handle_modify_con, "ModifiyConnection") + + /* SPEC extension */ + MGCP_REQUEST("RSIP", handle_rsip, "ReSetInProgress") }; static struct msgb *mgcp_msgb_alloc(void) @@ -194,23 +187,6 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp, return mgcp_create_response_with_data(200, msg, trans_id, sdp_record); } -/* send a static record */ -struct msgb *mgcp_create_rsip(void) -{ - struct msgb *msg; - int len; - - msg = mgcp_msgb_alloc(); - if (!msg) - return NULL; - - len = snprintf((char *) msg->data, 2048, - "RSIP %u *@mgw MGCP 1.0\n" - "RM: restart\n", generate_transaction_id()); - msg->l2h = msgb_put(msg, len); - return msg; -} - /* * handle incoming messages: * - this can be a command (four letters, space, transaction id) @@ -221,25 +197,25 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg) int code; struct msgb *resp = NULL; - if (msg->len < 4) { + if (msgb_l2len(msg) < 4) { LOGP(DMGCP, LOGL_ERROR, "mgs too short: %d\n", msg->len); return NULL; } /* attempt to treat it as a response */ - if (sscanf((const char *)&msg->data[0], "%3d %*s", &code) == 1) { + if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) { LOGP(DMGCP, LOGL_DEBUG, "Response: Code: %d\n", code); } else { int i, handled = 0; msg->l3h = &msg->l2h[4]; for (i = 0; i < ARRAY_SIZE(mgcp_requests); ++i) - if (strncmp(mgcp_requests[i].name, (const char *) &msg->data[0], 4) == 0) { + if (strncmp(mgcp_requests[i].name, (const char *) &msg->l2h[0], 4) == 0) { handled = 1; resp = mgcp_requests[i].handle_request(cfg, msg); break; } if (!handled) { - LOGP(DMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->data[0]); + LOGP(DMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->l2h[0]); } } @@ -296,9 +272,9 @@ static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char * return &cfg->endpoints[gw]; } -static int analyze_header(struct mgcp_config *cfg, struct msgb *msg, - struct mgcp_msg_ptr *ptr, int size, - const char **transaction_id, struct mgcp_endpoint **endp) +int mgcp_analyze_header(struct mgcp_config *cfg, struct msgb *msg, + struct mgcp_msg_ptr *ptr, int size, + const char **transaction_id, struct mgcp_endpoint **endp) { int found; @@ -334,8 +310,11 @@ static int analyze_header(struct mgcp_config *cfg, struct msgb *msg, } *transaction_id = (const char *)&msg->l3h[ptr[0].start]; - *endp = find_endpoint(cfg, (const char *)&msg->l3h[ptr[1].start]); - return *endp == NULL; + if (endp) { + *endp = find_endpoint(cfg, (const char *)&msg->l3h[ptr[1].start]); + return *endp == NULL; + } + return 0; } static int verify_call_id(const struct mgcp_endpoint *endp, @@ -369,7 +348,7 @@ static struct msgb *handle_audit_endpoint(struct mgcp_config *cfg, struct msgb * const char *trans_id; struct mgcp_endpoint *endp; - found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); + found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); if (found != 0) response = 500; else @@ -402,13 +381,19 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg) int error_code = 500; int port; - found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); + found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); if (found != 0) return create_response(500, "CRCX", trans_id); if (endp->ci != CI_UNUSED) { - LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n", ENDPOINT_NUMBER(endp)); - return create_response(500, "CRCX", trans_id); + if (cfg->force_realloc) { + LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n", + ENDPOINT_NUMBER(endp)); + } else { + LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n", + ENDPOINT_NUMBER(endp)); + return create_response(500, "CRCX", trans_id); + } } /* parse CallID C: and LocalParameters L: */ @@ -501,7 +486,7 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg) struct mgcp_endpoint *endp; int error_code = 500; - found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); + found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); if (found != 0) return create_response(error_code, "MDCX", trans_id); @@ -614,7 +599,7 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg) struct mgcp_endpoint *endp; int error_code = 500; - found = analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); + found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp); if (found != 0) return create_response(error_code, "DLCX", trans_id); @@ -678,6 +663,13 @@ error3: return create_response(error_code, "DLCX", trans_id); } +static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg) +{ + if (cfg->reset_cb) + cfg->reset_cb(cfg); + return NULL; +} + struct mgcp_config *mgcp_config_alloc(void) { struct mgcp_config *cfg; @@ -722,7 +714,7 @@ int mgcp_endpoints_allocate(struct mgcp_config *cfg) void mgcp_free_endp(struct mgcp_endpoint *endp) { - LOGP(DMGCP, LOGL_NOTICE, "Deleting endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp)); + LOGP(DMGCP, LOGL_DEBUG, "Deleting endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp)); endp->ci= CI_UNUSED; if (endp->callid) { @@ -732,7 +724,7 @@ void mgcp_free_endp(struct mgcp_endpoint *endp) if (endp->local_options) { talloc_free(endp->local_options); - endp->callid = NULL; + endp->local_options = NULL; } if (!endp->cfg->early_bind) { @@ -742,4 +734,7 @@ void mgcp_free_endp(struct mgcp_endpoint *endp) endp->net_rtp = endp->net_rtcp = endp->bts_rtp = endp->bts_rtcp = 0; endp->net_payload_type = endp->bts_payload_type = -1; + endp->in_bts = endp->in_remote = 0; + memset(&endp->remote, 0, sizeof(endp->remote)); + memset(&endp->bts, 0, sizeof(endp->bts)); } diff --git a/openbsc/src/mgcp/mgcp_vty.c b/openbsc/src/mgcp/mgcp_vty.c index f13b3cfa7..af762c57e 100644 --- a/openbsc/src/mgcp/mgcp_vty.c +++ b/openbsc/src/mgcp/mgcp_vty.c @@ -63,6 +63,8 @@ static int config_write_mgcp(struct vty *vty) vty_out(vty, " forward audio ip %s%s", g_cfg->forward_ip, VTY_NEWLINE); if (g_cfg->forward_port != 0) vty_out(vty, " forward audio port %d%s", g_cfg->forward_port, VTY_NEWLINE); + if (g_cfg->call_agent_addr) + vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE); return CMD_SUCCESS; } @@ -75,10 +77,12 @@ DEFUN(show_mcgp, show_mgcp_cmd, "show mgcp", vty_out(vty, "MGCP is up and running with %u endpoints:%s", g_cfg->number_endpoints - 1, VTY_NEWLINE); for (i = 1; i < g_cfg->number_endpoints; ++i) { struct mgcp_endpoint *endp = &g_cfg->endpoints[i]; - vty_out(vty, " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u%s", + vty_out(vty, " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s traffic in :%u/%u%s", i, endp->ci, ntohs(endp->net_rtp), ntohs(endp->net_rtcp), - ntohs(endp->bts_rtp), ntohs(endp->bts_rtcp), VTY_NEWLINE); + ntohs(endp->bts_rtp), ntohs(endp->bts_rtcp), + inet_ntoa(endp->bts), endp->in_bts, endp->in_remote, + VTY_NEWLINE); } return CMD_SUCCESS; @@ -237,6 +241,17 @@ DEFUN(cfg_mgcp_forward_port, return CMD_SUCCESS; } +DEFUN(cfg_mgcp_agent_addr, + cfg_mgcp_agent_addr_cmd, + "call agent ip IP", + "Set the address of the call agent.") +{ + if (g_cfg->call_agent_addr) + talloc_free(g_cfg->call_agent_addr); + g_cfg->call_agent_addr = talloc_strdup(g_cfg, argv[0]); + return CMD_SUCCESS; +} + int mgcp_vty_init(void) { install_element(VIEW_NODE, &show_mgcp_cmd); @@ -256,6 +271,7 @@ int mgcp_vty_init(void) install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd); install_element(MGCP_NODE, &cfg_mgcp_forward_ip_cmd); install_element(MGCP_NODE, &cfg_mgcp_forward_port_cmd); + install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd); return 0; } @@ -274,6 +290,11 @@ int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg) if (!g_cfg->bts_ip) fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n"); + if (!g_cfg->source_addr) { + fprintf(stderr, "You need to specify a bind address.\n"); + return -1; + } + if (mgcp_endpoints_allocate(g_cfg) != 0) { fprintf(stderr, "Failed to allocate endpoints: %d. Quitting.\n", g_cfg->number_endpoints); return -1; @@ -327,13 +348,3 @@ int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg) return !!g_cfg->forward_ip; } -struct gsm_network; -int bsc_vty_init(struct gsm_network *dummy) -{ - cmd_init(1); - vty_init(); - - mgcp_vty_init(); - return 0; -} - |