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::{IpParseError, IpParseResult};
23use crate::ethernet::EthernetIpExt;
24use crate::icmp::IcmpIpExt;
25use crate::ipv4::{
26 Ipv4Header, Ipv4OnlyMeta, Ipv4Packet, Ipv4PacketBuilder, Ipv4PacketRaw, IPV4_MIN_HDR_LEN,
27};
28use crate::ipv6::{Ipv6Header, Ipv6Packet, Ipv6PacketBuilder, Ipv6PacketRaw, IPV6_FIXED_HDR_LEN};
29use crate::private::Sealed;
30
31pub trait IpProtoExt: Ip {
34 type Proto: IpProtocol
38 + GenericOverIp<Self, Type = Self::Proto>
39 + GenericOverIp<Ipv4, Type = Ipv4Proto>
40 + GenericOverIp<Ipv6, Type = Ipv6Proto>
41 + Copy
42 + Clone
43 + Hash
44 + Debug
45 + Display
46 + PartialEq
47 + Eq
48 + PartialOrd
49 + Ord;
50}
51
52impl IpProtoExt for Ipv4 {
53 type Proto = Ipv4Proto;
54}
55
56impl IpProtoExt for Ipv6 {
57 type Proto = Ipv6Proto;
58}
59
60pub trait IpExt: EthernetIpExt + IcmpIpExt {
63 type Packet<B: SplitByteSlice>: IpPacket<B, Self, Builder = Self::PacketBuilder>
65 + GenericOverIp<Self, Type = Self::Packet<B>>
66 + GenericOverIp<Ipv4, Type = Ipv4Packet<B>>
67 + GenericOverIp<Ipv6, Type = Ipv6Packet<B>>;
68 type PacketRaw<B: SplitByteSlice>: IpPacketRaw<B, Self>
70 + GenericOverIp<Self, Type = Self::PacketRaw<B>>
71 + GenericOverIp<Ipv4, Type = Ipv4PacketRaw<B>>
72 + GenericOverIp<Ipv6, Type = Ipv6PacketRaw<B>>;
73 type PacketBuilder: IpPacketBuilder<Self> + Eq;
75 const MIN_HEADER_LENGTH: usize;
77}
78
79impl IpExt for Ipv4 {
80 type Packet<B: SplitByteSlice> = Ipv4Packet<B>;
81 type PacketRaw<B: SplitByteSlice> = Ipv4PacketRaw<B>;
82 type PacketBuilder = Ipv4PacketBuilder;
83
84 const MIN_HEADER_LENGTH: usize = IPV4_MIN_HDR_LEN;
85}
86
87impl IpExt for Ipv6 {
88 type Packet<B: SplitByteSlice> = Ipv6Packet<B>;
89 type PacketRaw<B: SplitByteSlice> = Ipv6PacketRaw<B>;
90 type PacketBuilder = Ipv6PacketBuilder;
91
92 const MIN_HEADER_LENGTH: usize = IPV6_FIXED_HDR_LEN;
93}
94
95#[derive(Debug)]
97pub enum Nat64Error {
98 NotImplemented,
100}
101
102#[derive(Debug)]
104pub enum Nat64TranslationResult<S, E> {
105 Forward(S),
107 Drop,
109 Err(E),
111}
112
113#[derive(
118 Default,
119 Debug,
120 Clone,
121 Copy,
122 PartialEq,
123 Eq,
124 KnownLayout,
125 FromBytes,
126 IntoBytes,
127 Immutable,
128 Unaligned,
129)]
130#[repr(C)]
131pub struct DscpAndEcn(u8);
132
133const DSCP_OFFSET: u8 = 2;
134const DSCP_MAX: u8 = (1 << (8 - DSCP_OFFSET)) - 1;
135const ECN_MAX: u8 = (1 << DSCP_OFFSET) - 1;
136
137impl DscpAndEcn {
138 pub const fn default() -> Self {
141 Self(0)
142 }
143
144 pub const fn new(dscp: u8, ecn: u8) -> Self {
147 debug_assert!(dscp <= DSCP_MAX);
148 debug_assert!(ecn <= ECN_MAX);
149 Self((dscp << DSCP_OFFSET) + ecn)
150 }
151
152 pub const fn new_with_raw(value: u8) -> Self {
155 Self(value)
156 }
157
158 pub fn dscp(self) -> u8 {
160 let Self(v) = self;
161 v >> 2
162 }
163
164 pub fn ecn(self) -> u8 {
166 let Self(v) = self;
167 v & 0x3
168 }
169
170 pub fn raw(self) -> u8 {
172 let Self(value) = self;
173 value
174 }
175}
176
177impl From<u8> for DscpAndEcn {
178 fn from(value: u8) -> Self {
179 Self::new_with_raw(value)
180 }
181}
182
183pub trait IpPacket<B: SplitByteSlice, I: IpExt>:
187 Sized + Debug + ParsablePacket<B, (), Error = IpParseError<I>>
188{
189 type Builder: IpPacketBuilder<I>;
191
192 type VersionSpecificMeta;
195
196 fn src_ip(&self) -> I::Addr;
198
199 fn dst_ip(&self) -> I::Addr;
201
202 fn proto(&self) -> I::Proto;
204
205 fn ttl(&self) -> u8;
207
208 fn dscp_and_ecn(&self) -> DscpAndEcn;
211
212 fn set_ttl(&mut self, ttl: u8)
216 where
217 B: SplitByteSliceMut;
218
219 fn body(&self) -> &[u8];
221
222 fn version_specific_meta(&self) -> Self::VersionSpecificMeta;
224
225 fn into_metadata(self) -> (I::Addr, I::Addr, I::Proto, ParseMetadata) {
230 let src_ip = self.src_ip();
231 let dst_ip = self.dst_ip();
232 let proto = self.proto();
233 let meta = self.parse_metadata();
234 (src_ip, dst_ip, proto, meta)
235 }
236
237 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Ipv6Packet<B>>;
239
240 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 type VersionSpecificMeta = Ipv4OnlyMeta;
259
260 fn src_ip(&self) -> Ipv4Addr {
261 Ipv4Header::src_ip(self)
262 }
263 fn dst_ip(&self) -> Ipv4Addr {
264 Ipv4Header::dst_ip(self)
265 }
266 fn proto(&self) -> Ipv4Proto {
267 Ipv4Header::proto(self)
268 }
269 fn dscp_and_ecn(&self) -> DscpAndEcn {
270 Ipv4Header::dscp_and_ecn(self)
271 }
272 fn ttl(&self) -> u8 {
273 Ipv4Header::ttl(self)
274 }
275 fn set_ttl(&mut self, ttl: u8)
276 where
277 B: SplitByteSliceMut,
278 {
279 Ipv4Packet::set_ttl(self, ttl)
280 }
281 fn body(&self) -> &[u8] {
282 Ipv4Packet::body(self)
283 }
284
285 fn version_specific_meta(&self) -> Ipv4OnlyMeta {
286 Ipv4OnlyMeta { id: Ipv4Header::id(self), fragment_type: Ipv4Header::fragment_type(self) }
287 }
288
289 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Self, &'_ Ipv6Packet<B>> {
290 IpAddr::V4(self)
291 }
292
293 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
294 buffer: BV,
295 header: Vec<u8>,
296 body_fragments: IT,
297 ) -> IpParseResult<Ipv4, ()>
298 where
299 B: SplitByteSliceMut,
300 {
301 crate::ipv4::reassemble_fragmented_packet(buffer, header, body_fragments)
302 }
303
304 fn to_vec(&self) -> Vec<u8> {
305 self.to_vec()
306 }
307
308 fn builder(&self) -> Self::Builder {
309 Ipv4Header::builder(self)
310 }
311}
312
313impl<B: SplitByteSlice> IpPacket<B, Ipv6> for Ipv6Packet<B> {
314 type Builder = Ipv6PacketBuilder;
315 type VersionSpecificMeta = ();
316
317 fn src_ip(&self) -> Ipv6Addr {
318 Ipv6Header::src_ip(self)
319 }
320 fn dst_ip(&self) -> Ipv6Addr {
321 Ipv6Header::dst_ip(self)
322 }
323 fn proto(&self) -> Ipv6Proto {
324 Ipv6Packet::proto(self)
325 }
326 fn dscp_and_ecn(&self) -> DscpAndEcn {
327 Ipv6Header::dscp_and_ecn(self)
328 }
329 fn ttl(&self) -> u8 {
330 Ipv6Header::hop_limit(self)
331 }
332 fn set_ttl(&mut self, ttl: u8)
333 where
334 B: SplitByteSliceMut,
335 {
336 Ipv6Packet::set_hop_limit(self, ttl)
337 }
338 fn body(&self) -> &[u8] {
339 Ipv6Packet::body(self)
340 }
341
342 fn version_specific_meta(&self) -> () {
343 ()
344 }
345 fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Self> {
346 IpAddr::V6(self)
347 }
348 fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
349 buffer: BV,
350 header: Vec<u8>,
351 body_fragments: IT,
352 ) -> IpParseResult<Ipv6, ()>
353 where
354 B: SplitByteSliceMut,
355 {
356 crate::ipv6::reassemble_fragmented_packet(buffer, header, body_fragments)
357 }
358
359 fn to_vec(&self) -> Vec<u8> {
360 self.to_vec()
361 }
362
363 fn builder(&self) -> Self::Builder {
364 self.builder()
365 }
366}
367
368pub trait IpPacketRaw<B: SplitByteSlice, I: IpExt>:
372 Sized + ParsablePacket<B, (), Error = IpParseError<I>>
373{
374}
375
376impl<B: SplitByteSlice> IpPacketRaw<B, Ipv4> for Ipv4PacketRaw<B> {}
377impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv4PacketRaw<B> {
378 type Type = <I as IpExt>::PacketRaw<B>;
379}
380
381impl<B: SplitByteSlice> IpPacketRaw<B, Ipv6> for Ipv6PacketRaw<B> {}
382impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv6PacketRaw<B> {
383 type Type = <I as IpExt>::PacketRaw<B>;
384}
385
386pub trait IpPacketBuilder<I: IpExt>: PacketBuilder + PartialPacketBuilder + Clone + Debug {
388 fn new(src_ip: I::Addr, dst_ip: I::Addr, ttl: u8, proto: I::Proto) -> Self;
392
393 fn src_ip(&self) -> I::Addr;
395
396 fn set_src_ip(&mut self, addr: I::Addr);
398
399 fn dst_ip(&self) -> I::Addr;
401
402 fn set_dst_ip(&mut self, addr: I::Addr);
404
405 fn proto(&self) -> I::Proto;
407
408 fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn);
410}
411
412pub trait IpProtocol: From<IpProto> + From<u8> + Sealed + Send + Sync + 'static {}
414
415impl Sealed for Never {}
416
417create_protocol_enum!(
418 #[allow(missing_docs)]
427 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
428 pub enum IpProto: u8 {
429 Tcp, 6, "TCP";
430 Udp, 17, "UDP";
431 Reserved, 255, "IANA-RESERVED";
432 }
433);
434
435create_protocol_enum!(
436 #[allow(missing_docs)]
442 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
443 pub enum Ipv4Proto: u8 {
444 Icmp, 1, "ICMP";
445 Igmp, 2, "IGMP";
446 + Proto(IpProto);
447 _, "IPv4 protocol {}";
448 }
449);
450
451impl IpProtocol for Ipv4Proto {}
452impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv4Proto {
453 type Type = I::Proto;
454}
455impl Sealed for Ipv4Proto {}
456
457create_protocol_enum!(
458 #[allow(missing_docs)]
464 #[derive(Copy, Clone, Hash, Eq, Ord, PartialEq, PartialOrd)]
465 pub enum Ipv6Proto: u8 {
466 Icmpv6, 58, "ICMPv6";
467 NoNextHeader, 59, "NO NEXT HEADER";
468 + Proto(IpProto);
469 _, "IPv6 protocol {}";
470 }
471);
472
473impl IpProtocol for Ipv6Proto {}
474impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv6Proto {
475 type Type = I::Proto;
476}
477impl Sealed for Ipv6Proto {}
478
479create_protocol_enum!(
480 #[allow(missing_docs)]
486 #[derive(Copy, Clone, Hash, Eq, PartialEq)]
487 pub enum Ipv6ExtHdrType: u8 {
488 HopByHopOptions, 0, "IPv6 HOP-BY-HOP OPTIONS HEADER";
489 Routing, 43, "IPv6 ROUTING HEADER";
490 Fragment, 44, "IPv6 FRAGMENT HEADER";
491 EncapsulatingSecurityPayload, 50, "ENCAPSULATING SECURITY PAYLOAD";
492 Authentication, 51, "AUTHENTICATION HEADER";
493 DestinationOptions, 60, "IPv6 DESTINATION OPTIONS HEADER";
494 _, "IPv6 EXTENSION HEADER {}";
495 }
496);
497
498#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Copy, Clone)]
509pub struct FragmentOffset(u16);
510
511impl FragmentOffset {
512 pub const ZERO: FragmentOffset = FragmentOffset(0);
514
515 pub const fn new(offset: u16) -> Option<Self> {
519 if offset < 1 << 13 {
520 Some(Self(offset))
521 } else {
522 None
523 }
524 }
525
526 pub(crate) fn new_with_lsb(offset: u16) -> Self {
529 Self(offset & 0x1FFF)
530 }
531
532 pub(crate) fn new_with_msb(offset: u16) -> Self {
535 Self(offset >> 3)
536 }
537
538 pub const fn new_with_bytes(offset_bytes: u16) -> Option<Self> {
542 if offset_bytes & 0x7 == 0 {
543 Some(Self(offset_bytes >> 3))
545 } else {
546 None
547 }
548 }
549
550 pub const fn into_raw(self) -> u16 {
552 self.0
553 }
554
555 pub fn into_bytes(self) -> u16 {
560 self.0 << 3
563 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569
570 #[test]
571 fn fragment_offset_raw() {
572 assert_eq!(FragmentOffset::new(1), Some(FragmentOffset(1)));
573 assert_eq!(FragmentOffset::new(1 << 13), None);
574 }
575
576 #[test]
577 fn fragment_offset_bytes() {
578 assert_eq!(FragmentOffset::new_with_bytes(0), Some(FragmentOffset(0)));
579 for i in 1..=7 {
580 assert_eq!(FragmentOffset::new_with_bytes(i), None);
581 }
582 assert_eq!(FragmentOffset::new_with_bytes(8), Some(FragmentOffset(1)));
583 assert_eq!(FragmentOffset::new_with_bytes(core::u16::MAX), None);
584 assert_eq!(
585 FragmentOffset::new_with_bytes(core::u16::MAX & !0x7),
586 Some(FragmentOffset((1 << 13) - 1)),
587 );
588 }
589}