$NetBSD: patch-src_3rdparty_chromium_net_socket_udp__socket__posix.cc,v 1.2 2022/04/18 11:18:19 adam Exp $ --- src/3rdparty/chromium/net/socket/udp_socket_posix.cc.orig 2021-02-19 16:41:59.000000000 +0000 +++ src/3rdparty/chromium/net/socket/udp_socket_posix.cc @@ -51,7 +51,7 @@ #include "base/strings/utf_string_conversions.h" #endif // defined(OS_ANDROID) -#if defined(OS_MAC) +#if defined(OS_MAC) || defined(OS_BSD) // This was needed to debug crbug.com/640281. // TODO(zhongyi): Remove once the bug is resolved. #include @@ -70,7 +70,38 @@ const int kActivityMonitorMinimumSamples const base::TimeDelta kActivityMonitorMsThreshold = base::TimeDelta::FromMilliseconds(100); -#if defined(OS_MAC) +#if defined(OS_BSD) +// When enabling multicast using setsockopt(IP_MULTICAST_IF) MacOS +// requires passing IPv4 address instead of interface index. This function +// resolves IPv4 address by interface index. The |address| is returned in +// network order. +int GetIPv4AddressFromIndex(int socket, uint32_t index, uint32_t* address) { + if (!index) { + *address = htonl(INADDR_ANY); + return OK; + } + + sockaddr_in* result = nullptr; + + ifreq ifr; + ifr.ifr_addr.sa_family = AF_INET; + if (!if_indextoname(index, ifr.ifr_name)) + return MapSystemError(errno); + int rv = ioctl(socket, SIOCGIFADDR, &ifr); + if (rv == -1) + return MapSystemError(errno); + result = reinterpret_cast(&ifr.ifr_addr); + + if (!result) + return ERR_ADDRESS_INVALID; + + *address = result->sin_addr.s_addr; + return OK; +} + +#endif // OS_BSD + +#if defined(OS_MAC) || defined(OS_BSD) // On OSX the file descriptor is guarded to detect the cause of // crbug.com/640281. guarded API is supported only on newer versions of OSX, @@ -622,7 +653,7 @@ int UDPSocketPosix::SetDoNotFragment() { } void UDPSocketPosix::SetMsgConfirm(bool confirm) { -#if !defined(OS_APPLE) +#if !defined(OS_APPLE) && !defined(OS_BSD) if (confirm) { sendto_flags_ |= MSG_CONFIRM; } else { @@ -643,13 +674,16 @@ int UDPSocketPosix::SetBroadcast(bool br DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); int value = broadcast ? 1 : 0; int rv; -#if defined(OS_APPLE) +#if defined(OS_APPLE) || defined(OS_BSD) // SO_REUSEPORT on OSX permits multiple processes to each receive // UDP multicast or broadcast datagrams destined for the bound // port. // This is only being set on OSX because its behavior is platform dependent // and we are playing it safe by only setting it on platforms where things // break. + rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); + if (rv != 0) + return MapSystemError(errno); rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)); if (rv != 0) return MapSystemError(errno); @@ -913,11 +947,23 @@ int UDPSocketPosix::SetMulticastOptions( if (multicast_interface_ != 0) { switch (addr_family_) { case AF_INET: { +#if defined(OS_BSD) + ip_mreq mreq = {}; + int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, + &mreq.imr_interface.s_addr); + if (error != OK) + return error; +#else ip_mreqn mreq = {}; mreq.imr_ifindex = multicast_interface_; mreq.imr_address.s_addr = htonl(INADDR_ANY); +#endif int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, +#if defined(OS_BSD) + reinterpret_cast(&mreq.imr_interface.s_addr), sizeof(mreq.imr_interface.s_addr)); +#else reinterpret_cast(&mreq), sizeof(mreq)); +#endif if (rv) return MapSystemError(errno); break; @@ -978,9 +1024,17 @@ int UDPSocketPosix::JoinGroup(const IPAd case IPAddress::kIPv4AddressSize: { if (addr_family_ != AF_INET) return ERR_ADDRESS_INVALID; +#if defined(OS_BSD) + ip_mreq mreq = {}; + int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, + &mreq.imr_interface.s_addr); + if (error != OK) + return error; +#else ip_mreqn mreq = {}; mreq.imr_ifindex = multicast_interface_; mreq.imr_address.s_addr = htonl(INADDR_ANY); +#endif memcpy(&mreq.imr_multiaddr, group_address.bytes().data(), IPAddress::kIPv4AddressSize); int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, @@ -1018,9 +1072,18 @@ int UDPSocketPosix::LeaveGroup(const IPA case IPAddress::kIPv4AddressSize: { if (addr_family_ != AF_INET) return ERR_ADDRESS_INVALID; +#if defined(OS_BSD) + ip_mreq mreq = {}; + int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, + &mreq.imr_interface.s_addr); + + if (error != OK) + return error; +#else ip_mreqn mreq = {}; mreq.imr_ifindex = multicast_interface_; mreq.imr_address.s_addr = INADDR_ANY; +#endif memcpy(&mreq.imr_multiaddr, group_address.bytes().data(), IPAddress::kIPv4AddressSize); int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,