From 93e1ba1e2b9852376cce8bf4b03f260598d5ca6c Mon Sep 17 00:00:00 2001 From: ache Date: Thu, 29 Aug 2019 02:13:14 +0200 Subject: Detect DHCP Message Type --- src/main.rs | 104 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 28 deletions(-) diff --git a/src/main.rs b/src/main.rs index f514adf..712b2d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,19 +2,22 @@ use std::net::UdpSocket; use std::net; use std::str; use std::fmt; +use std::mem; const BUFFER_SIZE: usize = 5000; const SERVER_PORT: u16 = 67; -enum DHCP_MESSAGE_TYPE { - DHCPDISCOVER = 1, - DHCPOFFER = 2, - DHCPREQUEST = 3, - DHCPDECLINE, - DHCPPACK, - DHCPNAK, - DHCPRELEASE, - DHCPINFORM +const IP_SERVER: net::Ipv4Addr = net::Ipv4Addr::new(10, 2, 0, 11); + +enum DhcpMessageType { + DHCPDISCOVER = 1, // Send by client + DHCPOFFER = 2, // Send by server + DHCPREQUEST = 3, // Send by client + DHCPDECLINE, // Send by client + DHCPPACK, // Send by server + DHCPNAK, // Send by server + DHCPRELEASE, // Send by client + DHCPINFORM // Not send } const OPTIONS_NAME : [&str;77] = ["Pad", // 0 @@ -113,6 +116,31 @@ struct DhcpMessage { file: [u8; 128], options: [u8; 312] } +impl DhcpMessage { + fn request_type( &self ) -> Option { + let mut i = 4; // Magic cookie ! 🍪 + loop { + if i >= 312 { + return None; + } + let i_tmp : usize = usize::from(i); + if self.options[i_tmp] == 53 { + if self.options[i_tmp+2] > 0 && self.options[i_tmp+2] < 9 { + print!("Type: {}\n", self.options[i_tmp+2]); + return Some(unsafe { mem::transmute(self.options[i_tmp+2]) }); + } else { + return None + } + } else if self.options[i_tmp] == 0 || self.options[i_tmp] == 255 { + i += 1 + } else if self.options[i_tmp] < 77 { + i += u16::from(self.options[i_tmp+1]); + } else { + return None; + } + } + } +} impl fmt::Display for DhcpMessage { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -150,25 +178,39 @@ impl fmt::Display for DhcpMessage { self.siaddr, self.giaddr, self.chaddr[0], self.chaddr[1], self.chaddr[2], self.chaddr[3], self.chaddr[4], self.chaddr[5], name, - if is_file_empty { "empty" } else {"not empty"}); - write!(f, "options :\n"); + if is_file_empty { "empty" } else {"not empty"})?; + write!(f, "options :\n(\n")?; let mut i: u16 = 0; + { // Check for Magic Cookie 🍪 + let i_tmp : usize = usize::from(i); + if self.options[i_tmp] == 0x63 && + self.options[i_tmp+1] == 0x82 && + self.options[i_tmp+2] == 0x53 && + self.options[i_tmp+3] == 0x63 { + write!(f, " MAGIC COOKIE 0x63825363\n")?; + i += 4 + } + } loop { if i >= 312 { break; } - let I : usize = usize::from(i); - if self.options[I] == 0xFF { - write!(f, " End Option(0xFF)"); + let i_tmp : usize = usize::from(i); + if self.options[i_tmp] == 0xFF { + write!(f, " End Option(0xFF)\n")?; break; - } else if self.options[I] == 0 { - write!(f, " Pad Option(0x00)"); - i += 1; - } else if self.options[I] < 77 { - write!(f, " {} Option({:02x})\n", OPTIONS_NAME[usize::from(self.options[I])], self.options[I]); - i += u16::from(self.options[I+1]); + } else if self.options[i_tmp] == 0 { + let mut times: u16= 1; + while i_tmp + usize::from(times) < 312 && self.options[i_tmp+usize::from(times)] == 0 { + times += 1; + } + write!(f, " Pad Option(0x00) x{}\n", times)?; + i += times; + } else if self.options[i_tmp] < 77 { + write!(f, " {} Option({:02x})\n", OPTIONS_NAME[usize::from(self.options[i_tmp])], self.options[i_tmp])?; + i += u16::from(self.options[i_tmp+1]); } else { - write!(f, " Unknow Option({:02x})", self.options[I]); + write!(f, " Unknow Option({:02x})\n", self.options[i_tmp])?; break; } } @@ -210,22 +252,22 @@ fn fill_dhcp_message( dhcp_message: &mut DhcpMessage, buf : &[u8; BUFFER_SIZE], dhcp_message.siaddr = u32::from_be_bytes([buf[20], buf[21], buf[22], buf[23]]); dhcp_message.giaddr = u32::from_be_bytes([buf[24], buf[25], buf[26], buf[27]]); dhcp_message.chaddr = [buf[28], buf[29], buf[30], buf[31], buf[32], buf[33]]; + for i in 0..64 { - dhcp_message.sname[i] = buf[i+34] + dhcp_message.sname[i] = buf[i+34]; } for i in 0..128 { - dhcp_message.file[i] = buf[i+98] + dhcp_message.file[i] = buf[i+98]; } - let size = if size > 226 + 538 { 538 } else { size }; - for i in 226..size { - dhcp_message.options[i-226] = buf[i+98] + let size = if size > 538 { 538 } else { size }; + for i in 236..size { + dhcp_message.options[i-236] = buf[i]; } - - true } + fn main() -> std::io::Result<()> { { let addrs = [ @@ -234,6 +276,7 @@ fn main() -> std::io::Result<()> { let socket = UdpSocket::bind(&addrs[..])?; loop { + print!("Ready to listen ! 🦊\n"); // Receives a single datagram message on the socket. If `buf` is too small to hold // the message, it will be cut off. let mut buf = [0; BUFFER_SIZE]; @@ -252,6 +295,11 @@ fn main() -> std::io::Result<()> { if dhcp_message.xid == 42 { break } + if let Some(DhcpMessageType::DHCPDISCOVER) = dhcp_message.request_type() { + print!("It's a discovery !\n"); + } else { + print!("It's not a discovery !\n"); + } } } // the socket is closed here Ok(()) -- cgit v1.2.3