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;
15use core::marker::PhantomData;
16
17use net_types::ip::{GenericOverIp, Ip, IpAddr, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
18use packet::{
19 BufferViewMut, NoOpSerializationContext, PacketBuilder, ParsablePacket, ParseMetadata,
20 PartialPacketBuilder, SerializationContext,
21};
22use zerocopy::{
23 FromBytes, Immutable, IntoBytes, KnownLayout, SplitByteSlice, SplitByteSliceMut, Unaligned,
24};
25
26use crate::error::{IpParseResult, Ipv6ParseError, ParseError};
27use crate::ethernet::EthernetIpExt;
28use crate::icmp::IcmpIpExt;
29use crate::ipv4::{IPV4_MIN_HDR_LEN, Ipv4Header, Ipv4Packet, Ipv4PacketBuilder, Ipv4PacketRaw};
30use crate::ipv6::{IPV6_FIXED_HDR_LEN, Ipv6Header, Ipv6Packet, Ipv6PacketBuilder, Ipv6PacketRaw};
31use crate::private::Sealed;
32
33pub trait IpProtoExt: Ip {
36 type Proto: IpProtocol
40 + GenericOverIp<Self, Type = Self::Proto>
41 + GenericOverIp<Ipv4, Type = Ipv4Proto>
42 + GenericOverIp<Ipv6, Type = Ipv6Proto>
43 + Copy
44 + Clone
45 + Hash
46 + Debug
47 + Display
48 + PartialEq
49 + Eq
50 + PartialOrd
51 + Ord;
52}
53
54impl IpProtoExt for Ipv4 {
55 type Proto = Ipv4Proto;
56}
57
58impl IpProtoExt for Ipv6 {
59 type Proto = Ipv6Proto;
60}
61
62pub struct IpEnvelope<I: IpExt> {
64 _marker: PhantomData<I>,
65}
66
67impl<I: IpExt> IpEnvelope<I> {
68 pub fn new() -> Self {
70 Self { _marker: PhantomData }
71 }
72}
73
74pub trait IpSerializationContext<I: IpExt>: SerializationContext {
76 fn envelope_to_state(envelope: IpEnvelope<I>) -> Self::ContextState;
78}
79
80impl<I: IpExt> IpSerializationContext<I> for NoOpSerializationContext {
81 fn envelope_to_state(_envelope: IpEnvelope<I>) -> Self::ContextState {
82 ()
83 }
84}
85
86pub trait IpExt: EthernetIpExt + IcmpIpExt {
89 type PacketParseError: From<ParseError> + Debug + PartialEq + Send + Sync;
91
92 type Packet<B: SplitByteSlice>: IpPacket<B, Self>
94 + GenericOverIp<Self, Type = Self::Packet<B>>
95 + GenericOverIp<Ipv4, Type = Ipv4Packet<B>>
96 + GenericOverIp<Ipv6, Type = Ipv6Packet<B>>;
97 type PacketRaw<B: SplitByteSlice>: IpPacketRaw<B, Self>
99 + GenericOverIp<Self, Type = Self::PacketRaw<B>>
100 + GenericOverIp<Ipv4, Type = Ipv4PacketRaw<B>>
101 + GenericOverIp<Ipv6, Type = Ipv6PacketRaw<B>>;
102 type PacketBuilder<C: IpSerializationContext<Self>>: IpPacketBuilder<C, Self> + Eq;
104 const MIN_HEADER_LENGTH: usize;
106}
107
108impl IpExt for Ipv4 {
109 type PacketParseError = ParseError;
110 type Packet<B: SplitByteSlice> = Ipv4Packet<B>;
111 type PacketRaw<B: SplitByteSlice> = Ipv4PacketRaw<B>;
112 type PacketBuilder<C: IpSerializationContext<Self>> = Ipv4PacketBuilder;
113
114 const MIN_HEADER_LENGTH: usize = IPV4_MIN_HDR_LEN;
115}
116
117impl IpExt for Ipv6 {
118 type PacketParseError = Ipv6ParseError;
119 type Packet<B: SplitByteSlice> = Ipv6Packet<B>;
120 type PacketRaw<B: SplitByteSlice> = Ipv6PacketRaw<B>;
121 type PacketBuilder<C: IpSerializationContext<Self>> = Ipv6PacketBuilder;
122
123 const MIN_HEADER_LENGTH: usize = IPV6_FIXED_HDR_LEN;
124}
125
126#[derive(Debug)]
128pub enum Nat64Error {
129 NotImplemented,
131}
132
133#[derive(Debug)]
135pub enum Nat64TranslationResult<S, E> {
136 Forward(S),
138 Drop,
140 Err(E),
142}
143
144#[derive(
149 Default,
150 Debug,
151 Clone,
152 Copy,
153 PartialEq,
154 Eq,
155 KnownLayout,
156 FromBytes,
157 IntoBytes,
158 Immutable,
159 Unaligned,
160)]
161#[repr(C)]
162pub struct DscpAndEcn(u8);
163
164const DSCP_OFFSET: u8 = 2;
165const DSCP_MAX: u8 = (1 << (8 - DSCP_OFFSET)) - 1;
166const ECN_MAX: u8 = (1 << DSCP_OFFSET) - 1;
167
168impl DscpAndEcn {
169 pub const fn default() -> Self {
172 Self(0)
173 }
174
175 pub const fn new(dscp: u8, ecn: u8) -> Self {
178 debug_assert!(dscp <= DSCP_MAX);
179 debug_assert!(ecn <= ECN_MAX);
180 Self((dscp << DSCP_OFFSET) + ecn)
181 }
182
183 pub const fn new_with_raw(value: u8) -> Self {
186 Self(value)
187 }
188
189 pub fn dscp(self) -> u8 {
191 let Self(v) = self;
192 v >> 2
193 }
194
195 pub fn ecn(self) -> u8 {
197 let Self(v) = self;
198 v & 0x3
199 }
200
201 pub fn raw(self) -> u8 {
203 let Self(value) = self;
204 value
205 }
206}
207
208impl From<u8> for DscpAndEcn {
209 fn from(value: u8) -> Self {
210 Self::new_with_raw(value)
211 }
212}
213
214pub trait IpPacket<B: SplitByteSlice, I: IpExt>:
218 Sized + Debug + ParsablePacket<B, (), Error = I::PacketParseError>
219{
220 type Builder<C: IpSerializationContext<I>>: IpPacketBuilder<C, I>;
222
223 fn src_ip(&self) -> I::Addr;
225
226 fn dst_ip(&self) -> I::Addr;
228
229 fn proto(&self) -> I::Proto;
231
232 fn ttl(&self) -> u8;
234
235 fn dscp_and_ecn(&self) -> DscpAndEcn;
238
239 fn set_ttl(&mut self, ttl: u8)
243 where
244 B: SplitByteSliceMut;
245
246 fn body(&self) -> &[u8];
248
249 fn into_metadata(self) -> (I::Addr, I::Addr, I::Proto, ParseMetadata) {
254 let src_ip = self.src_ip();
255 let dst_ip = self.dst_ip();
256 let proto = self.proto();
257 let meta = self.parse_metadata();
258 (src_ip, dst_ip, proto, meta)
259 }
260
261 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Ipv6Packet<B>>;
263
264 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
270 buffer: BV,
271 header: Vec<u8>,
272 body_fragments: IT,
273 ) -> IpParseResult<I, ()>
274 where
275 B: SplitByteSliceMut;
276
277 fn to_vec(&self) -> Vec<u8>;
279
280 fn builder<C: IpSerializationContext<I>>(&self) -> Self::Builder<C>;
282}
283
284impl<B: SplitByteSlice> IpPacket<B, Ipv4> for Ipv4Packet<B> {
285 type Builder<C: IpSerializationContext<Ipv4>> = Ipv4PacketBuilder;
286
287 fn src_ip(&self) -> Ipv4Addr {
288 Ipv4Header::src_ip(self)
289 }
290 fn dst_ip(&self) -> Ipv4Addr {
291 Ipv4Header::dst_ip(self)
292 }
293 fn proto(&self) -> Ipv4Proto {
294 Ipv4Header::proto(self)
295 }
296 fn dscp_and_ecn(&self) -> DscpAndEcn {
297 Ipv4Header::dscp_and_ecn(self)
298 }
299 fn ttl(&self) -> u8 {
300 Ipv4Header::ttl(self)
301 }
302 fn set_ttl(&mut self, ttl: u8)
303 where
304 B: SplitByteSliceMut,
305 {
306 Ipv4Packet::set_ttl(self, ttl)
307 }
308 fn body(&self) -> &[u8] {
309 Ipv4Packet::body(self)
310 }
311
312 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Self, &'_ Ipv6Packet<B>> {
313 IpAddr::V4(self)
314 }
315
316 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
317 buffer: BV,
318 header: Vec<u8>,
319 body_fragments: IT,
320 ) -> IpParseResult<Ipv4, ()>
321 where
322 B: SplitByteSliceMut,
323 {
324 crate::ipv4::reassemble_fragmented_packet(buffer, header, body_fragments)
325 }
326
327 fn to_vec(&self) -> Vec<u8> {
328 self.to_vec()
329 }
330
331 fn builder<C: IpSerializationContext<Ipv4>>(&self) -> Self::Builder<C> {
332 Ipv4Header::builder(self)
333 }
334}
335
336impl<B: SplitByteSlice> IpPacket<B, Ipv6> for Ipv6Packet<B> {
337 type Builder<C: IpSerializationContext<Ipv6>> = Ipv6PacketBuilder;
338
339 fn src_ip(&self) -> Ipv6Addr {
340 Ipv6Header::src_ip(self)
341 }
342 fn dst_ip(&self) -> Ipv6Addr {
343 Ipv6Header::dst_ip(self)
344 }
345 fn proto(&self) -> Ipv6Proto {
346 Ipv6Packet::proto(self)
347 }
348 fn dscp_and_ecn(&self) -> DscpAndEcn {
349 Ipv6Header::dscp_and_ecn(self)
350 }
351 fn ttl(&self) -> u8 {
352 Ipv6Header::hop_limit(self)
353 }
354 fn set_ttl(&mut self, ttl: u8)
355 where
356 B: SplitByteSliceMut,
357 {
358 Ipv6Packet::set_hop_limit(self, ttl)
359 }
360 fn body(&self) -> &[u8] {
361 Ipv6Packet::body(self)
362 }
363
364 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Self> {
365 IpAddr::V6(self)
366 }
367 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
368 buffer: BV,
369 header: Vec<u8>,
370 body_fragments: IT,
371 ) -> IpParseResult<Ipv6, ()>
372 where
373 B: SplitByteSliceMut,
374 {
375 crate::ipv6::reassemble_fragmented_packet(buffer, header, body_fragments)
376 }
377
378 fn to_vec(&self) -> Vec<u8> {
379 self.to_vec()
380 }
381
382 fn builder<C: IpSerializationContext<Ipv6>>(&self) -> Self::Builder<C> {
383 self.builder()
384 }
385}
386
387pub trait IpPacketRaw<B: SplitByteSlice, I: IpExt>:
391 Sized + ParsablePacket<B, (), Error = I::PacketParseError>
392{
393}
394
395impl<B: SplitByteSlice> IpPacketRaw<B, Ipv4> for Ipv4PacketRaw<B> {}
396impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv4PacketRaw<B> {
397 type Type = <I as IpExt>::PacketRaw<B>;
398}
399
400impl<B: SplitByteSlice> IpPacketRaw<B, Ipv6> for Ipv6PacketRaw<B> {}
401impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6PacketRaw<B> {
402 type Type = <I as IpExt>::PacketRaw<B>;
403}
404
405pub trait IpPacketBuilder<C: SerializationContext, I: IpExt>:
407 PacketBuilder<C> + PartialPacketBuilder<C> + Clone + Debug
408{
409 fn new(src_ip: I::Addr, dst_ip: I::Addr, ttl: u8, proto: I::Proto) -> Self;
413
414 fn src_ip(&self) -> I::Addr;
416
417 fn set_src_ip(&mut self, addr: I::Addr);
419
420 fn dst_ip(&self) -> I::Addr;
422
423 fn set_dst_ip(&mut self, addr: I::Addr);
425
426 fn proto(&self) -> I::Proto;
428
429 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn);
431}
432
433pub trait IpProtocol: From<IpProto> + From<u8> + Sealed + Send + Sync + 'static {}
435
436impl Sealed for Never {}
437
438create_protocol_enum!(
439 #[allow(missing_docs)]
448 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
449 pub enum IpProto: u8 {
450 Tcp, 6, "TCP";
451 Udp, 17, "UDP";
452 Reserved, 255, "IANA-RESERVED";
453 }
454);
455
456create_protocol_enum!(
457 #[allow(missing_docs)]
463 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
464 pub enum Ipv4Proto: u8 {
465 Icmp, 1, "ICMP";
466 Igmp, 2, "IGMP";
467 + Proto(IpProto);
468 _, "IPv4 protocol {}";
469 }
470);
471
472impl IpProtocol for Ipv4Proto {}
473impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv4Proto {
474 type Type = I::Proto;
475}
476impl Sealed for Ipv4Proto {}
477
478create_protocol_enum!(
479 #[allow(missing_docs)]
485 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
486 pub enum Ipv6Proto: u8 {
487 Icmpv6, 58, "ICMPv6";
488 NoNextHeader, 59, "NO NEXT HEADER";
489 + Proto(IpProto);
490 _, "IPv6 protocol {}";
491 }
492);
493
494impl IpProtocol for Ipv6Proto {}
495impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv6Proto {
496 type Type = I::Proto;
497}
498impl Sealed for Ipv6Proto {}
499
500create_protocol_enum!(
501 #[allow(missing_docs)]
507 #[derive(Copy, Clone, Hash, Eq, PartialEq)]
508 pub enum Ipv6ExtHdrType: u8 {
509 HopByHopOptions, 0, "IPv6 HOP-BY-HOP OPTIONS HEADER";
510 Routing, 43, "IPv6 ROUTING HEADER";
511 Fragment, 44, "IPv6 FRAGMENT HEADER";
512 EncapsulatingSecurityPayload, 50, "ENCAPSULATING SECURITY PAYLOAD";
513 Authentication, 51, "AUTHENTICATION HEADER";
514 DestinationOptions, 60, "IPv6 DESTINATION OPTIONS HEADER";
515 _, "IPv6 EXTENSION HEADER {}";
516 }
517);
518
519#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Copy, Clone)]
530pub struct FragmentOffset(u16);
531
532impl FragmentOffset {
533 pub const ZERO: FragmentOffset = FragmentOffset(0);
535
536 pub const fn new(offset: u16) -> Option<Self> {
540 if offset < 1 << 13 { Some(Self(offset)) } else { None }
541 }
542
543 pub(crate) fn new_with_lsb(offset: u16) -> Self {
546 Self(offset & 0x1FFF)
547 }
548
549 pub(crate) fn new_with_msb(offset: u16) -> Self {
552 Self(offset >> 3)
553 }
554
555 pub const fn new_with_bytes(offset_bytes: u16) -> Option<Self> {
559 if offset_bytes & 0x7 == 0 {
560 Some(Self(offset_bytes >> 3))
562 } else {
563 None
564 }
565 }
566
567 pub const fn into_raw(self) -> u16 {
569 self.0
570 }
571
572 pub fn into_bytes(self) -> u16 {
577 self.0 << 3
580 }
581}
582
583#[cfg(test)]
584mod tests {
585 use super::*;
586
587 #[test]
588 fn fragment_offset_raw() {
589 assert_eq!(FragmentOffset::new(1), Some(FragmentOffset(1)));
590 assert_eq!(FragmentOffset::new(1 << 13), None);
591 }
592
593 #[test]
594 fn fragment_offset_bytes() {
595 assert_eq!(FragmentOffset::new_with_bytes(0), Some(FragmentOffset(0)));
596 for i in 1..=7 {
597 assert_eq!(FragmentOffset::new_with_bytes(i), None);
598 }
599 assert_eq!(FragmentOffset::new_with_bytes(8), Some(FragmentOffset(1)));
600 assert_eq!(FragmentOffset::new_with_bytes(core::u16::MAX), None);
601 assert_eq!(
602 FragmentOffset::new_with_bytes(core::u16::MAX & !0x7),
603 Some(FragmentOffset((1 << 13) - 1)),
604 );
605 }
606}