1use crate::network::{ipv4::IPv4Reader, ipv6::IPv6Reader};
2use core::fmt::{self};
3
4#[derive(Debug)]
6pub enum IpInIp<'a> {
7 Ipv4(IPv4Reader<'a>),
8 Ipv6(IPv6Reader<'a>),
9}
10
11#[repr(u16)]
15#[derive(Debug, PartialEq)]
16pub enum EtherType {
17 Arp = 0x0806,
18 Ipv4 = 0x0800,
19 Ipv6 = 0x86dd,
20 Unknown(u16),
21}
22
23impl From<u16> for EtherType {
24 fn from(value: u16) -> Self {
25 match value {
26 0x0800 => EtherType::Ipv4,
27 0x0806 => EtherType::Arp,
28 0x86DD => EtherType::Ipv6,
29 other => EtherType::Unknown(other),
30 }
31 }
32}
33
34#[repr(u8)]
38#[derive(Debug, PartialEq)]
39pub enum IpProtocol {
40 Icmpv4 = 1,
41 Ipv4 = 4,
42 Tcp = 6,
43 Udp = 17,
44 Ipv6 = 41,
45 Icmpv6 = 58,
46 NoNextHeader = 59,
47 Unknown(u8),
48}
49
50impl From<u8> for IpProtocol {
51 fn from(value: u8) -> Self {
52 match value {
53 1 => IpProtocol::Icmpv4,
54 4 => IpProtocol::Ipv4,
55 6 => IpProtocol::Tcp,
56 17 => IpProtocol::Udp,
57 41 => IpProtocol::Ipv6,
58 58 => IpProtocol::Icmpv6,
59 59 => IpProtocol::NoNextHeader,
60 other => IpProtocol::Unknown(other),
61 }
62 }
63}
64
65#[repr(u8)]
67#[derive(Debug, PartialEq)]
68pub enum Icmpv4Type {
69 EchoReply = 0,
70 DestUnreachable = 3,
71 SourceQuench = 4,
72 Redirect = 5,
73 EchoRequest = 8,
74 RouterAdvertisement = 9,
75 RouterSelection = 10,
76 TimeExceeded = 11,
77 ParameterProblem = 12,
78 Timestamp = 13,
79 TimestampReply = 14,
80 InformationRequest = 15,
81 InformationReply = 16,
82 AddressMaskRequest = 17,
83 AddressMaskReply = 18,
84 Traceroute = 30,
85 Photuris = 40,
86 ExtendedEchoRequest = 42,
87 ExtendedEchoReply = 43,
88 Experimental1 = 253,
89 Experimental2 = 254,
90 Unknown,
91}
92
93impl From<u8> for Icmpv4Type {
94 fn from(value: u8) -> Self {
95 match value {
96 0 => Icmpv4Type::EchoReply,
97 3 => Icmpv4Type::DestUnreachable,
98 4 => Icmpv4Type::SourceQuench,
99 5 => Icmpv4Type::Redirect,
100 8 => Icmpv4Type::EchoRequest,
101 9 => Icmpv4Type::RouterAdvertisement,
102 10 => Icmpv4Type::RouterSelection,
103 11 => Icmpv4Type::TimeExceeded,
104 12 => Icmpv4Type::ParameterProblem,
105 13 => Icmpv4Type::Timestamp,
106 14 => Icmpv4Type::TimestampReply,
107 15 => Icmpv4Type::InformationRequest,
108 16 => Icmpv4Type::InformationReply,
109 17 => Icmpv4Type::AddressMaskRequest,
110 18 => Icmpv4Type::AddressMaskReply,
111 30 => Icmpv4Type::Traceroute,
112 40 => Icmpv4Type::Photuris,
113 42 => Icmpv4Type::ExtendedEchoRequest,
114 43 => Icmpv4Type::ExtendedEchoReply,
115 253 => Icmpv4Type::Experimental1,
116 254 => Icmpv4Type::Experimental2,
117 _ => Icmpv4Type::Unknown,
118 }
119 }
120}
121
122#[repr(u8)]
124#[derive(Debug, PartialEq)]
125pub enum Icmpv6Type {
126 DestUnreachable = 1,
127 PacketTooBig = 2,
128 TimeExceeded = 3,
129 ParameterProblem = 4,
130 Experimental1 = 100,
131 Experimental2 = 101,
132 EchoRequest = 128,
133 EchoReply = 129,
134 MldQuery = 130,
135 MldReport = 131,
136 MldDone = 132,
137 RouterSolicitation = 133,
138 RouterAdvertisement = 134,
139 NeighborSolicitation = 135,
140 NeighborAdvertisement = 136,
141 Redirect = 137,
142 RouterRenumbering = 138,
143 IcmpNodeInformationQuery = 139,
144 IcmpNodeInformationResponse = 140,
145 InverseNeighborDiscoverySolicitation = 141,
146 InverseNeighborDiscoveryAdvertisement = 142,
147 Mld2Report = 143,
148 HomeAgentAddressDiscoveryRequest = 144,
149 HomeAgentAddressDiscoveryReply = 145,
150 MobilePrefixSolicitation = 146,
151 MobilePrefixAdvertisement = 147,
152 CertificationPathSolicitation = 148,
153 CertificationPathAdvertisement = 149,
154 ExperimentalMobilityProtocols = 150,
155 MulticastRouterAdvertisement = 151,
156 MulticastRouterSolicitation = 152,
157 MulticastRouterTermination = 153,
158 RplControlMessage = 155,
159 Experimental3 = 200,
160 Experimental4 = 201,
161 Unknown,
162}
163
164impl From<u8> for Icmpv6Type {
165 fn from(value: u8) -> Self {
166 match value {
167 1 => Icmpv6Type::DestUnreachable,
168 2 => Icmpv6Type::PacketTooBig,
169 3 => Icmpv6Type::TimeExceeded,
170 4 => Icmpv6Type::ParameterProblem,
171 100 => Icmpv6Type::Experimental1,
172 101 => Icmpv6Type::Experimental2,
173 128 => Icmpv6Type::EchoRequest,
174 129 => Icmpv6Type::EchoReply,
175 130 => Icmpv6Type::MldQuery,
176 131 => Icmpv6Type::MldReport,
177 132 => Icmpv6Type::MldDone,
178 133 => Icmpv6Type::RouterSolicitation,
179 134 => Icmpv6Type::RouterAdvertisement,
180 135 => Icmpv6Type::NeighborSolicitation,
181 136 => Icmpv6Type::NeighborAdvertisement,
182 137 => Icmpv6Type::Redirect,
183 138 => Icmpv6Type::RouterRenumbering,
184 139 => Icmpv6Type::IcmpNodeInformationQuery,
185 140 => Icmpv6Type::IcmpNodeInformationResponse,
186 141 => Icmpv6Type::InverseNeighborDiscoverySolicitation,
187 142 => Icmpv6Type::InverseNeighborDiscoveryAdvertisement,
188 143 => Icmpv6Type::Mld2Report,
189 144 => Icmpv6Type::HomeAgentAddressDiscoveryRequest,
190 145 => Icmpv6Type::HomeAgentAddressDiscoveryReply,
191 146 => Icmpv6Type::MobilePrefixSolicitation,
192 147 => Icmpv6Type::MobilePrefixAdvertisement,
193 148 => Icmpv6Type::CertificationPathSolicitation,
194 149 => Icmpv6Type::CertificationPathAdvertisement,
195 150 => Icmpv6Type::ExperimentalMobilityProtocols,
196 151 => Icmpv6Type::MulticastRouterAdvertisement,
197 152 => Icmpv6Type::MulticastRouterSolicitation,
198 153 => Icmpv6Type::MulticastRouterTermination,
199 155 => Icmpv6Type::RplControlMessage,
200 200 => Icmpv6Type::Experimental3,
201 201 => Icmpv6Type::Experimental4,
202 _ => Icmpv6Type::Unknown,
203 }
204 }
205}
206
207#[repr(u8)]
211pub enum NextHeader {
212 HopByHop = 0,
213 Icmp = 1,
214 Tcp = 6,
215 Udp = 17,
216 Routing = 43,
217 Fragment = 44,
218 Esp = 50,
219 AuthHeader = 51,
220 NoNextHeader = 59,
221 Destination = 60,
222 Mobility = 135,
223 Unknown,
224}
225
226impl From<u8> for NextHeader {
227 fn from(value: u8) -> Self {
228 match value {
229 0 => NextHeader::HopByHop,
230 43 => NextHeader::Routing,
231 44 => NextHeader::Fragment,
232 50 => NextHeader::Esp,
233 51 => NextHeader::AuthHeader,
234 59 => NextHeader::NoNextHeader,
235 60 => NextHeader::Destination,
236 135 => NextHeader::Mobility,
237 _ => NextHeader::Unknown,
238 }
239 }
240}
241
242#[inline]
244pub fn bytes_to_mac(bytes: &[u8], buffer: &mut [u8]) -> usize {
245 const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
246
247 let mut buffer_index = 0;
248 for (i, &byte) in bytes.iter().enumerate() {
249 if i != 0 {
250 buffer[buffer_index] = b':';
251 buffer_index += 1;
252 }
253
254 buffer[buffer_index] = HEX_CHARS[(byte >> 4) as usize];
255 buffer[buffer_index + 1] = HEX_CHARS[(byte & 0xf) as usize];
256 buffer_index += 2;
257 }
258
259 buffer_index
260}
261
262#[inline]
264pub fn bytes_to_ipv6(bytes: &[u8], buffer: &mut [u8]) -> usize {
265 const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
266
267 let mut buffer_index = 0;
268 for (i, &byte) in bytes.iter().enumerate() {
269 if i % 2 == 0 && i != 0 {
270 buffer[buffer_index] = b':';
271 buffer_index += 1;
272 }
273
274 buffer[buffer_index] = HEX_CHARS[(byte >> 4) as usize];
275 buffer[buffer_index + 1] = HEX_CHARS[(byte & 0xf) as usize];
276 buffer_index += 2;
277 }
278
279 buffer_index
280}
281
282pub struct IpFormatter<'a>(pub &'a [u8]);
284
285impl fmt::Debug for IpFormatter<'_> {
286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287 let ip = self.0;
288 write!(f, "{}.{}.{}.{}", ip[0], ip[1], ip[2], ip[3])
289 }
290}