use n::packet::*;
use n::ip;
extract_field!(extract_vhl, ipv4, 1, vhl);
fill_field!(fill_vhl, ipv4, 1, vhl);
extract_field!(extract_dscp_ecn, ipv4, 1, dscp_ecn);
fill_field!(fill_dscp_ecn, ipv4, 1, dscp_ecn);
extract_field!(extract_identification, ipv4, 2, identification);
fill_field!(fill_identification, ipv4, 2, identification);
extract_field_value!(extract_identification_u16, ipv4, identification, u16);
apply_field_value!(apply_identification, ipv4, identification, u16);
extract_field!(extract_fragment, ipv4, 2, fragment);
fill_field!(fill_fragment, ipv4, 2, fragment);
extract_field!(extract_header_checksum, ipv4, 2, header_checksum);
fill_field!(fill_header_checksum, ipv4, 2, header_checksum);
extract_field_value!(extract_header_checksum_u16, ipv4, header_checksum, u16);
apply_field_value!(apply_header_checksum, ipv4, header_checksum, u16);
extract_field!(extract_source, ipv4, 4, source);
fill_field!(fill_source, ipv4, 4, source);
extract_field_value!(extract_source_u32, ipv4, source, u32);
apply_field_value!(apply_source, ipv4, source, u32);
extract_field!(extract_destination, ipv4, 4, destination);
fill_field!(fill_destination, ipv4, 4, destination);
extract_field_value!(extract_destination_u32, ipv4, destination, u32);
apply_field_value!(apply_destination, ipv4, destination, u32);
alias_protocol!(extract_total_length, ipv4, ip, total_length);
alias_protocol!(fill_total_length, ipv4, ip, total_length);
alias_protocol!(extract_total_length_u16, ipv4, ip, total_length, total_length_u16);
alias_protocol!(apply_total_length, ipv4, ip, total_length, total_length_u16);
alias_protocol!(extract_hop_limit, ipv4, ip, hop_limit);
alias_protocol!(fill_hop_limit, ipv4, ip, hop_limit);
alias_protocol!(extract_hop_limit_u8, ipv4, ip, hop_limit, hop_limit_u8);
alias_protocol!(apply_hop_limit, ipv4, ip, hop_limit, hop_limit_u8);
alias_protocol!(extract_protocol, ipv4, ip, protocol);
alias_protocol!(fill_protocol, ipv4, ip, protocol);
alias_protocol!(extract_protocol_u8, ipv4, ip, protocol, protocol_u8);
alias_protocol!(apply_protocol, ipv4, ip, protocol, protocol_u8);
#[millefeuille]
pub fn extract_version_u8(packet: Packet) -> Packet {
let mut packet = packet;
let ihl;
{
let field = packet.context.get_field("ipv4::vhl");
ihl = field.read_u8(0);
}
packet.context.set_u8("ipv4::version_u8", (ihl >> 4) & 0x0F);
packet
}
#[millefeuille]
pub fn apply_version(packet: Packet) -> Packet {
let mut packet = packet;
let mut field = packet.context.take_field("ipv4::vhl");
let value = packet.context.get_u8("ipv4::version_u8");
let value = value << 4;
let value = value | (field.read_u8(0) & 0x0F);
field.write_u8(0, value);
packet.context.set_field("ipv4::vhl", field);
packet
}
#[millefeuille]
pub fn extract_header_length_u8(packet: Packet) -> Packet {
let mut packet = packet;
let ihl;
{
let field = packet.context.get_field("ipv4::vhl");
ihl = field.read_u8(0);
}
packet.context.set_u8("ipv4::header_length_u8", (ihl & 0x0F) << 2);
packet
}
#[millefeuille]
pub fn apply_header_length(packet: Packet) -> Packet {
let mut packet = packet;
let mut field = packet.context.take_field("ipv4::vhl");
let value = packet.context.get_u8("ipv4::header_length_u8");
let value = value >> 2;
let value = value | (field.read_u8(0) & 0xF0);
field.write_u8(0, value);
packet.context.set_field("ipv4::vhl", field);
packet
}
#[millefeuille]
pub fn extract_dscp_u8(packet: Packet) -> Packet {
let mut packet = packet;
let dscp_ecn;
{
let field = packet.context.get_field("ipv4::dscp_ecn");
dscp_ecn = field.read_u8(0);
}
packet.context.set_u8("ipv4::dscp_u8", (dscp_ecn >> 2) & 0x3F);
packet.context.set_alias("ip::dscp_u8", "ipv4::dscp_u8");
packet
}
#[millefeuille]
pub fn apply_dscp(packet: Packet) -> Packet {
let mut packet = packet;
let mut field = packet.context.take_field("ipv4::dscp_ecn");
let value = packet.context.get_u8("ipv4::dscp_u8");
let value = value << 2;
let value = value | (field.read_u8(0) & 0x03);
field.write_u8(0, value);
packet.context.set_field("ipv4::dscp_ecn", field);
packet
}
#[millefeuille]
pub fn extract_ecn_u8(packet: Packet) -> Packet {
let mut packet = packet;
let dscp_ecn;
{
let field = packet.context.get_field("ipv4::dscp_ecn");
dscp_ecn = field.read_u8(0);
}
packet.context.set_u8("ipv4::ecn_u8", dscp_ecn & 0x03);
packet.context.set_alias("ip::ecn_u8", "ipv4::ecn_u8");
packet
}
#[millefeuille]
pub fn apply_ecn(packet: Packet) -> Packet {
let mut packet = packet;
let mut field = packet.context.take_field("ipv4::dscp_ecn");
let value = packet.context.get_u8("ipv4::ecn_u8");
let value = value & 0x03;
let value = value | (field.read_u8(0) & 0x3F);
field.write_u8(0, value);
packet.context.set_field("ipv4::dscp_ecn", field);
packet
}
#[millefeuille]
pub fn extract_fragment_flag_u8(packet: Packet) -> Packet {
let mut packet = packet;
let fragment;
{
let field = packet.context.get_field("ipv4::fragment");
fragment = field.read_u8(0);
}
packet.context.set_u8("ipv4::fragment_flag_u8", (fragment >> 5) & 0x03);
packet
}
#[millefeuille]
pub fn apply_fragment_flag(packet: Packet) -> Packet {
let mut packet = packet;
let mut field = packet.context.take_field("ipv4::fragment");
let value = packet.context.get_u8("ipv4::fragment_flag_u8");
let value = value << 5;
let value = value | (field.read_u8(0) & 0x1F);
field.write_u8(0, value);
packet.context.set_field("ipv4::fragment", field);
packet
}
#[millefeuille]
pub fn extract_fragment_offset_u16(packet: Packet) -> Packet {
let mut packet = packet;
let fragment;
{
let field = packet.context.get_field("ipv4::fragment");
fragment = field.read_u16(0);
}
packet.context.set_u16("ipv4::fragment_offset_u16", ((fragment) & 0x1FFF) << 3);
packet
}
#[millefeuille]
pub fn apply_fragment_offset(packet: Packet) -> Packet {
let mut packet = packet;
let mut field = packet.context.take_field("ipv4::fragment");
let value = packet.context.get_u16("ipv4::fragment_offset_u16");
let value = value >> 3;
let value = value | (field.read_u16(0) & 0xE000);
field.write_u16(0, value);
packet.context.set_field("ipv4::fragment", field);
packet
}
#[millefeuille]
pub fn extract_option(packet: Packet) -> Packet {
let ihl;
{
let field = packet.context.get_field("ipv4::vhl");
ihl = field.read_u8(0) & 0x0F;
}
assert!(ihl >= 5);
let option_bytes = ((ihl - 5) << 2) as usize;
let (mut packet, field) = packet.right_packet(option_bytes);
packet.context.set_field("ipv4::option", field);
packet
}
#[millefeuille]
pub fn verify_header_checksum(packet: Packet) -> Packet {
let mut packet = packet;
let header_length;
{
header_length = (packet.read_u8(0) & 0xFF) << 2;
}
let result = packet.ones_complement_sum_u16(header_length as usize);
packet.context.set_u16("ipv4::current_csum_u16", result);
packet.context.set_bool("ipv4::correct_csum_bool",
(result == 0xFFFF) || (result == 0x0000));
packet
}
#[millefeuille]
pub fn apply_current_checksum(packet: Packet) -> Packet {
let mut packet = packet;
let mut field = packet.context.take_field("ipv4::header_checksum");
let current = packet.context.get_u16("ipv4::current_csum_u16");
let csum = field.read_u16(0);
let current = (!csum) as u32 + current as u32;
let current = ((current >> 16) + (current & 0xFFFF)) as u16;
field.write_u16(0, !current);
packet.context.set_bool_released("ipv4::correct_csum_bool", true);
packet.context.set_u16_released("ipv4::current_csum_u16", 0);
packet.context.set_field("ipv4::header_checksum", field);
packet
}
#[millefeuille]
pub fn prepare_pseudo_header_u16(packet: Packet) -> Packet {
let mut sum: u32;
let playload_len;
{
let ipv4_src = packet.context.get_field("ipv4::source");
let ipv4_dst = packet.context.get_field("ipv4::destination");
let ipv4_proto = packet.context.get_field("ipv4::protocol").read_u8(0);
let ipv4_hlen;
{
let field = packet.context.get_field("ipv4::vhl");
ipv4_hlen = field.read_u8(0);
}
let ipv4_hlen = (ipv4_hlen & 0x0F) << 2;
let ipv4_tlen = packet.context.get_field("ipv4::total_length").read_u16(0);
playload_len = (ipv4_tlen - (ipv4_hlen as u16)) as u32;
sum = playload_len;
sum = sum + (ipv4_proto as u16) as u32;
sum = sum + ipv4_src.ones_complement_sum_u16(ipv4_src.len()) as u32;
sum = sum + ipv4_dst.ones_complement_sum_u16(ipv4_dst.len()) as u32;
while (sum & 0xFFFF0000) > 0 {
sum = (sum >> 16) + (sum & 0x0000FFFF);
}
}
let mut packet = packet;
packet.context.set_u16("ipv4::pseudo_csum_u16", sum as u16);
packet.context.set_alias("ip::pseudo_csum_u16", "ipv4::pseudo_csum_u16");
packet.context.set_u32("ipv4::payload_length_u32", playload_len);
packet.context.set_alias("ip::payload_length_u32", "ipv4::payload_length_u32");
packet
}
#[millefeuille]
pub fn extract(packet: Packet) -> Packet {
let packet = verify_header_checksum(packet);
let packet = extract_vhl(packet);
let packet = extract_dscp_ecn(packet);
let packet = extract_total_length(packet);
let packet = extract_identification(packet);
let packet = extract_fragment(packet);
let packet = extract_hop_limit(packet);
let packet = extract_protocol(packet);
let packet = extract_header_checksum(packet);
let packet = extract_source(packet);
let packet = extract_destination(packet);
let packet = extract_option(packet);
let packet = prepare_pseudo_header_u16(packet);
packet
}
#[millefeuille]
pub fn fill(packet: Packet) -> Packet {
let packet = fill_destination(packet);
let packet = fill_source(packet);
let packet = fill_header_checksum(packet);
let packet = fill_protocol(packet);
let packet = fill_hop_limit(packet);
let packet = fill_fragment(packet);
let packet = fill_identification(packet);
let packet = fill_total_length(packet);
let packet = fill_dscp_ecn(packet);
let packet = fill_vhl(packet);
packet
}