1use core::cmp::Ordering;
8use core::convert::Infallible;
9use core::num::NonZeroU8;
10
11use log::error;
12use net_types::ip::{Ip, IpVersionMarker, Ipv6Addr, Mtu};
13use net_types::{MulticastAddress, ScopeableAddress, SpecifiedAddr};
14use netstack3_base::socket::{SocketIpAddr, SocketIpAddrExt as _};
15use netstack3_base::{
16 AnyDevice, CounterContext, DeviceIdContext, DeviceIdentifier, EitherDeviceId, InstantContext,
17 IpDeviceAddr, IpExt, Marks, Mms, SendFrameErrorReason, StrongDeviceIdentifier,
18 TxMetadataBindingsTypes, WeakDeviceIdentifier,
19};
20use netstack3_filter::{
21 self as filter, FilterBindingsContext, FilterHandler as _, InterfaceProperties, RawIpBody,
22 TransportPacketSerializer,
23};
24use netstack3_trace::trace_duration;
25use packet::{BufferMut, PacketConstraints, SerializeError};
26use packet_formats::ip::DscpAndEcn;
27use thiserror::Error;
28
29use crate::internal::base::{
30 FilterHandlerProvider, IpCounters, IpDeviceMtuContext, IpLayerIpExt, IpLayerPacketMetadata,
31 IpPacketDestination, IpSendFrameError, IpSendFrameErrorReason, ResolveRouteError,
32 SendIpPacketMeta,
33};
34use crate::internal::device::state::IpDeviceStateIpExt;
35use crate::internal::routing::rules::RuleInput;
36use crate::internal::routing::PacketOrigin;
37use crate::internal::types::{InternalForwarding, ResolvedRoute, RoutableIpAddr};
38use crate::{HopLimits, NextHop};
39
40pub trait IpSocketHandler<I: IpExt, BC: TxMetadataBindingsTypes>:
42 DeviceIdContext<AnyDevice>
43{
44 fn new_ip_socket<O>(
59 &mut self,
60 bindings_ctx: &mut BC,
61 device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
62 local_ip: Option<IpDeviceAddr<I::Addr>>,
63 remote_ip: SocketIpAddr<I::Addr>,
64 proto: I::Proto,
65 options: &O,
66 ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
67 where
68 O: RouteResolutionOptions<I>;
69
70 fn send_ip_packet<S, O>(
83 &mut self,
84 bindings_ctx: &mut BC,
85 socket: &IpSock<I, Self::WeakDeviceId>,
86 body: S,
87 options: &O,
88 tx_metadata: BC::TxMetadata,
89 ) -> Result<(), IpSockSendError>
90 where
91 S: TransportPacketSerializer<I>,
92 S::Buffer: BufferMut,
93 O: SendOptions<I> + RouteResolutionOptions<I>;
94
95 fn confirm_reachable<O>(
101 &mut self,
102 bindings_ctx: &mut BC,
103 socket: &IpSock<I, Self::WeakDeviceId>,
104 options: &O,
105 ) where
106 O: RouteResolutionOptions<I>;
107
108 fn send_oneshot_ip_packet_with_fallible_serializer<S, E, F, O>(
131 &mut self,
132 bindings_ctx: &mut BC,
133 device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
134 local_ip: Option<IpDeviceAddr<I::Addr>>,
135 remote_ip: RoutableIpAddr<I::Addr>,
136 proto: I::Proto,
137 options: &O,
138 tx_metadata: BC::TxMetadata,
139 get_body_from_src_ip: F,
140 ) -> Result<(), SendOneShotIpPacketError<E>>
141 where
142 S: TransportPacketSerializer<I>,
143 S::Buffer: BufferMut,
144 F: FnOnce(IpDeviceAddr<I::Addr>) -> Result<S, E>,
145 O: SendOptions<I> + RouteResolutionOptions<I>,
146 {
147 let tmp = self
148 .new_ip_socket(bindings_ctx, device, local_ip, remote_ip, proto, options)
149 .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })?;
150 let packet = get_body_from_src_ip(*tmp.local_ip())
151 .map_err(SendOneShotIpPacketError::SerializeError)?;
152 self.send_ip_packet(bindings_ctx, &tmp, packet, options, tx_metadata)
153 .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })
154 }
155
156 fn send_oneshot_ip_packet<S, F, O>(
158 &mut self,
159 bindings_ctx: &mut BC,
160 device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
161 local_ip: Option<IpDeviceAddr<I::Addr>>,
162 remote_ip: SocketIpAddr<I::Addr>,
163 proto: I::Proto,
164 options: &O,
165 tx_metadata: BC::TxMetadata,
166 get_body_from_src_ip: F,
167 ) -> Result<(), IpSockCreateAndSendError>
168 where
169 S: TransportPacketSerializer<I>,
170 S::Buffer: BufferMut,
171 F: FnOnce(IpDeviceAddr<I::Addr>) -> S,
172 O: SendOptions<I> + RouteResolutionOptions<I>,
173 {
174 self.send_oneshot_ip_packet_with_fallible_serializer(
175 bindings_ctx,
176 device,
177 local_ip,
178 remote_ip,
179 proto,
180 options,
181 tx_metadata,
182 |ip| Ok::<_, Infallible>(get_body_from_src_ip(ip)),
183 )
184 .map_err(|err| match err {
185 SendOneShotIpPacketError::CreateAndSendError { err } => err,
186 })
187 }
188}
189
190#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
192pub enum IpSockSendError {
193 #[error("a maximum transmission unit (MTU) was exceeded")]
198 Mtu,
199 #[error("the socket is currently unroutable: {0}")]
201 Unroutable(#[from] ResolveRouteError),
202 #[error("illegal loopback address")]
205 IllegalLoopbackAddress,
206 #[error("Broadcast send is not enabled for the socket")]
208 BroadcastNotAllowed,
209}
210
211impl From<SerializeError<Infallible>> for IpSockSendError {
212 fn from(err: SerializeError<Infallible>) -> IpSockSendError {
213 match err {
214 SerializeError::SizeLimitExceeded => IpSockSendError::Mtu,
215 }
216 }
217}
218
219impl IpSockSendError {
220 fn from_ip_send_frame(e: IpSendFrameErrorReason) -> Result<(), Self> {
225 match e {
226 IpSendFrameErrorReason::Device(d) => Self::from_send_frame(d),
227 IpSendFrameErrorReason::IllegalLoopbackAddress => Err(Self::IllegalLoopbackAddress),
228 }
229 }
230
231 fn from_send_frame(e: SendFrameErrorReason) -> Result<(), Self> {
236 match e {
237 SendFrameErrorReason::Alloc | SendFrameErrorReason::QueueFull => Ok(()),
238 SendFrameErrorReason::SizeConstraintsViolation => Err(Self::Mtu),
239 }
240 }
241}
242
243#[derive(Error, Copy, Clone, Debug)]
245pub enum IpSockCreateAndSendError {
246 #[error("cannot send via temporary socket: {0}")]
248 Send(#[from] IpSockSendError),
249 #[error("the temporary socket could not be created: {0}")]
251 Create(#[from] IpSockCreationError),
252}
253
254#[derive(Debug)]
257#[allow(missing_docs)]
258pub enum SendOneShotIpPacketError<E> {
259 CreateAndSendError { err: IpSockCreateAndSendError },
260 SerializeError(E),
261}
262
263#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
265pub enum MmsError {
266 #[error("cannot find the device: {0}")]
269 NoDevice(#[from] ResolveRouteError),
270 #[error("invalid MTU: {0:?}")]
273 MTUTooSmall(Mtu),
274}
275
276pub trait DeviceIpSocketHandler<I: IpExt, BC>: DeviceIdContext<AnyDevice> {
278 fn get_mms<O: RouteResolutionOptions<I>>(
284 &mut self,
285 bindings_ctx: &mut BC,
286 ip_sock: &IpSock<I, Self::WeakDeviceId>,
287 options: &O,
288 ) -> Result<Mms, MmsError>;
289}
290
291#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
293pub enum IpSockCreationError {
294 #[error("a route cannot be determined: {0}")]
296 Route(#[from] ResolveRouteError),
297}
298
299#[derive(Clone, Debug)]
301#[cfg_attr(test, derive(PartialEq))]
302pub struct IpSock<I: IpExt, D> {
303 definition: IpSockDefinition<I, D>,
307}
308
309impl<I: IpExt, D> IpSock<I, D> {
310 #[cfg(any(test, feature = "testutils"))]
312 pub fn definition(&self) -> &IpSockDefinition<I, D> {
313 &self.definition
314 }
315}
316
317#[derive(Clone, Debug, PartialEq)]
321pub struct IpSockDefinition<I: IpExt, D> {
322 pub remote_ip: SocketIpAddr<I::Addr>,
324 pub local_ip: IpDeviceAddr<I::Addr>,
335 pub device: Option<D>,
337 pub proto: I::Proto,
339}
340
341impl<I: IpExt, D> IpSock<I, D> {
342 pub fn local_ip(&self) -> &IpDeviceAddr<I::Addr> {
344 &self.definition.local_ip
345 }
346 pub fn remote_ip(&self) -> &SocketIpAddr<I::Addr> {
348 &self.definition.remote_ip
349 }
350 pub fn device(&self) -> Option<&D> {
352 self.definition.device.as_ref()
353 }
354 pub fn proto(&self) -> I::Proto {
356 self.definition.proto
357 }
358}
359
360pub trait IpSocketBindingsContext:
367 InstantContext + FilterBindingsContext + TxMetadataBindingsTypes
368{
369}
370impl<BC: InstantContext + FilterBindingsContext + TxMetadataBindingsTypes> IpSocketBindingsContext
371 for BC
372{
373}
374
375pub trait IpSocketContext<I, BC: IpSocketBindingsContext>:
380 DeviceIdContext<AnyDevice, DeviceId: InterfaceProperties<BC::DeviceClass>>
381 + FilterHandlerProvider<I, BC>
382where
383 I: IpDeviceStateIpExt + IpExt,
384{
385 fn lookup_route(
390 &mut self,
391 bindings_ctx: &mut BC,
392 device: Option<&Self::DeviceId>,
393 src_ip: Option<IpDeviceAddr<I::Addr>>,
394 dst_ip: RoutableIpAddr<I::Addr>,
395 transparent: bool,
396 marks: &Marks,
397 ) -> Result<ResolvedRoute<I, Self::DeviceId>, ResolveRouteError>;
398
399 fn send_ip_packet<S>(
401 &mut self,
402 bindings_ctx: &mut BC,
403 meta: SendIpPacketMeta<I, &Self::DeviceId, SpecifiedAddr<I::Addr>>,
404 body: S,
405 packet_metadata: IpLayerPacketMetadata<I, Self::WeakAddressId, BC>,
406 ) -> Result<(), IpSendFrameError<S>>
407 where
408 S: TransportPacketSerializer<I>,
409 S::Buffer: BufferMut;
410
411 fn get_loopback_device(&mut self) -> Option<Self::DeviceId>;
413
414 fn confirm_reachable(
420 &mut self,
421 bindings_ctx: &mut BC,
422 dst: SpecifiedAddr<I::Addr>,
423 input: RuleInput<'_, I, Self::DeviceId>,
424 );
425}
426
427pub trait UseIpSocketHandlerBlanket {}
432
433impl<I, BC, CC> IpSocketHandler<I, BC> for CC
434where
435 I: IpLayerIpExt + IpDeviceStateIpExt,
436 BC: IpSocketBindingsContext,
437 CC: IpSocketContext<I, BC> + CounterContext<IpCounters<I>> + UseIpSocketHandlerBlanket,
438 CC::DeviceId: filter::InterfaceProperties<BC::DeviceClass>,
439{
440 fn new_ip_socket<O>(
441 &mut self,
442 bindings_ctx: &mut BC,
443 device: Option<EitherDeviceId<&CC::DeviceId, &CC::WeakDeviceId>>,
444 local_ip: Option<IpDeviceAddr<I::Addr>>,
445 remote_ip: SocketIpAddr<I::Addr>,
446 proto: I::Proto,
447 options: &O,
448 ) -> Result<IpSock<I, CC::WeakDeviceId>, IpSockCreationError>
449 where
450 O: RouteResolutionOptions<I>,
451 {
452 let device = device
453 .as_ref()
454 .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
455 .transpose()?;
456 let device = device.as_ref().map(|d| d.as_ref());
457
458 let resolved_route = self.lookup_route(
463 bindings_ctx,
464 device,
465 local_ip,
466 remote_ip,
467 options.transparent(),
468 options.marks(),
469 )?;
470 Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
471 }
472
473 fn send_ip_packet<S, O>(
474 &mut self,
475 bindings_ctx: &mut BC,
476 ip_sock: &IpSock<I, CC::WeakDeviceId>,
477 body: S,
478 options: &O,
479 tx_metadata: BC::TxMetadata,
480 ) -> Result<(), IpSockSendError>
481 where
482 S: TransportPacketSerializer<I>,
483 S::Buffer: BufferMut,
484 O: SendOptions<I> + RouteResolutionOptions<I>,
485 {
486 self.counters().send_ip_packet.increment();
488
489 send_ip_packet(self, bindings_ctx, ip_sock, body, options, tx_metadata)
490 }
491
492 fn confirm_reachable<O>(
493 &mut self,
494 bindings_ctx: &mut BC,
495 socket: &IpSock<I, CC::WeakDeviceId>,
496 options: &O,
497 ) where
498 O: RouteResolutionOptions<I>,
499 {
500 let bound_device = socket.device().and_then(|weak| weak.upgrade());
501 let bound_device = bound_device.as_ref();
502 let bound_address = Some((*socket.local_ip()).into());
503 let destination = (*socket.remote_ip()).into();
504 IpSocketContext::confirm_reachable(
505 self,
506 bindings_ctx,
507 destination,
508 RuleInput {
509 packet_origin: PacketOrigin::Local { bound_address, bound_device },
510 marks: options.marks(),
511 },
512 )
513 }
514}
515
516pub trait RouteResolutionOptions<I: Ip> {
528 fn transparent(&self) -> bool;
533
534 fn marks(&self) -> &Marks;
536}
537
538pub trait SendOptions<I: IpExt> {
546 fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8>;
552
553 fn multicast_loop(&self) -> bool;
556
557 fn allow_broadcast(&self) -> Option<I::BroadcastMarker>;
559
560 fn dscp_and_ecn(&self) -> DscpAndEcn;
562
563 fn mtu(&self) -> Mtu;
568}
569
570#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
572pub struct DefaultIpSocketOptions;
573
574impl<I: IpExt> SendOptions<I> for DefaultIpSocketOptions {
575 fn hop_limit(&self, _destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
576 None
577 }
578
579 fn multicast_loop(&self) -> bool {
580 false
581 }
582
583 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
584 None
585 }
586
587 fn dscp_and_ecn(&self) -> DscpAndEcn {
588 DscpAndEcn::default()
589 }
590
591 fn mtu(&self) -> Mtu {
592 Mtu::no_limit()
593 }
594}
595
596impl<I: Ip> RouteResolutionOptions<I> for DefaultIpSocketOptions {
597 fn transparent(&self) -> bool {
598 false
599 }
600
601 fn marks(&self) -> &Marks {
602 &Marks::UNMARKED
603 }
604}
605
606#[allow(missing_docs)]
614pub trait DelegatedSendOptions<I: IpExt>: OptionDelegationMarker {
615 fn delegate(&self) -> &impl SendOptions<I> {
617 &DefaultIpSocketOptions
618 }
619
620 fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
621 self.delegate().hop_limit(destination)
622 }
623
624 fn multicast_loop(&self) -> bool {
625 self.delegate().multicast_loop()
626 }
627
628 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
629 self.delegate().allow_broadcast()
630 }
631
632 fn dscp_and_ecn(&self) -> DscpAndEcn {
633 self.delegate().dscp_and_ecn()
634 }
635
636 fn mtu(&self) -> Mtu {
637 self.delegate().mtu()
638 }
639}
640
641impl<O: DelegatedSendOptions<I> + OptionDelegationMarker, I: IpExt> SendOptions<I> for O {
642 fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
643 self.hop_limit(destination)
644 }
645
646 fn multicast_loop(&self) -> bool {
647 self.multicast_loop()
648 }
649
650 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
651 self.allow_broadcast()
652 }
653
654 fn dscp_and_ecn(&self) -> DscpAndEcn {
655 self.dscp_and_ecn()
656 }
657
658 fn mtu(&self) -> Mtu {
659 self.mtu()
660 }
661}
662
663#[allow(missing_docs)]
671pub trait DelegatedRouteResolutionOptions<I: Ip>: OptionDelegationMarker {
672 fn delegate(&self) -> &impl RouteResolutionOptions<I> {
674 &DefaultIpSocketOptions
675 }
676
677 fn transparent(&self) -> bool {
678 self.delegate().transparent()
679 }
680
681 fn marks(&self) -> &Marks {
682 self.delegate().marks()
683 }
684}
685
686impl<O: DelegatedRouteResolutionOptions<I> + OptionDelegationMarker, I: IpExt>
687 RouteResolutionOptions<I> for O
688{
689 fn transparent(&self) -> bool {
690 self.transparent()
691 }
692
693 fn marks(&self) -> &Marks {
694 self.marks()
695 }
696}
697
698pub trait OptionDelegationMarker {}
703
704#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
706pub struct SocketHopLimits<I: Ip> {
707 pub unicast: Option<NonZeroU8>,
709 pub multicast: Option<NonZeroU8>,
713 pub version: IpVersionMarker<I>,
717}
718
719impl<I: Ip> SocketHopLimits<I> {
720 pub fn set_unicast(value: Option<NonZeroU8>) -> impl FnOnce(&mut Self) {
722 move |limits| limits.unicast = value
723 }
724
725 pub fn set_multicast(value: Option<NonZeroU8>) -> impl FnOnce(&mut Self) {
727 move |limits| limits.multicast = value
728 }
729
730 pub fn get_limits_with_defaults(&self, defaults: &HopLimits) -> HopLimits {
732 let Self { unicast, multicast, version: _ } = self;
733 HopLimits {
734 unicast: unicast.unwrap_or(defaults.unicast),
735 multicast: multicast.unwrap_or(defaults.multicast),
736 }
737 }
738
739 pub fn hop_limit_for_dst(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
741 let Self { unicast, multicast, version: _ } = self;
742 if destination.is_multicast() {
743 *multicast
744 } else {
745 *unicast
746 }
747 }
748}
749
750fn new_ip_socket<I, D>(
751 requested_device: Option<&D>,
752 route: ResolvedRoute<I, D>,
753 remote_ip: SocketIpAddr<I::Addr>,
754 proto: I::Proto,
755) -> IpSock<I, D::Weak>
756where
757 I: IpExt,
758 D: StrongDeviceIdentifier,
759{
760 let ResolvedRoute {
764 src_addr,
765 device: route_device,
766 local_delivery_device,
767 next_hop: _,
768 internal_forwarding: _,
769 } = route;
770
771 let socket_device = (src_addr.as_ref().must_have_zone() || remote_ip.as_ref().must_have_zone())
774 .then(|| {
775 local_delivery_device.unwrap_or(route_device)
779 })
780 .as_ref()
781 .or(requested_device)
782 .map(|d| d.downgrade());
783
784 let definition =
785 IpSockDefinition { local_ip: src_addr, remote_ip, device: socket_device, proto };
786 IpSock { definition }
787}
788
789fn send_ip_packet<I, S, BC, CC, O>(
790 core_ctx: &mut CC,
791 bindings_ctx: &mut BC,
792 socket: &IpSock<I, CC::WeakDeviceId>,
793 mut body: S,
794 options: &O,
795 tx_metadata: BC::TxMetadata,
796) -> Result<(), IpSockSendError>
797where
798 I: IpExt + IpDeviceStateIpExt,
799 S: TransportPacketSerializer<I>,
800 S::Buffer: BufferMut,
801 BC: IpSocketBindingsContext,
802 CC: IpSocketContext<I, BC>,
803 CC::DeviceId: filter::InterfaceProperties<BC::DeviceClass>,
804 O: SendOptions<I> + RouteResolutionOptions<I>,
805{
806 trace_duration!(c"ip::send_packet");
807
808 fn resolve<
811 I: IpExt + IpDeviceStateIpExt,
812 CC: IpSocketContext<I, BC>,
813 BC: IpSocketBindingsContext,
814 >(
815 core_ctx: &mut CC,
816 bindings_ctx: &mut BC,
817 device: &Option<CC::WeakDeviceId>,
818 local_ip: IpDeviceAddr<I::Addr>,
819 remote_ip: RoutableIpAddr<I::Addr>,
820 transparent: bool,
821 marks: &Marks,
822 ) -> Result<ResolvedRoute<I, CC::DeviceId>, IpSockSendError> {
823 let device = match device.as_ref().map(|d| d.upgrade()) {
824 Some(Some(device)) => Some(device),
825 Some(None) => return Err(ResolveRouteError::Unreachable.into()),
826 None => None,
827 };
828 let route = core_ctx
829 .lookup_route(
830 bindings_ctx,
831 device.as_ref(),
832 Some(local_ip),
833 remote_ip,
834 transparent,
835 marks,
836 )
837 .map_err(|e| IpSockSendError::Unroutable(e))?;
838 assert_eq!(local_ip, route.src_addr);
839 Ok(route)
840 }
841
842 let IpSock {
843 definition: IpSockDefinition { remote_ip, local_ip, device: socket_device, proto },
844 } = socket;
845 let ResolvedRoute {
846 src_addr: local_ip,
847 device: mut egress_device,
848 mut next_hop,
849 mut local_delivery_device,
850 mut internal_forwarding,
851 } = resolve(
852 core_ctx,
853 bindings_ctx,
854 socket_device,
855 *local_ip,
856 *remote_ip,
857 options.transparent(),
858 options.marks(),
859 )?;
860
861 if matches!(next_hop, NextHop::Broadcast(_)) && options.allow_broadcast().is_none() {
862 return Err(IpSockSendError::BroadcastNotAllowed);
863 }
864
865 let previous_dst = remote_ip.addr();
866 let mut packet = filter::TxPacket::new(local_ip.addr(), remote_ip.addr(), *proto, &mut body);
867 let mut packet_metadata =
868 IpLayerPacketMetadata::from_tx_metadata_and_marks(tx_metadata, *options.marks());
869
870 match core_ctx.filter_handler().local_egress_hook(
871 bindings_ctx,
872 &mut packet,
873 &egress_device,
874 &mut packet_metadata,
875 ) {
876 filter::Verdict::Drop => {
877 packet_metadata.acknowledge_drop();
878 return Ok(());
879 }
880 filter::Verdict::Accept(()) => {}
881 }
882
883 let Some(mut local_ip) = IpDeviceAddr::new(packet.src_addr()) else {
884 packet_metadata.acknowledge_drop();
885 return Err(IpSockSendError::Unroutable(ResolveRouteError::NoSrcAddr));
886 };
887 let Some(remote_ip) = RoutableIpAddr::new(packet.dst_addr()) else {
888 packet_metadata.acknowledge_drop();
889 return Err(IpSockSendError::Unroutable(ResolveRouteError::Unreachable));
890 };
891
892 if remote_ip.addr() != previous_dst {
895 let ResolvedRoute {
896 src_addr: new_local_ip,
897 device: new_device,
898 next_hop: new_next_hop,
899 local_delivery_device: new_local_delivery_device,
900 internal_forwarding: new_internal_forwarding,
901 } = match resolve(
902 core_ctx,
903 bindings_ctx,
904 socket_device,
905 local_ip,
906 remote_ip,
907 options.transparent(),
908 options.marks(),
909 ) {
910 Ok(r) => r,
911 Err(err) => {
912 packet_metadata.acknowledge_drop();
913 return Err(err);
914 }
915 };
916 local_ip = new_local_ip;
917 egress_device = new_device;
918 next_hop = new_next_hop;
919 local_delivery_device = new_local_delivery_device;
920 internal_forwarding = new_internal_forwarding;
921 }
922
923 match internal_forwarding {
925 InternalForwarding::Used(ingress_device) => {
926 match core_ctx.filter_handler().forwarding_hook(
927 &mut packet,
928 &ingress_device,
929 &egress_device,
930 &mut packet_metadata,
931 ) {
932 filter::Verdict::Drop => {
933 packet_metadata.acknowledge_drop();
934 return Ok(());
935 }
936 filter::Verdict::Accept(()) => {}
937 }
938 }
939 InternalForwarding::NotUsed => {}
940 }
941
942 let loopback_packet = (!egress_device.is_loopback()
947 && ((options.multicast_loop() && remote_ip.addr().is_multicast())
948 || next_hop.is_broadcast()))
949 .then(|| body.serialize_new_buf(PacketConstraints::UNCONSTRAINED, packet::new_buf_vec))
950 .transpose()?
951 .map(|buf| RawIpBody::new(*proto, local_ip.addr(), remote_ip.addr(), buf));
952
953 let destination = match &local_delivery_device {
954 Some(d) => IpPacketDestination::Loopback(d),
955 None => IpPacketDestination::from_next_hop(next_hop, remote_ip.into()),
956 };
957 let ttl = options.hop_limit(&remote_ip.into());
958 let meta = SendIpPacketMeta {
959 device: &egress_device,
960 src_ip: local_ip.into(),
961 dst_ip: remote_ip.into(),
962 destination,
963 ttl,
964 proto: *proto,
965 mtu: options.mtu(),
966 dscp_and_ecn: options.dscp_and_ecn(),
967 };
968 IpSocketContext::send_ip_packet(core_ctx, bindings_ctx, meta, body, packet_metadata).or_else(
969 |IpSendFrameError { serializer: _, error }| IpSockSendError::from_ip_send_frame(error),
970 )?;
971
972 match (loopback_packet, core_ctx.get_loopback_device()) {
973 (Some(loopback_packet), Some(loopback_device)) => {
974 let meta = SendIpPacketMeta {
975 device: &loopback_device,
976 src_ip: local_ip.into(),
977 dst_ip: remote_ip.into(),
978 destination: IpPacketDestination::Loopback(&egress_device),
979 ttl,
980 proto: *proto,
981 mtu: options.mtu(),
982 dscp_and_ecn: options.dscp_and_ecn(),
983 };
984 let packet_metadata = IpLayerPacketMetadata::default();
985
986 IpSocketContext::send_ip_packet(
989 core_ctx,
990 bindings_ctx,
991 meta,
992 loopback_packet,
993 packet_metadata,
994 )
995 .unwrap_or_else(|IpSendFrameError { serializer: _, error }| {
996 error!("failed to send loopback packet: {error:?}")
997 });
998 }
999 (Some(_loopback_packet), None) => {
1000 error!("can't send a loopback packet without the loopback device")
1001 }
1002 _ => (),
1003 }
1004
1005 Ok(())
1006}
1007
1008pub trait UseDeviceIpSocketHandlerBlanket {}
1013
1014impl<I, BC, CC> DeviceIpSocketHandler<I, BC> for CC
1015where
1016 I: IpLayerIpExt + IpDeviceStateIpExt,
1017 BC: IpSocketBindingsContext,
1018 CC: IpDeviceMtuContext<I> + IpSocketContext<I, BC> + UseDeviceIpSocketHandlerBlanket,
1019{
1020 fn get_mms<O: RouteResolutionOptions<I>>(
1021 &mut self,
1022 bindings_ctx: &mut BC,
1023 ip_sock: &IpSock<I, Self::WeakDeviceId>,
1024 options: &O,
1025 ) -> Result<Mms, MmsError> {
1026 let IpSockDefinition { remote_ip, local_ip, device, proto: _ } = &ip_sock.definition;
1027 let device = device
1028 .as_ref()
1029 .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
1030 .transpose()?;
1031
1032 let ResolvedRoute {
1033 src_addr: _,
1034 local_delivery_device: _,
1035 device,
1036 next_hop: _,
1037 internal_forwarding: _,
1038 } = self
1039 .lookup_route(
1040 bindings_ctx,
1041 device.as_ref(),
1042 Some(*local_ip),
1043 *remote_ip,
1044 options.transparent(),
1045 options.marks(),
1046 )
1047 .map_err(MmsError::NoDevice)?;
1048 let mtu = self.get_mtu(&device);
1049 Mms::from_mtu::<I>(mtu, 0 ).ok_or(MmsError::MTUTooSmall(mtu))
1052 }
1053}
1054
1055pub(crate) mod ipv6_source_address_selection {
1057 use net_types::ip::{AddrSubnet, IpAddress as _};
1058
1059 use super::*;
1060
1061 use netstack3_base::Ipv6DeviceAddr;
1062
1063 pub struct SasCandidate<D> {
1065 pub addr_sub: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1067 pub assigned: bool,
1069 pub deprecated: bool,
1071 pub temporary: bool,
1073 pub device: D,
1075 }
1076
1077 pub fn select_ipv6_source_address<
1090 'a,
1091 D: PartialEq,
1092 A,
1093 I: Iterator<Item = A>,
1094 F: FnMut(&A) -> SasCandidate<D>,
1095 >(
1096 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1097 outbound_device: &D,
1098 addresses: I,
1099 mut get_candidate: F,
1100 ) -> Option<A> {
1101 addresses
1113 .map(|item| {
1114 let candidate = get_candidate(&item);
1115 (item, candidate)
1116 })
1117 .filter(|(_, candidate)| candidate.assigned)
1120 .max_by(|(_, a), (_, b)| {
1121 select_ipv6_source_address_cmp(remote_ip, outbound_device, a, b)
1122 })
1123 .map(|(item, _candidate)| item)
1124 }
1125
1126 fn select_ipv6_source_address_cmp<D: PartialEq>(
1128 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1129 outbound_device: &D,
1130 a: &SasCandidate<D>,
1131 b: &SasCandidate<D>,
1132 ) -> Ordering {
1133 let SasCandidate {
1135 addr_sub: a_addr_sub,
1136 assigned: a_assigned,
1137 deprecated: a_deprecated,
1138 temporary: a_temporary,
1139 device: a_device,
1140 } = a;
1141 let SasCandidate {
1142 addr_sub: b_addr_sub,
1143 assigned: b_assigned,
1144 deprecated: b_deprecated,
1145 temporary: b_temporary,
1146 device: b_device,
1147 } = b;
1148
1149 let a_addr = a_addr_sub.addr().into_specified();
1150 let b_addr = b_addr_sub.addr().into_specified();
1151
1152 if let Some(remote_ip) = remote_ip {
1156 debug_assert!(!(a_addr == remote_ip && b_addr == remote_ip));
1157 }
1158
1159 debug_assert!(a_assigned);
1162 debug_assert!(b_assigned);
1163
1164 rule_1(remote_ip, a_addr, b_addr)
1165 .then_with(|| rule_2(remote_ip, a_addr, b_addr))
1166 .then_with(|| rule_3(*a_deprecated, *b_deprecated))
1167 .then_with(|| rule_5(outbound_device, a_device, b_device))
1168 .then_with(|| rule_7(*a_temporary, *b_temporary))
1169 .then_with(|| rule_8(remote_ip, *a_addr_sub, *b_addr_sub))
1170 }
1171
1172 fn rule_1(
1174 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1175 a: SpecifiedAddr<Ipv6Addr>,
1176 b: SpecifiedAddr<Ipv6Addr>,
1177 ) -> Ordering {
1178 let remote_ip = match remote_ip {
1179 Some(remote_ip) => remote_ip,
1180 None => return Ordering::Equal,
1181 };
1182 if (a == remote_ip) != (b == remote_ip) {
1183 if a == remote_ip {
1195 Ordering::Greater
1196 } else {
1197 Ordering::Less
1198 }
1199 } else {
1200 Ordering::Equal
1201 }
1202 }
1203
1204 fn rule_2(
1205 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1206 a: SpecifiedAddr<Ipv6Addr>,
1207 b: SpecifiedAddr<Ipv6Addr>,
1208 ) -> Ordering {
1209 let remote_scope = match remote_ip {
1212 Some(remote_ip) => remote_ip.scope().multicast_scope_id(),
1213 None => return Ordering::Equal,
1214 };
1215 let a_scope = a.scope().multicast_scope_id();
1216 let b_scope = b.scope().multicast_scope_id();
1217 if a_scope < b_scope {
1218 if a_scope < remote_scope {
1219 Ordering::Less
1220 } else {
1221 Ordering::Greater
1222 }
1223 } else if a_scope > b_scope {
1224 if b_scope < remote_scope {
1225 Ordering::Greater
1226 } else {
1227 Ordering::Less
1228 }
1229 } else {
1230 Ordering::Equal
1231 }
1232 }
1233
1234 fn rule_3(a_deprecated: bool, b_deprecated: bool) -> Ordering {
1235 match (a_deprecated, b_deprecated) {
1236 (true, false) => Ordering::Less,
1237 (true, true) | (false, false) => Ordering::Equal,
1238 (false, true) => Ordering::Greater,
1239 }
1240 }
1241
1242 fn rule_5<D: PartialEq>(outbound_device: &D, a_device: &D, b_device: &D) -> Ordering {
1243 if (a_device == outbound_device) != (b_device == outbound_device) {
1244 if a_device == outbound_device {
1246 Ordering::Greater
1247 } else {
1248 Ordering::Less
1249 }
1250 } else {
1251 Ordering::Equal
1252 }
1253 }
1254
1255 fn rule_7(a_temporary: bool, b_temporary: bool) -> Ordering {
1257 match (a_temporary, b_temporary) {
1258 (true, false) => Ordering::Greater,
1259 (true, true) | (false, false) => Ordering::Equal,
1260 (false, true) => Ordering::Less,
1261 }
1262 }
1263
1264 fn rule_8(
1265 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1266 a: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1267 b: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1268 ) -> Ordering {
1269 let remote_ip = match remote_ip {
1270 Some(remote_ip) => remote_ip,
1271 None => return Ordering::Equal,
1272 };
1273 fn common_prefix_len(
1283 src: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1284 dst: SpecifiedAddr<Ipv6Addr>,
1285 ) -> u8 {
1286 core::cmp::min(src.addr().common_prefix_len(&dst), src.subnet().prefix())
1287 }
1288
1289 common_prefix_len(a, remote_ip).cmp(&common_prefix_len(b, remote_ip))
1301 }
1302
1303 #[cfg(test)]
1304 mod tests {
1305 use net_declare::net_ip_v6;
1306
1307 use super::*;
1308
1309 #[test]
1310 fn test_select_ipv6_source_address() {
1311 let remote = SpecifiedAddr::new(net_ip_v6!("2001:0db8:1::")).unwrap();
1315 let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
1316 let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
1317 let link_local_remote = SpecifiedAddr::new(net_ip_v6!("fe80::1:2:42")).unwrap();
1318 let link_local = SpecifiedAddr::new(net_ip_v6!("fe80::1:2:4")).unwrap();
1319 let dev0 = &0;
1320 let dev1 = &1;
1321 let dev2 = &2;
1322
1323 assert_eq!(rule_1(Some(remote), remote, local0), Ordering::Greater);
1325 assert_eq!(rule_1(Some(remote), local0, remote), Ordering::Less);
1326 assert_eq!(rule_1(Some(remote), local0, local1), Ordering::Equal);
1327 assert_eq!(rule_1(None, local0, local1), Ordering::Equal);
1328
1329 assert_eq!(rule_2(Some(remote), local0, local1), Ordering::Equal);
1331 assert_eq!(rule_2(Some(remote), local1, local0), Ordering::Equal);
1332 assert_eq!(rule_2(Some(remote), local0, link_local), Ordering::Greater);
1333 assert_eq!(rule_2(Some(remote), link_local, local0), Ordering::Less);
1334 assert_eq!(rule_2(Some(link_local_remote), local0, link_local), Ordering::Less);
1335 assert_eq!(rule_2(Some(link_local_remote), link_local, local0), Ordering::Greater);
1336 assert_eq!(rule_1(None, local0, link_local), Ordering::Equal);
1337
1338 assert_eq!(rule_3(false, true), Ordering::Greater);
1340 assert_eq!(rule_3(true, false), Ordering::Less);
1341 assert_eq!(rule_3(true, true), Ordering::Equal);
1342 assert_eq!(rule_3(false, false), Ordering::Equal);
1343
1344 assert_eq!(rule_5(dev0, dev0, dev2), Ordering::Greater);
1346 assert_eq!(rule_5(dev0, dev2, dev0), Ordering::Less);
1347 assert_eq!(rule_5(dev0, dev0, dev0), Ordering::Equal);
1348 assert_eq!(rule_5(dev0, dev2, dev2), Ordering::Equal);
1349
1350 assert_eq!(rule_7(true, false), Ordering::Greater);
1352 assert_eq!(rule_7(false, true), Ordering::Less);
1353 assert_eq!(rule_7(true, true), Ordering::Equal);
1354 assert_eq!(rule_7(false, false), Ordering::Equal);
1355
1356 {
1358 let new_addr_entry = |addr, prefix_len| AddrSubnet::new(addr, prefix_len).unwrap();
1359
1360 let remote = SpecifiedAddr::new(net_ip_v6!("1111::")).unwrap();
1366 let local0 = new_addr_entry(net_ip_v6!("1110::"), 64);
1368 let local1 = new_addr_entry(net_ip_v6!("1100::"), 64);
1370
1371 assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Greater);
1372 assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Less);
1373 assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
1374 assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
1375 assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
1376
1377 let local0 = new_addr_entry(net_ip_v6!("1110::"), 8);
1382 let local1 = new_addr_entry(net_ip_v6!("1100::"), 8);
1384
1385 assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Equal);
1386 assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Equal);
1387 assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
1388 assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
1389 assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
1390 }
1391
1392 {
1393 let new_addr_entry = |addr, device| SasCandidate {
1394 addr_sub: AddrSubnet::new(addr, 128).unwrap(),
1395 deprecated: false,
1396 assigned: true,
1397 temporary: false,
1398 device,
1399 };
1400
1401 assert_eq!(
1403 select_ipv6_source_address_cmp(
1404 Some(remote),
1405 dev0,
1406 &new_addr_entry(*local0, *dev1),
1407 &new_addr_entry(*local1, *dev2),
1408 ),
1409 Ordering::Equal
1410 );
1411 }
1412 }
1413
1414 #[test]
1415 fn test_select_ipv6_source_address_no_remote() {
1416 let dev0 = &0;
1419 let dev1 = &1;
1420 let dev2 = &2;
1421
1422 let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
1423 let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
1424
1425 let new_addr_entry = |addr, deprecated, device| SasCandidate {
1426 addr_sub: AddrSubnet::new(addr, 128).unwrap(),
1427 deprecated,
1428 assigned: true,
1429 temporary: false,
1430 device,
1431 };
1432
1433 assert_eq!(
1435 select_ipv6_source_address_cmp(
1436 None,
1437 dev0,
1438 &new_addr_entry(*local0, false, *dev1),
1439 &new_addr_entry(*local1, true, *dev2),
1440 ),
1441 Ordering::Greater
1442 );
1443
1444 assert_eq!(
1446 select_ipv6_source_address_cmp(
1447 None,
1448 dev0,
1449 &new_addr_entry(*local0, false, *dev0),
1450 &new_addr_entry(*local1, false, *dev1),
1451 ),
1452 Ordering::Greater
1453 );
1454 }
1455 }
1456}
1457
1458#[cfg(any(test, feature = "testutils"))]
1460pub(crate) mod testutil {
1461 use alloc::boxed::Box;
1462 use alloc::collections::HashMap;
1463 use alloc::vec::Vec;
1464 use core::num::NonZeroUsize;
1465
1466 use derivative::Derivative;
1467 use net_types::ip::{GenericOverIp, IpAddr, IpAddress, Ipv4, Ipv4Addr, Ipv6, Subnet};
1468 use net_types::{MulticastAddr, Witness as _};
1469 use netstack3_base::testutil::{FakeCoreCtx, FakeStrongDeviceId, FakeWeakDeviceId};
1470 use netstack3_base::{SendFrameContext, SendFrameError};
1471 use netstack3_filter::Tuple;
1472
1473 use super::*;
1474 use crate::internal::base::{
1475 BaseTransportIpContext, HopLimits, MulticastMembershipHandler, DEFAULT_HOP_LIMITS,
1476 };
1477 use crate::internal::routing::testutil::FakeIpRoutingCtx;
1478 use crate::internal::routing::{self, RoutingTable};
1479 use crate::internal::types::{Destination, Entry, Metric, RawMetric};
1480
1481 #[derive(Derivative, GenericOverIp)]
1484 #[generic_over_ip(I, Ip)]
1485 #[derivative(Default(bound = ""))]
1486 pub struct FakeIpSocketCtx<I: Ip, D> {
1487 pub(crate) table: RoutingTable<I, D>,
1488 forwarding: FakeIpRoutingCtx<D>,
1489 devices: HashMap<D, FakeDeviceState<I>>,
1490 }
1491
1492 pub trait InnerFakeIpSocketCtx<I: Ip, D> {
1495 fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D>;
1497 }
1498
1499 impl<I: Ip, D> InnerFakeIpSocketCtx<I, D> for FakeIpSocketCtx<I, D> {
1500 fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1501 self
1502 }
1503 }
1504
1505 impl<I: IpExt, D: FakeStrongDeviceId, BC> BaseTransportIpContext<I, BC> for FakeIpSocketCtx<I, D> {
1506 fn get_default_hop_limits(&mut self, device: Option<&D>) -> HopLimits {
1507 device.map_or(DEFAULT_HOP_LIMITS, |device| {
1508 let hop_limit = self.get_device_state(device).default_hop_limit;
1509 HopLimits { unicast: hop_limit, multicast: DEFAULT_HOP_LIMITS.multicast }
1510 })
1511 }
1512
1513 type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;
1514
1515 fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
1516 &mut self,
1517 addr: SpecifiedAddr<I::Addr>,
1518 cb: F,
1519 ) -> O {
1520 cb(Box::new(self.devices.iter().filter_map(move |(device, state)| {
1521 state.addresses.contains(&addr).then(|| device.clone())
1522 })))
1523 }
1524
1525 fn get_original_destination(&mut self, _tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
1526 unimplemented!()
1527 }
1528 }
1529
1530 impl<I: IpExt, D: FakeStrongDeviceId> DeviceIdContext<AnyDevice> for FakeIpSocketCtx<I, D> {
1531 type DeviceId = D;
1532 type WeakDeviceId = D::Weak;
1533 }
1534
1535 impl<I, State, D, Meta, BC> IpSocketHandler<I, BC> for FakeCoreCtx<State, Meta, D>
1536 where
1537 I: IpExt,
1538 State: InnerFakeIpSocketCtx<I, D>,
1539 D: FakeStrongDeviceId,
1540 BC: TxMetadataBindingsTypes,
1541 FakeCoreCtx<State, Meta, D>:
1542 SendFrameContext<BC, SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>>,
1543 {
1544 fn new_ip_socket<O>(
1545 &mut self,
1546 _bindings_ctx: &mut BC,
1547 device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
1548 local_ip: Option<IpDeviceAddr<I::Addr>>,
1549 remote_ip: SocketIpAddr<I::Addr>,
1550 proto: I::Proto,
1551 options: &O,
1552 ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
1553 where
1554 O: RouteResolutionOptions<I>,
1555 {
1556 self.state.fake_ip_socket_ctx_mut().new_ip_socket(
1557 device,
1558 local_ip,
1559 remote_ip,
1560 proto,
1561 options.transparent(),
1562 )
1563 }
1564
1565 fn send_ip_packet<S, O>(
1566 &mut self,
1567 bindings_ctx: &mut BC,
1568 socket: &IpSock<I, Self::WeakDeviceId>,
1569 body: S,
1570 options: &O,
1571 _tx_meta: BC::TxMetadata,
1574 ) -> Result<(), IpSockSendError>
1575 where
1576 S: TransportPacketSerializer<I>,
1577 S::Buffer: BufferMut,
1578 O: SendOptions<I> + RouteResolutionOptions<I>,
1579 {
1580 let meta = self.state.fake_ip_socket_ctx_mut().resolve_send_meta(socket, options)?;
1581 self.send_frame(bindings_ctx, meta, body).or_else(
1582 |SendFrameError { serializer: _, error }| IpSockSendError::from_send_frame(error),
1583 )
1584 }
1585
1586 fn confirm_reachable<O>(
1587 &mut self,
1588 _bindings_ctx: &mut BC,
1589 _socket: &IpSock<I, Self::WeakDeviceId>,
1590 _options: &O,
1591 ) {
1592 }
1593 }
1594
1595 impl<I: IpExt, D: FakeStrongDeviceId, BC> MulticastMembershipHandler<I, BC>
1596 for FakeIpSocketCtx<I, D>
1597 {
1598 fn join_multicast_group(
1599 &mut self,
1600 _bindings_ctx: &mut BC,
1601 device: &Self::DeviceId,
1602 addr: MulticastAddr<<I as Ip>::Addr>,
1603 ) {
1604 let value = self.get_device_state_mut(device).multicast_groups.entry(addr).or_insert(0);
1605 *value = value.checked_add(1).unwrap();
1606 }
1607
1608 fn leave_multicast_group(
1609 &mut self,
1610 _bindings_ctx: &mut BC,
1611 device: &Self::DeviceId,
1612 addr: MulticastAddr<<I as Ip>::Addr>,
1613 ) {
1614 let value = self
1615 .get_device_state_mut(device)
1616 .multicast_groups
1617 .get_mut(&addr)
1618 .unwrap_or_else(|| panic!("no entry for {addr} on {device:?}"));
1619 *value = value.checked_sub(1).unwrap();
1620 }
1621
1622 fn select_device_for_multicast_group(
1623 &mut self,
1624 addr: MulticastAddr<<I as Ip>::Addr>,
1625 _marks: &Marks,
1626 ) -> Result<Self::DeviceId, ResolveRouteError> {
1627 let remote_ip = SocketIpAddr::new_from_multicast(addr);
1628 self.lookup_route(None, None, remote_ip, false)
1629 .map(|ResolvedRoute { device, .. }| device)
1630 }
1631 }
1632
1633 impl<I, BC, D, State, Meta> BaseTransportIpContext<I, BC> for FakeCoreCtx<State, Meta, D>
1634 where
1635 I: IpExt,
1636 D: FakeStrongDeviceId,
1637 State: InnerFakeIpSocketCtx<I, D>,
1638 BC: TxMetadataBindingsTypes,
1639 Self: IpSocketHandler<I, BC, DeviceId = D, WeakDeviceId = FakeWeakDeviceId<D>>,
1640 {
1641 type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;
1642
1643 fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
1644 &mut self,
1645 addr: SpecifiedAddr<I::Addr>,
1646 cb: F,
1647 ) -> O {
1648 BaseTransportIpContext::<I, BC>::with_devices_with_assigned_addr(
1649 self.state.fake_ip_socket_ctx_mut(),
1650 addr,
1651 cb,
1652 )
1653 }
1654
1655 fn get_default_hop_limits(&mut self, device: Option<&Self::DeviceId>) -> HopLimits {
1656 BaseTransportIpContext::<I, BC>::get_default_hop_limits(
1657 self.state.fake_ip_socket_ctx_mut(),
1658 device,
1659 )
1660 }
1661
1662 fn get_original_destination(&mut self, tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
1663 BaseTransportIpContext::<I, BC>::get_original_destination(
1664 self.state.fake_ip_socket_ctx_mut(),
1665 tuple,
1666 )
1667 }
1668 }
1669
1670 #[derive(Derivative)]
1672 #[derivative(Default(bound = ""))]
1673 pub struct FakeDualStackIpSocketCtx<D> {
1674 v4: FakeIpSocketCtx<Ipv4, D>,
1675 v6: FakeIpSocketCtx<Ipv6, D>,
1676 }
1677
1678 impl<D: FakeStrongDeviceId> FakeDualStackIpSocketCtx<D> {
1679 pub fn new<A: Into<SpecifiedAddr<IpAddr>>>(
1681 devices: impl IntoIterator<Item = FakeDeviceConfig<D, A>>,
1682 ) -> Self {
1683 let partition =
1684 |v: Vec<A>| -> (Vec<SpecifiedAddr<Ipv4Addr>>, Vec<SpecifiedAddr<Ipv6Addr>>) {
1685 v.into_iter().fold((Vec::new(), Vec::new()), |(mut v4, mut v6), i| {
1686 match IpAddr::from(i.into()) {
1687 IpAddr::V4(a) => v4.push(a),
1688 IpAddr::V6(a) => v6.push(a),
1689 }
1690 (v4, v6)
1691 })
1692 };
1693
1694 let (v4, v6): (Vec<_>, Vec<_>) = devices
1695 .into_iter()
1696 .map(|FakeDeviceConfig { device, local_ips, remote_ips }| {
1697 let (local_v4, local_v6) = partition(local_ips);
1698 let (remote_v4, remote_v6) = partition(remote_ips);
1699 (
1700 FakeDeviceConfig {
1701 device: device.clone(),
1702 local_ips: local_v4,
1703 remote_ips: remote_v4,
1704 },
1705 FakeDeviceConfig { device, local_ips: local_v6, remote_ips: remote_v6 },
1706 )
1707 })
1708 .unzip();
1709 Self { v4: FakeIpSocketCtx::new(v4), v6: FakeIpSocketCtx::new(v6) }
1710 }
1711
1712 pub fn inner_mut<I: Ip>(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1714 I::map_ip_out(self, |s| &mut s.v4, |s| &mut s.v6)
1715 }
1716
1717 fn inner<I: Ip>(&self) -> &FakeIpSocketCtx<I, D> {
1718 I::map_ip_out(self, |s| &s.v4, |s| &s.v6)
1719 }
1720
1721 pub fn add_route(&mut self, device: D, ip: SpecifiedAddr<IpAddr>) {
1723 match IpAddr::from(ip) {
1724 IpAddr::V4(ip) => {
1725 routing::testutil::add_on_link_routing_entry(&mut self.v4.table, ip, device)
1726 }
1727 IpAddr::V6(ip) => {
1728 routing::testutil::add_on_link_routing_entry(&mut self.v6.table, ip, device)
1729 }
1730 }
1731 }
1732
1733 pub fn add_subnet_route<A: IpAddress>(&mut self, device: D, subnet: Subnet<A>) {
1735 let entry = Entry {
1736 subnet,
1737 device,
1738 gateway: None,
1739 metric: Metric::ExplicitMetric(RawMetric(0)),
1740 };
1741 A::Version::map_ip::<_, ()>(
1742 entry,
1743 |entry_v4| {
1744 let _ = routing::testutil::add_entry(&mut self.v4.table, entry_v4)
1745 .expect("Failed to add route");
1746 },
1747 |entry_v6| {
1748 let _ = routing::testutil::add_entry(&mut self.v6.table, entry_v6)
1749 .expect("Failed to add route");
1750 },
1751 );
1752 }
1753
1754 pub fn get_device_state_mut<I: IpExt>(&mut self, device: &D) -> &mut FakeDeviceState<I> {
1756 self.inner_mut::<I>().get_device_state_mut(device)
1757 }
1758
1759 pub fn multicast_memberships<I: IpExt>(
1761 &self,
1762 ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
1763 self.inner::<I>().multicast_memberships()
1764 }
1765 }
1766
1767 impl<I: IpExt, S: InnerFakeIpSocketCtx<I, D>, Meta, D: FakeStrongDeviceId, BC>
1768 MulticastMembershipHandler<I, BC> for FakeCoreCtx<S, Meta, D>
1769 {
1770 fn join_multicast_group(
1771 &mut self,
1772 bindings_ctx: &mut BC,
1773 device: &Self::DeviceId,
1774 addr: MulticastAddr<<I as Ip>::Addr>,
1775 ) {
1776 MulticastMembershipHandler::<I, BC>::join_multicast_group(
1777 self.state.fake_ip_socket_ctx_mut(),
1778 bindings_ctx,
1779 device,
1780 addr,
1781 )
1782 }
1783
1784 fn leave_multicast_group(
1785 &mut self,
1786 bindings_ctx: &mut BC,
1787 device: &Self::DeviceId,
1788 addr: MulticastAddr<<I as Ip>::Addr>,
1789 ) {
1790 MulticastMembershipHandler::<I, BC>::leave_multicast_group(
1791 self.state.fake_ip_socket_ctx_mut(),
1792 bindings_ctx,
1793 device,
1794 addr,
1795 )
1796 }
1797
1798 fn select_device_for_multicast_group(
1799 &mut self,
1800 addr: MulticastAddr<<I as Ip>::Addr>,
1801 marks: &Marks,
1802 ) -> Result<Self::DeviceId, ResolveRouteError> {
1803 MulticastMembershipHandler::<I, BC>::select_device_for_multicast_group(
1804 self.state.fake_ip_socket_ctx_mut(),
1805 addr,
1806 marks,
1807 )
1808 }
1809 }
1810
1811 impl<I: Ip, D, State: InnerFakeIpSocketCtx<I, D>, Meta> InnerFakeIpSocketCtx<I, D>
1812 for FakeCoreCtx<State, Meta, D>
1813 {
1814 fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1815 self.state.fake_ip_socket_ctx_mut()
1816 }
1817 }
1818
1819 impl<I: Ip, D: FakeStrongDeviceId> InnerFakeIpSocketCtx<I, D> for FakeDualStackIpSocketCtx<D> {
1820 fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1821 self.inner_mut::<I>()
1822 }
1823 }
1824
1825 #[derive(Clone, GenericOverIp)]
1827 #[generic_over_ip()]
1828 pub struct FakeDeviceConfig<D, A> {
1829 pub device: D,
1831 pub local_ips: Vec<A>,
1833 pub remote_ips: Vec<A>,
1835 }
1836
1837 pub struct FakeDeviceState<I: Ip> {
1839 pub default_hop_limit: NonZeroU8,
1841 pub addresses: Vec<SpecifiedAddr<I::Addr>>,
1843 pub multicast_groups: HashMap<MulticastAddr<I::Addr>, usize>,
1845 }
1846
1847 impl<I: Ip> FakeDeviceState<I> {
1848 pub fn is_in_multicast_group(&self, addr: &MulticastAddr<I::Addr>) -> bool {
1850 self.multicast_groups.get(addr).is_some_and(|v| *v != 0)
1851 }
1852 }
1853
1854 impl<I: IpExt, D: FakeStrongDeviceId> FakeIpSocketCtx<I, D> {
1855 pub fn new(
1858 device_configs: impl IntoIterator<Item = FakeDeviceConfig<D, SpecifiedAddr<I::Addr>>>,
1859 ) -> Self {
1860 let mut table = RoutingTable::default();
1861 let mut devices = HashMap::default();
1862 for FakeDeviceConfig { device, local_ips, remote_ips } in device_configs {
1863 for addr in remote_ips {
1864 routing::testutil::add_on_link_routing_entry(&mut table, addr, device.clone())
1865 }
1866 let state = FakeDeviceState {
1867 default_hop_limit: DEFAULT_HOP_LIMITS.unicast,
1868 addresses: local_ips,
1869 multicast_groups: Default::default(),
1870 };
1871 assert!(
1872 devices.insert(device.clone(), state).is_none(),
1873 "duplicate entries for {device:?}",
1874 );
1875 }
1876
1877 Self { table, devices, forwarding: Default::default() }
1878 }
1879
1880 pub fn get_device_state(&self, device: &D) -> &FakeDeviceState<I> {
1882 self.devices.get(device).unwrap_or_else(|| panic!("no device {device:?}"))
1883 }
1884
1885 pub fn get_device_state_mut(&mut self, device: &D) -> &mut FakeDeviceState<I> {
1887 self.devices.get_mut(device).unwrap_or_else(|| panic!("no device {device:?}"))
1888 }
1889
1890 pub(crate) fn multicast_memberships(
1891 &self,
1892 ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
1893 self.devices
1894 .iter()
1895 .map(|(device, state)| {
1896 state.multicast_groups.iter().filter_map(|(group, count)| {
1897 NonZeroUsize::new(*count).map(|count| ((device.clone(), *group), count))
1898 })
1899 })
1900 .flatten()
1901 .collect()
1902 }
1903
1904 fn new_ip_socket(
1905 &mut self,
1906 device: Option<EitherDeviceId<&D, &D::Weak>>,
1907 local_ip: Option<IpDeviceAddr<I::Addr>>,
1908 remote_ip: SocketIpAddr<I::Addr>,
1909 proto: I::Proto,
1910 transparent: bool,
1911 ) -> Result<IpSock<I, D::Weak>, IpSockCreationError> {
1912 let device = device
1913 .as_ref()
1914 .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
1915 .transpose()?;
1916 let device = device.as_ref().map(|d| d.as_ref());
1917 let resolved_route = self.lookup_route(device, local_ip, remote_ip, transparent)?;
1918 Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
1919 }
1920
1921 fn lookup_route(
1922 &mut self,
1923 device: Option<&D>,
1924 local_ip: Option<IpDeviceAddr<I::Addr>>,
1925 addr: RoutableIpAddr<I::Addr>,
1926 transparent: bool,
1927 ) -> Result<ResolvedRoute<I, D>, ResolveRouteError> {
1928 let Self { table, devices, forwarding } = self;
1929 let (destination, ()) = table
1930 .lookup_filter_map(forwarding, device, addr.addr(), |_, d| match &local_ip {
1931 None => Some(()),
1932 Some(local_ip) => {
1933 if transparent {
1934 return Some(());
1935 }
1936 devices.get(d).and_then(|state| {
1937 state.addresses.contains(local_ip.as_ref()).then_some(())
1938 })
1939 }
1940 })
1941 .next()
1942 .ok_or(ResolveRouteError::Unreachable)?;
1943
1944 let Destination { device, next_hop } = destination;
1945 let mut addrs = devices.get(device).unwrap().addresses.iter();
1946 let local_ip = match local_ip {
1947 None => {
1948 let addr = addrs.next().ok_or(ResolveRouteError::NoSrcAddr)?;
1949 IpDeviceAddr::new(addr.get()).expect("not valid device addr")
1950 }
1951 Some(local_ip) => {
1952 if !transparent {
1953 assert!(
1956 addrs.any(|a| a.get() == local_ip.addr()),
1957 "didn't find IP {:?} in {:?}",
1958 local_ip,
1959 addrs.collect::<Vec<_>>()
1960 );
1961 }
1962 local_ip
1963 }
1964 };
1965
1966 Ok(ResolvedRoute {
1967 src_addr: local_ip,
1968 device: device.clone(),
1969 local_delivery_device: None,
1970 next_hop,
1971 internal_forwarding: InternalForwarding::NotUsed,
1974 })
1975 }
1976
1977 fn resolve_send_meta<O>(
1978 &mut self,
1979 socket: &IpSock<I, D::Weak>,
1980 options: &O,
1981 ) -> Result<SendIpPacketMeta<I, D, SpecifiedAddr<I::Addr>>, IpSockSendError>
1982 where
1983 O: SendOptions<I> + RouteResolutionOptions<I>,
1984 {
1985 let IpSockDefinition { remote_ip, local_ip, device, proto } = &socket.definition;
1986 let device = device
1987 .as_ref()
1988 .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
1989 .transpose()?;
1990 let ResolvedRoute {
1991 src_addr,
1992 device,
1993 next_hop,
1994 local_delivery_device: _,
1995 internal_forwarding: _,
1996 } = self.lookup_route(
1997 device.as_ref(),
1998 Some(*local_ip),
1999 *remote_ip,
2000 options.transparent(),
2001 )?;
2002
2003 let remote_ip: &SpecifiedAddr<_> = remote_ip.as_ref();
2004
2005 let destination = IpPacketDestination::from_next_hop(next_hop, *remote_ip);
2006 Ok(SendIpPacketMeta {
2007 device,
2008 src_ip: src_addr.into(),
2009 dst_ip: *remote_ip,
2010 destination,
2011 proto: *proto,
2012 ttl: options.hop_limit(remote_ip),
2013 mtu: options.mtu(),
2014 dscp_and_ecn: DscpAndEcn::default(),
2015 })
2016 }
2017 }
2018}