Skip to content

Commit e88ad54

Browse files
committed
net_udp: enforce v4 sock only for mac+mcast+iface
No longer enforce v4 socket for dot-decimal IPv4 mcast addresses unless macOS used with mcast4 addr and interface set. The default behavior now is to use dual-home v6 socket (with v4-mapped addresses). macOS treates the v4 mcast addresses transparently as v6 addresses (using v6 sockopts). But interface specification doesn't currently seem to work in macOS, neither for native v6 mcast addresses so enforce v4 sockets here.
1 parent d1023bd commit e88ad54

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

src/rtp/net_udp.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,30 @@ static bool set_sock_opts_and_bind(fd_t fd, bool ipv6, uint16_t rx_port, int ttl
881881
return true;
882882
}
883883

884+
/**
885+
* - checks force_ip_version validity
886+
* - for macOS with ipv4 mcast addr and iface set, return 4 if 0 requested
887+
* - otherwise return force_ip_version param
888+
*/
889+
static int
890+
adjust_ip_version(int force_ip_version, const char *addr, const char *iface)
891+
{
892+
assert(force_ip_version == 0 || force_ip_version == 4 ||
893+
force_ip_version == 6);
894+
#ifdef __APPLE__
895+
if (force_ip_version == 0 && iface != NULL && is_addr4(addr) &&
896+
is_addr_multicast(addr)) {
897+
MSG(INFO, "enforcing IPv4 mode on macOS for v4 mcast address "
898+
"and iface set\n");
899+
return IPv4;
900+
}
901+
return force_ip_version;
902+
#else
903+
(void) addr, (void) iface;
904+
return force_ip_version;
905+
#endif
906+
}
907+
884908
static unsigned
885909
get_ifindex(const char *iface)
886910
{
@@ -960,11 +984,7 @@ socket_udp *udp_init_if(const char *addr, const char *iface, uint16_t rx_port,
960984
pthread_cond_init(&s->local->boss_cv, NULL);
961985
pthread_cond_init(&s->local->reader_cv, NULL);
962986

963-
assert(force_ip_version == 0 || force_ip_version == 4 || force_ip_version == 6);
964-
s->local->mode = force_ip_version;
965-
if (s->local->mode == 0 && is_addr_multicast(addr)) {
966-
s->local->mode = strchr(addr, '.') != NULL ? 4 : 6;
967-
}
987+
s->local->mode = adjust_ip_version(force_ip_version, addr, iface);
968988

969989
if ((ret = resolve_address(s, addr, tx_port)) != 0) {
970990
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Can't resolve IP address for %s: %s\n", addr,

src/utils/net.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,9 @@ bool get_local_addresses(struct sockaddr_storage *addrs, size_t *len, int ip_ver
355355
/**
356356
* Checks if the address is a dot-separated numeric IPv4 address.
357357
*/
358-
static bool is_addr4(const char *addr) {
358+
bool
359+
is_addr4(const char *addr)
360+
{
359361
// only basic check
360362
while (*addr != '\0') {
361363
if (!isdigit(*addr) && *addr != '.') {
@@ -370,7 +372,9 @@ static bool is_addr4(const char *addr) {
370372
* Checks if the address is a colon-separated numeric IPv6 address
371373
* (with optional zone index).
372374
*/
373-
static bool is_addr6(const char *addr) {
375+
bool
376+
is_addr6(const char *addr)
377+
{
374378
while (*addr != '\0') {
375379
if (*addr == '%') { // skip zone identification at the end
376380
return true;

src/utils/net.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ extern "C" {
7979

8080
struct sockaddr;
8181
struct sockaddr_storage;
82+
bool is_addr4(const char *addr);
83+
bool is_addr6(const char *addr);
8284
bool is_addr_linklocal(struct sockaddr *sa);
8385
bool is_addr_loopback(struct sockaddr *sa);
8486
bool is_addr_private(struct sockaddr *sa);

0 commit comments

Comments
 (0)