Skip to main content

netlink_packet_core/
parsers.rs

1// SPDX-License-Identifier: MIT
2
3use std::{
4    mem::size_of,
5    net::{IpAddr, Ipv4Addr, Ipv6Addr},
6};
7
8use crate::DecodeError;
9
10pub fn parse_mac(payload: &[u8]) -> Result<[u8; 6], DecodeError> {
11    if payload.len() != 6 {
12        return Err(DecodeError::invalid_mac_address(payload.len()));
13    }
14    let mut address: [u8; 6] = [0; 6];
15    for (i, byte) in payload.iter().enumerate() {
16        address[i] = *byte;
17    }
18    Ok(address)
19}
20
21pub fn parse_ipv6(payload: &[u8]) -> Result<[u8; 16], DecodeError> {
22    if payload.len() != 16 {
23        return Err(DecodeError::invalid_ip_address(payload.len()));
24    }
25    let mut address: [u8; 16] = [0; 16];
26    for (i, byte) in payload.iter().enumerate() {
27        address[i] = *byte;
28    }
29    Ok(address)
30}
31
32pub fn parse_ip(payload: &[u8]) -> Result<IpAddr, DecodeError> {
33    match payload.len() {
34        4 => Ok(
35            Ipv4Addr::new(payload[0], payload[1], payload[2], payload[3])
36                .into(),
37        ),
38        16 => Ok(Ipv6Addr::from([
39            payload[0],
40            payload[1],
41            payload[2],
42            payload[3],
43            payload[4],
44            payload[5],
45            payload[6],
46            payload[7],
47            payload[8],
48            payload[9],
49            payload[10],
50            payload[11],
51            payload[12],
52            payload[13],
53            payload[14],
54            payload[15],
55        ])
56        .into()),
57        other => Err(DecodeError::invalid_ip_address(other)),
58    }
59}
60
61pub fn parse_string(payload: &[u8]) -> Result<String, DecodeError> {
62    if payload.is_empty() {
63        return Ok(String::new());
64    }
65    // iproute2 is a bit inconsistent with null-terminated strings.
66    let slice = if payload[payload.len() - 1] == 0 {
67        &payload[..payload.len() - 1]
68    } else {
69        &payload[..payload.len()]
70    };
71    let s = String::from_utf8(slice.to_vec())?;
72    Ok(s)
73}
74
75pub fn parse_u8(payload: &[u8]) -> Result<u8, DecodeError> {
76    if payload.len() != 1 {
77        return Err(DecodeError::invalid_number(1, payload.len()));
78    }
79    Ok(payload[0])
80}
81
82pub fn parse_i8(payload: &[u8]) -> Result<i8, DecodeError> {
83    if payload.len() != 1 {
84        return Err(DecodeError::invalid_number(1, payload.len()));
85    }
86    Ok(payload[0] as i8)
87}
88
89macro_rules! gen_int_parser {
90    (
91        $(
92            $parse:ident, $parse_be:ident, $parse_le:ident,
93            $emit:ident, $emit_le:ident, $emit_be:ident,
94            $data_type:ty,
95        )+
96    ) => {
97        $(
98            pub fn $parse(payload: &[u8]) -> Result<$data_type, DecodeError> {
99                if payload.len() != size_of::<$data_type>() {
100                    return Err(DecodeError::invalid_number(
101                        size_of::<$data_type>(),
102                        payload.len(),
103                    ));
104                }
105                let mut data = [0u8; size_of::<$data_type>()];
106                data.copy_from_slice(payload);
107                Ok(<$data_type>::from_ne_bytes(data))
108            }
109
110            pub fn $parse_be(payload: &[u8]) -> Result<$data_type, DecodeError> {
111                if payload.len() != size_of::<$data_type>() {
112                    return Err(DecodeError::invalid_number(
113                        size_of::<$data_type>(),
114                        payload.len(),
115                    ));
116                }
117                let mut data = [0u8; size_of::<$data_type>()];
118                data.copy_from_slice(payload);
119                Ok(<$data_type>::from_be_bytes(data))
120            }
121
122            pub fn $parse_le(payload: &[u8]) -> Result<$data_type, DecodeError> {
123                if payload.len() != size_of::<$data_type>() {
124                    return Err(DecodeError::invalid_number(
125                        size_of::<$data_type>(),
126                        payload.len(),
127                    ));
128                }
129                let mut data = [0u8; size_of::<$data_type>()];
130                data.copy_from_slice(payload);
131                Ok(<$data_type>::from_le_bytes(data))
132            }
133
134            pub fn $emit(
135                buf: &mut [u8],
136                value: $data_type,
137            ) -> Result<(), DecodeError> {
138                if buf.len() < size_of::<$data_type>() {
139                    return Err(DecodeError::buffer_too_small(
140                        buf.len(),
141                        size_of::<$data_type>(),
142                    ));
143                }
144                buf[..size_of::<$data_type>()]
145                    .copy_from_slice(&value.to_ne_bytes());
146                Ok(())
147            }
148
149            pub fn $emit_le(
150                buf: &mut [u8],
151                value: $data_type,
152            ) -> Result<(), DecodeError> {
153                if buf.len() < size_of::<$data_type>() {
154                    return Err(DecodeError::buffer_too_small(
155                        buf.len(),
156                        size_of::<$data_type>(),
157                    ));
158                }
159                buf[..size_of::<$data_type>()]
160                    .copy_from_slice(&value.to_le_bytes());
161                Ok(())
162            }
163
164            pub fn $emit_be(
165                buf: &mut [u8],
166                value: $data_type,
167            ) -> Result<(), DecodeError> {
168                if buf.len() < size_of::<$data_type>() {
169                    return Err(DecodeError::buffer_too_small(
170                        buf.len(),
171                        size_of::<$data_type>(),
172                    ));
173                }
174                buf[..size_of::<$data_type>()]
175                    .copy_from_slice(&value.to_be_bytes());
176                Ok(())
177            }
178        )+
179    }
180}
181
182gen_int_parser!(
183    parse_u16,
184    parse_u16_be,
185    parse_u16_le,
186    emit_u16,
187    emit_u16_le,
188    emit_u16_be,
189    u16,
190    parse_u32,
191    parse_u32_be,
192    parse_u32_le,
193    emit_u32,
194    emit_u32_le,
195    emit_u32_be,
196    u32,
197    parse_u64,
198    parse_u64_be,
199    parse_u64_le,
200    emit_u64,
201    emit_u64_le,
202    emit_u64_be,
203    u64,
204    parse_u128,
205    parse_u128_be,
206    parse_u128_le,
207    emit_u128,
208    emit_u128_le,
209    emit_u128_be,
210    u128,
211    parse_i16,
212    parse_i16_be,
213    parse_i16_le,
214    emit_i16,
215    emit_i16_le,
216    emit_i16_be,
217    i16,
218    parse_i32,
219    parse_i32_be,
220    parse_i32_le,
221    emit_i32,
222    emit_i32_le,
223    emit_i32_be,
224    i32,
225    parse_i64,
226    parse_i64_be,
227    parse_i64_le,
228    emit_i64,
229    emit_i64_le,
230    emit_i64_be,
231    i64,
232    parse_i128,
233    parse_i128_be,
234    parse_i128_le,
235    emit_i128,
236    emit_i128_le,
237    emit_i128_be,
238    i128,
239);