rips_packets/
arp.rs

1use ethernet::{EtherType, MacAddr};
2use std::net::Ipv4Addr;
3
4packet!(ArpPacket, MutArpPacket, 28);
5
6getters!(ArpPacket
7    pub fn hardware_type(&self) -> HardwareType {
8        HardwareType(read_offset!(self.0.as_ref(), 0, u16, from_be))
9    }
10
11    pub fn protocol_type(&self) -> EtherType {
12        EtherType(read_offset!(self.0.as_ref(), 2, u16, from_be))
13    }
14
15    pub fn hardware_length(&self) -> u8 {
16        read_offset!(self.0.as_ref(), 4, u8)
17    }
18
19    pub fn protocol_length(&self) -> u8 {
20        read_offset!(self.0.as_ref(), 5, u8)
21    }
22
23    pub fn operation(&self) -> Operation {
24        Operation(read_offset!(self.0.as_ref(), 6, u16, from_be))
25    }
26
27    pub fn sender_mac_addr(&self) -> MacAddr {
28        MacAddr::from_slice(&self.0.as_ref()[8..14])
29    }
30
31    pub fn sender_ip_addr(&self) -> Ipv4Addr {
32        Ipv4Addr::from(read_offset!(self.0.as_ref(), 14, [u8; 4]))
33    }
34
35    pub fn target_mac_addr(&self) -> MacAddr {
36        MacAddr::from_slice(&self.0.as_ref()[18..24])
37    }
38
39    pub fn target_ip_addr(&self) -> Ipv4Addr {
40        Ipv4Addr::from(read_offset!(self.0.as_ref(), 24, [u8; 4]))
41    }
42);
43
44impl<'a> MutArpPacket<'a> {
45    /// Sets the hardware_type, hardware_length, protocol_type and
46    /// protocol_length fields to correct values for an IPv4 over Ethernet
47    /// packet.
48    pub fn set_ipv4_over_ethernet_values(&mut self) {
49        self.set_hardware_type(HardwareType::ETHERNET);
50        self.set_protocol_type(EtherType::IPV4);
51        self.set_hardware_length(6);
52        self.set_protocol_length(4);
53    }
54}
55
56setters!(MutArpPacket
57    pub fn set_hardware_type(&mut self, hardware_type: HardwareType) {
58        write_offset!(self.0, 0, hardware_type.value(), u16, to_be)
59    }
60
61    pub fn set_protocol_type(&mut self, protocol_type: EtherType) {
62        write_offset!(self.0, 2, protocol_type.value(), u16, to_be)
63    }
64
65    pub fn set_hardware_length(&mut self, hardware_length: u8) {
66        write_offset!(self.0, 4, hardware_length, u8, to_be);
67    }
68
69    pub fn set_protocol_length(&mut self, protocol_length: u8) {
70        write_offset!(self.0, 5, protocol_length, u8, to_be);
71    }
72
73    pub fn set_operation(&mut self, operation: Operation) {
74        write_offset!(self.0, 6, operation.value(), u16, to_be)
75    }
76
77    pub fn set_sender_mac_addr(&mut self, sender_mac: MacAddr) {
78        self.0[8..14].copy_from_slice(sender_mac.as_ref());
79    }
80
81    pub fn set_sender_ip_addr(&mut self, sender_ip: Ipv4Addr) {
82        self.0[14..18].copy_from_slice(&sender_ip.octets());
83    }
84
85    pub fn set_target_mac_addr(&mut self, target_mac: MacAddr) {
86        self.0[18..24].copy_from_slice(target_mac.as_ref());
87    }
88
89    pub fn set_target_ip_addr(&mut self, target_ip: Ipv4Addr) {
90        self.0[24..28].copy_from_slice(&target_ip.octets());
91    }
92);
93
94
95#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
96pub struct HardwareType(pub u16);
97
98impl HardwareType {
99    pub const ETHERNET: HardwareType = HardwareType(1);
100
101    pub fn value(&self) -> u16 {
102        self.0
103    }
104}
105
106#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
107pub struct Operation(pub u16);
108
109impl Operation {
110    pub const REQUEST: Operation = Operation(1);
111    pub const REPLY: Operation = Operation(2);
112
113    pub fn value(&self) -> u16 {
114        self.0
115    }
116}
117
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    static MAC: [u8; 6] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
124    static IP: [u8; 4] = [0xff, 0xff, 0xff, 0xff];
125
126    macro_rules! arp_setget_test {
127        ($name:ident, $set_name:ident, $value:expr, $offset:expr, $expected:expr) => {
128            setget_test!(MutArpPacket, $name, $set_name, $value, $offset, $expected);
129        }
130    }
131
132    arp_setget_test!(
133        hardware_type,
134        set_hardware_type,
135        HardwareType(0xffff),
136        0,
137        [0xff, 0xff]
138    );
139    arp_setget_test!(
140        protocol_type,
141        set_protocol_type,
142        EtherType(0xffff),
143        2,
144        [0xff, 0xff]
145    );
146    arp_setget_test!(hardware_length, set_hardware_length, 0xff, 4, [0xff]);
147    arp_setget_test!(protocol_length, set_protocol_length, 0xff, 5, [0xff]);
148    arp_setget_test!(operation, set_operation, Operation(0xffff), 6, [0xff, 0xff]);
149    arp_setget_test!(sender_mac_addr, set_sender_mac_addr, MacAddr(MAC), 8, MAC);
150    arp_setget_test!(
151        sender_ip_addr,
152        set_sender_ip_addr,
153        Ipv4Addr::new(0xff, 0xff, 0xff, 0xff),
154        14,
155        IP
156    );
157    arp_setget_test!(target_mac_addr, set_target_mac_addr, MacAddr(MAC), 18, MAC);
158    arp_setget_test!(
159        target_ip_addr,
160        set_target_ip_addr,
161        Ipv4Addr::new(0xff, 0xff, 0xff, 0xff),
162        24,
163        IP
164    );
165
166    #[test]
167    fn setters_incremental() {
168        let mut backing_data = [0; 28];
169        {
170            let mut testee = MutArpPacket::new(&mut backing_data).unwrap();
171            testee.set_hardware_type(HardwareType(1 << 8 | 2));
172            testee.set_protocol_type(EtherType(3 << 8 | 4));
173            testee.set_hardware_length(5);
174            testee.set_protocol_length(6);
175            testee.set_operation(Operation(7 << 8 | 8));
176            testee.set_sender_mac_addr(MacAddr([9, 10, 11, 12, 13, 14]));
177            testee.set_sender_ip_addr(Ipv4Addr::new(15, 16, 17, 18));
178            testee.set_target_mac_addr(MacAddr([19, 20, 21, 22, 23, 24]));
179            testee.set_target_ip_addr(Ipv4Addr::new(25, 26, 27, 28));
180        }
181        for (i, (expected, actual)) in (1u8..29).zip(backing_data.iter()).enumerate() {
182            assert_eq!(expected, *actual, "Invalid byte at index {}", i);
183        }
184    }
185
186    #[test]
187    fn default_setter() {
188        let mut backing_data = [0; 28];
189        let mut testee = MutArpPacket::new(&mut backing_data).unwrap();
190        testee.set_ipv4_over_ethernet_values();
191
192        assert_eq!(
193            HardwareType::ETHERNET,
194            testee.as_immutable().hardware_type()
195        );
196        assert_eq!(EtherType::IPV4, testee.as_immutable().protocol_type());
197        assert_eq!(6, testee.as_immutable().hardware_length());
198        assert_eq!(4, testee.as_immutable().protocol_length());
199    }
200}