1use alloc::format;
8use alloc::string::String;
9use core::convert::Infallible as Never;
10use core::fmt::Debug;
11use core::num::NonZeroU64;
12use core::ops::RangeInclusive;
13
14use bitflags::bitflags;
15use derivative::Derivative;
16use net_types::ip::{Ip, IpAddr, IpAddress, Ipv4Addr, Ipv6Addr, Subnet};
17
18use crate::{InspectableValue, Inspector, Mark, MarkDomain, MarkStorage, Marks};
19
20pub trait MatcherBindingsTypes {
26 type DeviceClass: Clone + Debug;
28 type BindingsPacketMatcher: Clone + Debug + InspectableValue;
33}
34
35pub trait Matcher<T> {
39 fn matches(&self, actual: &T) -> bool;
41
42 fn required_matches(&self, actual: Option<&T>) -> bool {
44 actual.map_or(false, |actual| self.matches(actual))
45 }
46}
47
48impl<T, O> Matcher<T> for Option<O>
51where
52 O: Matcher<T>,
53{
54 fn matches(&self, actual: &T) -> bool {
55 self.as_ref().map_or(true, |expected| expected.matches(actual))
56 }
57
58 fn required_matches(&self, actual: Option<&T>) -> bool {
59 self.as_ref().map_or(true, |expected| expected.required_matches(actual))
60 }
61}
62
63#[derive(Debug, Copy, Clone, PartialEq, Eq)]
65pub struct SubnetMatcher<A: IpAddress>(pub Subnet<A>);
66
67impl<A: IpAddress> Matcher<A> for SubnetMatcher<A> {
68 fn matches(&self, actual: &A) -> bool {
69 let Self(matcher) = self;
70 matcher.contains(actual)
71 }
72}
73
74#[derive(Clone, Derivative, PartialEq, Eq)]
76#[derivative(Debug)]
77pub enum InterfaceMatcher<DeviceClass> {
78 Id(NonZeroU64),
80 Name(String),
82 DeviceClass(DeviceClass),
84}
85
86impl<DeviceClass: Debug> InspectableValue for InterfaceMatcher<DeviceClass> {
87 fn record<I: Inspector>(&self, name: &str, inspector: &mut I) {
88 match self {
89 InterfaceMatcher::Id(id) => inspector.record_string(name, format!("Id({})", id.get())),
90 InterfaceMatcher::Name(iface_name) => {
91 inspector.record_string(name, format!("Name({iface_name})"))
92 }
93 InterfaceMatcher::DeviceClass(class) => {
94 inspector.record_debug(name, format!("Class({class:?})"))
95 }
96 };
97 }
98}
99
100pub trait InterfaceProperties<DeviceClass> {
104 fn id_matches(&self, id: &NonZeroU64) -> bool;
106
107 fn name_matches(&self, name: &str) -> bool;
109
110 fn device_class_matches(&self, device_class: &DeviceClass) -> bool;
112}
113
114impl<DeviceClass, I: InterfaceProperties<DeviceClass>> Matcher<I>
115 for InterfaceMatcher<DeviceClass>
116{
117 fn matches(&self, actual: &I) -> bool {
118 match self {
119 InterfaceMatcher::Id(id) => actual.id_matches(id),
120 InterfaceMatcher::Name(name) => actual.name_matches(name),
121 InterfaceMatcher::DeviceClass(device_class) => {
122 actual.device_class_matches(device_class)
123 }
124 }
125 }
126}
127
128#[derive(Debug, Clone, PartialEq, Eq)]
130pub enum BoundInterfaceMatcher<DeviceClass> {
131 Bound(InterfaceMatcher<DeviceClass>),
133 Unbound,
135}
136
137impl<'a, DeviceClass, D: InterfaceProperties<DeviceClass>> Matcher<Option<&'a D>>
138 for BoundInterfaceMatcher<DeviceClass>
139{
140 fn matches(&self, actual: &Option<&'a D>) -> bool {
141 match self {
142 BoundInterfaceMatcher::Bound(matcher) => matcher.required_matches(actual.as_deref()),
143 BoundInterfaceMatcher::Unbound => actual.is_none(),
144 }
145 }
146}
147
148impl<DeviceClass: Debug> InspectableValue for BoundInterfaceMatcher<DeviceClass> {
149 fn record<I: Inspector>(&self, name: &str, inspector: &mut I) {
150 match self {
151 BoundInterfaceMatcher::Unbound => inspector.record_str(name, "Unbound"),
152 BoundInterfaceMatcher::Bound(interface) => {
153 inspector.record_inspectable_value(name, interface)
154 }
155 }
156 }
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub enum MarkMatcher {
162 Unmarked,
164 Marked {
166 mask: u32,
168 start: u32,
170 end: u32,
172 invert: bool,
174 },
175}
176
177impl Matcher<Mark> for MarkMatcher {
178 fn matches(&self, Mark(actual): &Mark) -> bool {
179 match self {
180 MarkMatcher::Unmarked => actual.is_none(),
181 MarkMatcher::Marked { mask, start, end, invert } => {
182 let val = actual.is_some_and(|actual| (*start..=*end).contains(&(actual & *mask)));
183
184 if *invert { !val } else { val }
185 }
186 }
187 }
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192pub struct MarkInDomainMatcher {
193 pub domain: MarkDomain,
195 pub matcher: MarkMatcher,
197}
198
199#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
201pub struct MarkMatchers(MarkStorage<Option<MarkMatcher>>);
202
203impl MarkMatchers {
204 pub fn new(matchers: impl IntoIterator<Item = (MarkDomain, MarkMatcher)>) -> Self {
212 MarkMatchers(MarkStorage::new(matchers))
213 }
214
215 pub fn iter(&self) -> impl Iterator<Item = (MarkDomain, &Option<MarkMatcher>)> {
217 let Self(storage) = self;
218 storage.iter()
219 }
220}
221
222impl Matcher<Marks> for MarkMatchers {
223 fn matches(&self, actual: &Marks) -> bool {
224 let Self(matchers) = self;
225 matchers.zip_with(actual).all(|(_domain, matcher, actual)| matcher.matches(actual))
226 }
227}
228
229pub struct SocketCookieMatcher {
231 pub cookie: u64,
233 pub invert: bool,
236}
237
238impl Matcher<u64> for SocketCookieMatcher {
239 fn matches(&self, actual: &u64) -> bool {
240 let val = *actual == self.cookie;
241 if self.invert { !val } else { val }
242 }
243}
244
245#[derive(Clone, Debug)]
247pub struct PortMatcher {
248 pub range: RangeInclusive<u16>,
250 pub invert: bool,
254}
255
256impl Matcher<u16> for PortMatcher {
257 fn matches(&self, actual: &u16) -> bool {
258 let Self { range, invert } = self;
259 range.contains(actual) ^ *invert
260 }
261}
262
263#[derive(Clone, Debug)]
265pub enum BoundPortMatcher {
266 Bound(PortMatcher),
268 Unbound,
270}
271
272impl Matcher<Option<u16>> for BoundPortMatcher {
273 fn matches(&self, actual: &Option<u16>) -> bool {
274 match (self, actual) {
275 (BoundPortMatcher::Unbound, None) => true,
276 (BoundPortMatcher::Bound(matcher), Some(port)) => matcher.matches(&port),
277 _ => false,
278 }
279 }
280}
281
282bitflags! {
283 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
285 pub struct TcpStateMatcher: u32 {
286 const ESTABLISHED = 1 << 0;
288 const SYN_SENT = 1 << 1;
290 const SYN_RECV = 1 << 2;
292 const FIN_WAIT1 = 1 << 3;
294 const FIN_WAIT2 = 1 << 4;
296 const TIME_WAIT = 1 << 5;
298 const CLOSE = 1 << 6;
300 const CLOSE_WAIT = 1 << 7;
302 const LAST_ACK = 1 << 8;
304 const LISTEN = 1 << 9;
306 const CLOSING = 1 << 10;
308 }
309}
310
311impl Matcher<TcpSocketState> for TcpStateMatcher {
312 fn matches(&self, actual: &TcpSocketState) -> bool {
313 self.contains(actual.matcher_flag())
314 }
315}
316
317#[derive(Debug, Copy, Clone, PartialEq, Eq)]
319#[allow(missing_docs)]
320pub enum TcpSocketState {
321 Established,
322 SynSent,
323 SynRecv,
324 FinWait1,
325 FinWait2,
326 TimeWait,
327 Close,
328 CloseWait,
329 LastAck,
330 Listen,
331 Closing,
332}
333
334impl TcpSocketState {
335 fn matcher_flag(&self) -> TcpStateMatcher {
336 match self {
337 TcpSocketState::Established => TcpStateMatcher::ESTABLISHED,
338 TcpSocketState::SynSent => TcpStateMatcher::SYN_SENT,
339 TcpSocketState::SynRecv => TcpStateMatcher::SYN_RECV,
340 TcpSocketState::FinWait1 => TcpStateMatcher::FIN_WAIT1,
341 TcpSocketState::FinWait2 => TcpStateMatcher::FIN_WAIT2,
342 TcpSocketState::TimeWait => TcpStateMatcher::TIME_WAIT,
343 TcpSocketState::Close => TcpStateMatcher::CLOSE,
344 TcpSocketState::CloseWait => TcpStateMatcher::CLOSE_WAIT,
345 TcpSocketState::LastAck => TcpStateMatcher::LAST_ACK,
346 TcpSocketState::Listen => TcpStateMatcher::LISTEN,
347 TcpSocketState::Closing => TcpStateMatcher::CLOSING,
348 }
349 }
350}
351
352pub trait TcpSocketProperties {
355 fn src_port_matches(&self, matcher: &BoundPortMatcher) -> bool;
357
358 fn dst_port_matches(&self, matcher: &BoundPortMatcher) -> bool;
360
361 fn state_matches(&self, matcher: &TcpStateMatcher) -> bool;
363}
364
365impl TcpSocketProperties for Never {
366 fn src_port_matches(&self, _matcher: &BoundPortMatcher) -> bool {
367 unimplemented!()
368 }
369
370 fn dst_port_matches(&self, _matcher: &BoundPortMatcher) -> bool {
371 unimplemented!()
372 }
373
374 fn state_matches(&self, _matcher: &TcpStateMatcher) -> bool {
375 unimplemented!()
376 }
377}
378
379impl<T> TcpSocketProperties for &T
380where
381 T: TcpSocketProperties,
382{
383 fn src_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
384 (*self).src_port_matches(matcher)
385 }
386
387 fn dst_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
388 (*self).dst_port_matches(matcher)
389 }
390
391 fn state_matches(&self, matcher: &TcpStateMatcher) -> bool {
392 (*self).state_matches(matcher)
393 }
394}
395
396pub enum TcpSocketMatcher {
398 Empty,
400 SrcPort(BoundPortMatcher),
402 DstPort(BoundPortMatcher),
404 State(TcpStateMatcher),
406}
407
408impl<T: TcpSocketProperties> Matcher<T> for TcpSocketMatcher {
409 fn matches(&self, actual: &T) -> bool {
410 match self {
411 TcpSocketMatcher::Empty => true,
412 TcpSocketMatcher::SrcPort(matcher) => actual.src_port_matches(matcher),
413 TcpSocketMatcher::DstPort(matcher) => actual.dst_port_matches(matcher),
414 TcpSocketMatcher::State(matcher) => actual.state_matches(matcher),
415 }
416 }
417}
418
419bitflags! {
420 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
422 pub struct UdpStateMatcher: u32 {
423 const BOUND = 1 << 0;
425 const CONNECTED = 1 << 1;
427 }
428}
429
430impl Matcher<UdpSocketState> for UdpStateMatcher {
431 fn matches(&self, actual: &UdpSocketState) -> bool {
432 self.contains(actual.matcher_flag())
433 }
434}
435
436#[derive(Debug, Copy, Clone, PartialEq, Eq)]
438pub enum UdpSocketState {
439 Bound,
441 Connected,
443}
444
445impl UdpSocketState {
446 fn matcher_flag(&self) -> UdpStateMatcher {
447 match self {
448 UdpSocketState::Bound => UdpStateMatcher::BOUND,
449 UdpSocketState::Connected => UdpStateMatcher::CONNECTED,
450 }
451 }
452}
453
454pub trait UdpSocketProperties {
457 fn src_port_matches(&self, matcher: &BoundPortMatcher) -> bool;
459
460 fn dst_port_matches(&self, matcher: &BoundPortMatcher) -> bool;
462
463 fn state_matches(&self, matcher: &UdpStateMatcher) -> bool;
465}
466
467impl UdpSocketProperties for Never {
468 fn src_port_matches(&self, _matcher: &BoundPortMatcher) -> bool {
469 unimplemented!()
470 }
471
472 fn dst_port_matches(&self, _matcher: &BoundPortMatcher) -> bool {
473 unimplemented!()
474 }
475
476 fn state_matches(&self, _matcher: &UdpStateMatcher) -> bool {
477 unimplemented!()
478 }
479}
480
481impl<U> UdpSocketProperties for &U
482where
483 U: UdpSocketProperties,
484{
485 fn src_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
486 (*self).src_port_matches(matcher)
487 }
488
489 fn dst_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
490 (*self).dst_port_matches(matcher)
491 }
492
493 fn state_matches(&self, matcher: &UdpStateMatcher) -> bool {
494 (*self).state_matches(matcher)
495 }
496}
497
498pub enum UdpSocketMatcher {
500 Empty,
502 SrcPort(BoundPortMatcher),
504 DstPort(BoundPortMatcher),
506 State(UdpStateMatcher),
508}
509
510impl<T: UdpSocketProperties> Matcher<T> for UdpSocketMatcher {
511 fn matches(&self, actual: &T) -> bool {
512 match self {
513 UdpSocketMatcher::Empty => true,
514 UdpSocketMatcher::SrcPort(matcher) => actual.src_port_matches(matcher),
515 UdpSocketMatcher::DstPort(matcher) => actual.dst_port_matches(matcher),
516 UdpSocketMatcher::State(matcher) => actual.state_matches(matcher),
517 }
518 }
519}
520
521pub trait MaybeSocketTransportProperties {
523 type TcpProps<'a>: TcpSocketProperties
525 where
526 Self: 'a;
527
528 type UdpProps<'a>: UdpSocketProperties
530 where
531 Self: 'a;
532
533 fn tcp_socket_properties(&self) -> Option<&Self::TcpProps<'_>>;
535
536 fn udp_socket_properties(&self) -> Option<&Self::UdpProps<'_>>;
538}
539
540impl MaybeSocketTransportProperties for Never {
541 type TcpProps<'a>
542 = Never
543 where
544 Self: 'a;
545
546 type UdpProps<'a>
547 = Never
548 where
549 Self: 'a;
550
551 fn tcp_socket_properties(&self) -> Option<&Self::TcpProps<'_>> {
552 unimplemented!()
553 }
554
555 fn udp_socket_properties(&self) -> Option<&Self::UdpProps<'_>> {
556 unimplemented!()
557 }
558}
559
560pub enum SocketTransportProtocolMatcher {
562 Tcp(TcpSocketMatcher),
564 Udp(UdpSocketMatcher),
566}
567
568impl<T: MaybeSocketTransportProperties> Matcher<T> for SocketTransportProtocolMatcher {
569 fn matches(&self, actual: &T) -> bool {
570 match self {
571 SocketTransportProtocolMatcher::Tcp(tcp_matcher) => {
572 actual.tcp_socket_properties().map_or(false, |props| tcp_matcher.matches(props))
573 }
574 SocketTransportProtocolMatcher::Udp(udp_matcher) => {
575 actual.udp_socket_properties().map_or(false, |props| udp_matcher.matches(props))
576 }
577 }
578 }
579}
580
581#[derive(Clone, Derivative)]
583#[derivative(Debug)]
584pub enum AddressMatcherType<A: IpAddress> {
585 #[derivative(Debug = "transparent")]
587 Subnet(SubnetMatcher<A>),
588 Range(RangeInclusive<A>),
590}
591
592impl<A: IpAddress> Matcher<A> for AddressMatcherType<A> {
593 fn matches(&self, actual: &A) -> bool {
594 match self {
595 Self::Subnet(subnet_matcher) => subnet_matcher.matches(actual),
596 Self::Range(range) => range.contains(actual),
597 }
598 }
599}
600
601#[derive(Clone, Debug)]
603pub struct AddressMatcher<A: IpAddress> {
604 pub matcher: AddressMatcherType<A>,
606 pub invert: bool,
610}
611
612impl<A: IpAddress> AddressMatcher<A> {
613 pub fn match_all() -> Self {
615 Self {
616 matcher: AddressMatcherType::Subnet(SubnetMatcher(A::Version::ALL_ADDRS_SUBNET)),
617 invert: false,
618 }
619 }
620}
621
622impl<A: IpAddress> InspectableValue for AddressMatcher<A> {
623 fn record<I: Inspector>(&self, name: &str, inspector: &mut I) {
624 let AddressMatcher { matcher, invert } = self;
625
626 inspector.record_child(name, |inspector| {
627 inspector.record_bool("invert", *invert);
628 match matcher {
629 AddressMatcherType::Subnet(SubnetMatcher(subnet)) => {
630 inspector.record_display("subnet", subnet)
631 }
632 AddressMatcherType::Range(range) => {
633 inspector.record_display("start", range.start());
634 inspector.record_display("end", range.end());
635 }
636 }
637 })
638 }
639}
640
641impl<A: IpAddress> Matcher<A> for AddressMatcher<A> {
642 fn matches(&self, addr: &A) -> bool {
643 let Self { matcher, invert } = self;
644 matcher.matches(addr) ^ *invert
645 }
646}
647
648pub enum AddressMatcherEither {
650 V4(AddressMatcher<Ipv4Addr>),
652 V6(AddressMatcher<Ipv6Addr>),
654}
655
656pub enum BoundAddressMatcherEither {
658 Bound(AddressMatcherEither),
660 Unbound,
662}
663
664impl Matcher<Option<IpAddr>> for BoundAddressMatcherEither {
665 fn matches(&self, addr: &Option<IpAddr>) -> bool {
666 match (self, addr) {
667 (BoundAddressMatcherEither::Unbound, None) => true,
668 (BoundAddressMatcherEither::Bound(matcher), Some(addr)) => match (matcher, addr) {
669 (AddressMatcherEither::V4(matcher), IpAddr::V4(addr)) => matcher.matches(addr),
670 (AddressMatcherEither::V6(matcher), IpAddr::V6(addr)) => matcher.matches(addr),
671 _ => false,
672 },
673 _ => false,
674 }
675 }
676}
677
678pub trait IpSocketProperties<DeviceClass> {
681 fn family_matches(&self, family: &net_types::ip::IpVersion) -> bool;
683
684 fn src_addr_matches(&self, addr: &BoundAddressMatcherEither) -> bool;
687
688 fn dst_addr_matches(&self, addr: &BoundAddressMatcherEither) -> bool;
691
692 fn transport_protocol_matches(&self, matcher: &SocketTransportProtocolMatcher) -> bool;
695
696 fn bound_interface_matches(&self, iface: &BoundInterfaceMatcher<DeviceClass>) -> bool;
699
700 fn cookie_matches(&self, cookie: &SocketCookieMatcher) -> bool;
702
703 fn mark_matches(&self, matcher: &MarkInDomainMatcher) -> bool;
705}
706
707pub enum IpSocketMatcher<DeviceClass> {
709 Family(net_types::ip::IpVersion),
711 SrcAddr(BoundAddressMatcherEither),
713 DstAddr(BoundAddressMatcherEither),
715 Proto(SocketTransportProtocolMatcher),
717 BoundInterface(BoundInterfaceMatcher<DeviceClass>),
719 Cookie(SocketCookieMatcher),
721 Mark(MarkInDomainMatcher),
723}
724
725impl<DeviceClass, S: IpSocketProperties<DeviceClass>> Matcher<S> for IpSocketMatcher<DeviceClass> {
726 fn matches(&self, actual: &S) -> bool {
727 match self {
728 IpSocketMatcher::Family(family) => actual.family_matches(family),
729 IpSocketMatcher::SrcAddr(addr) => actual.src_addr_matches(addr),
730 IpSocketMatcher::DstAddr(addr) => actual.dst_addr_matches(addr),
731 IpSocketMatcher::Proto(proto) => actual.transport_protocol_matches(proto),
732 IpSocketMatcher::BoundInterface(iface) => actual.bound_interface_matches(iface),
733 IpSocketMatcher::Cookie(cookie) => actual.cookie_matches(cookie),
734 IpSocketMatcher::Mark(mark) => actual.mark_matches(mark),
735 }
736 }
737}
738
739pub trait IpSocketPropertiesMatcher<DeviceClass> {
742 fn matches_ip_socket<S: IpSocketProperties<DeviceClass>>(&self, actual: &S) -> bool;
744}
745
746impl<DeviceClass> IpSocketPropertiesMatcher<DeviceClass> for IpSocketMatcher<DeviceClass> {
747 fn matches_ip_socket<S: IpSocketProperties<DeviceClass>>(&self, actual: &S) -> bool {
748 self.matches(actual)
749 }
750}
751
752impl<DeviceClass> IpSocketPropertiesMatcher<DeviceClass> for [IpSocketMatcher<DeviceClass>] {
753 fn matches_ip_socket<S: IpSocketProperties<DeviceClass>>(&self, actual: &S) -> bool {
754 self.iter().all(|matcher| matcher.matches(actual))
755 }
756}
757
758#[cfg(any(test, feature = "testutils"))]
759pub(crate) mod testutil {
760 use alloc::string::String;
761 use core::num::NonZeroU64;
762
763 use crate::matchers::InterfaceProperties;
764 use crate::testutil::{FakeDeviceClass, FakeStrongDeviceId, FakeWeakDeviceId};
765 use crate::{DeviceIdentifier, StrongDeviceIdentifier};
766
767 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
769 #[allow(missing_docs)]
770 pub struct FakeMatcherDeviceId {
771 pub id: NonZeroU64,
772 pub name: String,
773 pub class: FakeDeviceClass,
774 }
775
776 impl FakeMatcherDeviceId {
777 pub fn wlan_interface() -> FakeMatcherDeviceId {
781 FakeMatcherDeviceId {
782 id: NonZeroU64::new(1).unwrap(),
783 name: String::from("wlan"),
784 class: FakeDeviceClass::Wlan,
785 }
786 }
787
788 pub fn ethernet_interface() -> FakeMatcherDeviceId {
792 FakeMatcherDeviceId {
793 id: NonZeroU64::new(2).unwrap(),
794 name: String::from("eth"),
795 class: FakeDeviceClass::Ethernet,
796 }
797 }
798 }
799
800 impl StrongDeviceIdentifier for FakeMatcherDeviceId {
801 type Weak = FakeWeakDeviceId<Self>;
802
803 fn downgrade(&self) -> Self::Weak {
804 FakeWeakDeviceId(self.clone())
805 }
806 }
807
808 impl DeviceIdentifier for FakeMatcherDeviceId {
809 fn is_loopback(&self) -> bool {
810 false
811 }
812 }
813
814 impl FakeStrongDeviceId for FakeMatcherDeviceId {
815 fn is_alive(&self) -> bool {
816 true
817 }
818 }
819
820 impl PartialEq<FakeWeakDeviceId<FakeMatcherDeviceId>> for FakeMatcherDeviceId {
821 fn eq(&self, FakeWeakDeviceId(other): &FakeWeakDeviceId<FakeMatcherDeviceId>) -> bool {
822 self == other
823 }
824 }
825
826 impl InterfaceProperties<FakeDeviceClass> for FakeMatcherDeviceId {
827 fn id_matches(&self, id: &NonZeroU64) -> bool {
828 &self.id == id
829 }
830
831 fn name_matches(&self, name: &str) -> bool {
832 &self.name == name
833 }
834
835 fn device_class_matches(&self, class: &FakeDeviceClass) -> bool {
836 &self.class == class
837 }
838 }
839}
840
841#[cfg(test)]
842mod tests {
843 use ip_test_macro::ip_test;
844 use net_types::Witness;
845 use net_types::ip::{Ip, IpVersion, Ipv4, Ipv6};
846 use test_case::test_case;
847
848 use super::*;
849 use crate::testutil::{FakeDeviceClass, FakeMatcherDeviceId, TestIpExt};
850
851 #[derive(Debug)]
853 struct TrueMatcher;
854
855 impl Matcher<bool> for TrueMatcher {
856 fn matches(&self, actual: &bool) -> bool {
857 *actual
858 }
859 }
860
861 #[test]
862 fn test_optional_matcher_optional_value() {
863 assert!(TrueMatcher.matches(&true));
864 assert!(!TrueMatcher.matches(&false));
865
866 assert!(TrueMatcher.required_matches(Some(&true)));
867 assert!(!TrueMatcher.required_matches(Some(&false)));
868 assert!(!TrueMatcher.required_matches(None));
869
870 assert!(Some(TrueMatcher).matches(&true));
871 assert!(!Some(TrueMatcher).matches(&false));
872 assert!(None::<TrueMatcher>.matches(&true));
873 assert!(None::<TrueMatcher>.matches(&false));
874
875 assert!(Some(TrueMatcher).required_matches(Some(&true)));
876 assert!(!Some(TrueMatcher).required_matches(Some(&false)));
877 assert!(!Some(TrueMatcher).required_matches(None));
878 assert!(None::<TrueMatcher>.required_matches(Some(&true)));
879 assert!(None::<TrueMatcher>.required_matches(Some(&false)));
880 assert!(None::<TrueMatcher>.required_matches(None));
881 }
882
883 #[test_case(
884 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id),
885 FakeMatcherDeviceId::wlan_interface() => true
886 )]
887 #[test_case(
888 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id),
889 FakeMatcherDeviceId::ethernet_interface() => false
890 )]
891 #[test_case(
892 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name),
893 FakeMatcherDeviceId::wlan_interface() => true
894 )]
895 #[test_case(
896 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name),
897 FakeMatcherDeviceId::ethernet_interface() => false
898 )]
899 #[test_case(
900 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan),
901 FakeMatcherDeviceId::wlan_interface() => true
902 )]
903 #[test_case(
904 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan),
905 FakeMatcherDeviceId::ethernet_interface() => false
906 )]
907 fn interface_matcher(
908 matcher: InterfaceMatcher<FakeDeviceClass>,
909 device: FakeMatcherDeviceId,
910 ) -> bool {
911 matcher.matches(&device)
912 }
913
914 #[test_case(BoundInterfaceMatcher::Unbound, None => true)]
915 #[test_case(
916 BoundInterfaceMatcher::Unbound,
917 Some(FakeMatcherDeviceId::wlan_interface()) => false
918 )]
919 #[test_case(
920 BoundInterfaceMatcher::Bound(
921 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
922 ),
923 None => false
924 )]
925 #[test_case(
926 BoundInterfaceMatcher::Bound(
927 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
928 ),
929 Some(FakeMatcherDeviceId::wlan_interface()) => true
930 )]
931 #[test_case(
932 BoundInterfaceMatcher::Bound(
933 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
934 ),
935 Some(FakeMatcherDeviceId::ethernet_interface()) => false
936 )]
937 #[test_case(
938 BoundInterfaceMatcher::Bound(
939 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name)
940 ),
941 None => false
942 )]
943 #[test_case(
944 BoundInterfaceMatcher::Bound(
945 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name)
946 ),
947 Some(FakeMatcherDeviceId::wlan_interface()) => true
948 )]
949 #[test_case(
950 BoundInterfaceMatcher::Bound(
951 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name)
952 ),
953 Some(FakeMatcherDeviceId::ethernet_interface()) => false
954 )]
955 #[test_case(
956 BoundInterfaceMatcher::Bound(
957 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan)
958 ),
959 None => false
960 )]
961 #[test_case(
962 BoundInterfaceMatcher::Bound(
963 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan)
964 ),
965 Some(FakeMatcherDeviceId::wlan_interface()) => true
966 )]
967 #[test_case(
968 BoundInterfaceMatcher::Bound(
969 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan)
970 ),
971 Some(FakeMatcherDeviceId::ethernet_interface()) => false
972 )]
973 fn bound_interface_matcher(
974 matcher: BoundInterfaceMatcher<FakeDeviceClass>,
975 device: Option<FakeMatcherDeviceId>,
976 ) -> bool {
977 matcher.matches(&device.as_ref())
978 }
979
980 #[ip_test(I)]
981 fn subnet_matcher<I: Ip + TestIpExt>() {
982 let matcher = SubnetMatcher(I::TEST_ADDRS.subnet);
983 assert!(matcher.matches(&I::TEST_ADDRS.local_ip));
984 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
985 }
986
987 #[test_case(MarkMatcher::Unmarked, Mark(None) => true; "unmarked matches none")]
988 #[test_case(MarkMatcher::Unmarked, Mark(Some(0)) => false; "unmarked does not match some")]
989 #[test_case(MarkMatcher::Marked {
990 mask: 1,
991 start: 0,
992 end: 0,
993 invert: false,
994 }, Mark(None) => false; "marked does not match none")]
995 #[test_case(MarkMatcher::Marked {
996 mask: 1,
997 start: 0,
998 end: 0,
999 invert: false,
1000 }, Mark(Some(0)) => true; "marked 0 mask 1 matches 0")]
1001 #[test_case(MarkMatcher::Marked {
1002 mask: 1,
1003 start: 0,
1004 end: 0,
1005 invert: false,
1006 }, Mark(Some(1)) => false; "marked 0 mask 1 does not match 1")]
1007 #[test_case(MarkMatcher::Marked {
1008 mask: 1,
1009 start: 0,
1010 end: 0,
1011 invert: false,
1012 }, Mark(Some(2)) => true; "marked 0 mask 1 matches 2")]
1013 #[test_case(MarkMatcher::Marked {
1014 mask: 1,
1015 start: 0,
1016 end: 0,
1017 invert: false,
1018 }, Mark(Some(3)) => false; "marked 0 mask 1 does not match 3")]
1019 #[test_case(MarkMatcher::Marked {
1020 mask: !0,
1021 start: 0,
1022 end: 10,
1023 invert: true,
1024 }, Mark(Some(5)) => false; "marked invert no match in range")]
1025 #[test_case(MarkMatcher::Marked {
1026 mask: !0,
1027 start: 0,
1028 end: 10,
1029 invert: true,
1030 }, Mark(Some(11)) => true; "marked invert matches out of range")]
1031 fn mark_matcher(matcher: MarkMatcher, mark: Mark) -> bool {
1032 matcher.matches(&mark)
1033 }
1034
1035 #[test_case(
1036 MarkMatchers::new(
1037 [(MarkDomain::Mark1, MarkMatcher::Unmarked),
1038 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1039 ),
1040 Marks::new([]) => true;
1041 "all unmarked matches empty"
1042 )]
1043 #[test_case(
1044 MarkMatchers::new(
1045 [(MarkDomain::Mark1, MarkMatcher::Unmarked),
1046 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1047 ),
1048 Marks::new([(MarkDomain::Mark1, 1)]) => false;
1049 "all unmarked does not match mark1"
1050 )]
1051 #[test_case(
1052 MarkMatchers::new(
1053 [(MarkDomain::Mark1, MarkMatcher::Unmarked),
1054 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1055 ),
1056 Marks::new([(MarkDomain::Mark2, 1)]) => false;
1057 "all unmarked does not match mark2"
1058 )]
1059 #[test_case(
1060 MarkMatchers::new(
1061 [(MarkDomain::Mark1, MarkMatcher::Unmarked),
1062 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1063 ),
1064 Marks::new([
1065 (MarkDomain::Mark1, 1),
1066 (MarkDomain::Mark2, 1),
1067 ]) => false;
1068 "all unmarked does not match mark1 and mark2"
1069 )]
1070 #[test_case(
1071 MarkMatchers::new(
1072 [(MarkDomain::Mark1, MarkMatcher::Marked { mask: !0, start: 1, end: 1, invert: false }),
1073 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1074 ),
1075 Marks::new([(MarkDomain::Mark1, 1)]) => true;
1076 "mark1 marked matches"
1077 )]
1078 #[test_case(
1079 MarkMatchers::new(
1080 [(MarkDomain::Mark1, MarkMatcher::Marked { mask: !0, start: 1, end: 1, invert: false }),
1081 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1082 ),
1083 Marks::new([(MarkDomain::Mark1, 2)]) => false;
1084 "mark1 marked no match"
1085 )]
1086 #[test_case(
1087 MarkMatchers::new(
1088 [(MarkDomain::Mark1, MarkMatcher::Marked { mask: !0, start: 1, end: 1, invert: false }),
1089 (MarkDomain::Mark2, MarkMatcher::Marked { mask: !0, start: 2, end: 2, invert: false })]
1090 ),
1091 Marks::new([(MarkDomain::Mark1, 1), (MarkDomain::Mark2, 2)]) => true;
1092 "all marked matches"
1093 )]
1094 #[test_case(
1095 MarkMatchers::new(
1096 [(MarkDomain::Mark1, MarkMatcher::Marked { mask: !0, start: 1, end: 1, invert: false }),
1097 (MarkDomain::Mark2, MarkMatcher::Marked { mask: !0, start: 2, end: 2, invert: false })]
1098 ),
1099 Marks::new([(MarkDomain::Mark1, 1), (MarkDomain::Mark2, 3)]) => false;
1100 "all marked no match mark2"
1101 )]
1102 fn mark_matchers(matchers: MarkMatchers, marks: Marks) -> bool {
1103 matchers.matches(&marks)
1104 }
1105
1106 #[test_case(SocketCookieMatcher { cookie: 123, invert: false }, 123 => true)]
1107 #[test_case(SocketCookieMatcher { cookie: 123, invert: false }, 456 => false)]
1108 #[test_case(SocketCookieMatcher { cookie: 123, invert: true }, 123 => false)]
1109 #[test_case(SocketCookieMatcher { cookie: 123, invert: true }, 456 => true)]
1110 fn socket_cookie_matcher(matcher: SocketCookieMatcher, actual: u64) -> bool {
1111 matcher.matches(&actual)
1112 }
1113
1114 #[test_case(PortMatcher { range: 10..=20, invert: false }, 9 => false)]
1115 #[test_case(PortMatcher { range: 10..=20, invert: false }, 10 => true)]
1116 #[test_case(PortMatcher { range: 10..=20, invert: false }, 15 => true)]
1117 #[test_case(PortMatcher { range: 10..=20, invert: false }, 20 => true)]
1118 #[test_case(PortMatcher { range: 10..=20, invert: false }, 21 => false)]
1119 #[test_case(PortMatcher { range: 10..=20, invert: true }, 9 => true)]
1120 #[test_case(PortMatcher { range: 10..=20, invert: true }, 10 => false)]
1121 #[test_case(PortMatcher { range: 10..=20, invert: true }, 15 => false)]
1122 #[test_case(PortMatcher { range: 10..=20, invert: true }, 20 => false)]
1123 #[test_case(PortMatcher { range: 10..=20, invert: true }, 21 => true)]
1124 fn port_matcher(matcher: PortMatcher, actual: u16) -> bool {
1125 matcher.matches(&actual)
1126 }
1127
1128 #[test_case(BoundPortMatcher::Unbound, None => true)]
1129 #[test_case(BoundPortMatcher::Unbound, Some(80) => false)]
1130 #[test_case(
1131 BoundPortMatcher::Bound(PortMatcher { range: 10..=20, invert: false }),
1132 None => false
1133 )]
1134 #[test_case(
1135 BoundPortMatcher::Bound(PortMatcher { range: 10..=20, invert: false }),
1136 Some(10) => true
1137 )]
1138 #[test_case(
1139 BoundPortMatcher::Bound(PortMatcher { range: 10..=20, invert: false }),
1140 Some(9) => false
1141 )]
1142 fn bound_port_matcher(matcher: BoundPortMatcher, actual: Option<u16>) -> bool {
1143 matcher.matches(&actual)
1144 }
1145
1146 struct FakeTcpSocket {
1147 src_port: Option<u16>,
1148 dst_port: Option<u16>,
1149 state: TcpSocketState,
1150 }
1151
1152 impl MaybeSocketTransportProperties for FakeTcpSocket {
1153 type TcpProps<'a>
1154 = Self
1155 where
1156 Self: 'a;
1157
1158 type UdpProps<'a>
1159 = Never
1160 where
1161 Self: 'a;
1162
1163 fn tcp_socket_properties(&self) -> Option<&Self::TcpProps<'_>> {
1164 Some(self)
1165 }
1166
1167 fn udp_socket_properties(&self) -> Option<&Self::UdpProps<'_>> {
1168 None
1169 }
1170 }
1171
1172 impl TcpSocketProperties for FakeTcpSocket {
1173 fn src_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
1174 matcher.matches(&self.src_port)
1175 }
1176
1177 fn dst_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
1178 matcher.matches(&self.dst_port)
1179 }
1180
1181 fn state_matches(&self, matcher: &TcpStateMatcher) -> bool {
1182 matcher.matches(&self.state)
1183 }
1184 }
1185
1186 struct FakeUdpSocket {
1187 src_port: Option<u16>,
1188 dst_port: Option<u16>,
1189 state: UdpSocketState,
1190 }
1191
1192 impl MaybeSocketTransportProperties for FakeUdpSocket {
1193 type TcpProps<'a>
1194 = Never
1195 where
1196 Self: 'a;
1197
1198 type UdpProps<'a>
1199 = Self
1200 where
1201 Self: 'a;
1202
1203 fn tcp_socket_properties(&self) -> Option<&Self::TcpProps<'_>> {
1204 None
1205 }
1206
1207 fn udp_socket_properties(&self) -> Option<&Self::UdpProps<'_>> {
1208 Some(self)
1209 }
1210 }
1211
1212 impl UdpSocketProperties for FakeUdpSocket {
1213 fn src_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
1214 matcher.matches(&self.src_port)
1215 }
1216
1217 fn dst_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
1218 matcher.matches(&self.dst_port)
1219 }
1220
1221 fn state_matches(&self, matcher: &UdpStateMatcher) -> bool {
1222 matcher.matches(&self.state)
1223 }
1224 }
1225
1226 struct FakeIpSocket<I, T>
1227 where
1228 I: TestIpExt,
1229 T: MaybeSocketTransportProperties,
1230 {
1231 src_ip: Option<I::Addr>,
1232 dst_ip: Option<I::Addr>,
1233 proto: T,
1234 intf: Option<FakeMatcherDeviceId>,
1235 cookie: u64,
1236 marks: Marks,
1237 }
1238
1239 impl<I, T> MaybeSocketTransportProperties for FakeIpSocket<I, T>
1240 where
1241 I: TestIpExt,
1242 T: MaybeSocketTransportProperties,
1243 {
1244 type TcpProps<'a>
1245 = T::TcpProps<'a>
1246 where
1247 Self: 'a;
1248
1249 type UdpProps<'a>
1250 = T::UdpProps<'a>
1251 where
1252 Self: 'a;
1253
1254 fn tcp_socket_properties(&self) -> Option<&Self::TcpProps<'_>> {
1255 self.proto.tcp_socket_properties()
1256 }
1257
1258 fn udp_socket_properties(&self) -> Option<&Self::UdpProps<'_>> {
1259 self.proto.udp_socket_properties()
1260 }
1261 }
1262
1263 impl<I, T> IpSocketProperties<FakeDeviceClass> for FakeIpSocket<I, T>
1264 where
1265 I: TestIpExt,
1266 T: MaybeSocketTransportProperties,
1267 {
1268 fn family_matches(&self, family: &net_types::ip::IpVersion) -> bool {
1269 *family == I::VERSION
1270 }
1271
1272 fn src_addr_matches(&self, addr: &BoundAddressMatcherEither) -> bool {
1273 addr.matches(&self.src_ip.map(|a| a.into()))
1274 }
1275
1276 fn dst_addr_matches(&self, addr: &BoundAddressMatcherEither) -> bool {
1277 addr.matches(&self.dst_ip.map(|a| a.into()))
1278 }
1279
1280 fn transport_protocol_matches(&self, matcher: &SocketTransportProtocolMatcher) -> bool {
1281 matcher.matches(self)
1282 }
1283
1284 fn bound_interface_matches(&self, iface: &BoundInterfaceMatcher<FakeDeviceClass>) -> bool {
1285 iface.matches(&self.intf.as_ref())
1286 }
1287
1288 fn cookie_matches(&self, cookie: &SocketCookieMatcher) -> bool {
1289 cookie.matches(&self.cookie)
1290 }
1291
1292 fn mark_matches(&self, matcher: &MarkInDomainMatcher) -> bool {
1293 matcher.matcher.matches(self.marks.get(matcher.domain))
1294 }
1295 }
1296
1297 #[test_case(
1298 TcpSocketMatcher::Empty,
1299 FakeTcpSocket {
1300 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1301 } => true;
1302 "empty matcher"
1303 )]
1304 #[test_case(
1305 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1306 PortMatcher { range: 80..=80, invert: false }
1307 )),
1308 FakeTcpSocket {
1309 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1310 } => true;
1311 "src_port match"
1312 )]
1313 #[test_case(
1314 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1315 PortMatcher { range: 80..=80, invert: false }
1316 )),
1317 FakeTcpSocket {
1318 src_port: Some(81), dst_port: Some(12345), state: TcpSocketState::Established
1319 } => false;
1320 "src_port no match"
1321 )]
1322 #[test_case(
1323 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(PortMatcher {
1324 range: 80..=80, invert: true
1325 })),
1326 FakeTcpSocket {
1327 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1328 } => false;
1329 "src_port invert no match"
1330 )]
1331 #[test_case(
1332 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1333 PortMatcher { range: 80..=80, invert: true }
1334 )),
1335 FakeTcpSocket {
1336 src_port: Some(81), dst_port: Some(12345), state: TcpSocketState::Established
1337 } => true;
1338 "src_port invert match"
1339 )]
1340 #[test_case(
1341 TcpSocketMatcher::DstPort(BoundPortMatcher::Bound(
1342 PortMatcher {range: 12345..=12345, invert: false }
1343 )),
1344 FakeTcpSocket {
1345 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1346 } => true;
1347 "dst_port match"
1348 )]
1349 #[test_case(
1350 TcpSocketMatcher::DstPort(BoundPortMatcher::Bound(
1351 PortMatcher { range: 12345..=12345, invert: false }
1352 )),
1353 FakeTcpSocket {
1354 src_port: Some(80), dst_port: Some(12346), state: TcpSocketState::Established
1355 } => false;
1356 "dst_port no match"
1357 )]
1358 #[test_case(
1359 TcpSocketMatcher::State(TcpStateMatcher::ESTABLISHED),
1360 FakeTcpSocket {
1361 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1362 } => true;
1363 "state match"
1364 )]
1365 #[test_case(
1366 TcpSocketMatcher::State(TcpStateMatcher::SYN_SENT),
1367 FakeTcpSocket {
1368 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1369 } => false;
1370 "state no match"
1371 )]
1372 #[test_case(
1373 TcpSocketMatcher::State(TcpStateMatcher::ESTABLISHED | TcpStateMatcher::SYN_SENT),
1374 FakeTcpSocket {
1375 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1376 } => true;
1377 "state multi match established"
1378 )]
1379 #[test_case(
1380 TcpSocketMatcher::State(TcpStateMatcher::ESTABLISHED | TcpStateMatcher::SYN_SENT),
1381 FakeTcpSocket {
1382 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::SynSent
1383 } => true;
1384 "state multi match syn_sent"
1385 )]
1386 #[test_case(
1387 TcpSocketMatcher::State(TcpStateMatcher::ESTABLISHED | TcpStateMatcher::SYN_SENT),
1388 FakeTcpSocket {
1389 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::FinWait1
1390 } => false;
1391 "state multi no match"
1392 )]
1393 #[test_case(
1394 TcpSocketMatcher::SrcPort(BoundPortMatcher::Unbound),
1395 FakeTcpSocket {
1396 src_port: None, dst_port: Some(12345), state: TcpSocketState::Established
1397 } => true;
1398 "src_port unbound match"
1399 )]
1400 #[test_case(
1401 TcpSocketMatcher::SrcPort(BoundPortMatcher::Unbound),
1402 FakeTcpSocket {
1403 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1404 } => false;
1405 "src_port unbound no match"
1406 )]
1407 #[test_case(
1408 TcpSocketMatcher::DstPort(BoundPortMatcher::Unbound),
1409 FakeTcpSocket {
1410 src_port: Some(80), dst_port: None, state: TcpSocketState::Established
1411 } => true;
1412 "dst_port unbound match"
1413 )]
1414 #[test_case(
1415 TcpSocketMatcher::DstPort(BoundPortMatcher::Unbound),
1416 FakeTcpSocket {
1417 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1418 } => false;
1419 "dst_port unbound no match"
1420 )]
1421 fn tcp_socket_matcher(matcher: TcpSocketMatcher, socket: FakeTcpSocket) -> bool {
1422 matcher.matches(&socket)
1423 }
1424
1425 #[test_case(
1426 UdpSocketMatcher::Empty,
1427 FakeUdpSocket {
1428 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1429 } => true;
1430 "empty matcher"
1431 )]
1432 #[test_case(
1433 UdpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1434 PortMatcher { range: 53..=53, invert: false }
1435 )),
1436 FakeUdpSocket {
1437 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1438 } => true;
1439 "src_port match"
1440 )]
1441 #[test_case(
1442 UdpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1443 PortMatcher { range: 53..=53, invert: false }
1444 )),
1445 FakeUdpSocket {
1446 src_port: Some(54), dst_port: Some(12345), state: UdpSocketState::Bound
1447 } => false;
1448 "src_port no match"
1449 )]
1450 #[test_case(
1451 UdpSocketMatcher::DstPort(BoundPortMatcher::Bound(
1452 PortMatcher { range: 12345..=12345, invert: false }
1453 )),
1454 FakeUdpSocket {
1455 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1456 } => true;
1457 "dst_port match"
1458 )]
1459 #[test_case(
1460 UdpSocketMatcher::DstPort(BoundPortMatcher::Bound(
1461 PortMatcher { range: 12345..=12345, invert: false }
1462 )),
1463 FakeUdpSocket {
1464 src_port: Some(53), dst_port: Some(12346), state: UdpSocketState::Bound
1465 } => false;
1466 "dst_port no match"
1467 )]
1468 #[test_case(
1469 UdpSocketMatcher::State(UdpStateMatcher::BOUND),
1470 FakeUdpSocket {
1471 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1472 } => true;
1473 "state match bound"
1474 )]
1475 #[test_case(
1476 UdpSocketMatcher::State(UdpStateMatcher::CONNECTED),
1477 FakeUdpSocket {
1478 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1479 } => false;
1480 "state no match connected"
1481 )]
1482 #[test_case(
1483 UdpSocketMatcher::State(UdpStateMatcher::BOUND | UdpStateMatcher::CONNECTED),
1484 FakeUdpSocket {
1485 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1486 } => true;
1487 "state multi match bound"
1488 )]
1489 #[test_case(
1490 UdpSocketMatcher::State(UdpStateMatcher::BOUND | UdpStateMatcher::CONNECTED),
1491 FakeUdpSocket {
1492 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Connected
1493 } => true;
1494 "state multi match connected"
1495 )]
1496 #[test_case(
1497 UdpSocketMatcher::SrcPort(BoundPortMatcher::Unbound),
1498 FakeUdpSocket {
1499 src_port: None, dst_port: Some(12345), state: UdpSocketState::Bound
1500 } => true;
1501 "src_port unbound match"
1502 )]
1503 #[test_case(
1504 UdpSocketMatcher::SrcPort(BoundPortMatcher::Unbound),
1505 FakeUdpSocket {
1506 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1507 } => false;
1508 "src_port unbound no match"
1509 )]
1510 #[test_case(
1511 UdpSocketMatcher::DstPort(BoundPortMatcher::Unbound),
1512 FakeUdpSocket { src_port: Some(53), dst_port: None, state: UdpSocketState::Bound } => true;
1513 "dst_port unbound match"
1514 )]
1515 #[test_case(
1516 UdpSocketMatcher::DstPort(BoundPortMatcher::Unbound),
1517 FakeUdpSocket {
1518 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1519 } => false;
1520 "dst_port unbound no match"
1521 )]
1522 fn udp_socket_matcher(matcher: UdpSocketMatcher, socket: FakeUdpSocket) -> bool {
1523 matcher.matches(&socket)
1524 }
1525
1526 #[ip_test(I)]
1527 #[test_case(
1528 IpSocketMatcher::Proto(SocketTransportProtocolMatcher::Tcp(TcpSocketMatcher::Empty)),
1529 FakeIpSocket {
1530 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1531 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1532 proto: FakeTcpSocket {
1533 src_port: Some(80),
1534 dst_port: Some(12345),
1535 state: TcpSocketState::Established,
1536 },
1537 cookie: 0,
1538 intf: None,
1539 marks: Marks::default(),
1540 } => true;
1541 "tcpm empty"
1542 )]
1543 #[test_case(
1544 IpSocketMatcher::Proto(SocketTransportProtocolMatcher::Tcp(TcpSocketMatcher::Empty)),
1545 FakeIpSocket {
1546 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1547 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1548 proto: FakeUdpSocket {
1549 src_port: Some(53),
1550 dst_port: Some(12345),
1551 state: UdpSocketState::Bound,
1552 },
1553 cookie: 0,
1554 intf: None,
1555 marks: Marks::default(),
1556 } => false;
1557 "tcp empty no match udp"
1558 )]
1559 #[test_case(
1560 IpSocketMatcher::Proto(SocketTransportProtocolMatcher::Udp(UdpSocketMatcher::Empty)),
1561 FakeIpSocket {
1562 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1563 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1564 proto: FakeTcpSocket {
1565 src_port: Some(80),
1566 dst_port: Some(12345),
1567 state: TcpSocketState::Established
1568 },
1569 cookie: 0,
1570 intf: None,
1571 marks: Marks::default(),
1572 } => false;
1573 "udp empty no match tcp"
1574 )]
1575 #[test_case(
1576 IpSocketMatcher::Proto(SocketTransportProtocolMatcher::Udp(UdpSocketMatcher::Empty)),
1577 FakeIpSocket {
1578 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1579 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1580 proto: FakeUdpSocket {
1581 src_port: Some(53),
1582 dst_port: Some(12345),
1583 state: UdpSocketState::Bound,
1584 },
1585 cookie: 0,
1586 intf: None,
1587 marks: Marks::default(),
1588 } => true;
1589 "udp empty"
1590 )]
1591 #[test_case(
1592 IpSocketMatcher::Proto(
1593 SocketTransportProtocolMatcher::Tcp(
1594 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1595 PortMatcher { range: 80..=80, invert: false }
1596 ))
1597 )
1598 ),
1599 FakeIpSocket {
1600 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1601 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1602 proto: FakeTcpSocket {
1603 src_port: Some(80),
1604 dst_port: Some(12345),
1605 state: TcpSocketState::Established,
1606 },
1607 cookie: 0,
1608 intf: None,
1609 marks: Marks::default(),
1610 } => true;
1611 "tcp src_port match"
1612 )]
1613 #[test_case(
1614 IpSocketMatcher::Proto(
1615 SocketTransportProtocolMatcher::Tcp(
1616 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1617 PortMatcher { range: 80..=80, invert: false }
1618 ))
1619 )
1620 ),
1621 FakeIpSocket {
1622 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1623 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1624 proto: FakeTcpSocket {
1625 src_port: Some(81),
1626 dst_port: Some(12345),
1627 state: TcpSocketState::Established,
1628 },
1629 cookie: 0,
1630 intf: None,
1631 marks: Marks::default(),
1632 } => false;
1633 "tcp src_port no match"
1634 )]
1635 #[test_case(
1636 IpSocketMatcher::Proto(
1637 SocketTransportProtocolMatcher::Udp(
1638 UdpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1639 PortMatcher { range: 53..=53, invert: false }
1640 ))
1641 )
1642 ),
1643 FakeIpSocket {
1644 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1645 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1646 proto: FakeUdpSocket {
1647 src_port: Some(53),
1648 dst_port: Some(12345),
1649 state: UdpSocketState::Bound,
1650 },
1651 cookie: 0,
1652 intf: None,
1653 marks: Marks::default(),
1654 } => true;
1655 "udp src_port match"
1656 )]
1657 #[test_case(
1658 IpSocketMatcher::Proto(
1659 SocketTransportProtocolMatcher::Udp(
1660 UdpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1661 PortMatcher { range: 53..=53, invert: false }
1662 ))
1663 )
1664 ),
1665 FakeIpSocket {
1666 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1667 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1668 proto: FakeUdpSocket {
1669 src_port: Some(54),
1670 dst_port: Some(12345),
1671 state: UdpSocketState::Bound,
1672 },
1673 cookie: 0,
1674 intf: None,
1675 marks: Marks::default(),
1676 } => false;
1677 "udp src_port no match"
1678 )]
1679 #[test_case(
1680 IpSocketMatcher::Cookie(SocketCookieMatcher { cookie: 123, invert: false }),
1681 FakeIpSocket {
1682 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1683 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1684 proto: FakeTcpSocket {
1685 src_port: Some(80),
1686 dst_port: Some(12345),
1687 state: TcpSocketState::Established,
1688 },
1689 cookie: 123,
1690 intf: None,
1691 marks: Marks::default(),
1692 } => true;
1693 "cookie match"
1694 )]
1695 #[test_case(
1696 IpSocketMatcher::Cookie(SocketCookieMatcher { cookie: 123, invert: false }),
1697 FakeIpSocket {
1698 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1699 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1700 proto: FakeTcpSocket {
1701 src_port: Some(80),
1702 dst_port: Some(12345),
1703 state: TcpSocketState::Established,
1704 },
1705 cookie: 456,
1706 intf: None,
1707 marks: Marks::default(),
1708 } => false;
1709 "cookie no match"
1710 )]
1711 #[test_case(
1712 IpSocketMatcher::Mark(MarkInDomainMatcher {
1713 domain: MarkDomain::Mark1,
1714 matcher: MarkMatcher::Unmarked,
1715 }),
1716 FakeIpSocket {
1717 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1718 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1719 proto: FakeTcpSocket {
1720 src_port: Some(80),
1721 dst_port: Some(12345),
1722 state: TcpSocketState::Established,
1723 },
1724 cookie: 0,
1725 intf: None,
1726 marks: Marks::default(),
1727 } => true;
1728 "mark1 unmarked match"
1729 )]
1730 #[test_case(
1731 IpSocketMatcher::Mark(MarkInDomainMatcher {
1732 domain: MarkDomain::Mark1,
1733 matcher: MarkMatcher::Unmarked,
1734 }),
1735 FakeIpSocket {
1736 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1737 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1738 proto: FakeTcpSocket {
1739 src_port: Some(80),
1740 dst_port: Some(12345),
1741 state: TcpSocketState::Established,
1742 },
1743 cookie: 0,
1744 intf: None,
1745 marks: Marks::new([(MarkDomain::Mark1, 1)]),
1746 } => false;
1747 "mark1 unmarked no match"
1748 )]
1749 #[test_case(
1750 IpSocketMatcher::Mark(MarkInDomainMatcher {
1751 domain: MarkDomain::Mark2,
1752 matcher: MarkMatcher::Unmarked,
1753 }),
1754 FakeIpSocket {
1755 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1756 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1757 proto: FakeTcpSocket {
1758 src_port: Some(80),
1759 dst_port: Some(12345),
1760 state: TcpSocketState::Established,
1761 },
1762 cookie: 0,
1763 intf: None,
1764 marks: Marks::default(),
1765 } => true;
1766 "mark2 unmarked match"
1767 )]
1768 #[test_case(
1769 IpSocketMatcher::Mark(MarkInDomainMatcher {
1770 domain: MarkDomain::Mark2,
1771 matcher: MarkMatcher::Unmarked,
1772 }),
1773 FakeIpSocket {
1774 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1775 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1776 proto: FakeTcpSocket {
1777 src_port: Some(80),
1778 dst_port: Some(12345),
1779 state: TcpSocketState::Established,
1780 },
1781 cookie: 0,
1782 intf: None,
1783 marks: Marks::new([(MarkDomain::Mark2, 1)]),
1784 } => false;
1785 "mark2 unmarked no match"
1786 )]
1787 #[test_case(
1788 IpSocketMatcher::BoundInterface(BoundInterfaceMatcher::Bound(
1789 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
1790 )),
1791 FakeIpSocket {
1792 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1793 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1794 proto: FakeTcpSocket {
1795 src_port: Some(80),
1796 dst_port: Some(12345),
1797 state: TcpSocketState::Established,
1798 },
1799 cookie: 0,
1800 intf: Some(FakeMatcherDeviceId::wlan_interface()),
1801 marks: Marks::default(),
1802 } => true;
1803 "bound_interface match"
1804 )]
1805 #[test_case(
1806 IpSocketMatcher::BoundInterface(BoundInterfaceMatcher::Bound(
1807 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
1808 )),
1809 FakeIpSocket {
1810 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1811 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1812 proto: FakeTcpSocket {
1813 src_port: Some(80),
1814 dst_port: Some(12345),
1815 state: TcpSocketState::Established,
1816 },
1817 cookie: 0,
1818 intf: Some(FakeMatcherDeviceId::ethernet_interface()),
1819 marks: Marks::default(),
1820 } => false;
1821 "bound_interface no match"
1822 )]
1823 #[test_case(
1824 IpSocketMatcher::BoundInterface(BoundInterfaceMatcher::Unbound),
1825 FakeIpSocket {
1826 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1827 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1828 proto: FakeTcpSocket {
1829 src_port: Some(80),
1830 dst_port: Some(12345),
1831 state: TcpSocketState::Established,
1832 },
1833 cookie: 0,
1834 intf: None,
1835 marks: Marks::default(),
1836 } => true;
1837 "bound_interface unbound match"
1838 )]
1839 #[test_case(
1840 IpSocketMatcher::BoundInterface(BoundInterfaceMatcher::Unbound),
1841 FakeIpSocket {
1842 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1843 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1844 proto: FakeTcpSocket {
1845 src_port: Some(80),
1846 dst_port: Some(12345),
1847 state: TcpSocketState::Established,
1848 },
1849 cookie: 0,
1850 intf: Some(FakeMatcherDeviceId::wlan_interface()),
1851 marks: Marks::default(),
1852 } => false;
1853 "bound_interface unbound no match"
1854 )]
1855 fn ip_socket_matcher<I: TestIpExt, T: MaybeSocketTransportProperties>(
1856 matcher: IpSocketMatcher<FakeDeviceClass>,
1857 socket: FakeIpSocket<I, T>,
1858 ) -> bool {
1859 matcher.matches(&socket)
1860 }
1861
1862 #[ip_test(I)]
1863 fn address_matcher_type<I: TestIpExt>() {
1864 let local_ip = I::TEST_ADDRS.local_ip.get();
1865 let remote_ip = I::TEST_ADDRS.remote_ip.get();
1866
1867 let matcher = AddressMatcherType::Subnet(SubnetMatcher(I::TEST_ADDRS.subnet));
1868 assert!(matcher.matches(&local_ip));
1869 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
1870
1871 let matcher = AddressMatcherType::Range(local_ip..=remote_ip);
1872 assert!(matcher.matches(&local_ip));
1873 assert!(matcher.matches(&remote_ip));
1874 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
1875 }
1876
1877 #[ip_test(I)]
1878 fn address_matcher<I: TestIpExt>() {
1879 let local_ip = I::TEST_ADDRS.local_ip.get();
1880 let remote_ip = I::TEST_ADDRS.remote_ip.get();
1881
1882 let matcher = AddressMatcher {
1883 matcher: AddressMatcherType::Subnet(SubnetMatcher(I::TEST_ADDRS.subnet)),
1884 invert: false,
1885 };
1886 assert!(matcher.matches(&local_ip));
1887 assert!(matcher.matches(&remote_ip));
1888 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
1889
1890 let matcher = AddressMatcher {
1891 matcher: AddressMatcherType::Subnet(SubnetMatcher(I::TEST_ADDRS.subnet)),
1892 invert: true,
1893 };
1894 assert!(!matcher.matches(&local_ip));
1895 assert!(!matcher.matches(&remote_ip));
1896 assert!(matcher.matches(&I::get_other_remote_ip_address(1)));
1897
1898 let matcher = AddressMatcher {
1899 matcher: AddressMatcherType::Range(local_ip..=remote_ip),
1900 invert: false,
1901 };
1902 assert!(matcher.matches(&local_ip));
1903 assert!(matcher.matches(&remote_ip));
1904 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
1905
1906 let matcher = AddressMatcher {
1907 matcher: AddressMatcherType::Range(local_ip..=remote_ip),
1908 invert: true,
1909 };
1910 assert!(!matcher.matches(&local_ip));
1911 assert!(!matcher.matches(&remote_ip));
1912 assert!(matcher.matches(&I::get_other_remote_ip_address(1)));
1913 }
1914
1915 #[test]
1916 fn agnostic_address_matcher() {
1917 let v4_addr = IpAddr::V4(Ipv4Addr::new([192, 0, 2, 1]));
1918 let v6_addr = IpAddr::V6(Ipv6Addr::new([0x2001, 0xdb8, 0, 0, 0, 0, 0, 1]));
1919
1920 let v4_subnet = Subnet::new(Ipv4Addr::new([192, 0, 2, 0]), 24).unwrap();
1921 let v6_subnet = Subnet::new(Ipv6Addr::new([0x2001, 0xdb8, 0, 0, 0, 0, 0, 0]), 32).unwrap();
1922
1923 let v4_matcher =
1924 BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(AddressMatcher {
1925 matcher: AddressMatcherType::Subnet(SubnetMatcher(v4_subnet)),
1926 invert: false,
1927 }));
1928 assert!(v4_matcher.matches(&Some(v4_addr)));
1929 assert!(!v4_matcher.matches(&Some(v6_addr)));
1930
1931 let v6_matcher =
1932 BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(AddressMatcher {
1933 matcher: AddressMatcherType::Subnet(SubnetMatcher(v6_subnet)),
1934 invert: false,
1935 }));
1936 assert!(!v6_matcher.matches(&Some(v4_addr)));
1937 assert!(v6_matcher.matches(&Some(v6_addr)));
1938 }
1939
1940 #[test_case(IpSocketMatcher::Family(IpVersion::V4) => true; "v4 family matcher on v4 socket")]
1941 #[test_case(IpSocketMatcher::Family(IpVersion::V6) => false; "v6 family matcher on v4 socket")]
1942 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
1943 AddressMatcher {
1944 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv4::TEST_ADDRS.subnet)),
1945 invert: false,
1946 }
1947 ))) => true; "src_addr match")]
1948 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
1949 AddressMatcher {
1950 matcher: AddressMatcherType::Subnet(SubnetMatcher(
1951 Subnet::new(Ipv4Addr::new([0, 0, 0, 0]), 32).unwrap()
1952 )),
1953 invert: false,
1954 }
1955 ))) => false; "src_addr no match")]
1956 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
1957 AddressMatcher {
1958 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv4::TEST_ADDRS.subnet)),
1959 invert: false,
1960 }
1961 ))) => true; "dst_addr match")]
1962 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
1963 AddressMatcher {
1964 matcher: AddressMatcherType::Subnet(SubnetMatcher(
1965 Subnet::new(Ipv4Addr::new([0, 0, 0, 0]), 32).unwrap()
1966 )),
1967 invert: false,
1968 }))) => false; "dst_addr no match")]
1969 #[test_case(
1970 IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Unbound) => false;
1971 "src_addr unbound mismatch"
1972 )]
1973 #[test_case(
1974 IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Unbound) => false;
1975 "dst_addr unbound mismatch"
1976 )]
1977 fn ip_socket_matcher_test_v4(matcher: IpSocketMatcher<FakeDeviceClass>) -> bool {
1978 let socket = FakeIpSocket::<Ipv4, _> {
1979 src_ip: Some(<Ipv4 as TestIpExt>::TEST_ADDRS.local_ip.get()),
1980 dst_ip: Some(<Ipv4 as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1981 proto: FakeTcpSocket {
1982 src_port: Some(80),
1983 dst_port: Some(12345),
1984 state: TcpSocketState::Established,
1985 },
1986 cookie: 0,
1987 intf: None,
1988 marks: Marks::default(),
1989 };
1990 matcher.matches(&socket)
1991 }
1992
1993 #[test_case(IpSocketMatcher::Family(IpVersion::V4) => false; "v4 family matcher on v6 socket")]
1994 #[test_case(IpSocketMatcher::Family(IpVersion::V6) => true; "v6 family matcher on v6 socket")]
1995 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(
1996 AddressMatcher {
1997 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv6::TEST_ADDRS.subnet)),
1998 invert: false,
1999 }
2000 ))) => true; "src_addr match v6")]
2001 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(
2002 AddressMatcher {
2003 matcher: AddressMatcherType::Subnet(SubnetMatcher(
2004 Subnet::new(Ipv6Addr::new([0; 8]), 128).unwrap()
2005 )),
2006 invert: false,
2007 }
2008 ))) => false; "src_addr no match v6")]
2009 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(
2010 AddressMatcher {
2011 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv6::TEST_ADDRS.subnet)),
2012 invert: false,
2013 }
2014 ))) => true; "dst_addr match v6")]
2015 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(
2016 AddressMatcher {
2017 matcher: AddressMatcherType::Subnet(SubnetMatcher(
2018 Subnet::new(Ipv6Addr::new([0; 8]), 128).unwrap()
2019 )),
2020 invert: false,
2021 }
2022 ))) => false; "dst_addr no match v6")]
2023 fn ip_socket_matcher_test_v6(matcher: IpSocketMatcher<FakeDeviceClass>) -> bool {
2024 let socket = FakeIpSocket::<Ipv6, _> {
2025 src_ip: Some(<Ipv6 as TestIpExt>::TEST_ADDRS.local_ip.get()),
2026 dst_ip: Some(<Ipv6 as TestIpExt>::TEST_ADDRS.remote_ip.get()),
2027 proto: FakeTcpSocket {
2028 src_port: Some(80),
2029 dst_port: Some(12345),
2030 state: TcpSocketState::Established,
2031 },
2032 cookie: 0,
2033 intf: None,
2034 marks: Marks::default(),
2035 };
2036 matcher.matches(&socket)
2037 }
2038
2039 #[test_case(
2040 IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Unbound) => true;
2041 "src_addr unbound match"
2042 )]
2043 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
2044 AddressMatcher {
2045 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv4::TEST_ADDRS.subnet)),
2046 invert: false,
2047 }
2048 ))) => false; "src_addr bound mismatch")]
2049 #[test_case(
2050 IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Unbound) => true;
2051 "dst_addr unbound match"
2052 )]
2053 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
2054 AddressMatcher {
2055 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv4::TEST_ADDRS.subnet)),
2056 invert: false,
2057 }
2058 ))) => false; "dst_addr bound mismatch")]
2059
2060 fn ip_socket_matcher_unbound(matcher: IpSocketMatcher<FakeDeviceClass>) -> bool {
2061 let socket = FakeIpSocket::<Ipv4, _> {
2062 src_ip: None,
2063 dst_ip: None,
2064 proto: FakeTcpSocket {
2065 src_port: Some(80),
2066 dst_port: Some(12345),
2067 state: TcpSocketState::Established,
2068 },
2069 cookie: 0,
2070 intf: None,
2071 marks: Marks::default(),
2072 };
2073 matcher.matches(&socket)
2074 }
2075}