1pub mod counters;
8
9use alloc::boxed::Box;
10use core::convert::{Infallible as Never, TryInto as _};
11use core::fmt::Debug;
12use core::num::{NonZeroU8, NonZeroU16};
13
14use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
15use log::{debug, error, trace};
16use net_types::ip::{
17 GenericOverIp, Ip, IpMarked, Ipv4, Ipv4Addr, Ipv4SourceAddr, Ipv6, Ipv6Addr, Ipv6SourceAddr,
18 Mtu, SubnetError,
19};
20use net_types::{
21 LinkLocalAddress, LinkLocalUnicastAddr, MulticastAddr, MulticastAddress, SpecifiedAddr,
22 UnicastAddr, Witness,
23};
24use netstack3_base::socket::{AddrIsMappedError, SocketIpAddr, SocketIpAddrExt as _};
25use netstack3_base::sync::Mutex;
26use netstack3_base::{
27 AnyDevice, Counter, CounterContext, DeviceIdContext, EitherDeviceId, FrameDestination,
28 IcmpIpExt, Icmpv4ErrorCode, Icmpv6ErrorCode, InstantBindingsTypes, InstantContext,
29 IpDeviceAddr, IpExt, Marks, NetworkPartialSerializer, NetworkSerializer, RngContext,
30 TokenBucket, TxMetadataBindingsTypes,
31};
32use netstack3_filter::{DynTransportSerializer, DynamicTransportSerializer, FilterIpExt};
33use packet::{
34 BufferMut, InnerPacketBuilder as _, NestablePacketBuilder as _, ParsablePacket as _,
35 ParseBuffer, TruncateDirection, TruncatingSerializer,
36};
37use packet_formats::icmp::ndp::options::{NdpOption, NdpOptionBuilder};
38use packet_formats::icmp::ndp::{
39 NdpPacket, NeighborAdvertisement, NeighborSolicitation, NonZeroNdpLifetime,
40 OptionSequenceBuilder, RouterSolicitation,
41};
42use packet_formats::icmp::{
43 IcmpDestUnreachable, IcmpEchoRequest, IcmpMessage, IcmpMessageType, IcmpPacket,
44 IcmpPacketBuilder, IcmpPacketRaw, IcmpParseArgs, IcmpTimeExceeded, IcmpZeroCode,
45 Icmpv4DestUnreachableCode, Icmpv4Packet, Icmpv4ParameterProblem, Icmpv4ParameterProblemCode,
46 Icmpv4TimeExceededCode, Icmpv6DestUnreachableCode, Icmpv6Packet, Icmpv6PacketTooBig,
47 Icmpv6ParameterProblem, Icmpv6ParameterProblemCode, Icmpv6TimeExceededCode, MessageBody,
48 OriginalPacket, peek_message_type,
49};
50use packet_formats::ip::{DscpAndEcn, Ipv4Proto, Ipv6Proto};
51use packet_formats::ipv4::Ipv4Header;
52use packet_formats::ipv6::{ExtHdrParseError, Ipv6Header};
53use zerocopy::SplitByteSlice;
54
55use crate::IpLayerIpExt;
56use crate::internal::base::{
57 AddressStatus, IPV6_DEFAULT_SUBNET, IpDeviceIngressStateContext, IpLayerHandler,
58 IpPacketDestination, IpSendFrameError, IpTransportContext, Ipv6PresentAddressStatus,
59 NdpBindingsContext, RouterAdvertisementEvent, SendIpPacketMeta,
60};
61use crate::internal::device::nud::{ConfirmationFlags, NudIpHandler};
62use crate::internal::device::route_discovery::{
63 Ipv6DiscoveredRoute, Ipv6DiscoveredRouteProperties,
64};
65use crate::internal::device::{
66 IpAddressState, IpDeviceHandler, Ipv6DeviceHandler, Ipv6LinkLayerAddr,
67};
68use crate::internal::icmp::counters::{IcmpCountersIpExt, IcmpRxCounters, IcmpTxCounters};
69use crate::internal::local_delivery::{IpHeaderInfo, LocalDeliveryPacketInfo, ReceiveIpPacketMeta};
70use crate::internal::path_mtu::PmtuHandler;
71use crate::internal::socket::{
72 DelegatedRouteResolutionOptions, DelegatedSendOptions, IpSocketArgs, IpSocketHandler,
73 OptionDelegationMarker, RouteResolutionOptions, SendOptions,
74};
75use crate::internal::types::RoutePreference;
76
77pub const REQUIRED_NDP_IP_PACKET_HOP_LIMIT: u8 = 255;
89
90pub const DEFAULT_ERRORS_PER_SECOND: u64 = 1000;
98#[derive(GenericOverIp)]
100#[generic_over_ip(I, Ip)]
101pub struct IcmpState<I: IpExt + IcmpCountersIpExt, BT: IcmpBindingsTypes> {
102 error_send_bucket: Mutex<IpMarked<I, TokenBucket<BT::Instant>>>,
103 pub tx_counters: IcmpTxCounters<I>,
105 pub rx_counters: IcmpRxCounters<I>,
107}
108
109impl<I, BT> OrderedLockAccess<IpMarked<I, TokenBucket<BT::Instant>>> for IcmpState<I, BT>
110where
111 I: IpExt + IcmpCountersIpExt,
112 BT: IcmpBindingsTypes,
113{
114 type Lock = Mutex<IpMarked<I, TokenBucket<BT::Instant>>>;
115 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
116 OrderedLockRef::new(&self.error_send_bucket)
117 }
118}
119
120#[derive(Default)]
122pub struct NdpRxCounters {
123 pub neighbor_solicitation: Counter,
125 pub neighbor_advertisement: Counter,
127 pub router_advertisement: Counter,
129 pub router_solicitation: Counter,
131}
132
133#[derive(Default)]
135pub struct NdpTxCounters {
136 pub neighbor_advertisement: Counter,
138 pub neighbor_solicitation: Counter,
140}
141
142#[derive(Default)]
144pub struct NdpCounters {
145 pub rx: NdpRxCounters,
147 pub tx: NdpTxCounters,
149}
150
151#[derive(Copy, Clone)]
153pub struct Icmpv4StateBuilder {
154 send_timestamp_reply: bool,
155 errors_per_second: u64,
156}
157
158impl Default for Icmpv4StateBuilder {
159 fn default() -> Icmpv4StateBuilder {
160 Icmpv4StateBuilder {
161 send_timestamp_reply: false,
162 errors_per_second: DEFAULT_ERRORS_PER_SECOND,
163 }
164 }
165}
166
167impl Icmpv4StateBuilder {
168 pub fn send_timestamp_reply(&mut self, send_timestamp_reply: bool) -> &mut Self {
175 self.send_timestamp_reply = send_timestamp_reply;
176 self
177 }
178
179 pub fn build<BT: IcmpBindingsTypes>(self) -> Icmpv4State<BT> {
181 Icmpv4State {
182 inner: IcmpState {
183 error_send_bucket: Mutex::new(IpMarked::new(TokenBucket::new(
184 self.errors_per_second,
185 ))),
186 tx_counters: Default::default(),
187 rx_counters: Default::default(),
188 },
189 send_timestamp_reply: self.send_timestamp_reply,
190 }
191 }
192}
193
194pub struct Icmpv4State<BT: IcmpBindingsTypes> {
196 pub inner: IcmpState<Ipv4, BT>,
198 pub send_timestamp_reply: bool,
200}
201
202impl<BT: IcmpBindingsTypes> AsRef<IcmpState<Ipv4, BT>> for Icmpv4State<BT> {
203 fn as_ref(&self) -> &IcmpState<Ipv4, BT> {
204 &self.inner
205 }
206}
207
208impl<BT: IcmpBindingsTypes> AsMut<IcmpState<Ipv4, BT>> for Icmpv4State<BT> {
209 fn as_mut(&mut self) -> &mut IcmpState<Ipv4, BT> {
210 &mut self.inner
211 }
212}
213
214#[derive(Copy, Clone)]
216pub(crate) struct Icmpv6StateBuilder {
217 errors_per_second: u64,
218}
219
220impl Default for Icmpv6StateBuilder {
221 fn default() -> Icmpv6StateBuilder {
222 Icmpv6StateBuilder { errors_per_second: DEFAULT_ERRORS_PER_SECOND }
223 }
224}
225
226impl Icmpv6StateBuilder {
227 pub(crate) fn build<BT: IcmpBindingsTypes>(self) -> Icmpv6State<BT> {
228 Icmpv6State {
229 inner: IcmpState {
230 error_send_bucket: Mutex::new(IpMarked::new(TokenBucket::new(
231 self.errors_per_second,
232 ))),
233 tx_counters: Default::default(),
234 rx_counters: Default::default(),
235 },
236 ndp_counters: Default::default(),
237 }
238 }
239}
240
241pub struct Icmpv6State<BT: IcmpBindingsTypes> {
243 pub inner: IcmpState<Ipv6, BT>,
245 pub ndp_counters: NdpCounters,
247}
248
249impl<BT: IcmpBindingsTypes> AsRef<IcmpState<Ipv6, BT>> for Icmpv6State<BT> {
250 fn as_ref(&self) -> &IcmpState<Ipv6, BT> {
251 &self.inner
252 }
253}
254
255impl<BT: IcmpBindingsTypes> AsMut<IcmpState<Ipv6, BT>> for Icmpv6State<BT> {
256 fn as_mut(&mut self) -> &mut IcmpState<Ipv6, BT> {
257 &mut self.inner
258 }
259}
260
261pub trait IcmpHandlerIpExt: IpExt {
263 type IcmpError: IcmpError
265 + GenericOverIp<Self, Type = Self::IcmpError>
266 + GenericOverIp<Ipv4, Type = Icmpv4Error>
267 + GenericOverIp<Ipv6, Type = Icmpv6Error>;
268
269 fn received_source_as_icmp_source(src: Self::RecvSrcAddr) -> Option<SocketIpAddr<Self::Addr>>;
271
272 fn nud_failure_icmp_error() -> Self::IcmpError;
274}
275
276impl IcmpHandlerIpExt for Ipv4 {
277 type IcmpError = Icmpv4Error;
278
279 fn received_source_as_icmp_source(src: Ipv4SourceAddr) -> Option<SocketIpAddr<Ipv4Addr>> {
280 SocketIpAddr::new_from_ipv4_source(src)
281 }
282
283 fn nud_failure_icmp_error() -> Icmpv4Error {
284 Icmpv4Error::HostUnreachable
285 }
286}
287
288impl IcmpHandlerIpExt for Ipv6 {
289 type IcmpError = Icmpv6Error;
290
291 fn received_source_as_icmp_source(src: Ipv6SourceAddr) -> Option<SocketIpAddr<Ipv6Addr>> {
292 SocketIpAddr::new_from_ipv6_source(src)
293 }
294
295 fn nud_failure_icmp_error() -> Icmpv6Error {
296 Icmpv6Error::AddressUnreachable
297 }
298}
299
300pub trait IcmpError: Sized + Debug + PartialEq {
302 fn port_unreachable() -> Self;
304 fn ttl_expired() -> Self;
306 fn mtu_exceeded(mtu: Mtu) -> Option<Self>;
309}
310
311#[derive(Debug, PartialEq)]
313pub enum Icmpv4Error {
314 ParameterProblem {
316 code: Icmpv4ParameterProblemCode,
318 pointer: u8,
320 },
321 TtlExpired,
323 NetUnreachable,
325 ProtocolUnreachable,
327 PortUnreachable,
329 HostUnreachable,
331 NetworkProhibited,
333 HostProhibited,
335 AdminProhibited,
337}
338
339impl IcmpError for Icmpv4Error {
340 fn port_unreachable() -> Self {
341 Icmpv4Error::PortUnreachable
342 }
343 fn ttl_expired() -> Self {
344 Icmpv4Error::TtlExpired
345 }
346 fn mtu_exceeded(_mtu: Mtu) -> Option<Self> {
347 None
348 }
349}
350
351impl<I: IcmpHandlerIpExt> GenericOverIp<I> for Icmpv4Error {
352 type Type = I::IcmpError;
353}
354
355enum Icmpv4ErrorMessage {
358 TimeExceeded {
359 message: IcmpTimeExceeded,
360 code: <IcmpTimeExceeded as IcmpMessage<Ipv4>>::Code,
361 },
362 ParameterProblem {
363 message: Icmpv4ParameterProblem,
364 code: <Icmpv4ParameterProblem as IcmpMessage<Ipv4>>::Code,
365 },
366 DestUnreachable {
367 message: IcmpDestUnreachable,
368 code: <IcmpDestUnreachable as IcmpMessage<Ipv4>>::Code,
369 },
370}
371
372impl Icmpv4Error {
373 fn update_counters(&self, counters: &IcmpTxCounters<Ipv4>) {
374 match self {
375 Icmpv4Error::ParameterProblem { code, pointer: _ } => {
376 counters.parameter_problem.increment_code(*code);
377 }
378 Icmpv4Error::TtlExpired => {
379 counters.time_exceeded.increment_code(Icmpv4TimeExceededCode::TtlExpired);
380 }
381 Icmpv4Error::NetUnreachable => {
382 counters
383 .dest_unreachable
384 .increment_code(Icmpv4DestUnreachableCode::DestNetworkUnreachable);
385 }
386 Icmpv4Error::ProtocolUnreachable => {
387 counters
388 .dest_unreachable
389 .increment_code(Icmpv4DestUnreachableCode::DestProtocolUnreachable);
390 }
391 Icmpv4Error::PortUnreachable => {
392 counters
393 .dest_unreachable
394 .increment_code(Icmpv4DestUnreachableCode::DestPortUnreachable);
395 }
396 Icmpv4Error::HostUnreachable => {
397 counters
398 .dest_unreachable
399 .increment_code(Icmpv4DestUnreachableCode::DestHostUnreachable);
400 }
401 Icmpv4Error::NetworkProhibited => {
402 counters
403 .dest_unreachable
404 .increment_code(Icmpv4DestUnreachableCode::NetworkAdministrativelyProhibited);
405 }
406 Icmpv4Error::HostProhibited => {
407 counters
408 .dest_unreachable
409 .increment_code(Icmpv4DestUnreachableCode::HostAdministrativelyProhibited);
410 }
411 Icmpv4Error::AdminProhibited => {
412 counters
413 .dest_unreachable
414 .increment_code(Icmpv4DestUnreachableCode::CommAdministrativelyProhibited);
415 }
416 }
417 }
418
419 fn create_message(&self) -> Icmpv4ErrorMessage {
420 match self {
421 Icmpv4Error::ParameterProblem { code, pointer } => {
422 Icmpv4ErrorMessage::ParameterProblem {
423 message: Icmpv4ParameterProblem::new(*pointer),
424 code: *code,
425 }
426 }
427 Icmpv4Error::TtlExpired => Icmpv4ErrorMessage::TimeExceeded {
428 message: IcmpTimeExceeded::default(),
429 code: Icmpv4TimeExceededCode::TtlExpired,
430 },
431 Icmpv4Error::NetUnreachable => Icmpv4ErrorMessage::DestUnreachable {
432 message: IcmpDestUnreachable::default(),
433 code: Icmpv4DestUnreachableCode::DestNetworkUnreachable,
434 },
435 Icmpv4Error::ProtocolUnreachable => Icmpv4ErrorMessage::DestUnreachable {
436 message: IcmpDestUnreachable::default(),
437 code: Icmpv4DestUnreachableCode::DestProtocolUnreachable,
438 },
439 Icmpv4Error::PortUnreachable => Icmpv4ErrorMessage::DestUnreachable {
440 message: IcmpDestUnreachable::default(),
441 code: Icmpv4DestUnreachableCode::DestPortUnreachable,
442 },
443 Icmpv4Error::HostUnreachable => Icmpv4ErrorMessage::DestUnreachable {
444 message: IcmpDestUnreachable::default(),
445 code: Icmpv4DestUnreachableCode::DestHostUnreachable,
446 },
447 Icmpv4Error::NetworkProhibited => Icmpv4ErrorMessage::DestUnreachable {
448 message: IcmpDestUnreachable::default(),
449 code: Icmpv4DestUnreachableCode::NetworkAdministrativelyProhibited,
450 },
451 Icmpv4Error::HostProhibited => Icmpv4ErrorMessage::DestUnreachable {
452 message: IcmpDestUnreachable::default(),
453 code: Icmpv4DestUnreachableCode::HostAdministrativelyProhibited,
454 },
455 Icmpv4Error::AdminProhibited => Icmpv4ErrorMessage::DestUnreachable {
456 message: IcmpDestUnreachable::default(),
457 code: Icmpv4DestUnreachableCode::CommAdministrativelyProhibited,
458 },
459 }
460 }
461}
462
463impl<I: IcmpHandlerIpExt> GenericOverIp<I> for Icmpv6Error {
464 type Type = I::IcmpError;
465}
466
467#[derive(Debug, PartialEq, Eq)]
469pub enum Icmpv6Error {
470 ParameterProblem {
472 code: Icmpv6ParameterProblemCode,
474 pointer: u32,
476 allow_dst_multicast: bool,
478 },
479 TtlExpired,
481 NetUnreachable,
483 PacketTooBig {
485 mtu: Mtu,
487 },
488 PortUnreachable,
490 AddressUnreachable,
492 RejectRoute,
494 SourceAddressPolicyFailed,
496 AdminProhibited,
498}
499
500impl IcmpError for Icmpv6Error {
501 fn port_unreachable() -> Self {
502 Icmpv6Error::PortUnreachable
503 }
504 fn ttl_expired() -> Self {
505 Icmpv6Error::TtlExpired
506 }
507 fn mtu_exceeded(mtu: Mtu) -> Option<Self> {
508 Some(Icmpv6Error::PacketTooBig { mtu })
509 }
510}
511
512enum Icmpv6ErrorMessage {
515 TimeExceeded {
516 message: IcmpTimeExceeded,
517 code: <IcmpTimeExceeded as IcmpMessage<Ipv6>>::Code,
518 },
519 PacketTooBig {
520 message: Icmpv6PacketTooBig,
521 code: <Icmpv6PacketTooBig as IcmpMessage<Ipv6>>::Code,
522 },
523 ParameterProblem {
524 message: Icmpv6ParameterProblem,
525 code: <Icmpv6ParameterProblem as IcmpMessage<Ipv6>>::Code,
526 },
527 DestUnreachable {
528 message: IcmpDestUnreachable,
529 code: <IcmpDestUnreachable as IcmpMessage<Ipv6>>::Code,
530 },
531}
532
533impl Icmpv6Error {
534 fn update_counters(&self, counters: &IcmpTxCounters<Ipv6>) {
535 match self {
536 Icmpv6Error::ParameterProblem { code, pointer: _, allow_dst_multicast: _ } => {
537 counters.parameter_problem.increment_code(*code);
538 }
539 Icmpv6Error::TtlExpired => {
540 counters.time_exceeded.increment_code(Icmpv6TimeExceededCode::HopLimitExceeded);
541 }
542 Icmpv6Error::NetUnreachable => {
543 counters.dest_unreachable.increment_code(Icmpv6DestUnreachableCode::NoRoute);
544 }
545 Icmpv6Error::PacketTooBig { mtu: _ } => {
546 counters.packet_too_big.increment();
547 }
548 Icmpv6Error::PortUnreachable => {
549 counters
550 .dest_unreachable
551 .increment_code(Icmpv6DestUnreachableCode::PortUnreachable);
552 }
553 Icmpv6Error::AddressUnreachable => {
554 counters
555 .dest_unreachable
556 .increment_code(Icmpv6DestUnreachableCode::AddrUnreachable);
557 }
558 Icmpv6Error::RejectRoute => {
559 counters.dest_unreachable.increment_code(Icmpv6DestUnreachableCode::RejectRoute);
560 }
561 Icmpv6Error::SourceAddressPolicyFailed => {
562 counters
563 .dest_unreachable
564 .increment_code(Icmpv6DestUnreachableCode::SrcAddrFailedPolicy);
565 }
566 Icmpv6Error::AdminProhibited => {
567 counters
568 .dest_unreachable
569 .increment_code(Icmpv6DestUnreachableCode::CommAdministrativelyProhibited);
570 }
571 }
572 }
573
574 fn create_message(&self) -> Icmpv6ErrorMessage {
575 match self {
576 Icmpv6Error::ParameterProblem { code, pointer, allow_dst_multicast: _ } => {
577 Icmpv6ErrorMessage::ParameterProblem {
578 message: Icmpv6ParameterProblem::new(*pointer),
579 code: *code,
580 }
581 }
582 Icmpv6Error::TtlExpired => Icmpv6ErrorMessage::TimeExceeded {
583 message: IcmpTimeExceeded::default(),
584 code: Icmpv6TimeExceededCode::HopLimitExceeded,
585 },
586 Icmpv6Error::NetUnreachable => Icmpv6ErrorMessage::DestUnreachable {
587 message: IcmpDestUnreachable::default(),
588 code: Icmpv6DestUnreachableCode::NoRoute,
589 },
590 Icmpv6Error::PacketTooBig { mtu } => Icmpv6ErrorMessage::PacketTooBig {
591 message: Icmpv6PacketTooBig::new((*mtu).into()),
592 code: IcmpZeroCode,
593 },
594 Icmpv6Error::PortUnreachable => Icmpv6ErrorMessage::DestUnreachable {
595 message: IcmpDestUnreachable::default(),
596 code: Icmpv6DestUnreachableCode::PortUnreachable,
597 },
598 Icmpv6Error::AddressUnreachable => Icmpv6ErrorMessage::DestUnreachable {
599 message: IcmpDestUnreachable::default(),
600 code: Icmpv6DestUnreachableCode::AddrUnreachable,
601 },
602 Icmpv6Error::RejectRoute => Icmpv6ErrorMessage::DestUnreachable {
603 message: IcmpDestUnreachable::default(),
604 code: Icmpv6DestUnreachableCode::RejectRoute,
605 },
606 Icmpv6Error::SourceAddressPolicyFailed => Icmpv6ErrorMessage::DestUnreachable {
607 message: IcmpDestUnreachable::default(),
608 code: Icmpv6DestUnreachableCode::SrcAddrFailedPolicy,
609 },
610 Icmpv6Error::AdminProhibited => Icmpv6ErrorMessage::DestUnreachable {
611 message: IcmpDestUnreachable::default(),
612 code: Icmpv6DestUnreachableCode::CommAdministrativelyProhibited,
613 },
614 }
615 }
616
617 fn allow_dst_multicast(&self) -> bool {
618 match self {
631 Icmpv6Error::ParameterProblem { allow_dst_multicast, code, pointer: _ } => {
632 assert!(
633 !allow_dst_multicast
634 || *code == Icmpv6ParameterProblemCode::UnrecognizedIpv6Option
635 );
636 *allow_dst_multicast
637 }
638 Icmpv6Error::PacketTooBig { .. } => true,
639 _ => false,
640 }
641 }
642}
643
644pub trait IcmpErrorHandler<I: IcmpHandlerIpExt, BC>: DeviceIdContext<AnyDevice> {
646 fn send_icmp_error_message<B: BufferMut>(
653 &mut self,
654 bindings_ctx: &mut BC,
655 device: Option<&Self::DeviceId>,
656 frame_dst: Option<FrameDestination>,
657 src_ip: SocketIpAddr<I::Addr>,
658 dst_ip: SocketIpAddr<I::Addr>,
659 original_packet: B,
660 error: I::IcmpError,
661 header_len: usize,
662 proto: I::Proto,
663 marks: &Marks,
664 );
665}
666
667impl<BC: IcmpBindingsContext, CC: IcmpSendContext<Ipv4, BC> + CounterContext<IcmpTxCounters<Ipv4>>>
668 IcmpErrorHandler<Ipv4, BC> for CC
669{
670 fn send_icmp_error_message<B: BufferMut>(
671 &mut self,
672 bindings_ctx: &mut BC,
673 device: Option<&CC::DeviceId>,
674 frame_dst: Option<FrameDestination>,
675 src_ip: SocketIpAddr<Ipv4Addr>,
676 dst_ip: SocketIpAddr<Ipv4Addr>,
677 original_packet: B,
678 icmp_error: Icmpv4Error,
679 header_len: usize,
680 proto: Ipv4Proto,
681 marks: &Marks,
682 ) {
683 if is_icmp_error_or_redirect_message::<Ipv4>(proto, &original_packet.as_ref()[header_len..])
686 {
687 return;
688 }
689
690 icmp_error.update_counters(&self.counters());
691 send_icmpv4_error_message(
692 self,
693 bindings_ctx,
694 device,
695 frame_dst,
696 src_ip,
697 dst_ip,
698 icmp_error.create_message(),
699 original_packet,
700 header_len,
701 marks,
702 );
703 }
704}
705
706impl<BC: IcmpBindingsContext, CC: IcmpSendContext<Ipv6, BC> + CounterContext<IcmpTxCounters<Ipv6>>>
707 IcmpErrorHandler<Ipv6, BC> for CC
708{
709 fn send_icmp_error_message<B: BufferMut>(
710 &mut self,
711 bindings_ctx: &mut BC,
712 device: Option<&CC::DeviceId>,
713 frame_dst: Option<FrameDestination>,
714 src_ip: SocketIpAddr<Ipv6Addr>,
715 dst_ip: SocketIpAddr<Ipv6Addr>,
716 original_packet: B,
717 error: Icmpv6Error,
718 header_len: usize,
719 proto: Ipv6Proto,
720 marks: &Marks,
721 ) {
722 if is_icmp_error_or_redirect_message::<Ipv6>(proto, &original_packet.as_ref()[header_len..])
725 {
726 return;
727 }
728
729 error.update_counters(&self.counters());
730 send_icmpv6_error_message(
731 self,
732 bindings_ctx,
733 device,
734 frame_dst,
735 src_ip,
736 dst_ip,
737 error.create_message(),
738 original_packet,
739 error.allow_dst_multicast(),
740 marks,
741 )
742 }
743}
744
745pub trait IcmpBindingsContext: InstantContext + RngContext + IcmpBindingsTypes {}
748impl<BC> IcmpBindingsContext for BC where
749 BC: InstantContext + RngContext + IcmpBindingsTypes + IcmpBindingsTypes
750{
751}
752
753pub trait IcmpBindingsTypes: InstantBindingsTypes + TxMetadataBindingsTypes {}
755impl<BT: InstantBindingsTypes + TxMetadataBindingsTypes> IcmpBindingsTypes for BT {}
756
757pub trait IcmpStateContext {}
765
766pub trait EchoTransportContextMarker {}
776
777pub trait InnerIcmpContext<I, BC>: IpSocketHandler<I, BC>
780where
781 I: IpLayerIpExt,
782 BC: IcmpBindingsTypes,
783{
784 type EchoTransportContext: IpTransportContext<I, BC, Self> + EchoTransportContextMarker;
787
788 fn receive_icmp_error(
818 &mut self,
819 bindings_ctx: &mut BC,
820 device: &Self::DeviceId,
821 original_src_ip: Option<SpecifiedAddr<I::Addr>>,
822 original_dst_ip: SpecifiedAddr<I::Addr>,
823 original_proto: I::Proto,
824 original_body: &[u8],
825 err: I::ErrorCode,
826 );
827}
828
829pub trait InnerIcmpv4Context<BC: IcmpBindingsTypes>: InnerIcmpContext<Ipv4, BC> {
833 fn should_send_timestamp_reply(&self) -> bool;
835}
836
837pub trait IcmpSendContext<I, BC>: IpSocketHandler<I, BC>
839where
840 I: IpLayerIpExt,
841 BC: IcmpBindingsTypes,
842{
843 fn with_error_send_bucket_mut<O, F: FnOnce(&mut TokenBucket<BC::Instant>) -> O>(
846 &mut self,
847 cb: F,
848 ) -> O;
849}
850
851macro_rules! try_send_error {
865 ($core_ctx:expr, $bindings_ctx:expr, $e:expr) => {{
866 let send = $core_ctx.with_error_send_bucket_mut(|error_send_bucket| {
867 error_send_bucket.try_take($bindings_ctx)
868 });
869
870 if send {
871 $core_ctx.counters().error.increment();
872 $e
873 } else {
874 trace!("ip::icmp::try_send_error!: dropping rate-limited ICMP error message");
875 Ok(())
876 }
877 }};
878}
879
880pub enum IcmpIpTransportContext {}
882
883fn receive_ip_transport_icmp_error<
884 I: IpLayerIpExt,
885 CC: InnerIcmpContext<I, BC> + CounterContext<IcmpRxCounters<I>>,
886 BC: IcmpBindingsContext,
887>(
888 core_ctx: &mut CC,
889 bindings_ctx: &mut BC,
890 device: &CC::DeviceId,
891 original_src_ip: Option<SpecifiedAddr<I::Addr>>,
892 original_dst_ip: SpecifiedAddr<I::Addr>,
893 original_body: &[u8],
894 err: I::ErrorCode,
895) {
896 core_ctx.counters().error_delivered_to_transport_layer.increment();
897 trace!("IcmpIpTransportContext::receive_icmp_error({:?})", err);
898
899 let mut parse_body = original_body;
900 match parse_body.parse::<IcmpPacketRaw<I, _, IcmpEchoRequest>>() {
901 Ok(_echo_request) => (),
904 Err(_) => {
905 return;
909 }
910 }
911
912 <CC::EchoTransportContext as IpTransportContext<I, BC, CC>>::receive_icmp_error(
913 core_ctx,
914 bindings_ctx,
915 device,
916 original_src_ip,
917 original_dst_ip,
918 original_body,
919 err,
920 );
921}
922
923impl<
924 BC: IcmpBindingsContext,
925 CC: InnerIcmpv4Context<BC>
926 + PmtuHandler<Ipv4, BC>
927 + CounterContext<IcmpRxCounters<Ipv4>>
928 + CounterContext<IcmpTxCounters<Ipv4>>,
929> IpTransportContext<Ipv4, BC, CC> for IcmpIpTransportContext
930{
931 type EarlyDemuxSocket = Never;
932
933 fn early_demux<B: ParseBuffer>(
934 _core_ctx: &mut CC,
935 _device: &CC::DeviceId,
936 _src_ip: Ipv4Addr,
937 _dst_ip: Ipv4Addr,
938 _buffer: B,
939 ) -> Option<Self::EarlyDemuxSocket> {
940 None
941 }
942
943 fn receive_icmp_error(
944 core_ctx: &mut CC,
945 bindings_ctx: &mut BC,
946 device: &CC::DeviceId,
947 original_src_ip: Option<SpecifiedAddr<Ipv4Addr>>,
948 original_dst_ip: SpecifiedAddr<Ipv4Addr>,
949 original_body: &[u8],
950 err: Icmpv4ErrorCode,
951 ) {
952 receive_ip_transport_icmp_error(
953 core_ctx,
954 bindings_ctx,
955 device,
956 original_src_ip,
957 original_dst_ip,
958 original_body,
959 err,
960 )
961 }
962
963 fn receive_ip_packet<B: BufferMut, H: IpHeaderInfo<Ipv4>>(
964 core_ctx: &mut CC,
965 bindings_ctx: &mut BC,
966 device: &CC::DeviceId,
967 src_ip: Ipv4SourceAddr,
968 dst_ip: SpecifiedAddr<Ipv4Addr>,
969 mut buffer: B,
970 info: &mut LocalDeliveryPacketInfo<Ipv4, H>,
971 _early_demux_socket: Option<Never>,
972 ) -> Result<(), (B, Icmpv4Error)> {
973 let LocalDeliveryPacketInfo { meta, header_info: _, marks } = info;
974 let ReceiveIpPacketMeta { broadcast: _, transparent_override, parsing_context: _ } = meta;
975 if let Some(delivery) = transparent_override {
976 unreachable!(
977 "cannot perform transparent local delivery {delivery:?} to an ICMP socket; \
978 transparent proxy rules can only be configured for TCP and UDP packets"
979 );
980 }
981
982 trace!(
983 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet({}, {})",
984 src_ip, dst_ip
985 );
986 let packet =
987 match buffer.parse_with::<_, Icmpv4Packet<_>>(IcmpParseArgs::new(src_ip, dst_ip)) {
988 Ok(packet) => packet,
989 Err(_) => return Ok(()), };
991
992 match packet {
993 Icmpv4Packet::EchoRequest(echo_request) => {
994 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx).echo_request.increment();
995
996 if let Ipv4SourceAddr::Specified(src_ip) = src_ip {
997 let req = *echo_request.message();
998 let code = echo_request.code();
999 let (local_ip, remote_ip) = (dst_ip, src_ip);
1000 debug!(
1001 "replying to ICMP echo request from {remote_ip} to {local_ip}%{device:?}: \
1002 id={}, seq={}",
1003 req.id(),
1004 req.seq()
1005 );
1006 send_icmp_reply(
1007 core_ctx,
1008 bindings_ctx,
1009 device,
1010 SocketIpAddr::new_ipv4_specified(remote_ip.get()),
1011 SocketIpAddr::new_ipv4_specified(local_ip),
1012 |src_ip| {
1013 IcmpPacketBuilder::<Ipv4, _>::new(src_ip, *remote_ip, code, req.reply())
1014 .wrap_body(buffer)
1015 },
1016 &WithMarks(marks),
1017 );
1018 } else {
1019 trace!(
1020 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
1021 Received echo request with an unspecified source address"
1022 );
1023 }
1024 }
1025 Icmpv4Packet::EchoReply(echo_reply) => {
1026 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx).echo_reply.increment();
1027 trace!(
1028 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
1029 Received an EchoReply message"
1030 );
1031 let parse_metadata = echo_reply.parse_metadata();
1032 buffer.undo_parse(parse_metadata);
1033 return <CC::EchoTransportContext
1034 as IpTransportContext<Ipv4, BC, CC>>::receive_ip_packet(
1035 core_ctx,
1036 bindings_ctx,
1037 device,
1038 src_ip,
1039 dst_ip,
1040 buffer,
1041 info,
1042 None,
1043 );
1044 }
1045 Icmpv4Packet::TimestampRequest(timestamp_request) => {
1046 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx)
1047 .timestamp_request
1048 .increment();
1049 if let Ipv4SourceAddr::Specified(src_ip) = src_ip {
1050 if core_ctx.should_send_timestamp_reply() {
1051 trace!(
1052 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1053 receive_ip_packet: Responding to Timestamp Request message"
1054 );
1055 const NOW: u32 = 0x80000000;
1074 let reply = timestamp_request.message().reply(NOW, NOW);
1075 let (local_ip, remote_ip) = (dst_ip, src_ip);
1076 buffer.shrink_front_to(0);
1083 send_icmp_reply(
1084 core_ctx,
1085 bindings_ctx,
1086 device,
1087 SocketIpAddr::new_ipv4_specified(remote_ip.get()),
1088 SocketIpAddr::new_ipv4_specified(local_ip),
1089 |src_ip| {
1090 IcmpPacketBuilder::<Ipv4, _>::new(
1091 src_ip,
1092 *remote_ip,
1093 IcmpZeroCode,
1094 reply,
1095 )
1096 .wrap_body(buffer)
1097 },
1098 &WithMarks(marks),
1099 );
1100 } else {
1101 trace!(
1102 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1103 receive_ip_packet: Silently ignoring Timestamp Request message"
1104 );
1105 }
1106 } else {
1107 trace!(
1108 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1109 receive_ip_packet: Received timestamp request with an unspecified source \
1110 address"
1111 );
1112 }
1113 }
1114 Icmpv4Packet::TimestampReply(_) => {
1115 debug!(
1118 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
1119 Received unsolicited Timestamp Reply message"
1120 );
1121 }
1122 Icmpv4Packet::DestUnreachable(dest_unreachable) => {
1123 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx)
1124 .dest_unreachable
1125 .increment_code(dest_unreachable.code());
1126 trace!(
1127 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
1128 Received a Destination Unreachable message"
1129 );
1130
1131 let error = if dest_unreachable.code()
1132 == Icmpv4DestUnreachableCode::FragmentationRequired
1133 {
1134 let mtu = if let Some(next_hop_mtu) = dest_unreachable.message().next_hop_mtu()
1135 {
1136 core_ctx.update_pmtu_if_less(
1146 bindings_ctx,
1147 dst_ip.get(),
1148 src_ip.get(),
1149 Mtu::new(u32::from(next_hop_mtu.get())),
1150 )
1151 } else {
1152 let (original_packet_buf, inner_body) = dest_unreachable.body().bytes();
1174 debug_assert!(inner_body.is_none());
1176 if original_packet_buf.len() >= 4 {
1177 let total_len =
1181 u16::from_be_bytes(original_packet_buf[2..4].try_into().unwrap());
1182
1183 trace!(
1184 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1185 receive_ip_packet: Next-Hop MTU is 0 so using the next best PMTU \
1186 value from {total_len}"
1187 );
1188
1189 core_ctx.update_pmtu_next_lower(
1190 bindings_ctx,
1191 dst_ip.get(),
1192 src_ip.get(),
1193 Mtu::new(u32::from(total_len)),
1194 )
1195 } else {
1196 trace!(
1201 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1202 receive_ip_packet: Original packet buf is too small to get \
1203 original packet len so ignoring"
1204 );
1205 None
1206 }
1207 };
1208 mtu.and_then(|mtu| {
1209 let mtu = u16::try_from(mtu.get()).unwrap_or(u16::MAX);
1210 let mtu = NonZeroU16::new(mtu)?;
1211 Some(Icmpv4ErrorCode::DestUnreachable(
1212 dest_unreachable.code(),
1213 IcmpDestUnreachable::new_for_frag_req(mtu),
1214 ))
1215 })
1216 } else {
1217 Some(Icmpv4ErrorCode::DestUnreachable(
1218 dest_unreachable.code(),
1219 *dest_unreachable.message(),
1220 ))
1221 };
1222
1223 if let Some(error) = error {
1224 receive_icmpv4_error(core_ctx, bindings_ctx, device, &dest_unreachable, error);
1225 }
1226 }
1227 Icmpv4Packet::TimeExceeded(time_exceeded) => {
1228 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx)
1229 .time_exceeded
1230 .increment_code(time_exceeded.code());
1231 trace!(
1232 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
1233 Received a Time Exceeded message"
1234 );
1235
1236 receive_icmpv4_error(
1237 core_ctx,
1238 bindings_ctx,
1239 device,
1240 &time_exceeded,
1241 Icmpv4ErrorCode::TimeExceeded(time_exceeded.code()),
1242 );
1243 }
1244 Icmpv4Packet::Redirect(_) => {
1246 debug!(
1247 "Unimplemented: <IcmpIpTransportContext as IpTransportContext<Ipv4>>::\
1248 receive_ip_packet::redirect"
1249 )
1250 }
1251 Icmpv4Packet::ParameterProblem(parameter_problem) => {
1252 CounterContext::<IcmpRxCounters<Ipv4>>::counters(core_ctx)
1253 .parameter_problem
1254 .increment_code(parameter_problem.code());
1255 trace!(
1256 "<IcmpIpTransportContext as IpTransportContext<Ipv4>>::receive_ip_packet: \
1257 Received a Parameter Problem message"
1258 );
1259
1260 receive_icmpv4_error(
1261 core_ctx,
1262 bindings_ctx,
1263 device,
1264 ¶meter_problem,
1265 Icmpv4ErrorCode::ParameterProblem(parameter_problem.code()),
1266 );
1267 }
1268 }
1269
1270 Ok(())
1271 }
1272}
1273
1274#[allow(missing_docs)]
1277pub enum NdpMessage {
1278 NeighborSolicitation {
1279 message: NeighborSolicitation,
1280 code: <NeighborSolicitation as IcmpMessage<Ipv6>>::Code,
1281 },
1282
1283 RouterSolicitation {
1284 message: RouterSolicitation,
1285 code: <RouterSolicitation as IcmpMessage<Ipv6>>::Code,
1286 },
1287
1288 NeighborAdvertisement {
1289 message: NeighborAdvertisement,
1290 code: <NeighborAdvertisement as IcmpMessage<Ipv6>>::Code,
1291 },
1292}
1293
1294pub fn send_ndp_packet<BC, CC, S>(
1296 core_ctx: &mut CC,
1297 bindings_ctx: &mut BC,
1298 device_id: &CC::DeviceId,
1299 src_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1300 dst_ip: SpecifiedAddr<Ipv6Addr>,
1301 body: S,
1302 message: NdpMessage,
1303) -> Result<(), IpSendFrameError<S>>
1304where
1305 CC: IpLayerHandler<Ipv6, BC>,
1306 S: NetworkSerializer + NetworkPartialSerializer,
1307 S::Buffer: BufferMut,
1308{
1309 macro_rules! send {
1310 ($message:expr, $code:expr) => {{
1311 let mut ser = IcmpPacketBuilder::<Ipv6, _>::new(
1313 src_ip.map_or(Ipv6::UNSPECIFIED_ADDRESS, |a| a.get()),
1314 dst_ip.get(),
1315 $code,
1316 $message,
1317 )
1318 .wrap_body(body);
1319 match IpLayerHandler::<Ipv6, _>::send_ip_packet_from_device(
1320 core_ctx,
1321 bindings_ctx,
1322 SendIpPacketMeta {
1323 device: device_id,
1324 src_ip,
1325 dst_ip,
1326 destination: IpPacketDestination::from_addr(dst_ip),
1327 ttl: NonZeroU8::new(REQUIRED_NDP_IP_PACKET_HOP_LIMIT),
1328 proto: Ipv6Proto::Icmpv6,
1329 mtu: Mtu::no_limit(),
1330 dscp_and_ecn: DscpAndEcn::default(),
1331 },
1332 DynTransportSerializer::new(&mut ser),
1333 ) {
1334 Ok(()) => Ok(()),
1335 Err(e) => Err(e
1336 .map_serializer(|s| {
1337 let _: DynTransportSerializer<'_, _> = s;
1339 })
1340 .map_serializer(|()| ser.into_inner())),
1341 }
1342 }};
1343 }
1344
1345 match message {
1346 NdpMessage::NeighborSolicitation { message, code } => send!(message, code),
1347 NdpMessage::RouterSolicitation { message, code } => send!(message, code),
1348 NdpMessage::NeighborAdvertisement { message, code } => send!(message, code),
1349 }
1350}
1351
1352fn send_neighbor_advertisement<
1353 BC,
1354 CC: Ipv6DeviceHandler<BC>
1355 + IpDeviceHandler<Ipv6, BC>
1356 + IpLayerHandler<Ipv6, BC>
1357 + CounterContext<NdpCounters>,
1358>(
1359 core_ctx: &mut CC,
1360 bindings_ctx: &mut BC,
1361 device_id: &CC::DeviceId,
1362 solicited: bool,
1363 device_addr: UnicastAddr<Ipv6Addr>,
1364 dst_ip: SpecifiedAddr<Ipv6Addr>,
1365) {
1366 core_ctx.counters().tx.neighbor_advertisement.increment();
1367 debug!("send_neighbor_advertisement from {:?} to {:?}", device_addr, dst_ip);
1368 debug_assert!(dst_ip.is_valid_unicast() || (!solicited && dst_ip.is_multicast()));
1375
1376 let src_ll = core_ctx.get_link_layer_addr(&device_id);
1383
1384 let advertisement = NeighborAdvertisement::new(
1386 core_ctx.is_router_device(&device_id),
1387 solicited,
1388 true, device_addr.get(),
1401 );
1402 let _: Result<(), _> = send_ndp_packet(
1403 core_ctx,
1404 bindings_ctx,
1405 &device_id,
1406 Some(device_addr.into_specified()),
1407 dst_ip,
1408 OptionSequenceBuilder::new(
1409 src_ll
1410 .as_ref()
1411 .map(Ipv6LinkLayerAddr::as_bytes)
1412 .map(NdpOptionBuilder::TargetLinkLayerAddress)
1413 .iter(),
1414 )
1415 .into_serializer(),
1416 NdpMessage::NeighborAdvertisement { message: advertisement, code: IcmpZeroCode },
1417 );
1418}
1419
1420fn receive_ndp_packet<
1421 B: SplitByteSlice,
1422 BC: IcmpBindingsContext + NdpBindingsContext<CC::DeviceId>,
1423 CC: InnerIcmpContext<Ipv6, BC>
1424 + Ipv6DeviceHandler<BC>
1425 + IpDeviceHandler<Ipv6, BC>
1426 + IpDeviceIngressStateContext<Ipv6>
1427 + NudIpHandler<Ipv6, BC>
1428 + IpLayerHandler<Ipv6, BC>
1429 + CounterContext<NdpCounters>,
1430 H: IpHeaderInfo<Ipv6>,
1431>(
1432 core_ctx: &mut CC,
1433 bindings_ctx: &mut BC,
1434 device_id: &CC::DeviceId,
1435 src_ip: Ipv6SourceAddr,
1436 dst_ip: SpecifiedAddr<Ipv6Addr>,
1437 packet: NdpPacket<B>,
1438 header_info: &H,
1439) {
1440 if header_info.hop_limit() != REQUIRED_NDP_IP_PACKET_HOP_LIMIT {
1458 trace!("dropping NDP packet from {src_ip} with invalid hop limit");
1459 return;
1460 }
1461
1462 match packet {
1463 NdpPacket::RouterSolicitation(_) => {}
1464 NdpPacket::Redirect(_) => {}
1466 NdpPacket::NeighborSolicitation(ref p) => {
1467 let target_address = p.message().target_address();
1474 let target_address = match UnicastAddr::new(*target_address) {
1475 Some(a) => a,
1476 None => {
1477 trace!(
1478 "dropping NS from {} with non-unicast target={:?}",
1479 src_ip, target_address
1480 );
1481 return;
1482 }
1483 };
1484
1485 let (source_link_addr, nonce) = p.body().iter().fold(
1487 (None, None),
1488 |(found_source_link_addr, found_nonce), option| {
1489 match option {
1490 NdpOption::Nonce(nonce) => (found_source_link_addr, Some(nonce)),
1491 NdpOption::SourceLinkLayerAddress(source_link_addr) => {
1492 (Some(source_link_addr), found_nonce)
1493 }
1494 NdpOption::Mtu(_)
1502 | NdpOption::PrefixInformation(_)
1503 | NdpOption::RecursiveDnsServer(_)
1504 | NdpOption::RedirectedHeader { .. }
1505 | NdpOption::RouteInformation(_)
1506 | NdpOption::TargetLinkLayerAddress(_) => {
1507 (found_source_link_addr, found_nonce)
1508 }
1509 }
1510 },
1511 );
1512
1513 if src_ip == Ipv6SourceAddr::Unspecified {
1514 if target_address.get().to_solicited_node_address().get() != dst_ip.get() {
1523 debug!(
1524 "dropping NS from {} for {} with invalid IPv6 dst ({}).",
1525 src_ip, target_address, dst_ip
1526 );
1527 return;
1528 }
1529 if let Some(addr) = source_link_addr {
1534 debug!(
1535 "dropping NS from {} for {} with source link-layer addr option ({:?}).",
1536 src_ip, target_address, addr
1537 );
1538 return;
1539 }
1540 }
1541
1542 core_ctx.counters().rx.neighbor_solicitation.increment();
1543
1544 match src_ip {
1545 Ipv6SourceAddr::Unspecified => {
1546 match IpDeviceHandler::handle_received_dad_packet(
1556 core_ctx,
1557 bindings_ctx,
1558 &device_id,
1559 target_address.into_specified(),
1560 nonce,
1561 ) {
1562 Some(IpAddressState::Assigned) => {
1563 send_neighbor_advertisement(
1567 core_ctx,
1568 bindings_ctx,
1569 &device_id,
1570 false,
1571 target_address,
1572 Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.into_specified(),
1573 );
1574 }
1575 Some(IpAddressState::Tentative) => {
1576 }
1579 Some(IpAddressState::Unavailable) | None => {
1580 }
1583 }
1584
1585 return;
1586 }
1587 Ipv6SourceAddr::Unicast(src_ip) => {
1588 match core_ctx
1590 .address_status_for_device(target_address.into_specified(), device_id)
1591 {
1592 AddressStatus::Present(Ipv6PresentAddressStatus::UnicastAssigned) => {}
1593 AddressStatus::Present(
1594 Ipv6PresentAddressStatus::UnicastTentative
1595 | Ipv6PresentAddressStatus::Multicast,
1596 )
1597 | AddressStatus::Unassigned => {
1598 return;
1602 }
1603 }
1604
1605 if let Some(link_addr) = source_link_addr {
1606 NudIpHandler::handle_neighbor_probe(
1607 core_ctx,
1608 bindings_ctx,
1609 &device_id,
1610 src_ip.into_specified(),
1611 link_addr,
1612 );
1613 }
1614
1615 send_neighbor_advertisement(
1616 core_ctx,
1617 bindings_ctx,
1618 &device_id,
1619 true,
1620 target_address,
1621 src_ip.into_specified(),
1622 );
1623 }
1624 }
1625 }
1626 NdpPacket::NeighborAdvertisement(ref p) => {
1627 let target_address = p.message().target_address();
1631
1632 let target_address = match UnicastAddr::new(*target_address) {
1639 Some(a) => a,
1640 None => {
1641 debug!(
1642 "dropping NA from {} with non-unicast target={:?}",
1643 src_ip, target_address
1644 );
1645 return;
1646 }
1647 };
1648 if let Some(dst_ip) = MulticastAddr::new(dst_ip.get())
1652 && p.message().solicited_flag()
1653 {
1654 debug!(
1655 "dropping NA from {} with solicited flag and multicast dst {}",
1656 src_ip, dst_ip
1657 );
1658 return;
1659 }
1660
1661 core_ctx.counters().rx.neighbor_advertisement.increment();
1662
1663 let nonce = None;
1667 match IpDeviceHandler::handle_received_dad_packet(
1668 core_ctx,
1669 bindings_ctx,
1670 &device_id,
1671 target_address.into_specified(),
1672 nonce,
1673 ) {
1674 Some(IpAddressState::Assigned) => {
1675 error!(
1693 "NA from {src_ip} with target address {target_address} that is also \
1694 assigned on device {device_id:?}",
1695 );
1696 }
1697 Some(IpAddressState::Tentative) => {
1698 return;
1701 }
1702 Some(IpAddressState::Unavailable) | None => {
1703 }
1707 }
1708
1709 let link_addr = p.body().iter().find_map(|o| o.target_link_layer_address());
1710
1711 NudIpHandler::handle_neighbor_confirmation(
1712 core_ctx,
1713 bindings_ctx,
1714 &device_id,
1715 target_address.into_specified(),
1716 link_addr,
1717 ConfirmationFlags {
1718 solicited_flag: p.message().solicited_flag(),
1719 override_flag: p.message().override_flag(),
1720 },
1721 );
1722 }
1723 NdpPacket::RouterAdvertisement(ref p) => {
1724 let src_ip = match src_ip {
1737 Ipv6SourceAddr::Unicast(ip) => match LinkLocalUnicastAddr::new(*ip) {
1738 Some(ip) => ip,
1739 None => return,
1740 },
1741 Ipv6SourceAddr::Unspecified => return,
1742 };
1743
1744 let ra = p.message();
1745 debug!("received router advertisement from {:?}: {:?}", src_ip, ra);
1746 core_ctx.counters().rx.router_advertisement.increment();
1747
1748 if let Some(retransmit_timer) = ra.retransmit_timer() {
1755 Ipv6DeviceHandler::set_discovered_retrans_timer(
1756 core_ctx,
1757 bindings_ctx,
1758 &device_id,
1759 retransmit_timer,
1760 );
1761 }
1762
1763 if let Some(hop_limit) = ra.current_hop_limit() {
1770 trace!(
1771 "receive_ndp_packet: NDP RA: updating device's hop limit to {:?} for router: {:?}",
1772 ra.current_hop_limit(),
1773 src_ip
1774 );
1775 IpDeviceHandler::set_default_hop_limit(core_ctx, &device_id, hop_limit);
1776 }
1777
1778 Ipv6DeviceHandler::update_discovered_ipv6_route(
1779 core_ctx,
1780 bindings_ctx,
1781 &device_id,
1782 Ipv6DiscoveredRoute { subnet: IPV6_DEFAULT_SUBNET, gateway: Some(src_ip) },
1783 Ipv6DiscoveredRouteProperties { route_preference: p.message().preference().into() },
1784 p.message().router_lifetime().map(NonZeroNdpLifetime::Finite),
1785 );
1786
1787 for option in p.body().iter() {
1788 match option {
1789 NdpOption::TargetLinkLayerAddress(_)
1790 | NdpOption::RedirectedHeader { .. }
1791 | NdpOption::RecursiveDnsServer(_)
1792 | NdpOption::Nonce(_) => {}
1793 NdpOption::SourceLinkLayerAddress(addr) => {
1794 debug!("processing SourceLinkLayerAddress option in RA: {:?}", addr);
1795 NudIpHandler::handle_neighbor_probe(
1821 core_ctx,
1822 bindings_ctx,
1823 &device_id,
1824 {
1825 let src_ip: UnicastAddr<_> = src_ip.into_addr();
1826 src_ip.into_specified()
1827 },
1828 addr,
1829 );
1830 }
1831 NdpOption::PrefixInformation(prefix_info) => {
1832 debug!("processing Prefix Information option in RA: {:?}", prefix_info);
1833 if prefix_info.prefix().is_link_local() {
1851 continue;
1852 }
1853
1854 let subnet = match prefix_info.subnet() {
1855 Ok(subnet) => subnet,
1856 Err(err) => match err {
1857 SubnetError::PrefixTooLong | SubnetError::HostBitsSet => continue,
1858 },
1859 };
1860
1861 match UnicastAddr::new(subnet.network()) {
1862 Some(UnicastAddr { .. }) => {}
1863 None => continue,
1864 }
1865
1866 let valid_lifetime = prefix_info.valid_lifetime();
1867
1868 if prefix_info.on_link_flag() {
1869 Ipv6DeviceHandler::update_discovered_ipv6_route(
1870 core_ctx,
1871 bindings_ctx,
1872 &device_id,
1873 Ipv6DiscoveredRoute { subnet, gateway: None },
1874 Ipv6DiscoveredRouteProperties {
1875 route_preference: RoutePreference::Medium,
1876 },
1877 valid_lifetime,
1878 )
1879 }
1880
1881 if prefix_info.autonomous_address_configuration_flag() {
1882 Ipv6DeviceHandler::apply_slaac_update(
1883 core_ctx,
1884 bindings_ctx,
1885 &device_id,
1886 subnet,
1887 prefix_info.preferred_lifetime(),
1888 valid_lifetime,
1889 );
1890 }
1891 }
1892 NdpOption::RouteInformation(rio) => {
1893 debug!("processing Route Information option in RA: {:?}", rio);
1894 Ipv6DeviceHandler::update_discovered_ipv6_route(
1895 core_ctx,
1896 bindings_ctx,
1897 &device_id,
1898 Ipv6DiscoveredRoute {
1899 subnet: rio.prefix().clone(),
1900 gateway: Some(src_ip),
1901 },
1902 Ipv6DiscoveredRouteProperties {
1903 route_preference: rio.preference().into(),
1904 },
1905 rio.route_lifetime(),
1906 )
1907 }
1908 NdpOption::Mtu(mtu) => {
1909 debug!("processing MTU option in RA: {:?}", mtu);
1910 Ipv6DeviceHandler::set_link_mtu(core_ctx, &device_id, Mtu::new(mtu));
1914 }
1915 }
1916 }
1917
1918 bindings_ctx.on_event(RouterAdvertisementEvent {
1919 options_bytes: Box::from(p.body().bytes()),
1920 source: **src_ip,
1921 device: device_id.clone(),
1922 });
1923 }
1924 }
1925}
1926
1927impl<
1928 BC: IcmpBindingsContext + NdpBindingsContext<CC::DeviceId>,
1929 CC: InnerIcmpContext<Ipv6, BC>
1930 + InnerIcmpContext<Ipv6, BC>
1931 + Ipv6DeviceHandler<BC>
1932 + IpDeviceHandler<Ipv6, BC>
1933 + IpDeviceIngressStateContext<Ipv6>
1934 + PmtuHandler<Ipv6, BC>
1935 + NudIpHandler<Ipv6, BC>
1936 + IpLayerHandler<Ipv6, BC>
1937 + CounterContext<IcmpRxCounters<Ipv6>>
1938 + CounterContext<IcmpTxCounters<Ipv6>>
1939 + CounterContext<NdpCounters>,
1940> IpTransportContext<Ipv6, BC, CC> for IcmpIpTransportContext
1941{
1942 type EarlyDemuxSocket = Never;
1943
1944 fn early_demux<B: ParseBuffer>(
1945 _core_ctx: &mut CC,
1946 _device: &CC::DeviceId,
1947 _src_ip: Ipv6Addr,
1948 _dst_ip: Ipv6Addr,
1949 _buffer: B,
1950 ) -> Option<Self::EarlyDemuxSocket> {
1951 None
1952 }
1953
1954 fn receive_icmp_error(
1955 core_ctx: &mut CC,
1956 bindings_ctx: &mut BC,
1957 device: &CC::DeviceId,
1958 original_src_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1959 original_dst_ip: SpecifiedAddr<Ipv6Addr>,
1960 original_body: &[u8],
1961 err: Icmpv6ErrorCode,
1962 ) {
1963 receive_ip_transport_icmp_error(
1964 core_ctx,
1965 bindings_ctx,
1966 device,
1967 original_src_ip,
1968 original_dst_ip,
1969 original_body,
1970 err,
1971 )
1972 }
1973
1974 fn receive_ip_packet<B: BufferMut, H: IpHeaderInfo<Ipv6>>(
1975 core_ctx: &mut CC,
1976 bindings_ctx: &mut BC,
1977 device: &CC::DeviceId,
1978 src_ip: Ipv6SourceAddr,
1979 dst_ip: SpecifiedAddr<Ipv6Addr>,
1980 mut buffer: B,
1981 info: &mut LocalDeliveryPacketInfo<Ipv6, H>,
1982 _early_demux_socket: Option<Never>,
1983 ) -> Result<(), (B, Icmpv6Error)> {
1984 let LocalDeliveryPacketInfo { meta, header_info, marks } = info;
1985 let ReceiveIpPacketMeta { broadcast: _, transparent_override, parsing_context: _ } = meta;
1986 if let Some(delivery) = transparent_override {
1987 unreachable!(
1988 "cannot perform transparent local delivery {delivery:?} to an ICMP socket; \
1989 transparent proxy rules can only be configured for TCP and UDP packets"
1990 );
1991 }
1992
1993 trace!(
1994 "<IcmpIpTransportContext as IpTransportContext<Ipv6>>::receive_ip_packet({:?}, {})",
1995 src_ip, dst_ip
1996 );
1997
1998 let packet = match buffer
1999 .parse_with::<_, Icmpv6Packet<_>>(IcmpParseArgs::new(src_ip.get(), dst_ip))
2000 {
2001 Ok(packet) => packet,
2002 Err(_) => return Ok(()), };
2004
2005 match packet {
2006 Icmpv6Packet::EchoRequest(echo_request) => {
2007 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx).echo_request.increment();
2008
2009 if let Some(src_ip) = SocketIpAddr::new_from_ipv6_source(src_ip) {
2010 match SocketIpAddr::try_from(dst_ip) {
2011 Ok(dst_ip) => {
2012 let req = *echo_request.message();
2013 let code = echo_request.code();
2014 let (local_ip, remote_ip) = (dst_ip, src_ip);
2015 debug!(
2016 "replying to ICMP echo request from {remote_ip}: id={}, seq={}",
2017 req.id(),
2018 req.seq()
2019 );
2020 send_icmp_reply(
2021 core_ctx,
2022 bindings_ctx,
2023 device,
2024 remote_ip,
2025 local_ip,
2026 |src_ip| {
2027 IcmpPacketBuilder::<Ipv6, _>::new(
2028 src_ip,
2029 remote_ip.addr(),
2030 code,
2031 req.reply(),
2032 )
2033 .wrap_body(buffer)
2034 },
2035 &WithMarks(marks),
2036 );
2037 }
2038 Err(AddrIsMappedError {}) => {
2039 trace!(
2040 "IpTransportContext<Ipv6>::receive_ip_packet: Received echo request with an ipv4-mapped-ipv6 destination address"
2041 );
2042 }
2043 }
2044 } else {
2045 trace!(
2046 "<IcmpIpTransportContext as IpTransportContext<Ipv6>>::receive_ip_packet: Received echo request with an unspecified source address"
2047 );
2048 }
2049 }
2050 Icmpv6Packet::EchoReply(echo_reply) => {
2051 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx).echo_reply.increment();
2052 trace!(
2053 "<IcmpIpTransportContext as IpTransportContext<Ipv6>>::receive_ip_packet: Received an EchoReply message"
2054 );
2055 let parse_metadata = echo_reply.parse_metadata();
2056 buffer.undo_parse(parse_metadata);
2057 return <CC::EchoTransportContext
2058 as IpTransportContext<Ipv6, BC, CC>>::receive_ip_packet(
2059 core_ctx,
2060 bindings_ctx,
2061 device,
2062 src_ip,
2063 dst_ip,
2064 buffer,
2065 info,
2066 None
2067 );
2068 }
2069 Icmpv6Packet::Ndp(packet) => receive_ndp_packet(
2070 core_ctx,
2071 bindings_ctx,
2072 device,
2073 src_ip,
2074 dst_ip,
2075 packet,
2076 header_info,
2077 ),
2078 Icmpv6Packet::PacketTooBig(packet_too_big) => {
2079 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx)
2080 .packet_too_big
2081 .increment();
2082 trace!(
2083 "<IcmpIpTransportContext as IpTransportContext<Ipv6>>::receive_ip_packet: Received a Packet Too Big message"
2084 );
2085 if let Ipv6SourceAddr::Unicast(src_ip) = src_ip {
2086 let mtu = core_ctx.update_pmtu_if_less(
2096 bindings_ctx,
2097 dst_ip.get(),
2098 src_ip.get(),
2099 Mtu::new(packet_too_big.message().mtu()),
2100 );
2101 if let Some(mtu) = mtu {
2102 receive_icmpv6_error(
2103 core_ctx,
2104 bindings_ctx,
2105 device,
2106 &packet_too_big,
2107 Icmpv6ErrorCode::PacketTooBig(mtu),
2108 );
2109 }
2110 }
2111 }
2112 Icmpv6Packet::Mld(packet) => {
2113 core_ctx.receive_mld_packet(
2114 bindings_ctx,
2115 &device,
2116 src_ip,
2117 dst_ip,
2118 packet,
2119 header_info,
2120 );
2121 }
2122 Icmpv6Packet::DestUnreachable(dest_unreachable) => {
2123 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx)
2124 .dest_unreachable
2125 .increment_code(dest_unreachable.code());
2126 receive_icmpv6_error(
2127 core_ctx,
2128 bindings_ctx,
2129 device,
2130 &dest_unreachable,
2131 Icmpv6ErrorCode::DestUnreachable(dest_unreachable.code()),
2132 )
2133 }
2134 Icmpv6Packet::TimeExceeded(time_exceeded) => {
2135 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx)
2136 .time_exceeded
2137 .increment_code(time_exceeded.code());
2138 receive_icmpv6_error(
2139 core_ctx,
2140 bindings_ctx,
2141 device,
2142 &time_exceeded,
2143 Icmpv6ErrorCode::TimeExceeded(time_exceeded.code()),
2144 )
2145 }
2146 Icmpv6Packet::ParameterProblem(parameter_problem) => {
2147 CounterContext::<IcmpRxCounters<Ipv6>>::counters(core_ctx)
2148 .parameter_problem
2149 .increment_code(parameter_problem.code());
2150 receive_icmpv6_error(
2151 core_ctx,
2152 bindings_ctx,
2153 device,
2154 ¶meter_problem,
2155 Icmpv6ErrorCode::ParameterProblem(parameter_problem.code()),
2156 )
2157 }
2158 }
2159
2160 Ok(())
2161 }
2162}
2163
2164#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2165struct WithMarks<'a>(&'a Marks);
2166
2167impl<'a> OptionDelegationMarker for WithMarks<'a> {}
2168
2169impl<'a, I: IpExt> DelegatedRouteResolutionOptions<I> for WithMarks<'a> {
2170 fn marks(&self) -> &Marks {
2171 let Self(marks) = self;
2172 marks
2173 }
2174}
2175
2176impl<'a, I: IpExt> DelegatedSendOptions<I> for WithMarks<'a> {}
2177
2178fn send_icmp_reply<I, BC, CC, S, F, O>(
2189 core_ctx: &mut CC,
2190 bindings_ctx: &mut BC,
2191 device: &CC::DeviceId,
2192 original_src_ip: SocketIpAddr<I::Addr>,
2193 original_dst_ip: SocketIpAddr<I::Addr>,
2194 get_body_from_src_ip: F,
2195 ip_options: &O,
2196) where
2197 I: IpExt + FilterIpExt + IcmpCountersIpExt,
2198 CC: IpSocketHandler<I, BC> + DeviceIdContext<AnyDevice> + CounterContext<IcmpTxCounters<I>>,
2199 BC: TxMetadataBindingsTypes,
2200 S: DynamicTransportSerializer<I>,
2201 F: FnOnce(SpecifiedAddr<I::Addr>) -> S,
2202 O: SendOptions<I> + RouteResolutionOptions<I>,
2203{
2204 trace!("send_icmp_reply({:?}, {}, {})", device, original_src_ip, original_dst_ip);
2205 core_ctx.counters().reply.increment();
2206 let tx_metadata: BC::TxMetadata = Default::default();
2207
2208 let egress_device = (original_dst_ip.as_ref().is_multicast()
2212 || original_dst_ip.as_ref().must_have_zone())
2213 .then_some(EitherDeviceId::Strong(device));
2214
2215 core_ctx
2216 .send_oneshot_ip_packet_with_dyn_serializer(
2217 bindings_ctx,
2218 IpSocketArgs {
2219 device: egress_device,
2220 local_ip: IpDeviceAddr::new_from_socket_ip_addr(original_dst_ip),
2221 remote_ip: original_src_ip,
2222 proto: I::ICMP_IP_PROTO,
2223 options: ip_options,
2224 },
2225 tx_metadata,
2226 |src_ip| get_body_from_src_ip(src_ip.into()),
2227 )
2228 .unwrap_or_else(|err| {
2229 debug!("failed to send ICMP reply: {}", err);
2230 })
2231}
2232
2233fn receive_icmpv4_error<
2238 BC: IcmpBindingsContext,
2239 CC: InnerIcmpContext<Ipv4, BC>,
2240 B: SplitByteSlice,
2241 M: IcmpMessage<Ipv4, Body<B> = OriginalPacket<B>>,
2242>(
2243 core_ctx: &mut CC,
2244 bindings_ctx: &mut BC,
2245 device: &CC::DeviceId,
2246 packet: &IcmpPacket<Ipv4, B, M>,
2247 err: Icmpv4ErrorCode,
2248) {
2249 packet.with_original_packet(|res| match res {
2250 Ok(original_packet) => {
2251 let dst_ip = match SpecifiedAddr::new(original_packet.dst_ip()) {
2252 Some(ip) => ip,
2253 None => {
2254 trace!("receive_icmpv4_error: Got ICMP error message whose original IPv4 packet contains an unspecified destination address; discarding");
2255 return;
2256 },
2257 };
2258 InnerIcmpContext::receive_icmp_error(
2259 core_ctx,
2260 bindings_ctx,
2261 device,
2262 SpecifiedAddr::new(original_packet.src_ip()),
2263 dst_ip,
2264 original_packet.proto(),
2265 original_packet.body().into_inner(),
2266 err,
2267 );
2268 }
2269 Err(_) => debug!(
2270 "receive_icmpv4_error: Got ICMP error message with unparsable original IPv4 packet"
2271 ),
2272 })
2273}
2274
2275fn receive_icmpv6_error<
2280 BC: IcmpBindingsContext,
2281 CC: InnerIcmpContext<Ipv6, BC>,
2282 B: SplitByteSlice,
2283 M: IcmpMessage<Ipv6, Body<B> = OriginalPacket<B>>,
2284>(
2285 core_ctx: &mut CC,
2286 bindings_ctx: &mut BC,
2287 device: &CC::DeviceId,
2288 packet: &IcmpPacket<Ipv6, B, M>,
2289 err: Icmpv6ErrorCode,
2290) {
2291 packet.with_original_packet(|res| match res {
2292 Ok(original_packet) => {
2293 let dst_ip = match SpecifiedAddr::new(original_packet.dst_ip()) {
2294 Some(ip)=>ip,
2295 None => {
2296 trace!("receive_icmpv6_error: Got ICMP error message whose original IPv6 packet contains an unspecified destination address; discarding");
2297 return;
2298 },
2299 };
2300 match original_packet.body_proto() {
2301 Ok((body, proto)) => {
2302 InnerIcmpContext::receive_icmp_error(
2303 core_ctx,
2304 bindings_ctx,
2305 device,
2306 SpecifiedAddr::new(original_packet.src_ip()),
2307 dst_ip,
2308 proto,
2309 body.into_inner(),
2310 err,
2311 );
2312 }
2313 Err(ExtHdrParseError) => {
2314 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");
2315 return;
2318 }
2319 }
2320 }
2321 Err(_body) => debug!(
2322 "receive_icmpv6_error: Got ICMPv6 error message with unparsable original IPv6 packet"
2323 ),
2324 })
2325}
2326
2327fn send_icmpv4_error_message<B, BC, CC>(
2328 core_ctx: &mut CC,
2329 bindings_ctx: &mut BC,
2330 device: Option<&CC::DeviceId>,
2331 frame_dst: Option<FrameDestination>,
2332 original_src_ip: SocketIpAddr<Ipv4Addr>,
2333 original_dst_ip: SocketIpAddr<Ipv4Addr>,
2334 message: Icmpv4ErrorMessage,
2335 mut original_packet: B,
2336 header_len: usize,
2337 marks: &Marks,
2338) where
2339 B: BufferMut,
2340 BC: IcmpBindingsContext,
2341 CC: IcmpSendContext<Ipv4, BC> + CounterContext<IcmpTxCounters<Ipv4>>,
2342{
2343 if !should_send_icmpv4_error(frame_dst, original_src_ip.into(), original_dst_ip.into()) {
2347 return;
2348 }
2349
2350 original_packet.shrink_back_to(header_len + 64);
2353
2354 let tx_metadata: BC::TxMetadata = Default::default();
2355
2356 macro_rules! send {
2357 ($message:expr, $code:expr) => {{
2358 let _ = try_send_error!(
2361 core_ctx,
2362 bindings_ctx,
2363 core_ctx.send_oneshot_ip_packet_with_dyn_serializer(
2364 bindings_ctx,
2365 IpSocketArgs {
2366 device: device.map(EitherDeviceId::Strong),
2367 local_ip: None,
2368 remote_ip: original_src_ip,
2369 proto: Ipv4Proto::Icmp,
2370 options: &WithMarks(marks),
2371 },
2372 tx_metadata,
2373 |local_ip| {
2374 IcmpPacketBuilder::<Ipv4, _>::new(
2375 local_ip.addr(),
2376 original_src_ip.addr(),
2377 $code,
2378 $message,
2379 )
2380 .wrap_body(original_packet)
2381 },
2382 )
2383 );
2384 }};
2385 }
2386
2387 match message {
2388 Icmpv4ErrorMessage::TimeExceeded { message, code } => send!(message, code),
2389 Icmpv4ErrorMessage::ParameterProblem { message, code } => send!(message, code),
2390 Icmpv4ErrorMessage::DestUnreachable { message, code } => send!(message, code),
2391 }
2392}
2393
2394fn send_icmpv6_error_message<B, BC, CC>(
2395 core_ctx: &mut CC,
2396 bindings_ctx: &mut BC,
2397 device: Option<&CC::DeviceId>,
2398 frame_dst: Option<FrameDestination>,
2399 original_src_ip: SocketIpAddr<Ipv6Addr>,
2400 original_dst_ip: SocketIpAddr<Ipv6Addr>,
2401 message: Icmpv6ErrorMessage,
2402 original_packet: B,
2403 allow_dst_multicast: bool,
2404 marks: &Marks,
2405) where
2406 B: BufferMut,
2407 BC: IcmpBindingsContext,
2408 CC: IcmpSendContext<Ipv6, BC> + CounterContext<IcmpTxCounters<Ipv6>>,
2409{
2410 if !should_send_icmpv6_error(
2414 frame_dst,
2415 original_src_ip.into(),
2416 original_dst_ip.into(),
2417 allow_dst_multicast,
2418 ) {
2419 return;
2420 }
2421
2422 struct Icmpv6ErrorOptions<'a>(&'a Marks);
2423 impl<'a> OptionDelegationMarker for Icmpv6ErrorOptions<'a> {}
2424 impl<'a> DelegatedSendOptions<Ipv6> for Icmpv6ErrorOptions<'a> {
2425 fn mtu(&self) -> Mtu {
2426 Ipv6::MINIMUM_LINK_MTU
2427 }
2428 }
2429 impl<'a> DelegatedRouteResolutionOptions<Ipv6> for Icmpv6ErrorOptions<'a> {
2430 fn marks(&self) -> &Marks {
2431 let Self(marks) = self;
2432 marks
2433 }
2434 }
2435
2436 let tx_metadata: BC::TxMetadata = Default::default();
2437
2438 macro_rules! send {
2439 ($message:expr, $code:expr) => {{
2440 let _ = try_send_error!(
2443 core_ctx,
2444 bindings_ctx,
2445 core_ctx.send_oneshot_ip_packet_with_dyn_serializer(
2446 bindings_ctx,
2447 IpSocketArgs {
2448 device: device.map(EitherDeviceId::Strong),
2449 local_ip: None,
2450 remote_ip: original_src_ip,
2451 proto: Ipv6Proto::Icmpv6,
2452 options: &Icmpv6ErrorOptions(marks),
2453 },
2454 tx_metadata,
2455 |local_ip| {
2456 let icmp_builder = IcmpPacketBuilder::<Ipv6, _>::new(
2457 local_ip.addr(),
2458 original_src_ip.addr(),
2459 $code,
2460 $message,
2461 );
2462
2463 icmp_builder.wrap_body(TruncatingSerializer::new(
2466 original_packet,
2467 TruncateDirection::DiscardBack,
2468 ))
2469 },
2470 )
2471 );
2472 }};
2473 }
2474
2475 match message {
2476 Icmpv6ErrorMessage::TimeExceeded { message, code } => send!(message, code),
2477 Icmpv6ErrorMessage::PacketTooBig { message, code } => send!(message, code),
2478 Icmpv6ErrorMessage::ParameterProblem { message, code } => send!(message, code),
2479 Icmpv6ErrorMessage::DestUnreachable { message, code } => send!(message, code),
2480 }
2481}
2482
2483fn should_send_icmpv4_error(
2506 frame_dst: Option<FrameDestination>,
2507 src_ip: SpecifiedAddr<Ipv4Addr>,
2508 dst_ip: SpecifiedAddr<Ipv4Addr>,
2509) -> bool {
2510 !(dst_ip.is_multicast()
2530 || dst_ip.is_limited_broadcast()
2531 || frame_dst.is_some_and(|dst| dst.is_broadcast())
2532 || src_ip.is_limited_broadcast()
2533 || src_ip.is_multicast()
2534 || src_ip.is_class_e())
2535}
2536
2537fn should_send_icmpv6_error(
2567 frame_dst: Option<FrameDestination>,
2568 src_ip: SpecifiedAddr<Ipv6Addr>,
2569 dst_ip: SpecifiedAddr<Ipv6Addr>,
2570 allow_dst_multicast: bool,
2571) -> bool {
2572 let multicast_frame_dst = match frame_dst {
2575 Some(FrameDestination::Individual { local: _ }) | None => false,
2576 Some(FrameDestination::Broadcast) | Some(FrameDestination::Multicast) => true,
2577 };
2578 if (dst_ip.is_multicast() || multicast_frame_dst) && !allow_dst_multicast {
2579 return false;
2580 }
2581 if src_ip.is_multicast() {
2582 return false;
2583 }
2584 true
2585}
2586
2587fn is_icmp_error_or_redirect_message<I: IcmpIpExt>(proto: I::Proto, buf: &[u8]) -> bool {
2599 proto == I::ICMP_IP_PROTO
2600 && peek_message_type::<I::IcmpMessageType>(buf)
2601 .map(IcmpMessageType::is_error_or_redirect)
2602 .unwrap_or(true)
2603}
2604
2605#[cfg(any(test, feature = "testutils"))]
2607pub(crate) mod testutil {
2608 use alloc::vec::Vec;
2609 use net_types::ethernet::Mac;
2610 use net_types::ip::{Ipv6, Ipv6Addr};
2611 use netstack3_base::NetworkSerializationContext;
2612 use packet::{Buf, InnerPacketBuilder as _, NestableSerializer as _, Serializer as _};
2613 use packet_formats::icmp::ndp::options::NdpOptionBuilder;
2614 use packet_formats::icmp::ndp::{
2615 NeighborAdvertisement, NeighborSolicitation, OptionSequenceBuilder,
2616 };
2617 use packet_formats::icmp::{IcmpPacketBuilder, IcmpZeroCode};
2618 use packet_formats::ip::Ipv6Proto;
2619 use packet_formats::ipv6::Ipv6PacketBuilder;
2620
2621 use super::REQUIRED_NDP_IP_PACKET_HOP_LIMIT;
2622
2623 pub fn neighbor_advertisement_ip_packet(
2626 src_ip: Ipv6Addr,
2627 dst_ip: Ipv6Addr,
2628 router_flag: bool,
2629 solicited_flag: bool,
2630 override_flag: bool,
2631 mac: Mac,
2632 ) -> Buf<Vec<u8>> {
2633 OptionSequenceBuilder::new([NdpOptionBuilder::TargetLinkLayerAddress(&mac.bytes())].iter())
2634 .into_serializer()
2635 .wrap_in(IcmpPacketBuilder::<Ipv6, _>::new(
2636 src_ip,
2637 dst_ip,
2638 IcmpZeroCode,
2639 NeighborAdvertisement::new(router_flag, solicited_flag, override_flag, src_ip),
2640 ))
2641 .wrap_in(Ipv6PacketBuilder::new(
2642 src_ip,
2643 dst_ip,
2644 REQUIRED_NDP_IP_PACKET_HOP_LIMIT,
2645 Ipv6Proto::Icmpv6,
2646 ))
2647 .serialize_vec_outer(&mut NetworkSerializationContext::default())
2648 .unwrap()
2649 .unwrap_b()
2650 }
2651
2652 pub fn neighbor_solicitation_ip_packet(
2655 src_ip: Ipv6Addr,
2656 dst_ip: Ipv6Addr,
2657 target_addr: Ipv6Addr,
2658 mac: Mac,
2659 ) -> Buf<Vec<u8>> {
2660 OptionSequenceBuilder::new([NdpOptionBuilder::SourceLinkLayerAddress(&mac.bytes())].iter())
2661 .into_serializer()
2662 .wrap_in(IcmpPacketBuilder::<Ipv6, _>::new(
2663 src_ip,
2664 dst_ip,
2665 IcmpZeroCode,
2666 NeighborSolicitation::new(target_addr),
2667 ))
2668 .wrap_in(Ipv6PacketBuilder::new(
2669 src_ip,
2670 dst_ip,
2671 REQUIRED_NDP_IP_PACKET_HOP_LIMIT,
2672 Ipv6Proto::Icmpv6,
2673 ))
2674 .serialize_vec_outer(&mut NetworkSerializationContext::default())
2675 .unwrap()
2676 .unwrap_b()
2677 }
2678}
2679
2680#[cfg(test)]
2681mod tests {
2682 use alloc::vec;
2683 use alloc::vec::Vec;
2684 use packet_formats::icmp::ndp::options::NdpNonce;
2685
2686 use core::fmt::Debug;
2687 use core::time::Duration;
2688
2689 use net_types::ip::Subnet;
2690 use netstack3_base::testutil::{
2691 FakeBindingsCtx, FakeCoreCtx, FakeDeviceId, FakeInstant, FakeTxMetadata, FakeWeakDeviceId,
2692 TEST_ADDRS_V4, TEST_ADDRS_V6, TestIpExt, set_logger_for_test,
2693 };
2694 use netstack3_base::{CtxPair, NetworkSerializationContext, Uninstantiable};
2695 use netstack3_filter::TransportPacketSerializer;
2696 use packet::{Buf, EmptyBuf, NestableSerializer as _, Serializer as _};
2697 use packet_formats::icmp::mld::MldPacket;
2698 use packet_formats::ip::IpProto;
2699 use packet_formats::utils::NonZeroDuration;
2700
2701 use super::*;
2702 use crate::internal::base::{IpDeviceEgressStateContext, RouterAdvertisementEvent};
2703 use crate::internal::socket::testutil::{FakeDeviceConfig, FakeIpSocketCtx};
2704 use crate::internal::socket::{
2705 IpSock, IpSockCreationError, IpSockSendError, IpSocketHandler, SendOptions,
2706 };
2707 use crate::socket::RouteResolutionOptions;
2708
2709 use test_util::assert_geq;
2710
2711 pub(super) trait IcmpTestIpExt:
2712 TestIpExt + IpExt + FilterIpExt + IcmpCountersIpExt
2713 {
2714 }
2715 impl<I: TestIpExt + IpExt + FilterIpExt + IcmpCountersIpExt> IcmpTestIpExt for I {}
2716
2717 type InnerIpSocketCtx<I> = FakeCoreCtx<
2719 FakeIpSocketCtx<I, FakeDeviceId>,
2720 SendIpPacketMeta<I, FakeDeviceId, SpecifiedAddr<<I as Ip>::Addr>>,
2721 FakeDeviceId,
2722 >;
2723
2724 pub(super) struct FakeIcmpCoreCtx<I: IcmpTestIpExt> {
2726 ip_socket_ctx: InnerIpSocketCtx<I>,
2727 icmp: FakeIcmpCoreCtxState<I>,
2728 }
2729
2730 type FakeIcmpBindingsCtx<I> = FakeBindingsCtx<
2732 (),
2733 RouterAdvertisementEvent<FakeDeviceId>,
2734 FakeIcmpBindingsCtxState<I>,
2735 (),
2736 >;
2737
2738 pub(super) type FakeIcmpCtx<I> = CtxPair<FakeIcmpCoreCtx<I>, FakeIcmpBindingsCtx<I>>;
2742
2743 pub(super) struct FakeIcmpCoreCtxState<I: IcmpTestIpExt> {
2744 error_send_bucket: TokenBucket<FakeInstant>,
2745 receive_icmp_error: Vec<I::ErrorCode>,
2746 rx_counters: IcmpRxCounters<I>,
2747 tx_counters: IcmpTxCounters<I>,
2748 ndp_counters: NdpCounters,
2749 }
2750
2751 impl<I: IcmpTestIpExt> FakeIcmpCoreCtx<I> {
2752 fn with_errors_per_second(errors_per_second: u64) -> Self {
2753 Self {
2754 icmp: FakeIcmpCoreCtxState {
2755 error_send_bucket: TokenBucket::new(errors_per_second),
2756 receive_icmp_error: Default::default(),
2757 rx_counters: Default::default(),
2758 tx_counters: Default::default(),
2759 ndp_counters: Default::default(),
2760 },
2761 ip_socket_ctx: InnerIpSocketCtx::with_state(FakeIpSocketCtx::new(
2762 core::iter::once(FakeDeviceConfig {
2763 device: FakeDeviceId,
2764 local_ips: vec![I::TEST_ADDRS.local_ip],
2765 remote_ips: vec![I::TEST_ADDRS.remote_ip],
2766 }),
2767 )),
2768 }
2769 }
2770 }
2771
2772 impl<I: IcmpTestIpExt> Default for FakeIcmpCoreCtx<I> {
2773 fn default() -> Self {
2774 Self::with_errors_per_second(DEFAULT_ERRORS_PER_SECOND)
2775 }
2776 }
2777
2778 impl<I: IcmpTestIpExt> DeviceIdContext<AnyDevice> for FakeIcmpCoreCtx<I> {
2779 type DeviceId = FakeDeviceId;
2780 type WeakDeviceId = FakeWeakDeviceId<FakeDeviceId>;
2781 }
2782
2783 impl<I: IcmpTestIpExt> IcmpStateContext for FakeIcmpCoreCtx<I> {}
2784 impl<I: IcmpTestIpExt> IcmpStateContext for InnerIpSocketCtx<I> {}
2785
2786 impl<I: IcmpTestIpExt> CounterContext<IcmpRxCounters<I>> for FakeIcmpCoreCtx<I> {
2787 fn counters(&self) -> &IcmpRxCounters<I> {
2788 &self.icmp.rx_counters
2789 }
2790 }
2791
2792 impl<I: IcmpTestIpExt> CounterContext<IcmpTxCounters<I>> for FakeIcmpCoreCtx<I> {
2793 fn counters(&self) -> &IcmpTxCounters<I> {
2794 &self.icmp.tx_counters
2795 }
2796 }
2797
2798 impl<I: IcmpTestIpExt> CounterContext<NdpCounters> for FakeIcmpCoreCtx<I> {
2799 fn counters(&self) -> &NdpCounters {
2800 &self.icmp.ndp_counters
2801 }
2802 }
2803
2804 pub enum FakeEchoIpTransportContext {}
2805
2806 impl EchoTransportContextMarker for FakeEchoIpTransportContext {}
2807
2808 impl<I> IpTransportContext<I, FakeIcmpBindingsCtx<I>, FakeIcmpCoreCtx<I>>
2809 for FakeEchoIpTransportContext
2810 where
2811 I: IcmpTestIpExt + IpLayerIpExt,
2812 {
2813 type EarlyDemuxSocket = Never;
2814
2815 fn early_demux<B: ParseBuffer>(
2816 _core_ctx: &mut FakeIcmpCoreCtx<I>,
2817 _device: &FakeDeviceId,
2818 _src_ip: I::Addr,
2819 _dst_ip: I::Addr,
2820 _buffer: B,
2821 ) -> Option<Self::EarlyDemuxSocket> {
2822 None
2823 }
2824
2825 fn receive_icmp_error(
2826 core_ctx: &mut FakeIcmpCoreCtx<I>,
2827 _bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
2828 _device: &FakeDeviceId,
2829 _original_src_ip: Option<SpecifiedAddr<I::Addr>>,
2830 _original_dst_ip: SpecifiedAddr<I::Addr>,
2831 _original_body: &[u8],
2832 _err: I::ErrorCode,
2833 ) {
2834 core_ctx.icmp.rx_counters.error_delivered_to_socket.increment()
2835 }
2836
2837 fn receive_ip_packet<B: BufferMut, H: IpHeaderInfo<I>>(
2838 _core_ctx: &mut FakeIcmpCoreCtx<I>,
2839 _bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
2840 _device: &FakeDeviceId,
2841 _src_ip: I::RecvSrcAddr,
2842 _dst_ip: SpecifiedAddr<I::Addr>,
2843 _buffer: B,
2844 _info: &mut LocalDeliveryPacketInfo<I, H>,
2845 _early_demux_socket: Option<Never>,
2846 ) -> Result<(), (B, I::IcmpError)> {
2847 unimplemented!()
2848 }
2849 }
2850
2851 impl<I: IpLayerIpExt + IcmpTestIpExt> InnerIcmpContext<I, FakeIcmpBindingsCtx<I>>
2852 for FakeIcmpCoreCtx<I>
2853 {
2854 type EchoTransportContext = FakeEchoIpTransportContext;
2855
2856 fn receive_icmp_error(
2857 &mut self,
2858 bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
2859 device: &Self::DeviceId,
2860 original_src_ip: Option<SpecifiedAddr<I::Addr>>,
2861 original_dst_ip: SpecifiedAddr<I::Addr>,
2862 original_proto: I::Proto,
2863 original_body: &[u8],
2864 err: I::ErrorCode,
2865 ) {
2866 CounterContext::<IcmpRxCounters<I>>::counters(self).error.increment();
2867 self.icmp.receive_icmp_error.push(err);
2868 if original_proto == I::ICMP_IP_PROTO {
2869 receive_ip_transport_icmp_error(
2870 self,
2871 bindings_ctx,
2872 device,
2873 original_src_ip,
2874 original_dst_ip,
2875 original_body,
2876 err,
2877 )
2878 }
2879 }
2880 }
2881
2882 impl<I: IpLayerIpExt + IcmpTestIpExt> IcmpSendContext<I, FakeIcmpBindingsCtx<I>>
2883 for FakeIcmpCoreCtx<I>
2884 {
2885 fn with_error_send_bucket_mut<O, F: FnOnce(&mut TokenBucket<FakeInstant>) -> O>(
2886 &mut self,
2887 cb: F,
2888 ) -> O {
2889 cb(&mut self.icmp.error_send_bucket)
2890 }
2891 }
2892
2893 #[test]
2894 fn test_should_send_icmpv4_error() {
2895 let src_ip = TEST_ADDRS_V4.local_ip;
2896 let dst_ip = TEST_ADDRS_V4.remote_ip;
2897 let frame_dst = FrameDestination::Individual { local: true };
2898 let multicast_ip_1 = SpecifiedAddr::new(Ipv4Addr::new([224, 0, 0, 1])).unwrap();
2899 let multicast_ip_2 = SpecifiedAddr::new(Ipv4Addr::new([224, 0, 0, 2])).unwrap();
2900
2901 assert!(should_send_icmpv4_error(Some(frame_dst), src_ip, dst_ip));
2903 assert!(should_send_icmpv4_error(None, src_ip, dst_ip));
2904
2905 assert!(should_send_icmpv4_error(
2907 Some(frame_dst),
2908 Ipv4::LOOPBACK_ADDRESS,
2909 Ipv4::LOOPBACK_ADDRESS,
2910 ));
2911
2912 assert!(!should_send_icmpv4_error(
2914 Some(frame_dst),
2915 src_ip,
2916 Ipv4::LIMITED_BROADCAST_ADDRESS,
2917 ));
2918
2919 assert!(!should_send_icmpv4_error(Some(frame_dst), src_ip, multicast_ip_1,));
2921
2922 assert!(!should_send_icmpv4_error(Some(FrameDestination::Broadcast), src_ip, dst_ip,));
2924
2925 assert!(!should_send_icmpv4_error(
2927 Some(frame_dst),
2928 Ipv4::LIMITED_BROADCAST_ADDRESS,
2929 dst_ip,
2930 ));
2931
2932 assert!(!should_send_icmpv4_error(Some(frame_dst), multicast_ip_2, dst_ip));
2934
2935 assert!(!should_send_icmpv4_error(
2937 Some(frame_dst),
2938 SpecifiedAddr::new(Ipv4Addr::new([240, 0, 0, 1])).unwrap(),
2939 dst_ip,
2940 ));
2941 }
2942
2943 #[test]
2944 fn test_should_send_icmpv6_error() {
2945 let src_ip = TEST_ADDRS_V6.local_ip;
2946 let dst_ip = TEST_ADDRS_V6.remote_ip;
2947 let frame_dst = FrameDestination::Individual { local: true };
2948 let multicast_ip_1 =
2949 SpecifiedAddr::new(Ipv6Addr::new([0xff00, 0, 0, 0, 0, 0, 0, 1])).unwrap();
2950 let multicast_ip_2 =
2951 SpecifiedAddr::new(Ipv6Addr::new([0xff00, 0, 0, 0, 0, 0, 0, 2])).unwrap();
2952
2953 assert!(should_send_icmpv6_error(
2955 Some(frame_dst),
2956 src_ip,
2957 dst_ip,
2958 false ));
2960 assert!(should_send_icmpv6_error(
2961 None, src_ip, dst_ip, false ));
2963 assert!(should_send_icmpv6_error(
2964 Some(frame_dst),
2965 src_ip,
2966 dst_ip,
2967 true ));
2969
2970 assert!(should_send_icmpv6_error(
2972 Some(frame_dst),
2973 Ipv6::LOOPBACK_ADDRESS,
2974 Ipv6::LOOPBACK_ADDRESS,
2975 false ));
2977 assert!(should_send_icmpv6_error(
2978 Some(frame_dst),
2979 Ipv6::LOOPBACK_ADDRESS,
2980 Ipv6::LOOPBACK_ADDRESS,
2981 true ));
2983
2984 assert!(!should_send_icmpv6_error(
2987 Some(frame_dst),
2988 src_ip,
2989 multicast_ip_1,
2990 false ));
2992 assert!(should_send_icmpv6_error(
2993 Some(frame_dst),
2994 src_ip,
2995 multicast_ip_1,
2996 true ));
2998
2999 assert!(!should_send_icmpv6_error(
3002 Some(FrameDestination::Broadcast),
3003 src_ip,
3004 dst_ip,
3005 false ));
3007 assert!(should_send_icmpv6_error(
3008 Some(FrameDestination::Broadcast),
3009 src_ip,
3010 dst_ip,
3011 true ));
3013
3014 assert!(!should_send_icmpv6_error(
3016 Some(frame_dst),
3017 multicast_ip_2,
3018 dst_ip,
3019 false ));
3021 assert!(!should_send_icmpv6_error(
3022 Some(frame_dst),
3023 multicast_ip_2,
3024 dst_ip,
3025 true ));
3027
3028 assert!(!should_send_icmpv6_error(
3031 Some(FrameDestination::Broadcast),
3032 multicast_ip_2,
3033 dst_ip,
3034 false ));
3036 assert!(!should_send_icmpv6_error(
3037 Some(FrameDestination::Broadcast),
3038 multicast_ip_2,
3039 dst_ip,
3040 true ));
3042 assert!(!should_send_icmpv6_error(
3043 Some(frame_dst),
3044 multicast_ip_2,
3045 multicast_ip_1,
3046 false ));
3048 assert!(!should_send_icmpv6_error(
3049 Some(frame_dst),
3050 multicast_ip_2,
3051 multicast_ip_1,
3052 true ));
3054 }
3055
3056 #[derive(Default)]
3063 pub(super) struct FakeIcmpBindingsCtxState<I: IpExt> {
3064 _marker: core::marker::PhantomData<I>,
3065 }
3066
3067 impl InnerIcmpv4Context<FakeIcmpBindingsCtx<Ipv4>> for FakeIcmpCoreCtx<Ipv4> {
3068 fn should_send_timestamp_reply(&self) -> bool {
3069 false
3070 }
3071 }
3072 impl_pmtu_handler!(FakeIcmpCoreCtx<Ipv4>, FakeIcmpBindingsCtx<Ipv4>, Ipv4);
3073 impl_pmtu_handler!(FakeIcmpCoreCtx<Ipv6>, FakeIcmpBindingsCtx<Ipv6>, Ipv6);
3074
3075 impl<I: IcmpTestIpExt> IpSocketHandler<I, FakeIcmpBindingsCtx<I>> for FakeIcmpCoreCtx<I> {
3076 fn new_ip_socket<O>(
3077 &mut self,
3078 bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3079 args: IpSocketArgs<'_, Self::DeviceId, I, O>,
3080 ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
3081 where
3082 O: RouteResolutionOptions<I>,
3083 {
3084 self.ip_socket_ctx.new_ip_socket(bindings_ctx, args)
3085 }
3086
3087 fn send_ip_packet<S, O>(
3088 &mut self,
3089 bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3090 socket: &IpSock<I, Self::WeakDeviceId>,
3091 body: S,
3092 options: &O,
3093 tx_meta: FakeTxMetadata,
3094 ) -> Result<(), IpSockSendError>
3095 where
3096 S: TransportPacketSerializer<I>,
3097 S::Buffer: BufferMut,
3098 O: SendOptions<I> + RouteResolutionOptions<I>,
3099 {
3100 self.ip_socket_ctx.send_ip_packet(bindings_ctx, socket, body, options, tx_meta)
3101 }
3102
3103 fn confirm_reachable<O>(
3104 &mut self,
3105 bindings_ctx: &mut FakeIcmpBindingsCtx<I>,
3106 socket: &IpSock<I, Self::WeakDeviceId>,
3107 options: &O,
3108 ) where
3109 O: RouteResolutionOptions<I>,
3110 {
3111 self.ip_socket_ctx.confirm_reachable(bindings_ctx, socket, options)
3112 }
3113 }
3114
3115 impl IpDeviceHandler<Ipv6, FakeIcmpBindingsCtx<Ipv6>> for FakeIcmpCoreCtx<Ipv6> {
3116 fn is_router_device(&mut self, _device_id: &Self::DeviceId) -> bool {
3117 unimplemented!()
3118 }
3119
3120 fn set_default_hop_limit(&mut self, _device_id: &Self::DeviceId, _hop_limit: NonZeroU8) {
3121 unreachable!()
3122 }
3123
3124 fn handle_received_dad_packet(
3125 &mut self,
3126 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3127 _device_id: &Self::DeviceId,
3128 _addr: SpecifiedAddr<Ipv6Addr>,
3129 _probe_data: Option<NdpNonce<&'_ [u8]>>,
3130 ) -> Option<IpAddressState> {
3131 unimplemented!()
3132 }
3133 }
3134
3135 impl IpDeviceEgressStateContext<Ipv6> for FakeIcmpCoreCtx<Ipv6> {
3136 fn with_next_packet_id<O, F: FnOnce(&()) -> O>(&self, cb: F) -> O {
3137 cb(&())
3138 }
3139
3140 fn get_local_addr_for_remote(
3141 &mut self,
3142 _device_id: &Self::DeviceId,
3143 _remote: Option<SpecifiedAddr<Ipv6Addr>>,
3144 ) -> Option<IpDeviceAddr<Ipv6Addr>> {
3145 unimplemented!()
3146 }
3147
3148 fn get_hop_limit(&mut self, _device_id: &Self::DeviceId) -> NonZeroU8 {
3149 unimplemented!()
3150 }
3151 }
3152
3153 impl IpDeviceIngressStateContext<Ipv6> for FakeIcmpCoreCtx<Ipv6> {
3154 fn address_status_for_device(
3155 &mut self,
3156 _addr: SpecifiedAddr<Ipv6Addr>,
3157 _device_id: &Self::DeviceId,
3158 ) -> AddressStatus<Ipv6PresentAddressStatus> {
3159 unimplemented!()
3160 }
3161 }
3162
3163 impl Ipv6DeviceHandler<FakeIcmpBindingsCtx<Ipv6>> for FakeIcmpCoreCtx<Ipv6> {
3164 type LinkLayerAddr = Uninstantiable;
3165
3166 fn get_link_layer_addr(&mut self, _device_id: &Self::DeviceId) -> Option<Uninstantiable> {
3167 unimplemented!()
3168 }
3169
3170 fn set_discovered_retrans_timer(
3171 &mut self,
3172 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3173 _device_id: &Self::DeviceId,
3174 _retrans_timer: NonZeroDuration,
3175 ) {
3176 unimplemented!()
3177 }
3178
3179 fn set_link_mtu(&mut self, _device_id: &Self::DeviceId, _mtu: Mtu) {
3180 unimplemented!()
3181 }
3182
3183 fn update_discovered_ipv6_route(
3184 &mut self,
3185 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3186 _device_id: &Self::DeviceId,
3187 _route: Ipv6DiscoveredRoute,
3188 _properties: Ipv6DiscoveredRouteProperties,
3189 _lifetime: Option<NonZeroNdpLifetime>,
3190 ) {
3191 unimplemented!()
3192 }
3193
3194 fn apply_slaac_update(
3195 &mut self,
3196 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3197 _device_id: &Self::DeviceId,
3198 _subnet: Subnet<Ipv6Addr>,
3199 _preferred_lifetime: Option<NonZeroNdpLifetime>,
3200 _valid_lifetime: Option<NonZeroNdpLifetime>,
3201 ) {
3202 unimplemented!()
3203 }
3204
3205 fn receive_mld_packet<B: SplitByteSlice, H: IpHeaderInfo<Ipv6>>(
3206 &mut self,
3207 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3208 _device: &FakeDeviceId,
3209 _src_ip: Ipv6SourceAddr,
3210 _dst_ip: SpecifiedAddr<Ipv6Addr>,
3211 _packet: MldPacket<B>,
3212 _header_info: &H,
3213 ) {
3214 unimplemented!()
3215 }
3216 }
3217
3218 impl IpLayerHandler<Ipv6, FakeIcmpBindingsCtx<Ipv6>> for FakeIcmpCoreCtx<Ipv6> {
3219 fn send_ip_packet_from_device<S>(
3220 &mut self,
3221 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3222 _meta: SendIpPacketMeta<Ipv6, &Self::DeviceId, Option<SpecifiedAddr<Ipv6Addr>>>,
3223 _body: S,
3224 ) -> Result<(), IpSendFrameError<S>> {
3225 unimplemented!()
3226 }
3227
3228 fn send_ip_frame<S>(
3229 &mut self,
3230 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3231 _device: &Self::DeviceId,
3232 _destination: IpPacketDestination<Ipv6, &Self::DeviceId>,
3233 _body: S,
3234 ) -> Result<(), IpSendFrameError<S>>
3235 where
3236 S: NetworkSerializer,
3237 S::Buffer: BufferMut,
3238 {
3239 unimplemented!()
3240 }
3241 }
3242
3243 impl NudIpHandler<Ipv6, FakeIcmpBindingsCtx<Ipv6>> for FakeIcmpCoreCtx<Ipv6> {
3244 fn handle_neighbor_probe(
3245 &mut self,
3246 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3247 _device_id: &Self::DeviceId,
3248 _neighbor: SpecifiedAddr<Ipv6Addr>,
3249 _link_addr: &[u8],
3250 ) {
3251 unimplemented!()
3252 }
3253
3254 fn handle_neighbor_confirmation(
3255 &mut self,
3256 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3257 _device_id: &Self::DeviceId,
3258 _neighbor: SpecifiedAddr<Ipv6Addr>,
3259 _link_addr: Option<&[u8]>,
3260 _flags: ConfirmationFlags,
3261 ) {
3262 unimplemented!()
3263 }
3264
3265 fn flush_neighbor_table(
3266 &mut self,
3267 _bindings_ctx: &mut FakeIcmpBindingsCtx<Ipv6>,
3268 _device_id: &Self::DeviceId,
3269 ) {
3270 unimplemented!()
3271 }
3272 }
3273
3274 #[test]
3275 fn test_receive_icmpv4_error() {
3276 const ICMP_ID: u16 = 0x0F;
3279 const SEQ_NUM: u16 = 0xF0;
3280
3281 fn test_receive_icmpv4_error_helper<
3296 C: Debug,
3297 M: IcmpMessage<Ipv4, Code = C> + Debug,
3298 F: Fn(&FakeIcmpCtx<Ipv4>),
3299 >(
3300 original_packet: &mut [u8],
3301 code: C,
3302 msg: M,
3303 f: F,
3304 ) {
3305 set_logger_for_test();
3306
3307 let mut ctx: FakeIcmpCtx<Ipv4> = FakeIcmpCtx::default();
3308
3309 let CtxPair { core_ctx, bindings_ctx } = &mut ctx;
3310 <IcmpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_ip_packet(
3311 core_ctx,
3312 bindings_ctx,
3313 &FakeDeviceId,
3314 Ipv4SourceAddr::new(*TEST_ADDRS_V4.remote_ip).unwrap(),
3315 TEST_ADDRS_V4.local_ip,
3316 IcmpPacketBuilder::new(TEST_ADDRS_V4.remote_ip, TEST_ADDRS_V4.local_ip, code, msg)
3317 .wrap_body(Buf::new(original_packet, ..))
3318 .serialize_vec_outer(&mut NetworkSerializationContext::default())
3319 .unwrap(),
3320 &mut LocalDeliveryPacketInfo::default(),
3321 None,
3322 )
3323 .unwrap();
3324 f(&ctx);
3325 }
3326 let mut buffer = EmptyBuf
3339 .wrap_in(IcmpPacketBuilder::<Ipv4, _>::new(
3340 TEST_ADDRS_V4.local_ip,
3341 TEST_ADDRS_V4.remote_ip,
3342 IcmpZeroCode,
3343 IcmpEchoRequest::new(ICMP_ID, SEQ_NUM),
3344 ))
3345 .wrap_in(<Ipv4 as packet_formats::ip::IpExt>::PacketBuilder::<
3346 NetworkSerializationContext,
3347 >::new(
3348 TEST_ADDRS_V4.local_ip, TEST_ADDRS_V4.remote_ip, 64, Ipv4Proto::Icmp
3349 ))
3350 .serialize_vec_outer(&mut NetworkSerializationContext::default())
3351 .unwrap();
3352
3353 test_receive_icmpv4_error_helper(
3354 buffer.as_mut(),
3355 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3356 IcmpDestUnreachable::default(),
3357 |CtxPair { core_ctx, bindings_ctx: _ }| {
3358 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3359 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3360 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3361 assert_eq!(
3362 core_ctx.icmp.rx_counters.dest_unreachable.dest_network_unreachable.get(),
3363 1
3364 );
3365 let err = Icmpv4ErrorCode::DestUnreachable(
3366 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3367 IcmpDestUnreachable::default(),
3368 );
3369 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3370 },
3371 );
3372
3373 test_receive_icmpv4_error_helper(
3374 buffer.as_mut(),
3375 Icmpv4TimeExceededCode::TtlExpired,
3376 IcmpTimeExceeded::default(),
3377 |CtxPair { core_ctx, bindings_ctx: _ }| {
3378 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3379 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3380 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3381 assert_eq!(core_ctx.icmp.rx_counters.time_exceeded.ttl_expired.get(), 1);
3382 let err = Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired);
3383 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3384 },
3385 );
3386
3387 test_receive_icmpv4_error_helper(
3388 buffer.as_mut(),
3389 Icmpv4ParameterProblemCode::PointerIndicatesError,
3390 Icmpv4ParameterProblem::new(0),
3391 |CtxPair { core_ctx, bindings_ctx: _ }| {
3392 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3393 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3394 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3395 assert_eq!(
3396 core_ctx.icmp.rx_counters.parameter_problem.pointer_indicates_error.get(),
3397 1
3398 );
3399 let err = Icmpv4ErrorCode::ParameterProblem(
3400 Icmpv4ParameterProblemCode::PointerIndicatesError,
3401 );
3402 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3403 },
3404 );
3405
3406 let mut buffer = <Ipv4 as packet_formats::ip::IpExt>::PacketBuilder::<
3413 NetworkSerializationContext,
3414 >::new(
3415 TEST_ADDRS_V4.local_ip, TEST_ADDRS_V4.remote_ip, 64, Ipv4Proto::Icmp
3416 )
3417 .wrap_body(EmptyBuf)
3418 .serialize_vec_outer(&mut NetworkSerializationContext::default())
3419 .unwrap();
3420
3421 test_receive_icmpv4_error_helper(
3422 buffer.as_mut(),
3423 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3424 IcmpDestUnreachable::default(),
3425 |CtxPair { core_ctx, bindings_ctx: _ }| {
3426 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3427 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3428 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3429 assert_eq!(
3430 core_ctx.icmp.rx_counters.dest_unreachable.dest_network_unreachable.get(),
3431 1
3432 );
3433 let err = Icmpv4ErrorCode::DestUnreachable(
3434 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3435 IcmpDestUnreachable::default(),
3436 );
3437 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3438 },
3439 );
3440
3441 test_receive_icmpv4_error_helper(
3442 buffer.as_mut(),
3443 Icmpv4TimeExceededCode::TtlExpired,
3444 IcmpTimeExceeded::default(),
3445 |CtxPair { core_ctx, bindings_ctx: _ }| {
3446 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3447 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3448 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3449 assert_eq!(core_ctx.icmp.rx_counters.time_exceeded.ttl_expired.get(), 1);
3450 let err = Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired);
3451 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3452 },
3453 );
3454
3455 test_receive_icmpv4_error_helper(
3456 buffer.as_mut(),
3457 Icmpv4ParameterProblemCode::PointerIndicatesError,
3458 Icmpv4ParameterProblem::new(0),
3459 |CtxPair { core_ctx, bindings_ctx: _ }| {
3460 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3461 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3462 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3463 assert_eq!(
3464 core_ctx.icmp.rx_counters.parameter_problem.pointer_indicates_error.get(),
3465 1
3466 );
3467 let err = Icmpv4ErrorCode::ParameterProblem(
3468 Icmpv4ParameterProblemCode::PointerIndicatesError,
3469 );
3470 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3471 },
3472 );
3473
3474 let mut buffer = <Ipv4 as packet_formats::ip::IpExt>::PacketBuilder::<
3480 NetworkSerializationContext,
3481 >::new(
3482 TEST_ADDRS_V4.local_ip, TEST_ADDRS_V4.remote_ip, 64, IpProto::Udp.into()
3483 )
3484 .wrap_body(EmptyBuf)
3485 .serialize_vec_outer(&mut NetworkSerializationContext::default())
3486 .unwrap();
3487
3488 test_receive_icmpv4_error_helper(
3489 buffer.as_mut(),
3490 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3491 IcmpDestUnreachable::default(),
3492 |CtxPair { core_ctx, bindings_ctx: _ }| {
3493 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3494 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3495 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3496 assert_eq!(
3497 core_ctx.icmp.rx_counters.dest_unreachable.dest_network_unreachable.get(),
3498 1
3499 );
3500 let err = Icmpv4ErrorCode::DestUnreachable(
3501 Icmpv4DestUnreachableCode::DestNetworkUnreachable,
3502 IcmpDestUnreachable::default(),
3503 );
3504 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3505 },
3506 );
3507
3508 test_receive_icmpv4_error_helper(
3509 buffer.as_mut(),
3510 Icmpv4TimeExceededCode::TtlExpired,
3511 IcmpTimeExceeded::default(),
3512 |CtxPair { core_ctx, bindings_ctx: _ }| {
3513 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3514 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3515 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3516 assert_eq!(core_ctx.icmp.rx_counters.time_exceeded.ttl_expired.get(), 1);
3517 let err = Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired);
3518 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3519 },
3520 );
3521
3522 test_receive_icmpv4_error_helper(
3523 buffer.as_mut(),
3524 Icmpv4ParameterProblemCode::PointerIndicatesError,
3525 Icmpv4ParameterProblem::new(0),
3526 |CtxPair { core_ctx, bindings_ctx: _ }| {
3527 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3528 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3529 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3530 assert_eq!(
3531 core_ctx.icmp.rx_counters.parameter_problem.pointer_indicates_error.get(),
3532 1
3533 );
3534 let err = Icmpv4ErrorCode::ParameterProblem(
3535 Icmpv4ParameterProblemCode::PointerIndicatesError,
3536 );
3537 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3538 },
3539 );
3540 }
3541
3542 #[test]
3543 fn test_receive_icmpv6_error() {
3544 const ICMP_ID: u16 = 0x0F;
3547 const SEQ_NUM: u16 = 0xF0;
3548
3549 fn test_receive_icmpv6_error_helper<
3564 C: Debug,
3565 M: IcmpMessage<Ipv6, Code = C> + Debug,
3566 F: Fn(&FakeIcmpCtx<Ipv6>),
3567 >(
3568 original_packet: &mut [u8],
3569 code: C,
3570 msg: M,
3571 f: F,
3572 ) {
3573 set_logger_for_test();
3574
3575 let mut ctx = FakeIcmpCtx::<Ipv6>::default();
3576 let CtxPair { core_ctx, bindings_ctx } = &mut ctx;
3577 <IcmpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
3578 core_ctx,
3579 bindings_ctx,
3580 &FakeDeviceId,
3581 TEST_ADDRS_V6.remote_ip.get().try_into().unwrap(),
3582 TEST_ADDRS_V6.local_ip,
3583 IcmpPacketBuilder::new(TEST_ADDRS_V6.remote_ip, TEST_ADDRS_V6.local_ip, code, msg)
3584 .wrap_body(Buf::new(original_packet, ..))
3585 .serialize_vec_outer(&mut NetworkSerializationContext::default())
3586 .unwrap(),
3587 &mut LocalDeliveryPacketInfo::default(),
3588 None,
3589 )
3590 .unwrap();
3591 f(&ctx);
3592 }
3593 let mut buffer = EmptyBuf
3606 .wrap_in(IcmpPacketBuilder::<Ipv6, _>::new(
3607 TEST_ADDRS_V6.local_ip,
3608 TEST_ADDRS_V6.remote_ip,
3609 IcmpZeroCode,
3610 IcmpEchoRequest::new(ICMP_ID, SEQ_NUM),
3611 ))
3612 .wrap_in(<Ipv6 as packet_formats::ip::IpExt>::PacketBuilder::<
3613 NetworkSerializationContext,
3614 >::new(
3615 TEST_ADDRS_V6.local_ip, TEST_ADDRS_V6.remote_ip, 64, Ipv6Proto::Icmpv6
3616 ))
3617 .serialize_vec_outer(&mut NetworkSerializationContext::default())
3618 .unwrap();
3619
3620 test_receive_icmpv6_error_helper(
3621 buffer.as_mut(),
3622 Icmpv6DestUnreachableCode::NoRoute,
3623 IcmpDestUnreachable::default(),
3624 |CtxPair { core_ctx, bindings_ctx: _ }| {
3625 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3626 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3627 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3628 assert_eq!(core_ctx.icmp.rx_counters.dest_unreachable.no_route.get(), 1);
3629 let err = Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute);
3630 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3631 },
3632 );
3633
3634 test_receive_icmpv6_error_helper(
3635 buffer.as_mut(),
3636 Icmpv6TimeExceededCode::HopLimitExceeded,
3637 IcmpTimeExceeded::default(),
3638 |CtxPair { core_ctx, bindings_ctx: _ }| {
3639 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3640 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3641 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3642 assert_eq!(core_ctx.icmp.rx_counters.time_exceeded.hop_limit_exceeded.get(), 1);
3643 let err = Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded);
3644 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3645 },
3646 );
3647
3648 test_receive_icmpv6_error_helper(
3649 buffer.as_mut(),
3650 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
3651 Icmpv6ParameterProblem::new(0),
3652 |CtxPair { core_ctx, bindings_ctx: _ }| {
3653 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3654 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3655 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 1);
3656 assert_eq!(
3657 core_ctx.icmp.rx_counters.parameter_problem.unrecognized_next_header_type.get(),
3658 1
3659 );
3660 let err = Icmpv6ErrorCode::ParameterProblem(
3661 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
3662 );
3663 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3664 },
3665 );
3666
3667 let mut buffer = EmptyBuf
3674 .wrap_in(<Ipv6 as packet_formats::ip::IpExt>::PacketBuilder::<
3675 NetworkSerializationContext,
3676 >::new(
3677 TEST_ADDRS_V6.local_ip, TEST_ADDRS_V6.remote_ip, 64, Ipv6Proto::Icmpv6
3678 ))
3679 .serialize_vec_outer(&mut NetworkSerializationContext::default())
3680 .unwrap();
3681
3682 test_receive_icmpv6_error_helper(
3683 buffer.as_mut(),
3684 Icmpv6DestUnreachableCode::NoRoute,
3685 IcmpDestUnreachable::default(),
3686 |CtxPair { core_ctx, bindings_ctx: _ }| {
3687 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3688 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3689 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3690 assert_eq!(core_ctx.icmp.rx_counters.dest_unreachable.no_route.get(), 1);
3691 let err = Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute);
3692 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3693 },
3694 );
3695
3696 test_receive_icmpv6_error_helper(
3697 buffer.as_mut(),
3698 Icmpv6TimeExceededCode::HopLimitExceeded,
3699 IcmpTimeExceeded::default(),
3700 |CtxPair { core_ctx, bindings_ctx: _ }| {
3701 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3702 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3703 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3704 assert_eq!(core_ctx.icmp.rx_counters.time_exceeded.hop_limit_exceeded.get(), 1);
3705 let err = Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded);
3706 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3707 },
3708 );
3709
3710 test_receive_icmpv6_error_helper(
3711 buffer.as_mut(),
3712 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
3713 Icmpv6ParameterProblem::new(0),
3714 |CtxPair { core_ctx, bindings_ctx: _ }| {
3715 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3716 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 1);
3717 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3718 assert_eq!(
3719 core_ctx.icmp.rx_counters.parameter_problem.unrecognized_next_header_type.get(),
3720 1
3721 );
3722 let err = Icmpv6ErrorCode::ParameterProblem(
3723 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
3724 );
3725 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3726 },
3727 );
3728
3729 let mut buffer = <Ipv6 as packet_formats::ip::IpExt>::PacketBuilder::<
3735 NetworkSerializationContext,
3736 >::new(
3737 TEST_ADDRS_V6.local_ip, TEST_ADDRS_V6.remote_ip, 64, IpProto::Udp.into()
3738 )
3739 .wrap_body(EmptyBuf)
3740 .serialize_vec_outer(&mut NetworkSerializationContext::default())
3741 .unwrap();
3742
3743 test_receive_icmpv6_error_helper(
3744 buffer.as_mut(),
3745 Icmpv6DestUnreachableCode::NoRoute,
3746 IcmpDestUnreachable::default(),
3747 |CtxPair { core_ctx, bindings_ctx: _ }| {
3748 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3749 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3750 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3751 assert_eq!(core_ctx.icmp.rx_counters.dest_unreachable.no_route.get(), 1);
3752 let err = Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute);
3753 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3754 },
3755 );
3756
3757 test_receive_icmpv6_error_helper(
3758 buffer.as_mut(),
3759 Icmpv6TimeExceededCode::HopLimitExceeded,
3760 IcmpTimeExceeded::default(),
3761 |CtxPair { core_ctx, bindings_ctx: _ }| {
3762 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3763 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3764 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3765 assert_eq!(core_ctx.icmp.rx_counters.time_exceeded.hop_limit_exceeded.get(), 1);
3766 let err = Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded);
3767 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3768 },
3769 );
3770
3771 test_receive_icmpv6_error_helper(
3772 buffer.as_mut(),
3773 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
3774 Icmpv6ParameterProblem::new(0),
3775 |CtxPair { core_ctx, bindings_ctx: _ }| {
3776 assert_eq!(core_ctx.icmp.rx_counters.error.get(), 1);
3777 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_transport_layer.get(), 0);
3778 assert_eq!(core_ctx.icmp.rx_counters.error_delivered_to_socket.get(), 0);
3779 assert_eq!(
3780 core_ctx.icmp.rx_counters.parameter_problem.unrecognized_next_header_type.get(),
3781 1
3782 );
3783 let err = Icmpv6ErrorCode::ParameterProblem(
3784 Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType,
3785 );
3786 assert_eq!(core_ctx.icmp.receive_icmp_error, [err]);
3787 },
3788 );
3789 }
3790
3791 #[test]
3792 fn test_error_rate_limit() {
3793 set_logger_for_test();
3794
3795 fn send_icmpv4_ttl_expired_helper(
3797 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv4>,
3798 ) {
3799 let error = Icmpv4Error::TtlExpired;
3800 core_ctx.send_icmp_error_message(
3801 bindings_ctx,
3802 Some(&FakeDeviceId),
3803 Some(FrameDestination::Individual { local: true }),
3804 TEST_ADDRS_V4.remote_ip.try_into().unwrap(),
3805 TEST_ADDRS_V4.local_ip.try_into().unwrap(),
3806 EmptyBuf,
3807 error,
3808 0,
3809 packet_formats::ip::IpProto::Udp.into(),
3810 &Default::default(),
3811 );
3812 assert_geq!(core_ctx.icmp.tx_counters.time_exceeded.ttl_expired.get(), 1);
3813 }
3814
3815 fn send_icmpv4_parameter_problem_helper(
3817 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv4>,
3818 ) {
3819 let error = Icmpv4Error::ParameterProblem {
3820 code: Icmpv4ParameterProblemCode::PointerIndicatesError,
3821 pointer: 0,
3822 };
3823 core_ctx.send_icmp_error_message(
3824 bindings_ctx,
3825 Some(&FakeDeviceId),
3826 Some(FrameDestination::Individual { local: true }),
3827 TEST_ADDRS_V4.remote_ip.try_into().unwrap(),
3828 TEST_ADDRS_V4.local_ip.try_into().unwrap(),
3829 EmptyBuf,
3830 error,
3831 0,
3832 packet_formats::ip::IpProto::Udp.into(),
3833 &Default::default(),
3834 );
3835 assert_geq!(
3836 core_ctx.icmp.tx_counters.parameter_problem.pointer_indicates_error.get(),
3837 1
3838 );
3839 }
3840
3841 fn send_icmpv4_dest_unreachable_helper(
3843 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv4>,
3844 ) {
3845 core_ctx.send_icmp_error_message(
3846 bindings_ctx,
3847 Some(&FakeDeviceId),
3848 Some(FrameDestination::Individual { local: true }),
3849 TEST_ADDRS_V4.remote_ip.try_into().unwrap(),
3850 TEST_ADDRS_V4.local_ip.try_into().unwrap(),
3851 EmptyBuf,
3852 Icmpv4Error::NetUnreachable,
3853 0,
3854 packet_formats::ip::IpProto::Udp.into(),
3855 &Default::default(),
3856 );
3857 assert_geq!(
3858 core_ctx.icmp.tx_counters.dest_unreachable.dest_network_unreachable.get(),
3859 1
3860 );
3861 }
3862
3863 fn send_icmpv6_ttl_expired_helper(
3865 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv6>,
3866 ) {
3867 core_ctx.send_icmp_error_message(
3868 bindings_ctx,
3869 Some(&FakeDeviceId),
3870 Some(FrameDestination::Individual { local: true }),
3871 TEST_ADDRS_V6.remote_ip.try_into().unwrap(),
3872 TEST_ADDRS_V6.local_ip.try_into().unwrap(),
3873 EmptyBuf,
3874 Icmpv6Error::TtlExpired,
3875 0,
3876 Ipv6Proto::NoNextHeader,
3877 &Default::default(),
3878 );
3879 assert_geq!(core_ctx.icmp.tx_counters.time_exceeded.hop_limit_exceeded.get(), 1);
3880 }
3881
3882 fn send_icmpv6_packet_too_big_helper(
3884 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv6>,
3885 ) {
3886 core_ctx.send_icmp_error_message(
3887 bindings_ctx,
3888 Some(&FakeDeviceId),
3889 Some(FrameDestination::Individual { local: true }),
3890 TEST_ADDRS_V6.remote_ip.try_into().unwrap(),
3891 TEST_ADDRS_V6.local_ip.try_into().unwrap(),
3892 EmptyBuf,
3893 Icmpv6Error::PacketTooBig { mtu: Mtu::new(1280) },
3894 0,
3895 Ipv6Proto::NoNextHeader,
3896 &Default::default(),
3897 );
3898 assert_geq!(core_ctx.icmp.tx_counters.packet_too_big.get(), 1);
3899 }
3900
3901 fn send_icmpv6_parameter_problem_helper(
3903 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv6>,
3904 ) {
3905 let error = Icmpv6Error::ParameterProblem {
3906 code: Icmpv6ParameterProblemCode::ErroneousHeaderField,
3907 pointer: 0,
3908 allow_dst_multicast: false,
3909 };
3910 core_ctx.send_icmp_error_message(
3911 bindings_ctx,
3912 Some(&FakeDeviceId),
3913 Some(FrameDestination::Individual { local: true }),
3914 TEST_ADDRS_V6.remote_ip.try_into().unwrap(),
3915 TEST_ADDRS_V6.local_ip.try_into().unwrap(),
3916 EmptyBuf,
3917 error,
3918 0,
3919 Ipv6Proto::NoNextHeader,
3920 &Default::default(),
3921 );
3922 assert_geq!(
3923 core_ctx.icmp.tx_counters.parameter_problem.erroneous_header_field.get(),
3924 1
3925 );
3926 }
3927
3928 fn send_icmpv6_dest_unreachable_helper(
3930 CtxPair { core_ctx, bindings_ctx }: &mut FakeIcmpCtx<Ipv6>,
3931 ) {
3932 core_ctx.send_icmp_error_message(
3933 bindings_ctx,
3934 Some(&FakeDeviceId),
3935 Some(FrameDestination::Individual { local: true }),
3936 TEST_ADDRS_V6.remote_ip.try_into().unwrap(),
3937 TEST_ADDRS_V6.local_ip.try_into().unwrap(),
3938 EmptyBuf,
3939 Icmpv6Error::NetUnreachable,
3940 0,
3941 Ipv6Proto::NoNextHeader,
3942 &Default::default(),
3943 );
3944 assert_geq!(core_ctx.icmp.tx_counters.dest_unreachable.no_route.get(), 1);
3945 }
3946
3947 fn run_test<I: IcmpTestIpExt, W: Fn(u64) -> FakeIcmpCtx<I>, S: Fn(&mut FakeIcmpCtx<I>)>(
3951 with_errors_per_second: W,
3952 send: S,
3953 ) {
3954 const ERRORS_PER_SECOND: u64 = 64;
3968
3969 let mut ctx = with_errors_per_second(ERRORS_PER_SECOND);
3970
3971 for i in 0..ERRORS_PER_SECOND {
3972 send(&mut ctx);
3973 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), i + 1);
3974 }
3975
3976 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), ERRORS_PER_SECOND);
3977 send(&mut ctx);
3978 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), ERRORS_PER_SECOND);
3979
3980 let mut ctx = with_errors_per_second(0);
3984 send(&mut ctx);
3985 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), 0);
3986 ctx.bindings_ctx.timers.instant.sleep(Duration::from_secs(1));
3987 send(&mut ctx);
3988 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), 0);
3989 ctx.bindings_ctx.timers.instant.sleep(Duration::from_secs(1));
3990 send(&mut ctx);
3991 assert_eq!(ctx.core_ctx.icmp.tx_counters.error.get(), 0);
3992 }
3993
3994 fn with_errors_per_second_v4(errors_per_second: u64) -> FakeIcmpCtx<Ipv4> {
3995 CtxPair::with_core_ctx(FakeIcmpCoreCtx::with_errors_per_second(errors_per_second))
3996 }
3997 run_test::<Ipv4, _, _>(with_errors_per_second_v4, send_icmpv4_ttl_expired_helper);
3998 run_test::<Ipv4, _, _>(with_errors_per_second_v4, send_icmpv4_parameter_problem_helper);
3999 run_test::<Ipv4, _, _>(with_errors_per_second_v4, send_icmpv4_dest_unreachable_helper);
4000
4001 fn with_errors_per_second_v6(errors_per_second: u64) -> FakeIcmpCtx<Ipv6> {
4002 CtxPair::with_core_ctx(FakeIcmpCoreCtx::with_errors_per_second(errors_per_second))
4003 }
4004
4005 run_test::<Ipv6, _, _>(with_errors_per_second_v6, send_icmpv6_ttl_expired_helper);
4006 run_test::<Ipv6, _, _>(with_errors_per_second_v6, send_icmpv6_packet_too_big_helper);
4007 run_test::<Ipv6, _, _>(with_errors_per_second_v6, send_icmpv6_parameter_problem_helper);
4008 run_test::<Ipv6, _, _>(with_errors_per_second_v6, send_icmpv6_dest_unreachable_helper);
4009 }
4010}