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};
18use zerocopy::{
19 FromBytes, Immutable, IntoBytes, KnownLayout, SplitByteSlice, SplitByteSliceMut, Unaligned,
20};
21
22use crate::error::{IpParseError, IpParseResult};
23use crate::ethernet::EthernetIpExt;
24use crate::icmp::IcmpIpExt;
25use crate::ipv4::{Ipv4Header, Ipv4OnlyMeta, Ipv4Packet, Ipv4PacketBuilder, Ipv4PacketRaw};
26use crate::ipv6::{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 Packet<B: SplitByteSlice>: IpPacket<B, Self, Builder = Self::PacketBuilder>
63 + GenericOverIp<Self, Type = Self::Packet<B>>
64 + GenericOverIp<Ipv4, Type = Ipv4Packet<B>>
65 + GenericOverIp<Ipv6, Type = Ipv6Packet<B>>;
66 type PacketRaw<B: SplitByteSlice>: IpPacketRaw<B, Self>
68 + GenericOverIp<Self, Type = Self::PacketRaw<B>>
69 + GenericOverIp<Ipv4, Type = Ipv4PacketRaw<B>>
70 + GenericOverIp<Ipv6, Type = Ipv6PacketRaw<B>>;
71 type PacketBuilder: IpPacketBuilder<Self> + Eq;
73}
74
75impl IpExt for Ipv4 {
76 type Packet<B: SplitByteSlice> = Ipv4Packet<B>;
77 type PacketRaw<B: SplitByteSlice> = Ipv4PacketRaw<B>;
78 type PacketBuilder = Ipv4PacketBuilder;
79}
80
81impl IpExt for Ipv6 {
82 type Packet<B: SplitByteSlice> = Ipv6Packet<B>;
83 type PacketRaw<B: SplitByteSlice> = Ipv6PacketRaw<B>;
84 type PacketBuilder = Ipv6PacketBuilder;
85}
86
87#[derive(Debug)]
89pub enum Nat64Error {
90 NotImplemented,
92}
93
94#[derive(Debug)]
96pub enum Nat64TranslationResult<S, E> {
97 Forward(S),
99 Drop,
101 Err(E),
103}
104
105#[derive(
110 Default,
111 Debug,
112 Clone,
113 Copy,
114 PartialEq,
115 Eq,
116 KnownLayout,
117 FromBytes,
118 IntoBytes,
119 Immutable,
120 Unaligned,
121)]
122#[repr(C)]
123pub struct DscpAndEcn(u8);
124
125const DSCP_OFFSET: u8 = 2;
126const DSCP_MAX: u8 = (1 << (8 - DSCP_OFFSET)) - 1;
127const ECN_MAX: u8 = (1 << DSCP_OFFSET) - 1;
128
129impl DscpAndEcn {
130 pub const fn default() -> Self {
133 Self(0)
134 }
135
136 pub const fn new(dscp: u8, ecn: u8) -> Self {
139 debug_assert!(dscp <= DSCP_MAX);
140 debug_assert!(ecn <= ECN_MAX);
141 Self((dscp << DSCP_OFFSET) + ecn)
142 }
143
144 pub const fn new_with_raw(value: u8) -> Self {
147 Self(value)
148 }
149
150 pub fn dscp(self) -> u8 {
152 let Self(v) = self;
153 v >> 2
154 }
155
156 pub fn ecn(self) -> u8 {
158 let Self(v) = self;
159 v & 0x3
160 }
161
162 pub fn raw(self) -> u8 {
164 let Self(value) = self;
165 value
166 }
167}
168
169impl From<u8> for DscpAndEcn {
170 fn from(value: u8) -> Self {
171 Self::new_with_raw(value)
172 }
173}
174
175pub trait IpPacket<B: SplitByteSlice, I: IpExt>:
179 Sized + Debug + ParsablePacket<B, (), Error = IpParseError<I>>
180{
181 type Builder: IpPacketBuilder<I>;
183
184 type VersionSpecificMeta;
187
188 fn src_ip(&self) -> I::Addr;
190
191 fn dst_ip(&self) -> I::Addr;
193
194 fn proto(&self) -> I::Proto;
196
197 fn ttl(&self) -> u8;
199
200 fn dscp_and_ecn(&self) -> DscpAndEcn;
203
204 fn set_ttl(&mut self, ttl: u8)
208 where
209 B: SplitByteSliceMut;
210
211 fn body(&self) -> &[u8];
213
214 fn version_specific_meta(&self) -> Self::VersionSpecificMeta;
216
217 fn into_metadata(self) -> (I::Addr, I::Addr, I::Proto, ParseMetadata) {
222 let src_ip = self.src_ip();
223 let dst_ip = self.dst_ip();
224 let proto = self.proto();
225 let meta = self.parse_metadata();
226 (src_ip, dst_ip, proto, meta)
227 }
228
229 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Ipv6Packet<B>>;
231
232 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
234 buffer: BV,
235 header: Vec<u8>,
236 body_fragments: IT,
237 ) -> IpParseResult<I, ()>
238 where
239 B: SplitByteSliceMut;
240
241 fn to_vec(&self) -> Vec<u8>;
243
244 fn builder(&self) -> Self::Builder;
246}
247
248impl<B: SplitByteSlice> IpPacket<B, Ipv4> for Ipv4Packet<B> {
249 type Builder = Ipv4PacketBuilder;
250 type VersionSpecificMeta = Ipv4OnlyMeta;
251
252 fn src_ip(&self) -> Ipv4Addr {
253 Ipv4Header::src_ip(self)
254 }
255 fn dst_ip(&self) -> Ipv4Addr {
256 Ipv4Header::dst_ip(self)
257 }
258 fn proto(&self) -> Ipv4Proto {
259 Ipv4Header::proto(self)
260 }
261 fn dscp_and_ecn(&self) -> DscpAndEcn {
262 Ipv4Header::dscp_and_ecn(self)
263 }
264 fn ttl(&self) -> u8 {
265 Ipv4Header::ttl(self)
266 }
267 fn set_ttl(&mut self, ttl: u8)
268 where
269 B: SplitByteSliceMut,
270 {
271 Ipv4Packet::set_ttl(self, ttl)
272 }
273 fn body(&self) -> &[u8] {
274 Ipv4Packet::body(self)
275 }
276
277 fn version_specific_meta(&self) -> Ipv4OnlyMeta {
278 Ipv4OnlyMeta { id: Ipv4Header::id(self), fragment_type: Ipv4Header::fragment_type(self) }
279 }
280
281 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Self, &'_ Ipv6Packet<B>> {
282 IpAddr::V4(self)
283 }
284
285 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
286 buffer: BV,
287 header: Vec<u8>,
288 body_fragments: IT,
289 ) -> IpParseResult<Ipv4, ()>
290 where
291 B: SplitByteSliceMut,
292 {
293 crate::ipv4::reassemble_fragmented_packet(buffer, header, body_fragments)
294 }
295
296 fn to_vec(&self) -> Vec<u8> {
297 self.to_vec()
298 }
299
300 fn builder(&self) -> Self::Builder {
301 Ipv4Header::builder(self)
302 }
303}
304
305impl<B: SplitByteSlice> IpPacket<B, Ipv6> for Ipv6Packet<B> {
306 type Builder = Ipv6PacketBuilder;
307 type VersionSpecificMeta = ();
308
309 fn src_ip(&self) -> Ipv6Addr {
310 Ipv6Header::src_ip(self)
311 }
312 fn dst_ip(&self) -> Ipv6Addr {
313 Ipv6Header::dst_ip(self)
314 }
315 fn proto(&self) -> Ipv6Proto {
316 Ipv6Packet::proto(self)
317 }
318 fn dscp_and_ecn(&self) -> DscpAndEcn {
319 Ipv6Header::dscp_and_ecn(self)
320 }
321 fn ttl(&self) -> u8 {
322 Ipv6Header::hop_limit(self)
323 }
324 fn set_ttl(&mut self, ttl: u8)
325 where
326 B: SplitByteSliceMut,
327 {
328 Ipv6Packet::set_hop_limit(self, ttl)
329 }
330 fn body(&self) -> &[u8] {
331 Ipv6Packet::body(self)
332 }
333
334 fn version_specific_meta(&self) -> () {
335 ()
336 }
337 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Self> {
338 IpAddr::V6(self)
339 }
340 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
341 buffer: BV,
342 header: Vec<u8>,
343 body_fragments: IT,
344 ) -> IpParseResult<Ipv6, ()>
345 where
346 B: SplitByteSliceMut,
347 {
348 crate::ipv6::reassemble_fragmented_packet(buffer, header, body_fragments)
349 }
350
351 fn to_vec(&self) -> Vec<u8> {
352 self.to_vec()
353 }
354
355 fn builder(&self) -> Self::Builder {
356 self.builder()
357 }
358}
359
360pub trait IpPacketRaw<B: SplitByteSlice, I: IpExt>:
364 Sized + ParsablePacket<B, (), Error = IpParseError<I>>
365{
366}
367
368impl<B: SplitByteSlice> IpPacketRaw<B, Ipv4> for Ipv4PacketRaw<B> {}
369impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv4PacketRaw<B> {
370 type Type = <I as IpExt>::PacketRaw<B>;
371}
372
373impl<B: SplitByteSlice> IpPacketRaw<B, Ipv6> for Ipv6PacketRaw<B> {}
374impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6PacketRaw<B> {
375 type Type = <I as IpExt>::PacketRaw<B>;
376}
377
378pub trait IpPacketBuilder<I: IpExt>: PacketBuilder + Clone + Debug {
380 fn new(src_ip: I::Addr, dst_ip: I::Addr, ttl: u8, proto: I::Proto) -> Self;
384
385 fn src_ip(&self) -> I::Addr;
387
388 fn set_src_ip(&mut self, addr: I::Addr);
390
391 fn dst_ip(&self) -> I::Addr;
393
394 fn set_dst_ip(&mut self, addr: I::Addr);
396
397 fn proto(&self) -> I::Proto;
399
400 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn);
402}
403
404pub trait IpProtocol: From<IpProto> + From<u8> + Sealed + Send + Sync + 'static {}
406
407impl Sealed for Never {}
408
409create_protocol_enum!(
410 #[allow(missing_docs)]
419 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
420 pub enum IpProto: u8 {
421 Tcp, 6, "TCP";
422 Udp, 17, "UDP";
423 Reserved, 255, "IANA-RESERVED";
424 }
425);
426
427create_protocol_enum!(
428 #[allow(missing_docs)]
434 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
435 pub enum Ipv4Proto: u8 {
436 Icmp, 1, "ICMP";
437 Igmp, 2, "IGMP";
438 + Proto(IpProto);
439 _, "IPv4 protocol {}";
440 }
441);
442
443impl IpProtocol for Ipv4Proto {}
444impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv4Proto {
445 type Type = I::Proto;
446}
447impl Sealed for Ipv4Proto {}
448
449create_protocol_enum!(
450 #[allow(missing_docs)]
456 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
457 pub enum Ipv6Proto: u8 {
458 Icmpv6, 58, "ICMPv6";
459 NoNextHeader, 59, "NO NEXT HEADER";
460 + Proto(IpProto);
461 _, "IPv6 protocol {}";
462 }
463);
464
465impl IpProtocol for Ipv6Proto {}
466impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv6Proto {
467 type Type = I::Proto;
468}
469impl Sealed for Ipv6Proto {}
470
471create_protocol_enum!(
472 #[allow(missing_docs)]
478 #[derive(Copy, Clone, Hash, Eq, PartialEq)]
479 pub enum Ipv6ExtHdrType: u8 {
480 HopByHopOptions, 0, "IPv6 HOP-BY-HOP OPTIONS HEADER";
481 Routing, 43, "IPv6 ROUTING HEADER";
482 Fragment, 44, "IPv6 FRAGMENT HEADER";
483 EncapsulatingSecurityPayload, 50, "ENCAPSULATING SECURITY PAYLOAD";
484 Authentication, 51, "AUTHENTICATION HEADER";
485 DestinationOptions, 60, "IPv6 DESTINATION OPTIONS HEADER";
486 _, "IPv6 EXTENSION HEADER {}";
487 }
488);
489
490#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Copy, Clone)]
501pub struct FragmentOffset(u16);
502
503impl FragmentOffset {
504 pub const ZERO: FragmentOffset = FragmentOffset(0);
506
507 pub const fn new(offset: u16) -> Option<Self> {
511 if offset < 1 << 13 {
512 Some(Self(offset))
513 } else {
514 None
515 }
516 }
517
518 pub(crate) fn new_with_lsb(offset: u16) -> Self {
521 Self(offset & 0x1FFF)
522 }
523
524 pub(crate) fn new_with_msb(offset: u16) -> Self {
527 Self(offset >> 3)
528 }
529
530 pub const fn new_with_bytes(offset_bytes: u16) -> Option<Self> {
534 if offset_bytes & 0x7 == 0 {
535 Some(Self(offset_bytes >> 3))
537 } else {
538 None
539 }
540 }
541
542 pub const fn into_raw(self) -> u16 {
544 self.0
545 }
546
547 pub fn into_bytes(self) -> u16 {
552 self.0 << 3
555 }
556}
557
558#[cfg(test)]
559mod tests {
560 use super::*;
561
562 #[test]
563 fn fragment_offset_raw() {
564 assert_eq!(FragmentOffset::new(1), Some(FragmentOffset(1)));
565 assert_eq!(FragmentOffset::new(1 << 13), None);
566 }
567
568 #[test]
569 fn fragment_offset_bytes() {
570 assert_eq!(FragmentOffset::new_with_bytes(0), Some(FragmentOffset(0)));
571 for i in 1..=7 {
572 assert_eq!(FragmentOffset::new_with_bytes(i), None);
573 }
574 assert_eq!(FragmentOffset::new_with_bytes(8), Some(FragmentOffset(1)));
575 assert_eq!(FragmentOffset::new_with_bytes(core::u16::MAX), None);
576 assert_eq!(
577 FragmentOffset::new_with_bytes(core::u16::MAX & !0x7),
578 Some(FragmentOffset((1 << 13) - 1)),
579 );
580 }
581}