Skip to content

Commit 8a464b2

Browse files
committed
parsing: Copy parsers from netlink-core-utils
Signed-off-by: Enrique Llorente <[email protected]>
1 parent b3249b7 commit 8a464b2

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,6 @@ pub use self::constants::*;
270270

271271
pub mod nla;
272272
pub use self::nla::*;
273+
274+
pub mod parsers;
275+
pub use self::parsers::*;

src/parsers.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
use std::{
4+
mem::size_of,
5+
net::{IpAddr, Ipv4Addr, Ipv6Addr},
6+
};
7+
8+
use byteorder::{BigEndian, ByteOrder, NativeEndian};
9+
10+
use crate::DecodeError;
11+
12+
pub fn parse_mac(payload: &[u8]) -> Result<[u8; 6], DecodeError> {
13+
if payload.len() != 6 {
14+
return Err(DecodeError::invalid_mac_address(payload.len()));
15+
}
16+
let mut address: [u8; 6] = [0; 6];
17+
for (i, byte) in payload.iter().enumerate() {
18+
address[i] = *byte;
19+
}
20+
Ok(address)
21+
}
22+
23+
pub fn parse_ipv6(payload: &[u8]) -> Result<[u8; 16], DecodeError> {
24+
if payload.len() != 16 {
25+
return Err(DecodeError::invalid_ip_address(payload.len()));
26+
}
27+
let mut address: [u8; 16] = [0; 16];
28+
for (i, byte) in payload.iter().enumerate() {
29+
address[i] = *byte;
30+
}
31+
Ok(address)
32+
}
33+
34+
pub fn parse_ip(payload: &[u8]) -> Result<IpAddr, DecodeError> {
35+
match payload.len() {
36+
4 => Ok(
37+
Ipv4Addr::new(payload[0], payload[1], payload[2], payload[3])
38+
.into(),
39+
),
40+
16 => Ok(Ipv6Addr::from([
41+
payload[0],
42+
payload[1],
43+
payload[2],
44+
payload[3],
45+
payload[4],
46+
payload[5],
47+
payload[6],
48+
payload[7],
49+
payload[8],
50+
payload[9],
51+
payload[10],
52+
payload[11],
53+
payload[12],
54+
payload[13],
55+
payload[14],
56+
payload[15],
57+
])
58+
.into()),
59+
other => Err(DecodeError::invalid_ip_address(other)),
60+
}
61+
}
62+
63+
pub fn parse_string(payload: &[u8]) -> Result<String, DecodeError> {
64+
if payload.is_empty() {
65+
return Ok(String::new());
66+
}
67+
// iproute2 is a bit inconsistent with null-terminated strings.
68+
let slice = if payload[payload.len() - 1] == 0 {
69+
&payload[..payload.len() - 1]
70+
} else {
71+
&payload[..payload.len()]
72+
};
73+
let s = String::from_utf8(slice.to_vec())?;
74+
Ok(s)
75+
}
76+
77+
pub fn parse_u8(payload: &[u8]) -> Result<u8, DecodeError> {
78+
if payload.len() != 1 {
79+
return Err(DecodeError::invalid_number(1, payload.len()));
80+
}
81+
Ok(payload[0])
82+
}
83+
84+
pub fn parse_i8(payload: &[u8]) -> Result<i8, DecodeError> {
85+
if payload.len() != 1 {
86+
return Err(DecodeError::invalid_number(1, payload.len()));
87+
}
88+
Ok(payload[0] as i8)
89+
}
90+
91+
pub fn parse_u32(payload: &[u8]) -> Result<u32, DecodeError> {
92+
if payload.len() != size_of::<u32>() {
93+
return Err(DecodeError::invalid_number(
94+
size_of::<u32>(),
95+
payload.len(),
96+
));
97+
}
98+
Ok(NativeEndian::read_u32(payload))
99+
}
100+
101+
pub fn parse_u64(payload: &[u8]) -> Result<u64, DecodeError> {
102+
if payload.len() != size_of::<u64>() {
103+
return Err(DecodeError::invalid_number(
104+
size_of::<u64>(),
105+
payload.len(),
106+
));
107+
}
108+
Ok(NativeEndian::read_u64(payload))
109+
}
110+
pub fn parse_u128(payload: &[u8]) -> Result<u128, DecodeError> {
111+
if payload.len() != size_of::<u128>() {
112+
return Err(DecodeError::invalid_number(
113+
size_of::<u128>(),
114+
payload.len(),
115+
));
116+
}
117+
Ok(NativeEndian::read_u128(payload))
118+
}
119+
120+
pub fn parse_u16(payload: &[u8]) -> Result<u16, DecodeError> {
121+
if payload.len() != size_of::<u16>() {
122+
return Err(DecodeError::invalid_number(
123+
size_of::<u16>(),
124+
payload.len(),
125+
));
126+
}
127+
Ok(NativeEndian::read_u16(payload))
128+
}
129+
130+
pub fn parse_i32(payload: &[u8]) -> Result<i32, DecodeError> {
131+
if payload.len() != 4 {
132+
return Err(DecodeError::invalid_number(4, payload.len()));
133+
}
134+
Ok(NativeEndian::read_i32(payload))
135+
}
136+
137+
pub fn parse_i64(payload: &[u8]) -> Result<i64, DecodeError> {
138+
if payload.len() != 8 {
139+
return Err(format!("invalid i64: {payload:?}").into());
140+
}
141+
Ok(NativeEndian::read_i64(payload))
142+
}
143+
144+
pub fn parse_u16_be(payload: &[u8]) -> Result<u16, DecodeError> {
145+
if payload.len() != size_of::<u16>() {
146+
return Err(DecodeError::invalid_number(
147+
size_of::<u16>(),
148+
payload.len(),
149+
));
150+
}
151+
Ok(BigEndian::read_u16(payload))
152+
}
153+
154+
pub fn parse_u32_be(payload: &[u8]) -> Result<u32, DecodeError> {
155+
if payload.len() != size_of::<u32>() {
156+
return Err(DecodeError::invalid_number(
157+
size_of::<u32>(),
158+
payload.len(),
159+
));
160+
}
161+
Ok(BigEndian::read_u32(payload))
162+
}

0 commit comments

Comments
 (0)