1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use crate::{AsBeBytes, checksum};
use super::{Header, PacketData, Protocol, ParseError};

#[derive(AddGetter, AddSetter)]
#[get]
#[set]
pub struct IcmpHeader {
    msg_type: u8,
    code: u8,
    identifier: u16,
    sequence_number: u16,
}

impl IcmpHeader {
    pub fn new(msg_type: u8, code: u8, identifier: u16, sequence_number: u16) -> Self {
        IcmpHeader {
            msg_type,
            code,
            identifier,
            sequence_number,
        }
    }
}

impl Header for IcmpHeader {
    fn make(self) -> PacketData {
        // some hosts dont seem to reply when sequence number is 0, even though in RFC 792 on page 14 it says it can be zero
        let ident_bytes = self.identifier.split_to_bytes();
        let sn_bytes = self.sequence_number.split_to_bytes();
        let mut packet: Vec<u8> = vec![
            self.msg_type,
            self.code,
            0,
            0,
            ident_bytes[0],
            ident_bytes[1],
            sn_bytes[1],
            sn_bytes[0],
        ];
        let checksum = checksum(&packet, 1).split_to_bytes();
        packet[2] = checksum[0];
        packet[3] = checksum[1];
        packet
    }

    fn parse(raw_data: &[u8]) -> Result<Box<Self>, ParseError> {
        if raw_data.len() < Self::get_min_length().into() {
            return Err(ParseError::InvalidLength);
        }
        Ok(Box::new(Self {
            msg_type: raw_data[0],
            code: raw_data[1],
            identifier: ((raw_data[4] as u16) << 8) + raw_data[5] as u16,
            sequence_number: ((raw_data[6] as u16) << 8) + raw_data[7] as u16,
        }))
    }

    fn get_proto(&self) -> Protocol {
        Protocol::ICMP
    }


    fn get_length(&self) -> u8 {
        8
    }

    fn get_min_length() -> u8 {
        8
    }
}