1use alloc::boxed::Box;
8use core::convert::TryInto as _;
9use core::num::{NonZeroU16, NonZeroU8};
10
11use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
12use log::{debug, error, trace};
13use net_types::ip::{
14 GenericOverIp, Ip, IpAddress, IpMarked, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr, Ipv6SourceAddr, Mtu,
15 SubnetError,
16};
17use net_types::{
18 LinkLocalAddress, LinkLocalUnicastAddr, MulticastAddress, SpecifiedAddr, UnicastAddr, Witness,
19};
20use netstack3_base::socket::{AddrIsMappedError, SocketIpAddr, SocketIpAddrExt as _};
21use netstack3_base::sync::Mutex;
22use netstack3_base::{
23 AnyDevice, Counter, CounterContext, DeviceIdContext, EitherDeviceId, FrameDestination,
24 IcmpIpExt, Icmpv4ErrorCode, Icmpv6ErrorCode, InstantBindingsTypes, InstantContext,
25 IpDeviceAddr, IpExt, Marks, RngContext, TokenBucket, TxMetadataBindingsTypes,
26};
27use netstack3_filter::{self as filter, TransportPacketSerializer};
28use packet::{
29 BufferMut, InnerPacketBuilder as _, ParsablePacket as _, ParseBuffer, Serializer,
30 TruncateDirection, TruncatingSerializer,
31};
32use packet_formats::icmp::ndp::options::{NdpOption, NdpOptionBuilder};
33use packet_formats::icmp::ndp::{
34 NdpPacket, NeighborAdvertisement, NonZeroNdpLifetime, OptionSequenceBuilder,
35};
36use packet_formats::icmp::{
37 peek_message_type, IcmpDestUnreachable, IcmpEchoRequest, IcmpMessage, IcmpMessageType,
38 IcmpPacket, IcmpPacketBuilder, IcmpPacketRaw, IcmpParseArgs, IcmpTimeExceeded, IcmpZeroCode,
39 Icmpv4DestUnreachableCode, Icmpv4Packet, Icmpv4ParameterProblem, Icmpv4ParameterProblemCode,
40 Icmpv4TimeExceededCode, Icmpv6DestUnreachableCode, Icmpv6Packet, Icmpv6PacketTooBig,
41 Icmpv6ParameterProblem, Icmpv6ParameterProblemCode, Icmpv6TimeExceededCode, MessageBody,
42 OriginalPacket,
43};
44use packet_formats::ip::{DscpAndEcn, IpPacket, Ipv4Proto, Ipv6Proto};
45use packet_formats::ipv4::{Ipv4FragmentType, Ipv4Header, Ipv4OnlyMeta};
46use packet_formats::ipv6::{ExtHdrParseError, Ipv6Header};
47use zerocopy::SplitByteSlice;
48
49use crate::internal::base::{
50 AddressStatus, IpDeviceIngressStateContext, IpLayerHandler, IpPacketDestination,
51 IpSendFrameError, IpTransportContext, Ipv6PresentAddressStatus, NdpBindingsContext,
52 RouterAdvertisementEvent, SendIpPacketMeta, TransportReceiveError, IPV6_DEFAULT_SUBNET,
53};
54use crate::internal::device::nud::{ConfirmationFlags, NudIpHandler};
55use crate::internal::device::route_discovery::Ipv6DiscoveredRoute;
56use crate::internal::device::{
57 IpAddressState, IpDeviceHandler, Ipv6DeviceHandler, Ipv6LinkLayerAddr,
58};
59use crate::internal::local_delivery::{IpHeaderInfo, LocalDeliveryPacketInfo, ReceiveIpPacketMeta};
60use crate::internal::path_mtu::PmtuHandler;
61use crate::internal::socket::{
62 DelegatedRouteResolutionOptions, DelegatedSendOptions, IpSocketHandler, OptionDelegationMarker,
63 RouteResolutionOptions, SendOptions,
64};
65
66pub const REQUIRED_NDP_IP_PACKET_HOP_LIMIT: u8 = 255;
78
79pub const DEFAULT_ERRORS_PER_SECOND: u64 = 1000;
87#[derive(GenericOverIp)]
89#[generic_over_ip(I, Ip)]
90pub struct IcmpState<I: IpExt, BT: IcmpBindingsTypes> {
91 error_send_bucket: Mutex<IpMarked<I, TokenBucket<BT::Instant>>>,
92 pub tx_counters: IcmpTxCounters<I>,
94 pub rx_counters: IcmpRxCounters<I>,
96}
97
98impl<I, BT> OrderedLockAccess<IpMarked<I, TokenBucket<BT::Instant>>> for IcmpState<I, BT>
99where
100 I: IpExt,
101 BT: IcmpBindingsTypes,
102{
103 type Lock = Mutex<IpMarked<I, TokenBucket<BT::Instant>>>;
104 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
105 OrderedLockRef::new(&self.error_send_bucket)
106 }
107}
108
109pub type IcmpTxCounters<I> = IpMarked<I, IcmpTxCountersInner>;
111
112#[derive(Default)]
114pub struct IcmpTxCountersInner {
115 pub reply: Counter,
117 pub protocol_unreachable: Counter,
119 pub address_unreachable: Counter,
121 pub port_unreachable: Counter,
123 pub net_unreachable: Counter,
125 pub ttl_expired: Counter,
127 pub packet_too_big: Counter,
129 pub parameter_problem: Counter,
131 pub dest_unreachable: Counter,
133 pub error: Counter,
135}
136
137pub type IcmpRxCounters<I> = IpMarked<I, IcmpRxCountersInner>;
139
140#[derive(Default)]
142pub struct IcmpRxCountersInner {
143 pub error: Counter,
145 pub error_delivered_to_transport_layer: Counter,
147 pub error_delivered_to_socket: Counter,
149 pub echo_request: Counter,
151 pub echo_reply: Counter,
153 pub timestamp_request: Counter,
155 pub dest_unreachable: Counter,
157 pub time_exceeded: Counter,
159 pub parameter_problem: Counter,
161 pub packet_too_big: Counter,
163}
164
165#[derive(Default)]
167pub struct NdpRxCounters {
168 pub neighbor_solicitation: Counter,
170 pub neighbor_advertisement: Counter,
172 pub router_advertisement: Counter,
174 pub router_solicitation: Counter,
176}
177
178#[derive(Default)]
180pub struct NdpTxCounters {
181 pub neighbor_advertisement: Counter,
183 pub neighbor_solicitation: Counter,
185}
186
187#[derive(Default)]
189pub struct NdpCounters {
190 pub rx: NdpRxCounters,
192 pub tx: NdpTxCounters,
194}
195
196#[derive(Copy, Clone)]
198pub struct Icmpv4StateBuilder {
199 send_timestamp_reply: bool,
200 errors_per_second: u64,
201}
202
203impl Default for Icmpv4StateBuilder {
204 fn default() -> Icmpv4StateBuilder {
205 Icmpv4StateBuilder {
206 send_timestamp_reply: false,
207 errors_per_second: DEFAULT_ERRORS_PER_SECOND,
208 }
209 }
210}
211
212impl Icmpv4StateBuilder {
213 pub fn send_timestamp_reply(&mut self, send_timestamp_reply: bool) -> &mut Self {
220 self.send_timestamp_reply = send_timestamp_reply;
221 self
222 }
223
224 pub fn build<BT: IcmpBindingsTypes>(self) -> Icmpv4State<BT> {
226 Icmpv4State {
227 inner: IcmpState {
228 error_send_bucket: Mutex::new(IpMarked::new(TokenBucket::new(
229 self.errors_per_second,
230 ))),
231 tx_counters: Default::default(),
232 rx_counters: Default::default(),
233 },
234 send_timestamp_reply: self.send_timestamp_reply,
235 }
236 }
237}
238
239pub struct Icmpv4State<BT: IcmpBindingsTypes> {
241 pub inner: IcmpState<Ipv4, BT>,
243 pub send_timestamp_reply: bool,
245}
246
247impl<BT: IcmpBindingsTypes> AsRef<IcmpState<Ipv4, BT>> for Icmpv4State<BT> {
248 fn as_ref(&self) -> &IcmpState<Ipv4, BT> {
249 &self.inner
250 }
251}
252
253impl<BT: IcmpBindingsTypes> AsMut<IcmpState<Ipv4, BT>> for Icmpv4State<BT> {
254 fn as_mut(&mut self) -> &mut IcmpState<Ipv4, BT> {
255 &mut self.inner
256 }
257}
258
259#[derive(Copy, Clone)]
261pub(crate) struct Icmpv6StateBuilder {
262 errors_per_second: u64,
263}
264
265impl Default for Icmpv6StateBuilder {
266 fn default() -> Icmpv6StateBuilder {
267 Icmpv6StateBuilder { errors_per_second: DEFAULT_ERRORS_PER_SECOND }
268 }
269}
270
271impl Icmpv6StateBuilder {
272 pub(crate) fn build<BT: IcmpBindingsTypes>(self) -> Icmpv6State<BT> {
273 Icmpv6State {
274 inner: IcmpState {
275 error_send_bucket: Mutex::new(IpMarked::new(TokenBucket::new(
276 self.errors_per_second,
277 ))),
278 tx_counters: Default::default(),
279 rx_counters: Default::default(),
280 },
281 ndp_counters: Default::default(),
282 }
283 }
284}
285
286pub struct Icmpv6State<BT: IcmpBindingsTypes> {
288 pub inner: IcmpState<Ipv6, BT>,
290 pub ndp_counters: NdpCounters,
292}
293
294impl<BT: IcmpBindingsTypes> AsRef<IcmpState<Ipv6, BT>> for Icmpv6State<BT> {
295 fn as_ref(&self) -> &IcmpState<Ipv6, BT> {
296 &self.inner
297 }
298}
299
300impl<BT: IcmpBindingsTypes> AsMut<IcmpState<Ipv6, BT>> for Icmpv6State<BT> {
301 fn as_mut(&mut self) -> &mut IcmpState<Ipv6, BT> {
302 &mut self.inner
303 }
304}
305
306pub trait IcmpHandlerIpExt: IpExt {
308 type SourceAddress: Witness<Self::Addr>;
309 type IcmpError;
310
311 fn received_source_as_icmp_source(src: Self::RecvSrcAddr) -> Option<Self::SourceAddress>;
313
314 fn new_ttl_expired<B: SplitByteSlice>(
316 proto: Self::Proto,
317 header_len: usize,
318 meta: <Self::Packet<B> as IpPacket<B, Self>>::VersionSpecificMeta,
319 ) -> Self::IcmpError;
320
321 fn new_mtu_exceeded(proto: Self::Proto, header_len: usize, mtu: Mtu)
323 -> Option<Self::IcmpError>;
324}
325
326impl IcmpHandlerIpExt for Ipv4 {
327 type SourceAddress = SpecifiedAddr<Ipv4Addr>;
328 type IcmpError = Icmpv4Error;
329 fn received_source_as_icmp_source(src: Ipv4Addr) -> Option<SpecifiedAddr<Ipv4Addr>> {
330 SpecifiedAddr::new(src)
331 }
332 fn new_ttl_expired<B: SplitByteSlice>(
333 proto: Ipv4Proto,
334 header_len: usize,
335 Ipv4OnlyMeta { id: _, fragment_type }: Ipv4OnlyMeta,
336 ) -> Icmpv4Error {
337 Icmpv4Error { kind: Icmpv4ErrorKind::TtlExpired { proto, fragment_type }, header_len }
338 }
339 fn new_mtu_exceeded(_proto: Ipv4Proto, _header_len: usize, _mtu: Mtu) -> Option<Icmpv4Error> {
340 None
342 }
343}
344
345impl IcmpHandlerIpExt for Ipv6 {
346 type SourceAddress = UnicastAddr<Ipv6Addr>;
347 type IcmpError = Icmpv6ErrorKind;
348 fn received_source_as_icmp_source(src: Ipv6SourceAddr) -> Option<UnicastAddr<Ipv6Addr>> {
349 match src {
350 Ipv6SourceAddr::Unicast(src) => Some(src.get()),
351 Ipv6SourceAddr::Unspecified => None,
352 }
353 }
354 fn new_ttl_expired<B: SplitByteSlice>(
355 proto: Ipv6Proto,
356 header_len: usize,
357 _meta: (),
358 ) -> Icmpv6ErrorKind {
359 Icmpv6ErrorKind::TtlExpired { proto, header_len }
360 }
361 fn new_mtu_exceeded(proto: Ipv6Proto, header_len: usize, mtu: Mtu) -> Option<Icmpv6ErrorKind> {
362 Some(Icmpv6ErrorKind::PacketTooBig { proto, header_len, mtu })
363 }
364}
365
366pub(crate) enum Icmpv4ErrorKind {
368 ParameterProblem {
369 code: Icmpv4ParameterProblemCode,
370 pointer: u8,
371 fragment_type: Ipv4FragmentType,
372 },
373 TtlExpired {
374 proto: Ipv4Proto,
375 fragment_type: Ipv4FragmentType,
376 },
377 NetUnreachable {
378 proto: Ipv4Proto,
379 fragment_type: Ipv4FragmentType,
380 },
381 ProtocolUnreachable,
382 PortUnreachable,
383}
384
385pub struct Icmpv4Error {
387 pub(super) kind: Icmpv4ErrorKind,
388 pub(super) header_len: usize,
389}
390
391pub enum Icmpv6ErrorKind {
393 ParameterProblem { code: Icmpv6ParameterProblemCode, pointer: u32, allow_dst_multicast: bool },
394 TtlExpired { proto: Ipv6Proto, header_len: usize },
395 NetUnreachable { proto: Ipv6Proto, header_len: usize },
396 PacketTooBig { proto: Ipv6Proto, header_len: usize, mtu: Mtu },
397 ProtocolUnreachable { header_len: usize },
398 PortUnreachable,
399}
400
401pub trait IcmpErrorHandler<I: IcmpHandlerIpExt, BC>: DeviceIdContext<AnyDevice> {
403 fn send_icmp_error_message<B: BufferMut>(
408 &mut self,
409 bindings_ctx: &mut BC,
410 device: &Self::DeviceId,
411 frame_dst: Option<FrameDestination>,
412 src_ip: I::SourceAddress,
413 dst_ip: SpecifiedAddr<I::Addr>,
414 original_packet: B,
415 error: I::IcmpError,
416 marks: &Marks,
417 );
418}
419
420impl<
421 BC: IcmpBindingsContext,
422 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
423 > IcmpErrorHandler<Ipv4, BC> for CC
424{
425 fn send_icmp_error_message<B: BufferMut>(
426 &mut self,
427 bindings_ctx: &mut BC,
428 device: &CC::DeviceId,
429 frame_dst: Option<FrameDestination>,
430 src_ip: SpecifiedAddr<Ipv4Addr>,
431 dst_ip: SpecifiedAddr<Ipv4Addr>,
432 original_packet: B,
433 Icmpv4Error { kind, header_len }: Icmpv4Error,
434 marks: &Marks,
435 ) {
436 let src_ip = SocketIpAddr::new_ipv4_specified(src_ip);
437 let dst_ip = SocketIpAddr::new_ipv4_specified(dst_ip);
438 match kind {
439 Icmpv4ErrorKind::ParameterProblem { code, pointer, fragment_type } => {
440 send_icmpv4_parameter_problem(
441 self,
442 bindings_ctx,
443 device,
444 frame_dst,
445 src_ip,
446 dst_ip,
447 code,
448 Icmpv4ParameterProblem::new(pointer),
449 original_packet,
450 header_len,
451 fragment_type,
452 marks,
453 )
454 }
455 Icmpv4ErrorKind::TtlExpired { proto, fragment_type } => send_icmpv4_ttl_expired(
456 self,
457 bindings_ctx,
458 device,
459 frame_dst,
460 src_ip,
461 dst_ip,
462 proto,
463 original_packet,
464 header_len,
465 fragment_type,
466 marks,
467 ),
468 Icmpv4ErrorKind::NetUnreachable { proto, fragment_type } => {
469 send_icmpv4_net_unreachable(
470 self,
471 bindings_ctx,
472 device,
473 frame_dst,
474 src_ip,
475 dst_ip,
476 proto,
477 original_packet,
478 header_len,
479 fragment_type,
480 marks,
481 )
482 }
483 Icmpv4ErrorKind::ProtocolUnreachable => send_icmpv4_protocol_unreachable(
484 self,
485 bindings_ctx,
486 device,
487 frame_dst,
488 src_ip,
489 dst_ip,
490 original_packet,
491 header_len,
492 marks,
493 ),
494 Icmpv4ErrorKind::PortUnreachable => send_icmpv4_port_unreachable(
495 self,
496 bindings_ctx,
497 device,
498 frame_dst,
499 src_ip,
500 dst_ip,
501 original_packet,
502 header_len,
503 marks,
504 ),
505 }
506 }
507}
508
509impl<
510 BC: IcmpBindingsContext,
511 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
512 > IcmpErrorHandler<Ipv6, BC> for CC
513{
514 fn send_icmp_error_message<B: BufferMut>(
515 &mut self,
516 bindings_ctx: &mut BC,
517 device: &CC::DeviceId,
518 frame_dst: Option<FrameDestination>,
519 src_ip: UnicastAddr<Ipv6Addr>,
520 dst_ip: SpecifiedAddr<Ipv6Addr>,
521 original_packet: B,
522 error: Icmpv6ErrorKind,
523 marks: &Marks,
524 ) {
525 let src_ip: SocketIpAddr<Ipv6Addr> = match src_ip.into_specified().try_into() {
526 Ok(addr) => addr,
527 Err(AddrIsMappedError {}) => {
528 trace!("send_icmpv6_error_message: src_ip is mapped");
529 return;
530 }
531 };
532 let dst_ip: SocketIpAddr<Ipv6Addr> = match dst_ip.try_into() {
533 Ok(addr) => addr,
534 Err(AddrIsMappedError {}) => {
535 trace!("send_icmpv6_error_message: dst_ip is mapped");
536 return;
537 }
538 };
539
540 match error {
541 Icmpv6ErrorKind::ParameterProblem { code, pointer, allow_dst_multicast } => {
542 send_icmpv6_parameter_problem(
543 self,
544 bindings_ctx,
545 device,
546 frame_dst,
547 src_ip,
548 dst_ip,
549 code,
550 Icmpv6ParameterProblem::new(pointer),
551 original_packet,
552 allow_dst_multicast,
553 marks,
554 )
555 }
556 Icmpv6ErrorKind::TtlExpired { proto, header_len } => send_icmpv6_ttl_expired(
557 self,
558 bindings_ctx,
559 device,
560 frame_dst,
561 src_ip,
562 dst_ip,
563 proto,
564 original_packet,
565 header_len,
566 marks,
567 ),
568 Icmpv6ErrorKind::NetUnreachable { proto, header_len } => send_icmpv6_net_unreachable(
569 self,
570 bindings_ctx,
571 device,
572 frame_dst,
573 src_ip,
574 dst_ip,
575 proto,
576 original_packet,
577 header_len,
578 marks,
579 ),
580 Icmpv6ErrorKind::PacketTooBig { proto, header_len, mtu } => send_icmpv6_packet_too_big(
581 self,
582 bindings_ctx,
583 device,
584 frame_dst,
585 src_ip,
586 dst_ip,
587 proto,
588 mtu,
589 original_packet,
590 header_len,
591 marks,
592 ),
593 Icmpv6ErrorKind::ProtocolUnreachable { header_len } => {
594 send_icmpv6_protocol_unreachable(
595 self,
596 bindings_ctx,
597 device,
598 frame_dst,
599 src_ip,
600 dst_ip,
601 original_packet,
602 header_len,
603 marks,
604 )
605 }
606 Icmpv6ErrorKind::PortUnreachable => send_icmpv6_port_unreachable(
607 self,
608 bindings_ctx,
609 device,
610 frame_dst,
611 src_ip,
612 dst_ip,
613 original_packet,
614 marks,
615 ),
616 }
617 }
618}
619
620pub trait IcmpBindingsContext: InstantContext + RngContext + IcmpBindingsTypes {}
623impl<BC> IcmpBindingsContext for BC where
624 BC: InstantContext + RngContext + IcmpBindingsTypes + IcmpBindingsTypes
625{
626}
627
628pub trait IcmpBindingsTypes: InstantBindingsTypes + TxMetadataBindingsTypes {}
630impl<BT: InstantBindingsTypes + TxMetadataBindingsTypes> IcmpBindingsTypes for BT {}
631
632pub trait IcmpStateContext {}
640
641pub trait EchoTransportContextMarker {}
651
652pub trait InnerIcmpContext<I: IpExt, BC: IcmpBindingsTypes>: IpSocketHandler<I, BC> {
655 type EchoTransportContext: IpTransportContext<I, BC, Self> + EchoTransportContextMarker;
658
659 fn receive_icmp_error(
689 &mut self,
690 bindings_ctx: &mut BC,
691 device: &Self::DeviceId,
692 original_src_ip: Option<SpecifiedAddr<I::Addr>>,
693 original_dst_ip: SpecifiedAddr<I::Addr>,
694 original_proto: I::Proto,
695 original_body: &[u8],
696 err: I::ErrorCode,
697 );
698
699 fn with_error_send_bucket_mut<O, F: FnOnce(&mut TokenBucket<BC::Instant>) -> O>(
702 &mut self,
703 cb: F,
704 ) -> O;
705}
706
707pub trait InnerIcmpv4Context<BC: IcmpBindingsTypes>: InnerIcmpContext<Ipv4, BC> {
711 fn should_send_timestamp_reply(&self) -> bool;
713}
714
715pub trait InnerIcmpv6Context<BC: IcmpBindingsTypes>: InnerIcmpContext<Ipv6, BC> {}
719impl<BC: IcmpBindingsTypes, CC: InnerIcmpContext<Ipv6, BC>> InnerIcmpv6Context<BC> for CC {}
720
721macro_rules! try_send_error {
735 ($core_ctx:expr, $bindings_ctx:expr, $e:expr) => {{
736 let send = $core_ctx.with_error_send_bucket_mut(|error_send_bucket| {
737 error_send_bucket.try_take($bindings_ctx)
738 });
739
740 if send {
741 $core_ctx.counters().error.increment();
742 $e
743 } else {
744 trace!("ip::icmp::try_send_error!: dropping rate-limited ICMP error message");
745 Ok(())
746 }
747 }};
748}
749
750pub enum IcmpIpTransportContext {}
752
753fn receive_ip_transport_icmp_error<
754 I: IpExt,
755 CC: InnerIcmpContext<I, BC> + CounterContext<IcmpRxCounters<I>>,
756 BC: IcmpBindingsContext,
757>(
758 core_ctx: &mut CC,
759 bindings_ctx: &mut BC,
760 device: &CC::DeviceId,
761 original_src_ip: Option<SpecifiedAddr<I::Addr>>,
762 original_dst_ip: SpecifiedAddr<I::Addr>,
763 original_body: &[u8],
764 err: I::ErrorCode,
765) {
766 core_ctx.counters().error_delivered_to_transport_layer.increment();
767 trace!("IcmpIpTransportContext::receive_icmp_error({:?})", err);
768
769 let mut parse_body = original_body;
770 match parse_body.parse::<IcmpPacketRaw<I, _, IcmpEchoRequest>>() {
771 Ok(_echo_request) => (),
774 Err(_) => {
775 return;
779 }
780 }
781
782 <CC::EchoTransportContext as IpTransportContext<I, BC, CC>>::receive_icmp_error(
783 core_ctx,
784 bindings_ctx,
785 device,
786 original_src_ip,
787 original_dst_ip,
788 original_body,
789 err,
790 );
791}
792
793impl<
794 BC: IcmpBindingsContext,
795 CC: InnerIcmpv4Context<BC>
796 + PmtuHandler<Ipv4, BC>
797 + CounterContext<IcmpRxCounters<Ipv4>>
798 + CounterContext<IcmpTxCounters<Ipv4>>,
799 > IpTransportContext<Ipv4, BC, CC> for IcmpIpTransportContext
800{
801 fn receive_icmp_error(
802 core_ctx: &mut CC,
803 bindings_ctx: &mut BC,
804 device: &CC::DeviceId,
805 original_src_ip: Option<SpecifiedAddr<Ipv4Addr>>,
806 original_dst_ip: SpecifiedAddr<Ipv4Addr>,
807 original_body: &[u8],
808 err: Icmpv4ErrorCode,
809 ) {
810 receive_ip_transport_icmp_error(
811 core_ctx,
812 bindings_ctx,
813 device,
814 original_src_ip,
815 original_dst_ip,
816 original_body,
817 err,
818 )
819 }
820
821 fn receive_ip_packet<B: BufferMut, H: IpHeaderInfo<Ipv4>>(
822 core_ctx: &mut CC,
823 bindings_ctx: &mut BC,
824 device: &CC::DeviceId,
825 src_ip: Ipv4Addr,
826 dst_ip: SpecifiedAddr<Ipv4Addr>,
827 mut buffer: B,
828 info: &LocalDeliveryPacketInfo<Ipv4, H>,
829 ) -> Result<(), (B, TransportReceiveError)> {
830 let LocalDeliveryPacketInfo { meta, header_info: _, marks } = info;
831 let ReceiveIpPacketMeta { broadcast: _, transparent_override } = meta;
832 if let Some(delivery) = transparent_override {
833 unreachable!(
834 "cannot perform transparent local delivery {delivery:?} to an ICMP socket; \
835 transparent proxy rules can only be configured for TCP and UDP packets"
836 );
837 }
838
839 trace!(
840 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet({}, {})",
841 src_ip,
842 dst_ip
843 );
844 let packet =
845 match buffer.parse_with::<_, Icmpv4Packet<_>>(IcmpParseArgs::new(src_ip, dst_ip)) {
846 Ok(packet) => packet,
847 Err(_) => return Ok(()), };
849
850 match packet {
851 Icmpv4Packet::EchoRequest(echo_request) => {
852 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx).echo_request.increment();
853
854 if let Some(src_ip) = SpecifiedAddr::new(src_ip) {
855 let req = *echo_request.message();
856 let code = echo_request.code();
857 let (local_ip, remote_ip) = (dst_ip, src_ip);
858 debug!(
859 "replying to ICMP echo request from {remote_ip} to {local_ip}%{device:?}: \
860 id={}, seq={}",
861 req.id(),
862 req.seq()
863 );
864 send_icmp_reply(
865 core_ctx,
866 bindings_ctx,
867 device,
868 SocketIpAddr::new_ipv4_specified(remote_ip),
869 SocketIpAddr::new_ipv4_specified(local_ip),
870 |src_ip| {
871 buffer.encapsulate(IcmpPacketBuilder::<Ipv4, _>::new(
872 src_ip,
873 remote_ip,
874 code,
875 req.reply(),
876 ))
877 },
878 &WithMarks(marks),
879 );
880 } else {
881 trace!(
882 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
883 Received echo request with an unspecified source address"
884 );
885 }
886 }
887 Icmpv4Packet::EchoReply(echo_reply) => {
888 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx).echo_reply.increment();
889 trace!(
890 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
891 Received an EchoReply message"
892 );
893 let parse_metadata = echo_reply.parse_metadata();
894 buffer.undo_parse(parse_metadata);
895 return <CC::EchoTransportContext
896 as IpTransportContext<Ipv4, BC, CC>>::receive_ip_packet(
897 core_ctx,
898 bindings_ctx,
899 device,
900 src_ip,
901 dst_ip,
902 buffer,
903 info,
904 );
905 }
906 Icmpv4Packet::TimestampRequest(timestamp_request) => {
907 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx)
908 .timestamp_request
909 .increment();
910 if let Some(src_ip) = SpecifiedAddr::new(src_ip) {
911 if core_ctx.should_send_timestamp_reply() {
912 trace!(
913 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
914 receive_ip_packet: Responding to Timestamp Request message"
915 );
916 const NOW: u32 = 0x80000000;
935 let reply = timestamp_request.message().reply(NOW, NOW);
936 let (local_ip, remote_ip) = (dst_ip, src_ip);
937 buffer.shrink_front_to(0);
944 send_icmp_reply(
945 core_ctx,
946 bindings_ctx,
947 device,
948 SocketIpAddr::new_ipv4_specified(remote_ip),
949 SocketIpAddr::new_ipv4_specified(local_ip),
950 |src_ip| {
951 buffer.encapsulate(IcmpPacketBuilder::<Ipv4, _>::new(
952 src_ip,
953 remote_ip,
954 IcmpZeroCode,
955 reply,
956 ))
957 },
958 &WithMarks(marks),
959 );
960 } else {
961 trace!(
962 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
963 receive_ip_packet: Silently ignoring Timestamp Request message"
964 );
965 }
966 } else {
967 trace!(
968 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
969 receive_ip_packet: Received timestamp request with an unspecified source \
970 address"
971 );
972 }
973 }
974 Icmpv4Packet::TimestampReply(_) => {
975 debug!(
978 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
979 Received unsolicited Timestamp Reply message"
980 );
981 }
982 Icmpv4Packet::DestUnreachable(dest_unreachable) => {
983 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx)
984 .dest_unreachable
985 .increment();
986 trace!(
987 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
988 Received a Destination Unreachable message"
989 );
990
991 let error = if dest_unreachable.code()
992 == Icmpv4DestUnreachableCode::FragmentationRequired
993 {
994 let mtu = if let Some(next_hop_mtu) = dest_unreachable.message().next_hop_mtu()
995 {
996 core_ctx.update_pmtu_if_less(
1006 bindings_ctx,
1007 dst_ip.get(),
1008 src_ip,
1009 Mtu::new(u32::from(next_hop_mtu.get())),
1010 )
1011 } else {
1012 let (original_packet_buf, inner_body) = dest_unreachable.body().bytes();
1034 debug_assert!(inner_body.is_none());
1036 if original_packet_buf.len() >= 4 {
1037 let total_len =
1041 u16::from_be_bytes(original_packet_buf[2..4].try_into().unwrap());
1042
1043 trace!(
1044 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1045 receive_ip_packet: Next-Hop MTU is 0 so using the next best PMTU \
1046 value from {total_len}"
1047 );
1048
1049 core_ctx.update_pmtu_next_lower(
1050 bindings_ctx,
1051 dst_ip.get(),
1052 src_ip,
1053 Mtu::new(u32::from(total_len)),
1054 )
1055 } else {
1056 trace!(
1061 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1062 receive_ip_packet: Original packet buf is too small to get \
1063 original packet len so ignoring"
1064 );
1065 None
1066 }
1067 };
1068 mtu.and_then(|mtu| {
1069 let mtu = u16::try_from(mtu.get()).unwrap_or(u16::MAX);
1070 let mtu = NonZeroU16::new(mtu)?;
1071 Some(Icmpv4ErrorCode::DestUnreachable(
1072 dest_unreachable.code(),
1073 IcmpDestUnreachable::new_for_frag_req(mtu),
1074 ))
1075 })
1076 } else {
1077 Some(Icmpv4ErrorCode::DestUnreachable(
1078 dest_unreachable.code(),
1079 *dest_unreachable.message(),
1080 ))
1081 };
1082
1083 if let Some(error) = error {
1084 receive_icmpv4_error(core_ctx, bindings_ctx, device, &dest_unreachable, error);
1085 }
1086 }
1087 Icmpv4Packet::TimeExceeded(time_exceeded) => {
1088 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx)
1089 .time_exceeded
1090 .increment();
1091 trace!(
1092 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
1093 Received a Time Exceeded message"
1094 );
1095
1096 receive_icmpv4_error(
1097 core_ctx,
1098 bindings_ctx,
1099 device,
1100 &time_exceeded,
1101 Icmpv4ErrorCode::TimeExceeded(time_exceeded.code()),
1102 );
1103 }
1104 Icmpv4Packet::Redirect(_) => {
1106 debug!(
1107 "Unimplemented: <IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1108 receive_ip_packet::redirect"
1109 )
1110 }
1111 Icmpv4Packet::ParameterProblem(parameter_problem) => {
1112 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx)
1113 .parameter_problem
1114 .increment();
1115 trace!(
1116 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
1117 Received a Parameter Problem message"
1118 );
1119
1120 receive_icmpv4_error(
1121 core_ctx,
1122 bindings_ctx,
1123 device,
1124 ¶meter_problem,
1125 Icmpv4ErrorCode::ParameterProblem(parameter_problem.code()),
1126 );
1127 }
1128 }
1129
1130 Ok(())
1131 }
1132}
1133
1134pub fn send_ndp_packet<BC, CC, S, M>(
1136 core_ctx: &mut CC,
1137 bindings_ctx: &mut BC,
1138 device_id: &CC::DeviceId,
1139 src_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1140 dst_ip: SpecifiedAddr<Ipv6Addr>,
1141 body: S,
1142 code: M::Code,
1143 message: M,
1144) -> Result<(), IpSendFrameError<S>>
1145where
1146 CC: IpLayerHandler<Ipv6, BC>,
1147 S: Serializer,
1148 S::Buffer: BufferMut,
1149 M: filter::IcmpMessage<Ipv6>,
1150{
1151 IpLayerHandler::<Ipv6, _>::send_ip_packet_from_device(
1153 core_ctx,
1154 bindings_ctx,
1155 SendIpPacketMeta {
1156 device: device_id,
1157 src_ip,
1158 dst_ip,
1159 destination: IpPacketDestination::from_addr(dst_ip),
1160 ttl: NonZeroU8::new(REQUIRED_NDP_IP_PACKET_HOP_LIMIT),
1161 proto: Ipv6Proto::Icmpv6,
1162 mtu: Mtu::no_limit(),
1163 dscp_and_ecn: DscpAndEcn::default(),
1164 },
1165 body.encapsulate(IcmpPacketBuilder::<Ipv6, _>::new(
1166 src_ip.map_or(Ipv6::UNSPECIFIED_ADDRESS, |a| a.get()),
1167 dst_ip.get(),
1168 code,
1169 message,
1170 )),
1171 )
1172 .map_err(|s| s.into_inner())
1173}
1174
1175fn send_neighbor_advertisement<
1176 BC,
1177 CC: Ipv6DeviceHandler<BC>
1178 + IpDeviceHandler<Ipv6, BC>
1179 + IpLayerHandler<Ipv6, BC>
1180 + CounterContext<NdpCounters>,
1181>(
1182 core_ctx: &mut CC,
1183 bindings_ctx: &mut BC,
1184 device_id: &CC::DeviceId,
1185 solicited: bool,
1186 device_addr: UnicastAddr<Ipv6Addr>,
1187 dst_ip: SpecifiedAddr<Ipv6Addr>,
1188) {
1189 core_ctx.counters().tx.neighbor_advertisement.increment();
1190 debug!("send_neighbor_advertisement from {:?} to {:?}", device_addr, dst_ip);
1191 debug_assert!(dst_ip.is_valid_unicast() || (!solicited && dst_ip.is_multicast()));
1198
1199 let src_ll = core_ctx.get_link_layer_addr(&device_id);
1206
1207 let advertisement = NeighborAdvertisement::new(
1209 core_ctx.is_router_device(&device_id),
1210 solicited,
1211 false,
1212 device_addr.get(),
1213 );
1214 let _: Result<(), _> = send_ndp_packet(
1215 core_ctx,
1216 bindings_ctx,
1217 &device_id,
1218 Some(device_addr.into_specified()),
1219 dst_ip,
1220 OptionSequenceBuilder::new(
1221 src_ll
1222 .as_ref()
1223 .map(Ipv6LinkLayerAddr::as_bytes)
1224 .map(NdpOptionBuilder::TargetLinkLayerAddress)
1225 .iter(),
1226 )
1227 .into_serializer(),
1228 IcmpZeroCode,
1229 advertisement,
1230 );
1231}
1232
1233fn receive_ndp_packet<
1234 B: SplitByteSlice,
1235 BC: IcmpBindingsContext + NdpBindingsContext<CC::DeviceId>,
1236 CC: InnerIcmpv6Context<BC>
1237 + Ipv6DeviceHandler<BC>
1238 + IpDeviceHandler<Ipv6, BC>
1239 + IpDeviceIngressStateContext<Ipv6>
1240 + NudIpHandler<Ipv6, BC>
1241 + IpLayerHandler<Ipv6, BC>
1242 + CounterContext<NdpCounters>,
1243 H: IpHeaderInfo<Ipv6>,
1244>(
1245 core_ctx: &mut CC,
1246 bindings_ctx: &mut BC,
1247 device_id: &CC::DeviceId,
1248 src_ip: Ipv6SourceAddr,
1249 packet: NdpPacket<B>,
1250 header_info: &H,
1251) {
1252 if header_info.hop_limit() != REQUIRED_NDP_IP_PACKET_HOP_LIMIT {
1270 trace!("dropping NDP packet from {src_ip} with invalid hop limit");
1271 return;
1272 }
1273
1274 match packet {
1275 NdpPacket::RouterSolicitation(_) | NdpPacket::Redirect(_) => {}
1276 NdpPacket::NeighborSolicitation(ref p) => {
1277 let target_address = p.message().target_address();
1278 let target_address = match UnicastAddr::new(*target_address) {
1279 Some(a) => a,
1280 None => {
1281 trace!(
1282 "dropping NS from {} with non-unicast target={:?}",
1283 src_ip,
1284 target_address
1285 );
1286 return;
1287 }
1288 };
1289
1290 core_ctx.counters().rx.neighbor_solicitation.increment();
1291
1292 match src_ip {
1293 Ipv6SourceAddr::Unspecified => {
1294 match Ipv6DeviceHandler::handle_received_dad_neighbor_solicitation(
1304 core_ctx,
1305 bindings_ctx,
1306 &device_id,
1307 target_address,
1308 p.body().iter().find_map(|option| option.nonce()),
1309 ) {
1310 IpAddressState::Assigned => {
1311 send_neighbor_advertisement(
1315 core_ctx,
1316 bindings_ctx,
1317 &device_id,
1318 false,
1319 target_address,
1320 Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.into_specified(),
1321 );
1322 }
1323 IpAddressState::Tentative => {
1324 }
1327 IpAddressState::Unavailable => {
1328 }
1331 }
1332
1333 return;
1334 }
1335 Ipv6SourceAddr::Unicast(src_ip) => {
1336 match core_ctx
1338 .address_status_for_device(target_address.into_specified(), device_id)
1339 {
1340 AddressStatus::Present(Ipv6PresentAddressStatus::UnicastAssigned) => {}
1341 AddressStatus::Present(
1342 Ipv6PresentAddressStatus::UnicastTentative
1343 | Ipv6PresentAddressStatus::Multicast,
1344 )
1345 | AddressStatus::Unassigned => {
1346 return;
1350 }
1351 }
1352
1353 let link_addr = p.body().iter().find_map(|o| o.source_link_layer_address());
1354
1355 if let Some(link_addr) = link_addr {
1356 NudIpHandler::handle_neighbor_probe(
1357 core_ctx,
1358 bindings_ctx,
1359 &device_id,
1360 src_ip.into_specified(),
1361 link_addr,
1362 );
1363 }
1364
1365 send_neighbor_advertisement(
1366 core_ctx,
1367 bindings_ctx,
1368 &device_id,
1369 true,
1370 target_address,
1371 src_ip.into_specified(),
1372 );
1373 }
1374 }
1375 }
1376 NdpPacket::NeighborAdvertisement(ref p) => {
1377 let target_address = p.message().target_address();
1381
1382 let src_ip = match src_ip {
1383 Ipv6SourceAddr::Unicast(src_ip) => src_ip,
1384 Ipv6SourceAddr::Unspecified => {
1385 trace!("dropping NA with unspecified source and target = {:?}", target_address);
1386 return;
1387 }
1388 };
1389
1390 let target_address = match UnicastAddr::new(*target_address) {
1391 Some(a) => a,
1392 None => {
1393 trace!(
1394 "dropping NA from {} with non-unicast target={:?}",
1395 src_ip,
1396 target_address
1397 );
1398 return;
1399 }
1400 };
1401
1402 core_ctx.counters().rx.neighbor_advertisement.increment();
1403
1404 match Ipv6DeviceHandler::handle_received_neighbor_advertisement(
1405 core_ctx,
1406 bindings_ctx,
1407 &device_id,
1408 target_address,
1409 ) {
1410 IpAddressState::Assigned => {
1411 error!(
1429 "NA from {src_ip} with target address {target_address} that is also \
1430 assigned on device {device_id:?}",
1431 );
1432 }
1433 IpAddressState::Tentative => {
1434 return;
1437 }
1438 IpAddressState::Unavailable => {
1439 }
1443 }
1444
1445 let link_addr = p.body().iter().find_map(|o| o.target_link_layer_address());
1446 let link_addr = match link_addr {
1447 Some(a) => a,
1448 None => {
1449 trace!(
1450 "dropping NA from {} targetting {} with no TLL option",
1451 src_ip,
1452 target_address
1453 );
1454 return;
1455 }
1456 };
1457
1458 NudIpHandler::handle_neighbor_confirmation(
1459 core_ctx,
1460 bindings_ctx,
1461 &device_id,
1462 target_address.into_specified(),
1463 link_addr,
1464 ConfirmationFlags {
1465 solicited_flag: p.message().solicited_flag(),
1466 override_flag: p.message().override_flag(),
1467 },
1468 );
1469 }
1470 NdpPacket::RouterAdvertisement(ref p) => {
1471 let src_ip = match src_ip {
1484 Ipv6SourceAddr::Unicast(ip) => match LinkLocalUnicastAddr::new(*ip) {
1485 Some(ip) => ip,
1486 None => return,
1487 },
1488 Ipv6SourceAddr::Unspecified => return,
1489 };
1490
1491 let ra = p.message();
1492 debug!("received router advertisement from {:?}: {:?}", src_ip, ra);
1493 core_ctx.counters().rx.router_advertisement.increment();
1494
1495 if let Some(retransmit_timer) = ra.retransmit_timer() {
1502 Ipv6DeviceHandler::set_discovered_retrans_timer(
1503 core_ctx,
1504 bindings_ctx,
1505 &device_id,
1506 retransmit_timer,
1507 );
1508 }
1509
1510 if let Some(hop_limit) = ra.current_hop_limit() {
1517 trace!("receive_ndp_packet: NDP RA: updating device's hop limit to {:?} for router: {:?}", ra.current_hop_limit(), src_ip);
1518 IpDeviceHandler::set_default_hop_limit(core_ctx, &device_id, hop_limit);
1519 }
1520
1521 Ipv6DeviceHandler::update_discovered_ipv6_route(
1523 core_ctx,
1524 bindings_ctx,
1525 &device_id,
1526 Ipv6DiscoveredRoute { subnet: IPV6_DEFAULT_SUBNET, gateway: Some(src_ip) },
1527 p.message().router_lifetime().map(NonZeroNdpLifetime::Finite),
1528 );
1529
1530 for option in p.body().iter() {
1531 match option {
1532 NdpOption::TargetLinkLayerAddress(_)
1533 | NdpOption::RedirectedHeader { .. }
1534 | NdpOption::RecursiveDnsServer(_)
1535 | NdpOption::Nonce(_) => {}
1536 NdpOption::SourceLinkLayerAddress(addr) => {
1537 debug!("processing SourceLinkLayerAddress option in RA: {:?}", addr);
1538 NudIpHandler::handle_neighbor_probe(
1564 core_ctx,
1565 bindings_ctx,
1566 &device_id,
1567 {
1568 let src_ip: UnicastAddr<_> = src_ip.into_addr();
1569 src_ip.into_specified()
1570 },
1571 addr,
1572 );
1573 }
1574 NdpOption::PrefixInformation(prefix_info) => {
1575 debug!("processing Prefix Information option in RA: {:?}", prefix_info);
1576 if prefix_info.prefix().is_link_local() {
1594 continue;
1595 }
1596
1597 let subnet = match prefix_info.subnet() {
1598 Ok(subnet) => subnet,
1599 Err(err) => match err {
1600 SubnetError::PrefixTooLong | SubnetError::HostBitsSet => continue,
1601 },
1602 };
1603
1604 match UnicastAddr::new(subnet.network()) {
1605 Some(UnicastAddr { .. }) => {}
1606 None => continue,
1607 }
1608
1609 let valid_lifetime = prefix_info.valid_lifetime();
1610
1611 if prefix_info.on_link_flag() {
1612 Ipv6DeviceHandler::update_discovered_ipv6_route(
1614 core_ctx,
1615 bindings_ctx,
1616 &device_id,
1617 Ipv6DiscoveredRoute { subnet, gateway: None },
1618 valid_lifetime,
1619 )
1620 }
1621
1622 if prefix_info.autonomous_address_configuration_flag() {
1623 Ipv6DeviceHandler::apply_slaac_update(
1624 core_ctx,
1625 bindings_ctx,
1626 &device_id,
1627 subnet,
1628 prefix_info.preferred_lifetime(),
1629 valid_lifetime,
1630 );
1631 }
1632 }
1633 NdpOption::RouteInformation(rio) => {
1634 debug!("processing Route Information option in RA: {:?}", rio);
1635 Ipv6DeviceHandler::update_discovered_ipv6_route(
1637 core_ctx,
1638 bindings_ctx,
1639 &device_id,
1640 Ipv6DiscoveredRoute {
1641 subnet: rio.prefix().clone(),
1642 gateway: Some(src_ip),
1643 },
1644 rio.route_lifetime(),
1645 )
1646 }
1647 NdpOption::Mtu(mtu) => {
1648 debug!("processing MTU option in RA: {:?}", mtu);
1649 Ipv6DeviceHandler::set_link_mtu(core_ctx, &device_id, Mtu::new(mtu));
1653 }
1654 }
1655 }
1656
1657 bindings_ctx.on_event(RouterAdvertisementEvent {
1658 options_bytes: Box::from(p.body().bytes()),
1659 source: **src_ip,
1660 device: device_id.clone(),
1661 });
1662 }
1663 }
1664}
1665
1666impl<
1667 BC: IcmpBindingsContext + NdpBindingsContext<CC::DeviceId>,
1668 CC: InnerIcmpv6Context<BC>
1669 + InnerIcmpContext<Ipv6, BC>
1670 + Ipv6DeviceHandler<BC>
1671 + IpDeviceHandler<Ipv6, BC>
1672 + IpDeviceIngressStateContext<Ipv6>
1673 + PmtuHandler<Ipv6, BC>
1674 + NudIpHandler<Ipv6, BC>
1675 + IpLayerHandler<Ipv6, BC>
1676 + CounterContext<IcmpRxCounters<Ipv6>>
1677 + CounterContext<IcmpTxCounters<Ipv6>>
1678 + CounterContext<NdpCounters>,
1679 > IpTransportContext<Ipv6, BC, CC> for IcmpIpTransportContext
1680{
1681 fn receive_icmp_error(
1682 core_ctx: &mut CC,
1683 bindings_ctx: &mut BC,
1684 device: &CC::DeviceId,
1685 original_src_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1686 original_dst_ip: SpecifiedAddr<Ipv6Addr>,
1687 original_body: &[u8],
1688 err: Icmpv6ErrorCode,
1689 ) {
1690 receive_ip_transport_icmp_error(
1691 core_ctx,
1692 bindings_ctx,
1693 device,
1694 original_src_ip,
1695 original_dst_ip,
1696 original_body,
1697 err,
1698 )
1699 }
1700
1701 fn receive_ip_packet<B: BufferMut, H: IpHeaderInfo<Ipv6>>(
1702 core_ctx: &mut CC,
1703 bindings_ctx: &mut BC,
1704 device: &CC::DeviceId,
1705 src_ip: Ipv6SourceAddr,
1706 dst_ip: SpecifiedAddr<Ipv6Addr>,
1707 mut buffer: B,
1708 info: &LocalDeliveryPacketInfo<Ipv6, H>,
1709 ) -> Result<(), (B, TransportReceiveError)> {
1710 let LocalDeliveryPacketInfo { meta, header_info, marks } = info;
1711 let ReceiveIpPacketMeta { broadcast: _, transparent_override } = meta;
1712 if let Some(delivery) = transparent_override {
1713 unreachable!(
1714 "cannot perform transparent local delivery {delivery:?} to an ICMP socket; \
1715 transparent proxy rules can only be configured for TCP and UDP packets"
1716 );
1717 }
1718
1719 trace!(
1720 "<IcmpIpTransportContext as IpTransportContext<Ipv6>>::receive_ip_packet({:?}, {})",
1721 src_ip,
1722 dst_ip
1723 );
1724
1725 let packet = match buffer
1726 .parse_with::<_, Icmpv6Packet<_>>(IcmpParseArgs::new(src_ip.get(), dst_ip))
1727 {
1728 Ok(packet) => packet,
1729 Err(_) => return Ok(()), };
1731
1732 match packet {
1733 Icmpv6Packet::EchoRequest(echo_request) => {
1734 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx).echo_request.increment();
1735
1736 if let Some(src_ip) = SocketIpAddr::new_from_ipv6_source(src_ip) {
1737 match SocketIpAddr::try_from(dst_ip) {
1738 Ok(dst_ip) => {
1739 let req = *echo_request.message();
1740 let code = echo_request.code();
1741 let (local_ip, remote_ip) = (dst_ip, src_ip);
1742 debug!(
1743 "replying to ICMP echo request from {remote_ip}: id={}, seq={}",
1744 req.id(),
1745 req.seq()
1746 );
1747 send_icmp_reply(
1748 core_ctx,
1749 bindings_ctx,
1750 device,
1751 remote_ip,
1752 local_ip,
1753 |src_ip| {
1754 buffer.encapsulate(IcmpPacketBuilder::<Ipv6, _>::new(
1755 src_ip,
1756 remote_ip.addr(),
1757 code,
1758 req.reply(),
1759 ))
1760 },
1761 &WithMarks(marks),
1762 );
1763 }
1764 Err(AddrIsMappedError {}) => {
1765 trace!("IpTransportContext<Ipv6>::receive_ip_packet: Received echo request with an ipv4-mapped-ipv6 destination address");
1766 }
1767 }
1768 } else {
1769 trace!("<IcmpIpTransportContext as IpTransportContext<Ipv6>>::receive_ip_packet: Received echo request with an unspecified source address");
1770 }
1771 }
1772 Icmpv6Packet::EchoReply(echo_reply) => {
1773 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx).echo_reply.increment();
1774 trace!("<IcmpIpTransportContext as IpTransportContext<Ipv6>>::receive_ip_packet: Received an EchoReply message");
1775 let parse_metadata = echo_reply.parse_metadata();
1776 buffer.undo_parse(parse_metadata);
1777 return <CC::EchoTransportContext
1778 as IpTransportContext<Ipv6, BC, CC>>::receive_ip_packet(
1779 core_ctx,
1780 bindings_ctx,
1781 device,
1782 src_ip,
1783 dst_ip,
1784 buffer,
1785 info
1786 );
1787 }
1788 Icmpv6Packet::Ndp(packet) => {
1789 receive_ndp_packet(core_ctx, bindings_ctx, device, src_ip, packet, header_info)
1790 }
1791 Icmpv6Packet::PacketTooBig(packet_too_big) => {
1792 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx)
1793 .packet_too_big
1794 .increment();
1795 trace!("<IcmpIpTransportContext as IpTransportContext<Ipv6>>::receive_ip_packet: Received a Packet Too Big message");
1796 let new_mtu = if let Ipv6SourceAddr::Unicast(src_ip) = src_ip {
1797 core_ctx.update_pmtu_if_less(
1807 bindings_ctx,
1808 dst_ip.get(),
1809 src_ip.get(),
1810 Mtu::new(packet_too_big.message().mtu()),
1811 )
1812 } else {
1813 None
1814 };
1815 if let Some(mtu) = new_mtu {
1816 receive_icmpv6_error(
1817 core_ctx,
1818 bindings_ctx,
1819 device,
1820 &packet_too_big,
1821 Icmpv6ErrorCode::PacketTooBig(mtu),
1822 );
1823 }
1824 }
1825 Icmpv6Packet::Mld(packet) => {
1826 core_ctx.receive_mld_packet(
1827 bindings_ctx,
1828 &device,
1829 src_ip,
1830 dst_ip,
1831 packet,
1832 header_info,
1833 );
1834 }
1835 Icmpv6Packet::DestUnreachable(dest_unreachable) => receive_icmpv6_error(
1836 core_ctx,
1837 bindings_ctx,
1838 device,
1839 &dest_unreachable,
1840 Icmpv6ErrorCode::DestUnreachable(dest_unreachable.code()),
1841 ),
1842 Icmpv6Packet::TimeExceeded(time_exceeded) => receive_icmpv6_error(
1843 core_ctx,
1844 bindings_ctx,
1845 device,
1846 &time_exceeded,
1847 Icmpv6ErrorCode::TimeExceeded(time_exceeded.code()),
1848 ),
1849 Icmpv6Packet::ParameterProblem(parameter_problem) => receive_icmpv6_error(
1850 core_ctx,
1851 bindings_ctx,
1852 device,
1853 ¶meter_problem,
1854 Icmpv6ErrorCode::ParameterProblem(parameter_problem.code()),
1855 ),
1856 }
1857
1858 Ok(())
1859 }
1860}
1861
1862#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1863struct WithMarks<'a>(&'a Marks);
1864
1865impl<'a> OptionDelegationMarker for WithMarks<'a> {}
1866
1867impl<'a, I: IpExt> DelegatedRouteResolutionOptions<I> for WithMarks<'a> {
1868 fn marks(&self) -> &Marks {
1869 let Self(marks) = self;
1870 marks
1871 }
1872}
1873
1874impl<'a, I: IpExt> DelegatedSendOptions<I> for WithMarks<'a> {}
1875
1876fn send_icmp_reply<I, BC, CC, S, F, O>(
1887 core_ctx: &mut CC,
1888 bindings_ctx: &mut BC,
1889 device: &CC::DeviceId,
1890 original_src_ip: SocketIpAddr<I::Addr>,
1891 original_dst_ip: SocketIpAddr<I::Addr>,
1892 get_body_from_src_ip: F,
1893 ip_options: &O,
1894) where
1895 I: IpExt,
1896 CC: IpSocketHandler<I, BC> + DeviceIdContext<AnyDevice> + CounterContext<IcmpTxCounters<I>>,
1897 BC: TxMetadataBindingsTypes,
1898 S: TransportPacketSerializer<I>,
1899 S::Buffer: BufferMut,
1900 F: FnOnce(SpecifiedAddr<I::Addr>) -> S,
1901 O: SendOptions<I> + RouteResolutionOptions<I>,
1902{
1903 trace!("send_icmp_reply({:?}, {}, {})", device, original_src_ip, original_dst_ip);
1904 core_ctx.counters().reply.increment();
1905 let tx_metadata: BC::TxMetadata = Default::default();
1906
1907 let egress_device = (original_dst_ip.as_ref().is_multicast()
1911 || original_dst_ip.as_ref().must_have_zone())
1912 .then_some(EitherDeviceId::Strong(device));
1913
1914 core_ctx
1915 .send_oneshot_ip_packet(
1916 bindings_ctx,
1917 egress_device,
1918 IpDeviceAddr::new_from_socket_ip_addr(original_dst_ip),
1919 original_src_ip,
1920 I::ICMP_IP_PROTO,
1921 ip_options,
1922 tx_metadata,
1923 |src_ip| get_body_from_src_ip(src_ip.into()),
1924 )
1925 .unwrap_or_else(|err| {
1926 debug!("failed to send ICMP reply: {}", err);
1927 })
1928}
1929
1930fn receive_icmpv4_error<
1935 BC: IcmpBindingsContext,
1936 CC: InnerIcmpv4Context<BC>,
1937 B: SplitByteSlice,
1938 M: IcmpMessage<Ipv4, Body<B> = OriginalPacket<B>>,
1939>(
1940 core_ctx: &mut CC,
1941 bindings_ctx: &mut BC,
1942 device: &CC::DeviceId,
1943 packet: &IcmpPacket<Ipv4, B, M>,
1944 err: Icmpv4ErrorCode,
1945) {
1946 packet.with_original_packet(|res| match res {
1947 Ok(original_packet) => {
1948 let dst_ip = match SpecifiedAddr::new(original_packet.dst_ip()) {
1949 Some(ip) => ip,
1950 None => {
1951 trace!("receive_icmpv4_error: Got ICMP error message whose original IPv4 packet contains an unspecified destination address; discarding");
1952 return;
1953 },
1954 };
1955 InnerIcmpContext::receive_icmp_error(
1956 core_ctx,
1957 bindings_ctx,
1958 device,
1959 SpecifiedAddr::new(original_packet.src_ip()),
1960 dst_ip,
1961 original_packet.proto(),
1962 original_packet.body().into_inner(),
1963 err,
1964 );
1965 }
1966 Err(_) => debug!(
1967 "receive_icmpv4_error: Got ICMP error message with unparsable original IPv4 packet"
1968 ),
1969 })
1970}
1971
1972fn receive_icmpv6_error<
1977 BC: IcmpBindingsContext,
1978 CC: InnerIcmpv6Context<BC>,
1979 B: SplitByteSlice,
1980 M: IcmpMessage<Ipv6, Body<B> = OriginalPacket<B>>,
1981>(
1982 core_ctx: &mut CC,
1983 bindings_ctx: &mut BC,
1984 device: &CC::DeviceId,
1985 packet: &IcmpPacket<Ipv6, B, M>,
1986 err: Icmpv6ErrorCode,
1987) {
1988 packet.with_original_packet(|res| match res {
1989 Ok(original_packet) => {
1990 let dst_ip = match SpecifiedAddr::new(original_packet.dst_ip()) {
1991 Some(ip)=>ip,
1992 None => {
1993 trace!("receive_icmpv6_error: Got ICMP error message whose original IPv6 packet contains an unspecified destination address; discarding");
1994 return;
1995 },
1996 };
1997 match original_packet.body_proto() {
1998 Ok((body, proto)) => {
1999 InnerIcmpContext::receive_icmp_error(
2000 core_ctx,
2001 bindings_ctx,
2002 device,
2003 SpecifiedAddr::new(original_packet.src_ip()),
2004 dst_ip,
2005 proto,
2006 body.into_inner(),
2007 err,
2008 );
2009 }
2010 Err(ExtHdrParseError) => {
2011 trace!("receive_icmpv6_error: We could not parse the original packet's extension headers, and so we don't know where the original packet's body begins; discarding");
2012 return;
2015 }
2016 }
2017 }
2018 Err(_body) => debug!(
2019 "receive_icmpv6_error: Got ICMPv6 error message with unparsable original IPv6 packet"
2020 ),
2021 })
2022}
2023
2024pub fn send_icmpv4_host_unreachable<
2042 B: BufferMut,
2043 BC: IcmpBindingsContext,
2044 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2045>(
2046 core_ctx: &mut CC,
2047 bindings_ctx: &mut BC,
2048 device: Option<&CC::DeviceId>,
2049 frame_dst: Option<FrameDestination>,
2050 src_ip: SocketIpAddr<Ipv4Addr>,
2051 dst_ip: SocketIpAddr<Ipv4Addr>,
2052 original_packet: B,
2053 header_len: usize,
2054 fragment_type: Ipv4FragmentType,
2055 marks: &Marks,
2056) {
2057 core_ctx.counters().address_unreachable.increment();
2058
2059 send_icmpv4_dest_unreachable(
2060 core_ctx,
2061 bindings_ctx,
2062 device,
2063 frame_dst,
2064 src_ip,
2065 dst_ip,
2066 Icmpv4DestUnreachableCode::DestHostUnreachable,
2067 original_packet,
2068 header_len,
2069 fragment_type,
2070 marks,
2071 );
2072}
2073
2074pub fn send_icmpv6_address_unreachable<
2085 B: BufferMut,
2086 BC: IcmpBindingsContext,
2087 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2088>(
2089 core_ctx: &mut CC,
2090 bindings_ctx: &mut BC,
2091 device: Option<&CC::DeviceId>,
2092 frame_dst: Option<FrameDestination>,
2093 src_ip: SocketIpAddr<Ipv6Addr>,
2094 dst_ip: SocketIpAddr<Ipv6Addr>,
2095 original_packet: B,
2096 marks: &Marks,
2097) {
2098 core_ctx.counters().address_unreachable.increment();
2099
2100 send_icmpv6_dest_unreachable(
2101 core_ctx,
2102 bindings_ctx,
2103 device,
2104 frame_dst,
2105 src_ip,
2106 dst_ip,
2107 Icmpv6DestUnreachableCode::AddrUnreachable,
2108 original_packet,
2109 marks,
2110 );
2111}
2112
2113pub(crate) fn send_icmpv4_protocol_unreachable<
2125 B: BufferMut,
2126 BC: IcmpBindingsContext,
2127 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2128>(
2129 core_ctx: &mut CC,
2130 bindings_ctx: &mut BC,
2131 device: &CC::DeviceId,
2132 frame_dst: Option<FrameDestination>,
2133 src_ip: SocketIpAddr<Ipv4Addr>,
2134 dst_ip: SocketIpAddr<Ipv4Addr>,
2135 original_packet: B,
2136 header_len: usize,
2137 marks: &Marks,
2138) {
2139 core_ctx.counters().protocol_unreachable.increment();
2140
2141 send_icmpv4_dest_unreachable(
2142 core_ctx,
2143 bindings_ctx,
2144 Some(device),
2145 frame_dst,
2146 src_ip,
2147 dst_ip,
2148 Icmpv4DestUnreachableCode::DestProtocolUnreachable,
2149 original_packet,
2150 header_len,
2151 Ipv4FragmentType::InitialFragment,
2157 marks,
2158 );
2159}
2160
2161pub(crate) fn send_icmpv6_protocol_unreachable<
2171 B: BufferMut,
2172 BC: IcmpBindingsContext,
2173 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2174>(
2175 core_ctx: &mut CC,
2176 bindings_ctx: &mut BC,
2177 device: &CC::DeviceId,
2178 frame_dst: Option<FrameDestination>,
2179 src_ip: SocketIpAddr<Ipv6Addr>,
2180 dst_ip: SocketIpAddr<Ipv6Addr>,
2181 original_packet: B,
2182 header_len: usize,
2183 marks: &Marks,
2184) {
2185 core_ctx.counters().protocol_unreachable.increment();
2186
2187 send_icmpv6_parameter_problem(
2188 core_ctx,
2189 bindings_ctx,
2190 device,
2191 frame_dst,
2192 src_ip,
2193 dst_ip,
2194 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
2195 Icmpv6ParameterProblem::new(header_len as u32),
2209 original_packet,
2210 false,
2211 marks,
2212 );
2213}
2214
2215pub(crate) fn send_icmpv4_port_unreachable<
2227 B: BufferMut,
2228 BC: IcmpBindingsContext,
2229 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2230>(
2231 core_ctx: &mut CC,
2232 bindings_ctx: &mut BC,
2233 device: &CC::DeviceId,
2234 frame_dst: Option<FrameDestination>,
2235 src_ip: SocketIpAddr<Ipv4Addr>,
2236 dst_ip: SocketIpAddr<Ipv4Addr>,
2237 original_packet: B,
2238 header_len: usize,
2239 marks: &Marks,
2240) {
2241 core_ctx.counters().port_unreachable.increment();
2242
2243 send_icmpv4_dest_unreachable(
2244 core_ctx,
2245 bindings_ctx,
2246 Some(device),
2247 frame_dst,
2248 src_ip,
2249 dst_ip,
2250 Icmpv4DestUnreachableCode::DestPortUnreachable,
2251 original_packet,
2252 header_len,
2253 Ipv4FragmentType::InitialFragment,
2259 marks,
2260 );
2261}
2262
2263pub(crate) fn send_icmpv6_port_unreachable<
2272 B: BufferMut,
2273 BC: IcmpBindingsContext,
2274 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2275>(
2276 core_ctx: &mut CC,
2277 bindings_ctx: &mut BC,
2278 device: &CC::DeviceId,
2279 frame_dst: Option<FrameDestination>,
2280 src_ip: SocketIpAddr<Ipv6Addr>,
2281 dst_ip: SocketIpAddr<Ipv6Addr>,
2282 original_packet: B,
2283 marks: &Marks,
2284) {
2285 core_ctx.counters().port_unreachable.increment();
2286
2287 send_icmpv6_dest_unreachable(
2288 core_ctx,
2289 bindings_ctx,
2290 Some(device),
2291 frame_dst,
2292 src_ip,
2293 dst_ip,
2294 Icmpv6DestUnreachableCode::PortUnreachable,
2295 original_packet,
2296 marks,
2297 );
2298}
2299
2300pub(crate) fn send_icmpv4_net_unreachable<
2312 B: BufferMut,
2313 BC: IcmpBindingsContext,
2314 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2315>(
2316 core_ctx: &mut CC,
2317 bindings_ctx: &mut BC,
2318 device: &CC::DeviceId,
2319 frame_dst: Option<FrameDestination>,
2320 src_ip: SocketIpAddr<Ipv4Addr>,
2321 dst_ip: SocketIpAddr<Ipv4Addr>,
2322 proto: Ipv4Proto,
2323 original_packet: B,
2324 header_len: usize,
2325 fragment_type: Ipv4FragmentType,
2326 marks: &Marks,
2327) {
2328 core_ctx.counters().net_unreachable.increment();
2329
2330 if is_icmp_error_message::<Ipv4>(proto, &original_packet.as_ref()[header_len..]) {
2333 return;
2334 }
2335
2336 send_icmpv4_dest_unreachable(
2337 core_ctx,
2338 bindings_ctx,
2339 Some(device),
2340 frame_dst,
2341 src_ip,
2342 dst_ip,
2343 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
2344 original_packet,
2345 header_len,
2346 fragment_type,
2347 marks,
2348 );
2349}
2350
2351pub(crate) fn send_icmpv6_net_unreachable<
2362 B: BufferMut,
2363 BC: IcmpBindingsContext,
2364 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2365>(
2366 core_ctx: &mut CC,
2367 bindings_ctx: &mut BC,
2368 device: &CC::DeviceId,
2369 frame_dst: Option<FrameDestination>,
2370 src_ip: SocketIpAddr<Ipv6Addr>,
2371 dst_ip: SocketIpAddr<Ipv6Addr>,
2372 proto: Ipv6Proto,
2373 original_packet: B,
2374 header_len: usize,
2375 marks: &Marks,
2376) {
2377 core_ctx.counters().net_unreachable.increment();
2378
2379 if is_icmp_error_message::<Ipv6>(proto, &original_packet.as_ref()[header_len..]) {
2382 return;
2383 }
2384
2385 send_icmpv6_dest_unreachable(
2386 core_ctx,
2387 bindings_ctx,
2388 Some(device),
2389 frame_dst,
2390 src_ip,
2391 dst_ip,
2392 Icmpv6DestUnreachableCode::NoRoute,
2393 original_packet,
2394 marks,
2395 );
2396}
2397
2398pub(crate) fn send_icmpv4_ttl_expired<
2410 B: BufferMut,
2411 BC: IcmpBindingsContext,
2412 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2413>(
2414 core_ctx: &mut CC,
2415 bindings_ctx: &mut BC,
2416 device: &CC::DeviceId,
2417 frame_dst: Option<FrameDestination>,
2418 src_ip: SocketIpAddr<Ipv4Addr>,
2419 dst_ip: SocketIpAddr<Ipv4Addr>,
2420 proto: Ipv4Proto,
2421 original_packet: B,
2422 header_len: usize,
2423 fragment_type: Ipv4FragmentType,
2424 marks: &Marks,
2425) {
2426 core_ctx.counters().ttl_expired.increment();
2427
2428 if is_icmp_error_message::<Ipv4>(proto, &original_packet.as_ref()[header_len..]) {
2431 return;
2432 }
2433
2434 send_icmpv4_error_message(
2435 core_ctx,
2436 bindings_ctx,
2437 Some(device),
2438 frame_dst,
2439 src_ip,
2440 dst_ip,
2441 Icmpv4TimeExceededCode::TtlExpired,
2442 IcmpTimeExceeded::default(),
2443 original_packet,
2444 header_len,
2445 fragment_type,
2446 marks,
2447 )
2448}
2449
2450pub(crate) fn send_icmpv6_ttl_expired<
2461 B: BufferMut,
2462 BC: IcmpBindingsContext,
2463 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2464>(
2465 core_ctx: &mut CC,
2466 bindings_ctx: &mut BC,
2467 device: &CC::DeviceId,
2468 frame_dst: Option<FrameDestination>,
2469 src_ip: SocketIpAddr<Ipv6Addr>,
2470 dst_ip: SocketIpAddr<Ipv6Addr>,
2471 proto: Ipv6Proto,
2472 original_packet: B,
2473 header_len: usize,
2474 marks: &Marks,
2475) {
2476 core_ctx.counters().ttl_expired.increment();
2477
2478 if is_icmp_error_message::<Ipv6>(proto, &original_packet.as_ref()[header_len..]) {
2481 return;
2482 }
2483
2484 send_icmpv6_error_message(
2485 core_ctx,
2486 bindings_ctx,
2487 Some(device),
2488 frame_dst,
2489 src_ip,
2490 dst_ip,
2491 Icmpv6TimeExceededCode::HopLimitExceeded,
2492 IcmpTimeExceeded::default(),
2493 original_packet,
2494 false, marks,
2496 )
2497}
2498
2499pub(crate) fn send_icmpv6_packet_too_big<
2509 B: BufferMut,
2510 BC: IcmpBindingsContext,
2511 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2512>(
2513 core_ctx: &mut CC,
2514 bindings_ctx: &mut BC,
2515 device: &CC::DeviceId,
2516 frame_dst: Option<FrameDestination>,
2517 src_ip: SocketIpAddr<Ipv6Addr>,
2518 dst_ip: SocketIpAddr<Ipv6Addr>,
2519 proto: Ipv6Proto,
2520 mtu: Mtu,
2521 original_packet: B,
2522 header_len: usize,
2523 marks: &Marks,
2524) {
2525 core_ctx.counters().packet_too_big.increment();
2526 if is_icmp_error_message::<Ipv6>(proto, &original_packet.as_ref()[header_len..]) {
2529 return;
2530 }
2531
2532 send_icmpv6_error_message(
2533 core_ctx,
2534 bindings_ctx,
2535 Some(device),
2536 frame_dst,
2537 src_ip,
2538 dst_ip,
2539 IcmpZeroCode,
2540 Icmpv6PacketTooBig::new(mtu.into()),
2541 original_packet,
2542 true, marks,
2562 )
2563}
2564
2565pub(crate) fn send_icmpv4_parameter_problem<
2566 B: BufferMut,
2567 BC: IcmpBindingsContext,
2568 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2569>(
2570 core_ctx: &mut CC,
2571 bindings_ctx: &mut BC,
2572 device: &CC::DeviceId,
2573 frame_dst: Option<FrameDestination>,
2574 src_ip: SocketIpAddr<Ipv4Addr>,
2575 dst_ip: SocketIpAddr<Ipv4Addr>,
2576 code: Icmpv4ParameterProblemCode,
2577 parameter_problem: Icmpv4ParameterProblem,
2578 original_packet: B,
2579 header_len: usize,
2580 fragment_type: Ipv4FragmentType,
2581 marks: &Marks,
2582) {
2583 core_ctx.counters().parameter_problem.increment();
2584
2585 send_icmpv4_error_message(
2586 core_ctx,
2587 bindings_ctx,
2588 Some(device),
2589 frame_dst,
2590 src_ip,
2591 dst_ip,
2592 code,
2593 parameter_problem,
2594 original_packet,
2595 header_len,
2596 fragment_type,
2597 marks,
2598 )
2599}
2600
2601pub(crate) fn send_icmpv6_parameter_problem<
2612 B: BufferMut,
2613 BC: IcmpBindingsContext,
2614 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2615>(
2616 core_ctx: &mut CC,
2617 bindings_ctx: &mut BC,
2618 device: &CC::DeviceId,
2619 frame_dst: Option<FrameDestination>,
2620 src_ip: SocketIpAddr<Ipv6Addr>,
2621 dst_ip: SocketIpAddr<Ipv6Addr>,
2622 code: Icmpv6ParameterProblemCode,
2623 parameter_problem: Icmpv6ParameterProblem,
2624 original_packet: B,
2625 allow_dst_multicast: bool,
2626 marks: &Marks,
2627) {
2628 assert!(!allow_dst_multicast || code == Icmpv6ParameterProblemCode::UnrecognizedIpv6Option);
2633
2634 core_ctx.counters().parameter_problem.increment();
2635
2636 send_icmpv6_error_message(
2637 core_ctx,
2638 bindings_ctx,
2639 Some(device),
2640 frame_dst,
2641 src_ip,
2642 dst_ip,
2643 code,
2644 parameter_problem,
2645 original_packet,
2646 allow_dst_multicast,
2647 marks,
2648 )
2649}
2650
2651fn send_icmpv4_dest_unreachable<
2652 B: BufferMut,
2653 BC: IcmpBindingsContext,
2654 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2655>(
2656 core_ctx: &mut CC,
2657 bindings_ctx: &mut BC,
2658 device: Option<&CC::DeviceId>,
2659 frame_dst: Option<FrameDestination>,
2660 src_ip: SocketIpAddr<Ipv4Addr>,
2661 dst_ip: SocketIpAddr<Ipv4Addr>,
2662 code: Icmpv4DestUnreachableCode,
2663 original_packet: B,
2664 header_len: usize,
2665 fragment_type: Ipv4FragmentType,
2666 marks: &Marks,
2667) {
2668 core_ctx.counters().dest_unreachable.increment();
2669 send_icmpv4_error_message(
2670 core_ctx,
2671 bindings_ctx,
2672 device,
2673 frame_dst,
2674 src_ip,
2675 dst_ip,
2676 code,
2677 IcmpDestUnreachable::default(),
2678 original_packet,
2679 header_len,
2680 fragment_type,
2681 marks,
2682 )
2683}
2684
2685fn send_icmpv6_dest_unreachable<
2686 B: BufferMut,
2687 BC: IcmpBindingsContext,
2688 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2689>(
2690 core_ctx: &mut CC,
2691 bindings_ctx: &mut BC,
2692 device: Option<&CC::DeviceId>,
2693 frame_dst: Option<FrameDestination>,
2694 src_ip: SocketIpAddr<Ipv6Addr>,
2695 dst_ip: SocketIpAddr<Ipv6Addr>,
2696 code: Icmpv6DestUnreachableCode,
2697 original_packet: B,
2698 marks: &Marks,
2699) {
2700 send_icmpv6_error_message(
2701 core_ctx,
2702 bindings_ctx,
2703 device,
2704 frame_dst,
2705 src_ip,
2706 dst_ip,
2707 code,
2708 IcmpDestUnreachable::default(),
2709 original_packet,
2710 false, marks,
2712 )
2713}
2714
2715fn send_icmpv4_error_message<
2716 B: BufferMut,
2717 M: filter::IcmpMessage<Ipv4>,
2718 BC: IcmpBindingsContext,
2719 CC: InnerIcmpv4Context<BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2720>(
2721 core_ctx: &mut CC,
2722 bindings_ctx: &mut BC,
2723 device: Option<&CC::DeviceId>,
2724 frame_dst: Option<FrameDestination>,
2725 original_src_ip: SocketIpAddr<Ipv4Addr>,
2726 original_dst_ip: SocketIpAddr<Ipv4Addr>,
2727 code: M::Code,
2728 message: M,
2729 mut original_packet: B,
2730 header_len: usize,
2731 fragment_type: Ipv4FragmentType,
2732 marks: &Marks,
2733) {
2734 if !should_send_icmpv4_error(
2738 frame_dst,
2739 original_src_ip.into(),
2740 original_dst_ip.into(),
2741 fragment_type,
2742 ) {
2743 return;
2744 }
2745
2746 original_packet.shrink_back_to(header_len + 64);
2749
2750 let tx_metadata: BC::TxMetadata = Default::default();
2751 let _ = try_send_error!(
2754 core_ctx,
2755 bindings_ctx,
2756 core_ctx.send_oneshot_ip_packet(
2757 bindings_ctx,
2758 device.map(EitherDeviceId::Strong),
2759 None,
2760 original_src_ip,
2761 Ipv4Proto::Icmp,
2762 &WithMarks(marks),
2763 tx_metadata,
2764 |local_ip| {
2765 original_packet.encapsulate(IcmpPacketBuilder::<Ipv4, _>::new(
2766 local_ip.addr(),
2767 original_src_ip.addr(),
2768 code,
2769 message,
2770 ))
2771 },
2772 )
2773 );
2774}
2775
2776fn send_icmpv6_error_message<
2777 B: BufferMut,
2778 M: filter::IcmpMessage<Ipv6>,
2779 BC: IcmpBindingsContext,
2780 CC: InnerIcmpv6Context<BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2781>(
2782 core_ctx: &mut CC,
2783 bindings_ctx: &mut BC,
2784 device: Option<&CC::DeviceId>,
2785 frame_dst: Option<FrameDestination>,
2786 original_src_ip: SocketIpAddr<Ipv6Addr>,
2787 original_dst_ip: SocketIpAddr<Ipv6Addr>,
2788 code: M::Code,
2789 message: M,
2790 original_packet: B,
2791 allow_dst_multicast: bool,
2792 marks: &Marks,
2793) {
2794 if !should_send_icmpv6_error(
2798 frame_dst,
2799 original_src_ip.into(),
2800 original_dst_ip.into(),
2801 allow_dst_multicast,
2802 ) {
2803 return;
2804 }
2805
2806 struct Icmpv6ErrorOptions<'a>(&'a Marks);
2807 impl<'a> OptionDelegationMarker for Icmpv6ErrorOptions<'a> {}
2808 impl<'a> DelegatedSendOptions<Ipv6> for Icmpv6ErrorOptions<'a> {
2809 fn mtu(&self) -> Mtu {
2810 Ipv6::MINIMUM_LINK_MTU
2811 }
2812 }
2813 impl<'a> DelegatedRouteResolutionOptions<Ipv6> for Icmpv6ErrorOptions<'a> {
2814 fn marks(&self) -> &Marks {
2815 let Self(marks) = self;
2816 marks
2817 }
2818 }
2819
2820 let tx_metadata: BC::TxMetadata = Default::default();
2821 let _ = try_send_error!(
2824 core_ctx,
2825 bindings_ctx,
2826 core_ctx.send_oneshot_ip_packet(
2827 bindings_ctx,
2828 device.map(EitherDeviceId::Strong),
2829 None,
2830 original_src_ip,
2831 Ipv6Proto::Icmpv6,
2832 &Icmpv6ErrorOptions(marks),
2833 tx_metadata,
2834 |local_ip| {
2835 let icmp_builder = IcmpPacketBuilder::<Ipv6, _>::new(
2836 local_ip.addr(),
2837 original_src_ip.addr(),
2838 code,
2839 message,
2840 );
2841
2842 TruncatingSerializer::new(original_packet, TruncateDirection::DiscardBack)
2845 .encapsulate(icmp_builder)
2846 },
2847 )
2848 );
2849}
2850
2851fn should_send_icmpv4_error(
2869 frame_dst: Option<FrameDestination>,
2870 src_ip: SpecifiedAddr<Ipv4Addr>,
2871 dst_ip: SpecifiedAddr<Ipv4Addr>,
2872 fragment_type: Ipv4FragmentType,
2873) -> bool {
2874 fragment_type == Ipv4FragmentType::InitialFragment
2894 && !(dst_ip.is_multicast()
2895 || dst_ip.is_limited_broadcast()
2896 || frame_dst.is_some_and(|dst| dst.is_broadcast())
2897 || src_ip.is_loopback()
2898 || src_ip.is_limited_broadcast()
2899 || src_ip.is_multicast()
2900 || src_ip.is_class_e())
2901}
2902
2903fn should_send_icmpv6_error(
2930 frame_dst: Option<FrameDestination>,
2931 src_ip: SpecifiedAddr<Ipv6Addr>,
2932 dst_ip: SpecifiedAddr<Ipv6Addr>,
2933 allow_dst_multicast: bool,
2934) -> bool {
2935 let multicast_frame_dst = match frame_dst {
2938 Some(FrameDestination::Individual { local: _ }) | None => false,
2939 Some(FrameDestination::Broadcast) | Some(FrameDestination::Multicast) => true,
2940 };
2941 if (dst_ip.is_multicast() || multicast_frame_dst) && !allow_dst_multicast {
2942 return false;
2943 }
2944 if src_ip.is_loopback() || src_ip.is_multicast() {
2945 return false;
2946 }
2947 true
2948}
2949
2950fn is_icmp_error_message<I: IcmpIpExt>(proto: I::Proto, buf: &[u8]) -> bool {
2962 proto == I::ICMP_IP_PROTO
2963 && peek_message_type::<I::IcmpMessageType>(buf).map(IcmpMessageType::is_err).unwrap_or(true)
2964}
2965
2966#[cfg(any(test, feature = "testutils"))]
2968pub(crate) mod testutil {
2969 use alloc::vec::Vec;
2970 use net_types::ethernet::Mac;
2971 use net_types::ip::{Ipv6, Ipv6Addr};
2972 use packet::{Buf, InnerPacketBuilder as _, Serializer as _};
2973 use packet_formats::icmp::ndp::options::NdpOptionBuilder;
2974 use packet_formats::icmp::ndp::{
2975 NeighborAdvertisement, NeighborSolicitation, OptionSequenceBuilder,
2976 };
2977 use packet_formats::icmp::{IcmpPacketBuilder, IcmpZeroCode};
2978 use packet_formats::ip::Ipv6Proto;
2979 use packet_formats::ipv6::Ipv6PacketBuilder;
2980
2981 use super::REQUIRED_NDP_IP_PACKET_HOP_LIMIT;
2982
2983 pub fn neighbor_advertisement_ip_packet(
2986 src_ip: Ipv6Addr,
2987 dst_ip: Ipv6Addr,
2988 router_flag: bool,
2989 solicited_flag: bool,
2990 override_flag: bool,
2991 mac: Mac,
2992 ) -> Buf<Vec<u8>> {
2993 OptionSequenceBuilder::new([NdpOptionBuilder::TargetLinkLayerAddress(&mac.bytes())].iter())
2994 .into_serializer()
2995 .encapsulate(IcmpPacketBuilder::<Ipv6, _>::new(
2996 src_ip,
2997 dst_ip,
2998 IcmpZeroCode,
2999 NeighborAdvertisement::new(router_flag, solicited_flag, override_flag, src_ip),
3000 ))
3001 .encapsulate(Ipv6PacketBuilder::new(
3002 src_ip,
3003 dst_ip,
3004 REQUIRED_NDP_IP_PACKET_HOP_LIMIT,
3005 Ipv6Proto::Icmpv6,
3006 ))
3007 .serialize_vec_outer()
3008 .unwrap()
3009 .unwrap_b()
3010 }
3011
3012 pub fn neighbor_solicitation_ip_packet(
3015 src_ip: Ipv6Addr,
3016 dst_ip: Ipv6Addr,
3017 target_addr: Ipv6Addr,
3018 mac: Mac,
3019 ) -> Buf<Vec<u8>> {
3020 OptionSequenceBuilder::new([NdpOptionBuilder::SourceLinkLayerAddress(&mac.bytes())].iter())
3021 .into_serializer()
3022 .encapsulate(IcmpPacketBuilder::<Ipv6, _>::new(
3023 src_ip,
3024 dst_ip,
3025 IcmpZeroCode,
3026 NeighborSolicitation::new(target_addr),
3027 ))
3028 .encapsulate(Ipv6PacketBuilder::new(
3029 src_ip,
3030 dst_ip,
3031 REQUIRED_NDP_IP_PACKET_HOP_LIMIT,
3032 Ipv6Proto::Icmpv6,
3033 ))
3034 .serialize_vec_outer()
3035 .unwrap()
3036 .unwrap_b()
3037 }
3038}
3039
3040#[cfg(test)]
3041mod tests {
3042 use alloc::vec;
3043 use alloc::vec::Vec;
3044 use packet_formats::icmp::ndp::options::NdpNonce;
3045
3046 use core::fmt::Debug;
3047 use core::time::Duration;
3048
3049 use net_types::ip::Subnet;
3050 use netstack3_base::testutil::{
3051 set_logger_for_test, FakeBindingsCtx, FakeCoreCtx, FakeDeviceId, FakeInstant,
3052 FakeTxMetadata, FakeWeakDeviceId, TestIpExt, TEST_ADDRS_V4, TEST_ADDRS_V6,
3053 };
3054 use netstack3_base::{CtxPair, Uninstantiable};
3055 use packet::Buf;
3056 use packet_formats::icmp::mld::MldPacket;
3057 use packet_formats::ip::IpProto;
3058 use packet_formats::utils::NonZeroDuration;
3059
3060 use super::*;
3061 use crate::internal::base::{IpDeviceEgressStateContext, RouterAdvertisementEvent};
3062 use crate::internal::socket::testutil::{FakeDeviceConfig, FakeIpSocketCtx};
3063 use crate::internal::socket::{
3064 IpSock, IpSockCreationError, IpSockSendError, IpSocketHandler, SendOptions,
3065 };
3066 use crate::socket::RouteResolutionOptions;
3067
3068 type InnerIpSocketCtx<I> = FakeCoreCtx<
3070 FakeIpSocketCtx<I, FakeDeviceId>,
3071 SendIpPacketMeta<I, FakeDeviceId, SpecifiedAddr<<I as Ip>::Addr>>,
3072 FakeDeviceId,
3073 >;
3074
3075 pub(super) struct FakeIcmpCoreCtx<I: IpExt> {
3077 ip_socket_ctx: InnerIpSocketCtx<I>,
3078 icmp: FakeIcmpCoreCtxState<I>,
3079 }
3080
3081 type FakeIcmpBindingsCtx<I> = FakeBindingsCtx<
3083 (),
3084 RouterAdvertisementEvent<FakeDeviceId>,
3085 FakeIcmpBindingsCtxState<I>,
3086 (),
3087 >;
3088
3089 pub(super) type FakeIcmpCtx<I> = CtxPair<FakeIcmpCoreCtx<I>, FakeIcmpBindingsCtx<I>>;
3093
3094 pub(super) struct FakeIcmpCoreCtxState<I: IpExt> {
3095 error_send_bucket: TokenBucket<FakeInstant>,
3096 receive_icmp_error: Vec<I::ErrorCode>,
3097 rx_counters: IcmpRxCounters<I>,
3098 tx_counters: IcmpTxCounters<I>,
3099 ndp_counters: NdpCounters,
3100 }
3101
3102 impl<I: TestIpExt + IpExt> FakeIcmpCoreCtx<I> {
3103 fn with_errors_per_second(errors_per_second: u64) -> Self {
3104 Self {
3105 icmp: FakeIcmpCoreCtxState {
3106 error_send_bucket: TokenBucket::new(errors_per_second),
3107 receive_icmp_error: Default::default(),
3108 rx_counters: Default::default(),
3109 tx_counters: Default::default(),
3110 ndp_counters: Default::default(),
3111 },
3112 ip_socket_ctx: InnerIpSocketCtx::with_state(FakeIpSocketCtx::new(
3113 core::iter::once(FakeDeviceConfig {
3114 device: FakeDeviceId,
3115 local_ips: vec![I::TEST_ADDRS.local_ip],
3116 remote_ips: vec![I::TEST_ADDRS.remote_ip],
3117 }),
3118 )),
3119 }
3120 }
3121 }
3122
3123 impl<I: TestIpExt + IpExt> Default for FakeIcmpCoreCtx<I> {
3124 fn default() -> Self {
3125 Self::with_errors_per_second(DEFAULT_ERRORS_PER_SECOND)
3126 }
3127 }
3128
3129 impl<I: IpExt> DeviceIdContext<AnyDevice> for FakeIcmpCoreCtx<I> {
3130 type DeviceId = FakeDeviceId;
3131 type WeakDeviceId = FakeWeakDeviceId<FakeDeviceId>;
3132 }
3133
3134 impl<I: IpExt> IcmpStateContext for FakeIcmpCoreCtx<I> {}
3135 impl<I: IpExt> IcmpStateContext for InnerIpSocketCtx<I> {}
3136
3137 impl<I: IpExt> CounterContext<IcmpRxCounters<I>> for FakeIcmpCoreCtx<I> {
3138 fn counters(&self) -> &IcmpRxCounters<I> {
3139 &self.icmp.rx_counters
3140 }
3141 }
3142
3143 impl<I: IpExt> CounterContext<IcmpTxCounters<I>> for FakeIcmpCoreCtx<I> {
3144 fn counters(&self) -> &IcmpTxCounters<I> {
3145 &self.icmp.tx_counters
3146 }
3147 }
3148
3149 impl<I: IpExt> CounterContext<NdpCounters> for FakeIcmpCoreCtx<I> {
3150 fn counters(&self) -> &NdpCounters {
3151 &self.icmp.ndp_counters
3152 }
3153 }
3154
3155 pub enum FakeEchoIpTransportContext {}
3156
3157 impl EchoTransportContextMarker for FakeEchoIpTransportContext {}
3158
3159 impl<I: IpExt> IpTransportContext<I, FakeIcmpBindingsCtx<I>, FakeIcmpCoreCtx<I>>
3160 for FakeEchoIpTransportContext
3161 {
3162 fn receive_icmp_error(
3163 core_ctx: &mut FakeIcmpCoreCtx<I>,
3164 _bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3165 _device: &FakeDeviceId,
3166 _original_src_ip: Option<SpecifiedAddr<I::Addr>>,
3167 _original_dst_ip: SpecifiedAddr<I::Addr>,
3168 _original_body: &[u8],
3169 _err: I::ErrorCode,
3170 ) {
3171 core_ctx.icmp.rx_counters.error_delivered_to_socket.increment()
3172 }
3173
3174 fn receive_ip_packet<B: BufferMut, H: IpHeaderInfo<I>>(
3175 _core_ctx: &mut FakeIcmpCoreCtx<I>,
3176 _bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3177 _device: &FakeDeviceId,
3178 _src_ip: I::RecvSrcAddr,
3179 _dst_ip: SpecifiedAddr<I::Addr>,
3180 _buffer: B,
3181 _info: &LocalDeliveryPacketInfo<I, H>,
3182 ) -> Result<(), (B, TransportReceiveError)> {
3183 unimplemented!()
3184 }
3185 }
3186
3187 impl<I: IpExt> InnerIcmpContext<I, FakeIcmpBindingsCtx<I>> for FakeIcmpCoreCtx<I> {
3188 type EchoTransportContext = FakeEchoIpTransportContext;
3189
3190 fn receive_icmp_error(
3191 &mut self,
3192 bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3193 device: &Self::DeviceId,
3194 original_src_ip: Option<SpecifiedAddr<I::Addr>>,
3195 original_dst_ip: SpecifiedAddr<I::Addr>,
3196 original_proto: I::Proto,
3197 original_body: &[u8],
3198 err: I::ErrorCode,
3199 ) {
3200 CounterContext::<IcmpRxCounters<I>>::counters(self).error.increment();
3201 self.icmp.receive_icmp_error.push(err);
3202 if original_proto == I::ICMP_IP_PROTO {
3203 receive_ip_transport_icmp_error(
3204 self,
3205 bindings_ctx,
3206 device,
3207 original_src_ip,
3208 original_dst_ip,
3209 original_body,
3210 err,
3211 )
3212 }
3213 }
3214
3215 fn with_error_send_bucket_mut<O, F: FnOnce(&mut TokenBucket<FakeInstant>) -> O>(
3216 &mut self,
3217 cb: F,
3218 ) -> O {
3219 cb(&mut self.icmp.error_send_bucket)
3220 }
3221 }
3222
3223 #[test]
3224 fn test_should_send_icmpv4_error() {
3225 let src_ip = TEST_ADDRS_V4.local_ip;
3226 let dst_ip = TEST_ADDRS_V4.remote_ip;
3227 let frame_dst = FrameDestination::Individual { local: true };
3228 let multicast_ip_1 = SpecifiedAddr::new(Ipv4Addr::new([224, 0, 0, 1])).unwrap();
3229 let multicast_ip_2 = SpecifiedAddr::new(Ipv4Addr::new([224, 0, 0, 2])).unwrap();
3230
3231 assert!(should_send_icmpv4_error(
3233 Some(frame_dst),
3234 src_ip,
3235 dst_ip,
3236 Ipv4FragmentType::InitialFragment
3237 ));
3238 assert!(should_send_icmpv4_error(None, src_ip, dst_ip, Ipv4FragmentType::InitialFragment));
3239 assert!(!should_send_icmpv4_error(
3240 Some(frame_dst),
3241 src_ip,
3242 dst_ip,
3243 Ipv4FragmentType::NonInitialFragment
3244 ));
3245
3246 assert!(!should_send_icmpv4_error(
3248 Some(frame_dst),
3249 src_ip,
3250 Ipv4::LIMITED_BROADCAST_ADDRESS,
3251 Ipv4FragmentType::InitialFragment
3252 ));
3253 assert!(!should_send_icmpv4_error(
3254 Some(frame_dst),
3255 src_ip,
3256 Ipv4::LIMITED_BROADCAST_ADDRESS,
3257 Ipv4FragmentType::NonInitialFragment
3258 ));
3259
3260 assert!(!should_send_icmpv4_error(
3262 Some(frame_dst),
3263 src_ip,
3264 multicast_ip_1,
3265 Ipv4FragmentType::InitialFragment
3266 ));
3267 assert!(!should_send_icmpv4_error(
3268 Some(frame_dst),
3269 src_ip,
3270 multicast_ip_1,
3271 Ipv4FragmentType::NonInitialFragment
3272 ));
3273
3274 assert!(!should_send_icmpv4_error(
3276 Some(FrameDestination::Broadcast),
3277 src_ip,
3278 dst_ip,
3279 Ipv4FragmentType::InitialFragment
3280 ));
3281 assert!(!should_send_icmpv4_error(
3282 Some(FrameDestination::Broadcast),
3283 src_ip,
3284 dst_ip,
3285 Ipv4FragmentType::NonInitialFragment
3286 ));
3287
3288 assert!(!should_send_icmpv4_error(
3290 Some(frame_dst),
3291 Ipv4::LOOPBACK_ADDRESS,
3292 dst_ip,
3293 Ipv4FragmentType::InitialFragment
3294 ));
3295 assert!(!should_send_icmpv4_error(
3296 Some(frame_dst),
3297 Ipv4::LOOPBACK_ADDRESS,
3298 dst_ip,
3299 Ipv4FragmentType::NonInitialFragment
3300 ));
3301
3302 assert!(!should_send_icmpv4_error(
3304 Some(frame_dst),
3305 Ipv4::LIMITED_BROADCAST_ADDRESS,
3306 dst_ip,
3307 Ipv4FragmentType::InitialFragment
3308 ));
3309 assert!(!should_send_icmpv4_error(
3310 Some(frame_dst),
3311 Ipv4::LIMITED_BROADCAST_ADDRESS,
3312 dst_ip,
3313 Ipv4FragmentType::NonInitialFragment
3314 ));
3315
3316 assert!(!should_send_icmpv4_error(
3318 Some(frame_dst),
3319 multicast_ip_2,
3320 dst_ip,
3321 Ipv4FragmentType::InitialFragment
3322 ));
3323 assert!(!should_send_icmpv4_error(
3324 Some(frame_dst),
3325 multicast_ip_2,
3326 dst_ip,
3327 Ipv4FragmentType::NonInitialFragment
3328 ));
3329
3330 assert!(!should_send_icmpv4_error(
3332 Some(frame_dst),
3333 SpecifiedAddr::new(Ipv4Addr::new([240, 0, 0, 1])).unwrap(),
3334 dst_ip,
3335 Ipv4FragmentType::InitialFragment
3336 ));
3337 assert!(!should_send_icmpv4_error(
3338 Some(frame_dst),
3339 SpecifiedAddr::new(Ipv4Addr::new([240, 0, 0, 1])).unwrap(),
3340 dst_ip,
3341 Ipv4FragmentType::NonInitialFragment
3342 ));
3343 }
3344
3345 #[test]
3346 fn test_should_send_icmpv6_error() {
3347 let src_ip = TEST_ADDRS_V6.local_ip;
3348 let dst_ip = TEST_ADDRS_V6.remote_ip;
3349 let frame_dst = FrameDestination::Individual { local: true };
3350 let multicast_ip_1 =
3351 SpecifiedAddr::new(Ipv6Addr::new([0xff00, 0, 0, 0, 0, 0, 0, 1])).unwrap();
3352 let multicast_ip_2 =
3353 SpecifiedAddr::new(Ipv6Addr::new([0xff00, 0, 0, 0, 0, 0, 0, 2])).unwrap();
3354
3355 assert!(should_send_icmpv6_error(
3357 Some(frame_dst),
3358 src_ip,
3359 dst_ip,
3360 false ));
3362 assert!(should_send_icmpv6_error(None, src_ip, dst_ip, false ));
3363 assert!(should_send_icmpv6_error(
3364 Some(frame_dst),
3365 src_ip,
3366 dst_ip,
3367 true ));
3369
3370 assert!(!should_send_icmpv6_error(
3373 Some(frame_dst),
3374 src_ip,
3375 multicast_ip_1,
3376 false ));
3378 assert!(should_send_icmpv6_error(
3379 Some(frame_dst),
3380 src_ip,
3381 multicast_ip_1,
3382 true ));
3384
3385 assert!(!should_send_icmpv6_error(
3388 Some(FrameDestination::Broadcast),
3389 src_ip,
3390 dst_ip,
3391 false ));
3393 assert!(should_send_icmpv6_error(
3394 Some(FrameDestination::Broadcast),
3395 src_ip,
3396 dst_ip,
3397 true ));
3399
3400 assert!(!should_send_icmpv6_error(
3402 Some(frame_dst),
3403 Ipv6::LOOPBACK_ADDRESS,
3404 dst_ip,
3405 false ));
3407 assert!(!should_send_icmpv6_error(
3408 Some(frame_dst),
3409 Ipv6::LOOPBACK_ADDRESS,
3410 dst_ip,
3411 true ));
3413
3414 assert!(!should_send_icmpv6_error(
3416 Some(frame_dst),
3417 multicast_ip_2,
3418 dst_ip,
3419 false ));
3421 assert!(!should_send_icmpv6_error(
3422 Some(frame_dst),
3423 multicast_ip_2,
3424 dst_ip,
3425 true ));
3427
3428 assert!(!should_send_icmpv6_error(
3431 Some(FrameDestination::Broadcast),
3432 multicast_ip_2,
3433 dst_ip,
3434 false ));
3436 assert!(!should_send_icmpv6_error(
3437 Some(FrameDestination::Broadcast),
3438 multicast_ip_2,
3439 dst_ip,
3440 true ));
3442 assert!(!should_send_icmpv6_error(
3443 Some(frame_dst),
3444 multicast_ip_2,
3445 multicast_ip_1,
3446 false ));
3448 assert!(!should_send_icmpv6_error(
3449 Some(frame_dst),
3450 multicast_ip_2,
3451 multicast_ip_1,
3452 true ));
3454 }
3455
3456 #[derive(Default)]
3463 pub(super) struct FakeIcmpBindingsCtxState<I: IpExt> {
3464 _marker: core::marker::PhantomData<I>,
3465 }
3466
3467 impl InnerIcmpv4Context<FakeIcmpBindingsCtx<Ipv4>> for FakeIcmpCoreCtx<Ipv4> {
3468 fn should_send_timestamp_reply(&self) -> bool {
3469 false
3470 }
3471 }
3472 impl_pmtu_handler!(FakeIcmpCoreCtx<Ipv4>, FakeIcmpBindingsCtx<Ipv4>, Ipv4);
3473 impl_pmtu_handler!(FakeIcmpCoreCtx<Ipv6>, FakeIcmpBindingsCtx<Ipv6>, Ipv6);
3474
3475 impl<I: IpExt> IpSocketHandler<I, FakeIcmpBindingsCtx<I>> for FakeIcmpCoreCtx<I> {
3476 fn new_ip_socket<O>(
3477 &mut self,
3478 bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3479 device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
3480 local_ip: Option<IpDeviceAddr<I::Addr>>,
3481 remote_ip: SocketIpAddr<I::Addr>,
3482 proto: I::Proto,
3483 options: &O,
3484 ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
3485 where
3486 O: RouteResolutionOptions<I>,
3487 {
3488 self.ip_socket_ctx.new_ip_socket(
3489 bindings_ctx,
3490 device,
3491 local_ip,
3492 remote_ip,
3493 proto,
3494 options,
3495 )
3496 }
3497
3498 fn send_ip_packet<S, O>(
3499 &mut self,
3500 bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3501 socket: &IpSock<I, Self::WeakDeviceId>,
3502 body: S,
3503 options: &O,
3504 tx_meta: FakeTxMetadata,
3505 ) -> Result<(), IpSockSendError>
3506 where
3507 S: TransportPacketSerializer<I>,
3508 S::Buffer: BufferMut,
3509 O: SendOptions<I> + RouteResolutionOptions<I>,
3510 {
3511 self.ip_socket_ctx.send_ip_packet(bindings_ctx, socket, body, options, tx_meta)
3512 }
3513
3514 fn confirm_reachable<O>(
3515 &mut self,
3516 bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3517 socket: &IpSock<I, Self::WeakDeviceId>,
3518 options: &O,
3519 ) where
3520 O: RouteResolutionOptions<I>,
3521 {
3522 self.ip_socket_ctx.confirm_reachable(bindings_ctx, socket, options)
3523 }
3524 }
3525
3526 impl IpDeviceHandler<Ipv6, FakeIcmpBindingsCtx<Ipv6>> for FakeIcmpCoreCtx<Ipv6> {
3527 fn is_router_device(&mut self, _device_id: &Self::DeviceId) -> bool {
3528 unimplemented!()
3529 }
3530
3531 fn set_default_hop_limit(&mut self, _device_id: &Self::DeviceId, _hop_limit: NonZeroU8) {
3532 unreachable!()
3533 }
3534 }
3535
3536 impl IpDeviceEgressStateContext<Ipv6> for FakeIcmpCoreCtx<Ipv6> {
3537 fn with_next_packet_id<O, F: FnOnce(&()) -> O>(&self, cb: F) -> O {
3538 cb(&())
3539 }
3540
3541 fn get_local_addr_for_remote(
3542 &mut self,
3543 _device_id: &Self::DeviceId,
3544 _remote: Option<SpecifiedAddr<Ipv6Addr>>,
3545 ) -> Option<IpDeviceAddr<Ipv6Addr>> {
3546 unimplemented!()
3547 }
3548
3549 fn get_hop_limit(&mut self, _device_id: &Self::DeviceId) -> NonZeroU8 {
3550 unimplemented!()
3551 }
3552 }
3553
3554 impl IpDeviceIngressStateContext<Ipv6> for FakeIcmpCoreCtx<Ipv6> {
3555 fn address_status_for_device(
3556 &mut self,
3557 _addr: SpecifiedAddr<Ipv6Addr>,
3558 _device_id: &Self::DeviceId,
3559 ) -> AddressStatus<Ipv6PresentAddressStatus> {
3560 unimplemented!()
3561 }
3562 }
3563
3564 impl Ipv6DeviceHandler<FakeIcmpBindingsCtx<Ipv6>> for FakeIcmpCoreCtx<Ipv6> {
3565 type LinkLayerAddr = Uninstantiable;
3566
3567 fn get_link_layer_addr(&mut self, _device_id: &Self::DeviceId) -> Option<Uninstantiable> {
3568 unimplemented!()
3569 }
3570
3571 fn set_discovered_retrans_timer(
3572 &mut self,
3573 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3574 _device_id: &Self::DeviceId,
3575 _retrans_timer: NonZeroDuration,
3576 ) {
3577 unimplemented!()
3578 }
3579
3580 fn handle_received_dad_neighbor_solicitation(
3581 &mut self,
3582 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3583 _device_id: &Self::DeviceId,
3584 _addr: UnicastAddr<Ipv6Addr>,
3585 _nonce: Option<NdpNonce<&'_ [u8]>>,
3586 ) -> IpAddressState {
3587 unimplemented!()
3588 }
3589
3590 fn handle_received_neighbor_advertisement(
3591 &mut self,
3592 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3593 _device_id: &Self::DeviceId,
3594 _addr: UnicastAddr<Ipv6Addr>,
3595 ) -> IpAddressState {
3596 unimplemented!()
3597 }
3598
3599 fn set_link_mtu(&mut self, _device_id: &Self::DeviceId, _mtu: Mtu) {
3600 unimplemented!()
3601 }
3602
3603 fn update_discovered_ipv6_route(
3604 &mut self,
3605 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3606 _device_id: &Self::DeviceId,
3607 _route: Ipv6DiscoveredRoute,
3608 _lifetime: Option<NonZeroNdpLifetime>,
3609 ) {
3610 unimplemented!()
3611 }
3612
3613 fn apply_slaac_update(
3614 &mut self,
3615 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3616 _device_id: &Self::DeviceId,
3617 _subnet: Subnet<Ipv6Addr>,
3618 _preferred_lifetime: Option<NonZeroNdpLifetime>,
3619 _valid_lifetime: Option<NonZeroNdpLifetime>,
3620 ) {
3621 unimplemented!()
3622 }
3623
3624 fn receive_mld_packet<B: SplitByteSlice, H: IpHeaderInfo<Ipv6>>(
3625 &mut self,
3626 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3627 _device: &FakeDeviceId,
3628 _src_ip: Ipv6SourceAddr,
3629 _dst_ip: SpecifiedAddr<Ipv6Addr>,
3630 _packet: MldPacket<B>,
3631 _header_info: &H,
3632 ) {
3633 unimplemented!()
3634 }
3635 }
3636
3637 impl IpLayerHandler<Ipv6, FakeIcmpBindingsCtx<Ipv6>> for FakeIcmpCoreCtx<Ipv6> {
3638 fn send_ip_packet_from_device<S>(
3639 &mut self,
3640 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3641 _meta: SendIpPacketMeta<Ipv6, &Self::DeviceId, Option<SpecifiedAddr<Ipv6Addr>>>,
3642 _body: S,
3643 ) -> Result<(), IpSendFrameError<S>> {
3644 unimplemented!()
3645 }
3646
3647 fn send_ip_frame<S>(
3648 &mut self,
3649 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3650 _device: &Self::DeviceId,
3651 _destination: IpPacketDestination<Ipv6, &Self::DeviceId>,
3652 _body: S,
3653 ) -> Result<(), IpSendFrameError<S>>
3654 where
3655 S: Serializer,
3656 S::Buffer: BufferMut,
3657 {
3658 unimplemented!()
3659 }
3660 }
3661
3662 impl NudIpHandler<Ipv6, FakeIcmpBindingsCtx<Ipv6>> for FakeIcmpCoreCtx<Ipv6> {
3663 fn handle_neighbor_probe(
3664 &mut self,
3665 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3666 _device_id: &Self::DeviceId,
3667 _neighbor: SpecifiedAddr<Ipv6Addr>,
3668 _link_addr: &[u8],
3669 ) {
3670 unimplemented!()
3671 }
3672
3673 fn handle_neighbor_confirmation(
3674 &mut self,
3675 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3676 _device_id: &Self::DeviceId,
3677 _neighbor: SpecifiedAddr<Ipv6Addr>,
3678 _link_addr: &[u8],
3679 _flags: ConfirmationFlags,
3680 ) {
3681 unimplemented!()
3682 }
3683
3684 fn flush_neighbor_table(
3685 &mut self,
3686 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3687 _device_id: &Self::DeviceId,
3688 ) {
3689 unimplemented!()
3690 }
3691 }
3692
3693 #[test]
3694 fn test_receive_icmpv4_error() {
3695 const ICMP_ID: u16 = 0x0F;
3698 const SEQ_NUM: u16 = 0xF0;
3699
3700 fn test_receive_icmpv4_error_helper<
3715 C: Debug,
3716 M: IcmpMessage<Ipv4, Code = C> + Debug,
3717 F: Fn(&FakeIcmpCtx<Ipv4>),
3718 >(
3719 original_packet: &mut [u8],
3720 code: C,
3721 msg: M,
3722 f: F,
3723 ) {
3724 set_logger_for_test();
3725
3726 let mut ctx: FakeIcmpCtx<Ipv4> = FakeIcmpCtx::default();
3727
3728 let CtxPair { core_ctx, bindings_ctx } = &mut ctx;
3729 <IcmpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_ip_packet(
3730 core_ctx,
3731 bindings_ctx,
3732 &FakeDeviceId,
3733 TEST_ADDRS_V4.remote_ip.get(),
3734 TEST_ADDRS_V4.local_ip,
3735 Buf::new(original_packet, ..)
3736 .encapsulate(IcmpPacketBuilder::new(
3737 TEST_ADDRS_V4.remote_ip,
3738 TEST_ADDRS_V4.local_ip,
3739 code,
3740 msg,
3741 ))
3742 .serialize_vec_outer()
3743 .unwrap(),
3744 &LocalDeliveryPacketInfo::default(),
3745 )
3746 .unwrap();
3747 f(&ctx);
3748 }
3749 let mut buffer = Buf::new(&mut [], ..)
3762 .encapsulate(IcmpPacketBuilder::<Ipv4, _>::new(
3763 TEST_ADDRS_V4.local_ip,
3764 TEST_ADDRS_V4.remote_ip,
3765 IcmpZeroCode,
3766 IcmpEchoRequest::new(ICMP_ID, SEQ_NUM),
3767 ))
3768 .encapsulate(<Ipv4 as packet_formats::ip::IpExt>::PacketBuilder::new(
3769 TEST_ADDRS_V4.local_ip,
3770 TEST_ADDRS_V4.remote_ip,
3771 64,
3772 Ipv4Proto::Icmp,
3773 ))
3774 .serialize_vec_outer()
3775 .unwrap();
3776
3777 test_receive_icmpv4_error_helper(
3778 buffer.as_mut(),
3779 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3780 IcmpDestUnreachable::default(),
3781 |CtxPair { core_ctx, bindings_ctx: _ }| {
3782 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3783 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3784 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3785 let err = Icmpv4ErrorCode::DestUnreachable(
3786 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3787 IcmpDestUnreachable::default(),
3788 );
3789 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3790 },
3791 );
3792
3793 test_receive_icmpv4_error_helper(
3794 buffer.as_mut(),
3795 Icmpv4TimeExceededCode::TtlExpired,
3796 IcmpTimeExceeded::default(),
3797 |CtxPair { core_ctx, bindings_ctx: _ }| {
3798 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3799 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3800 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3801 let err = Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired);
3802 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3803 },
3804 );
3805
3806 test_receive_icmpv4_error_helper(
3807 buffer.as_mut(),
3808 Icmpv4ParameterProblemCode::PointerIndicatesError,
3809 Icmpv4ParameterProblem::new(0),
3810 |CtxPair { core_ctx, bindings_ctx: _ }| {
3811 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3812 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3813 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3814 let err = Icmpv4ErrorCode::ParameterProblem(
3815 Icmpv4ParameterProblemCode::PointerIndicatesError,
3816 );
3817 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3818 },
3819 );
3820
3821 let mut buffer = Buf::new(&mut [], ..)
3828 .encapsulate(<Ipv4 as packet_formats::ip::IpExt>::PacketBuilder::new(
3829 TEST_ADDRS_V4.local_ip,
3830 TEST_ADDRS_V4.remote_ip,
3831 64,
3832 Ipv4Proto::Icmp,
3833 ))
3834 .serialize_vec_outer()
3835 .unwrap();
3836
3837 test_receive_icmpv4_error_helper(
3838 buffer.as_mut(),
3839 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3840 IcmpDestUnreachable::default(),
3841 |CtxPair { core_ctx, bindings_ctx: _ }| {
3842 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3843 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3844 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3845 let err = Icmpv4ErrorCode::DestUnreachable(
3846 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3847 IcmpDestUnreachable::default(),
3848 );
3849 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3850 },
3851 );
3852
3853 test_receive_icmpv4_error_helper(
3854 buffer.as_mut(),
3855 Icmpv4TimeExceededCode::TtlExpired,
3856 IcmpTimeExceeded::default(),
3857 |CtxPair { core_ctx, bindings_ctx: _ }| {
3858 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3859 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3860 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3861 let err = Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired);
3862 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3863 },
3864 );
3865
3866 test_receive_icmpv4_error_helper(
3867 buffer.as_mut(),
3868 Icmpv4ParameterProblemCode::PointerIndicatesError,
3869 Icmpv4ParameterProblem::new(0),
3870 |CtxPair { core_ctx, bindings_ctx: _ }| {
3871 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3872 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3873 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3874 let err = Icmpv4ErrorCode::ParameterProblem(
3875 Icmpv4ParameterProblemCode::PointerIndicatesError,
3876 );
3877 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3878 },
3879 );
3880
3881 let mut buffer = Buf::new(&mut [], ..)
3887 .encapsulate(<Ipv4 as packet_formats::ip::IpExt>::PacketBuilder::new(
3888 TEST_ADDRS_V4.local_ip,
3889 TEST_ADDRS_V4.remote_ip,
3890 64,
3891 IpProto::Udp.into(),
3892 ))
3893 .serialize_vec_outer()
3894 .unwrap();
3895
3896 test_receive_icmpv4_error_helper(
3897 buffer.as_mut(),
3898 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3899 IcmpDestUnreachable::default(),
3900 |CtxPair { core_ctx, bindings_ctx: _ }| {
3901 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3902 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3903 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3904 let err = Icmpv4ErrorCode::DestUnreachable(
3905 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3906 IcmpDestUnreachable::default(),
3907 );
3908 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3909 },
3910 );
3911
3912 test_receive_icmpv4_error_helper(
3913 buffer.as_mut(),
3914 Icmpv4TimeExceededCode::TtlExpired,
3915 IcmpTimeExceeded::default(),
3916 |CtxPair { core_ctx, bindings_ctx: _ }| {
3917 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3918 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3919 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3920 let err = Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired);
3921 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3922 },
3923 );
3924
3925 test_receive_icmpv4_error_helper(
3926 buffer.as_mut(),
3927 Icmpv4ParameterProblemCode::PointerIndicatesError,
3928 Icmpv4ParameterProblem::new(0),
3929 |CtxPair { core_ctx, bindings_ctx: _ }| {
3930 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3931 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3932 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3933 let err = Icmpv4ErrorCode::ParameterProblem(
3934 Icmpv4ParameterProblemCode::PointerIndicatesError,
3935 );
3936 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3937 },
3938 );
3939 }
3940
3941 #[test]
3942 fn test_receive_icmpv6_error() {
3943 const ICMP_ID: u16 = 0x0F;
3946 const SEQ_NUM: u16 = 0xF0;
3947
3948 fn test_receive_icmpv6_error_helper<
3963 C: Debug,
3964 M: IcmpMessage<Ipv6, Code = C> + Debug,
3965 F: Fn(&FakeIcmpCtx<Ipv6>),
3966 >(
3967 original_packet: &mut [u8],
3968 code: C,
3969 msg: M,
3970 f: F,
3971 ) {
3972 set_logger_for_test();
3973
3974 let mut ctx = FakeIcmpCtx::<Ipv6>::default();
3975 let CtxPair { core_ctx, bindings_ctx } = &mut ctx;
3976 <IcmpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
3977 core_ctx,
3978 bindings_ctx,
3979 &FakeDeviceId,
3980 TEST_ADDRS_V6.remote_ip.get().try_into().unwrap(),
3981 TEST_ADDRS_V6.local_ip,
3982 Buf::new(original_packet, ..)
3983 .encapsulate(IcmpPacketBuilder::new(
3984 TEST_ADDRS_V6.remote_ip,
3985 TEST_ADDRS_V6.local_ip,
3986 code,
3987 msg,
3988 ))
3989 .serialize_vec_outer()
3990 .unwrap(),
3991 &LocalDeliveryPacketInfo::default(),
3992 )
3993 .unwrap();
3994 f(&ctx);
3995 }
3996 let mut buffer = Buf::new(&mut [], ..)
4009 .encapsulate(IcmpPacketBuilder::<Ipv6, _>::new(
4010 TEST_ADDRS_V6.local_ip,
4011 TEST_ADDRS_V6.remote_ip,
4012 IcmpZeroCode,
4013 IcmpEchoRequest::new(ICMP_ID, SEQ_NUM),
4014 ))
4015 .encapsulate(<Ipv6 as packet_formats::ip::IpExt>::PacketBuilder::new(
4016 TEST_ADDRS_V6.local_ip,
4017 TEST_ADDRS_V6.remote_ip,
4018 64,
4019 Ipv6Proto::Icmpv6,
4020 ))
4021 .serialize_vec_outer()
4022 .unwrap();
4023
4024 test_receive_icmpv6_error_helper(
4025 buffer.as_mut(),
4026 Icmpv6DestUnreachableCode::NoRoute,
4027 IcmpDestUnreachable::default(),
4028 |CtxPair { core_ctx, bindings_ctx: _ }| {
4029 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4030 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
4031 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
4032 let err = Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute);
4033 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4034 },
4035 );
4036
4037 test_receive_icmpv6_error_helper(
4038 buffer.as_mut(),
4039 Icmpv6TimeExceededCode::HopLimitExceeded,
4040 IcmpTimeExceeded::default(),
4041 |CtxPair { core_ctx, bindings_ctx: _ }| {
4042 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4043 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
4044 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
4045 let err = Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded);
4046 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4047 },
4048 );
4049
4050 test_receive_icmpv6_error_helper(
4051 buffer.as_mut(),
4052 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
4053 Icmpv6ParameterProblem::new(0),
4054 |CtxPair { core_ctx, bindings_ctx: _ }| {
4055 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4056 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
4057 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
4058 let err = Icmpv6ErrorCode::ParameterProblem(
4059 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
4060 );
4061 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4062 },
4063 );
4064
4065 let mut buffer = Buf::new(&mut [], ..)
4072 .encapsulate(<Ipv6 as packet_formats::ip::IpExt>::PacketBuilder::new(
4073 TEST_ADDRS_V6.local_ip,
4074 TEST_ADDRS_V6.remote_ip,
4075 64,
4076 Ipv6Proto::Icmpv6,
4077 ))
4078 .serialize_vec_outer()
4079 .unwrap();
4080
4081 test_receive_icmpv6_error_helper(
4082 buffer.as_mut(),
4083 Icmpv6DestUnreachableCode::NoRoute,
4084 IcmpDestUnreachable::default(),
4085 |CtxPair { core_ctx, bindings_ctx: _ }| {
4086 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4087 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
4088 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
4089 let err = Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute);
4090 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4091 },
4092 );
4093
4094 test_receive_icmpv6_error_helper(
4095 buffer.as_mut(),
4096 Icmpv6TimeExceededCode::HopLimitExceeded,
4097 IcmpTimeExceeded::default(),
4098 |CtxPair { core_ctx, bindings_ctx: _ }| {
4099 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4100 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
4101 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
4102 let err = Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded);
4103 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4104 },
4105 );
4106
4107 test_receive_icmpv6_error_helper(
4108 buffer.as_mut(),
4109 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
4110 Icmpv6ParameterProblem::new(0),
4111 |CtxPair { core_ctx, bindings_ctx: _ }| {
4112 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4113 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
4114 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
4115 let err = Icmpv6ErrorCode::ParameterProblem(
4116 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
4117 );
4118 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4119 },
4120 );
4121
4122 let mut buffer = Buf::new(&mut [], ..)
4128 .encapsulate(<Ipv6 as packet_formats::ip::IpExt>::PacketBuilder::new(
4129 TEST_ADDRS_V6.local_ip,
4130 TEST_ADDRS_V6.remote_ip,
4131 64,
4132 IpProto::Udp.into(),
4133 ))
4134 .serialize_vec_outer()
4135 .unwrap();
4136
4137 test_receive_icmpv6_error_helper(
4138 buffer.as_mut(),
4139 Icmpv6DestUnreachableCode::NoRoute,
4140 IcmpDestUnreachable::default(),
4141 |CtxPair { core_ctx, bindings_ctx: _ }| {
4142 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4143 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
4144 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
4145 let err = Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute);
4146 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4147 },
4148 );
4149
4150 test_receive_icmpv6_error_helper(
4151 buffer.as_mut(),
4152 Icmpv6TimeExceededCode::HopLimitExceeded,
4153 IcmpTimeExceeded::default(),
4154 |CtxPair { core_ctx, bindings_ctx: _ }| {
4155 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4156 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
4157 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
4158 let err = Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded);
4159 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4160 },
4161 );
4162
4163 test_receive_icmpv6_error_helper(
4164 buffer.as_mut(),
4165 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
4166 Icmpv6ParameterProblem::new(0),
4167 |CtxPair { core_ctx, bindings_ctx: _ }| {
4168 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
4169 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
4170 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
4171 let err = Icmpv6ErrorCode::ParameterProblem(
4172 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
4173 );
4174 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
4175 },
4176 );
4177 }
4178
4179 #[test]
4180 fn test_error_rate_limit() {
4181 set_logger_for_test();
4182
4183 fn send_icmpv4_ttl_expired_helper(
4185 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv4>,
4186 ) {
4187 send_icmpv4_ttl_expired(
4188 core_ctx,
4189 bindings_ctx,
4190 &FakeDeviceId,
4191 Some(FrameDestination::Individual { local: true }),
4192 TEST_ADDRS_V4.remote_ip.try_into().unwrap(),
4193 TEST_ADDRS_V4.local_ip.try_into().unwrap(),
4194 IpProto::Udp.into(),
4195 Buf::new(&mut [], ..),
4196 0,
4197 Ipv4FragmentType::InitialFragment,
4198 &Default::default(),
4199 );
4200 }
4201
4202 fn send_icmpv4_parameter_problem_helper(
4204 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv4>,
4205 ) {
4206 send_icmpv4_parameter_problem(
4207 core_ctx,
4208 bindings_ctx,
4209 &FakeDeviceId,
4210 Some(FrameDestination::Individual { local: true }),
4211 TEST_ADDRS_V4.remote_ip.try_into().unwrap(),
4212 TEST_ADDRS_V4.local_ip.try_into().unwrap(),
4213 Icmpv4ParameterProblemCode::PointerIndicatesError,
4214 Icmpv4ParameterProblem::new(0),
4215 Buf::new(&mut [], ..),
4216 0,
4217 Ipv4FragmentType::InitialFragment,
4218 &Default::default(),
4219 );
4220 }
4221
4222 fn send_icmpv4_dest_unreachable_helper(
4224 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv4>,
4225 ) {
4226 send_icmpv4_dest_unreachable(
4227 core_ctx,
4228 bindings_ctx,
4229 Some(&FakeDeviceId),
4230 Some(FrameDestination::Individual { local: true }),
4231 TEST_ADDRS_V4.remote_ip.try_into().unwrap(),
4232 TEST_ADDRS_V4.local_ip.try_into().unwrap(),
4233 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
4234 Buf::new(&mut [], ..),
4235 0,
4236 Ipv4FragmentType::InitialFragment,
4237 &Default::default(),
4238 );
4239 }
4240
4241 fn send_icmpv6_ttl_expired_helper(
4243 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv6>,
4244 ) {
4245 send_icmpv6_ttl_expired(
4246 core_ctx,
4247 bindings_ctx,
4248 &FakeDeviceId,
4249 Some(FrameDestination::Individual { local: true }),
4250 TEST_ADDRS_V6.remote_ip.try_into().unwrap(),
4251 TEST_ADDRS_V6.local_ip.try_into().unwrap(),
4252 IpProto::Udp.into(),
4253 Buf::new(&mut [], ..),
4254 0,
4255 &Default::default(),
4256 );
4257 }
4258
4259 fn send_icmpv6_packet_too_big_helper(
4261 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv6>,
4262 ) {
4263 send_icmpv6_packet_too_big(
4264 core_ctx,
4265 bindings_ctx,
4266 &FakeDeviceId,
4267 Some(FrameDestination::Individual { local: true }),
4268 TEST_ADDRS_V6.remote_ip.try_into().unwrap(),
4269 TEST_ADDRS_V6.local_ip.try_into().unwrap(),
4270 IpProto::Udp.into(),
4271 Mtu::new(0),
4272 Buf::new(&mut [], ..),
4273 0,
4274 &Default::default(),
4275 );
4276 }
4277
4278 fn send_icmpv6_parameter_problem_helper(
4280 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv6>,
4281 ) {
4282 send_icmpv6_parameter_problem(
4283 core_ctx,
4284 bindings_ctx,
4285 &FakeDeviceId,
4286 Some(FrameDestination::Individual { local: true }),
4287 TEST_ADDRS_V6.remote_ip.try_into().unwrap(),
4288 TEST_ADDRS_V6.local_ip.try_into().unwrap(),
4289 Icmpv6ParameterProblemCode::ErroneousHeaderField,
4290 Icmpv6ParameterProblem::new(0),
4291 Buf::new(&mut [], ..),
4292 false,
4293 &Default::default(),
4294 );
4295 }
4296
4297 fn send_icmpv6_dest_unreachable_helper(
4299 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv6>,
4300 ) {
4301 send_icmpv6_dest_unreachable(
4302 core_ctx,
4303 bindings_ctx,
4304 Some(&FakeDeviceId),
4305 Some(FrameDestination::Individual { local: true }),
4306 TEST_ADDRS_V6.remote_ip.try_into().unwrap(),
4307 TEST_ADDRS_V6.local_ip.try_into().unwrap(),
4308 Icmpv6DestUnreachableCode::NoRoute,
4309 Buf::new(&mut [], ..),
4310 &Default::default(),
4311 );
4312 }
4313
4314 fn run_test<I: IpExt, W: Fn(u64) -> FakeIcmpCtx<I>, S: Fn(&mut FakeIcmpCtx<I>)>(
4318 with_errors_per_second: W,
4319 send: S,
4320 ) {
4321 const ERRORS_PER_SECOND: u64 = 64;
4335
4336 let mut ctx = with_errors_per_second(ERRORS_PER_SECOND);
4337
4338 for i in 0..ERRORS_PER_SECOND {
4339 send(&mut ctx);
4340 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), i + 1);
4341 }
4342
4343 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), ERRORS_PER_SECOND);
4344 send(&mut ctx);
4345 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), ERRORS_PER_SECOND);
4346
4347 let mut ctx = with_errors_per_second(0);
4351 send(&mut ctx);
4352 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), 0);
4353 ctx.bindings_ctx.timers.instant.sleep(Duration::from_secs(1));
4354 send(&mut ctx);
4355 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), 0);
4356 ctx.bindings_ctx.timers.instant.sleep(Duration::from_secs(1));
4357 send(&mut ctx);
4358 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), 0);
4359 }
4360
4361 fn with_errors_per_second_v4(errors_per_second: u64) -> FakeIcmpCtx<Ipv4> {
4362 CtxPair::with_core_ctx(FakeIcmpCoreCtx::with_errors_per_second(errors_per_second))
4363 }
4364 run_test::<Ipv4, _, _>(with_errors_per_second_v4, send_icmpv4_ttl_expired_helper);
4365 run_test::<Ipv4, _, _>(with_errors_per_second_v4, send_icmpv4_parameter_problem_helper);
4366 run_test::<Ipv4, _, _>(with_errors_per_second_v4, send_icmpv4_dest_unreachable_helper);
4367
4368 fn with_errors_per_second_v6(errors_per_second: u64) -> FakeIcmpCtx<Ipv6> {
4369 CtxPair::with_core_ctx(FakeIcmpCoreCtx::with_errors_per_second(errors_per_second))
4370 }
4371
4372 run_test::<Ipv6, _, _>(with_errors_per_second_v6, send_icmpv6_ttl_expired_helper);
4373 run_test::<Ipv6, _, _>(with_errors_per_second_v6, send_icmpv6_packet_too_big_helper);
4374 run_test::<Ipv6, _, _>(with_errors_per_second_v6, send_icmpv6_parameter_problem_helper);
4375 run_test::<Ipv6, _, _>(with_errors_per_second_v6, send_icmpv6_dest_unreachable_helper);
4376 }
4377}