Set/get broadcast address in TunInterface

Modelled after TunInterface's IPV4 logic.
Uses SIOCGIFBRDADDR & SIOCSIFBRDADDR.
View https://man7.org/linux/man-pages/man7/netdevice.7.html.
This commit is contained in:
Sam Poder 2023-07-03 17:29:52 +00:00 committed by Conrad Kramer
parent 22e41203fb
commit c8df4b860d
3 changed files with 39 additions and 0 deletions

View file

@ -103,6 +103,28 @@ impl TunInterface {
Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr)) 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] #[throws]
pub fn set_ipv6_addr(&self, addr: Ipv6Addr) { pub fn set_ipv6_addr(&self, addr: Ipv6Addr) {
let mut iff = self.in6_ifreq()?; let mut iff = self.in6_ifreq()?;

View file

@ -18,10 +18,12 @@ ioctl_read_bad!(
); );
ioctl_read_bad!(if_get_index, libc::SIOCGIFINDEX, libc::ifreq); 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_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_mtu, libc::SIOCGIFMTU, libc::ifreq);
ioctl_read_bad!(if_get_netmask, libc::SIOCGIFNETMASK, 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_addr, libc::SIOCSIFADDR, libc::ifreq);
ioctl_write_ptr_bad!(if_set_addr6, libc::SIOCSIFADDR, libc::in6_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_mtu, libc::SIOCSIFMTU, libc::ifreq);
ioctl_write_ptr_bad!(if_set_netmask, libc::SIOCSIFNETMASK, libc::ifreq); ioctl_write_ptr_bad!(if_set_netmask, libc::SIOCSIFNETMASK, libc::ifreq);

View file

@ -9,6 +9,21 @@ fn test_create() {
TunInterface::new()?; 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] #[test]
#[throws] #[throws]
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]