tiny_ping/packet/
ipv4.rs

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}