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 pastey::paste;
9
10use crate::DecodeError;
11
12pub 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
23pub 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
34pub 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
63pub 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
77pub 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
84pub 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
91macro_rules! gen_int_parser {
92    ( $($data_type:ty,)+ ) => {
93        $(
94
95            paste! {
96                pub fn [<parse_ $data_type >](
97                    payload: &[u8]
98                ) -> 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_ $data_type _be>](
111                    payload: &[u8]
112                ) -> Result<$data_type, DecodeError> {
113                    if payload.len() != size_of::<$data_type>() {
114                        return Err(DecodeError::invalid_number(
115                            size_of::<$data_type>(),
116                            payload.len(),
117                        ));
118                    }
119                    let mut data = [0u8; size_of::<$data_type>()];
120                    data.copy_from_slice(payload);
121                    Ok(<$data_type>::from_be_bytes(data))
122                }
123
124                pub fn [<parse_ $data_type _le>](
125                    payload: &[u8]
126                ) -> Result<$data_type, DecodeError> {
127                    if payload.len() != size_of::<$data_type>() {
128                        return Err(DecodeError::invalid_number(
129                            size_of::<$data_type>(),
130                            payload.len(),
131                        ));
132                    }
133                    let mut data = [0u8; size_of::<$data_type>()];
134                    data.copy_from_slice(payload);
135                    Ok(<$data_type>::from_le_bytes(data))
136                }
137
138                pub fn [<emit_ $data_type >](
139                    buf: &mut [u8],
140                    value: $data_type,
141                ) -> Result<(), DecodeError> {
142                    if buf.len() < size_of::<$data_type>() {
143                        return Err(DecodeError::buffer_too_small(
144                            buf.len(),
145                            size_of::<$data_type>(),
146                        ));
147                    }
148                    buf[..size_of::<$data_type>()].copy_from_slice(
149                        &value.to_ne_bytes()
150                    );
151                    Ok(())
152                }
153
154                pub fn [<emit_ $data_type _le>](
155                    buf: &mut [u8],
156                    value: $data_type,
157                ) -> Result<(), DecodeError> {
158                    if buf.len() < size_of::<$data_type>() {
159                        return Err(DecodeError::buffer_too_small(
160                            buf.len(),
161                            size_of::<$data_type>(),
162                        ));
163                    }
164                    buf[..size_of::<$data_type>()].copy_from_slice(
165                        &value.to_le_bytes()
166                    );
167                    Ok(())
168                }
169
170                pub fn [<emit_ $data_type _be>](
171                    buf: &mut [u8],
172                    value: $data_type,
173                ) -> Result<(), DecodeError> {
174                    if buf.len() < size_of::<$data_type>() {
175                        return Err(DecodeError::buffer_too_small(
176                            buf.len(),
177                            size_of::<$data_type>(),
178                        ));
179                    }
180                    buf[..size_of::<$data_type>()].copy_from_slice(
181                        &value.to_be_bytes()
182                    );
183                    Ok(())
184                }
185            }
186        )+
187    }
188}
189
190gen_int_parser!(u16, u32, u64, u128, i16, i32, i64, i128,);