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() { IPV4_ADDR_LEN } else { IPV6_ADDR_LEN }
62}
63
64pub(crate) fn emit_ip_addr(addr: &IpAddr, buffer: &mut [u8]) {
65    match addr {
66        IpAddr::V4(ip) => buffer.copy_from_slice(&ip.octets()),
67        IpAddr::V6(ip) => buffer.copy_from_slice(&ip.octets()),
68    }
69}
70
71// These is defined by Assigned Internet Protocol Numbers, no need to use libc
72// as they are supposed to identical between all operating system.
73const IPPROTO_HOPOPTS: i32 = 0;
74const IPPROTO_ICMP: i32 = 1;
75const IPPROTO_IGMP: i32 = 2;
76const IPPROTO_IPIP: i32 = 4;
77const IPPROTO_TCP: i32 = 6;
78const IPPROTO_EGP: i32 = 8;
79const IPPROTO_PUP: i32 = 12;
80const IPPROTO_UDP: i32 = 17;
81const IPPROTO_IDP: i32 = 22;
82const IPPROTO_TP: i32 = 29;
83const IPPROTO_DCCP: i32 = 33;
84const IPPROTO_IPV6: i32 = 41;
85const IPPROTO_RSVP: i32 = 46;
86const IPPROTO_GRE: i32 = 47;
87const IPPROTO_ESP: i32 = 50;
88const IPPROTO_AH: i32 = 51;
89const IPPROTO_MTP: i32 = 92;
90const IPPROTO_BEETPH: i32 = 94;
91const IPPROTO_ENCAP: i32 = 98;
92const IPPROTO_PIM: i32 = 103;
93const IPPROTO_COMP: i32 = 108;
94const IPPROTO_L2TP: i32 = 115;
95const IPPROTO_SCTP: i32 = 132;
96const IPPROTO_UDPLITE: i32 = 136;
97const IPPROTO_MPLS: i32 = 137;
98const IPPROTO_ETHERNET: i32 = 143;
99const IPPROTO_RAW: i32 = 255;
100const IPPROTO_MPTCP: i32 = 262;
101
102#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
103#[non_exhaustive]
104pub enum IpProtocol {
105    Hopopts,
106    Icmp,
107    Igmp,
108    Ipip,
109    Tcp,
110    Egp,
111    Pup,
112    Udp,
113    Idp,
114    Tp,
115    Dccp,
116    Ipv6,
117    Rsvp,
118    Gre,
119    Esp,
120    Ah,
121    Mtp,
122    Beetph,
123    Encap,
124    Pim,
125    Comp,
126    L2tp,
127    Sctp,
128    Udplite,
129    Mpls,
130    Ethernet,
131    #[default]
132    Raw,
133    Mptcp,
134    Other(i32),
135}
136
137impl From<i32> for IpProtocol {
138    fn from(d: i32) -> Self {
139        match d {
140            IPPROTO_HOPOPTS => Self::Hopopts,
141            IPPROTO_ICMP => Self::Icmp,
142            IPPROTO_IGMP => Self::Igmp,
143            IPPROTO_IPIP => Self::Ipip,
144            IPPROTO_TCP => Self::Tcp,
145            IPPROTO_EGP => Self::Egp,
146            IPPROTO_PUP => Self::Pup,
147            IPPROTO_UDP => Self::Udp,
148            IPPROTO_IDP => Self::Idp,
149            IPPROTO_TP => Self::Tp,
150            IPPROTO_DCCP => Self::Dccp,
151            IPPROTO_IPV6 => Self::Ipv6,
152            IPPROTO_RSVP => Self::Rsvp,
153            IPPROTO_GRE => Self::Gre,
154            IPPROTO_ESP => Self::Esp,
155            IPPROTO_AH => Self::Ah,
156            IPPROTO_MTP => Self::Mtp,
157            IPPROTO_BEETPH => Self::Beetph,
158            IPPROTO_ENCAP => Self::Encap,
159            IPPROTO_PIM => Self::Pim,
160            IPPROTO_COMP => Self::Comp,
161            IPPROTO_L2TP => Self::L2tp,
162            IPPROTO_SCTP => Self::Sctp,
163            IPPROTO_UDPLITE => Self::Udplite,
164            IPPROTO_MPLS => Self::Mpls,
165            IPPROTO_ETHERNET => Self::Ethernet,
166            IPPROTO_RAW => Self::Raw,
167            IPPROTO_MPTCP => Self::Mptcp,
168            _ => Self::Other(d),
169        }
170    }
171}
172
173impl From<IpProtocol> for i32 {
174    fn from(v: IpProtocol) -> i32 {
175        match v {
176            IpProtocol::Hopopts => IPPROTO_HOPOPTS,
177            IpProtocol::Icmp => IPPROTO_ICMP,
178            IpProtocol::Igmp => IPPROTO_IGMP,
179            IpProtocol::Ipip => IPPROTO_IPIP,
180            IpProtocol::Tcp => IPPROTO_TCP,
181            IpProtocol::Egp => IPPROTO_EGP,
182            IpProtocol::Pup => IPPROTO_PUP,
183            IpProtocol::Udp => IPPROTO_UDP,
184            IpProtocol::Idp => IPPROTO_IDP,
185            IpProtocol::Tp => IPPROTO_TP,
186            IpProtocol::Dccp => IPPROTO_DCCP,
187            IpProtocol::Ipv6 => IPPROTO_IPV6,
188            IpProtocol::Rsvp => IPPROTO_RSVP,
189            IpProtocol::Gre => IPPROTO_GRE,
190            IpProtocol::Esp => IPPROTO_ESP,
191            IpProtocol::Ah => IPPROTO_AH,
192            IpProtocol::Mtp => IPPROTO_MTP,
193            IpProtocol::Beetph => IPPROTO_BEETPH,
194            IpProtocol::Encap => IPPROTO_ENCAP,
195            IpProtocol::Pim => IPPROTO_PIM,
196            IpProtocol::Comp => IPPROTO_COMP,
197            IpProtocol::L2tp => IPPROTO_L2TP,
198            IpProtocol::Sctp => IPPROTO_SCTP,
199            IpProtocol::Udplite => IPPROTO_UDPLITE,
200            IpProtocol::Mpls => IPPROTO_MPLS,
201            IpProtocol::Ethernet => IPPROTO_ETHERNET,
202            IpProtocol::Raw => IPPROTO_RAW,
203            IpProtocol::Mptcp => IPPROTO_MPTCP,
204            IpProtocol::Other(d) => d,
205        }
206    }
207}