netlink_packet_route/
ip.rs

1// SPDX-License-Identifier: MIT
2
3use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
4
5use netlink_packet_utils::DecodeError;
6
7pub(crate) const IPV4_ADDR_LEN: usize = 4;
8pub(crate) const IPV6_ADDR_LEN: usize = 16;
9
10pub(crate) fn parse_ipv4_addr(raw: &[u8]) -> Result<Ipv4Addr, DecodeError> {
11    if raw.len() == IPV4_ADDR_LEN {
12        Ok(Ipv4Addr::new(raw[0], raw[1], raw[2], raw[3]))
13    } else {
14        Err(DecodeError::from(format!(
15            "Invalid u8 array length {}, expecting \
16            {IPV4_ADDR_LEN} for IPv4 address, got {:?}",
17            raw.len(),
18            raw,
19        )))
20    }
21}
22
23pub(crate) fn parse_ipv6_addr(raw: &[u8]) -> Result<Ipv6Addr, DecodeError> {
24    if raw.len() == IPV6_ADDR_LEN {
25        let mut data = [0u8; IPV6_ADDR_LEN];
26        data.copy_from_slice(raw);
27        Ok(Ipv6Addr::from(data))
28    } else {
29        Err(DecodeError::from(format!(
30            "Invalid u8 array length {}, expecting {IPV6_ADDR_LEN} \
31            for IPv6 address, got {:?}",
32            raw.len(),
33            raw,
34        )))
35    }
36}
37
38pub(crate) fn emit_ip_to_buffer(ip: &IpAddr, buffer: &mut [u8]) {
39    match ip {
40        IpAddr::V4(ip) => buffer.copy_from_slice(&ip.octets()),
41        IpAddr::V6(ip) => buffer.copy_from_slice(&ip.octets()),
42    }
43}
44
45pub(crate) fn parse_ip_addr(raw: &[u8]) -> Result<IpAddr, DecodeError> {
46    if raw.len() == IPV6_ADDR_LEN {
47        parse_ipv6_addr(raw).map(IpAddr::from)
48    } else if raw.len() == IPV4_ADDR_LEN {
49        parse_ipv4_addr(raw).map(IpAddr::from)
50    } else {
51        Err(DecodeError::from(format!(
52            "Invalid u8 array length {}, expecting {IPV6_ADDR_LEN} \
53            for IPv6 address or {IPV4_ADDR_LEN} for IPv4 address, got {:?}",
54            raw.len(),
55            raw,
56        )))
57    }
58}
59
60pub(crate) fn ip_addr_len(addr: &IpAddr) -> usize {
61    if addr.is_ipv4() {
62        IPV4_ADDR_LEN
63    } else {
64        IPV6_ADDR_LEN
65    }
66}
67
68pub(crate) fn emit_ip_addr(addr: &IpAddr, buffer: &mut [u8]) {
69    match addr {
70        IpAddr::V4(ip) => buffer.copy_from_slice(&ip.octets()),
71        IpAddr::V6(ip) => buffer.copy_from_slice(&ip.octets()),
72    }
73}
74
75// These is defined by Assigned Internet Protocol Numbers, no need to use libc
76// as they are supposed to identical between all operating system.
77const IPPROTO_HOPOPTS: i32 = 0;
78const IPPROTO_ICMP: i32 = 1;
79const IPPROTO_IGMP: i32 = 2;
80const IPPROTO_IPIP: i32 = 4;
81const IPPROTO_TCP: i32 = 6;
82const IPPROTO_EGP: i32 = 8;
83const IPPROTO_PUP: i32 = 12;
84const IPPROTO_UDP: i32 = 17;
85const IPPROTO_IDP: i32 = 22;
86const IPPROTO_TP: i32 = 29;
87const IPPROTO_DCCP: i32 = 33;
88const IPPROTO_IPV6: i32 = 41;
89const IPPROTO_RSVP: i32 = 46;
90const IPPROTO_GRE: i32 = 47;
91const IPPROTO_ESP: i32 = 50;
92const IPPROTO_AH: i32 = 51;
93const IPPROTO_MTP: i32 = 92;
94const IPPROTO_BEETPH: i32 = 94;
95const IPPROTO_ENCAP: i32 = 98;
96const IPPROTO_PIM: i32 = 103;
97const IPPROTO_COMP: i32 = 108;
98const IPPROTO_L2TP: i32 = 115;
99const IPPROTO_SCTP: i32 = 132;
100const IPPROTO_UDPLITE: i32 = 136;
101const IPPROTO_MPLS: i32 = 137;
102const IPPROTO_ETHERNET: i32 = 143;
103const IPPROTO_RAW: i32 = 255;
104const IPPROTO_MPTCP: i32 = 262;
105
106#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
107#[non_exhaustive]
108pub enum IpProtocol {
109    Hopopts,
110    Icmp,
111    Igmp,
112    Ipip,
113    Tcp,
114    Egp,
115    Pup,
116    Udp,
117    Idp,
118    Tp,
119    Dccp,
120    Ipv6,
121    Rsvp,
122    Gre,
123    Esp,
124    Ah,
125    Mtp,
126    Beetph,
127    Encap,
128    Pim,
129    Comp,
130    L2tp,
131    Sctp,
132    Udplite,
133    Mpls,
134    Ethernet,
135    #[default]
136    Raw,
137    Mptcp,
138    Other(i32),
139}
140
141impl From<i32> for IpProtocol {
142    fn from(d: i32) -> Self {
143        match d {
144            IPPROTO_HOPOPTS => Self::Hopopts,
145            IPPROTO_ICMP => Self::Icmp,
146            IPPROTO_IGMP => Self::Igmp,
147            IPPROTO_IPIP => Self::Ipip,
148            IPPROTO_TCP => Self::Tcp,
149            IPPROTO_EGP => Self::Egp,
150            IPPROTO_PUP => Self::Pup,
151            IPPROTO_UDP => Self::Udp,
152            IPPROTO_IDP => Self::Idp,
153            IPPROTO_TP => Self::Tp,
154            IPPROTO_DCCP => Self::Dccp,
155            IPPROTO_IPV6 => Self::Ipv6,
156            IPPROTO_RSVP => Self::Rsvp,
157            IPPROTO_GRE => Self::Gre,
158            IPPROTO_ESP => Self::Esp,
159            IPPROTO_AH => Self::Ah,
160            IPPROTO_MTP => Self::Mtp,
161            IPPROTO_BEETPH => Self::Beetph,
162            IPPROTO_ENCAP => Self::Encap,
163            IPPROTO_PIM => Self::Pim,
164            IPPROTO_COMP => Self::Comp,
165            IPPROTO_L2TP => Self::L2tp,
166            IPPROTO_SCTP => Self::Sctp,
167            IPPROTO_UDPLITE => Self::Udplite,
168            IPPROTO_MPLS => Self::Mpls,
169            IPPROTO_ETHERNET => Self::Ethernet,
170            IPPROTO_RAW => Self::Raw,
171            IPPROTO_MPTCP => Self::Mptcp,
172            _ => Self::Other(d),
173        }
174    }
175}
176
177impl From<IpProtocol> for i32 {
178    fn from(v: IpProtocol) -> i32 {
179        match v {
180            IpProtocol::Hopopts => IPPROTO_HOPOPTS,
181            IpProtocol::Icmp => IPPROTO_ICMP,
182            IpProtocol::Igmp => IPPROTO_IGMP,
183            IpProtocol::Ipip => IPPROTO_IPIP,
184            IpProtocol::Tcp => IPPROTO_TCP,
185            IpProtocol::Egp => IPPROTO_EGP,
186            IpProtocol::Pup => IPPROTO_PUP,
187            IpProtocol::Udp => IPPROTO_UDP,
188            IpProtocol::Idp => IPPROTO_IDP,
189            IpProtocol::Tp => IPPROTO_TP,
190            IpProtocol::Dccp => IPPROTO_DCCP,
191            IpProtocol::Ipv6 => IPPROTO_IPV6,
192            IpProtocol::Rsvp => IPPROTO_RSVP,
193            IpProtocol::Gre => IPPROTO_GRE,
194            IpProtocol::Esp => IPPROTO_ESP,
195            IpProtocol::Ah => IPPROTO_AH,
196            IpProtocol::Mtp => IPPROTO_MTP,
197            IpProtocol::Beetph => IPPROTO_BEETPH,
198            IpProtocol::Encap => IPPROTO_ENCAP,
199            IpProtocol::Pim => IPPROTO_PIM,
200            IpProtocol::Comp => IPPROTO_COMP,
201            IpProtocol::L2tp => IPPROTO_L2TP,
202            IpProtocol::Sctp => IPPROTO_SCTP,
203            IpProtocol::Udplite => IPPROTO_UDPLITE,
204            IpProtocol::Mpls => IPPROTO_MPLS,
205            IpProtocol::Ethernet => IPPROTO_ETHERNET,
206            IpProtocol::Raw => IPPROTO_RAW,
207            IpProtocol::Mptcp => IPPROTO_MPTCP,
208            IpProtocol::Other(d) => d,
209        }
210    }
211}