From a790f0c0823671283ac854ee82ea50deafa96c4b Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 31 Aug 2020 13:29:11 +0200 Subject: [PATCH] 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 --- include/osmocom/mgcp/mgcp.h | 3 +- include/osmocom/mgcp/mgcp_endp.h | 4 +- include/osmocom/mgcp/mgcp_network.h | 11 +- include/osmocom/mgcp/osmux.h | 3 +- src/libosmo-mgcp/mgcp_conn.c | 3 +- src/libosmo-mgcp/mgcp_network.c | 212 +++++++++++++++++++--------- src/libosmo-mgcp/mgcp_osmux.c | 31 ++-- src/libosmo-mgcp/mgcp_protocol.c | 2 +- src/libosmo-mgcp/mgcp_sdp.c | 60 ++++++-- src/libosmo-mgcp/mgcp_vty.c | 55 ++++++-- src/osmo-mgw/mgw_main.c | 6 +- tests/mgcp/mgcp_test.c | 8 +- 12 files changed, 281 insertions(+), 117 deletions(-) diff --git a/include/osmocom/mgcp/mgcp.h b/include/osmocom/mgcp/mgcp.h index 33bfe716c..75e531bec 100644 --- a/include/osmocom/mgcp/mgcp.h +++ b/include/osmocom/mgcp/mgcp.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include #include @@ -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); diff --git a/include/osmocom/mgcp/mgcp_endp.h b/include/osmocom/mgcp/mgcp_endp.h index 065494f95..14cae25f7 100644 --- a/include/osmocom/mgcp/mgcp_endp.h +++ b/include/osmocom/mgcp/mgcp_endp.h @@ -26,7 +26,7 @@ #include #include -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) diff --git a/include/osmocom/mgcp/mgcp_network.h b/include/osmocom/mgcp/mgcp_network.h index c4967eb97..967444508 100644 --- a/include/osmocom/mgcp/mgcp_network.h +++ b/include/osmocom/mgcp/mgcp_network.h @@ -2,6 +2,9 @@ #include #include + +#include + #include #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); diff --git a/include/osmocom/mgcp/osmux.h b/include/osmocom/mgcp/osmux.h index 69ba3d043..99b44d1a9 100644 --- a/include/osmocom/mgcp/osmux.h +++ b/include/osmocom/mgcp/osmux.h @@ -1,5 +1,6 @@ #pragma once +#include #include 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); diff --git a/src/libosmo-mgcp/mgcp_conn.c b/src/libosmo-mgcp/mgcp_conn.c index d52fa64a0..328e5807c 100644 --- a/src/libosmo-mgcp/mgcp_conn.c +++ b/src/libosmo-mgcp/mgcp_conn.c @@ -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; diff --git a/src/libosmo-mgcp/mgcp_network.c b/src/libosmo-mgcp/mgcp_network.c index 712c706ed..6ecb945b9 100644 --- a/src/libosmo-mgcp/mgcp_network.c +++ b/src/libosmo-mgcp/mgcp_network.c @@ -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; diff --git a/src/libosmo-mgcp/mgcp_osmux.c b/src/libosmo-mgcp/mgcp_osmux.c index 93c922d4a..5864c95f6 100644 --- a/src/libosmo-mgcp/mgcp_osmux.c +++ b/src/libosmo-mgcp/mgcp_osmux.c @@ -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); diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c index 9ec4aeed2..12695247c 100644 --- a/src/libosmo-mgcp/mgcp_protocol.c +++ b/src/libosmo-mgcp/mgcp_protocol.c @@ -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) diff --git a/src/libosmo-mgcp/mgcp_sdp.c b/src/libosmo-mgcp/mgcp_sdp.c index 1c3c89afe..e98ca9430 100644 --- a/src/libosmo-mgcp/mgcp_sdp.c +++ b/src/libosmo-mgcp/mgcp_sdp.c @@ -21,6 +21,9 @@ */ #include +#include +#include + #include #include #include @@ -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; diff --git a/src/libosmo-mgcp/mgcp_vty.c b/src/libosmo-mgcp/mgcp_vty.c index 22863c708..8ea1cddb3 100644 --- a/src/libosmo-mgcp/mgcp_vty.c +++ b/src/libosmo-mgcp/mgcp_vty.c @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -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; diff --git a/src/osmo-mgw/mgw_main.c b/src/osmo-mgw/mgw_main.c index 7f4df2e2f..37357a0fd 100644 --- a/src/osmo-mgw/mgw_main.c +++ b/src/osmo-mgw/mgw_main.c @@ -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) { diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c index c5b6d17b6..620b0d141 100644 --- a/tests/mgcp/mgcp_test.c +++ b/tests/mgcp/mgcp_test.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -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 */