use std::{mem, slice, u8, u16}; 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 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)] pub struct Checksum { pub data: u16, } impl Checksum { pub unsafe fn check(&self, mut ptr: usize, mut len: usize) -> bool { let mut sum: usize = 0; while len > 1 { sum += *(ptr as *const u16) as usize; len -= 2; ptr += 2; } if len > 0 { sum += *(ptr as *const u8) as usize; } while (sum >> 16) > 0 { sum = (sum & 0xFFFF) + (sum >> 16); } sum == 0xFFFF } pub unsafe fn calculate(&mut self, ptr: usize, len: usize) { self.data = 0; let sum = Checksum::sum(ptr, len); self.data = Checksum::compile(sum); } pub unsafe fn sum(mut ptr: usize, mut len: usize) -> usize { let mut sum = 0; while len > 1 { sum += *(ptr as *const u16) as usize; len -= 2; ptr += 2; } if len > 0 { sum += *(ptr as *const u8) as usize; } sum } pub fn compile(mut sum: usize) -> u16 { while (sum >> 16) > 0 { sum = (sum & 0xFFFF) + (sum >> 16); } 0xFFFF - (sum as u16) } } #[derive(Copy, Clone)] #[repr(packed)] pub struct UdpHeader { pub src: n16, pub dst: n16, pub len: n16, pub checksum: Checksum, } pub struct Udp { pub header: UdpHeader, pub data: Vec, } impl Udp { pub fn from_bytes(bytes: &[u8]) -> Option { if bytes.len() >= mem::size_of::() { unsafe { Option::Some(Udp { header: *(bytes.as_ptr() as *const UdpHeader), data: bytes[mem::size_of::()..bytes.len()].to_vec(), }) } } else { Option::None } } pub fn to_bytes(&self) -> Vec { unsafe { let header_ptr: *const UdpHeader = &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 } } }