mgw: Initial IPv6 support

This commit contains the bulky work of moving all address parsing to
support IPv6 together with IPv4.
Some specific patches required for full IPv6+IPv4 support requiring
behavioral changes come after this one.

Full Osmux IPv6 support is left out of the scope of this patch.

Depends: libosmocore.git Ie07a38b05b7888885dba4ae795e9f3d9a561543d (> 1.4.0)
Depends: libosmocore.git I59bf4b4b3ed14766a5a5285923d1ffa9fc8b2294 (> 1.4.0)
Change-Id: I504ca776d88fd852bbaef07060c125980db3fdd7
This commit is contained in:
Pau Espin 2020-08-31 13:29:11 +02:00
parent 0ab152b2c6
commit a790f0c082
12 changed files with 281 additions and 117 deletions

View File

@ -23,6 +23,7 @@
#pragma once
#include <osmocom/core/msgb.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/write_queue.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/logging.h>
@ -207,4 +208,4 @@ int mgcp_send_reset_all(struct mgcp_config *cfg);
int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
int mgcp_udp_send(int fd, struct osmo_sockaddr *addr, int port, char *buf, int len);

View File

@ -26,7 +26,7 @@
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/i460_mux.h>
struct sockaddr_in;
struct sockaddr;
struct mgcp_conn;
struct mgcp_conn_rtp;
struct mgcp_endpoint;
@ -42,7 +42,7 @@ LOGP(cat, level, "endpoint:%s " fmt, \
struct osmo_rtp_msg_ctx {
int proto;
struct mgcp_conn_rtp *conn_src;
struct sockaddr_in *from_addr;
struct osmo_sockaddr *from_addr;
};
#define OSMO_RTP_MSG_CTX(MSGB) ((struct osmo_rtp_msg_ctx*)(MSGB)->cb)

View File

@ -2,6 +2,9 @@
#include <inttypes.h>
#include <stdbool.h>
#include <osmocom/core/socket.h>
#include <osmocom/mgcp/mgcp.h>
#define MGCP_DUMMY_LOAD 0x23
@ -79,7 +82,7 @@ struct mgcp_rtp_codec {
/* 'mgcp_rtp_end': basically a wrapper around the RTP+RTCP ports */
struct mgcp_rtp_end {
/* remote IP address of the RTP socket */
struct in_addr addr;
struct osmo_sockaddr addr;
/* in network byte order */
int rtp_port, rtcp_port;
@ -121,12 +124,12 @@ struct mgcp_rtp_tap {
/* is this tap active (1) or not (0) */
int enabled;
/* IP/port to which we're forwarding the tapped data */
struct sockaddr_in forward;
struct osmo_sockaddr forward;
};
struct mgcp_conn;
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct osmo_sockaddr *addr,
struct msgb *msg, struct mgcp_conn_rtp *conn_src,
struct mgcp_conn_rtp *conn_dst);
int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
@ -140,7 +143,7 @@ void mgcp_free_rtp_port(struct mgcp_rtp_end *end);
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr, struct msgb *msg);
struct osmo_sockaddr *addr, struct msgb *msg);
void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn);
int mgcp_set_ip_tos(int fd, int tos);

View File

@ -1,5 +1,6 @@
#pragma once
#include <osmocom/core/socket.h>
#include <osmocom/netif/osmux.h>
struct mgcp_conn_rtp;
@ -13,7 +14,7 @@ enum {
int osmux_init(int role, struct mgcp_config *cfg);
int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
struct in_addr *addr, uint16_t port);
struct osmo_sockaddr *addr, uint16_t port);
void conn_osmux_disable(struct mgcp_conn_rtp *conn);
int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid);
void conn_osmux_release_cid(struct mgcp_conn_rtp *conn);

View File

