nat: First go at handling MGCP inside the nat

Listen on the MGCP gateway port and let our protocol stack
handle everything for now. We will need to have some more
control over things though.
This commit is contained in:
Holger Hans Peter Freyther 2010-03-31 13:02:22 +02:00
parent 2980442e33
commit 82cb311c4f
3 changed files with 117 additions and 0 deletions

View File

@ -142,6 +142,7 @@ struct bsc_nat {
/* MGCP config */
struct mgcp_config *mgcp_cfg;
struct write_queue mgcp_queue;
};
/* create and init the structures */
@ -180,5 +181,6 @@ int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned in
int bsc_mgcp_assign(struct sccp_connections *, struct msgb *msg);
void bsc_mgcp_clear(struct sccp_connections *);
void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
int bsc_mgcp_init(struct bsc_nat *nat);
#endif

View File

@ -29,6 +29,9 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
{
struct tlv_parsed tp;
@ -74,3 +77,109 @@ void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
for (i = 1; i < nat->mgcp_cfg->number_endpoints; ++i)
mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
}
static int mgcp_do_read(struct bsc_fd *fd)
{
struct bsc_nat *nat;
struct msgb *msg, *resp;
int rc;
msg = msgb_alloc(4096, "MGCP GW Read");
if (!msg) {
LOGP(DMGCP, LOGL_ERROR, "Failed to create buffer.\n");
return -1;
}
rc = read(fd->fd, msg->data, msg->data_len);
if (rc <= 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to read errno: %d\n", errno);
msgb_free(msg);
return -1;
}
nat = fd->data;
msg->l2h = msgb_put(msg, rc);
resp = mgcp_handle_message(nat->mgcp_cfg, msg);
msgb_free(msg);
/* we do have a direct answer... e.g. AUEP */
if (resp) {
if (write_queue_enqueue(&nat->mgcp_queue, resp) != 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to enqueue msg.\n");
msgb_free(resp);
}
}
return 0;
}
static int mgcp_do_write(struct bsc_fd *bfd, struct msgb *msg)
{
int rc;
rc = write(bfd->fd, msg->data, msg->len);
if (rc != msg->len) {
LOGP(DMGCP, LOGL_ERROR, "Failed to write msg to MGCP CallAgent.\n");
return -1;
}
return rc;
}
int bsc_mgcp_init(struct bsc_nat *nat)
{
int on;
struct sockaddr_in addr;
if (!nat->mgcp_cfg->call_agent_addr) {
LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
return -1;
}
nat->mgcp_queue.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
if (nat->mgcp_queue.bfd.fd < 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to create MGCP socket. errno: %d\n", errno);
return -1;
}
on = 1;
setsockopt(nat->mgcp_queue.bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
addr.sin_family = AF_INET;
addr.sin_port = htons(nat->mgcp_cfg->source_port);
inet_aton(nat->mgcp_cfg->source_addr, &addr.sin_addr);
if (bind(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to bind. errno: %d\n", errno);
close(nat->mgcp_queue.bfd.fd);
nat->mgcp_queue.bfd.fd = -1;
return -1;
}
addr.sin_port = htons(2727);
inet_aton(nat->mgcp_cfg->call_agent_addr, &addr.sin_addr);
if (connect(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n",
nat->mgcp_cfg->call_agent_addr, errno);
close(nat->mgcp_queue.bfd.fd);
nat->mgcp_queue.bfd.fd = -1;
return -1;
}
write_queue_init(&nat->mgcp_queue, 10);
nat->mgcp_queue.bfd.when = BSC_FD_READ;
nat->mgcp_queue.bfd.data = nat;
nat->mgcp_queue.read_cb = mgcp_do_read;
nat->mgcp_queue.write_cb = mgcp_do_write;
if (bsc_register_fd(&nat->mgcp_queue.bfd) != 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to register MGCP fd.\n");
close(nat->mgcp_queue.bfd.fd);
nat->mgcp_queue.bfd.fd = -1;
return -1;
}
return 0;
}

View File

@ -754,6 +754,12 @@ int main(int argc, char** argv)
/* seed the PRNG */
srand(time(NULL));
/*
* Setup the MGCP code..
*/
if (bsc_mgcp_init(nat) != 0)
return -4;
/* connect to the MSC */
msc_con = bsc_msc_create(msc_address, 5000);
if (!msc_con) {