Skip to content

Commit 77eb5c7

Browse files
committed
Added Socket::set_multicast_if_v4_n to set interface by index (#458)
1 parent 758a9e2 commit 77eb5c7

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ pub use sockaddr::{sa_family_t, socklen_t, SockAddr, SockAddrStorage};
189189
#[cfg(not(any(
190190
target_os = "haiku",
191191
target_os = "illumos",
192-
target_os = "netbsd",
193192
target_os = "redox",
194193
target_os = "solaris",
195194
)))]

src/socket.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,6 @@ fn set_common_flags(socket: Socket) -> io::Result<Socket> {
821821
#[cfg(not(any(
822822
target_os = "haiku",
823823
target_os = "illumos",
824-
target_os = "netbsd",
825824
target_os = "redox",
826825
target_os = "solaris",
827826
)))]
@@ -1461,6 +1460,54 @@ impl Socket {
14611460
}
14621461
}
14631462

1463+
/// Set the value of the `IP_MULTICAST_IF` option for this socket.
1464+
///
1465+
/// Specifies the interface to use for routing multicast packets.
1466+
/// See [`InterfaceIndexOrAddress`].
1467+
#[cfg(all(
1468+
feature = "all",
1469+
any(
1470+
target_os = "freebsd",
1471+
target_os = "netbsd",
1472+
target_os = "linux",
1473+
target_os = "android",
1474+
target_os = "fuchsia",
1475+
)
1476+
))]
1477+
pub fn set_multicast_if_v4_n(&self, interface: &InterfaceIndexOrAddress) -> io::Result<()> {
1478+
#[cfg(any(
1479+
target_os = "freebsd",
1480+
target_os = "linux",
1481+
target_os = "android",
1482+
target_os = "fuchsia"
1483+
))]
1484+
{
1485+
// IP_MULTICAST_IF supports struct mreqn to set the interface
1486+
let mreqn = sys::to_mreqn(&Ipv4Addr::UNSPECIFIED, interface);
1487+
unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF, mreqn) }
1488+
}
1489+
1490+
#[cfg(target_os = "netbsd")]
1491+
{
1492+
// IP_MULTICAST_IF only supports struct in_addr to set the interface, but passing an
1493+
// address in the 0.0.0.0/8 range is interpreted as an interface index (in network
1494+
// byte order)
1495+
let addr = match interface {
1496+
InterfaceIndexOrAddress::Index(index) => {
1497+
if *index >= 0x0100_0000 {
1498+
return Err(io::Error::new(
1499+
io::ErrorKind::AddrNotAvailable,
1500+
"Interface index out of bounds",
1501+
));
1502+
}
1503+
Ipv4Addr::from_bits(*index)
1504+
}
1505+
InterfaceIndexOrAddress::Address(a) => *a,
1506+
};
1507+
unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF, addr) }
1508+
}
1509+
}
1510+
14641511
/// Get the value of the `IP_MULTICAST_LOOP` option for this socket.
14651512
///
14661513
/// For more information about this option, see [`set_multicast_loop_v4`].

0 commit comments

Comments
 (0)