10000 dhcpd::get_macaddress: make use of ifreq to pass data through · Andy-Python-Programmer/dhcpd@d9f9481 · GitHub
[go: up one dir, main page]

Skip to content

Commit d9f9481

Browse files
dhcpd::get_macaddress: make use of ifreq to pass data through
Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
1 parent 264852d commit d9f9481

File tree

1 file changed

+79
-26
lines changed

1 file changed

+79
-26
lines changed

src/main.rs

Lines changed: 79 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ impl Ipv4Addr {
2727
}
2828
}
2929

30+
impl From<libc::in_addr> for Ipv4Addr {
31+
fn from(value: libc::in_addr) -> Self {
32+
Self(value.s_addr.to_be_bytes())
33+
}
34+
}
35+
3036
impl Display for Ipv4Addr {
3137
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3238
f.write_str(&format!(
@@ -368,47 +374,94 @@ fn get_macaddress<'a>() -> &'a [u8; 6] {
368374
.try_call_once(|| unsafe {
369375
let fd = cvt(libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0))?;
370376

371-
let mut buffer = [0u8; 6];
372-
cvt(libc::ioctl(fd, libc::SIOCGIFHWADDR, buffer.as_mut_ptr()))?;
377+
let macaddr = IfReq::new(DEFAULT_NIC);
378+
cvt(libc::ioctl(fd, libc::SIOCGIFHWADDR, &macaddr))?;
373379

374-
Ok::<[u8; 6], io::Error>(buffer)
380+
Ok::<[u8; 6], io::Error>(macaddr.macaddr())
375381
})
376382
// FIXME: Should we panic here?
377383
.expect("[ DHCPD ] (EE) failed to retrieve the mac address")
378384
}
379385

380-
fn configure(interface: &str, ip: Ipv4Addr) -> io::Result<()> {
381-
let fd = cvt(unsafe { libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0) })?;
382-
let socket = libc::sockaddr_in {
383-
sin_family: libc::AF_INET as _,
384-
sin_addr: libc::in_addr {
385-
s_addr: ip.as_u32(),
386-
},
386+
struct SockAddrIn(libc::sockaddr_in);
387387

388-
sin_port: 0,
389-
sin_zero: [0; 8],
390-
};
388+
impl SockAddrIn {
389+
pub fn new(addr: Ipv4Addr) -> Self {
390+
let sin_addr = libc::in_addr {
391+
s_addr: addr.as_u32(),
392+
};
391393

392-
let mut ifr: libc::ifreq = unsafe { core::mem::zeroed() };
393-
assert!(interface.len() <= libc::IFNAMSIZ);
394+
Self(libc::sockaddr_in {
395+
sin_family: libc::AF_INET as _,
396+
sin_addr,
394397

395-
// SAFETY: We have verified above that the name will fit
396-
// in the buffer.
397-
unsafe {
398-
core::ptr::copy_nonoverlapping(
399-
interface.as_ptr(),
400-
ifr.ifr_name.as_mut_ptr() as *mut u8,
401-
interface.len(),
402-
);
398+
..unsafe { core::mem::zeroed() }
399+
})
403400
}
401+
}
404402

405-
ifr.ifr_ifru.ifru_addr = unsafe { *(&socket as *const _ as *const libc::sockaddr) };
403+
impl Into<libc::sockaddr> for SockAddrIn {
404+
fn into(self) -> libc::sockaddr {
405+
unsafe { core::mem::transmute_copy(&self.0) }
406+
}
407+
}
408+
409+
struct IfReq(libc::ifreq);
410+
411+
impl IfReq {
412+
pub fn new(interface: &str) -> Self {
413+
let mut ifr: libc::ifreq = unsafe { core::mem::zeroed() };
414+
assert!(interface.len() <= libc::IFNAMSIZ);
415+
416+
// SAFETY: We have verified above that the name will fit
417+
// in the buffer.
418+
unsafe {
419+
core::ptr::copy_nonoverlapping(
420+
interface.as_ptr(),
421+
ifr.ifr_name.as_mut_ptr() as *mut u8,
422+
interface.len(),
423+
);
424+
}
425+
426+
Self(ifr)
427+
}
428+
429+
fn set_addr(mut self, ip: Ipv4Addr) -> libc::ifreq {
430+
self.0.ifr_ifru.ifru_addr = SockAddrIn::new(ip).into();
431+
self.0
432+
}
433+
434+
unsafe fn macaddr(&self) -> [u8; 6] {
435+
let data: &[i8; 6] = &self.0.ifr_ifru.ifru_hwaddr.sa_data[..6]
436+
.try_into()
437+
.expect("macaddr: address validation failed");
438+
439+
let data: [i8; 6] = data.clone();
440+
441+
// SAFETY: The caller guarantees that union field we are accessing
442+
// has been initialized with a mac address. With all of that,
443+
// transmuting the data array into [u8; 6] is safe.
444+
core::mem::transmute(data)
445+
}
446+
}
447+
448+
fn configure(interface: &str, ip: Ipv4Addr, subnet_mask: Ipv4Addr) -> io::Result<()> {
449+
let fd = cvt(unsafe { libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0) })?;
450+
451+
let interface_addr = IfReq::new(interface).set_addr(ip);
406452

407453
// Set the interface address.
408454
unsafe {
409-
cvt(libc::ioctl(fd, libc::SIOCSIFADDR, &ifr))?;
455+
cvt(libc::ioctl(fd, libc::SIOCSIFADDR, &interface_addr))?;
410456
}
411457

458+
let subnet_mask = IfReq::new(interface).set_addr(subnet_mask);
459+
460+
// Set the subnet mask.
461+
// unsafe {
462+
// cvt(libc::ioctl(fd, libc::SIOCSIFNETMASK, &subnet_mask))?;
463+
// }
464+
412465
Ok(())
413466
}
414467

@@ -466,7 +519,7 @@ pub fn main() -> Result<(), Box<dyn Error>> {
466519
let subnet_mask = subnet_mask.unwrap();
467520
let dns = dns.unwrap();
468521

469-
configure(DEFAULT_NIC, ack.your_ip)?;
522+
configure(DEFAULT_NIC, ack.your_ip, subnet_mask)?;
470523

471524
println!("[ DHCPD ] (!!) Configured:");
472525
println!("[ DHCPD ] (!!) IP: {}", ack.your_ip);

0 commit comments

Comments
 (0)
0