net_parser_rs/layer3/
arp.rs

1use crate::Error;
2use crate::common::{MacAddress, MAC_LENGTH};
3
4use arrayref::array_ref;
5use nom::*;
6
7#[derive(Clone, Copy, Debug)]
8pub struct Arp {
9    pub sender_ip: std::net::IpAddr,
10    pub sender_mac: MacAddress,
11    pub target_ip: std::net::IpAddr,
12    pub target_mac: MacAddress,
13    pub operation: u16,
14}
15
16const ADDRESS_LENGTH: usize = 4;
17fn to_ip_address(i: &[u8]) -> std::net::IpAddr {
18    let ipv4 = std::net::Ipv4Addr::from(array_ref![i, 0, ADDRESS_LENGTH].clone());
19    std::net::IpAddr::V4(ipv4)
20}
21
22named!(
23    ipv4_address<&[u8], std::net::IpAddr>,
24    map!(take!(ADDRESS_LENGTH), to_ip_address)
25);
26
27fn to_mac_address(i: &[u8]) -> MacAddress {
28    let mac_addr = MacAddress(array_ref![i, 0, MAC_LENGTH].clone());
29    mac_addr
30}
31
32named!(
33    mac_address<MacAddress>,
34    map!(take!(MAC_LENGTH), to_mac_address)
35);
36
37impl Arp {
38    pub fn new(
39        sender_ip: std::net::Ipv4Addr,
40        sender_mac: [u8; MAC_LENGTH],
41        target_ip: std::net::Ipv4Addr,
42        target_mac: [u8; MAC_LENGTH],
43        operation: u16,
44    ) -> Arp {
45        Arp {
46            sender_ip: std::net::IpAddr::V4(sender_ip),
47            sender_mac: MacAddress(sender_mac),
48            target_ip: std::net::IpAddr::V4(target_ip),
49            target_mac: MacAddress(target_mac),
50            operation,
51        }
52    }
53
54    pub fn parse(input: &[u8]) -> Result<(&[u8], Arp), Error> {
55        do_parse!(
56            input,
57            _hardware_type: be_u16 >>
58            _protocol_type: be_u16 >>
59            _hardware_address_length: be_u8 >>
60            _protocol_address_length: be_u8 >>
61            operation: be_u16 >>
62            sender_hardware_address: mac_address >> // ethernet address size is 6 bytes
63            sender_protocol_address: ipv4_address >> // ipv4 address size is 4
64            target_hardware_address: mac_address >>
65            target_protocol_address: ipv4_address >>
66            (
67                Arp {
68                    sender_ip: sender_protocol_address,
69                    sender_mac: sender_hardware_address,
70                    target_ip: target_protocol_address,
71                    target_mac: target_hardware_address,
72                    operation: operation
73                }
74            )
75        ).map_err(Error::from)
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    const RAW_DATA: &'static [u8] = &[
84        // all the raw datas
85        0x00u8, 0x01u8, // hardware type
86        0x08u8, 0x00u8, // protocol type
87        0x06u8, // hardware address length
88        0x04u8, // protocol address length
89        0x00u8, 0x01u8, // operation
90        0x00u8, 0x0au8, 0xdcu8, 0x64u8, 0x85u8, 0xc2u8, // sender hardware address
91        0xc0u8, 0xa8u8, 0x59u8, 0x01u8, // sender protocol address
92        0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, // target hardware address
93        0xc0u8, 0xa8u8, 0x59u8, 0x02u8, // target protocol address
94    ];
95
96    #[test]
97    fn parse_arp() {
98        let (rem, l3) = Arp::parse(RAW_DATA).expect("Unable to parse");
99
100        assert!(rem.is_empty());
101        assert_eq!(
102            l3.sender_ip,
103            "192.168.89.1"
104                .parse::<std::net::IpAddr>()
105                .expect("Could not parse ip address")
106        );
107        assert_eq!(
108            format!("{}", l3.sender_mac),
109            "00:0a:dc:64:85:c2".to_string()
110        );
111        assert_eq!(
112            l3.target_ip,
113            "192.168.89.2"
114                .parse::<std::net::IpAddr>()
115                .expect("Could not parse ip address")
116        );
117        assert_eq!(
118            format!("{}", l3.target_mac),
119            "00:00:00:00:00:00".to_string()
120        );
121        assert_eq!(l3.operation, 1u16);
122    }
123}