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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::Error;
use crate::common::{MacAddress, MAC_LENGTH};
use arrayref::array_ref;
use nom::*;
#[derive(Clone, Copy, Debug)]
pub struct Arp {
pub sender_ip: std::net::IpAddr,
pub sender_mac: MacAddress,
pub target_ip: std::net::IpAddr,
pub target_mac: MacAddress,
pub operation: u16,
}
const ADDRESS_LENGTH: usize = 4;
fn to_ip_address(i: &[u8]) -> std::net::IpAddr {
let ipv4 = std::net::Ipv4Addr::from(array_ref![i, 0, ADDRESS_LENGTH].clone());
std::net::IpAddr::V4(ipv4)
}
named!(
ipv4_address<&[u8], std::net::IpAddr>,
map!(take!(ADDRESS_LENGTH), to_ip_address)
);
fn to_mac_address(i: &[u8]) -> MacAddress {
let mac_addr = MacAddress(array_ref![i, 0, MAC_LENGTH].clone());
mac_addr
}
named!(
mac_address<MacAddress>,
map!(take!(MAC_LENGTH), to_mac_address)
);
impl Arp {
pub fn new(
sender_ip: std::net::Ipv4Addr,
sender_mac: [u8; MAC_LENGTH],
target_ip: std::net::Ipv4Addr,
target_mac: [u8; MAC_LENGTH],
operation: u16,
) -> Arp {
Arp {
sender_ip: std::net::IpAddr::V4(sender_ip),
sender_mac: MacAddress(sender_mac),
target_ip: std::net::IpAddr::V4(target_ip),
target_mac: MacAddress(target_mac),
operation,
}
}
pub fn parse(input: &[u8]) -> Result<(&[u8], Arp), Error> {
do_parse!(
input,
_hardware_type: be_u16 >>
_protocol_type: be_u16 >>
_hardware_address_length: be_u8 >>
_protocol_address_length: be_u8 >>
operation: be_u16 >>
sender_hardware_address: mac_address >>
sender_protocol_address: ipv4_address >>
target_hardware_address: mac_address >>
target_protocol_address: ipv4_address >>
(
Arp {
sender_ip: sender_protocol_address,
sender_mac: sender_hardware_address,
target_ip: target_protocol_address,
target_mac: target_hardware_address,
operation: operation
}
)
).map_err(Error::from)
}
}
#[cfg(test)]
mod tests {
use super::*;
const RAW_DATA: &'static [u8] = &[
0x00u8, 0x01u8,
0x08u8, 0x00u8,
0x06u8,
0x04u8,
0x00u8, 0x01u8,
0x00u8, 0x0au8, 0xdcu8, 0x64u8, 0x85u8, 0xc2u8,
0xc0u8, 0xa8u8, 0x59u8, 0x01u8,
0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8,
0xc0u8, 0xa8u8, 0x59u8, 0x02u8,
];
#[test]
fn parse_arp() {
let (rem, l3) = Arp::parse(RAW_DATA).expect("Unable to parse");
assert!(rem.is_empty());
assert_eq!(
l3.sender_ip,
"192.168.89.1"
.parse::<std::net::IpAddr>()
.expect("Could not parse ip address")
);
assert_eq!(
format!("{}", l3.sender_mac),
"00:0a:dc:64:85:c2".to_string()
);
assert_eq!(
l3.target_ip,
"192.168.89.2"
.parse::<std::net::IpAddr>()
.expect("Could not parse ip address")
);
assert_eq!(
format!("{}", l3.target_mac),
"00:00:00:00:00:00".to_string()
);
assert_eq!(l3.operation, 1u16);
}
}