1use core::borrow::Borrow;
6use core::convert::Infallible as Never;
7use core::num::NonZeroU16;
8
9use net_types::ip::{GenericOverIp, Ip, IpAddress, IpInvariant, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
10use netstack3_base::{Options, PayloadLen, SegmentHeader};
11use packet::records::options::OptionSequenceBuilder;
12use packet::{
13 Buf, BufferAlloc, BufferMut, BufferProvider, BufferViewMut, EitherSerializer, EmptyBuf,
14 GrowBufferMut, InnerSerializer, Nested, PacketConstraints, ParsablePacket, ParseBuffer,
15 ParseMetadata, ReusableBuffer, SerializeError, Serializer, SliceBufViewMut,
16};
17use packet_formats::icmp::mld::{
18 MulticastListenerDone, MulticastListenerQuery, MulticastListenerQueryV2,
19 MulticastListenerReport, MulticastListenerReportV2,
20};
21use packet_formats::icmp::ndp::options::NdpOptionBuilder;
22use packet_formats::icmp::ndp::{
23 NeighborAdvertisement, NeighborSolicitation, Redirect, RouterAdvertisement, RouterSolicitation,
24};
25use packet_formats::icmp::{
26 self, IcmpDestUnreachable, IcmpEchoReply, IcmpEchoRequest, IcmpPacketBuilder, IcmpPacketRaw,
27 IcmpPacketTypeRaw as _, IcmpTimeExceeded, Icmpv4MessageType, Icmpv4PacketRaw,
28 Icmpv4ParameterProblem, Icmpv4Redirect, Icmpv4TimestampReply, Icmpv4TimestampRequest,
29 Icmpv6MessageType, Icmpv6PacketRaw, Icmpv6PacketTooBig, Icmpv6ParameterProblem,
30};
31use packet_formats::igmp::messages::IgmpMembershipReportV3Builder;
32use packet_formats::igmp::{self, IgmpPacketBuilder};
33use packet_formats::ip::{IpExt, IpPacket as _, IpPacketBuilder, IpProto, Ipv4Proto, Ipv6Proto};
34use packet_formats::ipv4::{Ipv4Packet, Ipv4PacketRaw};
35use packet_formats::ipv6::{Ipv6Packet, Ipv6PacketRaw};
36use packet_formats::tcp::options::TcpOption;
37use packet_formats::tcp::{TcpParseArgs, TcpSegment, TcpSegmentBuilderWithOptions, TcpSegmentRaw};
38use packet_formats::udp::{UdpPacket, UdpPacketBuilder, UdpPacketRaw, UdpParseArgs};
39use zerocopy::{SplitByteSlice, SplitByteSliceMut};
40
41pub trait FilterIpExt: IpExt {
43 type FilterIpPacket<B: SplitByteSliceMut>: IpPacket<Self>;
45
46 fn as_filter_packet<B: SplitByteSliceMut>(
49 packet: &mut Self::Packet<B>,
50 ) -> &mut Self::FilterIpPacket<B>;
51}
52
53impl FilterIpExt for Ipv4 {
54 type FilterIpPacket<B: SplitByteSliceMut> = Ipv4Packet<B>;
55
56 #[inline]
57 fn as_filter_packet<B: SplitByteSliceMut>(packet: &mut Ipv4Packet<B>) -> &mut Ipv4Packet<B> {
58 packet
59 }
60}
61
62impl FilterIpExt for Ipv6 {
63 type FilterIpPacket<B: SplitByteSliceMut> = Ipv6Packet<B>;
64
65 #[inline]
66 fn as_filter_packet<B: SplitByteSliceMut>(packet: &mut Ipv6Packet<B>) -> &mut Ipv6Packet<B> {
67 packet
68 }
69}
70
71pub trait IpPacket<I: IpExt> {
73 type TransportPacket<'a>: MaybeTransportPacket
76 where
77 Self: 'a;
78
79 type TransportPacketMut<'a>: MaybeTransportPacketMut<I>
82 where
83 Self: 'a;
84
85 fn src_addr(&self) -> I::Addr;
87
88 fn set_src_addr(&mut self, addr: I::Addr);
90
91 fn dst_addr(&self) -> I::Addr;
93
94 fn set_dst_addr(&mut self, addr: I::Addr);
96
97 fn protocol(&self) -> I::Proto;
99
100 fn maybe_transport_packet<'a>(&'a self) -> Self::TransportPacket<'a>;
111
112 fn transport_packet_mut<'a>(&'a mut self) -> Self::TransportPacketMut<'a>;
123}
124
125pub trait MaybeTransportPacket {
132 fn transport_packet_data(&self) -> Option<TransportPacketData>;
135}
136
137pub trait MaybeTransportPacketMut<I: IpExt> {
145 type TransportPacketMut<'a>: TransportPacketMut<I>
148 where
149 Self: 'a;
150
151 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>>;
154}
155
156pub trait TransportPacketSerializer<I: IpExt>:
158 Serializer + MaybeTransportPacket + MaybeTransportPacketMut<I>
159{
160}
161
162impl<I, S> TransportPacketSerializer<I> for S
163where
164 I: IpExt,
165 S: Serializer + MaybeTransportPacket + MaybeTransportPacketMut<I>,
166{
167}
168
169impl<T: ?Sized> MaybeTransportPacket for &T
170where
171 T: MaybeTransportPacket,
172{
173 fn transport_packet_data(&self) -> Option<TransportPacketData> {
174 (**self).transport_packet_data()
175 }
176}
177
178impl<T: ?Sized> MaybeTransportPacket for &mut T
179where
180 T: MaybeTransportPacket,
181{
182 fn transport_packet_data(&self) -> Option<TransportPacketData> {
183 (**self).transport_packet_data()
184 }
185}
186
187impl<I: IpExt, T: ?Sized> MaybeTransportPacketMut<I> for &mut T
188where
189 T: MaybeTransportPacketMut<I>,
190{
191 type TransportPacketMut<'a>
192 = T::TransportPacketMut<'a>
193 where
194 Self: 'a;
195
196 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
197 (**self).transport_packet_mut()
198 }
199}
200
201impl<I: IpExt, T: TransportPacketMut<I>> MaybeTransportPacketMut<I> for Option<T> {
202 type TransportPacketMut<'a>
203 = &'a mut T
204 where
205 Self: 'a;
206
207 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
208 self.as_mut()
209 }
210}
211
212#[derive(Debug, Clone, GenericOverIp, PartialEq, Eq)]
215#[generic_over_ip()]
216pub enum TransportPacketData {
217 Tcp { src_port: u16, dst_port: u16, segment: SegmentHeader, payload_len: usize },
218 Generic { src_port: u16, dst_port: u16 },
219}
220
221impl TransportPacketData {
222 pub fn src_port(&self) -> u16 {
223 match self {
224 TransportPacketData::Tcp { src_port, .. }
225 | TransportPacketData::Generic { src_port, .. } => *src_port,
226 }
227 }
228
229 pub fn dst_port(&self) -> u16 {
230 match self {
231 TransportPacketData::Tcp { dst_port, .. }
232 | TransportPacketData::Generic { dst_port, .. } => *dst_port,
233 }
234 }
235
236 pub fn tcp_segment_and_len(&self) -> Option<(&SegmentHeader, usize)> {
237 match self {
238 TransportPacketData::Tcp { segment, payload_len, .. } => Some((&segment, *payload_len)),
239 TransportPacketData::Generic { .. } => None,
240 }
241 }
242
243 fn parse_in_ip_packet<I: IpExt, B: ParseBuffer>(
244 src_ip: I::Addr,
245 dst_ip: I::Addr,
246 proto: I::Proto,
247 body: B,
248 ) -> Option<TransportPacketData> {
249 I::map_ip(
250 (src_ip, dst_ip, proto, IpInvariant(body)),
251 |(src_ip, dst_ip, proto, IpInvariant(body))| {
252 parse_transport_header_in_ipv4_packet(src_ip, dst_ip, proto, body)
253 },
254 |(src_ip, dst_ip, proto, IpInvariant(body))| {
255 parse_transport_header_in_ipv6_packet(src_ip, dst_ip, proto, body)
256 },
257 )
258 }
259}
260
261pub trait TransportPacketMut<I: IpExt> {
266 fn set_src_port(&mut self, port: NonZeroU16);
268
269 fn set_dst_port(&mut self, port: NonZeroU16);
271
272 fn update_pseudo_header_src_addr(&mut self, old: I::Addr, new: I::Addr);
274
275 fn update_pseudo_header_dst_addr(&mut self, old: I::Addr, new: I::Addr);
277}
278
279impl<B: SplitByteSliceMut> IpPacket<Ipv4> for Ipv4Packet<B> {
280 type TransportPacket<'a>
281 = &'a Self
282 where
283 Self: 'a;
284 type TransportPacketMut<'a>
285 = Option<ParsedTransportHeaderMut<'a, Ipv4>>
286 where
287 B: 'a;
288
289 fn src_addr(&self) -> Ipv4Addr {
290 self.src_ip()
291 }
292
293 fn set_src_addr(&mut self, addr: Ipv4Addr) {
294 let old = self.src_addr();
295 if let Some(packet) = self.transport_packet_mut().transport_packet_mut() {
296 packet.update_pseudo_header_src_addr(old, addr);
297 }
298 self.set_src_ip_and_update_checksum(addr);
307 }
308
309 fn dst_addr(&self) -> Ipv4Addr {
310 self.dst_ip()
311 }
312
313 fn set_dst_addr(&mut self, addr: Ipv4Addr) {
314 let old = self.dst_addr();
315 if let Some(packet) = self.transport_packet_mut().transport_packet_mut() {
316 packet.update_pseudo_header_dst_addr(old, addr);
317 }
318 self.set_dst_ip_and_update_checksum(addr);
328 }
329
330 fn protocol(&self) -> Ipv4Proto {
331 self.proto()
332 }
333
334 fn maybe_transport_packet(&self) -> Self::TransportPacket<'_> {
335 self
336 }
337
338 fn transport_packet_mut(&mut self) -> Self::TransportPacketMut<'_> {
339 ParsedTransportHeaderMut::parse_in_ipv4_packet(
340 self.src_ip(),
341 self.dst_ip(),
342 self.proto(),
343 SliceBufViewMut::new(self.body_mut()),
344 )
345 }
346}
347
348impl<B: SplitByteSlice> MaybeTransportPacket for Ipv4Packet<B> {
349 fn transport_packet_data(&self) -> Option<TransportPacketData> {
350 parse_transport_header_in_ipv4_packet(
351 self.src_ip(),
352 self.dst_ip(),
353 self.proto(),
354 self.body(),
355 )
356 }
357}
358
359impl<B: SplitByteSliceMut> IpPacket<Ipv6> for Ipv6Packet<B> {
360 type TransportPacket<'a>
361 = &'a Self
362 where
363 Self: 'a;
364 type TransportPacketMut<'a>
365 = Option<ParsedTransportHeaderMut<'a, Ipv6>>
366 where
367 B: 'a;
368
369 fn src_addr(&self) -> Ipv6Addr {
370 self.src_ip()
371 }
372
373 fn set_src_addr(&mut self, addr: Ipv6Addr) {
374 let old = self.src_addr();
375 if let Some(packet) = self.transport_packet_mut().transport_packet_mut() {
376 packet.update_pseudo_header_src_addr(old, addr);
377 }
378 self.set_src_ip(addr);
387 }
388
389 fn dst_addr(&self) -> Ipv6Addr {
390 self.dst_ip()
391 }
392
393 fn set_dst_addr(&mut self, addr: Ipv6Addr) {
394 let old = self.dst_addr();
395 if let Some(packet) = self.transport_packet_mut().transport_packet_mut() {
396 packet.update_pseudo_header_dst_addr(old, addr);
397 }
398 self.set_dst_ip(addr);
408 }
409
410 fn protocol(&self) -> Ipv6Proto {
411 self.proto()
412 }
413
414 fn maybe_transport_packet(&self) -> Self::TransportPacket<'_> {
415 self
416 }
417
418 fn transport_packet_mut(&mut self) -> Self::TransportPacketMut<'_> {
419 ParsedTransportHeaderMut::parse_in_ipv6_packet(
420 self.src_ip(),
421 self.dst_ip(),
422 self.proto(),
423 SliceBufViewMut::new(self.body_mut()),
424 )
425 }
426}
427
428impl<B: SplitByteSlice> MaybeTransportPacket for Ipv6Packet<B> {
429 fn transport_packet_data(&self) -> Option<TransportPacketData> {
430 parse_transport_header_in_ipv6_packet(
431 self.src_ip(),
432 self.dst_ip(),
433 self.proto(),
434 self.body(),
435 )
436 }
437}
438
439#[derive(Debug, PartialEq, GenericOverIp)]
442#[generic_over_ip(I, Ip)]
443pub struct TxPacket<'a, I: IpExt, S> {
444 src_addr: I::Addr,
445 dst_addr: I::Addr,
446 protocol: I::Proto,
447 serializer: &'a mut S,
448}
449
450impl<'a, I: IpExt, S> TxPacket<'a, I, S> {
451 pub fn new(
453 src_addr: I::Addr,
454 dst_addr: I::Addr,
455 protocol: I::Proto,
456 serializer: &'a mut S,
457 ) -> Self {
458 Self { src_addr, dst_addr, protocol, serializer }
459 }
460
461 pub fn src_addr(&self) -> I::Addr {
463 self.src_addr
464 }
465
466 pub fn dst_addr(&self) -> I::Addr {
468 self.dst_addr
469 }
470}
471
472impl<I: IpExt, S: TransportPacketSerializer<I>> IpPacket<I> for TxPacket<'_, I, S> {
473 type TransportPacket<'a>
474 = &'a S
475 where
476 Self: 'a;
477 type TransportPacketMut<'a>
478 = &'a mut S
479 where
480 Self: 'a;
481
482 fn src_addr(&self) -> I::Addr {
483 self.src_addr
484 }
485
486 fn set_src_addr(&mut self, addr: I::Addr) {
487 let old = core::mem::replace(&mut self.src_addr, addr);
488 if let Some(mut packet) = self.transport_packet_mut().transport_packet_mut() {
489 packet.update_pseudo_header_src_addr(old, addr);
490 }
491 }
492
493 fn dst_addr(&self) -> I::Addr {
494 self.dst_addr
495 }
496
497 fn set_dst_addr(&mut self, addr: I::Addr) {
498 let old = core::mem::replace(&mut self.dst_addr, addr);
499 if let Some(mut packet) = self.transport_packet_mut().transport_packet_mut() {
500 packet.update_pseudo_header_dst_addr(old, addr);
501 }
502 }
503
504 fn protocol(&self) -> I::Proto {
505 self.protocol
506 }
507
508 fn maybe_transport_packet(&self) -> Self::TransportPacket<'_> {
509 self.serializer
510 }
511
512 fn transport_packet_mut(&mut self) -> Self::TransportPacketMut<'_> {
513 self.serializer
514 }
515}
516
517#[derive(Debug, PartialEq, GenericOverIp)]
519#[generic_over_ip(I, Ip)]
520pub struct ForwardedPacket<I: IpExt, B> {
521 src_addr: I::Addr,
522 dst_addr: I::Addr,
523 protocol: I::Proto,
524 transport_header_offset: usize,
525 buffer: B,
526}
527
528impl<I: IpExt, B: BufferMut> ForwardedPacket<I, B> {
529 pub fn new(
536 src_addr: I::Addr,
537 dst_addr: I::Addr,
538 protocol: I::Proto,
539 meta: ParseMetadata,
540 mut buffer: B,
541 ) -> Self {
542 let transport_header_offset = meta.header_len();
543 buffer.undo_parse(meta);
544 Self { src_addr, dst_addr, protocol, transport_header_offset, buffer }
545 }
546
547 pub fn into_buffer(self) -> B {
553 self.buffer
554 }
555
556 pub fn buffer(&self) -> &B {
561 &self.buffer
562 }
563}
564
565impl<I: IpExt, B: BufferMut> Serializer for ForwardedPacket<I, B> {
566 type Buffer = <B as Serializer>::Buffer;
567
568 fn serialize<G: packet::GrowBufferMut, P: packet::BufferProvider<Self::Buffer, G>>(
569 self,
570 outer: packet::PacketConstraints,
571 provider: P,
572 ) -> Result<G, (packet::SerializeError<P::Error>, Self)> {
573 let Self { src_addr, dst_addr, protocol, transport_header_offset, buffer } = self;
574 buffer.serialize(outer, provider).map_err(|(err, buffer)| {
575 (err, Self { src_addr, dst_addr, protocol, transport_header_offset, buffer })
576 })
577 }
578
579 fn serialize_new_buf<BB: packet::ReusableBuffer, A: packet::BufferAlloc<BB>>(
580 &self,
581 outer: packet::PacketConstraints,
582 alloc: A,
583 ) -> Result<BB, packet::SerializeError<A::Error>> {
584 self.buffer.serialize_new_buf(outer, alloc)
585 }
586}
587
588impl<I: IpExt, B: BufferMut> IpPacket<I> for ForwardedPacket<I, B> {
589 type TransportPacket<'a>
590 = &'a Self
591 where
592 Self: 'a;
593 type TransportPacketMut<'a>
594 = Option<ParsedTransportHeaderMut<'a, I>>
595 where
596 Self: 'a;
597
598 fn src_addr(&self) -> I::Addr {
599 self.src_addr
600 }
601
602 fn set_src_addr(&mut self, addr: I::Addr) {
603 I::map_ip::<_, ()>(
605 (IpInvariant(self.buffer.as_mut()), addr),
606 |(IpInvariant(buffer), addr)| {
607 let mut packet = Ipv4PacketRaw::parse_mut(SliceBufViewMut::new(buffer), ())
608 .expect("ForwardedPacket must have been created from a valid IP packet");
609 packet.set_src_ip_and_update_checksum(addr);
610 },
611 |(IpInvariant(buffer), addr)| {
612 let mut packet = Ipv6PacketRaw::parse_mut(SliceBufViewMut::new(buffer), ())
613 .expect("ForwardedPacket must have been created from a valid IP packet");
614 packet.set_src_ip(addr);
615 },
616 );
617
618 let old = self.src_addr;
619 if let Some(packet) = self.transport_packet_mut().transport_packet_mut() {
620 packet.update_pseudo_header_src_addr(old, addr);
621 }
622 self.src_addr = addr;
631 }
632
633 fn dst_addr(&self) -> I::Addr {
634 self.dst_addr
635 }
636
637 fn set_dst_addr(&mut self, addr: I::Addr) {
638 I::map_ip::<_, ()>(
640 (IpInvariant(self.buffer.as_mut()), addr),
641 |(IpInvariant(buffer), addr)| {
642 let mut packet = Ipv4PacketRaw::parse_mut(SliceBufViewMut::new(buffer), ())
643 .expect("ForwardedPacket must have been created from a valid IP packet");
644 packet.set_dst_ip_and_update_checksum(addr);
645 },
646 |(IpInvariant(buffer), addr)| {
647 let mut packet = Ipv6PacketRaw::parse_mut(SliceBufViewMut::new(buffer), ())
648 .expect("ForwardedPacket must have been created from a valid IP packet");
649 packet.set_dst_ip(addr);
650 },
651 );
652
653 let old = self.dst_addr;
654 if let Some(packet) = self.transport_packet_mut().transport_packet_mut() {
655 packet.update_pseudo_header_dst_addr(old, addr);
656 }
657 self.dst_addr = addr;
666 }
667
668 fn protocol(&self) -> I::Proto {
669 self.protocol
670 }
671
672 fn maybe_transport_packet(&self) -> Self::TransportPacket<'_> {
673 self
674 }
675
676 fn transport_packet_mut(&mut self) -> Self::TransportPacketMut<'_> {
677 let ForwardedPacket { src_addr, dst_addr, protocol, buffer, transport_header_offset } =
678 self;
679 ParsedTransportHeaderMut::<I>::parse_in_ip_packet(
680 *src_addr,
681 *dst_addr,
682 *protocol,
683 SliceBufViewMut::new(&mut buffer.as_mut()[*transport_header_offset..]),
684 )
685 }
686}
687
688impl<I: IpExt, B: BufferMut> MaybeTransportPacket for ForwardedPacket<I, B> {
689 fn transport_packet_data(&self) -> Option<TransportPacketData> {
690 let ForwardedPacket { protocol, buffer, src_addr, dst_addr, transport_header_offset } =
691 self;
692 TransportPacketData::parse_in_ip_packet::<I, _>(
693 *src_addr,
694 *dst_addr,
695 *protocol,
696 Buf::new(&buffer.as_ref()[*transport_header_offset..], ..),
697 )
698 }
699}
700
701impl<I: IpExt, S: TransportPacketSerializer<I>, B: IpPacketBuilder<I>> IpPacket<I>
702 for Nested<S, B>
703{
704 type TransportPacket<'a>
705 = &'a S
706 where
707 Self: 'a;
708 type TransportPacketMut<'a>
709 = &'a mut S
710 where
711 Self: 'a;
712
713 fn src_addr(&self) -> I::Addr {
714 self.outer().src_ip()
715 }
716
717 fn set_src_addr(&mut self, addr: I::Addr) {
718 let old = self.outer().src_ip();
719 self.outer_mut().set_src_ip(addr);
720 if let Some(mut packet) = self.transport_packet_mut().transport_packet_mut() {
721 packet.update_pseudo_header_src_addr(old, addr);
722 }
723 }
724
725 fn dst_addr(&self) -> I::Addr {
726 self.outer().dst_ip()
727 }
728
729 fn set_dst_addr(&mut self, addr: I::Addr) {
730 let old = self.outer().dst_ip();
731 self.outer_mut().set_dst_ip(addr);
732 if let Some(mut packet) = self.transport_packet_mut().transport_packet_mut() {
733 packet.update_pseudo_header_dst_addr(old, addr);
734 }
735 }
736
737 fn protocol(&self) -> I::Proto {
738 self.outer().proto()
739 }
740
741 fn maybe_transport_packet(&self) -> Self::TransportPacket<'_> {
742 self.inner()
743 }
744
745 fn transport_packet_mut(&mut self) -> Self::TransportPacketMut<'_> {
746 self.inner_mut()
747 }
748}
749
750impl<I: IpExt, T: ?Sized> TransportPacketMut<I> for &mut T
751where
752 T: TransportPacketMut<I>,
753{
754 fn set_src_port(&mut self, port: NonZeroU16) {
755 (*self).set_src_port(port);
756 }
757
758 fn set_dst_port(&mut self, port: NonZeroU16) {
759 (*self).set_dst_port(port);
760 }
761
762 fn update_pseudo_header_src_addr(&mut self, old: I::Addr, new: I::Addr) {
763 (*self).update_pseudo_header_src_addr(old, new);
764 }
765
766 fn update_pseudo_header_dst_addr(&mut self, old: I::Addr, new: I::Addr) {
767 (*self).update_pseudo_header_dst_addr(old, new);
768 }
769}
770
771impl MaybeTransportPacket for Never {
772 fn transport_packet_data(&self) -> Option<TransportPacketData> {
773 match *self {}
774 }
775}
776
777impl<I: IpExt> MaybeTransportPacketMut<I> for Never {
778 type TransportPacketMut<'a>
779 = Never
780 where
781 Self: 'a;
782
783 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
784 match *self {}
785 }
786}
787
788impl<I: IpExt> TransportPacketMut<I> for Never {
789 fn set_src_port(&mut self, _: NonZeroU16) {
790 match *self {}
791 }
792
793 fn set_dst_port(&mut self, _: NonZeroU16) {
794 match *self {}
795 }
796
797 fn update_pseudo_header_src_addr(&mut self, _: I::Addr, _: I::Addr) {
798 match *self {}
799 }
800
801 fn update_pseudo_header_dst_addr(&mut self, _: I::Addr, _: I::Addr) {
802 match *self {}
803 }
804}
805
806impl<A: IpAddress, Inner> MaybeTransportPacket for Nested<Inner, UdpPacketBuilder<A>> {
807 fn transport_packet_data(&self) -> Option<TransportPacketData> {
808 Some(TransportPacketData::Generic {
809 src_port: self.outer().src_port().map_or(0, NonZeroU16::get),
810 dst_port: self.outer().dst_port().map_or(0, NonZeroU16::get),
811 })
812 }
813}
814
815impl<I: IpExt, Inner> MaybeTransportPacketMut<I> for Nested<Inner, UdpPacketBuilder<I::Addr>> {
816 type TransportPacketMut<'a>
817 = &'a mut Self
818 where
819 Self: 'a;
820
821 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
822 Some(self)
823 }
824}
825
826impl<I: IpExt, Inner> TransportPacketMut<I> for Nested<Inner, UdpPacketBuilder<I::Addr>> {
827 fn set_src_port(&mut self, port: NonZeroU16) {
828 self.outer_mut().set_src_port(port.get());
829 }
830
831 fn set_dst_port(&mut self, port: NonZeroU16) {
832 self.outer_mut().set_dst_port(port);
833 }
834
835 fn update_pseudo_header_src_addr(&mut self, _old: I::Addr, new: I::Addr) {
836 self.outer_mut().set_src_ip(new);
837 }
838
839 fn update_pseudo_header_dst_addr(&mut self, _old: I::Addr, new: I::Addr) {
840 self.outer_mut().set_dst_ip(new);
841 }
842}
843
844impl<'a, A: IpAddress, Inner: PayloadLen, I> MaybeTransportPacket
845 for Nested<Inner, TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<TcpOption<'a>, I>>>
846where
847 I: Iterator + Clone,
848 I::Item: Borrow<TcpOption<'a>>,
849{
850 fn transport_packet_data(&self) -> Option<TransportPacketData> {
851 Some(TransportPacketData::Tcp {
852 src_port: self.outer().src_port().map_or(0, NonZeroU16::get),
853 dst_port: self.outer().dst_port().map_or(0, NonZeroU16::get),
854 segment: self.outer().try_into().ok()?,
855 payload_len: self.inner().len(),
856 })
857 }
858}
859
860impl<I: IpExt, Outer, Inner> MaybeTransportPacketMut<I>
861 for Nested<Inner, TcpSegmentBuilderWithOptions<I::Addr, Outer>>
862{
863 type TransportPacketMut<'a>
864 = &'a mut Self
865 where
866 Self: 'a;
867
868 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
869 Some(self)
870 }
871}
872
873impl<I: IpExt, Outer, Inner> TransportPacketMut<I>
874 for Nested<Inner, TcpSegmentBuilderWithOptions<I::Addr, Outer>>
875{
876 fn set_src_port(&mut self, port: NonZeroU16) {
877 self.outer_mut().set_src_port(port);
878 }
879
880 fn set_dst_port(&mut self, port: NonZeroU16) {
881 self.outer_mut().set_dst_port(port);
882 }
883
884 fn update_pseudo_header_src_addr(&mut self, _old: I::Addr, new: I::Addr) {
885 self.outer_mut().set_src_ip(new);
886 }
887
888 fn update_pseudo_header_dst_addr(&mut self, _old: I::Addr, new: I::Addr) {
889 self.outer_mut().set_dst_ip(new);
890 }
891}
892
893impl<I: IpExt, Inner, M: IcmpMessage<I>> MaybeTransportPacket
894 for Nested<Inner, IcmpPacketBuilder<I, M>>
895{
896 fn transport_packet_data(&self) -> Option<TransportPacketData> {
897 self.outer().message().transport_packet_data()
898 }
899}
900
901impl<I: IpExt, Inner, M: IcmpMessage<I>> MaybeTransportPacketMut<I>
902 for Nested<Inner, IcmpPacketBuilder<I, M>>
903{
904 type TransportPacketMut<'a>
905 = &'a mut IcmpPacketBuilder<I, M>
906 where
907 M: 'a,
908 Inner: 'a;
909
910 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
911 Some(self.outer_mut())
912 }
913}
914
915impl<I: IpExt, M: IcmpMessage<I>> TransportPacketMut<I> for IcmpPacketBuilder<I, M> {
916 fn set_src_port(&mut self, id: NonZeroU16) {
917 let _: u16 = self.message_mut().update_icmp_id(id.get());
918 }
919
920 fn set_dst_port(&mut self, id: NonZeroU16) {
921 let _: u16 = self.message_mut().update_icmp_id(id.get());
922 }
923
924 fn update_pseudo_header_src_addr(&mut self, _old: I::Addr, new: I::Addr) {
925 self.set_src_ip(new);
926 }
927
928 fn update_pseudo_header_dst_addr(&mut self, _old: I::Addr, new: I::Addr) {
929 self.set_dst_ip(new);
930 }
931}
932
933pub trait IcmpMessage<I: IpExt>: icmp::IcmpMessage<I> + MaybeTransportPacket {
935 fn update_icmp_id(&mut self, id: u16) -> u16;
939}
940
941impl MaybeTransportPacket for IcmpEchoReply {
946 fn transport_packet_data(&self) -> Option<TransportPacketData> {
947 Some(TransportPacketData::Generic { src_port: self.id(), dst_port: self.id() })
948 }
949}
950
951impl<I: IpExt> IcmpMessage<I> for IcmpEchoReply {
952 fn update_icmp_id(&mut self, id: u16) -> u16 {
953 let old = self.id();
954 self.set_id(id);
955 old
956 }
957}
958
959impl MaybeTransportPacket for IcmpEchoRequest {
964 fn transport_packet_data(&self) -> Option<TransportPacketData> {
965 Some(TransportPacketData::Generic { src_port: self.id(), dst_port: self.id() })
966 }
967}
968
969impl<I: IpExt> IcmpMessage<I> for IcmpEchoRequest {
970 fn update_icmp_id(&mut self, id: u16) -> u16 {
971 let old = self.id();
972 self.set_id(id);
973 old
974 }
975}
976
977macro_rules! unsupported_icmp_message_type {
978 ($message:ty, $($ips:ty),+) => {
979 impl MaybeTransportPacket for $message {
980 fn transport_packet_data(&self) -> Option<TransportPacketData> {
981 None
982 }
983 }
984
985 $(
986 impl IcmpMessage<$ips> for $message {
987 fn update_icmp_id(&mut self, _: u16) -> u16 {
988 unreachable!("non-echo ICMP packets should never be rewritten")
989 }
990 }
991 )+
992 };
993}
994
995unsupported_icmp_message_type!(Icmpv4TimestampRequest, Ipv4);
996unsupported_icmp_message_type!(Icmpv4TimestampReply, Ipv4);
997unsupported_icmp_message_type!(Icmpv4Redirect, Ipv4);
998unsupported_icmp_message_type!(NeighborSolicitation, Ipv6);
999unsupported_icmp_message_type!(NeighborAdvertisement, Ipv6);
1000unsupported_icmp_message_type!(RouterSolicitation, Ipv6);
1001unsupported_icmp_message_type!(MulticastListenerDone, Ipv6);
1002unsupported_icmp_message_type!(MulticastListenerReport, Ipv6);
1003unsupported_icmp_message_type!(MulticastListenerReportV2, Ipv6);
1004unsupported_icmp_message_type!(MulticastListenerQuery, Ipv6);
1005unsupported_icmp_message_type!(MulticastListenerQueryV2, Ipv6);
1006unsupported_icmp_message_type!(RouterAdvertisement, Ipv6);
1007unsupported_icmp_message_type!(Redirect, Ipv6);
1008
1009macro_rules! icmp_error_message {
1015 ($message:ty, $($ips:ty),+) => {
1016 unsupported_icmp_message_type!($message, $( $ips ),+);
1017 };
1018}
1019
1020icmp_error_message!(IcmpDestUnreachable, Ipv4, Ipv6);
1021icmp_error_message!(IcmpTimeExceeded, Ipv4, Ipv6);
1022icmp_error_message!(Icmpv4ParameterProblem, Ipv4);
1023icmp_error_message!(Icmpv6ParameterProblem, Ipv6);
1024icmp_error_message!(Icmpv6PacketTooBig, Ipv6);
1025
1026impl<M: igmp::MessageType<EmptyBuf>> MaybeTransportPacket
1027 for InnerSerializer<IgmpPacketBuilder<EmptyBuf, M>, EmptyBuf>
1028{
1029 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1030 None
1031 }
1032}
1033
1034impl<M: igmp::MessageType<EmptyBuf>> MaybeTransportPacketMut<Ipv4>
1035 for InnerSerializer<IgmpPacketBuilder<EmptyBuf, M>, EmptyBuf>
1036{
1037 type TransportPacketMut<'a>
1038 = Never
1039 where
1040 M: 'a;
1041
1042 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1043 None
1044 }
1045}
1046
1047impl<I> MaybeTransportPacket for InnerSerializer<IgmpMembershipReportV3Builder<I>, EmptyBuf> {
1048 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1049 None
1050 }
1051}
1052
1053impl<I> MaybeTransportPacketMut<Ipv4>
1054 for InnerSerializer<IgmpMembershipReportV3Builder<I>, EmptyBuf>
1055{
1056 type TransportPacketMut<'a>
1057 = Never
1058 where
1059 I: 'a;
1060
1061 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1062 None
1063 }
1064}
1065
1066impl<I> MaybeTransportPacket
1067 for EitherSerializer<
1068 EmptyBuf,
1069 InnerSerializer<packet::records::RecordSequenceBuilder<NdpOptionBuilder<'_>, I>, EmptyBuf>,
1070 >
1071{
1072 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1073 None
1074 }
1075}
1076
1077#[derive(GenericOverIp)]
1082#[generic_over_ip(I, Ip)]
1083pub struct RawIpBody<I: IpExt, B: ParseBuffer> {
1084 protocol: I::Proto,
1087 src_addr: I::Addr,
1090 dst_addr: I::Addr,
1093 body: B,
1096 transport_packet_data: Option<TransportPacketData>,
1099}
1100
1101impl<I: IpExt, B: ParseBuffer> RawIpBody<I, B> {
1102 pub fn new(
1104 protocol: I::Proto,
1105 src_addr: I::Addr,
1106 dst_addr: I::Addr,
1107 body: B,
1108 ) -> RawIpBody<I, B> {
1109 let transport_packet_data = TransportPacketData::parse_in_ip_packet::<I, _>(
1110 src_addr,
1111 dst_addr,
1112 protocol,
1113 Buf::new(&body, ..),
1114 );
1115 RawIpBody { protocol, src_addr, dst_addr, body, transport_packet_data }
1116 }
1117}
1118
1119impl<I: IpExt, B: ParseBuffer> MaybeTransportPacket for RawIpBody<I, B> {
1120 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1121 self.transport_packet_data.clone()
1122 }
1123}
1124
1125impl<I: IpExt, B: BufferMut> MaybeTransportPacketMut<I> for RawIpBody<I, B> {
1126 type TransportPacketMut<'a>
1127 = ParsedTransportHeaderMut<'a, I>
1128 where
1129 Self: 'a;
1130
1131 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1132 let RawIpBody { protocol, src_addr, dst_addr, body, transport_packet_data: _ } = self;
1133 ParsedTransportHeaderMut::<I>::parse_in_ip_packet(
1134 *src_addr,
1135 *dst_addr,
1136 *protocol,
1137 SliceBufViewMut::new(body.as_mut()),
1138 )
1139 }
1140}
1141
1142impl<I: IpExt, B: BufferMut> Serializer for RawIpBody<I, B> {
1143 type Buffer = <B as Serializer>::Buffer;
1144
1145 fn serialize<G: GrowBufferMut, P: BufferProvider<Self::Buffer, G>>(
1146 self,
1147 outer: PacketConstraints,
1148 provider: P,
1149 ) -> Result<G, (SerializeError<P::Error>, Self)> {
1150 let Self { protocol, src_addr, dst_addr, body, transport_packet_data } = self;
1151 body.serialize(outer, provider).map_err(|(err, body)| {
1152 (err, Self { protocol, src_addr, dst_addr, body, transport_packet_data })
1153 })
1154 }
1155
1156 fn serialize_new_buf<BB: ReusableBuffer, A: BufferAlloc<BB>>(
1157 &self,
1158 outer: PacketConstraints,
1159 alloc: A,
1160 ) -> Result<BB, SerializeError<A::Error>> {
1161 self.body.serialize_new_buf(outer, alloc)
1162 }
1163}
1164
1165fn parse_transport_header_in_ipv4_packet<B: ParseBuffer>(
1166 src_ip: Ipv4Addr,
1167 dst_ip: Ipv4Addr,
1168 proto: Ipv4Proto,
1169 body: B,
1170) -> Option<TransportPacketData> {
1171 match proto {
1172 Ipv4Proto::Proto(IpProto::Udp) => parse_udp_header::<_, Ipv4>(body),
1173 Ipv4Proto::Proto(IpProto::Tcp) => parse_tcp_header::<_, Ipv4>(body, src_ip, dst_ip),
1174 Ipv4Proto::Icmp => parse_icmpv4_header(body),
1175 Ipv4Proto::Proto(IpProto::Reserved) | Ipv4Proto::Igmp | Ipv4Proto::Other(_) => None,
1176 }
1177}
1178
1179fn parse_transport_header_in_ipv6_packet<B: ParseBuffer>(
1180 src_ip: Ipv6Addr,
1181 dst_ip: Ipv6Addr,
1182 proto: Ipv6Proto,
1183 body: B,
1184) -> Option<TransportPacketData> {
1185 match proto {
1186 Ipv6Proto::Proto(IpProto::Udp) => parse_udp_header::<_, Ipv6>(body),
1187 Ipv6Proto::Proto(IpProto::Tcp) => parse_tcp_header::<_, Ipv6>(body, src_ip, dst_ip),
1188 Ipv6Proto::Icmpv6 => parse_icmpv6_header(body),
1189 Ipv6Proto::Proto(IpProto::Reserved) | Ipv6Proto::NoNextHeader | Ipv6Proto::Other(_) => None,
1190 }
1191}
1192
1193fn parse_udp_header<B: ParseBuffer, I: Ip>(mut body: B) -> Option<TransportPacketData> {
1194 let packet = body.parse_with::<_, UdpPacketRaw<_>>(I::VERSION_MARKER).ok()?;
1195 Some(TransportPacketData::Generic {
1196 src_port: packet.src_port().map(NonZeroU16::get).unwrap_or(0),
1197 dst_port: packet.dst_port()?.get(),
1200 })
1201}
1202
1203fn parse_tcp_header<B: ParseBuffer, I: IpExt>(
1204 mut body: B,
1205 src_ip: I::Addr,
1206 dst_ip: I::Addr,
1207) -> Option<TransportPacketData> {
1208 let packet = body.parse::<TcpSegmentRaw<_>>().ok()?;
1217
1218 let (builder, options, body) = packet.into_builder_options(src_ip, dst_ip)?;
1219 let options = Options::from_iter(builder.syn_set(), options.iter());
1220
1221 let segment = SegmentHeader::from_builder_options(&builder, options).ok()?;
1222
1223 Some(TransportPacketData::Tcp {
1224 src_port: builder.src_port().map(NonZeroU16::get).unwrap_or(0),
1225 dst_port: builder.dst_port().map(NonZeroU16::get).unwrap_or(0),
1226 segment,
1227 payload_len: body.len(),
1228 })
1229}
1230
1231fn parse_icmpv4_header<B: ParseBuffer>(mut body: B) -> Option<TransportPacketData> {
1232 match icmp::peek_message_type(body.as_ref()).ok()? {
1233 Icmpv4MessageType::EchoRequest => {
1234 let packet = body.parse::<IcmpPacketRaw<Ipv4, _, IcmpEchoRequest>>().ok()?;
1235 packet.message().transport_packet_data()
1236 }
1237 Icmpv4MessageType::EchoReply => {
1238 let packet = body.parse::<IcmpPacketRaw<Ipv4, _, IcmpEchoReply>>().ok()?;
1239 packet.message().transport_packet_data()
1240 }
1241 Icmpv4MessageType::DestUnreachable
1244 | Icmpv4MessageType::Redirect
1245 | Icmpv4MessageType::TimeExceeded
1246 | Icmpv4MessageType::ParameterProblem
1247 | Icmpv4MessageType::TimestampRequest
1251 | Icmpv4MessageType::TimestampReply => None,
1252 }
1253}
1254
1255fn parse_icmpv6_header<B: ParseBuffer>(mut body: B) -> Option<TransportPacketData> {
1256 match icmp::peek_message_type(body.as_ref()).ok()? {
1257 Icmpv6MessageType::EchoRequest => {
1258 let packet = body.parse::<IcmpPacketRaw<Ipv6, _, IcmpEchoRequest>>().ok()?;
1259 packet.message().transport_packet_data()
1260 }
1261 Icmpv6MessageType::EchoReply => {
1262 let packet = body.parse::<IcmpPacketRaw<Ipv6, _, IcmpEchoReply>>().ok()?;
1263 packet.message().transport_packet_data()
1264 }
1265 Icmpv6MessageType::DestUnreachable
1268 | Icmpv6MessageType::PacketTooBig
1269 | Icmpv6MessageType::TimeExceeded
1270 | Icmpv6MessageType::ParameterProblem
1271 | Icmpv6MessageType::RouterSolicitation
1272 | Icmpv6MessageType::RouterAdvertisement
1273 | Icmpv6MessageType::NeighborSolicitation
1274 | Icmpv6MessageType::NeighborAdvertisement
1275 | Icmpv6MessageType::Redirect
1276 | Icmpv6MessageType::MulticastListenerQuery
1277 | Icmpv6MessageType::MulticastListenerReport
1278 | Icmpv6MessageType::MulticastListenerDone
1279 | Icmpv6MessageType::MulticastListenerReportV2 => None,
1280 }
1281}
1282
1283#[derive(GenericOverIp)]
1286#[generic_over_ip(I, Ip)]
1287pub enum ParsedTransportHeaderMut<'a, I: IpExt> {
1288 Tcp(TcpSegment<&'a mut [u8]>),
1289 Udp(UdpPacket<&'a mut [u8]>),
1290 Icmp(I::IcmpPacketTypeRaw<&'a mut [u8]>),
1291}
1292
1293impl<'a> ParsedTransportHeaderMut<'a, Ipv4> {
1294 fn parse_in_ipv4_packet<BV: BufferViewMut<&'a mut [u8]>>(
1295 src_ip: Ipv4Addr,
1296 dst_ip: Ipv4Addr,
1297 proto: Ipv4Proto,
1298 body: BV,
1299 ) -> Option<Self> {
1300 match proto {
1301 Ipv4Proto::Proto(IpProto::Udp) => {
1302 Some(Self::Udp(UdpPacket::parse_mut(body, UdpParseArgs::new(src_ip, dst_ip)).ok()?))
1303 }
1304 Ipv4Proto::Proto(IpProto::Tcp) => Some(Self::Tcp(
1305 TcpSegment::parse_mut(body, TcpParseArgs::new(src_ip, dst_ip)).ok()?,
1306 )),
1307 Ipv4Proto::Icmp => Some(Self::Icmp(Icmpv4PacketRaw::parse_mut(body, ()).ok()?)),
1308 Ipv4Proto::Proto(IpProto::Reserved) | Ipv4Proto::Igmp | Ipv4Proto::Other(_) => None,
1309 }
1310 }
1311}
1312
1313impl<'a> ParsedTransportHeaderMut<'a, Ipv6> {
1314 fn parse_in_ipv6_packet<BV: BufferViewMut<&'a mut [u8]>>(
1315 src_ip: Ipv6Addr,
1316 dst_ip: Ipv6Addr,
1317 proto: Ipv6Proto,
1318 body: BV,
1319 ) -> Option<Self> {
1320 match proto {
1321 Ipv6Proto::Proto(IpProto::Udp) => {
1322 Some(Self::Udp(UdpPacket::parse_mut(body, UdpParseArgs::new(src_ip, dst_ip)).ok()?))
1323 }
1324 Ipv6Proto::Proto(IpProto::Tcp) => Some(Self::Tcp(
1325 TcpSegment::parse_mut(body, TcpParseArgs::new(src_ip, dst_ip)).ok()?,
1326 )),
1327 Ipv6Proto::Icmpv6 => Some(Self::Icmp(Icmpv6PacketRaw::parse_mut(body, ()).ok()?)),
1328 Ipv6Proto::Proto(IpProto::Reserved) | Ipv6Proto::NoNextHeader | Ipv6Proto::Other(_) => {
1329 None
1330 }
1331 }
1332 }
1333}
1334
1335impl<'a, I: IpExt> ParsedTransportHeaderMut<'a, I> {
1336 fn parse_in_ip_packet<BV: BufferViewMut<&'a mut [u8]>>(
1337 src_ip: I::Addr,
1338 dst_ip: I::Addr,
1339 proto: I::Proto,
1340 body: BV,
1341 ) -> Option<Self> {
1342 I::map_ip(
1343 (src_ip, dst_ip, proto, IpInvariant(body)),
1344 |(src_ip, dst_ip, proto, IpInvariant(body))| {
1345 ParsedTransportHeaderMut::<'a, Ipv4>::parse_in_ipv4_packet(
1346 src_ip, dst_ip, proto, body,
1347 )
1348 },
1349 |(src_ip, dst_ip, proto, IpInvariant(body))| {
1350 ParsedTransportHeaderMut::<'a, Ipv6>::parse_in_ipv6_packet(
1351 src_ip, dst_ip, proto, body,
1352 )
1353 },
1354 )
1355 }
1356
1357 fn update_pseudo_header_address(&mut self, old: I::Addr, new: I::Addr) {
1358 match self {
1359 Self::Tcp(segment) => segment.update_checksum_pseudo_header_address(old, new),
1360 Self::Udp(packet) => {
1361 packet.update_checksum_pseudo_header_address(old, new);
1362 }
1363 Self::Icmp(packet) => {
1364 packet.update_checksum_pseudo_header_address(old, new);
1365 }
1366 }
1367 }
1368}
1369
1370trait IcmpMessageImplHelper<I: IpExt> {
1372 fn message_impl_mut(&mut self) -> &mut impl IcmpMessage<I>;
1373}
1374
1375impl<I: IpExt, B: SplitByteSliceMut, M: IcmpMessage<I>> IcmpMessageImplHelper<I>
1376 for IcmpPacketRaw<I, B, M>
1377{
1378 fn message_impl_mut(&mut self) -> &mut impl IcmpMessage<I> {
1379 self.message_mut()
1380 }
1381}
1382
1383impl<'a, I: IpExt> TransportPacketMut<I> for ParsedTransportHeaderMut<'a, I> {
1384 fn set_src_port(&mut self, port: NonZeroU16) {
1385 match self {
1386 ParsedTransportHeaderMut::Tcp(segment) => segment.set_src_port(port),
1387 ParsedTransportHeaderMut::Udp(packet) => packet.set_src_port(port.get()),
1388 ParsedTransportHeaderMut::Icmp(packet) => {
1389 I::map_ip::<_, ()>(
1390 packet,
1391 |packet| {
1392 packet_formats::icmpv4_dispatch!(
1393 packet: raw,
1394 p => {
1395 let old = p.message_impl_mut().update_icmp_id(port.get());
1396 p.update_checksum_header_field_u16(old, port.get())
1397 }
1398 );
1399 },
1400 |packet| {
1401 packet_formats::icmpv6_dispatch!(
1402 packet: raw,
1403 p => {
1404 let old = p.message_impl_mut().update_icmp_id(port.get());
1405 p.update_checksum_header_field_u16(old, port.get())
1406 }
1407 );
1408 },
1409 );
1410 }
1411 }
1412 }
1413
1414 fn set_dst_port(&mut self, port: NonZeroU16) {
1415 match self {
1416 ParsedTransportHeaderMut::Tcp(ref mut segment) => segment.set_dst_port(port),
1417 ParsedTransportHeaderMut::Udp(ref mut packet) => packet.set_dst_port(port),
1418 ParsedTransportHeaderMut::Icmp(packet) => {
1419 I::map_ip::<_, ()>(
1420 packet,
1421 |packet| {
1422 packet_formats::icmpv4_dispatch!(
1423 packet:raw,
1424 p => {
1425 let old = p.message_impl_mut().update_icmp_id(port.get());
1426 p.update_checksum_header_field_u16(old, port.get())
1427 }
1428 );
1429 },
1430 |packet| {
1431 packet_formats::icmpv6_dispatch!(
1432 packet:raw,
1433 p => {
1434 let old = p.message_impl_mut().update_icmp_id(port.get());
1435 p.update_checksum_header_field_u16(old, port.get())
1436 }
1437 );
1438 },
1439 );
1440 }
1441 }
1442 }
1443
1444 fn update_pseudo_header_src_addr(&mut self, old: I::Addr, new: I::Addr) {
1445 self.update_pseudo_header_address(old, new);
1446 }
1447
1448 fn update_pseudo_header_dst_addr(&mut self, old: I::Addr, new: I::Addr) {
1449 self.update_pseudo_header_address(old, new);
1450 }
1451}
1452
1453#[cfg(any(test, feature = "testutils"))]
1454pub mod testutil {
1455 use super::*;
1456
1457 impl<B: BufferMut> MaybeTransportPacket for Nested<B, ()> {
1465 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1466 unimplemented!()
1467 }
1468 }
1469
1470 impl<I: IpExt, B: BufferMut> MaybeTransportPacketMut<I> for Nested<B, ()> {
1471 type TransportPacketMut<'a>
1472 = Never
1473 where
1474 B: 'a;
1475
1476 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1477 unimplemented!()
1478 }
1479 }
1480
1481 impl MaybeTransportPacket for InnerSerializer<&[u8], EmptyBuf> {
1482 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1483 None
1484 }
1485 }
1486
1487 impl<I: IpExt> MaybeTransportPacketMut<I> for InnerSerializer<&[u8], EmptyBuf> {
1488 type TransportPacketMut<'a>
1489 = Never
1490 where
1491 Self: 'a;
1492
1493 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1494 None
1495 }
1496 }
1497
1498 #[cfg(test)]
1499 pub(crate) mod internal {
1500 use net_declare::{net_ip_v4, net_ip_v6, net_subnet_v4, net_subnet_v6};
1501 use net_types::ip::Subnet;
1502 use netstack3_base::{SeqNum, UnscaledWindowSize};
1503
1504 use super::*;
1505
1506 pub trait TestIpExt: IpExt {
1507 const SRC_IP: Self::Addr;
1508 const SRC_PORT: u16 = 1234;
1509 const DST_IP: Self::Addr;
1510 const DST_PORT: u16 = 9876;
1511 const SRC_IP_2: Self::Addr;
1512 const DST_IP_2: Self::Addr;
1513 const IP_OUTSIDE_SUBNET: Self::Addr;
1514 const SUBNET: Subnet<Self::Addr>;
1515 }
1516
1517 impl TestIpExt for Ipv4 {
1518 const SRC_IP: Self::Addr = net_ip_v4!("192.0.2.1");
1519 const DST_IP: Self::Addr = net_ip_v4!("192.0.2.2");
1520 const SRC_IP_2: Self::Addr = net_ip_v4!("192.0.2.3");
1521 const DST_IP_2: Self::Addr = net_ip_v4!("192.0.2.4");
1522 const IP_OUTSIDE_SUBNET: Self::Addr = net_ip_v4!("192.0.3.1");
1523 const SUBNET: Subnet<Self::Addr> = net_subnet_v4!("192.0.2.0/24");
1524 }
1525
1526 impl TestIpExt for Ipv6 {
1527 const SRC_IP: Self::Addr = net_ip_v6!("2001:db8::1");
1528 const DST_IP: Self::Addr = net_ip_v6!("2001:db8::2");
1529 const SRC_IP_2: Self::Addr = net_ip_v6!("2001:db8::3");
1530 const DST_IP_2: Self::Addr = net_ip_v6!("2001:db8::4");
1531 const IP_OUTSIDE_SUBNET: Self::Addr = net_ip_v6!("2001:db8:ffff::1");
1532 const SUBNET: Subnet<Self::Addr> = net_subnet_v6!("2001:db8::/64");
1533 }
1534
1535 #[derive(Clone, Debug, PartialEq)]
1536 pub struct FakeIpPacket<I: IpExt, T>
1537 where
1538 for<'a> &'a T: TransportPacketExt<I>,
1539 {
1540 pub src_ip: I::Addr,
1541 pub dst_ip: I::Addr,
1542 pub body: T,
1543 }
1544
1545 impl<I: IpExt> FakeIpPacket<I, FakeUdpPacket> {
1546 pub(crate) fn reply(&self) -> Self {
1547 Self { src_ip: self.dst_ip, dst_ip: self.src_ip, body: self.body.reply() }
1548 }
1549 }
1550
1551 pub trait TransportPacketExt<I: IpExt>: MaybeTransportPacket {
1552 fn proto() -> I::Proto;
1553 }
1554
1555 impl<I: IpExt, T> IpPacket<I> for FakeIpPacket<I, T>
1556 where
1557 for<'a> &'a T: TransportPacketExt<I>,
1558 for<'a> &'a mut T: MaybeTransportPacketMut<I>,
1559 {
1560 type TransportPacket<'a>
1561 = &'a T
1562 where
1563 T: 'a;
1564 type TransportPacketMut<'a>
1565 = &'a mut T
1566 where
1567 T: 'a;
1568
1569 fn src_addr(&self) -> I::Addr {
1570 self.src_ip
1571 }
1572
1573 fn set_src_addr(&mut self, addr: I::Addr) {
1574 self.src_ip = addr;
1575 }
1576
1577 fn dst_addr(&self) -> I::Addr {
1578 self.dst_ip
1579 }
1580
1581 fn set_dst_addr(&mut self, addr: I::Addr) {
1582 self.dst_ip = addr;
1583 }
1584
1585 fn protocol(&self) -> I::Proto {
1586 <&T>::proto()
1587 }
1588
1589 fn maybe_transport_packet(&self) -> Self::TransportPacket<'_> {
1590 &self.body
1591 }
1592
1593 fn transport_packet_mut(&mut self) -> Self::TransportPacketMut<'_> {
1594 &mut self.body
1595 }
1596 }
1597
1598 #[derive(Clone, Debug, PartialEq)]
1599 pub struct FakeTcpSegment {
1600 pub src_port: u16,
1601 pub dst_port: u16,
1602 pub segment: SegmentHeader,
1603 pub payload_len: usize,
1604 }
1605
1606 impl<I: IpExt> TransportPacketExt<I> for &FakeTcpSegment {
1607 fn proto() -> I::Proto {
1608 I::map_ip_out(
1609 (),
1610 |()| Ipv4Proto::Proto(IpProto::Tcp),
1611 |()| Ipv6Proto::Proto(IpProto::Tcp),
1612 )
1613 }
1614 }
1615
1616 impl MaybeTransportPacket for &FakeTcpSegment {
1617 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1618 Some(TransportPacketData::Tcp {
1619 src_port: self.src_port,
1620 dst_port: self.dst_port,
1621 segment: self.segment.clone(),
1622 payload_len: self.payload_len,
1623 })
1624 }
1625 }
1626
1627 impl<I: IpExt> MaybeTransportPacketMut<I> for FakeTcpSegment {
1628 type TransportPacketMut<'a> = &'a mut Self;
1629
1630 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1631 Some(self)
1632 }
1633 }
1634
1635 impl<I: IpExt> TransportPacketMut<I> for FakeTcpSegment {
1636 fn set_src_port(&mut self, port: NonZeroU16) {
1637 self.src_port = port.get();
1638 }
1639
1640 fn set_dst_port(&mut self, port: NonZeroU16) {
1641 self.dst_port = port.get();
1642 }
1643
1644 fn update_pseudo_header_src_addr(&mut self, _: I::Addr, _: I::Addr) {}
1645
1646 fn update_pseudo_header_dst_addr(&mut self, _: I::Addr, _: I::Addr) {}
1647 }
1648
1649 #[derive(Clone, Debug, PartialEq)]
1650 pub struct FakeUdpPacket {
1651 pub src_port: u16,
1652 pub dst_port: u16,
1653 }
1654
1655 impl FakeUdpPacket {
1656 fn reply(&self) -> Self {
1657 Self { src_port: self.dst_port, dst_port: self.src_port }
1658 }
1659 }
1660
1661 impl<I: IpExt> TransportPacketExt<I> for &FakeUdpPacket {
1662 fn proto() -> I::Proto {
1663 I::map_ip_out(
1664 (),
1665 |()| Ipv4Proto::Proto(IpProto::Udp),
1666 |()| Ipv6Proto::Proto(IpProto::Udp),
1667 )
1668 }
1669 }
1670
1671 impl MaybeTransportPacket for &FakeUdpPacket {
1672 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1673 Some(TransportPacketData::Generic {
1674 src_port: self.src_port,
1675 dst_port: self.dst_port,
1676 })
1677 }
1678 }
1679
1680 impl<I: IpExt> MaybeTransportPacketMut<I> for FakeUdpPacket {
1681 type TransportPacketMut<'a> = &'a mut Self;
1682
1683 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1684 Some(self)
1685 }
1686 }
1687
1688 impl<I: IpExt> TransportPacketMut<I> for FakeUdpPacket {
1689 fn set_src_port(&mut self, port: NonZeroU16) {
1690 self.src_port = port.get();
1691 }
1692
1693 fn set_dst_port(&mut self, port: NonZeroU16) {
1694 self.dst_port = port.get();
1695 }
1696
1697 fn update_pseudo_header_src_addr(&mut self, _: I::Addr, _: I::Addr) {}
1698
1699 fn update_pseudo_header_dst_addr(&mut self, _: I::Addr, _: I::Addr) {}
1700 }
1701
1702 pub struct FakeIcmpEchoRequest {
1703 pub id: u16,
1704 }
1705
1706 impl<I: IpExt> TransportPacketExt<I> for &FakeIcmpEchoRequest {
1707 fn proto() -> I::Proto {
1708 I::map_ip_out((), |()| Ipv4Proto::Icmp, |()| Ipv6Proto::Icmpv6)
1709 }
1710 }
1711
1712 impl MaybeTransportPacket for &FakeIcmpEchoRequest {
1713 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1714 Some(TransportPacketData::Generic { src_port: self.id, dst_port: 0 })
1715 }
1716 }
1717
1718 impl<I: IpExt> MaybeTransportPacketMut<I> for FakeIcmpEchoRequest {
1719 type TransportPacketMut<'a> = &'a mut Self;
1720
1721 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1722 Some(self)
1723 }
1724 }
1725
1726 impl<I: IpExt> TransportPacketMut<I> for FakeIcmpEchoRequest {
1727 fn set_src_port(&mut self, port: NonZeroU16) {
1728 self.id = port.get();
1729 }
1730
1731 fn set_dst_port(&mut self, _: NonZeroU16) {
1732 panic!("cannot set destination port for ICMP echo request")
1733 }
1734
1735 fn update_pseudo_header_src_addr(&mut self, _: I::Addr, _: I::Addr) {}
1736
1737 fn update_pseudo_header_dst_addr(&mut self, _: I::Addr, _: I::Addr) {}
1738 }
1739
1740 pub trait ArbitraryValue {
1741 fn arbitrary_value() -> Self;
1742 }
1743
1744 impl<I, T> ArbitraryValue for FakeIpPacket<I, T>
1745 where
1746 I: TestIpExt,
1747 T: ArbitraryValue,
1748 for<'a> &'a T: TransportPacketExt<I>,
1749 {
1750 fn arbitrary_value() -> Self {
1751 FakeIpPacket { src_ip: I::SRC_IP, dst_ip: I::DST_IP, body: T::arbitrary_value() }
1752 }
1753 }
1754
1755 impl ArbitraryValue for FakeTcpSegment {
1756 fn arbitrary_value() -> Self {
1757 FakeTcpSegment {
1758 src_port: 33333,
1759 dst_port: 44444,
1760 segment: SegmentHeader::arbitrary_value(),
1761 payload_len: 8888,
1762 }
1763 }
1764 }
1765
1766 impl ArbitraryValue for FakeUdpPacket {
1767 fn arbitrary_value() -> Self {
1768 FakeUdpPacket { src_port: 33333, dst_port: 44444 }
1769 }
1770 }
1771
1772 impl ArbitraryValue for FakeIcmpEchoRequest {
1773 fn arbitrary_value() -> Self {
1774 FakeIcmpEchoRequest { id: 1 }
1775 }
1776 }
1777
1778 impl ArbitraryValue for SegmentHeader {
1779 fn arbitrary_value() -> Self {
1780 SegmentHeader {
1781 seq: SeqNum::new(55555),
1782 ack: None,
1783 control: None,
1784 wnd: UnscaledWindowSize::from(1234),
1785 options: Options::default(),
1786 }
1787 }
1788 }
1789 }
1790}
1791
1792#[cfg(test)]
1793mod tests {
1794 use alloc::vec::Vec;
1795 use core::fmt::Debug;
1796 use netstack3_base::{SeqNum, UnscaledWindowSize};
1797
1798 use ip_test_macro::ip_test;
1799 use packet::InnerPacketBuilder as _;
1800 use packet_formats::icmp::IcmpZeroCode;
1801 use packet_formats::tcp::TcpSegmentBuilder;
1802 use test_case::test_case;
1803
1804 use super::testutil::internal::TestIpExt;
1805 use super::*;
1806
1807 const SRC_PORT: NonZeroU16 = NonZeroU16::new(11111).unwrap();
1808 const DST_PORT: NonZeroU16 = NonZeroU16::new(22222).unwrap();
1809 const SRC_PORT_2: NonZeroU16 = NonZeroU16::new(44444).unwrap();
1810 const DST_PORT_2: NonZeroU16 = NonZeroU16::new(55555).unwrap();
1811
1812 const SEQ_NUM: u32 = 1;
1813 const ACK_NUM: Option<u32> = Some(2);
1814 const WINDOW_SIZE: u16 = 3u16;
1815
1816 trait Protocol {
1817 type Serializer<'a, I: IpExt>: TransportPacketSerializer<I, Buffer: packet::ReusableBuffer>
1818 + MaybeTransportPacketMut<I>
1819 + Debug
1820 + PartialEq;
1821
1822 fn proto<I: IpExt>() -> I::Proto;
1823
1824 fn make_serializer_with_ports<'a, I: IpExt>(
1825 src_ip: I::Addr,
1826 dst_ip: I::Addr,
1827 src_port: NonZeroU16,
1828 dst_port: NonZeroU16,
1829 ) -> Self::Serializer<'a, I>;
1830
1831 fn make_serializer<'a, I: IpExt>(
1832 src_ip: I::Addr,
1833 dst_ip: I::Addr,
1834 ) -> Self::Serializer<'a, I> {
1835 Self::make_serializer_with_ports(src_ip, dst_ip, SRC_PORT, DST_PORT)
1836 }
1837
1838 fn make_packet<I: IpExt>(src_ip: I::Addr, dst_ip: I::Addr) -> Vec<u8> {
1839 Self::make_packet_with_ports::<I>(src_ip, dst_ip, SRC_PORT, DST_PORT)
1840 }
1841
1842 fn make_packet_with_ports<I: IpExt>(
1843 src_ip: I::Addr,
1844 dst_ip: I::Addr,
1845 src_port: NonZeroU16,
1846 dst_port: NonZeroU16,
1847 ) -> Vec<u8> {
1848 Self::make_serializer_with_ports::<I>(src_ip, dst_ip, src_port, dst_port)
1849 .serialize_vec_outer()
1850 .expect("serialize packet")
1851 .unwrap_b()
1852 .into_inner()
1853 }
1854 }
1855
1856 struct Udp;
1857
1858 impl Protocol for Udp {
1859 type Serializer<'a, I: IpExt> =
1860 Nested<InnerSerializer<&'a [u8], EmptyBuf>, UdpPacketBuilder<I::Addr>>;
1861
1862 fn proto<I: IpExt>() -> I::Proto {
1863 IpProto::Udp.into()
1864 }
1865
1866 fn make_serializer_with_ports<'a, I: IpExt>(
1867 src_ip: I::Addr,
1868 dst_ip: I::Addr,
1869 src_port: NonZeroU16,
1870 dst_port: NonZeroU16,
1871 ) -> Self::Serializer<'a, I> {
1872 [].into_serializer().encapsulate(UdpPacketBuilder::new(
1873 src_ip,
1874 dst_ip,
1875 Some(src_port),
1876 dst_port,
1877 ))
1878 }
1879 }
1880
1881 impl<A: IpAddress, Inner: PayloadLen> MaybeTransportPacket for Nested<Inner, TcpSegmentBuilder<A>> {
1889 fn transport_packet_data(&self) -> Option<TransportPacketData> {
1890 Some(TransportPacketData::Tcp {
1891 src_port: TcpSegmentBuilder::src_port(self.outer()).map_or(0, NonZeroU16::get),
1892 dst_port: TcpSegmentBuilder::dst_port(self.outer()).map_or(0, NonZeroU16::get),
1893 segment: self.outer().try_into().ok()?,
1894 payload_len: self.inner().len(),
1895 })
1896 }
1897 }
1898
1899 impl<I: IpExt, Inner> MaybeTransportPacketMut<I> for Nested<Inner, TcpSegmentBuilder<I::Addr>> {
1900 type TransportPacketMut<'a>
1901 = &'a mut Self
1902 where
1903 Self: 'a;
1904
1905 fn transport_packet_mut(&mut self) -> Option<Self::TransportPacketMut<'_>> {
1906 Some(self)
1907 }
1908 }
1909
1910 impl<I: IpExt, Inner> TransportPacketMut<I> for Nested<Inner, TcpSegmentBuilder<I::Addr>> {
1911 fn set_src_port(&mut self, port: NonZeroU16) {
1912 self.outer_mut().set_src_port(port);
1913 }
1914
1915 fn set_dst_port(&mut self, port: NonZeroU16) {
1916 self.outer_mut().set_dst_port(port);
1917 }
1918
1919 fn update_pseudo_header_src_addr(&mut self, _old: I::Addr, new: I::Addr) {
1920 self.outer_mut().set_src_ip(new);
1921 }
1922
1923 fn update_pseudo_header_dst_addr(&mut self, _old: I::Addr, new: I::Addr) {
1924 self.outer_mut().set_dst_ip(new);
1925 }
1926 }
1927
1928 struct Tcp;
1929
1930 impl Protocol for Tcp {
1931 type Serializer<'a, I: IpExt> =
1932 Nested<InnerSerializer<&'a [u8], EmptyBuf>, TcpSegmentBuilder<I::Addr>>;
1933
1934 fn proto<I: IpExt>() -> I::Proto {
1935 IpProto::Tcp.into()
1936 }
1937
1938 fn make_serializer_with_ports<'a, I: IpExt>(
1939 src_ip: I::Addr,
1940 dst_ip: I::Addr,
1941 src_port: NonZeroU16,
1942 dst_port: NonZeroU16,
1943 ) -> Self::Serializer<'a, I> {
1944 [1, 2, 3].into_serializer().encapsulate(TcpSegmentBuilder::new(
1945 src_ip,
1946 dst_ip,
1947 src_port,
1948 dst_port,
1949 SEQ_NUM,
1950 ACK_NUM,
1951 WINDOW_SIZE,
1952 ))
1953 }
1954 }
1955
1956 struct IcmpEchoRequest;
1957
1958 impl Protocol for IcmpEchoRequest {
1959 type Serializer<'a, I: IpExt> = Nested<
1960 InnerSerializer<&'a [u8], EmptyBuf>,
1961 IcmpPacketBuilder<I, icmp::IcmpEchoRequest>,
1962 >;
1963
1964 fn proto<I: IpExt>() -> I::Proto {
1965 I::map_ip((), |()| Ipv4Proto::Icmp, |()| Ipv6Proto::Icmpv6)
1966 }
1967
1968 fn make_serializer_with_ports<'a, I: IpExt>(
1969 src_ip: I::Addr,
1970 dst_ip: I::Addr,
1971 src_port: NonZeroU16,
1972 _dst_port: NonZeroU16,
1973 ) -> Self::Serializer<'a, I> {
1974 [].into_serializer().encapsulate(IcmpPacketBuilder::<I, _>::new(
1975 src_ip,
1976 dst_ip,
1977 IcmpZeroCode,
1978 icmp::IcmpEchoRequest::new(src_port.get(), 0),
1979 ))
1980 }
1981 }
1982
1983 struct IcmpEchoReply;
1984
1985 impl Protocol for IcmpEchoReply {
1986 type Serializer<'a, I: IpExt> =
1987 Nested<InnerSerializer<&'a [u8], EmptyBuf>, IcmpPacketBuilder<I, icmp::IcmpEchoReply>>;
1988
1989 fn proto<I: IpExt>() -> I::Proto {
1990 I::map_ip((), |()| Ipv4Proto::Icmp, |()| Ipv6Proto::Icmpv6)
1991 }
1992
1993 fn make_serializer_with_ports<'a, I: IpExt>(
1994 src_ip: I::Addr,
1995 dst_ip: I::Addr,
1996 _src_port: NonZeroU16,
1997 dst_port: NonZeroU16,
1998 ) -> Self::Serializer<'a, I> {
1999 [].into_serializer().encapsulate(IcmpPacketBuilder::<I, _>::new(
2000 src_ip,
2001 dst_ip,
2002 IcmpZeroCode,
2003 icmp::IcmpEchoReply::new(dst_port.get(), 0),
2004 ))
2005 }
2006 }
2007
2008 enum TransportPacketDataProtocol {
2009 Tcp,
2010 Udp,
2011 IcmpEchoRequest,
2012 }
2013
2014 impl TransportPacketDataProtocol {
2015 fn make_packet<I: TestIpExt>(&self, src_ip: I::Addr, dst_ip: I::Addr) -> Vec<u8> {
2016 match self {
2017 TransportPacketDataProtocol::Tcp => Tcp::make_packet::<I>(src_ip, dst_ip),
2018 TransportPacketDataProtocol::Udp => Udp::make_packet::<I>(src_ip, dst_ip),
2019 TransportPacketDataProtocol::IcmpEchoRequest => {
2020 IcmpEchoRequest::make_packet::<I>(src_ip, dst_ip)
2021 }
2022 }
2023 }
2024
2025 fn proto<I: TestIpExt>(&self) -> I::Proto {
2026 match self {
2027 TransportPacketDataProtocol::Tcp => Tcp::proto::<I>(),
2028 TransportPacketDataProtocol::Udp => Udp::proto::<I>(),
2029 TransportPacketDataProtocol::IcmpEchoRequest => IcmpEchoRequest::proto::<I>(),
2030 }
2031 }
2032 }
2033
2034 #[ip_test(I)]
2035 #[test_case(TransportPacketDataProtocol::Udp)]
2036 #[test_case(TransportPacketDataProtocol::Tcp)]
2037 #[test_case(TransportPacketDataProtocol::IcmpEchoRequest)]
2038 fn transport_packet_data_from_serialized<I: TestIpExt>(proto: TransportPacketDataProtocol) {
2039 let expected_data = match proto {
2040 TransportPacketDataProtocol::Tcp => TransportPacketData::Tcp {
2041 src_port: SRC_PORT.get(),
2042 dst_port: DST_PORT.get(),
2043 segment: SegmentHeader {
2044 seq: SeqNum::new(SEQ_NUM),
2045 ack: ACK_NUM.map(SeqNum::new),
2046 control: None,
2047 wnd: UnscaledWindowSize::from(WINDOW_SIZE),
2048 options: Options::default(),
2049 },
2050 payload_len: 3,
2051 },
2052 TransportPacketDataProtocol::Udp => {
2053 TransportPacketData::Generic { src_port: SRC_PORT.get(), dst_port: DST_PORT.get() }
2054 }
2055 TransportPacketDataProtocol::IcmpEchoRequest => {
2056 TransportPacketData::Generic { src_port: SRC_PORT.get(), dst_port: SRC_PORT.get() }
2057 }
2058 };
2059
2060 let buf = proto.make_packet::<I>(I::SRC_IP, I::DST_IP);
2061 let parsed_data = TransportPacketData::parse_in_ip_packet::<I, _>(
2062 I::SRC_IP,
2063 I::DST_IP,
2064 proto.proto::<I>(),
2065 buf.as_slice(),
2066 )
2067 .expect("failed to parse transport packet data");
2068
2069 assert_eq!(parsed_data, expected_data);
2070 }
2071
2072 #[ip_test(I)]
2073 #[test_case(Udp)]
2074 #[test_case(Tcp)]
2075 #[test_case(IcmpEchoRequest)]
2076 fn update_pseudo_header_address_updates_checksum<I: TestIpExt, P: Protocol>(_proto: P) {
2077 let mut buf = P::make_packet::<I>(I::SRC_IP, I::DST_IP);
2078 let view = SliceBufViewMut::new(&mut buf);
2079
2080 let mut packet = ParsedTransportHeaderMut::<I>::parse_in_ip_packet(
2081 I::SRC_IP,
2082 I::DST_IP,
2083 P::proto::<I>(),
2084 view,
2085 )
2086 .expect("parse transport header");
2087 packet.update_pseudo_header_src_addr(I::SRC_IP, I::SRC_IP_2);
2088 packet.update_pseudo_header_dst_addr(I::DST_IP, I::DST_IP_2);
2089 drop(packet);
2092
2093 let equivalent = P::make_packet::<I>(I::SRC_IP_2, I::DST_IP_2);
2094
2095 assert_eq!(equivalent, buf);
2096 }
2097
2098 #[ip_test(I)]
2099 #[test_case(Udp, true, true)]
2100 #[test_case(Tcp, true, true)]
2101 #[test_case(IcmpEchoRequest, true, false)]
2102 #[test_case(IcmpEchoReply, false, true)]
2103 fn parsed_packet_update_src_dst_port_updates_checksum<I: TestIpExt, P: Protocol>(
2104 _proto: P,
2105 update_src_port: bool,
2106 update_dst_port: bool,
2107 ) {
2108 let mut buf = P::make_packet_with_ports::<I>(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT);
2109 let view = SliceBufViewMut::new(&mut buf);
2110
2111 let mut packet = ParsedTransportHeaderMut::<I>::parse_in_ip_packet(
2112 I::SRC_IP,
2113 I::DST_IP,
2114 P::proto::<I>(),
2115 view,
2116 )
2117 .expect("parse transport header");
2118 let expected_src_port = if update_src_port {
2119 packet.set_src_port(SRC_PORT_2);
2120 SRC_PORT_2
2121 } else {
2122 SRC_PORT
2123 };
2124 let expected_dst_port = if update_dst_port {
2125 packet.set_dst_port(DST_PORT_2);
2126 DST_PORT_2
2127 } else {
2128 DST_PORT
2129 };
2130 drop(packet);
2131
2132 let equivalent = P::make_packet_with_ports::<I>(
2133 I::SRC_IP,
2134 I::DST_IP,
2135 expected_src_port,
2136 expected_dst_port,
2137 );
2138
2139 assert_eq!(equivalent, buf);
2140 }
2141
2142 #[ip_test(I)]
2143 #[test_case(Udp)]
2144 #[test_case(Tcp)]
2145 fn serializer_update_src_dst_port_updates_checksum<I: TestIpExt, P: Protocol>(_proto: P) {
2146 let mut serializer =
2147 P::make_serializer_with_ports::<I>(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT);
2148 let mut packet =
2149 serializer.transport_packet_mut().expect("packet should support rewriting");
2150 packet.set_src_port(SRC_PORT_2);
2151 packet.set_dst_port(DST_PORT_2);
2152 drop(packet);
2153
2154 let equivalent =
2155 P::make_serializer_with_ports::<I>(I::SRC_IP, I::DST_IP, SRC_PORT_2, DST_PORT_2);
2156
2157 assert_eq!(equivalent, serializer);
2158 }
2159
2160 #[ip_test(I)]
2161 fn icmp_echo_request_update_id_port_updates_checksum<I: TestIpExt>() {
2162 let mut serializer = [].into_serializer().encapsulate(IcmpPacketBuilder::<I, _>::new(
2163 I::SRC_IP,
2164 I::DST_IP,
2165 IcmpZeroCode,
2166 icmp::IcmpEchoRequest::new(SRC_PORT.get(), 0),
2167 ));
2168 serializer
2169 .transport_packet_mut()
2170 .expect("packet should support rewriting")
2171 .set_src_port(SRC_PORT_2);
2172
2173 let equivalent = [].into_serializer().encapsulate(IcmpPacketBuilder::<I, _>::new(
2174 I::SRC_IP,
2175 I::DST_IP,
2176 IcmpZeroCode,
2177 icmp::IcmpEchoRequest::new(SRC_PORT_2.get(), 0),
2178 ));
2179
2180 assert_eq!(equivalent, serializer);
2181 }
2182
2183 #[ip_test(I)]
2184 fn icmp_echo_reply_update_id_port_updates_checksum<I: TestIpExt>() {
2185 let mut serializer = [].into_serializer().encapsulate(IcmpPacketBuilder::<I, _>::new(
2186 I::SRC_IP,
2187 I::DST_IP,
2188 IcmpZeroCode,
2189 icmp::IcmpEchoReply::new(SRC_PORT.get(), 0),
2190 ));
2191 serializer
2192 .transport_packet_mut()
2193 .expect("packet should support rewriting")
2194 .set_dst_port(SRC_PORT_2);
2195
2196 let equivalent = [].into_serializer().encapsulate(IcmpPacketBuilder::<I, _>::new(
2197 I::SRC_IP,
2198 I::DST_IP,
2199 IcmpZeroCode,
2200 icmp::IcmpEchoReply::new(SRC_PORT_2.get(), 0),
2201 ));
2202
2203 assert_eq!(equivalent, serializer);
2204 }
2205
2206 #[test]
2207 #[should_panic]
2208 fn icmp_serializer_set_port_panics_on_unsupported_type() {
2209 let mut serializer = [].into_serializer().encapsulate(IcmpPacketBuilder::new(
2210 Ipv4::SRC_IP,
2211 Ipv4::DST_IP,
2212 IcmpZeroCode,
2213 icmp::Icmpv4TimestampRequest::new(
2214 0,
2215 SRC_PORT.get(),
2216 0,
2217 )
2218 .reply(0, 0),
2219 ));
2220 let Some(packet) = serializer.transport_packet_mut() else {
2221 return;
2225 };
2226 packet.set_src_port(SRC_PORT_2);
2227 }
2228
2229 fn ip_packet<I: IpExt, P: Protocol>(src: I::Addr, dst: I::Addr) -> Buf<Vec<u8>> {
2230 Buf::new(P::make_packet::<I>(src, dst), ..)
2231 .encapsulate(I::PacketBuilder::new(src, dst, u8::MAX, P::proto::<I>()))
2232 .serialize_vec_outer()
2233 .expect("serialize IP packet")
2234 .unwrap_b()
2235 }
2236
2237 #[ip_test(I)]
2238 #[test_case(Udp)]
2239 #[test_case(Tcp)]
2240 #[test_case(IcmpEchoRequest)]
2241 fn ip_packet_set_src_dst_addr_updates_checksums<I: TestIpExt, P: Protocol>(_proto: P)
2242 where
2243 for<'a> I::Packet<&'a mut [u8]>: IpPacket<I>,
2244 {
2245 let mut buf = ip_packet::<I, P>(I::SRC_IP, I::DST_IP).into_inner();
2246
2247 let mut packet =
2248 I::Packet::parse_mut(SliceBufViewMut::new(&mut buf), ()).expect("parse IP packet");
2249 packet.set_src_addr(I::SRC_IP_2);
2250 packet.set_dst_addr(I::DST_IP_2);
2251 drop(packet);
2252
2253 let equivalent = ip_packet::<I, P>(I::SRC_IP_2, I::DST_IP_2).into_inner();
2254
2255 assert_eq!(equivalent, buf);
2256 }
2257
2258 #[ip_test(I)]
2259 #[test_case(Udp)]
2260 #[test_case(Tcp)]
2261 #[test_case(IcmpEchoRequest)]
2262 fn forwarded_packet_set_src_dst_addr_updates_checksums<I: TestIpExt, P: Protocol>(_proto: P) {
2263 let mut buffer = ip_packet::<I, P>(I::SRC_IP, I::DST_IP);
2264 let meta = buffer.parse::<I::Packet<_>>().expect("parse IP packet").parse_metadata();
2265 let mut packet =
2266 ForwardedPacket::<I, _>::new(I::SRC_IP, I::DST_IP, P::proto::<I>(), meta, buffer);
2267 packet.set_src_addr(I::SRC_IP_2);
2268 packet.set_dst_addr(I::DST_IP_2);
2269
2270 let mut buffer = ip_packet::<I, P>(I::SRC_IP_2, I::DST_IP_2);
2271 let meta = buffer.parse::<I::Packet<_>>().expect("parse IP packet").parse_metadata();
2272 let equivalent =
2273 ForwardedPacket::<I, _>::new(I::SRC_IP_2, I::DST_IP_2, P::proto::<I>(), meta, buffer);
2274
2275 assert_eq!(equivalent, packet);
2276 }
2277
2278 #[ip_test(I)]
2279 #[test_case(Udp)]
2280 #[test_case(Tcp)]
2281 #[test_case(IcmpEchoRequest)]
2282 fn tx_packet_set_src_dst_addr_updates_checksums<I: TestIpExt, P: Protocol>(_proto: P) {
2283 let mut body = P::make_serializer::<I>(I::SRC_IP, I::DST_IP);
2284 let mut packet = TxPacket::<I, _>::new(I::SRC_IP, I::DST_IP, P::proto::<I>(), &mut body);
2285 packet.set_src_addr(I::SRC_IP_2);
2286 packet.set_dst_addr(I::DST_IP_2);
2287
2288 let mut equivalent_body = P::make_serializer::<I>(I::SRC_IP_2, I::DST_IP_2);
2289 let equivalent =
2290 TxPacket::new(I::SRC_IP_2, I::DST_IP_2, P::proto::<I>(), &mut equivalent_body);
2291
2292 assert_eq!(equivalent, packet);
2293 }
2294
2295 #[ip_test(I)]
2296 #[test_case(Udp)]
2297 #[test_case(Tcp)]
2298 #[test_case(IcmpEchoRequest)]
2299 fn nested_serializer_set_src_dst_addr_updates_checksums<I: TestIpExt, P: Protocol>(_proto: P) {
2300 let mut packet = P::make_serializer::<I>(I::SRC_IP, I::DST_IP).encapsulate(
2301 I::PacketBuilder::new(I::SRC_IP, I::DST_IP, u8::MAX, P::proto::<I>()),
2302 );
2303 packet.set_src_addr(I::SRC_IP_2);
2304 packet.set_dst_addr(I::DST_IP_2);
2305
2306 let equivalent =
2307 P::make_serializer::<I>(I::SRC_IP_2, I::DST_IP_2).encapsulate(I::PacketBuilder::new(
2308 I::SRC_IP_2,
2309 I::DST_IP_2,
2310 u8::MAX,
2311 P::proto::<I>(),
2312 ));
2313
2314 assert_eq!(equivalent, packet);
2315 }
2316}