Skip to content

Commit 3fac89f

Browse files
committed
Added Socket::set_multicast_if_v4_n to set interface by index (#458)
1 parent f083696 commit 3fac89f

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
@@ -805,7 +805,6 @@ fn set_common_flags(socket: Socket) -> io::Result<Socket> {
805805
#[cfg(not(any(
806806
target_os = "haiku",
807807
target_os = "illumos",
808-
target_os = "netbsd",
809808
target_os = "redox",
810809
target_os = "solaris",
811810
)))]
@@ -1480,6 +1479,54 @@ impl Socket {
14801479
}
14811480
}
14821481

1482+
/// Set the value of the `IP_MULTICAST_IF` option for this socket.
1483+
///
1484+
/// Specifies the interface to use for routing multicast packets.
1485+
/// See [`InterfaceIndexOrAddress`].
1486+
#[cfg(all(
1487+
feature = "all",
1488+
any(
1489+
target_os = "freebsd",
1490+
target_os = "netbsd",
1491+
target_os = "linux",
1492+
target_os = "android",
1493+
target_os = "fuchsia",
1494+
)
1495+
))]
1496+
pub fn set_multicast_if_v4_n(&self, interface: &InterfaceIndexOrAddress) -> io::Result<()> {
1497+
#[cfg(any(
1498+
target_os = "freebsd",
1499+
target_os = "linux",
1500+
target_os = "android",
1501+
target_os = "fuchsia"
1502+
))]
1503+
{
1504+
// IP_MULTICAST_IF supports struct mreqn to set the interface
1505+
let mreqn = sys::to_mreqn(&Ipv4Addr::UNSPECIFIED, interface);
1506+
unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF, mreqn) }
1507+
}
1508+
1509+
#[cfg(target_os = "netbsd")]
1510+
{
1511+
// IP_MULTICAST_IF only supports struct in_addr to set the interface, but passing an
1512+
// address in the 0.0.0.0/8 range is interpreted as an interface index (in network
1513+
// byte order)
1514+
let addr = match interface {
1515+
InterfaceIndexOrAddress::Index(index) => {
1516+
if *index >= 0x0100_0000 {
1517+
return Err(io::Error::new(
1518+
io::ErrorKind::AddrNotAvailable,
1519+
"Interface index out of bounds",
1520+
));
1521+
}
1522+
Ipv4Addr::from_bits(*index)
1523+
}
1524+
InterfaceIndexOrAddress::Address(a) => *a,
1525+
};
1526+
unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF, addr) }
1527+
}
1528+
}
1529+
14831530
/// Get the value of the `IP_MULTICAST_LOOP` option for this socket.
14841531
///
14851532
/// For more information about this option, see [`set_multicast_loop_v4`].

0 commit comments

Comments
 (0)