1use 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
71const 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}