netlink_packet_utils/
parsers.rs

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