netlink_packet_utils/
parsers.rs

1// SPDX-License-Identifier: MIT
2
3use std::mem::size_of;
4use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
5
6use byteorder::{BigEndian, ByteOrder, NativeEndian};
7
8use crate::DecodeError;
9
10pub fn parse_mac(payload: &[u8]) -> Result<[u8; 6], DecodeError> {
11    if payload.len() != 6 {
12        return Err(DecodeError::InvalidMACAddress);
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::InvalidIPAddress);
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(Ipv4Addr::new(payload[0], payload[1], payload[2], payload[3]).into()),
35        16 => Ok(Ipv6Addr::from([
36            payload[0],
37            payload[1],
38            payload[2],
39            payload[3],
40            payload[4],
41            payload[5],
42            payload[6],
43            payload[7],
44            payload[8],
45            payload[9],
46            payload[10],
47            payload[11],
48            payload[12],
49            payload[13],
50            payload[14],
51            payload[15],
52        ])
53        .into()),
54        _ => Err(DecodeError::InvalidIPAddress),
55    }
56}
57
58pub fn parse_string(payload: &[u8]) -> Result<String, DecodeError> {
59    if payload.is_empty() {
60        return Ok(String::new());
61    }
62    // iproute2 is a bit inconsistent with null-terminated strings.
63    let slice = if payload[payload.len() - 1] == 0 {
64        &payload[..payload.len() - 1]
65    } else {
66        &payload[..payload.len()]
67    };
68    let s = String::from_utf8(slice.to_vec())?;
69    Ok(s)
70}
71
72pub fn parse_u8(payload: &[u8]) -> Result<u8, DecodeError> {
73    if payload.len() != 1 {
74        return Err(DecodeError::InvalidU8);
75    }
76    Ok(payload[0])
77}
78
79pub fn parse_u32(payload: &[u8]) -> Result<u32, DecodeError> {
80    if payload.len() != size_of::<u32>() {
81        return Err(DecodeError::InvalidU32);
82    }
83    Ok(NativeEndian::read_u32(payload))
84}
85
86pub fn parse_u64(payload: &[u8]) -> Result<u64, DecodeError> {
87    if payload.len() != size_of::<u64>() {
88        return Err(DecodeError::InvalidU64);
89    }
90    Ok(NativeEndian::read_u64(payload))
91}
92
93pub fn parse_u128(payload: &[u8]) -> Result<u128, DecodeError> {
94    if payload.len() != size_of::<u128>() {
95        return Err(DecodeError::InvalidU128);
96    }
97    Ok(NativeEndian::read_u128(payload))
98}
99
100pub fn parse_u16(payload: &[u8]) -> Result<u16, DecodeError> {
101    if payload.len() != size_of::<u16>() {
102        return Err(DecodeError::InvalidU16);
103    }
104    Ok(NativeEndian::read_u16(payload))
105}
106
107pub fn parse_i32(payload: &[u8]) -> Result<i32, DecodeError> {
108    if payload.len() != 4 {
109        return Err(DecodeError::InvalidI32);
110    }
111    Ok(NativeEndian::read_i32(payload))
112}
113
114pub fn parse_u16_be(payload: &[u8]) -> Result<u16, DecodeError> {
115    if payload.len() != size_of::<u16>() {
116        return Err(DecodeError::InvalidU16);
117    }
118    Ok(BigEndian::read_u16(payload))
119}
120
121pub fn parse_u32_be(payload: &[u8]) -> Result<u32, DecodeError> {
122    if payload.len() != size_of::<u32>() {
123        return Err(DecodeError::InvalidU32);
124    }
125    Ok(BigEndian::read_u32(payload))
126}