summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorache <ache@ache.one>2019-08-26 00:24:48 +0200
committerache <ache@ache.one>2019-08-26 00:24:48 +0200
commit8ad6494a252b9121c47198bd13d010890f78436c (patch)
tree18c85081ef5c1f57696537beb7bf3b56f0799b91
Init commit
-rw-r--r--Cargo.lock6
-rw-r--r--Cargo.toml7
-rw-r--r--src/main.rs258
3 files changed, 271 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..e7e6991
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "pinkydhcpd"
+version = "0.1.0"
+
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..729bb12
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "pinkydhcpd"
+version = "0.1.0"
+authors = ["ache <ache@ache.one>"]
+edition = "2018"
+
+[dependencies]
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..f514adf
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,258 @@
+use std::net::UdpSocket;
+use std::net;
+use std::str;
+use std::fmt;
+
+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 OPTIONS_NAME : [&str;77] = ["Pad", // 0
+ "Subnet mask",
+ "Time offset",
+ "Router option",
+ "Time server",
+ "Name server", // 5
+ "Domain name server",
+ "Log server",
+ "Cookie server 🍪",
+ "LPR server",
+ "Impress server", // 10
+ "Ressource location server",
+ "Host name",
+ "Boot file size",
+ "Merit dump file",
+ "Domain name", // 15
+ "Swap server",
+ "Root path",
+ "Extensions path",
+ "IP Forwarding",
+ "Non-local source routing", // 20
+ "Policy filter",
+ "Maximum datagram",
+ "Default TTL",
+ "Path MTU again",
+ "Path MTU plateau", // 25
+ "Interface MTU",
+ "All subnets are local",
+ "Broadcast address",
+ "Perform mask discovery",
+ "Mask supplier", // 30
+ "Perform router discovery",
+ "Router solicitation address",
+ "Static route",
+ "Trailer Encapsulation",
+ "ARP cache timeout", // 35
+ "Ethernet encapsulation",
+ "TCP Default TTL",
+ "TCP Keepalive interval",
+ "TCP Keepalive garbage",
+ "Network information service domain", // 40
+ "Network information servers",
+ "Network time protocol servers",
+ "Vendor specific information",
+ "NetBIOS over TCP/IP Name server",
+ "NetBIOS over TCP/IP Datagram disctribution server", // 45
+ "NetBIOS over TCP/IP Node type",
+ "NetBIOS over TCP/IP Scope",
+ "X Window System Font Server",
+ "X Window System Display Manager",
+ "Requested IP Address", // 50
+ "IP Address Lease Time",
+ "Option Overload",
+ "DHCP Message Type",
+ "Server Identifier",
+ "Parameter Request List", // 55
+ "Message",
+ "Maximum DHCP Message Size",
+ "Renewal T1 Time Value",
+ "Rebindin T2 Time Value",
+ "Vendor class identifier", // 60
+ "Client-identifier",
+ "62 - Unused",
+ "63 - Unused",
+ "Network Information Service+ Domain",
+ "Network Information Service+ Servers", // 65
+ "TFTP Server Option",
+ "Bootfile name",
+ "Mobile IP Home Agent",
+ "SMTP Server",
+ "POP3 Server", // 70
+ "NNTP Server",
+ "WWW Server",
+ "Finger Server",
+ "IRC Server",
+ "StreetTalk Server", // 75
+ "STDA Server",
+];
+
+struct DhcpMessage {
+ op: u8,
+ htype: u8,
+ hlen: u8,
+ hops: u8,
+ xid: u32,
+ secs: u16,
+ flags: u16,
+ ciaddr: u32,
+ yiaddr: u32,
+ siaddr: u32,
+ giaddr: u32,
+ chaddr: [u8; 6],
+ sname: [u8; 64],
+ file: [u8; 128],
+ options: [u8; 312]
+}
+
+impl fmt::Display for DhcpMessage {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut name: &str = "Undef";
+ let mut is_file_empty = true;
+ for o in &self.file[..] {
+ if *o != 0 {
+ is_file_empty = false;
+ }
+ };
+ let is_file_empty = is_file_empty;
+
+ if let Ok(s) = std::str::from_utf8(&self.sname[..]) {
+ name = s;
+ }
+
+ write!(f, "(
+ op: {:02X}
+ htype: {:02X}
+ hlen: {:02X}
+ hops: {:02X}
+ xid: {}
+ secs: {:04X}
+ flags: {:04X}
+ ciaddr: {:#08X}
+ yiaddr: {:#08X}
+ siaddr: {:#08X}
+ giaddr: {:#08X}
+ chaddr: {:02X}{:02X}{:02X}{:02X}{:02X}{:02X}
+ sname: [{}]
+ file: {}
+", self.op, self.htype,
+ self.hlen, self.hops, self.xid, self.secs,
+ self.flags, self.ciaddr, self.yiaddr,
+ 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");
+ let mut i: u16 = 0;
+ loop {
+ if i >= 312 {
+ break;
+ }
+ let I : usize = usize::from(i);
+ if self.options[I] == 0xFF {
+ write!(f, " End Option(0xFF)");
+ 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 {
+ write!(f, " Unknow Option({:02x})", self.options[I]);
+ break;
+ }
+ }
+ write!(f, ")\n")
+ }
+}
+impl DhcpMessage {
+ pub fn new() -> DhcpMessage {
+ DhcpMessage {
+ op: 0,
+ htype: 0,
+ hlen: 0,
+ hops: 0,
+ xid: 0,
+ secs: 0,
+ flags: 0,
+ ciaddr: 0,
+ yiaddr: 0,
+ siaddr: 0,
+ giaddr: 0,
+ chaddr: [0; 6],
+ sname: [0; 64],
+ file: [0; 128],
+ options: [0; 312],
+ }
+ }
+}
+fn fill_dhcp_message( dhcp_message: &mut DhcpMessage, buf : &[u8; BUFFER_SIZE], size: usize) -> bool {
+ dhcp_message.op = buf[0];
+ dhcp_message.htype = buf[1];
+ dhcp_message.hlen = buf[2];
+ dhcp_message.hops = buf[3];
+ dhcp_message.xid = u32::from_be_bytes([buf[4], buf[5], buf[ 6], buf[ 7]]);
+ dhcp_message.secs = u16::from_be_bytes([buf[ 8], buf[ 9]]);
+ dhcp_message.flags = u16::from_be_bytes([buf[10], buf[11]]);
+
+ dhcp_message.ciaddr = u32::from_be_bytes([buf[12], buf[13], buf[14], buf[15]]);
+ dhcp_message.yiaddr = u32::from_be_bytes([buf[16], buf[17], buf[18], buf[19]]);
+ 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]
+ }
+ for i in 0..128 {
+ 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]
+ }
+
+
+
+ true
+}
+
+fn main() -> std::io::Result<()> {
+ {
+ let addrs = [
+ net::SocketAddr::from(([0, 0, 0, 0], SERVER_PORT)),
+ ];
+ let socket = UdpSocket::bind(&addrs[..])?;
+
+ loop {
+ // 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];
+ let mut dhcp_message: DhcpMessage = DhcpMessage::new();
+ let (amt, _) = socket.recv_from(&mut buf)?;
+ print!("Receive {} bytes\n", amt);
+ for i in 0..amt {
+ if i % 16 == 0 {
+ print!("\n");
+ }
+ print!("{:02x}", buf[i])
+ }
+ fill_dhcp_message(&mut dhcp_message, &buf, amt);
+ print!("\n");
+ print!("{}\n", dhcp_message);
+ if dhcp_message.xid == 42 {
+ break
+ }
+ }
+ } // the socket is closed here
+ Ok(())
+}