diff --git a/tun/src/unix/linux/mod.rs b/tun/src/unix/linux/mod.rs index 7b8b05d..2b3d3a7 100644 --- a/tun/src/unix/linux/mod.rs +++ b/tun/src/unix/linux/mod.rs @@ -103,6 +103,28 @@ impl TunInterface { Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr)) } + #[throws] + pub fn set_broadcast_addr(&self, addr: Ipv4Addr) { + let addr = SockAddr::from(SocketAddrV4::new(addr, 0)); + let mut iff = self.ifreq()?; + iff.ifr_ifru.ifru_broadaddr = unsafe { *addr.as_ptr() }; + self.perform(|fd| unsafe { sys::if_set_brdaddr(fd, &iff) })?; + info!( + "broadcast_addr_set: {:?} (fd: {:?})", + addr, + self.as_raw_fd() + ) + } + + #[throws] + pub fn broadcast_addr(&self) -> Ipv4Addr { + let mut iff = self.ifreq()?; + self.perform(|fd| unsafe { sys::if_get_brdaddr(fd, &mut iff) })?; + let addr = + unsafe { *(&iff.ifr_ifru.ifru_broadaddr as *const _ as *const sys::sockaddr_in) }; + Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr)) + } + #[throws] pub fn set_ipv6_addr(&self, addr: Ipv6Addr) { let mut iff = self.in6_ifreq()?; diff --git a/tun/src/unix/linux/sys.rs b/tun/src/unix/linux/sys.rs index 61dd50e..8d8725b 100644 --- a/tun/src/unix/linux/sys.rs +++ b/tun/src/unix/linux/sys.rs @@ -18,10 +18,12 @@ ioctl_read_bad!( ); ioctl_read_bad!(if_get_index, libc::SIOCGIFINDEX, libc::ifreq); ioctl_read_bad!(if_get_addr, libc::SIOCGIFADDR, libc::ifreq); +ioctl_read_bad!(if_get_brdaddr, libc::SIOCGIFBRDADDR, libc::ifreq); ioctl_read_bad!(if_get_mtu, libc::SIOCGIFMTU, libc::ifreq); ioctl_read_bad!(if_get_netmask, libc::SIOCGIFNETMASK, libc::ifreq); ioctl_write_ptr_bad!(if_set_addr, libc::SIOCSIFADDR, libc::ifreq); ioctl_write_ptr_bad!(if_set_addr6, libc::SIOCSIFADDR, libc::in6_ifreq); +ioctl_write_ptr_bad!(if_set_brdaddr, libc::SIOCSIFBRDADDR, libc::ifreq); ioctl_write_ptr_bad!(if_set_mtu, libc::SIOCSIFMTU, libc::ifreq); ioctl_write_ptr_bad!(if_set_netmask, libc::SIOCSIFNETMASK, libc::ifreq); diff --git a/tun/tests/configure.rs b/tun/tests/configure.rs index 35f9726..0f1199d 100644 --- a/tun/tests/configure.rs +++ b/tun/tests/configure.rs @@ -9,6 +9,21 @@ fn test_create() { TunInterface::new()?; } +#[test] +#[throws] +#[cfg(not(any(target_os = "windows", target_vendor = "apple")))] +fn test_set_get_broadcast_addr() { + let tun = TunInterface::new()?; + let addr = Ipv4Addr::new(10, 0, 0, 1); + tun.set_ipv4_addr(addr)?; + + let broadcast_addr = Ipv4Addr::new(255, 255, 255, 0); + tun.set_broadcast_addr(broadcast_addr)?; + let result = tun.broadcast_addr()?; + + assert_eq!(broadcast_addr, result); +} + #[test] #[throws] #[cfg(not(target_os = "windows"))]