#[macro_use]
extern crate bitrange;
#[macro_use]
extern crate bitrange_plugin;
bitrange! {
Ipv4First: u32, "u32",
"aaaa_bbbb_cccccccc_dddddddddddddddd",
a: version,
b: ihl,
c: type_of_service,
d: total_length
}
bitrange! {
Ipv4Second: u32, "u32",
"aaaaaaaaaaaaaaaa_bbb_ccccccccccccc",
a: identification,
b: flags,
c: fragment_offset
}
bitrange! {
Ipv4Third: u32, "u32",
"aaaaaaaa_bbbbbbbb_cccccccccccccccc",
a: time_to_live,
b: protocol,
c: header_checksum
}
bitrange! {
Ipv4Sixth: u32, "u32",
"aaaaaaaaaaaaaaaaaaaaaaaa_bbbbbbbb",
a: options,
b: padding
}
pub struct Ipv4Header {
first: Ipv4First,
second: Ipv4Second,
third: Ipv4Third,
fourth: [u8; 4],
fifth: [u8; 4],
sixth: Ipv4Sixth,
}
impl Ipv4Header {
pub fn version(&self) -> u8 {
self.first.version() as u8
}
pub fn ihl(&self) -> u8 {
self.first.ihl() as u8
}
pub fn type_of_service(&self) -> u8 {
self.first.type_of_service() as u8
}
pub fn total_length(&self) -> u16 {
self.first.total_length() as u16
}
pub fn identification(&self) -> u16 {
self.second.identification() as u16
}
pub fn flags(&self) -> u8 {
self.second.flags() as u8
}
pub fn fragment_offset(&self) -> u16 {
self.second.fragment_offset() as u16
}
pub fn time_to_live(&self) -> u8 {
self.third.time_to_live() as u8
}
pub fn protocol(&self) -> u8 {
self.third.protocol() as u8
}
pub fn header_checksum(&self) -> u16 {
self.third.header_checksum() as u16
}
pub fn source_address(&self) -> [u8; 4] {
self.fourth
}
pub fn destination_address(&self) -> [u8; 4] {
self.fifth
}
pub fn options(&self) -> u32 {
self.sixth.options()
}
pub fn padding(&self) -> u8 {
self.sixth.padding() as u8
}
}
fn to_u32(b: &[u8]) -> u32 {
(b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24)
}
impl<'a> From<&'a [u8]> for Ipv4Header {
fn from(u: &[u8]) -> Ipv4Header {
let mut chunks = u.chunks(4);
let first = to_u32(chunks.next().unwrap());
let second = to_u32(chunks.next().unwrap());
let third = to_u32(chunks.next().unwrap());
let fourth = {
let mut v = [0u8; 4];
v.copy_from_slice(chunks.next().unwrap());
v
};
let fifth = {
let mut v = [0u8; 4];
v.copy_from_slice(chunks.next().unwrap());
v
};
let sixth = to_u32(chunks.next().unwrap());
Ipv4Header {
first: Ipv4First::from(first).unwrap(),
second: Ipv4Second::from(second).unwrap(),
third: Ipv4Third::from(third).unwrap(),
fourth: fourth,
fifth: fifth,
sixth: Ipv4Sixth::from(sixth).unwrap(),
}
}
}
fn main() {
let bytes: [u8; 24] = [
0x02, 0x5c, 0x44, 0xd8, 0x00, 0x00, 0x80, 0x11, 0x6e, 0x62, 0xc0, 0xa8, 0x02, 0x02, 0xc0,
0xa8, 0x02, 0x04, 0xe8, 0xa8, 0x13, 0xc4, 0x02, 0x48,
];
let header = Ipv4Header::from(&bytes[..]);
println!("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
println!(
"|{:^7}|{:^7}|{:^15}|{:^31}|",
header.version(),
header.ihl(),
header.type_of_service(),
header.total_length()
);
println!("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
println!(
"|{:^31}|{:^5}|{:^25}|",
header.identification(),
header.flags(),
header.fragment_offset()
);
println!("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
println!(
"|{:^15}|{:^15}|{:^31}|",
header.time_to_live(),
header.protocol(),
header.header_checksum()
);
println!("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
println!("|{:^63}|", format!("{:?}", header.source_address()));
println!("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
println!("|{:^63}|", format!("{:?}", header.destination_address()));
println!("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
println!("|{:^47}|{:^15}|", header.options(), header.padding());
println!("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
}