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:
parent
0ab152b2c6
commit
a790f0c082
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue