1use crate::error::Error;
2
3const MINIMUM_PACKET_SIZE: usize = 20;
4
5#[derive(Debug, PartialEq)]
6pub enum IpV4Protocol {
7 Icmp,
8}
9
10impl IpV4Protocol {
11 fn decode(data: u8) -> Option<Self> {
12 match data {
13 1 => Some(IpV4Protocol::Icmp),
14 _ => None,
15 }
16 }
17}
18
19#[derive(Debug)]
20pub struct IpV4Packet<'a> {
21 pub protocol: IpV4Protocol,
22 pub data: &'a [u8],
23}
24
25impl<'a> IpV4Packet<'a> {
26 pub fn decode(data: &'a [u8]) -> Result<Self, Error> {
27 if data.len() < MINIMUM_PACKET_SIZE {
28 return Err(Error::TooSmallHeader);
29 }
30 let byte0 = data[0];
31 let version = (byte0 & 0xf0) >> 4;
32 let header_size = 4 * ((byte0 & 0x0f) as usize);
33
34 if version != 4 {
35 return Err(Error::InvalidVersion);
36 }
37
38 if data.len() < header_size {
39 return Err(Error::InvalidHeaderSize);
40 }
41
42 let protocol = match IpV4Protocol::decode(data[9]) {
43 Some(protocol) => protocol,
44 None => return Err(Error::UnknownProtocol),
45 };
46
47 Ok(Self {
48 protocol,
49 data: &data[header_size..],
50 })
51 }
52}