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 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}