@ -349,6 +349,7 @@ void mgcp_conn_free_all(struct mgcp_endpoint *endp)
char *mgcp_conn_dump(struct mgcp_conn *conn)
{
static char str[sizeof(conn->name)+sizeof(conn->id)+256];
char ipbuf[INET6_ADDRSTRLEN];
if (!conn) {
snprintf(str, sizeof(str), "(null connection)");
@ -362,7 +363,7 @@ char *mgcp_conn_dump(struct mgcp_conn *conn)
"rtp:%u rtcp:%u)",
conn->name,
conn->id,
inet_ntoa(conn->u.rtp.end.addr),
osmo_sockaddr_ntop(&conn->u.rtp.end.addr.u.sa, ipbuf),
ntohs(conn->u.rtp.end.rtp_port),
ntohs(conn->u.rtp.end.rtcp_port));
break;

View File

@ -77,6 +77,16 @@ static void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_end
static int rx_rtp(struct msgb *msg);
static bool addr_is_any(struct osmo_sockaddr *osa) {
if (osa->u.sa.sa_family == AF_INET6) {
struct in6_addr ip6_any = IN6ADDR_ANY_INIT;
return memcmp(&osa->u.sin6.sin6_addr,
&ip6_any, sizeof(ip6_any)) == 0;
} else {
return osa->u.sin.sin_addr.s_addr == 0;
}
}
/*! Determine the local rtp bind IP-address.
* \param[out] addr caller provided memory to store the resulting IP-Address.
* \param[in] endp mgcp endpoint, that holds a copy of the VTY parameters.
@ -89,19 +99,20 @@ void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn)
{
struct mgcp_endpoint *endp;
char ipbuf[INET6_ADDRSTRLEN];
int rc;
endp = conn->conn->endp;
/* Try probing the local IP-Address */
if (endp->cfg->net_ports.bind_addr_probe && conn->end.addr.s_addr != 0) {
rc = osmo_sock_local_ip(addr, inet_ntoa(conn->end.addr));
if (endp->cfg->net_ports.bind_addr_probe && !addr_is_any(&conn->end.addr)) {
rc = osmo_sock_local_ip(addr, osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
if (rc < 0)
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"local interface auto detection failed, using configured addresses...\n");
else {
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
"selected local rtp bind ip %s by probing using remote ip %s\n",
addr, inet_ntoa(conn->end.addr));
addr, osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
return;
}
}
@ -110,7 +121,7 @@ void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn)
if (endp->cfg->net_ports.bind_addr) {
/* Check there is a bind IP for the RTP traffic configured,
* if so, use that IP-Address */
osmo_strlcpy(addr, endp->cfg->net_ports.bind_addr, INET_ADDRSTRLEN);
osmo_strlcpy(addr, endp->cfg->net_ports.bind_addr, INET6_ADDRSTRLEN);
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
"using configured rtp bind ip as local bind ip %s\n",
addr);
@ -118,7 +129,7 @@ void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn)
/* No specific bind IP is configured for the RTP traffic, so
* assume the IP where we listen for incoming MGCP messages
* as bind IP */
osmo_strlcpy(addr, endp->cfg->source_addr, INET_ADDRSTRLEN);
osmo_strlcpy(addr, endp->cfg->source_addr, INET6_ADDRSTRLEN);
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
"using mgcp bind ip as local rtp bind ip: %s\n", addr);
}
@ -154,19 +165,26 @@ static uint32_t get_current_ts(unsigned codec_rate)
* \param[in] buf buffer that holds the data to be send.
* \param[in] len length of the data to be sent.
* \returns bytes sent, -1 on error. */
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
int mgcp_udp_send(int fd, struct osmo_sockaddr *addr, int port, char *buf, int len)
{
struct sockaddr_in out;
char ipbuf[INET6_ADDRSTRLEN];
size_t addr_len;
bool is_ipv6 = addr->u.sa.sa_family == AF_INET6;
LOGP(DRTP, LOGL_DEBUG,
"sending %i bytes length packet to %s:%u ...\n",
len, inet_ntoa(*addr), ntohs(port));
"sending %i bytes length packet to %s:%u ...\n", len,
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
ntohs(port));
out.sin_family = AF_INET;
out.sin_port = port;
memcpy(&out.sin_addr, addr, sizeof(*addr));
if (is_ipv6) {
addr->u.sin6.sin6_port = port;
addr_len = sizeof(addr->u.sin6);
} else {
addr->u.sin.sin_port = port;
addr_len = sizeof(addr->u.sin);
}
return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out));
return sendto(fd, buf, len, 0, &addr->u.sa, addr_len);
}
/*! send RTP dummy packet (to keep NAT connection open).
@ -229,12 +247,13 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_stream_state *sstate,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr,
struct osmo_sockaddr *addr,
uint16_t seq, uint32_t timestamp,
const char *text, int32_t * tsdelta_out)
{
int32_t tsdelta;
int32_t timestamp_error;
char ipbuf[INET6_ADDRSTRLEN];
/* Not fully intialized, skip */
if (sstate->last_tsdelta == 0 && timestamp == sstate->last_timestamp)
@ -251,8 +270,9 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
"from %s:%d\n",
text, seq,
state->patch.timestamp_offset, state->patch.seq_offset,
sstate->ssrc, timestamp, inet_ntoa(addr->sin_addr),
ntohs(addr->sin_port));
sstate->ssrc, timestamp,
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
return 0;
}
@ -267,9 +287,9 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
"The %s timestamp delta is %d "
"on SSRC: %u timestamp: %u "
"from %s:%d\n",
text, tsdelta,
sstate->ssrc, timestamp,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
text, tsdelta, sstate->ssrc, timestamp,
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
return 0;
}
@ -281,7 +301,8 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
"on SSRC: %u timestamp: %u from %s:%d\n",
text, sstate->last_tsdelta, tsdelta,
sstate->ssrc, timestamp,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
}
@ -303,7 +324,8 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
(int16_t)(seq - sstate->last_seq),
(int32_t)(timestamp - sstate->last_timestamp),
tsdelta,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa),
state->packet_duration);
}
return 1;
@ -313,12 +335,13 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr,
struct osmo_sockaddr *addr,
int16_t delta_seq, uint32_t in_timestamp)
{
int32_t tsdelta = state->packet_duration;
int timestamp_offset;
uint32_t out_timestamp;
char ipbuf[INET6_ADDRSTRLEN];
if (tsdelta == 0) {
tsdelta = state->out_stream.last_tsdelta;
@ -327,7 +350,8 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
"A fixed packet duration is not available, "
"using last output timestamp delta instead: %d "
"from %s:%d\n", tsdelta,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
} else {
tsdelta = rtp_end->codec->rate * 20 / 1000;
LOGPENDP(endp, DRTP, LOGL_NOTICE,
@ -335,7 +359,8 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
"are not available, "
"using fixed 20ms instead: %d "
"from %s:%d\n", tsdelta,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
}
@ -344,13 +369,13 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
if (state->patch.timestamp_offset != timestamp_offset) {
state->patch.timestamp_offset = timestamp_offset;
LOGPENDP(endp, DRTP, LOGL_NOTICE,
"Timestamp offset change on SSRC: %u "
"SeqNo delta: %d, TS offset: %d, "
"from %s:%d\n", state->in_stream.ssrc,
delta_seq, state->patch.timestamp_offset,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
return timestamp_offset;
@ -360,9 +385,10 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr,
struct osmo_sockaddr *addr,
uint32_t timestamp)
{
char ipbuf[INET6_ADDRSTRLEN];
int ts_error = 0;
int ts_check = 0;
int ptime = state->packet_duration;
@ -375,14 +401,14 @@ static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
/* If there is an alignment error, we have to compensate it */
if (ts_error) {
state->patch.timestamp_offset += ptime - ts_error;
LOGPENDP(endp, DRTP, LOGL_NOTICE,
"Corrected timestamp alignment error of %d on SSRC: %u "
"new TS offset: %d, "
"from %s:%d\n",
ts_error, state->in_stream.ssrc,
state->patch.timestamp_offset, inet_ntoa(addr->sin_addr),
ntohs(addr->sin_port));
state->patch.timestamp_offset,
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
/* Check we really managed to compensate the timestamp
@ -521,8 +547,9 @@ static int mgcp_patch_pt(struct mgcp_conn_rtp *conn_src,
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr, struct msgb *msg)
struct osmo_sockaddr *addr, struct msgb *msg)
{
char ipbuf[INET6_ADDRSTRLEN];
uint32_t arrival_time;
int32_t transit;
uint16_t seq;
@ -560,7 +587,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
"pkt-duration: %d, from %s:%d\n",
state->in_stream.ssrc,
state->patch.seq_offset, state->packet_duration,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
if (state->packet_duration == 0) {
state->packet_duration =
rtp_end->codec->rate * 20 / 1000;
@ -568,14 +596,16 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
"fixed packet duration is not available, "
"using fixed 20ms instead: %d from %s:%d\n",
state->packet_duration,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
} else if (state->in_stream.ssrc != ssrc) {
LOGPENDP(endp, DRTP, LOGL_NOTICE,
"SSRC changed: %u -> %u "
"from %s:%d\n",
state->in_stream.ssrc, rtp_hdr->ssrc,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
state->in_stream.ssrc = ssrc;
if (rtp_end->force_constant_ssrc) {
@ -604,7 +634,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
"SeqNo offset: %d, TS offset: %d "
"from %s:%d\n", state->in_stream.ssrc,
state->patch.seq_offset, state->patch.timestamp_offset,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
state->in_stream.last_tsdelta = 0;
@ -825,7 +856,7 @@ static void gen_rtp_header(struct msgb *msg, struct mgcp_rtp_end *rtp_end,
* \param[in] conn_src associated source connection.
* \param[in] conn_dst associated destination connection.
* \returns 0 on success, -1 on ERROR. */
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct osmo_sockaddr *addr,
struct msgb *msg, struct mgcp_conn_rtp *conn_src,
struct mgcp_conn_rtp *conn_dst)
{
@ -836,6 +867,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
struct mgcp_trunk *trunk = endp->trunk;
struct mgcp_rtp_end *rtp_end;
struct mgcp_rtp_state *rtp_state;
char ipbuf[INET6_ADDRSTRLEN];
char *dest_name;
int rc;
int len;
@ -886,7 +918,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
"output disabled, drop to %s %s "
"rtp_port:%u rtcp_port:%u\n",
dest_name,
inet_ntoa(rtp_end->addr),
osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
);
} else if (is_rtp) {
@ -932,7 +964,8 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
LOGPENDP(endp, DRTP, LOGL_DEBUG,
"process/send to %s %s "
"rtp_port:%u rtcp_port:%u\n",
dest_name, inet_ntoa(rtp_end->addr),
dest_name,
osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
);
@ -975,7 +1008,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
} else if (!trunk->omit_rtcp) {
LOGPENDP(endp, DRTP, LOGL_DEBUG,
"send to %s %s rtp_port:%u rtcp_port:%u\n",
dest_name, inet_ntoa(rtp_end->addr),
dest_name, osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
);
@ -995,10 +1028,11 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
/* Check if the origin (addr) matches the address/port data of the RTP
* connections. */
static int check_rtp_origin(struct mgcp_conn_rtp *conn,
struct sockaddr_in *addr)
static int check_rtp_origin(struct mgcp_conn_rtp *conn, struct osmo_sockaddr *addr)
{
if (conn->end.addr.s_addr == 0) {
char ipbuf[INET6_ADDRSTRLEN];
if (addr_is_any(&conn->end.addr)) {
switch (conn->conn->mode) {
case MGCP_CONN_LOOPBACK:
/* HACK: for IuUP, we want to reply with an IuUP Initialization ACK upon the first RTP
@ -1010,7 +1044,8 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
* MGCP port is in loopback mode, allow looping back the packet to any source. */
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"In loopback mode and remote address not set:"
" allowing data from address: %s\n", inet_ntoa(addr->sin_addr));
" allowing data from address: %s\n",
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
return 0;
default:
@ -1019,18 +1054,25 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
* confuse humans with expected errors. */
LOGPCONN(conn->conn, DRTP, LOGL_INFO,
"Rx RTP from %s, but remote address not set:"
" dropping early media\n", inet_ntoa(addr->sin_addr));
" dropping early media\n",
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
return -1;
}
}
/* Note: Check if the inbound RTP data comes from the same host to
* which we send our outgoing RTP traffic. */
if (conn->end.addr.s_addr != addr->sin_addr.s_addr) {
if (conn->end.addr.u.sa.sa_family != addr->u.sa.sa_family ||
(conn->end.addr.u.sa.sa_family == AF_INET &&
conn->end.addr.u.sin.sin_addr.s_addr != addr->u.sin.sin_addr.s_addr) ||
(conn->end.addr.u.sa.sa_family == AF_INET6 &&
memcmp(&conn->end.addr.u.sin6.sin6_addr, &addr->u.sin6.sin6_addr,
sizeof(struct in6_addr)))) {
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"data from wrong address: %s, ", inet_ntoa(addr->sin_addr));
"data from wrong address: %s, ",
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
LOGPC(DRTP, LOGL_ERROR, "expected: %s\n",
inet_ntoa(conn->end.addr));
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
LOGPCONN(conn->conn, DRTP, LOGL_ERROR, "packet tossed\n");
return -1;
}
@ -1039,10 +1081,11 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
* the same as the remote port where we transmit outgoing RTP traffic
* to (set by MDCX). We use this to check the origin of the data for
* plausibility. */
if (conn->end.rtp_port != addr->sin_port &&
conn->end.rtcp_port != addr->sin_port) {
if (ntohs(conn->end.rtp_port) != osmo_sockaddr_port(&addr->u.sa) &&
ntohs(conn->end.rtcp_port) != osmo_sockaddr_port(&addr->u.sa)) {
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"data from wrong source port: %d, ", ntohs(addr->sin_port));
"data from wrong source port: %d, ",
osmo_sockaddr_port(&addr->u.sa));
LOGPC(DRTP, LOGL_ERROR,
"expected: %d for RTP or %d for RTCP\n",
ntohs(conn->end.rtp_port), ntohs(conn->end.rtcp_port));
@ -1057,26 +1100,29 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
* makes sense */
static int check_rtp_destin(struct mgcp_conn_rtp *conn)
{
char ipbuf[INET6_ADDRSTRLEN];
bool ip_is_any = addr_is_any(&conn->end.addr);
/* Note: it is legal to create a connection but never setting a port
* and IP-address for outgoing data. */
if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0 && conn->end.rtp_port == 0) {
if (ip_is_any && conn->end.rtp_port == 0) {
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
"destination IP-address and rtp port is (not yet) known (%s:%u)\n",
inet_ntoa(conn->end.addr), conn->end.rtp_port);
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
return -1;
}
if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0) {
if (ip_is_any) {
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"destination IP-address is invalid (%s:%u)\n",
inet_ntoa(conn->end.addr), conn->end.rtp_port);
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
return -1;
}
if (conn->end.rtp_port == 0) {
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"destination rtp port is invalid (%s:%u)\n",
inet_ntoa(conn->end.addr), conn->end.rtp_port);
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
return -1;
}
@ -1147,7 +1193,6 @@ static int mgcp_send_rtp(struct mgcp_conn_rtp *conn_dst, struct msgb *msg)
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
enum rtp_proto proto = mc->proto;
struct mgcp_conn_rtp *conn_src = mc->conn_src;
struct sockaddr_in *from_addr = mc->from_addr;
struct mgcp_endpoint *endp = conn_src->conn->endp;
LOGPENDP(endp, DRTP, LOGL_DEBUG, "destin conn:%s\n",
@ -1167,7 +1212,7 @@ static int mgcp_send_rtp(struct mgcp_conn_rtp *conn_dst, struct msgb *msg)
"endpoint type is MGCP_RTP_DEFAULT, "
"using mgcp_send() to forward data directly\n");
return mgcp_send(endp, proto == MGCP_PROTO_RTP,
from_addr, msg, conn_src, conn_dst);
mc->from_addr, msg, conn_src, conn_dst);
case MGCP_OSMUX_BSC_NAT:
case MGCP_OSMUX_BSC:
LOGPENDP(endp, DRTP, LOGL_DEBUG,
@ -1197,7 +1242,7 @@ int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg)
struct mgcp_conn_rtp *conn_src = mc->conn_src;
struct mgcp_conn *conn = conn_src->conn;
struct mgcp_conn *conn_dst;
struct sockaddr_in *from_addr = mc->from_addr;
struct osmo_sockaddr *from_addr = mc->from_addr;
/*! NOTE: This callback function implements the endpoint specific
* dispatch behaviour of an rtp bridge/proxy endpoint. It is assumed
@ -1216,8 +1261,19 @@ int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg)
* address data from the UDP packet header to patch the
* outgoing address in connection on the fly */
if (conn->u.rtp.end.rtp_port == 0) {
conn->u.rtp.end.addr = from_addr->sin_addr;
conn->u.rtp.end.rtp_port = from_addr->sin_port;
OSMO_ASSERT(conn->u.rtp.end.addr.u.sa.sa_family == from_addr->u.sa.sa_family);
switch (from_addr->u.sa.sa_family) {
case AF_INET:
conn->u.rtp.end.addr.u.sin.sin_addr = from_addr->u.sin.sin_addr;
conn->u.rtp.end.rtp_port = from_addr->u.sin.sin_port;
break;
case AF_INET6:
conn->u.rtp.end.addr.u.sin6.sin6_addr = from_addr->u.sin6.sin6_addr;
conn->u.rtp.end.rtp_port = from_addr->u.sin6.sin6_port;
break;
default:
OSMO_ASSERT(false);
}
}
return mgcp_send_rtp(conn_src, msg);
}
@ -1266,7 +1322,7 @@ int mgcp_dispatch_e1_bridge_cb(struct msgb *msg)
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
struct mgcp_conn_rtp *conn_src = mc->conn_src;
struct mgcp_conn *conn = conn_src->conn;
struct sockaddr_in *from_addr = mc->from_addr;
struct osmo_sockaddr *from_addr = mc->from_addr;
/* Check if the connection is in loopback mode, if yes, just send the
* incoming data back to the origin */
@ -1276,8 +1332,19 @@ int mgcp_dispatch_e1_bridge_cb(struct msgb *msg)
* address data from the UDP packet header to patch the
* outgoing address in connection on the fly */
if (conn->u.rtp.end.rtp_port == 0) {
conn->u.rtp.end.addr = from_addr->sin_addr;
conn->u.rtp.end.rtp_port = from_addr->sin_port;
OSMO_ASSERT(conn->u.rtp.end.addr.u.sa.sa_family == from_addr->u.sa.sa_family);
switch (from_addr->u.sa.sa_family) {
case AF_INET:
conn->u.rtp.end.addr.u.sin.sin_addr = from_addr->u.sin.sin_addr;
conn->u.rtp.end.rtp_port = from_addr->u.sin.sin_port;
break;
case AF_INET6:
conn->u.rtp.end.addr.u.sin6.sin6_addr = from_addr->u.sin6.sin6_addr;
conn->u.rtp.end.rtp_port = from_addr->u.sin6.sin6_port;
break;
default:
OSMO_ASSERT(false);
}
}
return mgcp_send_rtp(conn_src, msg);
}
@ -1331,8 +1398,9 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
struct mgcp_conn_rtp *conn_src;
struct mgcp_endpoint *endp;
struct sockaddr_in addr;
struct osmo_sockaddr addr;
socklen_t slen = sizeof(addr);
char ipbuf[INET6_ADDRSTRLEN];
int ret;
enum rtp_proto proto;
struct osmo_rtp_msg_ctx *mc;
@ -1346,7 +1414,7 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
proto = (fd == &conn_src->end.rtp)? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
ret = recvfrom(fd->fd, msgb_data(msg), msg->data_len, 0, (struct sockaddr *)&addr, &slen);
ret = recvfrom(fd->fd, msgb_data(msg), msg->data_len, 0, (struct sockaddr *)&addr.u.sa, &slen);
if (ret <= 0) {
LOG_CONN_RTP(conn_src, LOGL_ERROR, "recvfrom error: %s\n", strerror(errno));
@ -1358,7 +1426,8 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "%s: rx %u bytes from %s:%u\n",
proto == MGCP_PROTO_RTP ? "RTP" : "RTPC",
msgb_length(msg), inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
msgb_length(msg), osmo_sockaddr_ntop(&addr.u.sa, ipbuf),
osmo_sockaddr_port(&addr.u.sa));
if ((proto == MGCP_PROTO_RTP && check_rtp(conn_src, msg))
|| (proto == MGCP_PROTO_RTCP && check_rtcp(conn_src, msg))) {
@ -1383,7 +1452,10 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
};
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "msg ctx: %d %p %s\n",
mc->proto, mc->conn_src,
osmo_hexdump((void*)mc->from_addr, sizeof(struct sockaddr_in)));
osmo_hexdump((void*)mc->from_addr,
mc->from_addr->u.sa.sa_family == AF_INET6 ?
sizeof(struct sockaddr_in6) :
sizeof(struct sockaddr_in)));
/* Increment RX statistics */
rate_ctr_inc(&conn_src->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR]);
@ -1404,7 +1476,7 @@ static int rx_rtp(struct msgb *msg)
{
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
struct mgcp_conn_rtp *conn_src = mc->conn_src;
struct sockaddr_in *from_addr = mc->from_addr;
struct osmo_sockaddr *from_addr = mc->from_addr;
struct mgcp_conn *conn = conn_src->conn;
struct mgcp_trunk *trunk = conn->endp->trunk;
@ -1456,7 +1528,7 @@ int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port)
{
int rc;
rc = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP, source_addr, port,
rc = osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, source_addr, port,
NULL, 0, OSMO_SOCK_F_BIND);
if (rc < 0) {
LOGP(DRTP, LOGL_ERROR, "failed to bind UDP port (%s:%i).\n",
@ -1536,7 +1608,7 @@ int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
{
char name[512];
struct mgcp_rtp_end *end;
char local_ip_addr[INET_ADDRSTRLEN];
char local_ip_addr[INET6_ADDRSTRLEN];
snprintf(name, sizeof(name), "%s-%s", conn->conn->name, conn->conn->id);
end = &conn->end;

View File

@ -148,15 +148,20 @@ osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
/* Lookup existing handle for a specified address, if the handle can not be
* found, the function will automatically allocate one */
static struct osmux_in_handle *
osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
osmux_handle_lookup(struct mgcp_config *cfg, struct osmo_sockaddr *addr, int rem_port)
{
struct osmux_handle *h;
h = osmux_handle_find_get(addr, rem_port);
if (addr->u.sa.sa_family != AF_INET) {
LOGP(DLMGCP, LOGL_DEBUG, "IPv6 not supported in osmux yet!\n");
return NULL;
}
h = osmux_handle_find_get(&addr->u.sin.sin_addr, rem_port);
if (h != NULL)
return h->in;
h = osmux_handle_alloc(cfg, addr, rem_port);
h = osmux_handle_alloc(cfg, &addr->u.sin.sin_addr, rem_port);
if (h == NULL)
return NULL;
@ -236,7 +241,7 @@ static void scheduled_from_osmux_tx_rtp_cb(struct msgb *msg, void *data)
{
struct mgcp_conn_rtp *conn = data;
struct mgcp_endpoint *endp = conn->conn->endp;
struct sockaddr_in addr = { /* FIXME: do we know the source address?? */ };
struct osmo_sockaddr addr = { /* FIXME: do we know the source address?? */ };
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
*mc = (struct osmo_rtp_msg_ctx){
.proto = MGCP_PROTO_RTP,
@ -275,6 +280,8 @@ static struct msgb *osmux_recv(struct osmo_fd *ofd, struct sockaddr_in *addr)
static int endp_osmux_state_check(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
bool sending)
{
char ipbuf[INET6_ADDRSTRLEN];
switch(conn->osmux.state) {
case OSMUX_STATE_ACTIVATING:
if (osmux_enable_conn(endp, conn, &conn->end.addr, conn->end.rtp_port) < 0) {
@ -287,7 +294,8 @@ static int endp_osmux_state_check(struct mgcp_endpoint *endp, struct mgcp_conn_r
LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR,
"Osmux %s CID %u towards %s:%u is now enabled\n",
sending ? "sent" : "received",
conn->osmux.cid, inet_ntoa(conn->end.addr),
conn->osmux.cid,
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf),
ntohs(conn->end.rtp_port));
return 0;
case OSMUX_STATE_ENABLED:
@ -433,7 +441,7 @@ int osmux_init(int role, struct mgcp_config *cfg)
* \param[in] port portnumber of the remote OSMUX endpoint (in network byte order)
* \returns 0 on success, -1 on ERROR */
int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
struct in_addr *addr, uint16_t port)
struct osmo_sockaddr *addr, uint16_t port)
{
/*! If osmux is enabled, initialize the output handler. This handler is
* used to reconstruct the RTP flow from osmux. The RTP SSRC is
@ -444,7 +452,7 @@ int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
* overlapping RTP SSRC traveling to the BTSes behind the BSC,
* similarly, for flows traveling to the MSC.
*/
struct in_addr addr_unset = {};
struct in6_addr addr_unset = {};
static const uint32_t rtp_ssrc_winlen = UINT32_MAX / (OSMUX_CID_MAX + 1);
uint16_t osmux_dummy = endp->cfg->osmux_dummy;
@ -457,7 +465,10 @@ int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
}
/* Wait until we have the connection information from MDCX */
if (memcmp(&conn->end.addr, &addr_unset, sizeof(addr_unset)) == 0) {
if (memcmp(&conn->end.addr, &addr_unset,
conn->end.addr.u.sa.sa_family == AF_INET6 ?
sizeof(struct in6_addr) :
sizeof(struct in_addr)) == 0) {
LOGPCONN(conn->conn, DLMGCP, LOGL_INFO,
"Osmux remote address/port still unknown\n");
return -1;
@ -559,6 +570,7 @@ int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid)
* \returns bytes sent, -1 on error */
int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
{
char ipbuf[INET6_ADDRSTRLEN];
struct osmux_hdr *osmuxh;
int buf_len;
struct in_addr addr_unset = {};
@ -588,7 +600,8 @@ int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
LOGPCONN(conn->conn, DLMGCP, LOGL_DEBUG,
"sending OSMUX dummy load to %s:%u CID %u\n",
inet_ntoa(conn->end.addr), ntohs(conn->end.rtp_port), conn->osmux.cid);
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf),
ntohs(conn->end.rtp_port), conn->osmux.cid);
return mgcp_udp_send(osmux_fd.fd, &conn->end.addr,
conn->end.rtp_port, (char*)osmuxh, buf_len);

View File

@ -230,7 +230,7 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
struct msgb *sdp;
int rc;
struct msgb *result;
char local_ip_addr[INET_ADDRSTRLEN];
char local_ip_addr[INET6_ADDRSTRLEN];
sdp = msgb_alloc_headroom(4096, 128, "sdp record");
if (!sdp)

View File

@ -21,6 +21,9 @@
*/
#include <osmocom/core/msgb.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/mgcp/mgcp.h>
#include <osmocom/mgcp/osmux.h>
#include <osmocom/mgcp/mgcp_conn.h>
@ -259,6 +262,42 @@ error:
return -EINVAL;
}
static int audio_ip_from_sdp(struct osmo_sockaddr *dst_addr, char *sdp)
{
bool is_ipv6;
char ipbuf[INET6_ADDRSTRLEN];
if (strncmp("c=IN IP", sdp, 7) != 0)
return -1;
sdp += 7;
if (*sdp == '6')
is_ipv6 = true;
else if (*sdp == '4')
is_ipv6 = false;
else
return -1;
sdp++;
if (*sdp != ' ')
return -1;
sdp++;
if (is_ipv6) {
/* 45 = INET6_ADDRSTRLEN -1 */
if (sscanf(sdp, "%45s", ipbuf) != 1)
return -1;
if (inet_pton(AF_INET6, ipbuf, &dst_addr->u.sin6.sin6_addr) != 1)
return -1;
dst_addr->u.sa.sa_family = AF_INET6;
} else {
/* 15 = INET_ADDRSTRLEN -1 */
if (sscanf(sdp, "%15s", ipbuf) != 1)
return -1;
if (inet_pton(AF_INET, ipbuf, &dst_addr->u.sin.sin_addr) != 1)
return -1;
dst_addr->u.sa.sa_family = AF_INET;
}
return 0;
}
/* Pick optional fmtp parameters by payload type, if there are no fmtp
* parameters, a nullpointer is returned */
static struct mgcp_codec_param *param_by_pt(int pt, struct sdp_fmtp_param *fmtp_params, unsigned int fmtp_params_len)
@ -289,6 +328,7 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
struct sdp_fmtp_param fmtp_params[MGCP_MAX_CODECS];
unsigned int fmtp_used = 0;
struct mgcp_codec_param *codec_param;
char ipbuf[INET6_ADDRSTRLEN];
char *line;
unsigned int i;
void *tmp_ctx = talloc_new(NULL);
@ -298,7 +338,6 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
int ptime, ptime2 = 0;
char audio_name[64];
int port, rc;
char ipv4[16];
OSMO_ASSERT(endp);
OSMO_ASSERT(conn);
@ -355,10 +394,8 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
codecs_used = rc;
break;
case 'c':
if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) {
inet_aton(ipv4, &rtp->addr);
}
if (audio_ip_from_sdp(&rtp->addr, line) < 0)
return -1;
break;
default:
if (p->endp)
@ -393,7 +430,7 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
LOGPCONN(conn->conn, DLMGCP, LOGL_NOTICE,
"Got media info via SDP: port:%d, addr:%s, duration:%d, payload-types:",
ntohs(rtp->rtp_port), inet_ntoa(rtp->addr),
ntohs(rtp->rtp_port), osmo_sockaddr_ntop(&rtp->addr.u.sa, ipbuf),
rtp->packet_duration_ms);
if (codecs_used == 0)
LOGPC(DLMGCP, LOGL_NOTICE, "none");
@ -529,6 +566,7 @@ int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
int local_port;
struct sdp_fmtp_param fmtp_params[1];
unsigned int fmtp_params_len = 0;
bool addr_is_v6;
OSMO_ASSERT(endp);
OSMO_ASSERT(conn);
@ -543,12 +581,16 @@ int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
audio_name = codec->audio_name;
payload_type = codec->payload_type;
addr_is_v6 = osmo_ip_str_type(addr) == AF_INET6;
rc = msgb_printf(sdp,
"v=0\r\n"
"o=- %s 23 IN IP4 %s\r\n"
"o=- %s 23 IN IP%c %s\r\n"
"s=-\r\n"
"c=IN IP4 %s\r\n"
"t=0 0\r\n", conn->conn->id, addr, addr);
"c=IN IP%c %s\r\n"
"t=0 0\r\n", conn->conn->id,
addr_is_v6 ? '6' : '4', addr,
addr_is_v6 ? '6' : '4', addr);
if (rc < 0)
goto buffer_too_small;

View File

@ -22,6 +22,7 @@
*/
#include <osmocom/core/talloc.h>
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/vty/misc.h>
#include <osmocom/mgcp/mgcp.h>
#include <osmocom/mgcp/mgcp_common.h>
@ -407,9 +408,11 @@ DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
DEFUN(cfg_mgcp_local_ip,
cfg_mgcp_local_ip_cmd,
"local ip A.B.C.D",
"local ip " VTY_IPV46_CMD,
"Local options for the SDP record\n"
IP_STR "IPv4 Address to use in SDP record\n")
IP_STR
"IPv4 Address to use in SDP record\n"
"IPv6 Address to use in SDP record\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
return CMD_SUCCESS;
@ -418,7 +421,10 @@ DEFUN(cfg_mgcp_local_ip,
#define BIND_STR "Listen/Bind related socket option\n"
DEFUN(cfg_mgcp_bind_ip,
cfg_mgcp_bind_ip_cmd,
"bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
"bind ip " VTY_IPV46_CMD,
BIND_STR IP_STR
"IPv4 Address to bind to\n"
"IPv6 Address to bind to\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
return CMD_SUCCESS;
@ -494,8 +500,10 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
DEFUN(cfg_mgcp_rtp_bind_ip,
cfg_mgcp_rtp_bind_ip_cmd,
"rtp bind-ip A.B.C.D",
RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
"rtp bind-ip " VTY_IPV46_CMD,
RTP_STR "Bind endpoints facing the Network\n"
"IPv4 Address to bind to\n"
"IPv6 Address to bind to\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
return CMD_SUCCESS;
@ -850,11 +858,13 @@ DEFUN(cfg_mgcp_no_rtp_keepalive,
return CMD_SUCCESS;
}
#define CALL_AGENT_STR "Callagent information\n"
#define CALL_AGENT_STR "Call agent information\n"
DEFUN(cfg_mgcp_agent_addr,
cfg_mgcp_agent_addr_cmd,
"call-agent ip A.B.C.D",
CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
"call-agent ip " VTY_IPV46_CMD,
CALL_AGENT_STR IP_STR
"IPv4 Address of the call agent\n"
"IPv6 Address of the call agent\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
return CMD_SUCCESS;
@ -1236,13 +1246,15 @@ DEFUN(loop_conn,
DEFUN(tap_rtp,
tap_rtp_cmd,
"tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
"tap-rtp <0-64> ENDPOINT CONN (in|out) " VTY_IPV46_CMD " <0-65534>",
"Forward data on endpoint to a different system\n" "Trunk number\n"
"The endpoint in hex\n"
"The connection id in hex\n"
"Forward incoming data\n"
"Forward leaving data\n"
"destination IP of the data\n" "destination port\n")
"Destination IPv4 of the data\n"
"Destination IPv6 of the data\n"
"Destination port\n")
{
struct mgcp_rtp_tap *tap;
struct mgcp_trunk *trunk;
@ -1290,8 +1302,22 @@ DEFUN(tap_rtp,
}
memset(&tap->forward, 0, sizeof(tap->forward));
inet_aton(argv[4], &tap->forward.sin_addr);
tap->forward.sin_port = htons(atoi(argv[5]));
tap->forward.u.sa.sa_family = osmo_ip_str_type(argv[4]);
switch (tap->forward.u.sa.sa_family) {
case AF_INET:
if (inet_pton(AF_INET, argv[4], &tap->forward.u.sin.sin_addr) != 1)
return CMD_WARNING;
tap->forward.u.sin.sin_port = htons(atoi(argv[5]));
break;
case AF_INET6:
if (inet_pton(AF_INET6, argv[4], &tap->forward.u.sin6.sin6_addr) != 1)
return CMD_WARNING;
tap->forward.u.sin6.sin6_port = htons(atoi(argv[5]));
break;
default:
return CMD_WARNING;
}
tap->enabled = 1;
return CMD_SUCCESS;
}
@ -1407,7 +1433,10 @@ DEFUN(cfg_mgcp_osmux,
DEFUN(cfg_mgcp_osmux_ip,
cfg_mgcp_osmux_ip_cmd,
"osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
"osmux bind-ip " VTY_IPV46_CMD,
OSMUX_STR IP_STR
"IPv4 Address to bind to\n"
"IPv6 Address to bind to\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
return CMD_SUCCESS;

View File

@ -179,7 +179,7 @@ static int mgcp_rsip_cb(struct mgcp_trunk *trunk)
static int read_call_agent(struct osmo_fd *fd, unsigned int what)
{
struct sockaddr_in addr;
struct osmo_sockaddr addr;
socklen_t slen = sizeof(addr);
struct msgb *msg;
struct msgb *resp;
@ -205,7 +205,7 @@ static int read_call_agent(struct osmo_fd *fd, unsigned int what)
msgb_reset(msg);
if (resp) {
sendto(cfg->gw_fd.bfd.fd, resp->l2h, msgb_l2len(resp), 0, (struct sockaddr *) &addr, sizeof(addr));
sendto(cfg->gw_fd.bfd.fd, resp->l2h, msgb_l2len(resp), 0, &addr.u.sa, sizeof(addr));
msgb_free(resp);
}
@ -345,7 +345,7 @@ int main(int argc, char **argv)
if (cfg->call_agent_addr)
flags |= OSMO_SOCK_F_CONNECT;
rc = osmo_sock_init2_ofd(&cfg->gw_fd.bfd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
rc = osmo_sock_init2_ofd(&cfg->gw_fd.bfd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
cfg->source_addr, cfg->source_port,
cfg->call_agent_addr, cfg->call_agent_addr ? 2727 : 0, flags);
if (rc < 0) {

View File

@ -34,6 +34,7 @@
#include <osmocom/core/application.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
#include <string.h>
#include <limits.h>
#include <dlfcn.h>
@ -1262,7 +1263,7 @@ struct rtp_packet_info test_rtp_packets1[] = {
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr, struct msgb *msg);
struct osmo_sockaddr *addr, struct msgb *msg);
static void test_packet_error_detection(int patch_ssrc, int patch_ts)
{
@ -1274,7 +1275,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
struct mgcp_config cfg = {0};
struct mgcp_rtp_state state;
struct mgcp_rtp_end *rtp;
struct sockaddr_in addr = { 0 };
struct osmo_sockaddr addr = { 0 };
uint32_t last_ssrc = 0;
uint32_t last_timestamp = 0;
uint32_t last_seqno = 0;
@ -1486,7 +1487,8 @@ static void test_multilple_codec(void)
OSMO_ASSERT(conn->end.rtp_port == htons(16434));
memset(&addr, 0, sizeof(addr));
inet_aton("8.8.8.8", &addr);
OSMO_ASSERT(conn->end.addr.s_addr == addr.s_addr);
OSMO_ASSERT(conn->end.addr.u.sa.sa_family == AF_INET);
OSMO_ASSERT(conn->end.addr.u.sin.sin_addr.s_addr == addr.s_addr);
/* Check what happens without that flag */