Skip to content

Commit 159c832

Browse files
committed
Added Socket::set_multicast_if_v4_n to set interface by index (#458)
1 parent 0c9efe1 commit 159c832

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
)))]
@@ -1496,6 +1495,54 @@ impl Socket {
14961495
}
14971496
}
14981497

1498+
/// Set the value of the `IP_MULTICAST_IF` option for this socket.
1499+
///
1500+
/// Specifies the interface to use for routing multicast packets.
1501+
/// See [`InterfaceIndexOrAddress`].
1502+
#[cfg(all(
1503+
feature = "all",
1504+
any(
1505+
target_os = "freebsd",
1506+
target_os = "netbsd",
1507+
target_os = "linux",
1508+
target_os = "android",
1509+
target_os = "fuchsia",
1510+
)
1511+
))]
1512+
pub fn set_multicast_if_v4_n(&self, interface: &InterfaceIndexOrAddress) -> io::Result<()> {
1513+
#[cfg(any(
1514+
target_os = "freebsd",
1515+
target_os = "linux",
1516+
target_os = "android",
1517+
target_os = "fuchsia"
1518+
))]
1519+
{
1520+
// IP_MULTICAST_IF supports struct mreqn to set the interface
1521+
let mreqn = sys::to_mreqn(&Ipv4Addr::UNSPECIFIED, interface);
1522+
unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF, mreqn) }
1523+
}
1524+
1525+
#[cfg(target_os = "netbsd")]
1526+
{
1527+
// IP_MULTICAST_IF only supports struct in_addr to set the interface, but passing an
1528+
// address in the 0.0.0.0/8 range is interpreted as an interface index (in network
1529+
// byte order)
1530+
let addr = match interface {
1531+
InterfaceIndexOrAddress::Index(index) => {
1532+
if *index >= 0x0100_0000 {
1533+
return Err(io::Error::new(
1534+
io::ErrorKind::AddrNotAvailable,
1535+
"Interface index out of bounds",
1536+
));
1537+
}
1538+
Ipv4Addr::from_bits(*index)
1539+
}
1540+
InterfaceIndexOrAddress::Address(a) => *a,
1541+
};
1542+
unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF, addr) }
1543+
}
1544+
}
1545+
14991546
/// Get the value of the `IP_MULTICAST_LOOP` option for this socket.
15001547
///
15011548
/// For more information about this option, see [`set_multicast_loop_v4`].

0 commit comments

Comments
 (0)