From 743c38725f49318cf52f6e996d8611bcc9667be5 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Fri, 6 Nov 2020 00:04:41 +0800 Subject: [PATCH] feat: add ip --- __network/ip/Cargo.lock | 5 +++ __network/ip/Cargo.toml | 9 +++++ __network/ip/src/lib.rs | 84 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 __network/ip/Cargo.lock create mode 100644 __network/ip/Cargo.toml create mode 100644 __network/ip/src/lib.rs diff --git a/__network/ip/Cargo.lock b/__network/ip/Cargo.lock new file mode 100644 index 0000000..187d085 --- /dev/null +++ b/__network/ip/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "ip" +version = "0.1.0" diff --git a/__network/ip/Cargo.toml b/__network/ip/Cargo.toml new file mode 100644 index 0000000..08073ba --- /dev/null +++ b/__network/ip/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ip" +version = "0.1.0" +authors = ["Hatter Jiang "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/__network/ip/src/lib.rs b/__network/ip/src/lib.rs new file mode 100644 index 0000000..af34ee6 --- /dev/null +++ b/__network/ip/src/lib.rs @@ -0,0 +1,84 @@ + +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); +} \ No newline at end of file