1use core::cmp::Ordering;
8use core::num::NonZeroU8;
9
10use log::{debug, error};
11use net_types::ip::{Ip, IpVersionMarker, Ipv6Addr, Mtu};
12use net_types::{MulticastAddress, ScopeableAddress, SpecifiedAddr, Witness as _};
13use netstack3_base::socket::{SocketIpAddr, SocketIpAddrExt as _};
14use netstack3_base::{
15 AnyDevice, CounterContext, DeviceIdContext, DeviceIdentifier, EitherDeviceId, InstantContext,
16 InterfaceProperties, IpDeviceAddr, IpExt, Marks, Mms, NetworkSerializationContext, PacketType,
17 SendFrameErrorReason, StrongDeviceIdentifier, TxMetadata, TxMetadataBindingsTypes,
18 WeakDeviceIdentifier,
19};
20use netstack3_filter::{
21 self as filter, DynTransportSerializer, DynamicTransportSerializer, FilterBindingsContext,
22 FilterHandler as _, FilterIpExt, RawIpBody, SocketEgressFilterResult, SocketOpsFilter,
23 SocketOpsFilterBindingContext, TransportPacketSerializer,
24};
25use netstack3_trace::trace_duration;
26use packet::{
27 BufferMut, NestablePacketBuilder as _, PacketConstraints, SerializeError, Serializer,
28};
29use packet_formats::ip::{DscpAndEcn, IpPacketBuilder as _};
30use thiserror::Error;
31
32use crate::icmp::IcmpErrorHandler;
33use crate::internal::base::{
34 FilterHandlerProvider, IpDeviceMtuContext, IpLayerIpExt, IpLayerPacketMetadata,
35 IpPacketDestination, IpSendFrameError, IpSendFrameErrorReason, ResolveRouteError,
36 SendIpPacketMeta, SplitMulticastPacketMetadata, reject_type_to_icmpv4_error,
37 reject_type_to_icmpv6_error,
38};
39use crate::internal::counters::IpCounters;
40use crate::internal::device::state::IpDeviceStateIpExt;
41use crate::internal::gso::MaybeSegmentableTransportSerializer;
42use crate::internal::routing::PacketOrigin;
43use crate::internal::routing::rules::RuleInput;
44use crate::internal::types::{InternalForwarding, ResolvedRoute, RoutableIpAddr};
45use crate::{HopLimits, NextHop};
46
47pub struct IpSocketArgs<'a, D: StrongDeviceIdentifier, I: IpExt, O> {
49 pub device: Option<EitherDeviceId<&'a D, &'a D::Weak>>,
51 pub local_ip: Option<IpDeviceAddr<I::Addr>>,
54 pub remote_ip: RoutableIpAddr<I::Addr>,
56 pub proto: I::Proto,
58 pub options: &'a O,
60}
61pub trait IpSocketHandler<I: IpExt + FilterIpExt, BC: TxMetadataBindingsTypes>:
63 DeviceIdContext<AnyDevice>
64{
65 fn new_ip_socket<O>(
80 &mut self,
81 bindings_ctx: &mut BC,
82 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
83 ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
84 where
85 O: RouteResolutionOptions<I>;
86
87 fn send_ip_packet<S, O>(
100 &mut self,
101 bindings_ctx: &mut BC,
102 socket: &IpSock<I, Self::WeakDeviceId>,
103 body: S,
104 options: &O,
105 tx_metadata: BC::TxMetadata,
106 ) -> Result<(), IpSockSendError>
107 where
108 S: TransportPacketSerializer<I> + MaybeSegmentableTransportSerializer,
109 S::Buffer: BufferMut,
110 O: SendOptions<I> + RouteResolutionOptions<I>;
111
112 fn confirm_reachable<O>(
118 &mut self,
119 bindings_ctx: &mut BC,
120 socket: &IpSock<I, Self::WeakDeviceId>,
121 options: &O,
122 ) where
123 O: RouteResolutionOptions<I>;
124
125 fn send_oneshot_ip_packet_with_fallible_serializer<S, E, F, O>(
148 &mut self,
149 bindings_ctx: &mut BC,
150 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
151 tx_metadata: BC::TxMetadata,
152 get_body_from_src_ip: F,
153 ) -> Result<(), SendOneShotIpPacketError<E>>
154 where
155 S: TransportPacketSerializer<I> + MaybeSegmentableTransportSerializer,
156 S::Buffer: BufferMut,
157 F: FnOnce(IpDeviceAddr<I::Addr>) -> Result<S, E>,
158 O: SendOptions<I> + RouteResolutionOptions<I>,
159 {
160 let options = args.options;
161 let tmp = self
162 .new_ip_socket(bindings_ctx, args)
163 .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })?;
164 let packet = get_body_from_src_ip(*tmp.local_ip())
165 .map_err(SendOneShotIpPacketError::SerializeError)?;
166 self.send_ip_packet(bindings_ctx, &tmp, packet, options, tx_metadata)
167 .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })
168 }
169
170 fn send_oneshot_ip_packet_with_dyn_fallible_serializer<S, E, F, O>(
176 &mut self,
177 bindings_ctx: &mut BC,
178 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
179 tx_metadata: BC::TxMetadata,
180 get_body_from_src_ip: F,
181 ) -> Result<(), SendOneShotIpPacketError<E>>
182 where
183 S: DynamicTransportSerializer<I>,
184 F: FnOnce(IpDeviceAddr<I::Addr>) -> Result<S, E>,
185 O: SendOptions<I> + RouteResolutionOptions<I>,
186 {
187 let options = args.options;
188 let tmp = self
189 .new_ip_socket(bindings_ctx, args)
190 .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })?;
191 let mut packet = get_body_from_src_ip(*tmp.local_ip())
192 .map_err(SendOneShotIpPacketError::SerializeError)?;
193 self.send_ip_packet(
194 bindings_ctx,
195 &tmp,
196 DynTransportSerializer::new(&mut packet),
197 options,
198 tx_metadata,
199 )
200 .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })
201 }
202
203 fn send_oneshot_ip_packet<S, F, O>(
205 &mut self,
206 bindings_ctx: &mut BC,
207 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
208 tx_metadata: BC::TxMetadata,
209 get_body_from_src_ip: F,
210 ) -> Result<(), IpSockCreateAndSendError>
211 where
212 S: TransportPacketSerializer<I> + MaybeSegmentableTransportSerializer,
213 S::Buffer: BufferMut,
214 F: FnOnce(IpDeviceAddr<I::Addr>) -> S,
215 O: SendOptions<I> + RouteResolutionOptions<I>,
216 {
217 self.send_oneshot_ip_packet_with_fallible_serializer(
218 bindings_ctx,
219 args,
220 tx_metadata,
221 |ip| Ok::<_, !>(get_body_from_src_ip(ip)),
222 )
223 .map_err(|err| match err {
224 SendOneShotIpPacketError::CreateAndSendError { err } => err,
225 })
226 }
227
228 fn send_oneshot_ip_packet_with_dyn_serializer<S, F, O>(
234 &mut self,
235 bindings_ctx: &mut BC,
236 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
237 tx_metadata: BC::TxMetadata,
238 get_body_from_src_ip: F,
239 ) -> Result<(), IpSockCreateAndSendError>
240 where
241 S: DynamicTransportSerializer<I>,
242 F: FnOnce(IpDeviceAddr<I::Addr>) -> S,
243 O: SendOptions<I> + RouteResolutionOptions<I>,
244 {
245 self.send_oneshot_ip_packet_with_dyn_fallible_serializer(
246 bindings_ctx,
247 args,
248 tx_metadata,
249 |ip| Ok::<_, !>(get_body_from_src_ip(ip)),
250 )
251 .map_err(|err| match err {
252 SendOneShotIpPacketError::CreateAndSendError { err } => err,
253 })
254 }
255}
256
257#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
259pub enum IpSockSendError {
260 #[error("a maximum transmission unit (MTU) was exceeded")]
265 Mtu,
266 #[error("the socket is currently unroutable: {0}")]
268 Unroutable(#[from] ResolveRouteError),
269 #[error("illegal loopback address")]
272 IllegalLoopbackAddress,
273 #[error("broadcast send is not enabled for the socket")]
275 BroadcastNotAllowed,
276}
277
278impl From<SerializeError<!>> for IpSockSendError {
279 fn from(err: SerializeError<!>) -> IpSockSendError {
280 match err {
281 SerializeError::SizeLimitExceeded => IpSockSendError::Mtu,
282 }
283 }
284}
285
286impl IpSockSendError {
287 fn from_ip_send_frame(e: IpSendFrameErrorReason) -> Result<(), Self> {
292 match e {
293 IpSendFrameErrorReason::Device(d) => Self::from_send_frame(d),
294 IpSendFrameErrorReason::IllegalLoopbackAddress => Err(Self::IllegalLoopbackAddress),
295 }
296 }
297
298 fn from_send_frame(e: SendFrameErrorReason) -> Result<(), Self> {
303 match e {
304 SendFrameErrorReason::Alloc
305 | SendFrameErrorReason::QueueFull
306 | SendFrameErrorReason::AddressResolutionFailed => Ok(()),
307 SendFrameErrorReason::SizeConstraintsViolation => Err(Self::Mtu),
308 }
309 }
310}
311
312#[derive(Error, Copy, Clone, Debug)]
314pub enum IpSockCreateAndSendError {
315 #[error("cannot send via temporary socket: {0}")]
317 Send(#[from] IpSockSendError),
318 #[error("the temporary socket could not be created: {0}")]
320 Create(#[from] IpSockCreationError),
321}
322
323#[derive(Debug)]
326#[allow(missing_docs)]
327pub enum SendOneShotIpPacketError<E> {
328 CreateAndSendError { err: IpSockCreateAndSendError },
329 SerializeError(E),
330}
331
332#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
334pub enum MmsError {
335 #[error("cannot find the device: {0}")]
338 NoDevice(#[from] ResolveRouteError),
339 #[error("invalid MTU: {0:?}")]
342 MTUTooSmall(Mtu),
343}
344
345pub trait DeviceIpSocketHandler<I: IpExt, BC>: DeviceIdContext<AnyDevice> {
347 fn get_mms<O: RouteResolutionOptions<I>>(
353 &mut self,
354 bindings_ctx: &mut BC,
355 ip_sock: &IpSock<I, Self::WeakDeviceId>,
356 options: &O,
357 ) -> Result<Mms, MmsError>;
358}
359
360#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
362pub enum IpSockCreationError {
363 #[error("a route cannot be determined: {0}")]
365 Route(#[from] ResolveRouteError),
366}
367
368#[derive(Clone, Debug)]
370#[cfg_attr(test, derive(PartialEq))]
371pub struct IpSock<I: IpExt, D> {
372 definition: IpSockDefinition<I, D>,
376}
377
378impl<I: IpExt, D> IpSock<I, D> {
379 #[cfg(any(test, feature = "testutils"))]
381 pub fn definition(&self) -> &IpSockDefinition<I, D> {
382 &self.definition
383 }
384}
385
386#[derive(Clone, Debug, PartialEq)]
390pub struct IpSockDefinition<I: IpExt, D> {
391 pub remote_ip: SocketIpAddr<I::Addr>,
393 pub local_ip: IpDeviceAddr<I::Addr>,
404 pub device: Option<D>,
406 pub proto: I::Proto,
408}
409
410impl<I: IpExt, D> IpSock<I, D> {
411 pub fn local_ip(&self) -> &IpDeviceAddr<I::Addr> {
413 &self.definition.local_ip
414 }
415 pub fn remote_ip(&self) -> &SocketIpAddr<I::Addr> {
417 &self.definition.remote_ip
418 }
419 pub fn device(&self) -> Option<&D> {
421 self.definition.device.as_ref()
422 }
423 pub fn proto(&self) -> I::Proto {
425 self.definition.proto
426 }
427}
428
429pub trait IpSocketBindingsContext<D>:
436 InstantContext
437 + FilterBindingsContext<D>
438 + TxMetadataBindingsTypes
439 + SocketOpsFilterBindingContext<D>
440{
441}
442impl<
443 D,
444 BC: InstantContext
445 + FilterBindingsContext<D>
446 + TxMetadataBindingsTypes
447 + SocketOpsFilterBindingContext<D>,
448> IpSocketBindingsContext<D> for BC
449{
450}
451
452pub trait IpSocketContext<I, BC>:
457 DeviceIdContext<AnyDevice, DeviceId: InterfaceProperties<BC::DeviceClass>>
458 + FilterHandlerProvider<I, BC>
459 + IcmpErrorHandler<I, BC>
460where
461 I: IpLayerIpExt,
462 BC: IpSocketBindingsContext<Self::DeviceId>,
463{
464 fn lookup_route(
469 &mut self,
470 bindings_ctx: &mut BC,
471 device: Option<&Self::DeviceId>,
472 src_ip: Option<IpDeviceAddr<I::Addr>>,
473 dst_ip: RoutableIpAddr<I::Addr>,
474 transparent: bool,
475 marks: &Marks,
476 ) -> Result<ResolvedRoute<I, Self::DeviceId>, ResolveRouteError>;
477
478 fn send_ip_packet<S>(
480 &mut self,
481 bindings_ctx: &mut BC,
482 meta: SendIpPacketMeta<I, &Self::DeviceId, SpecifiedAddr<I::Addr>>,
483 body: S,
484 packet_metadata: IpLayerPacketMetadata<I, Self::WeakAddressId, BC>,
485 ) -> Result<(), IpSendFrameError<S>>
486 where
487 S: TransportPacketSerializer<I> + MaybeSegmentableTransportSerializer,
488 S::Buffer: BufferMut;
489
490 fn get_loopback_device(&mut self) -> Option<Self::DeviceId>;
492
493 fn confirm_reachable(
499 &mut self,
500 bindings_ctx: &mut BC,
501 dst: SpecifiedAddr<I::Addr>,
502 input: RuleInput<'_, I, Self::DeviceId>,
503 );
504}
505
506pub trait UseIpSocketHandlerBlanket {}
511
512impl<I, BC, CC> IpSocketHandler<I, BC> for CC
513where
514 I: IpLayerIpExt + IpDeviceStateIpExt,
515 BC: IpSocketBindingsContext<Self::DeviceId>,
516 CC: IpSocketContext<I, BC> + CounterContext<IpCounters<I>> + UseIpSocketHandlerBlanket,
517 CC::DeviceId: netstack3_base::InterfaceProperties<BC::DeviceClass>,
518{
519 fn new_ip_socket<O>(
520 &mut self,
521 bindings_ctx: &mut BC,
522 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
523 ) -> Result<IpSock<I, CC::WeakDeviceId>, IpSockCreationError>
524 where
525 O: RouteResolutionOptions<I>,
526 {
527 let IpSocketArgs { device, local_ip, remote_ip, proto, options } = args;
528 let device = device
529 .as_ref()
530 .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
531 .transpose()?;
532 let device = device.as_ref().map(|d| d.as_ref());
533
534 let resolved_route = self.lookup_route(
539 bindings_ctx,
540 device,
541 local_ip,
542 remote_ip,
543 options.transparent(),
544 options.marks(),
545 )?;
546 Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
547 }
548
549 fn send_ip_packet<S, O>(
550 &mut self,
551 bindings_ctx: &mut BC,
552 ip_sock: &IpSock<I, CC::WeakDeviceId>,
553 body: S,
554 options: &O,
555 tx_metadata: BC::TxMetadata,
556 ) -> Result<(), IpSockSendError>
557 where
558 S: TransportPacketSerializer<I> + MaybeSegmentableTransportSerializer,
559 S::Buffer: BufferMut,
560 O: SendOptions<I> + RouteResolutionOptions<I>,
561 {
562 send_ip_packet(self, bindings_ctx, ip_sock, body, options, tx_metadata)
563 }
564
565 fn confirm_reachable<O>(
566 &mut self,
567 bindings_ctx: &mut BC,
568 socket: &IpSock<I, CC::WeakDeviceId>,
569 options: &O,
570 ) where
571 O: RouteResolutionOptions<I>,
572 {
573 let bound_device = socket.device().and_then(|weak| weak.upgrade());
574 let bound_device = bound_device.as_ref();
575 let bound_address = Some((*socket.local_ip()).into());
576 let destination = (*socket.remote_ip()).into();
577 IpSocketContext::confirm_reachable(
578 self,
579 bindings_ctx,
580 destination,
581 RuleInput {
582 packet_origin: PacketOrigin::Local { bound_address, bound_device },
583 marks: options.marks(),
584 },
585 )
586 }
587}
588
589pub trait RouteResolutionOptions<I: Ip> {
601 fn transparent(&self) -> bool;
606
607 fn marks(&self) -> &Marks;
609}
610
611pub trait SendOptions<I: IpExt> {
619 fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8>;
625
626 fn multicast_loop(&self) -> bool;
629
630 fn allow_broadcast(&self) -> Option<I::BroadcastMarker>;
632
633 fn dscp_and_ecn(&self) -> DscpAndEcn;
635
636 fn mtu(&self) -> Mtu;
641}
642
643#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
645pub struct DefaultIpSocketOptions;
646
647impl<I: IpExt> SendOptions<I> for DefaultIpSocketOptions {
648 fn hop_limit(&self, _destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
649 None
650 }
651
652 fn multicast_loop(&self) -> bool {
653 false
654 }
655
656 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
657 None
658 }
659
660 fn dscp_and_ecn(&self) -> DscpAndEcn {
661 DscpAndEcn::default()
662 }
663
664 fn mtu(&self) -> Mtu {
665 Mtu::no_limit()
666 }
667}
668
669impl<I: Ip> RouteResolutionOptions<I> for DefaultIpSocketOptions {
670 fn transparent(&self) -> bool {
671 false
672 }
673
674 fn marks(&self) -> &Marks {
675 &Marks::UNMARKED
676 }
677}
678
679#[allow(missing_docs)]
687pub trait DelegatedSendOptions<I: IpExt>: OptionDelegationMarker {
688 fn delegate(&self) -> &impl SendOptions<I> {
690 &DefaultIpSocketOptions
691 }
692
693 fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
694 self.delegate().hop_limit(destination)
695 }
696
697 fn multicast_loop(&self) -> bool {
698 self.delegate().multicast_loop()
699 }
700
701 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
702 self.delegate().allow_broadcast()
703 }
704
705 fn dscp_and_ecn(&self) -> DscpAndEcn {
706 self.delegate().dscp_and_ecn()
707 }
708
709 fn mtu(&self) -> Mtu {
710 self.delegate().mtu()
711 }
712}
713
714impl<O: DelegatedSendOptions<I> + OptionDelegationMarker, I: IpExt> SendOptions<I> for O {
715 fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
716 self.hop_limit(destination)
717 }
718
719 fn multicast_loop(&self) -> bool {
720 self.multicast_loop()
721 }
722
723 fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
724 self.allow_broadcast()
725 }
726
727 fn dscp_and_ecn(&self) -> DscpAndEcn {
728 self.dscp_and_ecn()
729 }
730
731 fn mtu(&self) -> Mtu {
732 self.mtu()
733 }
734}
735
736#[allow(missing_docs)]
744pub trait DelegatedRouteResolutionOptions<I: Ip>: OptionDelegationMarker {
745 fn delegate(&self) -> &impl RouteResolutionOptions<I> {
747 &DefaultIpSocketOptions
748 }
749
750 fn transparent(&self) -> bool {
751 self.delegate().transparent()
752 }
753
754 fn marks(&self) -> &Marks {
755 self.delegate().marks()
756 }
757}
758
759impl<O: DelegatedRouteResolutionOptions<I> + OptionDelegationMarker, I: IpExt>
760 RouteResolutionOptions<I> for O
761{
762 fn transparent(&self) -> bool {
763 self.transparent()
764 }
765
766 fn marks(&self) -> &Marks {
767 self.marks()
768 }
769}
770
771pub trait OptionDelegationMarker {}
776
777#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
779pub struct SocketHopLimits<I: Ip> {
780 pub unicast: Option<NonZeroU8>,
782 pub multicast: Option<NonZeroU8>,
786 pub version: IpVersionMarker<I>,
790}
791
792impl<I: Ip> SocketHopLimits<I> {
793 pub fn set_unicast(value: Option<NonZeroU8>) -> impl FnOnce(&mut Self) {
795 move |limits| limits.unicast = value
796 }
797
798 pub fn set_multicast(value: Option<NonZeroU8>) -> impl FnOnce(&mut Self) {
800 move |limits| limits.multicast = value
801 }
802
803 pub fn get_limits_with_defaults(&self, defaults: &HopLimits) -> HopLimits {
805 let Self { unicast, multicast, version: _ } = self;
806 HopLimits {
807 unicast: unicast.unwrap_or(defaults.unicast),
808 multicast: multicast.unwrap_or(defaults.multicast),
809 }
810 }
811
812 pub fn hop_limit_for_dst(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
814 let Self { unicast, multicast, version: _ } = self;
815 if destination.is_multicast() { *multicast } else { *unicast }
816 }
817}
818
819fn new_ip_socket<I, D>(
820 requested_device: Option<&D>,
821 route: ResolvedRoute<I, D>,
822 remote_ip: SocketIpAddr<I::Addr>,
823 proto: I::Proto,
824) -> IpSock<I, D::Weak>
825where
826 I: IpExt,
827 D: StrongDeviceIdentifier,
828{
829 let ResolvedRoute {
833 src_addr,
834 device: route_device,
835 local_delivery_device,
836 next_hop: _,
837 internal_forwarding: _,
838 } = route;
839
840 let socket_device = (src_addr.as_ref().must_have_zone() || remote_ip.as_ref().must_have_zone())
843 .then(|| {
844 local_delivery_device.unwrap_or(route_device)
848 })
849 .as_ref()
850 .or(requested_device)
851 .map(|d| d.downgrade());
852
853 let definition =
854 IpSockDefinition { local_ip: src_addr, remote_ip, device: socket_device, proto };
855 IpSock { definition }
856}
857
858fn send_ip_packet<I, S, BC, CC, O>(
859 core_ctx: &mut CC,
860 bindings_ctx: &mut BC,
861 socket: &IpSock<I, CC::WeakDeviceId>,
862 mut body: S,
863 options: &O,
864 tx_metadata: BC::TxMetadata,
865) -> Result<(), IpSockSendError>
866where
867 I: IpLayerIpExt,
868 S: TransportPacketSerializer<I> + MaybeSegmentableTransportSerializer,
869 S::Buffer: BufferMut,
870 BC: IpSocketBindingsContext<CC::DeviceId>,
871 CC: IpSocketContext<I, BC> + CounterContext<IpCounters<I>>,
872 CC::DeviceId: netstack3_base::InterfaceProperties<BC::DeviceClass>,
873 O: SendOptions<I> + RouteResolutionOptions<I>,
874{
875 trace_duration!("ip::send_packet");
876
877 fn resolve<
880 I: IpLayerIpExt,
881 CC: IpSocketContext<I, BC>,
882 BC: IpSocketBindingsContext<CC::DeviceId>,
883 >(
884 core_ctx: &mut CC,
885 bindings_ctx: &mut BC,
886 device: &Option<CC::WeakDeviceId>,
887 local_ip: IpDeviceAddr<I::Addr>,
888 remote_ip: RoutableIpAddr<I::Addr>,
889 transparent: bool,
890 marks: &Marks,
891 ) -> Result<ResolvedRoute<I, CC::DeviceId>, IpSockSendError> {
892 let device = match device.as_ref().map(|d| d.upgrade()) {
893 Some(Some(device)) => Some(device),
894 Some(None) => return Err(ResolveRouteError::Unreachable.into()),
895 None => None,
896 };
897 let route = core_ctx
898 .lookup_route(
899 bindings_ctx,
900 device.as_ref(),
901 Some(local_ip),
902 remote_ip,
903 transparent,
904 marks,
905 )
906 .map_err(|e| IpSockSendError::Unroutable(e))?;
907 assert_eq!(local_ip, route.src_addr);
908 Ok(route)
909 }
910
911 let IpSock {
912 definition: IpSockDefinition { remote_ip, local_ip, device: socket_device, proto },
913 } = socket;
914 let ResolvedRoute {
915 src_addr: local_ip,
916 device: mut egress_device,
917 mut next_hop,
918 mut local_delivery_device,
919 mut internal_forwarding,
920 } = resolve(
921 core_ctx,
922 bindings_ctx,
923 socket_device,
924 *local_ip,
925 *remote_ip,
926 options.transparent(),
927 options.marks(),
928 )?;
929
930 if matches!(next_hop, NextHop::Broadcast(_)) && options.allow_broadcast().is_none() {
931 return Err(IpSockSendError::BroadcastNotAllowed);
932 }
933
934 let previous_dst = remote_ip.addr();
935 let mut packet = filter::TxPacket::new(local_ip.addr(), remote_ip.addr(), *proto, &mut body);
936 let gso_info = None;
939 let mut packet_metadata =
940 IpLayerPacketMetadata::new_local_tx(tx_metadata, *options.marks(), gso_info);
941
942 let filter_result = core_ctx.filter_handler().local_egress_hook(
943 bindings_ctx,
944 &mut packet,
945 &egress_device,
946 &mut packet_metadata,
947 );
948 match filter_result {
949 filter::Verdict::Stop(filter::DropOrReject::Drop) => {
950 packet_metadata.acknowledge_drop();
951 return Ok(());
952 }
953 filter::Verdict::Stop(filter::DropOrReject::Reject(reject_type)) => {
954 packet_metadata.acknowledge_drop();
955
956 let Some(icmp_error): Option<I::IcmpError> = I::map_ip_out(
957 reject_type,
958 |reject_type| reject_type_to_icmpv4_error(reject_type),
959 |reject_type| reject_type_to_icmpv6_error(reject_type),
960 ) else {
961 debug!("Unsupported reject type: {:?}", reject_type);
962 return Ok(());
963 };
964
965 let src_ip = SocketIpAddr::new_from_witness(local_ip.into_inner().get());
966 let dst_ip = *remote_ip;
967 let ttl = options.hop_limit(&dst_ip.into()).map(|v| v.into()).unwrap_or(1);
968 let packet_builder = I::PacketBuilder::new(
969 src_ip.into_inner().get(),
970 dst_ip.into_inner().get(),
971 ttl,
972 *proto,
973 );
974 let header_len = packet_builder.constraints().header_len();
975 let ip_frame = packet_builder.wrap_body(body);
976 let packet = match ip_frame.serialize_outer(
977 &mut NetworkSerializationContext::default(),
978 packet::NoReuseBufferProvider(packet::new_buf_vec),
979 ) {
980 Ok(packet) => packet,
981 Err((error, _frame)) => {
982 debug!("Failed to serialize packet {:?}", error);
983 return Ok(());
984 }
985 };
986
987 core_ctx.send_icmp_error_message(
991 bindings_ctx,
992 None,
993 None,
994 src_ip,
995 dst_ip,
996 packet,
997 icmp_error,
998 header_len,
999 *proto,
1000 &options.marks(),
1001 );
1002
1003 return Ok(());
1004 }
1005 filter::Verdict::Proceed(filter::Accept) => {}
1006 }
1007
1008 let Some(mut local_ip) = IpDeviceAddr::new(packet.src_addr()) else {
1009 packet_metadata.acknowledge_drop();
1010 return Err(IpSockSendError::Unroutable(ResolveRouteError::NoSrcAddr));
1011 };
1012 let Some(remote_ip) = RoutableIpAddr::new(packet.dst_addr()) else {
1013 packet_metadata.acknowledge_drop();
1014 return Err(IpSockSendError::Unroutable(ResolveRouteError::Unreachable));
1015 };
1016
1017 if remote_ip.addr() != previous_dst || packet_metadata.marks() != options.marks() {
1021 let ResolvedRoute {
1022 src_addr: new_local_ip,
1023 device: new_device,
1024 next_hop: new_next_hop,
1025 local_delivery_device: new_local_delivery_device,
1026 internal_forwarding: new_internal_forwarding,
1027 } = match resolve(
1028 core_ctx,
1029 bindings_ctx,
1030 socket_device,
1031 local_ip,
1032 remote_ip,
1033 options.transparent(),
1034 packet_metadata.marks(),
1035 ) {
1036 Ok(r) => r,
1037 Err(err) => {
1038 packet_metadata.acknowledge_drop();
1039 return Err(err);
1040 }
1041 };
1042 local_ip = new_local_ip;
1043 egress_device = new_device;
1044 next_hop = new_next_hop;
1045 local_delivery_device = new_local_delivery_device;
1046 internal_forwarding = new_internal_forwarding;
1047 }
1048
1049 match internal_forwarding {
1051 InternalForwarding::Used(ingress_device) => {
1052 match core_ctx.filter_handler().forwarding_hook(
1053 &mut packet,
1054 &ingress_device,
1055 &egress_device,
1056 &mut packet_metadata,
1057 ) {
1058 filter::Verdict::Stop(filter::DropOrReject::Drop) => {
1059 packet_metadata.acknowledge_drop();
1060 return Ok(());
1061 }
1062 filter::Verdict::Stop(filter::DropOrReject::Reject(_reject_type)) => {
1063 packet_metadata.acknowledge_drop();
1065 return Ok(());
1066 }
1067 filter::Verdict::Proceed(filter::Accept) => {}
1068 }
1069 }
1070 InternalForwarding::NotUsed => {}
1071 }
1072
1073 if let Some(socket_info) = packet_metadata.tx_metadata().socket_info() {
1074 let egress_filter_result = bindings_ctx.socket_ops_filter().on_egress(
1075 &packet,
1076 &egress_device,
1077 socket_info,
1078 packet_metadata.marks(),
1079 packet_metadata.gso_info(),
1080 );
1081
1082 match egress_filter_result {
1084 SocketEgressFilterResult::Pass { congestion: _ } => (),
1085 SocketEgressFilterResult::Drop { congestion: _ } => {
1086 core_ctx.counters().socket_egress_filter_dropped.increment();
1087 packet_metadata.acknowledge_drop();
1088 return Ok(());
1089 }
1090 }
1091 }
1092
1093 let loopback_packet_and_meta = if !egress_device.is_loopback()
1098 && ((options.multicast_loop() && remote_ip.addr().is_multicast())
1099 || next_hop.is_broadcast())
1100 {
1101 let body_copy = body.serialize_new_buf(
1102 &mut NetworkSerializationContext::default(),
1103 PacketConstraints::UNCONSTRAINED,
1104 packet::new_buf_vec,
1105 )?;
1106 let mut loopback_metadata;
1107 SplitMulticastPacketMetadata { primary: packet_metadata, secondary: loopback_metadata } =
1108 packet_metadata.split_for_multicast();
1109 loopback_metadata.set_packet_type(PacketType::Loopback);
1110 Some((
1111 RawIpBody::new(*proto, local_ip.addr(), remote_ip.addr(), body_copy),
1112 loopback_metadata,
1113 ))
1114 } else {
1115 None
1116 };
1117
1118 let destination = match &local_delivery_device {
1119 Some(d) => IpPacketDestination::Loopback(d),
1120 None => IpPacketDestination::from_next_hop(next_hop, remote_ip.into()),
1121 };
1122 let ttl = options.hop_limit(&remote_ip.into());
1123 let meta = SendIpPacketMeta {
1124 device: &egress_device,
1125 src_ip: local_ip.into(),
1126 dst_ip: remote_ip.into(),
1127 destination,
1128 ttl,
1129 proto: *proto,
1130 mtu: options.mtu(),
1131 dscp_and_ecn: options.dscp_and_ecn(),
1132 };
1133 let result =
1134 IpSocketContext::send_ip_packet(core_ctx, bindings_ctx, meta, body, packet_metadata)
1135 .or_else(|IpSendFrameError { serializer: _, error }| {
1136 IpSockSendError::from_ip_send_frame(error)
1137 });
1138
1139 match (result, loopback_packet_and_meta, core_ctx.get_loopback_device()) {
1140 (Ok(()), Some((loopback_packet, packet_metadata)), Some(loopback_device)) => {
1141 let meta = SendIpPacketMeta {
1142 device: &loopback_device,
1143 src_ip: local_ip.into(),
1144 dst_ip: remote_ip.into(),
1145 destination: IpPacketDestination::Loopback(&egress_device),
1146 ttl,
1147 proto: *proto,
1148 mtu: options.mtu(),
1149 dscp_and_ecn: options.dscp_and_ecn(),
1150 };
1151
1152 IpSocketContext::send_ip_packet(
1155 core_ctx,
1156 bindings_ctx,
1157 meta,
1158 loopback_packet,
1159 packet_metadata,
1160 )
1161 .unwrap_or_else(|IpSendFrameError { serializer: _, error }| {
1162 error!("failed to send loopback packet: {error:?}")
1163 });
1164 }
1165 (Ok(()), Some((_loopback_packet, packet_metadata)), None) => {
1166 error!("can't send a loopback packet without the loopback device");
1167 packet_metadata.acknowledge_drop();
1168 }
1169 (Err(_), Some((_loopback_packet, packet_metadata)), _) => {
1170 packet_metadata.acknowledge_drop();
1172 }
1173 (_, None, _) => (),
1174 }
1175
1176 result
1177}
1178
1179pub trait UseDeviceIpSocketHandlerBlanket {}
1184
1185impl<I, BC, CC> DeviceIpSocketHandler<I, BC> for CC
1186where
1187 I: IpLayerIpExt + IpDeviceStateIpExt,
1188 BC: IpSocketBindingsContext<CC::DeviceId>,
1189 CC: IpDeviceMtuContext<I> + IpSocketContext<I, BC> + UseDeviceIpSocketHandlerBlanket,
1190{
1191 fn get_mms<O: RouteResolutionOptions<I>>(
1192 &mut self,
1193 bindings_ctx: &mut BC,
1194 ip_sock: &IpSock<I, Self::WeakDeviceId>,
1195 options: &O,
1196 ) -> Result<Mms, MmsError> {
1197 let IpSockDefinition { remote_ip, local_ip, device, proto: _ } = &ip_sock.definition;
1198 let device = device
1199 .as_ref()
1200 .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
1201 .transpose()?;
1202
1203 let ResolvedRoute {
1204 src_addr: _,
1205 local_delivery_device: _,
1206 device,
1207 next_hop: _,
1208 internal_forwarding: _,
1209 } = self
1210 .lookup_route(
1211 bindings_ctx,
1212 device.as_ref(),
1213 Some(*local_ip),
1214 *remote_ip,
1215 options.transparent(),
1216 options.marks(),
1217 )
1218 .map_err(MmsError::NoDevice)?;
1219 let mtu = self.get_mtu(&device);
1220 Mms::from_mtu::<I>(mtu, 0 ).ok_or(MmsError::MTUTooSmall(mtu))
1223 }
1224}
1225
1226pub(crate) mod ipv6_source_address_selection {
1228 use net_types::ip::{AddrSubnet, IpAddress as _};
1229
1230 use super::*;
1231
1232 use netstack3_base::Ipv6DeviceAddr;
1233
1234 pub struct SasCandidate<D> {
1236 pub addr_sub: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1238 pub assigned: bool,
1240 pub deprecated: bool,
1242 pub temporary: bool,
1244 pub device: D,
1246 }
1247
1248 pub fn select_ipv6_source_address<
1261 'a,
1262 D: PartialEq,
1263 A,
1264 I: Iterator<Item = A>,
1265 F: FnMut(&A) -> SasCandidate<D>,
1266 >(
1267 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1268 outbound_device: &D,
1269 addresses: I,
1270 mut get_candidate: F,
1271 ) -> Option<A> {
1272 addresses
1284 .map(|item| {
1285 let candidate = get_candidate(&item);
1286 (item, candidate)
1287 })
1288 .filter(|(_, candidate)| candidate.assigned)
1291 .max_by(|(_, a), (_, b)| {
1292 select_ipv6_source_address_cmp(remote_ip, outbound_device, a, b)
1293 })
1294 .map(|(item, _candidate)| item)
1295 }
1296
1297 fn select_ipv6_source_address_cmp<D: PartialEq>(
1299 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1300 outbound_device: &D,
1301 a: &SasCandidate<D>,
1302 b: &SasCandidate<D>,
1303 ) -> Ordering {
1304 let SasCandidate {
1306 addr_sub: a_addr_sub,
1307 assigned: a_assigned,
1308 deprecated: a_deprecated,
1309 temporary: a_temporary,
1310 device: a_device,
1311 } = a;
1312 let SasCandidate {
1313 addr_sub: b_addr_sub,
1314 assigned: b_assigned,
1315 deprecated: b_deprecated,
1316 temporary: b_temporary,
1317 device: b_device,
1318 } = b;
1319
1320 let a_addr = a_addr_sub.addr().into_specified();
1321 let b_addr = b_addr_sub.addr().into_specified();
1322
1323 if let Some(remote_ip) = remote_ip {
1327 debug_assert!(!(a_addr == remote_ip && b_addr == remote_ip));
1328 }
1329
1330 debug_assert!(a_assigned);
1333 debug_assert!(b_assigned);
1334
1335 rule_1(remote_ip, a_addr, b_addr)
1336 .then_with(|| rule_2(remote_ip, a_addr, b_addr))
1337 .then_with(|| rule_3(*a_deprecated, *b_deprecated))
1338 .then_with(|| rule_5(outbound_device, a_device, b_device))
1339 .then_with(|| rule_7(*a_temporary, *b_temporary))
1340 .then_with(|| rule_8(remote_ip, *a_addr_sub, *b_addr_sub))
1341 }
1342
1343 fn rule_1(
1345 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1346 a: SpecifiedAddr<Ipv6Addr>,
1347 b: SpecifiedAddr<Ipv6Addr>,
1348 ) -> Ordering {
1349 let remote_ip = match remote_ip {
1350 Some(remote_ip) => remote_ip,
1351 None => return Ordering::Equal,
1352 };
1353 if (a == remote_ip) != (b == remote_ip) {
1354 if a == remote_ip { Ordering::Greater } else { Ordering::Less }
1366 } else {
1367 Ordering::Equal
1368 }
1369 }
1370
1371 fn rule_2(
1372 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1373 a: SpecifiedAddr<Ipv6Addr>,
1374 b: SpecifiedAddr<Ipv6Addr>,
1375 ) -> Ordering {
1376 let remote_scope = match remote_ip {
1379 Some(remote_ip) => remote_ip.scope().multicast_scope_id(),
1380 None => return Ordering::Equal,
1381 };
1382 let a_scope = a.scope().multicast_scope_id();
1383 let b_scope = b.scope().multicast_scope_id();
1384 if a_scope < b_scope {
1385 if a_scope < remote_scope { Ordering::Less } else { Ordering::Greater }
1386 } else if a_scope > b_scope {
1387 if b_scope < remote_scope { Ordering::Greater } else { Ordering::Less }
1388 } else {
1389 Ordering::Equal
1390 }
1391 }
1392
1393 fn rule_3(a_deprecated: bool, b_deprecated: bool) -> Ordering {
1394 match (a_deprecated, b_deprecated) {
1395 (true, false) => Ordering::Less,
1396 (true, true) | (false, false) => Ordering::Equal,
1397 (false, true) => Ordering::Greater,
1398 }
1399 }
1400
1401 fn rule_5<D: PartialEq>(outbound_device: &D, a_device: &D, b_device: &D) -> Ordering {
1402 if (a_device == outbound_device) != (b_device == outbound_device) {
1403 if a_device == outbound_device { Ordering::Greater } else { Ordering::Less }
1405 } else {
1406 Ordering::Equal
1407 }
1408 }
1409
1410 fn rule_7(a_temporary: bool, b_temporary: bool) -> Ordering {
1412 match (a_temporary, b_temporary) {
1413 (true, false) => Ordering::Greater,
1414 (true, true) | (false, false) => Ordering::Equal,
1415 (false, true) => Ordering::Less,
1416 }
1417 }
1418
1419 fn rule_8(
1420 remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1421 a: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1422 b: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1423 ) -> Ordering {
1424 let remote_ip = match remote_ip {
1425 Some(remote_ip) => remote_ip,
1426 None => return Ordering::Equal,
1427 };
1428 fn common_prefix_len(
1438 src: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1439 dst: SpecifiedAddr<Ipv6Addr>,
1440 ) -> u8 {
1441 core::cmp::min(src.addr().common_prefix_len(&dst), src.subnet().prefix())
1442 }
1443
1444 common_prefix_len(a, remote_ip).cmp(&common_prefix_len(b, remote_ip))
1456 }
1457
1458 #[cfg(test)]
1459 mod tests {
1460 use net_declare::net_ip_v6;
1461
1462 use super::*;
1463
1464 #[test]
1465 fn test_select_ipv6_source_address() {
1466 let remote = SpecifiedAddr::new(net_ip_v6!("2001:0db8:1::")).unwrap();
1470 let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
1471 let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
1472 let link_local_remote = SpecifiedAddr::new(net_ip_v6!("fe80::1:2:42")).unwrap();
1473 let link_local = SpecifiedAddr::new(net_ip_v6!("fe80::1:2:4")).unwrap();
1474 let dev0 = &0;
1475 let dev1 = &1;
1476 let dev2 = &2;
1477
1478 assert_eq!(rule_1(Some(remote), remote, local0), Ordering::Greater);
1480 assert_eq!(rule_1(Some(remote), local0, remote), Ordering::Less);
1481 assert_eq!(rule_1(Some(remote), local0, local1), Ordering::Equal);
1482 assert_eq!(rule_1(None, local0, local1), Ordering::Equal);
1483
1484 assert_eq!(rule_2(Some(remote), local0, local1), Ordering::Equal);
1486 assert_eq!(rule_2(Some(remote), local1, local0), Ordering::Equal);
1487 assert_eq!(rule_2(Some(remote), local0, link_local), Ordering::Greater);
1488 assert_eq!(rule_2(Some(remote), link_local, local0), Ordering::Less);
1489 assert_eq!(rule_2(Some(link_local_remote), local0, link_local), Ordering::Less);
1490 assert_eq!(rule_2(Some(link_local_remote), link_local, local0), Ordering::Greater);
1491 assert_eq!(rule_1(None, local0, link_local), Ordering::Equal);
1492
1493 assert_eq!(rule_3(false, true), Ordering::Greater);
1495 assert_eq!(rule_3(true, false), Ordering::Less);
1496 assert_eq!(rule_3(true, true), Ordering::Equal);
1497 assert_eq!(rule_3(false, false), Ordering::Equal);
1498
1499 assert_eq!(rule_5(dev0, dev0, dev2), Ordering::Greater);
1501 assert_eq!(rule_5(dev0, dev2, dev0), Ordering::Less);
1502 assert_eq!(rule_5(dev0, dev0, dev0), Ordering::Equal);
1503 assert_eq!(rule_5(dev0, dev2, dev2), Ordering::Equal);
1504
1505 assert_eq!(rule_7(true, false), Ordering::Greater);
1507 assert_eq!(rule_7(false, true), Ordering::Less);
1508 assert_eq!(rule_7(true, true), Ordering::Equal);
1509 assert_eq!(rule_7(false, false), Ordering::Equal);
1510
1511 {
1513 let new_addr_entry = |addr, prefix_len| AddrSubnet::new(addr, prefix_len).unwrap();
1514
1515 let remote = SpecifiedAddr::new(net_ip_v6!("1111::")).unwrap();
1521 let local0 = new_addr_entry(net_ip_v6!("1110::"), 64);
1523 let local1 = new_addr_entry(net_ip_v6!("1100::"), 64);
1525
1526 assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Greater);
1527 assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Less);
1528 assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
1529 assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
1530 assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
1531
1532 let local0 = new_addr_entry(net_ip_v6!("1110::"), 8);
1537 let local1 = new_addr_entry(net_ip_v6!("1100::"), 8);
1539
1540 assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Equal);
1541 assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Equal);
1542 assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
1543 assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
1544 assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
1545 }
1546
1547 {
1548 let new_addr_entry = |addr, device| SasCandidate {
1549 addr_sub: AddrSubnet::new(addr, 128).unwrap(),
1550 deprecated: false,
1551 assigned: true,
1552 temporary: false,
1553 device,
1554 };
1555
1556 assert_eq!(
1558 select_ipv6_source_address_cmp(
1559 Some(remote),
1560 dev0,
1561 &new_addr_entry(*local0, *dev1),
1562 &new_addr_entry(*local1, *dev2),
1563 ),
1564 Ordering::Equal
1565 );
1566 }
1567 }
1568
1569 #[test]
1570 fn test_select_ipv6_source_address_no_remote() {
1571 let dev0 = &0;
1574 let dev1 = &1;
1575 let dev2 = &2;
1576
1577 let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
1578 let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
1579
1580 let new_addr_entry = |addr, deprecated, device| SasCandidate {
1581 addr_sub: AddrSubnet::new(addr, 128).unwrap(),
1582 deprecated,
1583 assigned: true,
1584 temporary: false,
1585 device,
1586 };
1587
1588 assert_eq!(
1590 select_ipv6_source_address_cmp(
1591 None,
1592 dev0,
1593 &new_addr_entry(*local0, false, *dev1),
1594 &new_addr_entry(*local1, true, *dev2),
1595 ),
1596 Ordering::Greater
1597 );
1598
1599 assert_eq!(
1601 select_ipv6_source_address_cmp(
1602 None,
1603 dev0,
1604 &new_addr_entry(*local0, false, *dev0),
1605 &new_addr_entry(*local1, false, *dev1),
1606 ),
1607 Ordering::Greater
1608 );
1609 }
1610 }
1611}
1612
1613#[cfg(any(test, feature = "testutils"))]
1615pub(crate) mod testutil {
1616 use alloc::boxed::Box;
1617 use alloc::vec::Vec;
1618 use core::num::NonZeroUsize;
1619
1620 use crate::internal::types::RoutePreference;
1621 use derivative::Derivative;
1622 use net_types::MulticastAddr;
1623 use net_types::ip::{GenericOverIp, IpAddr, IpAddress, Ipv4, Ipv4Addr, Ipv6, Subnet};
1624 use netstack3_base::testutil::{FakeCoreCtx, FakeStrongDeviceId, FakeWeakDeviceId};
1625 use netstack3_base::{SendFrameContext, SendFrameError};
1626 use netstack3_filter::Tuple;
1627 use netstack3_hashmap::HashMap;
1628
1629 use super::*;
1630 use crate::internal::base::{
1631 BaseTransportIpContext, DEFAULT_HOP_LIMITS, HopLimits, MulticastMembershipHandler,
1632 };
1633 use crate::internal::routing::testutil::FakeIpRoutingCtx;
1634 use crate::internal::routing::{self, RoutingTable};
1635 use crate::internal::types::{Destination, Entry, Metric, RawMetric};
1636
1637 #[derive(Derivative, GenericOverIp)]
1640 #[generic_over_ip(I, Ip)]
1641 #[derivative(Default(bound = ""))]
1642 pub struct FakeIpSocketCtx<I: Ip, D> {
1643 pub(crate) table: RoutingTable<I, D>,
1644 forwarding: FakeIpRoutingCtx<D>,
1645 devices: HashMap<D, FakeDeviceState<I>>,
1646 }
1647
1648 pub trait InnerFakeIpSocketCtx<I: Ip, D> {
1651 fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D>;
1653 }
1654
1655 impl<I: Ip, D> InnerFakeIpSocketCtx<I, D> for FakeIpSocketCtx<I, D> {
1656 fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1657 self
1658 }
1659 }
1660
1661 impl<I: IpExt, D: FakeStrongDeviceId, BC> BaseTransportIpContext<I, BC> for FakeIpSocketCtx<I, D> {
1662 fn get_default_hop_limits(&mut self, device: Option<&D>) -> HopLimits {
1663 device.map_or(DEFAULT_HOP_LIMITS, |device| {
1664 let hop_limit = self.get_device_state(device).default_hop_limit;
1665 HopLimits { unicast: hop_limit, multicast: DEFAULT_HOP_LIMITS.multicast }
1666 })
1667 }
1668
1669 type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;
1670
1671 fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
1672 &mut self,
1673 addr: SpecifiedAddr<I::Addr>,
1674 cb: F,
1675 ) -> O {
1676 cb(Box::new(self.devices.iter().filter_map(move |(device, state)| {
1677 state.addresses.contains(&addr).then(|| device.clone())
1678 })))
1679 }
1680
1681 fn get_original_destination(&mut self, _tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
1682 unimplemented!()
1683 }
1684 }
1685
1686 impl<I: IpExt, D: FakeStrongDeviceId> DeviceIdContext<AnyDevice> for FakeIpSocketCtx<I, D> {
1687 type DeviceId = D;
1688 type WeakDeviceId = D::Weak;
1689 }
1690
1691 impl<I, State, D, Meta, BC> IpSocketHandler<I, BC> for FakeCoreCtx<State, Meta, D>
1692 where
1693 I: IpExt + FilterIpExt,
1694 State: InnerFakeIpSocketCtx<I, D>,
1695 D: FakeStrongDeviceId,
1696 BC: TxMetadataBindingsTypes,
1697 FakeCoreCtx<State, Meta, D>:
1698 SendFrameContext<BC, SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>>,
1699 {
1700 fn new_ip_socket<O>(
1701 &mut self,
1702 _bindings_ctx: &mut BC,
1703 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
1704 ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
1705 where
1706 O: RouteResolutionOptions<I>,
1707 {
1708 self.state.fake_ip_socket_ctx_mut().new_ip_socket(args)
1709 }
1710
1711 fn send_ip_packet<S, O>(
1712 &mut self,
1713 bindings_ctx: &mut BC,
1714 socket: &IpSock<I, Self::WeakDeviceId>,
1715 body: S,
1716 options: &O,
1717 _tx_meta: BC::TxMetadata,
1720 ) -> Result<(), IpSockSendError>
1721 where
1722 S: TransportPacketSerializer<I> + MaybeSegmentableTransportSerializer,
1723 S::Buffer: BufferMut,
1724 O: SendOptions<I> + RouteResolutionOptions<I>,
1725 {
1726 let meta = self.state.fake_ip_socket_ctx_mut().resolve_send_meta(socket, options)?;
1727 self.send_frame(bindings_ctx, meta, body).or_else(
1728 |SendFrameError { serializer: _, error }| IpSockSendError::from_send_frame(error),
1729 )
1730 }
1731
1732 fn confirm_reachable<O>(
1733 &mut self,
1734 _bindings_ctx: &mut BC,
1735 _socket: &IpSock<I, Self::WeakDeviceId>,
1736 _options: &O,
1737 ) {
1738 }
1739 }
1740
1741 impl<I: IpExt, D: FakeStrongDeviceId, BC> MulticastMembershipHandler<I, BC>
1742 for FakeIpSocketCtx<I, D>
1743 {
1744 fn join_multicast_group(
1745 &mut self,
1746 _bindings_ctx: &mut BC,
1747 device: &Self::DeviceId,
1748 addr: MulticastAddr<<I as Ip>::Addr>,
1749 ) {
1750 let value = self.get_device_state_mut(device).multicast_groups.entry(addr).or_insert(0);
1751 *value = value.checked_add(1).unwrap();
1752 }
1753
1754 fn leave_multicast_group(
1755 &mut self,
1756 _bindings_ctx: &mut BC,
1757 device: &Self::DeviceId,
1758 addr: MulticastAddr<<I as Ip>::Addr>,
1759 ) {
1760 let value = self
1761 .get_device_state_mut(device)
1762 .multicast_groups
1763 .get_mut(&addr)
1764 .unwrap_or_else(|| panic!("no entry for {addr} on {device:?}"));
1765 *value = value.checked_sub(1).unwrap();
1766 }
1767
1768 fn select_device_for_multicast_group(
1769 &mut self,
1770 addr: MulticastAddr<<I as Ip>::Addr>,
1771 _marks: &Marks,
1772 ) -> Result<Self::DeviceId, ResolveRouteError> {
1773 let remote_ip = SocketIpAddr::new_from_multicast(addr);
1774 self.lookup_route(None, None, remote_ip, false)
1775 .map(|ResolvedRoute { device, .. }| device)
1776 }
1777 }
1778
1779 impl<I, BC, D, State, Meta> BaseTransportIpContext<I, BC> for FakeCoreCtx<State, Meta, D>
1780 where
1781 I: IpExt + FilterIpExt,
1782 D: FakeStrongDeviceId,
1783 State: InnerFakeIpSocketCtx<I, D>,
1784 BC: TxMetadataBindingsTypes,
1785 Self: IpSocketHandler<I, BC, DeviceId = D, WeakDeviceId = FakeWeakDeviceId<D>>,
1786 {
1787 type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;
1788
1789 fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
1790 &mut self,
1791 addr: SpecifiedAddr<I::Addr>,
1792 cb: F,
1793 ) -> O {
1794 BaseTransportIpContext::<I, BC>::with_devices_with_assigned_addr(
1795 self.state.fake_ip_socket_ctx_mut(),
1796 addr,
1797 cb,
1798 )
1799 }
1800
1801 fn get_default_hop_limits(&mut self, device: Option<&Self::DeviceId>) -> HopLimits {
1802 BaseTransportIpContext::<I, BC>::get_default_hop_limits(
1803 self.state.fake_ip_socket_ctx_mut(),
1804 device,
1805 )
1806 }
1807
1808 fn get_original_destination(&mut self, tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
1809 BaseTransportIpContext::<I, BC>::get_original_destination(
1810 self.state.fake_ip_socket_ctx_mut(),
1811 tuple,
1812 )
1813 }
1814 }
1815
1816 #[derive(Derivative)]
1818 #[derivative(Default(bound = ""))]
1819 pub struct FakeDualStackIpSocketCtx<D> {
1820 v4: FakeIpSocketCtx<Ipv4, D>,
1821 v6: FakeIpSocketCtx<Ipv6, D>,
1822 }
1823
1824 impl<D: FakeStrongDeviceId> FakeDualStackIpSocketCtx<D> {
1825 pub fn new<A: Into<SpecifiedAddr<IpAddr>>>(
1827 devices: impl IntoIterator<Item = FakeDeviceConfig<D, A>>,
1828 ) -> Self {
1829 let partition =
1830 |v: Vec<A>| -> (Vec<SpecifiedAddr<Ipv4Addr>>, Vec<SpecifiedAddr<Ipv6Addr>>) {
1831 v.into_iter().fold((Vec::new(), Vec::new()), |(mut v4, mut v6), i| {
1832 match IpAddr::from(i.into()) {
1833 IpAddr::V4(a) => v4.push(a),
1834 IpAddr::V6(a) => v6.push(a),
1835 }
1836 (v4, v6)
1837 })
1838 };
1839
1840 let (v4, v6): (Vec<_>, Vec<_>) = devices
1841 .into_iter()
1842 .map(|FakeDeviceConfig { device, local_ips, remote_ips }| {
1843 let (local_v4, local_v6) = partition(local_ips);
1844 let (remote_v4, remote_v6) = partition(remote_ips);
1845 (
1846 FakeDeviceConfig {
1847 device: device.clone(),
1848 local_ips: local_v4,
1849 remote_ips: remote_v4,
1850 },
1851 FakeDeviceConfig { device, local_ips: local_v6, remote_ips: remote_v6 },
1852 )
1853 })
1854 .unzip();
1855 Self { v4: FakeIpSocketCtx::new(v4), v6: FakeIpSocketCtx::new(v6) }
1856 }
1857
1858 pub fn inner_mut<I: Ip>(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1860 I::map_ip_out(self, |s| &mut s.v4, |s| &mut s.v6)
1861 }
1862
1863 fn inner<I: Ip>(&self) -> &FakeIpSocketCtx<I, D> {
1864 I::map_ip_out(self, |s| &s.v4, |s| &s.v6)
1865 }
1866
1867 pub fn add_route(&mut self, device: D, ip: SpecifiedAddr<IpAddr>) {
1869 match IpAddr::from(ip) {
1870 IpAddr::V4(ip) => {
1871 routing::testutil::add_on_link_routing_entry(&mut self.v4.table, ip, device)
1872 }
1873 IpAddr::V6(ip) => {
1874 routing::testutil::add_on_link_routing_entry(&mut self.v6.table, ip, device)
1875 }
1876 }
1877 }
1878
1879 pub fn add_subnet_route<A: IpAddress>(&mut self, device: D, subnet: Subnet<A>) {
1881 let entry = Entry {
1882 subnet,
1883 device,
1884 gateway: None,
1885 metric: Metric::ExplicitMetric(RawMetric(0)),
1886 route_preference: RoutePreference::Medium,
1887 };
1888 A::Version::map_ip::<_, ()>(
1889 entry,
1890 |entry_v4| {
1891 let _ = routing::testutil::add_entry(&mut self.v4.table, entry_v4)
1892 .expect("Failed to add route");
1893 },
1894 |entry_v6| {
1895 let _ = routing::testutil::add_entry(&mut self.v6.table, entry_v6)
1896 .expect("Failed to add route");
1897 },
1898 );
1899 }
1900
1901 pub fn get_device_state_mut<I: IpExt>(&mut self, device: &D) -> &mut FakeDeviceState<I> {
1903 self.inner_mut::<I>().get_device_state_mut(device)
1904 }
1905
1906 pub fn multicast_memberships<I: IpExt>(
1908 &self,
1909 ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
1910 self.inner::<I>().multicast_memberships()
1911 }
1912 }
1913
1914 impl<I: IpExt, S: InnerFakeIpSocketCtx<I, D>, Meta, D: FakeStrongDeviceId, BC>
1915 MulticastMembershipHandler<I, BC> for FakeCoreCtx<S, Meta, D>
1916 {
1917 fn join_multicast_group(
1918 &mut self,
1919 bindings_ctx: &mut BC,
1920 device: &Self::DeviceId,
1921 addr: MulticastAddr<<I as Ip>::Addr>,
1922 ) {
1923 MulticastMembershipHandler::<I, BC>::join_multicast_group(
1924 self.state.fake_ip_socket_ctx_mut(),
1925 bindings_ctx,
1926 device,
1927 addr,
1928 )
1929 }
1930
1931 fn leave_multicast_group(
1932 &mut self,
1933 bindings_ctx: &mut BC,
1934 device: &Self::DeviceId,
1935 addr: MulticastAddr<<I as Ip>::Addr>,
1936 ) {
1937 MulticastMembershipHandler::<I, BC>::leave_multicast_group(
1938 self.state.fake_ip_socket_ctx_mut(),
1939 bindings_ctx,
1940 device,
1941 addr,
1942 )
1943 }
1944
1945 fn select_device_for_multicast_group(
1946 &mut self,
1947 addr: MulticastAddr<<I as Ip>::Addr>,
1948 marks: &Marks,
1949 ) -> Result<Self::DeviceId, ResolveRouteError> {
1950 MulticastMembershipHandler::<I, BC>::select_device_for_multicast_group(
1951 self.state.fake_ip_socket_ctx_mut(),
1952 addr,
1953 marks,
1954 )
1955 }
1956 }
1957
1958 impl<I: Ip, D, State: InnerFakeIpSocketCtx<I, D>, Meta> InnerFakeIpSocketCtx<I, D>
1959 for FakeCoreCtx<State, Meta, D>
1960 {
1961 fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1962 self.state.fake_ip_socket_ctx_mut()
1963 }
1964 }
1965
1966 impl<I: Ip, D: FakeStrongDeviceId> InnerFakeIpSocketCtx<I, D> for FakeDualStackIpSocketCtx<D> {
1967 fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1968 self.inner_mut::<I>()
1969 }
1970 }
1971
1972 #[derive(Clone, GenericOverIp)]
1974 #[generic_over_ip()]
1975 pub struct FakeDeviceConfig<D, A> {
1976 pub device: D,
1978 pub local_ips: Vec<A>,
1980 pub remote_ips: Vec<A>,
1982 }
1983
1984 pub struct FakeDeviceState<I: Ip> {
1986 pub default_hop_limit: NonZeroU8,
1988 pub addresses: Vec<SpecifiedAddr<I::Addr>>,
1990 pub multicast_groups: HashMap<MulticastAddr<I::Addr>, usize>,
1992 }
1993
1994 impl<I: Ip> FakeDeviceState<I> {
1995 pub fn is_in_multicast_group(&self, addr: &MulticastAddr<I::Addr>) -> bool {
1997 self.multicast_groups.get(addr).is_some_and(|v| *v != 0)
1998 }
1999 }
2000
2001 impl<I: IpExt, D: FakeStrongDeviceId> FakeIpSocketCtx<I, D> {
2002 pub fn new(
2005 device_configs: impl IntoIterator<Item = FakeDeviceConfig<D, SpecifiedAddr<I::Addr>>>,
2006 ) -> Self {
2007 let mut table = RoutingTable::default();
2008 let mut devices = HashMap::default();
2009 for FakeDeviceConfig { device, local_ips, remote_ips } in device_configs {
2010 for addr in remote_ips {
2011 routing::testutil::add_on_link_routing_entry(&mut table, addr, device.clone())
2012 }
2013 let state = FakeDeviceState {
2014 default_hop_limit: DEFAULT_HOP_LIMITS.unicast,
2015 addresses: local_ips,
2016 multicast_groups: Default::default(),
2017 };
2018 assert!(
2019 devices.insert(device.clone(), state).is_none(),
2020 "duplicate entries for {device:?}",
2021 );
2022 }
2023
2024 Self { table, devices, forwarding: Default::default() }
2025 }
2026
2027 pub fn get_device_state(&self, device: &D) -> &FakeDeviceState<I> {
2029 self.devices.get(device).unwrap_or_else(|| panic!("no device {device:?}"))
2030 }
2031
2032 pub fn get_device_state_mut(&mut self, device: &D) -> &mut FakeDeviceState<I> {
2034 self.devices.get_mut(device).unwrap_or_else(|| panic!("no device {device:?}"))
2035 }
2036
2037 pub(crate) fn multicast_memberships(
2038 &self,
2039 ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
2040 self.devices
2041 .iter()
2042 .map(|(device, state)| {
2043 state.multicast_groups.iter().filter_map(|(group, count)| {
2044 NonZeroUsize::new(*count).map(|count| ((device.clone(), *group), count))
2045 })
2046 })
2047 .flatten()
2048 .collect()
2049 }
2050
2051 fn new_ip_socket<O>(
2052 &mut self,
2053 args: IpSocketArgs<'_, D, I, O>,
2054 ) -> Result<IpSock<I, D::Weak>, IpSockCreationError>
2055 where
2056 O: RouteResolutionOptions<I>,
2057 {
2058 let IpSocketArgs { device, local_ip, remote_ip, proto, options } = args;
2059 let device = device
2060 .as_ref()
2061 .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
2062 .transpose()?;
2063 let device = device.as_ref().map(|d| d.as_ref());
2064 let resolved_route =
2065 self.lookup_route(device, local_ip, remote_ip, options.transparent())?;
2066 Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
2067 }
2068
2069 fn lookup_route(
2070 &mut self,
2071 device: Option<&D>,
2072 local_ip: Option<IpDeviceAddr<I::Addr>>,
2073 addr: RoutableIpAddr<I::Addr>,
2074 transparent: bool,
2075 ) -> Result<ResolvedRoute<I, D>, ResolveRouteError> {
2076 let Self { table, devices, forwarding } = self;
2077 let (destination, ()) = table
2078 .lookup_filter_map(forwarding, device, addr.addr(), |_, d| match &local_ip {
2079 None => Some(()),
2080 Some(local_ip) => {
2081 if transparent {
2082 return Some(());
2083 }
2084 devices.get(d).and_then(|state| {
2085 state.addresses.contains(local_ip.as_ref()).then_some(())
2086 })
2087 }
2088 })
2089 .next()
2090 .ok_or(ResolveRouteError::Unreachable)?;
2091
2092 let Destination { device, next_hop } = destination;
2093 let mut addrs = devices.get(device).unwrap().addresses.iter();
2094 let local_ip = match local_ip {
2095 None => {
2096 let addr = addrs.next().ok_or(ResolveRouteError::NoSrcAddr)?;
2097 IpDeviceAddr::new(addr.get()).expect("not valid device addr")
2098 }
2099 Some(local_ip) => {
2100 if !transparent {
2101 assert!(
2104 addrs.any(|a| a.get() == local_ip.addr()),
2105 "didn't find IP {:?} in {:?}",
2106 local_ip,
2107 addrs.collect::<Vec<_>>()
2108 );
2109 }
2110 local_ip
2111 }
2112 };
2113
2114 Ok(ResolvedRoute {
2115 src_addr: local_ip,
2116 device: device.clone(),
2117 local_delivery_device: None,
2118 next_hop,
2119 internal_forwarding: InternalForwarding::NotUsed,
2122 })
2123 }
2124
2125 fn resolve_send_meta<O>(
2126 &mut self,
2127 socket: &IpSock<I, D::Weak>,
2128 options: &O,
2129 ) -> Result<SendIpPacketMeta<I, D, SpecifiedAddr<I::Addr>>, IpSockSendError>
2130 where
2131 O: SendOptions<I> + RouteResolutionOptions<I>,
2132 {
2133 let IpSockDefinition { remote_ip, local_ip, device, proto } = &socket.definition;
2134 let device = device
2135 .as_ref()
2136 .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
2137 .transpose()?;
2138 let ResolvedRoute {
2139 src_addr,
2140 device,
2141 next_hop,
2142 local_delivery_device: _,
2143 internal_forwarding: _,
2144 } = self.lookup_route(
2145 device.as_ref(),
2146 Some(*local_ip),
2147 *remote_ip,
2148 options.transparent(),
2149 )?;
2150
2151 let remote_ip: &SpecifiedAddr<_> = remote_ip.as_ref();
2152
2153 let destination = IpPacketDestination::from_next_hop(next_hop, *remote_ip);
2154 Ok(SendIpPacketMeta {
2155 device,
2156 src_ip: src_addr.into(),
2157 dst_ip: *remote_ip,
2158 destination,
2159 proto: *proto,
2160 ttl: options.hop_limit(remote_ip),
2161 mtu: options.mtu(),
2162 dscp_and_ecn: DscpAndEcn::default(),
2163 })
2164 }
2165 }
2166}