Skip to content

Commit

Permalink
Initialized ipv4 packet.
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul-weqe committed Jun 21, 2024
1 parent 5c65f68 commit 0e30798
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 89 deletions.
115 changes: 114 additions & 1 deletion holo-vrrp/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ pub enum DecodeError {
#[derive(Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub enum PacketLengthError {

// A maximum number of 16 IP addresses are allowed for
// VRRP. Referenced from count_ip field
AddressCount(usize),
Expand All @@ -87,6 +86,42 @@ pub enum PacketLengthError {

}


// IP packet header
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |Version| IHL |Type of Service| Total Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Identification |Flags| Fragment Offset |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Time to Live | Protocol | Header Checksum |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Source Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Destination Address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Options | Padding |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
struct IPv4Paket {
version: u8,
ihl: u8,
tos: u8,
total_length: u16,
identification: u16,
flags: u8,
offset: u16,
ttl: u8,
protocol: u8,
checksum: u16,
src_address: Ipv4Addr,
dst_address: Ipv4Addr,
options: Option<u32>,
padding: Option<u8>
}

// ===== impl Packet =====

impl VRRPPacket {
Expand Down Expand Up @@ -180,6 +215,84 @@ impl VRRPPacket {
}
}

impl IPv4Paket {
fn encode(&self) -> BytesMut {
let mut buf = BytesMut::new();

// ver_ihl -> version[4 bits] + ihl[4 bits]
let ver_ihl: u8 = (self.version << 4) | self.ihl;
buf.put_u8(ver_ihl);
buf.put_u8(self.tos);
buf.put_u16(self.total_length);
buf.put_u16(self.identification);

// flag_off -> flags[4 bits] + offset[12 bits]
let flag_off: u16 = ((self.flags as u16) << 12) | self.offset;
buf.put_u16(flag_off);
buf.put_u8(self.ttl);
buf.put_u8(self.protocol);
buf.put_u16(self.checksum);
buf.put_ipv4(&self.src_address);
buf.put_ipv4(&self.dst_address);

// the header length for IP is between 20 and 24
// when 24, the options and padding fields are present.
if let (Some(options), Some(padding)) = (self.options, self.padding) {
let opt_pad: u32 = (options << 8) | (padding as u32);
buf.put_u32(opt_pad);
}
buf
}

pub fn decode(data: &[u8]) -> Self {
let buf = Bytes::copy_from_slice(data);

// ver_ihl -> version[4 bits] + ihl[4 bits]
let ver_ihl = buf.get_u8();
let version = ver_ihl >> 4;
let ihl = ver_ihl &0x0F;

let tos = buf.get_u8();
let total_length = buf.get_u16();
let identification = buf.get_u16();

// flag_off -> flags[4 bits] + offset[12 bits]
let flag_off = buf.get_u16();
let flags: u8 = flag_off >> 12;
let offset: u16 = flag_off & 0xFFF;

let ttl = buf.get_u8();
let protocol = buf.get_u8();
let checksum = buf.get_u16();
let src_address = buf.get_ipv4();
let dst_address = buf.get_ipv4();

let options: Option<u32> = None;
let padding: Option<u8> = None;
if ihl > 20 {
let opt_pad = buf.get_u32();
options = Some(opt_pad >> 8);
padding = Some(opt_pad & 0xFF);
}
Self {
version,
ihl,
tos,
total_length,
identification,
flags,
offset,
ttl,
protocol,
checksum,
src_address,
dst_address,
options,
padding
}
}
}

// ===== impl DecodeError =====

impl std::fmt::Display for DecodeError {
Expand Down
30 changes: 30 additions & 0 deletions holo-vrrp/tests/packet/ipv4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// Copyright (c) The Holo Core Contributors
//
// SPDX-License-Identifier: MIT
//


// the ipv4 Packet header details that will be used in IPV4 tests
// - version: 4
// - header length: 20
// - tos: 0
// - total length: 52
// - identification: 0x6cb8
// - flags: 0b0100000000000000
// - ttl: 51
// - protocol: 6 [TCP]
// - checksum: 0xfe74
// - source_address: 208.115.231.106
// - destination_address: 192.168.100.16
fn valid_pkt_data() -> [u8; 20] {
[
0x45, 0x00, 0x00, 0x34,
0x6c, 0xb8, 0x40, 0x00,
0x33, 0x06, 0xfe, 0x74,
0xd0, 0x73, 0xe7, 0x6a,
0xc0, 0xa8, 0x61, 0x10
]
}


90 changes: 2 additions & 88 deletions holo-vrrp/tests/packet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,91 +4,5 @@
// SPDX-License-Identifier: MIT
//


use bytes::Buf;
// TODO
use holo_vrrp::packet::{VRRPPacket, DecodeError, PacketLengthError};

/*
generally in the packet tests we will use the following packet structure
with slight modifications to be done on a per test basis(the changes will
be specified)
Valid VRRP packet with the following params:
- ver_type: 21 [version: 2, header_type: 1]
- vrid: 51
- priority: 101
- count_ip: 1
- auth_type: 0
- adver_int: 1
- checksum: 0x54db
- ip_addresses: [192.168.100.100]
- auth_data: 0
- auth_data2: 0
*/
fn valid_pkt_data() -> [u8; 20] {
[
0x21, 0x33, 0x65, 0x01,
0x00, 0x01, 0x54, 0xbd,
0xc0, 0xa8, 0x64, 0x64,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
]
}

// test the valid packet being decoded
#[test]
fn test_valid_decoding(){
let vrrp_pkt = VRRPPacket::decode(&valid_pkt_data());
assert!(vrrp_pkt.is_ok());
}


// make the VRRP packet too short. We will use 10 bytes.
#[test]
fn test_pkt_too_short() {
let vrrp_pkt = VRRPPacket::decode(&[0x00; 10]);
assert_eq!(
vrrp_pkt,
Err(DecodeError::PacketLengthError(PacketLengthError::TooShort(10)))
);
}

// the length of the entire packet is too long
#[test]
fn test_pkt_too_long() {
let vrrp_pkt = VRRPPacket::decode(&[0x00; 100]);
assert_eq!(
vrrp_pkt,
Err(DecodeError::PacketLengthError(PacketLengthError::TooLong(100)))
);
}

// test when the packet is too long in length
// we set count_ip as 17
#[test]
fn test_count_ip_too_high() {
let data: &mut [u8] = &mut valid_pkt_data();
data[3] = 17;
let vrrp_pkt = VRRPPacket::decode(data);
assert_eq!(
vrrp_pkt,
Err(DecodeError::PacketLengthError(PacketLengthError::AddressCount(17)))
);
}



// let us claim we have 3 ip addresses yet we have only one
// we set count_ip as 17
#[test]
fn test_count_ip_corrupted() {
let data: &mut [u8] = &mut valid_pkt_data();
data[3] = 3;
let vrrp_pkt = VRRPPacket::decode(data);
assert_eq!(
vrrp_pkt,
Err(DecodeError::PacketLengthError(PacketLengthError::CorruptedLength))
);
}

mod ipv4;
mod vrrp;
91 changes: 91 additions & 0 deletions holo-vrrp/tests/packet/vrrp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// Copyright (c) The Holo Core Contributors
//
// SPDX-License-Identifier: MIT
//

use bytes::Buf;
use holo_vrrp::packet::{VRRPPacket, DecodeError, PacketLengthError};

/*
generally in the packet tests we will use the following packet structure
with slight modifications to be done on a per test basis(the changes will
be specified)
Valid VRRP packet with the following params:
- ver_type: 21 [version: 2, header_type: 1]
- vrid: 51
- priority: 101
- count_ip: 1
- auth_type: 0
- adver_int: 1
- checksum: 0x54db
- ip_addresses: [192.168.100.100]
- auth_data: 0
- auth_data2: 0
*/
fn valid_pkt_data() -> [u8; 20] {
[
0x21, 0x33, 0x65, 0x01,
0x00, 0x01, 0x54, 0xbd,
0xc0, 0xa8, 0x64, 0x64,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
]
}

// test the valid packet being decoded
#[test]
fn test_valid_decoding(){
let vrrp_pkt = VRRPPacket::decode(&valid_pkt_data());
assert!(vrrp_pkt.is_ok());
}


// make the VRRP packet too short. We will use 10 bytes.
#[test]
fn test_pkt_too_short() {
let vrrp_pkt = VRRPPacket::decode(&[0x00; 10]);
assert_eq!(
vrrp_pkt,
Err(DecodeError::PacketLengthError(PacketLengthError::TooShort(10)))
);
}

// the length of the entire packet is too long
#[test]
fn test_pkt_too_long() {
let vrrp_pkt = VRRPPacket::decode(&[0x00; 100]);
assert_eq!(
vrrp_pkt,
Err(DecodeError::PacketLengthError(PacketLengthError::TooLong(100)))
);
}

// test when the packet is too long in length
// we set count_ip as 17
#[test]
fn test_count_ip_too_high() {
let data: &mut [u8] = &mut valid_pkt_data();
data[3] = 17;
let vrrp_pkt = VRRPPacket::decode(data);
assert_eq!(
vrrp_pkt,
Err(DecodeError::PacketLengthError(PacketLengthError::AddressCount(17)))
);
}



// let us claim we have 3 ip addresses yet we have only one
// we set count_ip as 17
#[test]
fn test_count_ip_corrupted() {
let data: &mut [u8] = &mut valid_pkt_data();
data[3] = 3;
let vrrp_pkt = VRRPPacket::decode(data);
assert_eq!(
vrrp_pkt,
Err(DecodeError::PacketLengthError(PacketLengthError::CorruptedLength))
);
}

0 comments on commit 0e30798

Please sign in to comment.