1use alloc::collections::HashMap;
8
9use lock_order::lock::{DelegatedOrderedLockAccess, LockLevelFor};
10use lock_order::relation::LockBefore;
11use log::trace;
12use net_types::ip::{Ip, IpMarked, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr, Ipv6SourceAddr};
13use net_types::{MulticastAddr, SpecifiedAddr};
14use netstack3_base::socket::SocketIpAddr;
15use netstack3_base::{
16 CounterContext, Icmpv4ErrorCode, Icmpv6ErrorCode, Marks, ResourceCounterContext, TokenBucket,
17 WeakDeviceIdentifier,
18};
19use netstack3_datagram as datagram;
20use netstack3_device::{for_any_device_id, BaseDeviceId, DeviceId, DeviceStateSpec, WeakDeviceId};
21use netstack3_icmp_echo::{
22 self as icmp_echo, IcmpEchoBoundStateContext, IcmpEchoContextMarker,
23 IcmpEchoIpTransportContext, IcmpEchoStateContext, IcmpSocketId, IcmpSocketSet, IcmpSocketState,
24 IcmpSockets,
25};
26use netstack3_ip::device::{self, IpDeviceBindingsContext, IpDeviceIpExt};
27use netstack3_ip::gmp::{IgmpCounters, MldCounters};
28use netstack3_ip::icmp::{
29 self, IcmpIpTransportContext, IcmpRxCounters, IcmpState, IcmpTxCounters, InnerIcmpContext,
30 InnerIcmpv4Context, NdpCounters,
31};
32use netstack3_ip::multicast_forwarding::MulticastForwardingState;
33use netstack3_ip::raw::RawIpSocketMap;
34use netstack3_ip::{
35 self as ip, FragmentContext, IpCounters, IpDeviceContext, IpHeaderInfo, IpLayerBindingsContext,
36 IpLayerIpExt, IpPacketFragmentCache, IpRouteTableContext, IpRouteTablesContext, IpStateContext,
37 IpStateInner, IpTransportContext, IpTransportDispatchContext, LocalDeliveryPacketInfo,
38 MulticastMembershipHandler, PmtuCache, PmtuContext, ResolveRouteError, ResolvedRoute,
39 RoutingTable, RoutingTableId, RulesTable, TransportReceiveError,
40};
41use netstack3_sync::rc::Primary;
42use netstack3_sync::RwLock;
43use netstack3_tcp::TcpIpTransportContext;
44use netstack3_udp::UdpIpTransportContext;
45use packet::BufferMut;
46use packet_formats::ip::{IpProto, Ipv4Proto, Ipv6Proto};
47
48use crate::context::prelude::*;
49use crate::context::WrapLockLevel;
50use crate::{BindingsContext, BindingsTypes, CoreCtx, StackState};
51
52impl<I, BT, L> FragmentContext<I, BT> for CoreCtx<'_, BT, L>
53where
54 I: IpLayerIpExt,
55 BT: BindingsTypes,
56 L: LockBefore<crate::lock_ordering::IpStateFragmentCache<I>>,
57{
58 fn with_state_mut<O, F: FnOnce(&mut IpPacketFragmentCache<I, BT>) -> O>(&mut self, cb: F) -> O {
59 let mut cache = self.lock::<crate::lock_ordering::IpStateFragmentCache<I>>();
60 cb(&mut cache)
61 }
62}
63
64impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpStatePmtuCache<Ipv4>>>
65 PmtuContext<Ipv4, BC> for CoreCtx<'_, BC, L>
66{
67 fn with_state_mut<O, F: FnOnce(&mut PmtuCache<Ipv4, BC>) -> O>(&mut self, cb: F) -> O {
68 let mut cache = self.lock::<crate::lock_ordering::IpStatePmtuCache<Ipv4>>();
69 cb(&mut cache)
70 }
71}
72
73impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpStatePmtuCache<Ipv6>>>
74 PmtuContext<Ipv6, BC> for CoreCtx<'_, BC, L>
75{
76 fn with_state_mut<O, F: FnOnce(&mut PmtuCache<Ipv6, BC>) -> O>(&mut self, cb: F) -> O {
77 let mut cache = self.lock::<crate::lock_ordering::IpStatePmtuCache<Ipv6>>();
78 cb(&mut cache)
79 }
80}
81
82impl<
83 I: Ip + IpDeviceIpExt + IpLayerIpExt,
84 BC: BindingsContext
85 + IpDeviceBindingsContext<I, Self::DeviceId>
86 + IpLayerBindingsContext<I, Self::DeviceId>,
87 L: LockBefore<crate::lock_ordering::IpState<I>>,
88 > MulticastMembershipHandler<I, BC> for CoreCtx<'_, BC, L>
89where
90 Self: device::IpDeviceConfigurationContext<I, BC> + IpStateContext<I> + IpDeviceContext<I>,
91{
92 fn join_multicast_group(
93 &mut self,
94 bindings_ctx: &mut BC,
95 device: &Self::DeviceId,
96 addr: MulticastAddr<I::Addr>,
97 ) {
98 ip::device::join_ip_multicast::<I, _, _>(self, bindings_ctx, device, addr)
99 }
100
101 fn leave_multicast_group(
102 &mut self,
103 bindings_ctx: &mut BC,
104 device: &Self::DeviceId,
105 addr: MulticastAddr<I::Addr>,
106 ) {
107 ip::device::leave_ip_multicast::<I, _, _>(self, bindings_ctx, device, addr)
108 }
109
110 fn select_device_for_multicast_group(
111 &mut self,
112 addr: MulticastAddr<I::Addr>,
113 marks: &Marks,
114 ) -> Result<Self::DeviceId, ResolveRouteError> {
115 let remote_ip = SocketIpAddr::new_from_multicast(addr);
116 let ResolvedRoute {
117 src_addr: _,
118 device,
119 local_delivery_device,
120 next_hop: _,
121 internal_forwarding: _,
122 } = ip::resolve_output_route_to_destination(self, None, None, Some(remote_ip), marks)?;
123 debug_assert!(local_delivery_device.is_none(), "{:?}", local_delivery_device);
126 Ok(device)
127 }
128}
129
130impl<BT: BindingsTypes, I: datagram::DualStackIpExt, L> CounterContext<IcmpTxCounters<I>>
131 for CoreCtx<'_, BT, L>
132{
133 fn counters(&self) -> &IcmpTxCounters<I> {
134 &self
135 .unlocked_access::<crate::lock_ordering::UnlockedState>()
136 .inner_icmp_state::<I>()
137 .tx_counters
138 }
139}
140
141impl<BT: BindingsTypes, I: datagram::DualStackIpExt, L> CounterContext<IcmpRxCounters<I>>
142 for CoreCtx<'_, BT, L>
143{
144 fn counters(&self) -> &IcmpRxCounters<I> {
145 &self
146 .unlocked_access::<crate::lock_ordering::UnlockedState>()
147 .inner_icmp_state::<I>()
148 .rx_counters
149 }
150}
151
152impl<BT: BindingsTypes, L> CounterContext<IgmpCounters> for CoreCtx<'_, BT, L> {
153 fn counters(&self) -> &IgmpCounters {
154 &self
155 .unlocked_access::<crate::lock_ordering::UnlockedState>()
156 .inner_ip_state::<Ipv4>()
157 .igmp_counters()
158 }
159}
160
161impl<BT: BindingsTypes, L> ResourceCounterContext<DeviceId<BT>, IgmpCounters>
162 for CoreCtx<'_, BT, L>
163{
164 fn per_resource_counters<'a>(&'a self, device_id: &'a DeviceId<BT>) -> &'a IgmpCounters {
165 for_any_device_id!(
166 DeviceId,
167 device_id,
168 id => self.per_resource_counters(id)
169 )
170 }
171}
172
173impl<BT: BindingsTypes, D: DeviceStateSpec, L>
174 ResourceCounterContext<BaseDeviceId<D, BT>, IgmpCounters> for CoreCtx<'_, BT, L>
175{
176 fn per_resource_counters<'a>(&'a self, device_id: &'a BaseDeviceId<D, BT>) -> &'a IgmpCounters {
177 device_id
178 .device_state(
179 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
180 )
181 .as_ref()
182 .igmp_counters()
183 }
184}
185
186impl<BT: BindingsTypes, L> CounterContext<MldCounters> for CoreCtx<'_, BT, L> {
187 fn counters(&self) -> &MldCounters {
188 &self
189 .unlocked_access::<crate::lock_ordering::UnlockedState>()
190 .inner_ip_state::<Ipv4>()
191 .mld_counters()
192 }
193}
194
195impl<BT: BindingsTypes, L> ResourceCounterContext<DeviceId<BT>, MldCounters>
196 for CoreCtx<'_, BT, L>
197{
198 fn per_resource_counters<'a>(&'a self, device_id: &'a DeviceId<BT>) -> &'a MldCounters {
199 for_any_device_id!(
200 DeviceId,
201 device_id,
202 id => self.per_resource_counters(id)
203 )
204 }
205}
206
207impl<BT: BindingsTypes, D: DeviceStateSpec, L>
208 ResourceCounterContext<BaseDeviceId<D, BT>, MldCounters> for CoreCtx<'_, BT, L>
209{
210 fn per_resource_counters<'a>(&'a self, device_id: &'a BaseDeviceId<D, BT>) -> &'a MldCounters {
211 device_id
212 .device_state(
213 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
214 )
215 .as_ref()
216 .mld_counters()
217 }
218}
219
220impl<BT: BindingsTypes, L> CounterContext<NdpCounters> for CoreCtx<'_, BT, L> {
221 fn counters(&self) -> &NdpCounters {
222 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().ipv6.icmp.ndp_counters
223 }
224}
225
226impl<
227 BC: BindingsContext,
228 L: LockBefore<crate::lock_ordering::IcmpBoundMap<Ipv4>>
229 + LockBefore<crate::lock_ordering::TcpAllSocketsSet<Ipv4>>
230 + LockBefore<crate::lock_ordering::UdpAllSocketsSet<Ipv4>>,
231 > InnerIcmpv4Context<BC> for CoreCtx<'_, BC, L>
232{
233 fn should_send_timestamp_reply(&self) -> bool {
234 self.unlocked_access::<crate::lock_ordering::UnlockedState>().ipv4.icmp.send_timestamp_reply
235 }
236}
237
238impl<BT: BindingsTypes, I: IpLayerIpExt, L> CounterContext<IpCounters<I>> for CoreCtx<'_, BT, L> {
239 fn counters(&self) -> &IpCounters<I> {
240 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().inner_ip_state().counters()
241 }
242}
243
244#[netstack3_macros::instantiate_ip_impl_block(I)]
245impl<I, BC, L> IpStateContext<I> for CoreCtx<'_, BC, L>
246where
247 I: IpLayerIpExt,
248 BC: BindingsContext,
249 L: LockBefore<crate::lock_ordering::IpStateRulesTable<I>>,
250{
251 type IpRouteTablesCtx<'a> =
252 CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::IpStateRulesTable<I>>>;
253
254 fn with_rules_table<
255 O,
256 F: FnOnce(&mut Self::IpRouteTablesCtx<'_>, &RulesTable<I, Self::DeviceId>) -> O,
257 >(
258 &mut self,
259 cb: F,
260 ) -> O {
261 let (rules_table, mut restricted) =
262 self.read_lock_and::<crate::lock_ordering::IpStateRulesTable<I>>();
263 cb(&mut restricted, &rules_table)
264 }
265
266 fn with_rules_table_mut<
267 O,
268 F: FnOnce(&mut Self::IpRouteTablesCtx<'_>, &mut RulesTable<I, Self::DeviceId>) -> O,
269 >(
270 &mut self,
271 cb: F,
272 ) -> O {
273 let (mut rules_table, mut restricted) =
274 self.write_lock_and::<crate::lock_ordering::IpStateRulesTable<I>>();
275 cb(&mut restricted, &mut rules_table)
276 }
277}
278
279#[netstack3_macros::instantiate_ip_impl_block(I)]
280impl<I, BC, L> IpRouteTablesContext<I> for CoreCtx<'_, BC, L>
281where
282 I: IpLayerIpExt,
283 BC: BindingsContext,
284 L: LockBefore<crate::lock_ordering::IpStateRoutingTables<I>>,
285{
286 type Ctx<'a> = CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::IpStateRoutingTables<I>>>;
287
288 fn main_table_id(&self) -> RoutingTableId<I, Self::DeviceId> {
289 self.unlocked_access::<crate::lock_ordering::UnlockedState>()
290 .inner_ip_state()
291 .main_table_id()
292 .clone()
293 }
294
295 fn with_ip_routing_tables<
296 O,
297 F: FnOnce(
298 &mut Self::Ctx<'_>,
299 &HashMap<
300 RoutingTableId<I, Self::DeviceId>,
301 Primary<RwLock<RoutingTable<I, Self::DeviceId>>>,
302 >,
303 ) -> O,
304 >(
305 &mut self,
306 cb: F,
307 ) -> O {
308 let (table, mut ctx) = self.lock_and::<crate::lock_ordering::IpStateRoutingTables<I>>();
309 cb(&mut ctx, &table)
310 }
311
312 fn with_ip_routing_tables_mut<
313 O,
314 F: FnOnce(
315 &mut HashMap<
316 RoutingTableId<I, Self::DeviceId>,
317 Primary<RwLock<RoutingTable<I, Self::DeviceId>>>,
318 >,
319 ) -> O,
320 >(
321 &mut self,
322 cb: F,
323 ) -> O {
324 let mut tables = self.lock::<crate::lock_ordering::IpStateRoutingTables<I>>();
325 cb(&mut *tables)
326 }
327}
328
329#[netstack3_macros::instantiate_ip_impl_block(I)]
330impl<I, BC, L> IpRouteTableContext<I> for CoreCtx<'_, BC, L>
331where
332 I: IpLayerIpExt,
333 BC: BindingsContext,
334 L: LockBefore<crate::lock_ordering::IpStateRoutingTable<I>>,
335{
336 type IpDeviceIdCtx<'a> =
337 CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::IpStateRoutingTable<I>>>;
338
339 fn with_ip_routing_table<
340 O,
341 F: FnOnce(&mut Self::IpDeviceIdCtx<'_>, &RoutingTable<I, Self::DeviceId>) -> O,
342 >(
343 &mut self,
344 table_id: &RoutingTableId<I, Self::DeviceId>,
345 cb: F,
346 ) -> O {
347 let mut table = self.adopt(table_id);
348 let (table, mut restricted) = table
349 .read_lock_with_and::<crate::lock_ordering::IpStateRoutingTable<I>, _>(|c| c.right());
350 let mut restricted = restricted.cast_core_ctx();
351 cb(&mut restricted, &table)
352 }
353
354 fn with_ip_routing_table_mut<
355 O,
356 F: FnOnce(&mut Self::IpDeviceIdCtx<'_>, &mut RoutingTable<I, Self::DeviceId>) -> O,
357 >(
358 &mut self,
359 table_id: &RoutingTableId<I, Self::DeviceId>,
360 cb: F,
361 ) -> O {
362 let mut table = self.adopt(table_id);
363 let (mut table, mut restricted) = table
364 .write_lock_with_and::<crate::lock_ordering::IpStateRoutingTable<I>, _>(|c| c.right());
365 let mut restricted = restricted.cast_core_ctx();
366 cb(&mut restricted, &mut table)
367 }
368}
369
370impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IcmpAllSocketsSet<Ipv4>>>
371 IpTransportDispatchContext<Ipv4, BC> for CoreCtx<'_, BC, L>
372{
373 fn dispatch_receive_ip_packet<B: BufferMut, H: IpHeaderInfo<Ipv4>>(
374 &mut self,
375 bindings_ctx: &mut BC,
376 device: &Self::DeviceId,
377 src_ip: Ipv4Addr,
378 dst_ip: SpecifiedAddr<Ipv4Addr>,
379 proto: Ipv4Proto,
380 body: B,
381 info: &LocalDeliveryPacketInfo<Ipv4, H>,
382 ) -> Result<(), TransportReceiveError> {
383 match proto {
384 Ipv4Proto::Icmp => {
385 <IcmpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_ip_packet(
386 self,
387 bindings_ctx,
388 device,
389 src_ip,
390 dst_ip,
391 body,
392 info,
393 )
394 .map_err(|(_body, err)| err)
395 }
396 Ipv4Proto::Igmp => {
397 device::receive_igmp_packet(self, bindings_ctx, device, src_ip, dst_ip, body, info);
398 Ok(())
399 }
400 Ipv4Proto::Proto(IpProto::Udp) => {
401 <UdpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_ip_packet(
402 self,
403 bindings_ctx,
404 device,
405 src_ip,
406 dst_ip,
407 body,
408 info,
409 )
410 .map_err(|(_body, err)| err)
411 }
412 Ipv4Proto::Proto(IpProto::Tcp) => {
413 <TcpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_ip_packet(
414 self,
415 bindings_ctx,
416 device,
417 src_ip,
418 dst_ip,
419 body,
420 info,
421 )
422 .map_err(|(_body, err)| err)
423 }
424 _ => Err(TransportReceiveError::ProtocolUnsupported),
427 }
428 }
429}
430
431impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IcmpAllSocketsSet<Ipv6>>>
432 IpTransportDispatchContext<Ipv6, BC> for CoreCtx<'_, BC, L>
433{
434 fn dispatch_receive_ip_packet<B: BufferMut, H: IpHeaderInfo<Ipv6>>(
435 &mut self,
436 bindings_ctx: &mut BC,
437 device: &Self::DeviceId,
438 src_ip: Ipv6SourceAddr,
439 dst_ip: SpecifiedAddr<Ipv6Addr>,
440 proto: Ipv6Proto,
441 body: B,
442 info: &LocalDeliveryPacketInfo<Ipv6, H>,
443 ) -> Result<(), TransportReceiveError> {
444 match proto {
445 Ipv6Proto::Icmpv6 => {
446 <IcmpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
447 self,
448 bindings_ctx,
449 device,
450 src_ip,
451 dst_ip,
452 body,
453 info,
454 )
455 .map_err(|(_body, err)| err)
456 }
457 Ipv6Proto::NoNextHeader => Ok(()),
461 Ipv6Proto::Proto(IpProto::Tcp) => {
462 <TcpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
463 self,
464 bindings_ctx,
465 device,
466 src_ip,
467 dst_ip,
468 body,
469 info,
470 )
471 .map_err(|(_body, err)| err)
472 }
473 Ipv6Proto::Proto(IpProto::Udp) => {
474 <UdpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
475 self,
476 bindings_ctx,
477 device,
478 src_ip,
479 dst_ip,
480 body,
481 info,
482 )
483 .map_err(|(_body, err)| err)
484 }
485 _ => Err(TransportReceiveError::ProtocolUnsupported),
488 }
489 }
490}
491
492impl<
493 BC: BindingsContext,
494 L: LockBefore<crate::lock_ordering::IcmpBoundMap<Ipv4>>
495 + LockBefore<crate::lock_ordering::TcpAllSocketsSet<Ipv4>>
496 + LockBefore<crate::lock_ordering::UdpAllSocketsSet<Ipv4>>,
497 > InnerIcmpContext<Ipv4, BC> for CoreCtx<'_, BC, L>
498{
499 type EchoTransportContext = IcmpEchoIpTransportContext;
500
501 fn receive_icmp_error(
502 &mut self,
503 bindings_ctx: &mut BC,
504 device: &DeviceId<BC>,
505 original_src_ip: Option<SpecifiedAddr<Ipv4Addr>>,
506 original_dst_ip: SpecifiedAddr<Ipv4Addr>,
507 original_proto: Ipv4Proto,
508 original_body: &[u8],
509 err: Icmpv4ErrorCode,
510 ) {
511 CounterContext::<IpCounters<Ipv4>>::counters(self).receive_icmp_error.increment();
512 trace!("InnerIcmpContext<Ipv4>::receive_icmp_error({:?})", err);
513
514 match original_proto {
515 Ipv4Proto::Icmp => {
516 <IcmpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_icmp_error(
517 self,
518 bindings_ctx,
519 device,
520 original_src_ip,
521 original_dst_ip,
522 original_body,
523 err,
524 )
525 }
526 Ipv4Proto::Proto(IpProto::Tcp) => {
527 <TcpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_icmp_error(
528 self,
529 bindings_ctx,
530 device,
531 original_src_ip,
532 original_dst_ip,
533 original_body,
534 err,
535 )
536 }
537 Ipv4Proto::Proto(IpProto::Udp) => {
538 <UdpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_icmp_error(
539 self,
540 bindings_ctx,
541 device,
542 original_src_ip,
543 original_dst_ip,
544 original_body,
545 err,
546 )
547 }
548 _ => <() as IpTransportContext<Ipv4, _, _>>::receive_icmp_error(
551 self,
552 bindings_ctx,
553 device,
554 original_src_ip,
555 original_dst_ip,
556 original_body,
557 err,
558 ),
559 }
560 }
561
562 fn with_error_send_bucket_mut<O, F: FnOnce(&mut TokenBucket<BC::Instant>) -> O>(
563 &mut self,
564 cb: F,
565 ) -> O {
566 cb(&mut self.lock::<crate::lock_ordering::IcmpTokenBucket<Ipv4>>())
567 }
568}
569
570impl<
571 BC: BindingsContext,
572 L: LockBefore<crate::lock_ordering::IcmpBoundMap<Ipv6>>
573 + LockBefore<crate::lock_ordering::TcpAllSocketsSet<Ipv6>>
574 + LockBefore<crate::lock_ordering::UdpAllSocketsSet<Ipv6>>,
575 > InnerIcmpContext<Ipv6, BC> for CoreCtx<'_, BC, L>
576{
577 type EchoTransportContext = IcmpEchoIpTransportContext;
578
579 fn receive_icmp_error(
580 &mut self,
581 bindings_ctx: &mut BC,
582 device: &DeviceId<BC>,
583 original_src_ip: Option<SpecifiedAddr<Ipv6Addr>>,
584 original_dst_ip: SpecifiedAddr<Ipv6Addr>,
585 original_next_header: Ipv6Proto,
586 original_body: &[u8],
587 err: Icmpv6ErrorCode,
588 ) {
589 CounterContext::<IpCounters<Ipv6>>::counters(self).receive_icmp_error.increment();
590 trace!("InnerIcmpContext<Ipv6>::receive_icmp_error({:?})", err);
591
592 match original_next_header {
593 Ipv6Proto::Icmpv6 => {
594 <IcmpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_icmp_error(
595 self,
596 bindings_ctx,
597 device,
598 original_src_ip,
599 original_dst_ip,
600 original_body,
601 err,
602 )
603 }
604 Ipv6Proto::Proto(IpProto::Tcp) => {
605 <TcpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_icmp_error(
606 self,
607 bindings_ctx,
608 device,
609 original_src_ip,
610 original_dst_ip,
611 original_body,
612 err,
613 )
614 }
615 Ipv6Proto::Proto(IpProto::Udp) => {
616 <UdpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_icmp_error(
617 self,
618 bindings_ctx,
619 device,
620 original_src_ip,
621 original_dst_ip,
622 original_body,
623 err,
624 )
625 }
626 _ => <() as IpTransportContext<Ipv6, _, _>>::receive_icmp_error(
629 self,
630 bindings_ctx,
631 device,
632 original_src_ip,
633 original_dst_ip,
634 original_body,
635 err,
636 ),
637 }
638 }
639
640 fn with_error_send_bucket_mut<O, F: FnOnce(&mut TokenBucket<BC::Instant>) -> O>(
641 &mut self,
642 cb: F,
643 ) -> O {
644 cb(&mut self.lock::<crate::lock_ordering::IcmpTokenBucket<Ipv6>>())
645 }
646}
647
648impl<L, BC: BindingsContext> icmp::IcmpStateContext for CoreCtx<'_, BC, L> {}
649
650impl<BT: BindingsTypes, L> IcmpEchoContextMarker for CoreCtx<'_, BT, L> {}
651
652#[netstack3_macros::instantiate_ip_impl_block(I)]
653impl<I, BC: BindingsContext, L: LockBefore<crate::lock_ordering::IcmpAllSocketsSet<I>>>
654 IcmpEchoStateContext<I, BC> for CoreCtx<'_, BC, L>
655{
656 type SocketStateCtx<'a> =
657 CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::IcmpSocketState<I>>>;
658
659 fn with_all_sockets_mut<O, F: FnOnce(&mut IcmpSocketSet<I, Self::WeakDeviceId, BC>) -> O>(
660 &mut self,
661 cb: F,
662 ) -> O {
663 cb(&mut self.write_lock::<crate::lock_ordering::IcmpAllSocketsSet<I>>())
664 }
665
666 fn with_all_sockets<O, F: FnOnce(&IcmpSocketSet<I, Self::WeakDeviceId, BC>) -> O>(
667 &mut self,
668 cb: F,
669 ) -> O {
670 cb(&self.read_lock::<crate::lock_ordering::IcmpAllSocketsSet<I>>())
671 }
672
673 fn with_socket_state<
674 O,
675 F: FnOnce(&mut Self::SocketStateCtx<'_>, &IcmpSocketState<I, Self::WeakDeviceId, BC>) -> O,
676 >(
677 &mut self,
678 id: &IcmpSocketId<I, Self::WeakDeviceId, BC>,
679 cb: F,
680 ) -> O {
681 let mut locked = self.adopt(id);
682 let (socket_state, mut restricted) =
683 locked.read_lock_with_and::<crate::lock_ordering::IcmpSocketState<I>, _>(|c| c.right());
684 let mut restricted = restricted.cast_core_ctx();
685 cb(&mut restricted, &socket_state)
686 }
687
688 fn with_socket_state_mut<
689 O,
690 F: FnOnce(&mut Self::SocketStateCtx<'_>, &mut IcmpSocketState<I, Self::WeakDeviceId, BC>) -> O,
691 >(
692 &mut self,
693 id: &IcmpSocketId<I, Self::WeakDeviceId, BC>,
694 cb: F,
695 ) -> O {
696 let mut locked = self.adopt(id);
697 let (mut socket_state, mut restricted) = locked
698 .write_lock_with_and::<crate::lock_ordering::IcmpSocketState<I>, _>(|c| c.right());
699 let mut restricted = restricted.cast_core_ctx();
700 cb(&mut restricted, &mut socket_state)
701 }
702
703 fn with_bound_state_context<O, F: FnOnce(&mut Self::SocketStateCtx<'_>) -> O>(
704 &mut self,
705 cb: F,
706 ) -> O {
707 cb(&mut self.cast_locked::<crate::lock_ordering::IcmpSocketState<I>>())
708 }
709
710 fn for_each_socket<
711 F: FnMut(
712 &mut Self::SocketStateCtx<'_>,
713 &IcmpSocketId<I, Self::WeakDeviceId, BC>,
714 &IcmpSocketState<I, Self::WeakDeviceId, BC>,
715 ),
716 >(
717 &mut self,
718 mut cb: F,
719 ) {
720 let (all_sockets, mut locked) =
721 self.read_lock_and::<crate::lock_ordering::IcmpAllSocketsSet<I>>();
722 all_sockets.keys().for_each(|id| {
723 let id = IcmpSocketId::from(id.clone());
724 let mut locked = locked.adopt(&id);
725 let (socket_state, mut restricted) = locked
726 .read_lock_with_and::<crate::lock_ordering::IcmpSocketState<I>, _>(|c| c.right());
727 let mut restricted = restricted.cast_core_ctx();
728 cb(&mut restricted, &id, &socket_state);
729 });
730 }
731}
732
733#[netstack3_macros::instantiate_ip_impl_block(I)]
734impl<I, BC: BindingsContext, L: LockBefore<crate::lock_ordering::IcmpBoundMap<I>>>
735 IcmpEchoBoundStateContext<I, BC> for CoreCtx<'_, BC, L>
736{
737 type IpSocketsCtx<'a> = CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::IcmpBoundMap<I>>>;
738 fn with_icmp_ctx_and_sockets_mut<
739 O,
740 F: FnOnce(
741 &mut Self::IpSocketsCtx<'_>,
742 &mut icmp_echo::BoundSockets<I, Self::WeakDeviceId, BC>,
743 ) -> O,
744 >(
745 &mut self,
746 cb: F,
747 ) -> O {
748 let (mut sockets, mut core_ctx) =
749 self.write_lock_and::<crate::lock_ordering::IcmpBoundMap<I>>();
750 cb(&mut core_ctx, &mut sockets)
751 }
752}
753
754impl<I: IpLayerIpExt, BT: BindingsTypes> DelegatedOrderedLockAccess<IpPacketFragmentCache<I, BT>>
755 for StackState<BT>
756{
757 type Inner = IpStateInner<I, DeviceId<BT>, BT>;
758 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
759 self.inner_ip_state()
760 }
761}
762
763impl<I: IpLayerIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
764 for crate::lock_ordering::IpStateFragmentCache<I>
765{
766 type Data = IpPacketFragmentCache<I, BT>;
767}
768
769impl<I: IpLayerIpExt, BT: BindingsTypes> DelegatedOrderedLockAccess<PmtuCache<I, BT>>
770 for StackState<BT>
771{
772 type Inner = IpStateInner<I, DeviceId<BT>, BT>;
773 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
774 self.inner_ip_state()
775 }
776}
777
778impl<I: IpLayerIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
779 for crate::lock_ordering::IpStateRulesTable<I>
780{
781 type Data = RulesTable<I, DeviceId<BT>>;
782}
783
784impl<I: IpLayerIpExt, BT: BindingsTypes> DelegatedOrderedLockAccess<RulesTable<I, DeviceId<BT>>>
785 for StackState<BT>
786{
787 type Inner = IpStateInner<I, DeviceId<BT>, BT>;
788 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
789 self.inner_ip_state()
790 }
791}
792
793impl<I: IpLayerIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
794 for crate::lock_ordering::IpStatePmtuCache<I>
795{
796 type Data = PmtuCache<I, BT>;
797}
798
799impl<I: IpLayerIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
800 for crate::lock_ordering::IpStateRoutingTables<I>
801{
802 type Data =
803 HashMap<RoutingTableId<I, DeviceId<BT>>, Primary<RwLock<RoutingTable<I, DeviceId<BT>>>>>;
804}
805
806impl<I: IpLayerIpExt, BT: BindingsTypes>
807 DelegatedOrderedLockAccess<
808 HashMap<RoutingTableId<I, DeviceId<BT>>, Primary<RwLock<RoutingTable<I, DeviceId<BT>>>>>,
809 > for StackState<BT>
810{
811 type Inner = IpStateInner<I, DeviceId<BT>, BT>;
812 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
813 self.inner_ip_state()
814 }
815}
816
817impl<I: IpLayerIpExt, BT: BindingsTypes> LockLevelFor<RoutingTableId<I, DeviceId<BT>>>
818 for crate::lock_ordering::IpStateRoutingTable<I>
819{
820 type Data = RoutingTable<I, DeviceId<BT>>;
821}
822
823impl<I: IpLayerIpExt, BT: BindingsTypes>
824 DelegatedOrderedLockAccess<MulticastForwardingState<I, DeviceId<BT>, BT>> for StackState<BT>
825{
826 type Inner = IpStateInner<I, DeviceId<BT>, BT>;
827 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
828 self.inner_ip_state()
829 }
830}
831
832impl<I: IpLayerIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
833 for crate::lock_ordering::IpMulticastForwardingState<I>
834{
835 type Data = MulticastForwardingState<I, DeviceId<BT>, BT>;
836}
837
838impl<I: IpLayerIpExt, BT: BindingsTypes>
839 DelegatedOrderedLockAccess<RawIpSocketMap<I, WeakDeviceId<BT>, BT>> for StackState<BT>
840{
841 type Inner = IpStateInner<I, DeviceId<BT>, BT>;
842 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
843 self.inner_ip_state()
844 }
845}
846
847impl<I: IpLayerIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
848 for crate::lock_ordering::AllRawIpSockets<I>
849{
850 type Data = RawIpSocketMap<I, WeakDeviceId<BT>, BT>;
851}
852
853impl<I: datagram::DualStackIpExt, BT: BindingsTypes>
854 DelegatedOrderedLockAccess<icmp_echo::BoundSockets<I, WeakDeviceId<BT>, BT>>
855 for StackState<BT>
856{
857 type Inner = IcmpSockets<I, WeakDeviceId<BT>, BT>;
858 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
859 &self.transport.icmp_echo_state()
860 }
861}
862
863impl<I: datagram::DualStackIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
864 for crate::lock_ordering::IcmpBoundMap<I>
865{
866 type Data = icmp_echo::BoundSockets<I, WeakDeviceId<BT>, BT>;
867}
868
869impl<I: datagram::DualStackIpExt, BT: BindingsTypes>
870 DelegatedOrderedLockAccess<IcmpSocketSet<I, WeakDeviceId<BT>, BT>> for StackState<BT>
871{
872 type Inner = IcmpSockets<I, WeakDeviceId<BT>, BT>;
873 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
874 &self.transport.icmp_echo_state()
875 }
876}
877
878impl<I: datagram::DualStackIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
879 for crate::lock_ordering::IcmpAllSocketsSet<I>
880{
881 type Data = IcmpSocketSet<I, WeakDeviceId<BT>, BT>;
882}
883
884impl<I: datagram::DualStackIpExt, BT: BindingsTypes>
885 DelegatedOrderedLockAccess<IpMarked<I, TokenBucket<BT::Instant>>> for StackState<BT>
886{
887 type Inner = IcmpState<I, BT>;
888 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
889 self.inner_icmp_state()
890 }
891}
892
893impl<I: datagram::DualStackIpExt, BT: BindingsTypes> LockLevelFor<StackState<BT>>
894 for crate::lock_ordering::IcmpTokenBucket<I>
895{
896 type Data = IpMarked<I, TokenBucket<BT::Instant>>;
897}
898
899impl<I: datagram::DualStackIpExt, D: WeakDeviceIdentifier, BT: BindingsTypes>
900 LockLevelFor<IcmpSocketId<I, D, BT>> for crate::lock_ordering::IcmpSocketState<I>
901{
902 type Data = IcmpSocketState<I, D, BT>;
903}