feat: add ip

This commit is contained in:
2020-11-06 00:04:41 +08:00
parent 47f94a6544
commit 743c38725f
3 changed files with 98 additions and 0 deletions

5
__network/ip/Cargo.lock generated Normal file
View File

@@ -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"

9
__network/ip/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "ip"
version = "0.1.0"
authors = ["Hatter Jiang <jht5945@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

84
__network/ip/src/lib.rs Normal file
View File

@@ -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<u8>,
}
impl IpPackage {
fn parse(bytes: &[u8]) -> Result<Self, String> {
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);
}