1#[allow(unused_imports)]
10use alloc::vec::Vec;
11use core::cmp::PartialEq;
12use core::convert::Infallible as Never;
13use core::fmt::{Debug, Display};
14use core::hash::Hash;
15
16use net_types::ip::{GenericOverIp, Ip, IpAddr, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
17use packet::{BufferViewMut, PacketBuilder, ParsablePacket, ParseMetadata, PartialPacketBuilder};
18use zerocopy::{
19 FromBytes, Immutable, IntoBytes, KnownLayout, SplitByteSlice, SplitByteSliceMut, Unaligned,
20};
21
22use crate::error::{IpParseResult, Ipv6ParseError, ParseError};
23use crate::ethernet::EthernetIpExt;
24use crate::icmp::IcmpIpExt;
25use crate::ipv4::{IPV4_MIN_HDR_LEN, Ipv4Header, Ipv4Packet, Ipv4PacketBuilder, Ipv4PacketRaw};
26use crate::ipv6::{IPV6_FIXED_HDR_LEN, Ipv6Header, Ipv6Packet, Ipv6PacketBuilder, Ipv6PacketRaw};
27use crate::private::Sealed;
28
29pub trait IpProtoExt: Ip {
32 type Proto: IpProtocol
36 + GenericOverIp<Self, Type = Self::Proto>
37 + GenericOverIp<Ipv4, Type = Ipv4Proto>
38 + GenericOverIp<Ipv6, Type = Ipv6Proto>
39 + Copy
40 + Clone
41 + Hash
42 + Debug
43 + Display
44 + PartialEq
45 + Eq
46 + PartialOrd
47 + Ord;
48}
49
50impl IpProtoExt for Ipv4 {
51 type Proto = Ipv4Proto;
52}
53
54impl IpProtoExt for Ipv6 {
55 type Proto = Ipv6Proto;
56}
57
58pub trait IpExt: EthernetIpExt + IcmpIpExt {
61 type PacketParseError: From<ParseError> + Debug + PartialEq + Send + Sync;
63
64 type Packet<B: SplitByteSlice>: IpPacket<B, Self, Builder = Self::PacketBuilder>
66 + GenericOverIp<Self, Type = Self::Packet<B>>
67 + GenericOverIp<Ipv4, Type = Ipv4Packet<B>>
68 + GenericOverIp<Ipv6, Type = Ipv6Packet<B>>;
69 type PacketRaw<B: SplitByteSlice>: IpPacketRaw<B, Self>
71 + GenericOverIp<Self, Type = Self::PacketRaw<B>>
72 + GenericOverIp<Ipv4, Type = Ipv4PacketRaw<B>>
73 + GenericOverIp<Ipv6, Type = Ipv6PacketRaw<B>>;
74 type PacketBuilder: IpPacketBuilder<Self> + Eq;
76 const MIN_HEADER_LENGTH: usize;
78}
79
80impl IpExt for Ipv4 {
81 type PacketParseError = ParseError;
82 type Packet<B: SplitByteSlice> = Ipv4Packet<B>;
83 type PacketRaw<B: SplitByteSlice> = Ipv4PacketRaw<B>;
84 type PacketBuilder = Ipv4PacketBuilder;
85
86 const MIN_HEADER_LENGTH: usize = IPV4_MIN_HDR_LEN;
87}
88
89impl IpExt for Ipv6 {
90 type PacketParseError = Ipv6ParseError;
91 type Packet<B: SplitByteSlice> = Ipv6Packet<B>;
92 type PacketRaw<B: SplitByteSlice> = Ipv6PacketRaw<B>;
93 type PacketBuilder = Ipv6PacketBuilder;
94
95 const MIN_HEADER_LENGTH: usize = IPV6_FIXED_HDR_LEN;
96}
97
98#[derive(Debug)]
100pub enum Nat64Error {
101 NotImplemented,
103}
104
105#[derive(Debug)]
107pub enum Nat64TranslationResult<S, E> {
108 Forward(S),
110 Drop,
112 Err(E),
114}
115
116#[derive(
121 Default,
122 Debug,
123 Clone,
124 Copy,
125 PartialEq,
126 Eq,
127 KnownLayout,
128 FromBytes,
129 IntoBytes,
130 Immutable,
131 Unaligned,
132)]
133#[repr(C)]
134pub struct DscpAndEcn(u8);
135
136const DSCP_OFFSET: u8 = 2;
137const DSCP_MAX: u8 = (1 << (8 - DSCP_OFFSET)) - 1;
138const ECN_MAX: u8 = (1 << DSCP_OFFSET) - 1;
139
140impl DscpAndEcn {
141 pub const fn default() -> Self {
144 Self(0)
145 }
146
147 pub const fn new(dscp: u8, ecn: u8) -> Self {
150 debug_assert!(dscp <= DSCP_MAX);
151 debug_assert!(ecn <= ECN_MAX);
152 Self((dscp << DSCP_OFFSET) + ecn)
153 }
154
155 pub const fn new_with_raw(value: u8) -> Self {
158 Self(value)
159 }
160
161 pub fn dscp(self) -> u8 {
163 let Self(v) = self;
164 v >> 2
165 }
166
167 pub fn ecn(self) -> u8 {
169 let Self(v) = self;
170 v & 0x3
171 }
172
173 pub fn raw(self) -> u8 {
175 let Self(value) = self;
176 value
177 }
178}
179
180impl From<u8> for DscpAndEcn {
181 fn from(value: u8) -> Self {
182 Self::new_with_raw(value)
183 }
184}
185
186pub trait IpPacket<B: SplitByteSlice, I: IpExt>:
190 Sized + Debug + ParsablePacket<B, (), Error = I::PacketParseError>
191{
192 type Builder: IpPacketBuilder<I>;
194
195 fn src_ip(&self) -> I::Addr;
197
198 fn dst_ip(&self) -> I::Addr;
200
201 fn proto(&self) -> I::Proto;
203
204 fn ttl(&self) -> u8;
206
207 fn dscp_and_ecn(&self) -> DscpAndEcn;
210
211 fn set_ttl(&mut self, ttl: u8)
215 where
216 B: SplitByteSliceMut;
217
218 fn body(&self) -> &[u8];
220
221 fn into_metadata(self) -> (I::Addr, I::Addr, I::Proto, ParseMetadata) {
226 let src_ip = self.src_ip();
227 let dst_ip = self.dst_ip();
228 let proto = self.proto();
229 let meta = self.parse_metadata();
230 (src_ip, dst_ip, proto, meta)
231 }
232
233 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Ipv6Packet<B>>;
235
236 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
242 buffer: BV,
243 header: Vec<u8>,
244 body_fragments: IT,
245 ) -> IpParseResult<I, ()>
246 where
247 B: SplitByteSliceMut;
248
249 fn to_vec(&self) -> Vec<u8>;
251
252 fn builder(&self) -> Self::Builder;
254}
255
256impl<B: SplitByteSlice> IpPacket<B, Ipv4> for Ipv4Packet<B> {
257 type Builder = Ipv4PacketBuilder;
258
259 fn src_ip(&self) -> Ipv4Addr {
260 Ipv4Header::src_ip(self)
261 }
262 fn dst_ip(&self) -> Ipv4Addr {
263 Ipv4Header::dst_ip(self)
264 }
265 fn proto(&self) -> Ipv4Proto {
266 Ipv4Header::proto(self)
267 }
268 fn dscp_and_ecn(&self) -> DscpAndEcn {
269 Ipv4Header::dscp_and_ecn(self)
270 }
271 fn ttl(&self) -> u8 {
272 Ipv4Header::ttl(self)
273 }
274 fn set_ttl(&mut self, ttl: u8)
275 where
276 B: SplitByteSliceMut,
277 {
278 Ipv4Packet::set_ttl(self, ttl)
279 }
280 fn body(&self) -> &[u8] {
281 Ipv4Packet::body(self)
282 }
283
284 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Self, &'_ Ipv6Packet<B>> {
285 IpAddr::V4(self)
286 }
287
288 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
289 buffer: BV,
290 header: Vec<u8>,
291 body_fragments: IT,
292 ) -> IpParseResult<Ipv4, ()>
293 where
294 B: SplitByteSliceMut,
295 {
296 crate::ipv4::reassemble_fragmented_packet(buffer, header, body_fragments)
297 }
298
299 fn to_vec(&self) -> Vec<u8> {
300 self.to_vec()
301 }
302
303 fn builder(&self) -> Self::Builder {
304 Ipv4Header::builder(self)
305 }
306}
307
308impl<B: SplitByteSlice> IpPacket<B, Ipv6> for Ipv6Packet<B> {
309 type Builder = Ipv6PacketBuilder;
310
311 fn src_ip(&self) -> Ipv6Addr {
312 Ipv6Header::src_ip(self)
313 }
314 fn dst_ip(&self) -> Ipv6Addr {
315 Ipv6Header::dst_ip(self)
316 }
317 fn proto(&self) -> Ipv6Proto {
318 Ipv6Packet::proto(self)
319 }
320 fn dscp_and_ecn(&self) -> DscpAndEcn {
321 Ipv6Header::dscp_and_ecn(self)
322 }
323 fn ttl(&self) -> u8 {
324 Ipv6Header::hop_limit(self)
325 }
326 fn set_ttl(&mut self, ttl: u8)
327 where
328 B: SplitByteSliceMut,
329 {
330 Ipv6Packet::set_hop_limit(self, ttl)
331 }
332 fn body(&self) -> &[u8] {
333 Ipv6Packet::body(self)
334 }
335
336 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Self> {
337 IpAddr::V6(self)
338 }
339 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
340 buffer: BV,
341 header: Vec<u8>,
342 body_fragments: IT,
343 ) -> IpParseResult<Ipv6, ()>
344 where
345 B: SplitByteSliceMut,
346 {
347 crate::ipv6::reassemble_fragmented_packet(buffer, header, body_fragments)
348 }
349
350 fn to_vec(&self) -> Vec<u8> {
351 self.to_vec()
352 }
353
354 fn builder(&self) -> Self::Builder {
355 self.builder()
356 }
357}
358
359pub trait IpPacketRaw<B: SplitByteSlice, I: IpExt>:
363 Sized + ParsablePacket<B, (), Error = I::PacketParseError>
364{
365}
366
367impl<B: SplitByteSlice> IpPacketRaw<B, Ipv4> for Ipv4PacketRaw<B> {}
368impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv4PacketRaw<B> {
369 type Type = <I as IpExt>::PacketRaw<B>;
370}
371
372impl<B: SplitByteSlice> IpPacketRaw<B, Ipv6> for Ipv6PacketRaw<B> {}
373impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6PacketRaw<B> {
374 type Type = <I as IpExt>::PacketRaw<B>;
375}
376
377pub trait IpPacketBuilder<I: IpExt>: PacketBuilder + PartialPacketBuilder + Clone + Debug {
379 fn new(src_ip: I::Addr, dst_ip: I::Addr, ttl: u8, proto: I::Proto) -> Self;
383
384 fn src_ip(&self) -> I::Addr;
386
387 fn set_src_ip(&mut self, addr: I::Addr);
389
390 fn dst_ip(&self) -> I::Addr;
392
393 fn set_dst_ip(&mut self, addr: I::Addr);
395
396 fn proto(&self) -> I::Proto;
398
399 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn);
401}
402
403pub trait IpProtocol: From<IpProto> + From<u8> + Sealed + Send + Sync + 'static {}
405
406impl Sealed for Never {}
407
408create_protocol_enum!(
409 #[allow(missing_docs)]
418 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
419 pub enum IpProto: u8 {
420 Tcp, 6, "TCP";
421 Udp, 17, "UDP";
422 Reserved, 255, "IANA-RESERVED";
423 }
424);
425
426create_protocol_enum!(
427 #[allow(missing_docs)]
433 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
434 pub enum Ipv4Proto: u8 {
435 Icmp, 1, "ICMP";
436 Igmp, 2, "IGMP";
437 + Proto(IpProto);
438 _, "IPv4 protocol {}";
439 }
440);
441
442impl IpProtocol for Ipv4Proto {}
443impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv4Proto {
444 type Type = I::Proto;
445}
446impl Sealed for Ipv4Proto {}
447
448create_protocol_enum!(
449 #[allow(missing_docs)]
455 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
456 pub enum Ipv6Proto: u8 {
457 Icmpv6, 58, "ICMPv6";
458 NoNextHeader, 59, "NO NEXT HEADER";
459 + Proto(IpProto);
460 _, "IPv6 protocol {}";
461 }
462);
463
464impl IpProtocol for Ipv6Proto {}
465impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv6Proto {
466 type Type = I::Proto;
467}
468impl Sealed for Ipv6Proto {}
469
470create_protocol_enum!(
471 #[allow(missing_docs)]
477 #[derive(Copy, Clone, Hash, Eq, PartialEq)]
478 pub enum Ipv6ExtHdrType: u8 {
479 HopByHopOptions, 0, "IPv6 HOP-BY-HOP OPTIONS HEADER";
480 Routing, 43, "IPv6 ROUTING HEADER";
481 Fragment, 44, "IPv6 FRAGMENT HEADER";
482 EncapsulatingSecurityPayload, 50, "ENCAPSULATING SECURITY PAYLOAD";
483 Authentication, 51, "AUTHENTICATION HEADER";
484 DestinationOptions, 60, "IPv6 DESTINATION OPTIONS HEADER";
485 _, "IPv6 EXTENSION HEADER {}";
486 }
487);
488
489#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Copy, Clone)]
500pub struct FragmentOffset(u16);
501
502impl FragmentOffset {
503 pub const ZERO: FragmentOffset = FragmentOffset(0);
505
506 pub const fn new(offset: u16) -> Option<Self> {
510 if offset < 1 << 13 { Some(Self(offset)) } else { None }
511 }
512
513 pub(crate) fn new_with_lsb(offset: u16) -> Self {
516 Self(offset & 0x1FFF)
517 }
518
519 pub(crate) fn new_with_msb(offset: u16) -> Self {
522 Self(offset >> 3)
523 }
524
525 pub const fn new_with_bytes(offset_bytes: u16) -> Option<Self> {
529 if offset_bytes & 0x7 == 0 {
530 Some(Self(offset_bytes >> 3))
532 } else {
533 None
534 }
535 }
536
537 pub const fn into_raw(self) -> u16 {
539 self.0
540 }
541
542 pub fn into_bytes(self) -> u16 {
547 self.0 << 3
550 }
551}
552
553#[cfg(test)]
554mod tests {
555 use super::*;
556
557 #[test]
558 fn fragment_offset_raw() {
559 assert_eq!(FragmentOffset::new(1), Some(FragmentOffset(1)));
560 assert_eq!(FragmentOffset::new(1 << 13), None);
561 }
562
563 #[test]
564 fn fragment_offset_bytes() {
565 assert_eq!(FragmentOffset::new_with_bytes(0), Some(FragmentOffset(0)));
566 for i in 1..=7 {
567 assert_eq!(FragmentOffset::new_with_bytes(i), None);
568 }
569 assert_eq!(FragmentOffset::new_with_bytes(8), Some(FragmentOffset(1)));
570 assert_eq!(FragmentOffset::new_with_bytes(core::u16::MAX), None);
571 assert_eq!(
572 FragmentOffset::new_with_bytes(core::u16::MAX & !0x7),
573 Some(FragmentOffset((1 << 13) - 1)),
574 );
575 }
576}