summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorache <ache@ache.one>2019-09-25 13:46:09 +0200
committerache <ache@ache.one>2019-09-25 13:46:09 +0200
commit554eb2d72fd3b2c5f37fa8462b6a7bd9edb2da5d (patch)
tree0979882570934ac6f49dcb1dfabcfe37166e9d3b
parentDetect DHCP Message Type (diff)
Understand the DHCP requestHEADmaster
-rw-r--r--src/main.rs170
1 files changed, 160 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs
index 712b2d9..eeaaedd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,6 +3,9 @@ use std::net;
use std::str;
use std::fmt;
use std::mem;
+use std::net::Ipv4Addr;
+
+use std::io::ErrorKind;
const BUFFER_SIZE: usize = 5000;
const SERVER_PORT: u16 = 67;
@@ -19,6 +22,37 @@ enum DhcpMessageType {
DHCPRELEASE, // Send by client
DHCPINFORM // Not send
}
+impl fmt::Display for DhcpMessageType {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = match self {
+ DhcpMessageType::DHCPDISCOVER => "DHCPDISCOVER",
+ DhcpMessageType::DHCPOFFER => "DHCPOFFER",
+ DhcpMessageType::DHCPREQUEST => "DHCPREQUEST",
+ DhcpMessageType::DHCPNAK => "DHCPNAK",
+ DhcpMessageType::DHCPDECLINE => "DHCPDECLINE",
+ DhcpMessageType::DHCPPACK => "DHCPPACK",
+ DhcpMessageType::DHCPRELEASE => "DHCPRELEASE",
+ DhcpMessageType::DHCPINFORM => "DHCPINFORM"
+ };
+ write!(f, "{}", s)
+ }
+}
+
+impl DhcpMessageType {
+ fn into( i: u8 ) -> DhcpMessageType {
+ match(i) {
+ 1 => DhcpMessageType::DHCPDISCOVER,
+ 2 => DhcpMessageType::DHCPOFFER,
+ 3 => DhcpMessageType::DHCPREQUEST,
+ _ => DhcpMessageType::DHCPNAK,
+ }
+ }
+}
+
+struct Config {
+ ranges: Vec<(Ipv4Addr, Ipv4Addr)>,
+ name: String,
+}
const OPTIONS_NAME : [&str;77] = ["Pad", // 0
"Subnet mask",
@@ -117,6 +151,27 @@ struct DhcpMessage {
options: [u8; 312]
}
impl DhcpMessage {
+ fn get_option_data( &self, opt: u8) -> Option<&[u8]> {
+ if opt == 0 || opt == 255 {
+ return None;
+ }
+ let mut i = 4; // Magic cookie ! 🍪
+ loop {
+ if i >= 312 {
+ return None;
+ }
+ let i_tmp : usize = usize::from(i);
+ if self.options[i_tmp] == opt {
+ return Some(&self.options[i_tmp..(self.options[i_tmp+1] as usize + 2 + i_tmp)]);
+ } 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]) + 2;
+ } else {
+ return None;
+ }
+ }
+ }
fn request_type( &self ) -> Option<DhcpMessageType> {
let mut i = 4; // Magic cookie ! 🍪
loop {
@@ -126,7 +181,6 @@ impl DhcpMessage {
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
@@ -134,12 +188,26 @@ impl DhcpMessage {
} 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]);
+ i += u16::from(self.options[i_tmp+1]) + 2;
} else {
return None;
}
}
}
+ fn to_bytes( &self ) -> Vec<u8> {
+ let mut ret = Vec::new();
+ ret
+ }
+ /*
+ *
+ *use std::net::UdpSocket;
+
+let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data");
+ *
+ *
+ *
+ */
}
impl fmt::Display for DhcpMessage {
@@ -208,7 +276,7 @@ impl fmt::Display for DhcpMessage {
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]);
+ i += u16::from(self.options[i_tmp+1]) + 2;
} else {
write!(f, " Unknow Option({:02x})\n", self.options[i_tmp])?;
break;
@@ -267,8 +335,84 @@ fn fill_dhcp_message( dhcp_message: &mut DhcpMessage, buf : &[u8; BUFFER_SIZE],
true
}
+fn deal_discovery(dhcp_message: &mut DhcpMessage, conf: &Config) -> Result<DhcpMessage, ErrorKind> {
+ println!("Discovery ! 🦊");
+ Err(ErrorKind::NotFound)
+}
+
+fn is_in_range(ip: Ipv4Addr, range: &Vec<(Ipv4Addr,Ipv4Addr)>) -> bool {
+ for (min, max) in range {
+ if ip >= *min && ip <= *max {
+ return true
+ }
+ }
+ return false
+}
+
+fn deal_request(dhcp_message: &DhcpMessage, conf: &Config, leases: &Vec<Ipv4Addr>) -> Result<DhcpMessage, ErrorKind> {
+ println!("Request ! 🦊");
+ let request_opt = dhcp_message.get_option_data(50);
+
+ let mut ret: DhcpMessage = DhcpMessage {
+ op: dhcp_message.op,
+ htype: dhcp_message.op,
+ hlen: dhcp_message.hlen,
+ hops: dhcp_message.hops,
+ xid: dhcp_message.xid,
+ secs: 0,
+ flags: dhcp_message.flags,
+ ciaddr: 0,
+ siaddr: 0,
+ giaddr: 0,
+ yiaddr: 0,
+ chaddr: dhcp_message.chaddr,
+ sname: [0; 64],
+ file: dhcp_message.file,
+ options: dhcp_message.options,
+ };
+
+ let request_opt = if let Some(request_opt) = request_opt {
+ if request_opt.len() < 6 {
+ println!("Too short {:?}", request_opt);
+ return Err(ErrorKind::InvalidData);
+ }
+ request_opt
+ } else {
+ println!("Didn't get anything 🤷");
+ return Err(ErrorKind::InvalidData);
+ };
+ let requested_addr = net::Ipv4Addr::new(request_opt[2], request_opt[3], request_opt[4], request_opt[5]);
+ println!("Want: {}", requested_addr);
+
+ if leases.contains(&requested_addr) {
+ // Send DHCPNAK
+ return Err(ErrorKind::AddrInUse);
+ }
+
+ if !is_in_range(requested_addr, &conf.ranges) {
+ // Send DHCPDECLINE
+ return Err(ErrorKind::AddrNotAvailable);
+ }
+
+ ret.yiaddr = u32::from(requested_addr);
+ // Send DHCPPACK
+ Err(ErrorKind::NotFound)
+}
+
+
fn main() -> std::io::Result<()> {
+
+ let mut available_ips = Vec::new();
+ available_ips.push((Ipv4Addr::new(10, 0, 0, 0), Ipv4Addr::new(11, 0, 0, 0)));
+
+ let config = Config {
+ ranges: available_ips,
+ name: "Unibit".to_string(),
+ };
+
+ let mut leases: Vec<Ipv4Addr> = Vec::new();
+
{
let addrs = [
net::SocketAddr::from(([0, 0, 0, 0], SERVER_PORT)),
@@ -290,17 +434,23 @@ fn main() -> std::io::Result<()> {
print!("{:02x}", buf[i])
}
fill_dhcp_message(&mut dhcp_message, &buf, amt);
- print!("\n");
- print!("{}\n", dhcp_message);
+ println!("");
+ println!("{}", dhcp_message);
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");
- }
+ let r = match dhcp_message.request_type() {
+ Some(DhcpMessageType::DHCPDISCOVER) => deal_discovery(&mut dhcp_message, &config),
+ Some(DhcpMessageType::DHCPREQUEST) => deal_request(&mut dhcp_message, &config, &leases),
+ Some(DhcpMessageType::DHCPOFFER) => Err(ErrorKind::PermissionDenied),
+ Some(e) => {
+ println!("Its {} !", e);
+ Err(ErrorKind::InvalidData)
+ },
+ _ => Err(ErrorKind::InvalidData)
+ };
}
} // the socket is closed here
+
Ok(())
}