diff --git a/src/lib.rs b/src/lib.rs index a0a56a52..85ed9adb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -189,7 +189,6 @@ pub use sockaddr::{sa_family_t, socklen_t, SockAddr, SockAddrStorage}; #[cfg(not(any( target_os = "haiku", target_os = "illumos", - target_os = "netbsd", target_os = "redox", target_os = "solaris", )))] diff --git a/src/socket.rs b/src/socket.rs index 1fc6f080..8b86beb0 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -821,7 +821,6 @@ fn set_common_flags(socket: Socket) -> io::Result { #[cfg(not(any( target_os = "haiku", target_os = "illumos", - target_os = "netbsd", target_os = "redox", target_os = "solaris", )))] @@ -1496,6 +1495,54 @@ impl Socket { } } + /// Set the value of the `IP_MULTICAST_IF` option for this socket. + /// + /// Specifies the interface to use for routing multicast packets. + /// See [`InterfaceIndexOrAddress`]. + #[cfg(all( + feature = "all", + any( + target_os = "freebsd", + target_os = "netbsd", + target_os = "linux", + target_os = "android", + target_os = "fuchsia", + ) + ))] + pub fn set_multicast_if_v4_n(&self, interface: &InterfaceIndexOrAddress) -> io::Result<()> { + #[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "android", + target_os = "fuchsia" + ))] + { + // IP_MULTICAST_IF supports struct mreqn to set the interface + let mreqn = sys::to_mreqn(&Ipv4Addr::UNSPECIFIED, interface); + unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF, mreqn) } + } + + #[cfg(target_os = "netbsd")] + { + // IP_MULTICAST_IF only supports struct in_addr to set the interface, but passing an + // address in the 0.0.0.0/8 range is interpreted as an interface index (in network + // byte order) + let addr = match interface { + InterfaceIndexOrAddress::Index(index) => { + if *index >= 0x0100_0000 { + return Err(io::Error::new( + io::ErrorKind::AddrNotAvailable, + "Interface index out of bounds", + )); + } + Ipv4Addr::from_bits(*index) + } + InterfaceIndexOrAddress::Address(a) => *a, + }; + unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF, addr) } + } + } + /// Get the value of the `IP_MULTICAST_LOOP` option for this socket. /// /// For more information about this option, see [`set_multicast_loop_v4`].