summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/mgcp_internal.h18
-rw-r--r--openbsc/src/mgcp/mgcp_network.c15
-rw-r--r--openbsc/src/mgcp/mgcp_protocol.c2
-rw-r--r--openbsc/src/mgcp/mgcp_vty.c45
4 files changed, 80 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index bdcd03030..19e8e3f2b 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -69,6 +69,21 @@ struct mgcp_rtp_end {
int local_alloc;
};
+enum {
+ MGCP_TAP_BTS_IN,
+ MGCP_TAP_BTS_OUT,
+ MGCP_TAP_NET_IN,
+ MGCP_TAP_NET_OUT,
+
+ /* last element */
+ MGCP_TAP_COUNT
+};
+
+struct mgcp_rtp_tap {
+ int enabled;
+ struct sockaddr_in forward;
+};
+
struct mgcp_endpoint {
int ci;
char *callid;
@@ -89,6 +104,9 @@ struct mgcp_endpoint {
/* SSRC/seq/ts patching for loop */
int allow_patch;
+
+ /* tap for the endpoint */
+ struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
};
#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
diff --git a/openbsc/src/mgcp/mgcp_network.c b/openbsc/src/mgcp/mgcp_network.c
index 387711298..bbc46f418 100644
--- a/openbsc/src/mgcp/mgcp_network.c
+++ b/openbsc/src/mgcp/mgcp_network.c
@@ -151,6 +151,14 @@ static void patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *s
* The below code is for dispatching. We have a dedicated port for
* the data coming from the net and one to discover the BTS.
*/
+static int forward_data(int fd, struct mgcp_rtp_tap *tap, const char *buf, int len)
+{
+ if (!tap->enabled)
+ return 0;
+
+ return sendto(fd, buf, len, 0,
+ (struct sockaddr *)&tap->forward, sizeof(tap->forward));
+}
static int send_to(struct mgcp_endpoint *endp, int dest, int is_rtp,
struct sockaddr_in *addr, char *buf, int rc)
{
@@ -168,6 +176,8 @@ static int send_to(struct mgcp_endpoint *endp, int dest, int is_rtp,
patch_and_count(endp, &endp->bts_state,
endp->net_end.payload_type,
addr, buf, rc);
+ forward_data(endp->net_end.rtp.fd,
+ &endp->taps[MGCP_TAP_NET_OUT], buf, rc);
return udp_send(endp->net_end.rtp.fd, &endp->net_end.addr,
endp->net_end.rtp_port, buf, rc);
} else {
@@ -179,6 +189,8 @@ static int send_to(struct mgcp_endpoint *endp, int dest, int is_rtp,
patch_and_count(endp, &endp->net_state,
endp->bts_end.payload_type,
addr, buf, rc);
+ forward_data(endp->bts_end.rtp.fd,
+ &endp->taps[MGCP_TAP_BTS_OUT], buf, rc);
return udp_send(endp->bts_end.rtp.fd, &endp->bts_end.addr,
endp->bts_end.rtp_port, buf, rc);
} else {
@@ -248,6 +260,8 @@ static int rtp_data_net(struct bsc_fd *fd, unsigned int what)
proto = fd == &endp->net_end.rtp ? PROTO_RTP : PROTO_RTCP;
endp->net_end.packets += 1;
+
+ forward_data(fd->fd, &endp->taps[MGCP_TAP_NET_IN], buf, rc);
return send_to(endp, DEST_BTS, proto == PROTO_RTP, &addr, &buf[0], rc);
}
@@ -310,6 +324,7 @@ static int rtp_data_bts(struct bsc_fd *fd, unsigned int what)
/* do this before the loop handling */
endp->bts_end.packets += 1;
+ forward_data(fd->fd, &endp->taps[MGCP_TAP_BTS_IN], buf, rc);
return send_to(endp, DEST_NETWORK, proto == PROTO_RTP, &addr, &buf[0], rc);
}
diff --git a/openbsc/src/mgcp/mgcp_protocol.c b/openbsc/src/mgcp/mgcp_protocol.c
index 036ddf02a..9916b4086 100644
--- a/openbsc/src/mgcp/mgcp_protocol.c
+++ b/openbsc/src/mgcp/mgcp_protocol.c
@@ -826,4 +826,6 @@ void mgcp_free_endp(struct mgcp_endpoint *endp)
endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE;
endp->allow_patch = 0;
+
+ memset(&endp->taps, 0, sizeof(endp->taps));
}
diff --git a/openbsc/src/mgcp/mgcp_vty.c b/openbsc/src/mgcp/mgcp_vty.c
index 040e8ff2a..0faa674d4 100644
--- a/openbsc/src/mgcp/mgcp_vty.c
+++ b/openbsc/src/mgcp/mgcp_vty.c
@@ -310,10 +310,55 @@ DEFUN(loop_endp,
return CMD_SUCCESS;
}
+DEFUN(tap_call,
+ tap_call_cmd,
+ "tap-call ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
+ "Forward data on endpoint to a different system\n"
+ "The endpoint in hex\n"
+ "Forward the data coming from the bts\n"
+ "Forward the data coming from the bts leaving to the network\n"
+ "Forward the data coming from the net\n"
+ "Forward the data coming from the net leaving to the bts\n"
+ "destination IP of the data\n" "destination port\n")
+{
+ struct mgcp_rtp_tap *tap;
+ struct mgcp_endpoint *endp;
+ int port = 0;
+
+ int endp_no = strtoul(argv[0], NULL, 16);
+ if (endp_no < 1 || endp_no >= g_cfg->number_endpoints) {
+ vty_out(vty, "Endpoint number %s/%d is invalid.%s",
+ argv[0], endp_no, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ endp = &g_cfg->endpoints[endp_no];
+
+ if (strcmp(argv[1], "bts-in") == 0) {
+ port = MGCP_TAP_BTS_IN;
+ } else if (strcmp(argv[1], "bts-out") == 0) {
+ port = MGCP_TAP_BTS_OUT;
+ } else if (strcmp(argv[1], "net-in") == 0) {
+ port = MGCP_TAP_NET_IN;
+ } else if (strcmp(argv[1], "net-out") == 0) {
+ port = MGCP_TAP_NET_OUT;
+ } else {
+ vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ tap = &endp->taps[port];
+ memset(&tap->forward, 0, sizeof(tap->forward));
+ inet_aton(argv[2], &tap->forward.sin_addr);
+ tap->forward.sin_port = htons(atoi(argv[3]));
+ return CMD_SUCCESS;
+}
+
int mgcp_vty_init(void)
{
install_element_ve(&show_mgcp_cmd);
install_element(ENABLE_NODE, &loop_endp_cmd);
+ install_element(ENABLE_NODE, &tap_call_cmd);
install_element(CONFIG_NODE, &cfg_mgcp_cmd);
install_node(&mgcp_node, config_write_mgcp);