use std::{mem, slice, u8, u16}; pub static mut MAC_ADDR: MacAddr = MacAddr { bytes: [0x50, 0x51, 0x52, 0x53, 0x54, 0x55] }; pub static mut IP_ADDR: Ipv4Addr = Ipv4Addr { bytes: [10, 0, 2, 15] }; #[derive(Copy, Clone)] #[allow(non_camel_case_types)] #[repr(packed)] pub struct n16(u16); impl n16 { pub fn new(value: u16) -> Self { n16(value.to_be()) } pub fn get(&self) -> u16 { u16::from_be(self.0) } pub fn set(&mut self, value: u16) { self.0 = value.to_be(); } } #[derive(Copy, Clone)] pub struct MacAddr { pub bytes: [u8; 6], } impl MacAddr { pub fn equals(&self, other: Self) -> bool { for i in 0..6 { if self.bytes[i] != other.bytes[i] { return false; } } true } pub fn from_str(string: &str) -> Self { let mut addr = MacAddr { bytes: [0, 0, 0, 0, 0, 0] }; let mut i = 0; for part in string.split('.') { let octet = u8::from_str_radix(part, 16).unwrap_or(0); match i { 0 => addr.bytes[0] = octet, 1 => addr.bytes[1] = octet, 2 => addr.bytes[2] = octet, 3 => addr.bytes[3] = octet, 4 => addr.bytes[4] = octet, 5 => addr.bytes[5] = octet, _ => break, } i += 1; } addr } pub fn to_string(&self) -> String { let mut string = String::new(); for i in 0..6 { if i > 0 { string.push('.'); } string.push_str(&format!("{:X}", self.bytes[i])); } string } } #[derive(Copy, Clone)] pub struct Ipv4Addr { pub bytes: [u8; 4], } impl Ipv4Addr { pub fn equals(&self, other: Self) -> bool { for i in 0..4 { if self.bytes[i] != other.bytes[i] { return false; } } true } pub fn from_str(string: &str) -> Self { let mut addr = Ipv4Addr { bytes: [0, 0, 0, 0] }; let mut i = 0; for part in string.split('.') { let octet = part.parse::().unwrap_or(0); match i { 0 => addr.bytes[0] = octet, 1 => addr.bytes[1] = octet, 2 => addr.bytes[2] = octet, 3 => addr.bytes[3] = octet, _ => break, } i += 1; } addr } pub fn to_string(&self) -> String { let mut string = String::new(); for i in 0..4 { if i > 0 { string = string + "."; } string = string + &format!("{}", self.bytes[i]); } string } } #[derive(Copy, Clone)] #[repr(packed)] pub struct ArpHeader { pub htype: n16, pub ptype: n16, pub hlen: u8, pub plen: u8, pub oper: n16, pub src_mac: MacAddr, pub src_ip: Ipv4Addr, pub dst_mac: MacAddr, pub dst_ip: Ipv4Addr, } pub struct Arp { pub header: ArpHeader, pub data: Vec, } impl Arp { pub fn from_bytes(bytes: &[u8]) -> Option { if bytes.len() >= mem::size_of::() { unsafe { return Some(Arp { header: *(bytes.as_ptr() as *const ArpHeader), data: bytes[mem::size_of::() ..].to_vec(), }); } } None } pub fn to_bytes(&self) -> Vec { unsafe { let header_ptr: *const ArpHeader = &self.header; let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8, mem::size_of::())); ret.extend_from_slice(&self.data); ret } } }