enum IpType { ICMP = 0x01, TCP = 0x06, UDP = 0x11, } #[derive(Debug, Clone)] struct IpPackage { version: u8, // 4bits hlen: u8, // 4bits, type_of_service: u8, // 8bits total_length: u16, // 16bits identification: u16, // 16bits flags: u8, // 4bits fragment_offset: u16, // 12 bits ttl: u8, // 8bits protocol: u8, // 8bits header_checksum: u16, // 16bits source_ip_address: [u8; 4], // 32bits destination_ip_address: [u8; 4], // 32bits ip_options: [u8; 3], // 24bits data: Vec, } impl IpPackage { fn parse(bytes: &[u8]) -> Result { if bytes.len() < 24 { return Err("Length < 24".to_owned()); } let mut bytes_iter = bytes.iter(); let ver_hlen = bytes_iter.next().unwrap(); let version = (ver_hlen >> 4) & 0x0f as u8; let hlen = ver_hlen & 0x0f as u8; let type_of_service = *bytes_iter.next().unwrap(); let total_length_bytes = [*bytes_iter.next().unwrap(), *bytes_iter.next().unwrap()]; let total_length = u16::from_be_bytes(total_length_bytes); let identification_bytes = [*bytes_iter.next().unwrap(), *bytes_iter.next().unwrap()]; let identification = u16::from_be_bytes(identification_bytes); let tmp = *bytes_iter.next().unwrap(); let flags = (tmp >> 4) & 0x0f as u8; let fragment_offset_bytes = [tmp & 0x0f, *bytes_iter.next().unwrap()]; let fragment_offset = u16::from_be_bytes(fragment_offset_bytes); let ttl = *bytes_iter.next().unwrap(); let protocol = *bytes_iter.next().unwrap(); let header_checksum_bytes = [*bytes_iter.next().unwrap(), *bytes_iter.next().unwrap()]; let header_checksum = u16::from_be_bytes(header_checksum_bytes); let source_ip_address = [ *bytes_iter.next().unwrap(), *bytes_iter.next().unwrap(), *bytes_iter.next().unwrap(), *bytes_iter.next().unwrap() ]; let destination_ip_address = [ *bytes_iter.next().unwrap(), *bytes_iter.next().unwrap(), *bytes_iter.next().unwrap(), *bytes_iter.next().unwrap() ]; let ip_options = [ *bytes_iter.next().unwrap(), *bytes_iter.next().unwrap(), *bytes_iter.next().unwrap() ]; bytes_iter.next(); // padding let data = bytes[24..].to_vec(); Ok(Self{ version, hlen, type_of_service, total_length, identification, flags, fragment_offset, ttl, protocol, header_checksum, source_ip_address, destination_ip_address, ip_options, data, }) } } #[test] fn test_ip_package_parse() { let icmp_ip_package = vec![ 0x45, 0x00, 0x00, 0x54, 0x36, 0x55, 0x40, 0x00, 0x40, 0x01, 0x30, 0x6D, 0xC0, 0xA8, 0x03, 0x2F, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x6C, 0x47, 0x08, 0xBF, 0x00, 0x01, 0xE8, 0x4D, 0xA3, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x33, 0x78, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 ]; let package = IpPackage::parse(&icmp_ip_package).unwrap(); println!("{:#?}", package); assert_eq!(0x04, package.version); }