diff --git a/tun/src/unix/linux/mod.rs b/tun/src/unix/linux/mod.rs index 82a2125..7167a32 100644 --- a/tun/src/unix/linux/mod.rs +++ b/tun/src/unix/linux/mod.rs @@ -75,6 +75,16 @@ impl TunInterface { self.perform(|fd| unsafe { sys::if_set_mtu(fd, &iff) })?; } + #[throws] + pub fn set_netmask(&self, addr: Ipv4Addr) { + let addr = SockAddr::from(SocketAddrV4::new(addr, 0)); + + let mut iff = self.ifreq()?; + iff.ifr_ifru.ifru_netmask = unsafe { *addr.as_ptr() }; + + self.perform(|fd| unsafe { sys::if_set_netmask(fd, &iff) })?; + } + #[throws] pub fn ipv4_addr(&self) -> Ipv4Addr { let mut iff = self.ifreq()?; @@ -92,6 +102,17 @@ impl TunInterface { mtu } + #[throws] + pub fn netmask(&self) -> Ipv4Addr { + let mut iff = self.ifreq()?; + self.perform(|fd| unsafe { sys::if_get_netmask(fd, &mut iff) })?; + + let netmask = + unsafe { *(&iff.ifr_ifru.ifru_netmask as *const _ as *const sys::sockaddr_in) }; + + Ipv4Addr::from(u32::from_be(netmask.sin_addr.s_addr)) + } + #[throws] fn perform(&self, perform: impl FnOnce(RawFd) -> Result) -> R { let socket = Socket::new(Domain::IPV4, Type::DGRAM, None)?; @@ -101,6 +122,7 @@ impl TunInterface { mod test { use super::TunInterface; + use std::net::Ipv4Addr; #[test] fn mtu() { @@ -110,4 +132,15 @@ mod test { assert_eq!(interf.mtu().unwrap(), 500); } + + #[test] + fn netmask() { + let interf = TunInterface::new().unwrap(); + + let addr = Ipv4Addr::new(255, 0, 0, 0); + + interf.set_netmask(addr); + + assert_eq!(interf.netmask().unwrap(), addr); + } } diff --git a/tun/src/unix/linux/sys.rs b/tun/src/unix/linux/sys.rs index e8e373f..8bac12d 100644 --- a/tun/src/unix/linux/sys.rs +++ b/tun/src/unix/linux/sys.rs @@ -2,6 +2,7 @@ use nix::{ioctl_read_bad, ioctl_write_ptr_bad, request_code_read, request_code_w use std::mem::size_of; pub use libc::ifreq; +pub use libc::sockaddr; pub use libc::sockaddr_in; ioctl_write_ptr_bad!( @@ -17,6 +18,8 @@ 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_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_mtu, libc::SIOCSIFMTU, libc::ifreq); +ioctl_write_ptr_bad!(if_set_netmask, libc::SIOCSIFNETMASK, libc::ifreq);