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::{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> InspectableValue for AddressMatcher<A> {
613 fn record<I: Inspector>(&self, name: &str, inspector: &mut I) {
614 let AddressMatcher { matcher, invert } = self;
615
616 inspector.record_child(name, |inspector| {
617 inspector.record_bool("invert", *invert);
618 match matcher {
619 AddressMatcherType::Subnet(SubnetMatcher(subnet)) => {
620 inspector.record_display("subnet", subnet)
621 }
622 AddressMatcherType::Range(range) => {
623 inspector.record_display("start", range.start());
624 inspector.record_display("end", range.end());
625 }
626 }
627 })
628 }
629}
630
631impl<A: IpAddress> Matcher<A> for AddressMatcher<A> {
632 fn matches(&self, addr: &A) -> bool {
633 let Self { matcher, invert } = self;
634 matcher.matches(addr) ^ *invert
635 }
636}
637
638pub enum AddressMatcherEither {
640 V4(AddressMatcher<Ipv4Addr>),
642 V6(AddressMatcher<Ipv6Addr>),
644}
645
646pub enum BoundAddressMatcherEither {
648 Bound(AddressMatcherEither),
650 Unbound,
652}
653
654impl Matcher<Option<IpAddr>> for BoundAddressMatcherEither {
655 fn matches(&self, addr: &Option<IpAddr>) -> bool {
656 match (self, addr) {
657 (BoundAddressMatcherEither::Unbound, None) => true,
658 (BoundAddressMatcherEither::Bound(matcher), Some(addr)) => match (matcher, addr) {
659 (AddressMatcherEither::V4(matcher), IpAddr::V4(addr)) => matcher.matches(addr),
660 (AddressMatcherEither::V6(matcher), IpAddr::V6(addr)) => matcher.matches(addr),
661 _ => false,
662 },
663 _ => false,
664 }
665 }
666}
667
668pub trait IpSocketProperties<DeviceClass> {
671 fn family_matches(&self, family: &net_types::ip::IpVersion) -> bool;
673
674 fn src_addr_matches(&self, addr: &BoundAddressMatcherEither) -> bool;
677
678 fn dst_addr_matches(&self, addr: &BoundAddressMatcherEither) -> bool;
681
682 fn transport_protocol_matches(&self, matcher: &SocketTransportProtocolMatcher) -> bool;
685
686 fn bound_interface_matches(&self, iface: &BoundInterfaceMatcher<DeviceClass>) -> bool;
689
690 fn cookie_matches(&self, cookie: &SocketCookieMatcher) -> bool;
692
693 fn mark_matches(&self, matcher: &MarkInDomainMatcher) -> bool;
695}
696
697pub enum IpSocketMatcher<DeviceClass> {
699 Family(net_types::ip::IpVersion),
701 SrcAddr(BoundAddressMatcherEither),
703 DstAddr(BoundAddressMatcherEither),
705 Proto(SocketTransportProtocolMatcher),
707 BoundInterface(BoundInterfaceMatcher<DeviceClass>),
709 Cookie(SocketCookieMatcher),
711 Mark(MarkInDomainMatcher),
713}
714
715impl<DeviceClass, S: IpSocketProperties<DeviceClass>> Matcher<S> for IpSocketMatcher<DeviceClass> {
716 fn matches(&self, actual: &S) -> bool {
717 match self {
718 IpSocketMatcher::Family(family) => actual.family_matches(family),
719 IpSocketMatcher::SrcAddr(addr) => actual.src_addr_matches(addr),
720 IpSocketMatcher::DstAddr(addr) => actual.dst_addr_matches(addr),
721 IpSocketMatcher::Proto(proto) => actual.transport_protocol_matches(proto),
722 IpSocketMatcher::BoundInterface(iface) => actual.bound_interface_matches(iface),
723 IpSocketMatcher::Cookie(cookie) => actual.cookie_matches(cookie),
724 IpSocketMatcher::Mark(mark) => actual.mark_matches(mark),
725 }
726 }
727}
728
729pub trait IpSocketPropertiesMatcher<DeviceClass> {
732 fn matches_ip_socket<S: IpSocketProperties<DeviceClass>>(&self, actual: &S) -> bool;
734}
735
736impl<DeviceClass> IpSocketPropertiesMatcher<DeviceClass> for IpSocketMatcher<DeviceClass> {
737 fn matches_ip_socket<S: IpSocketProperties<DeviceClass>>(&self, actual: &S) -> bool {
738 self.matches(actual)
739 }
740}
741
742impl<DeviceClass> IpSocketPropertiesMatcher<DeviceClass> for [IpSocketMatcher<DeviceClass>] {
743 fn matches_ip_socket<S: IpSocketProperties<DeviceClass>>(&self, actual: &S) -> bool {
744 self.iter().all(|matcher| matcher.matches(actual))
745 }
746}
747
748#[cfg(any(test, feature = "testutils"))]
749pub(crate) mod testutil {
750 use alloc::string::String;
751 use core::num::NonZeroU64;
752
753 use crate::matchers::InterfaceProperties;
754 use crate::testutil::{FakeDeviceClass, FakeStrongDeviceId, FakeWeakDeviceId};
755 use crate::{DeviceIdentifier, StrongDeviceIdentifier};
756
757 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
759 #[allow(missing_docs)]
760 pub struct FakeMatcherDeviceId {
761 pub id: NonZeroU64,
762 pub name: String,
763 pub class: FakeDeviceClass,
764 }
765
766 impl FakeMatcherDeviceId {
767 pub fn wlan_interface() -> FakeMatcherDeviceId {
771 FakeMatcherDeviceId {
772 id: NonZeroU64::new(1).unwrap(),
773 name: String::from("wlan"),
774 class: FakeDeviceClass::Wlan,
775 }
776 }
777
778 pub fn ethernet_interface() -> FakeMatcherDeviceId {
782 FakeMatcherDeviceId {
783 id: NonZeroU64::new(2).unwrap(),
784 name: String::from("eth"),
785 class: FakeDeviceClass::Ethernet,
786 }
787 }
788 }
789
790 impl StrongDeviceIdentifier for FakeMatcherDeviceId {
791 type Weak = FakeWeakDeviceId<Self>;
792
793 fn downgrade(&self) -> Self::Weak {
794 FakeWeakDeviceId(self.clone())
795 }
796 }
797
798 impl DeviceIdentifier for FakeMatcherDeviceId {
799 fn is_loopback(&self) -> bool {
800 false
801 }
802 }
803
804 impl FakeStrongDeviceId for FakeMatcherDeviceId {
805 fn is_alive(&self) -> bool {
806 true
807 }
808 }
809
810 impl PartialEq<FakeWeakDeviceId<FakeMatcherDeviceId>> for FakeMatcherDeviceId {
811 fn eq(&self, FakeWeakDeviceId(other): &FakeWeakDeviceId<FakeMatcherDeviceId>) -> bool {
812 self == other
813 }
814 }
815
816 impl InterfaceProperties<FakeDeviceClass> for FakeMatcherDeviceId {
817 fn id_matches(&self, id: &NonZeroU64) -> bool {
818 &self.id == id
819 }
820
821 fn name_matches(&self, name: &str) -> bool {
822 &self.name == name
823 }
824
825 fn device_class_matches(&self, class: &FakeDeviceClass) -> bool {
826 &self.class == class
827 }
828 }
829}
830
831#[cfg(test)]
832mod tests {
833 use ip_test_macro::ip_test;
834 use net_types::Witness;
835 use net_types::ip::{Ip, IpVersion, Ipv4, Ipv6};
836 use test_case::test_case;
837
838 use super::*;
839 use crate::testutil::{FakeDeviceClass, FakeMatcherDeviceId, TestIpExt};
840
841 #[derive(Debug)]
843 struct TrueMatcher;
844
845 impl Matcher<bool> for TrueMatcher {
846 fn matches(&self, actual: &bool) -> bool {
847 *actual
848 }
849 }
850
851 #[test]
852 fn test_optional_matcher_optional_value() {
853 assert!(TrueMatcher.matches(&true));
854 assert!(!TrueMatcher.matches(&false));
855
856 assert!(TrueMatcher.required_matches(Some(&true)));
857 assert!(!TrueMatcher.required_matches(Some(&false)));
858 assert!(!TrueMatcher.required_matches(None));
859
860 assert!(Some(TrueMatcher).matches(&true));
861 assert!(!Some(TrueMatcher).matches(&false));
862 assert!(None::<TrueMatcher>.matches(&true));
863 assert!(None::<TrueMatcher>.matches(&false));
864
865 assert!(Some(TrueMatcher).required_matches(Some(&true)));
866 assert!(!Some(TrueMatcher).required_matches(Some(&false)));
867 assert!(!Some(TrueMatcher).required_matches(None));
868 assert!(None::<TrueMatcher>.required_matches(Some(&true)));
869 assert!(None::<TrueMatcher>.required_matches(Some(&false)));
870 assert!(None::<TrueMatcher>.required_matches(None));
871 }
872
873 #[test_case(
874 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id),
875 FakeMatcherDeviceId::wlan_interface() => true
876 )]
877 #[test_case(
878 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id),
879 FakeMatcherDeviceId::ethernet_interface() => false
880 )]
881 #[test_case(
882 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name),
883 FakeMatcherDeviceId::wlan_interface() => true
884 )]
885 #[test_case(
886 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name),
887 FakeMatcherDeviceId::ethernet_interface() => false
888 )]
889 #[test_case(
890 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan),
891 FakeMatcherDeviceId::wlan_interface() => true
892 )]
893 #[test_case(
894 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan),
895 FakeMatcherDeviceId::ethernet_interface() => false
896 )]
897 fn interface_matcher(
898 matcher: InterfaceMatcher<FakeDeviceClass>,
899 device: FakeMatcherDeviceId,
900 ) -> bool {
901 matcher.matches(&device)
902 }
903
904 #[test_case(BoundInterfaceMatcher::Unbound, None => true)]
905 #[test_case(
906 BoundInterfaceMatcher::Unbound,
907 Some(FakeMatcherDeviceId::wlan_interface()) => false
908 )]
909 #[test_case(
910 BoundInterfaceMatcher::Bound(
911 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
912 ),
913 None => false
914 )]
915 #[test_case(
916 BoundInterfaceMatcher::Bound(
917 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
918 ),
919 Some(FakeMatcherDeviceId::wlan_interface()) => true
920 )]
921 #[test_case(
922 BoundInterfaceMatcher::Bound(
923 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
924 ),
925 Some(FakeMatcherDeviceId::ethernet_interface()) => false
926 )]
927 #[test_case(
928 BoundInterfaceMatcher::Bound(
929 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name)
930 ),
931 None => false
932 )]
933 #[test_case(
934 BoundInterfaceMatcher::Bound(
935 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name)
936 ),
937 Some(FakeMatcherDeviceId::wlan_interface()) => true
938 )]
939 #[test_case(
940 BoundInterfaceMatcher::Bound(
941 InterfaceMatcher::Name(FakeMatcherDeviceId::wlan_interface().name)
942 ),
943 Some(FakeMatcherDeviceId::ethernet_interface()) => false
944 )]
945 #[test_case(
946 BoundInterfaceMatcher::Bound(
947 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan)
948 ),
949 None => false
950 )]
951 #[test_case(
952 BoundInterfaceMatcher::Bound(
953 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan)
954 ),
955 Some(FakeMatcherDeviceId::wlan_interface()) => true
956 )]
957 #[test_case(
958 BoundInterfaceMatcher::Bound(
959 InterfaceMatcher::DeviceClass(FakeDeviceClass::Wlan)
960 ),
961 Some(FakeMatcherDeviceId::ethernet_interface()) => false
962 )]
963 fn bound_interface_matcher(
964 matcher: BoundInterfaceMatcher<FakeDeviceClass>,
965 device: Option<FakeMatcherDeviceId>,
966 ) -> bool {
967 matcher.matches(&device.as_ref())
968 }
969
970 #[ip_test(I)]
971 fn subnet_matcher<I: Ip + TestIpExt>() {
972 let matcher = SubnetMatcher(I::TEST_ADDRS.subnet);
973 assert!(matcher.matches(&I::TEST_ADDRS.local_ip));
974 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
975 }
976
977 #[test_case(MarkMatcher::Unmarked, Mark(None) => true; "unmarked matches none")]
978 #[test_case(MarkMatcher::Unmarked, Mark(Some(0)) => false; "unmarked does not match some")]
979 #[test_case(MarkMatcher::Marked {
980 mask: 1,
981 start: 0,
982 end: 0,
983 invert: false,
984 }, Mark(None) => false; "marked does not match none")]
985 #[test_case(MarkMatcher::Marked {
986 mask: 1,
987 start: 0,
988 end: 0,
989 invert: false,
990 }, Mark(Some(0)) => true; "marked 0 mask 1 matches 0")]
991 #[test_case(MarkMatcher::Marked {
992 mask: 1,
993 start: 0,
994 end: 0,
995 invert: false,
996 }, Mark(Some(1)) => false; "marked 0 mask 1 does not match 1")]
997 #[test_case(MarkMatcher::Marked {
998 mask: 1,
999 start: 0,
1000 end: 0,
1001 invert: false,
1002 }, Mark(Some(2)) => true; "marked 0 mask 1 matches 2")]
1003 #[test_case(MarkMatcher::Marked {
1004 mask: 1,
1005 start: 0,
1006 end: 0,
1007 invert: false,
1008 }, Mark(Some(3)) => false; "marked 0 mask 1 does not match 3")]
1009 #[test_case(MarkMatcher::Marked {
1010 mask: !0,
1011 start: 0,
1012 end: 10,
1013 invert: true,
1014 }, Mark(Some(5)) => false; "marked invert no match in range")]
1015 #[test_case(MarkMatcher::Marked {
1016 mask: !0,
1017 start: 0,
1018 end: 10,
1019 invert: true,
1020 }, Mark(Some(11)) => true; "marked invert matches out of range")]
1021 fn mark_matcher(matcher: MarkMatcher, mark: Mark) -> bool {
1022 matcher.matches(&mark)
1023 }
1024
1025 #[test_case(
1026 MarkMatchers::new(
1027 [(MarkDomain::Mark1, MarkMatcher::Unmarked),
1028 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1029 ),
1030 Marks::new([]) => true;
1031 "all unmarked matches empty"
1032 )]
1033 #[test_case(
1034 MarkMatchers::new(
1035 [(MarkDomain::Mark1, MarkMatcher::Unmarked),
1036 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1037 ),
1038 Marks::new([(MarkDomain::Mark1, 1)]) => false;
1039 "all unmarked does not match mark1"
1040 )]
1041 #[test_case(
1042 MarkMatchers::new(
1043 [(MarkDomain::Mark1, MarkMatcher::Unmarked),
1044 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1045 ),
1046 Marks::new([(MarkDomain::Mark2, 1)]) => false;
1047 "all unmarked does not match mark2"
1048 )]
1049 #[test_case(
1050 MarkMatchers::new(
1051 [(MarkDomain::Mark1, MarkMatcher::Unmarked),
1052 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1053 ),
1054 Marks::new([
1055 (MarkDomain::Mark1, 1),
1056 (MarkDomain::Mark2, 1),
1057 ]) => false;
1058 "all unmarked does not match mark1 and mark2"
1059 )]
1060 #[test_case(
1061 MarkMatchers::new(
1062 [(MarkDomain::Mark1, MarkMatcher::Marked { mask: !0, start: 1, end: 1, invert: false }),
1063 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1064 ),
1065 Marks::new([(MarkDomain::Mark1, 1)]) => true;
1066 "mark1 marked matches"
1067 )]
1068 #[test_case(
1069 MarkMatchers::new(
1070 [(MarkDomain::Mark1, MarkMatcher::Marked { mask: !0, start: 1, end: 1, invert: false }),
1071 (MarkDomain::Mark2, MarkMatcher::Unmarked)]
1072 ),
1073 Marks::new([(MarkDomain::Mark1, 2)]) => false;
1074 "mark1 marked no match"
1075 )]
1076 #[test_case(
1077 MarkMatchers::new(
1078 [(MarkDomain::Mark1, MarkMatcher::Marked { mask: !0, start: 1, end: 1, invert: false }),
1079 (MarkDomain::Mark2, MarkMatcher::Marked { mask: !0, start: 2, end: 2, invert: false })]
1080 ),
1081 Marks::new([(MarkDomain::Mark1, 1), (MarkDomain::Mark2, 2)]) => true;
1082 "all marked matches"
1083 )]
1084 #[test_case(
1085 MarkMatchers::new(
1086 [(MarkDomain::Mark1, MarkMatcher::Marked { mask: !0, start: 1, end: 1, invert: false }),
1087 (MarkDomain::Mark2, MarkMatcher::Marked { mask: !0, start: 2, end: 2, invert: false })]
1088 ),
1089 Marks::new([(MarkDomain::Mark1, 1), (MarkDomain::Mark2, 3)]) => false;
1090 "all marked no match mark2"
1091 )]
1092 fn mark_matchers(matchers: MarkMatchers, marks: Marks) -> bool {
1093 matchers.matches(&marks)
1094 }
1095
1096 #[test_case(SocketCookieMatcher { cookie: 123, invert: false }, 123 => true)]
1097 #[test_case(SocketCookieMatcher { cookie: 123, invert: false }, 456 => false)]
1098 #[test_case(SocketCookieMatcher { cookie: 123, invert: true }, 123 => false)]
1099 #[test_case(SocketCookieMatcher { cookie: 123, invert: true }, 456 => true)]
1100 fn socket_cookie_matcher(matcher: SocketCookieMatcher, actual: u64) -> bool {
1101 matcher.matches(&actual)
1102 }
1103
1104 #[test_case(PortMatcher { range: 10..=20, invert: false }, 9 => false)]
1105 #[test_case(PortMatcher { range: 10..=20, invert: false }, 10 => true)]
1106 #[test_case(PortMatcher { range: 10..=20, invert: false }, 15 => true)]
1107 #[test_case(PortMatcher { range: 10..=20, invert: false }, 20 => true)]
1108 #[test_case(PortMatcher { range: 10..=20, invert: false }, 21 => false)]
1109 #[test_case(PortMatcher { range: 10..=20, invert: true }, 9 => true)]
1110 #[test_case(PortMatcher { range: 10..=20, invert: true }, 10 => false)]
1111 #[test_case(PortMatcher { range: 10..=20, invert: true }, 15 => false)]
1112 #[test_case(PortMatcher { range: 10..=20, invert: true }, 20 => false)]
1113 #[test_case(PortMatcher { range: 10..=20, invert: true }, 21 => true)]
1114 fn port_matcher(matcher: PortMatcher, actual: u16) -> bool {
1115 matcher.matches(&actual)
1116 }
1117
1118 #[test_case(BoundPortMatcher::Unbound, None => true)]
1119 #[test_case(BoundPortMatcher::Unbound, Some(80) => false)]
1120 #[test_case(
1121 BoundPortMatcher::Bound(PortMatcher { range: 10..=20, invert: false }),
1122 None => false
1123 )]
1124 #[test_case(
1125 BoundPortMatcher::Bound(PortMatcher { range: 10..=20, invert: false }),
1126 Some(10) => true
1127 )]
1128 #[test_case(
1129 BoundPortMatcher::Bound(PortMatcher { range: 10..=20, invert: false }),
1130 Some(9) => false
1131 )]
1132 fn bound_port_matcher(matcher: BoundPortMatcher, actual: Option<u16>) -> bool {
1133 matcher.matches(&actual)
1134 }
1135
1136 struct FakeTcpSocket {
1137 src_port: Option<u16>,
1138 dst_port: Option<u16>,
1139 state: TcpSocketState,
1140 }
1141
1142 impl MaybeSocketTransportProperties for FakeTcpSocket {
1143 type TcpProps<'a>
1144 = Self
1145 where
1146 Self: 'a;
1147
1148 type UdpProps<'a>
1149 = Never
1150 where
1151 Self: 'a;
1152
1153 fn tcp_socket_properties(&self) -> Option<&Self::TcpProps<'_>> {
1154 Some(self)
1155 }
1156
1157 fn udp_socket_properties(&self) -> Option<&Self::UdpProps<'_>> {
1158 None
1159 }
1160 }
1161
1162 impl TcpSocketProperties for FakeTcpSocket {
1163 fn src_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
1164 matcher.matches(&self.src_port)
1165 }
1166
1167 fn dst_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
1168 matcher.matches(&self.dst_port)
1169 }
1170
1171 fn state_matches(&self, matcher: &TcpStateMatcher) -> bool {
1172 matcher.matches(&self.state)
1173 }
1174 }
1175
1176 struct FakeUdpSocket {
1177 src_port: Option<u16>,
1178 dst_port: Option<u16>,
1179 state: UdpSocketState,
1180 }
1181
1182 impl MaybeSocketTransportProperties for FakeUdpSocket {
1183 type TcpProps<'a>
1184 = Never
1185 where
1186 Self: 'a;
1187
1188 type UdpProps<'a>
1189 = Self
1190 where
1191 Self: 'a;
1192
1193 fn tcp_socket_properties(&self) -> Option<&Self::TcpProps<'_>> {
1194 None
1195 }
1196
1197 fn udp_socket_properties(&self) -> Option<&Self::UdpProps<'_>> {
1198 Some(self)
1199 }
1200 }
1201
1202 impl UdpSocketProperties for FakeUdpSocket {
1203 fn src_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
1204 matcher.matches(&self.src_port)
1205 }
1206
1207 fn dst_port_matches(&self, matcher: &BoundPortMatcher) -> bool {
1208 matcher.matches(&self.dst_port)
1209 }
1210
1211 fn state_matches(&self, matcher: &UdpStateMatcher) -> bool {
1212 matcher.matches(&self.state)
1213 }
1214 }
1215
1216 struct FakeIpSocket<I, T>
1217 where
1218 I: TestIpExt,
1219 T: MaybeSocketTransportProperties,
1220 {
1221 src_ip: Option<I::Addr>,
1222 dst_ip: Option<I::Addr>,
1223 proto: T,
1224 intf: Option<FakeMatcherDeviceId>,
1225 cookie: u64,
1226 marks: Marks,
1227 }
1228
1229 impl<I, T> MaybeSocketTransportProperties for FakeIpSocket<I, T>
1230 where
1231 I: TestIpExt,
1232 T: MaybeSocketTransportProperties,
1233 {
1234 type TcpProps<'a>
1235 = T::TcpProps<'a>
1236 where
1237 Self: 'a;
1238
1239 type UdpProps<'a>
1240 = T::UdpProps<'a>
1241 where
1242 Self: 'a;
1243
1244 fn tcp_socket_properties(&self) -> Option<&Self::TcpProps<'_>> {
1245 self.proto.tcp_socket_properties()
1246 }
1247
1248 fn udp_socket_properties(&self) -> Option<&Self::UdpProps<'_>> {
1249 self.proto.udp_socket_properties()
1250 }
1251 }
1252
1253 impl<I, T> IpSocketProperties<FakeDeviceClass> for FakeIpSocket<I, T>
1254 where
1255 I: TestIpExt,
1256 T: MaybeSocketTransportProperties,
1257 {
1258 fn family_matches(&self, family: &net_types::ip::IpVersion) -> bool {
1259 *family == I::VERSION
1260 }
1261
1262 fn src_addr_matches(&self, addr: &BoundAddressMatcherEither) -> bool {
1263 addr.matches(&self.src_ip.map(|a| a.into()))
1264 }
1265
1266 fn dst_addr_matches(&self, addr: &BoundAddressMatcherEither) -> bool {
1267 addr.matches(&self.dst_ip.map(|a| a.into()))
1268 }
1269
1270 fn transport_protocol_matches(&self, matcher: &SocketTransportProtocolMatcher) -> bool {
1271 matcher.matches(self)
1272 }
1273
1274 fn bound_interface_matches(&self, iface: &BoundInterfaceMatcher<FakeDeviceClass>) -> bool {
1275 iface.matches(&self.intf.as_ref())
1276 }
1277
1278 fn cookie_matches(&self, cookie: &SocketCookieMatcher) -> bool {
1279 cookie.matches(&self.cookie)
1280 }
1281
1282 fn mark_matches(&self, matcher: &MarkInDomainMatcher) -> bool {
1283 matcher.matcher.matches(self.marks.get(matcher.domain))
1284 }
1285 }
1286
1287 #[test_case(
1288 TcpSocketMatcher::Empty,
1289 FakeTcpSocket {
1290 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1291 } => true;
1292 "empty matcher"
1293 )]
1294 #[test_case(
1295 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1296 PortMatcher { range: 80..=80, invert: false }
1297 )),
1298 FakeTcpSocket {
1299 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1300 } => true;
1301 "src_port match"
1302 )]
1303 #[test_case(
1304 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1305 PortMatcher { range: 80..=80, invert: false }
1306 )),
1307 FakeTcpSocket {
1308 src_port: Some(81), dst_port: Some(12345), state: TcpSocketState::Established
1309 } => false;
1310 "src_port no match"
1311 )]
1312 #[test_case(
1313 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(PortMatcher {
1314 range: 80..=80, invert: true
1315 })),
1316 FakeTcpSocket {
1317 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1318 } => false;
1319 "src_port invert no match"
1320 )]
1321 #[test_case(
1322 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1323 PortMatcher { range: 80..=80, invert: true }
1324 )),
1325 FakeTcpSocket {
1326 src_port: Some(81), dst_port: Some(12345), state: TcpSocketState::Established
1327 } => true;
1328 "src_port invert match"
1329 )]
1330 #[test_case(
1331 TcpSocketMatcher::DstPort(BoundPortMatcher::Bound(
1332 PortMatcher {range: 12345..=12345, invert: false }
1333 )),
1334 FakeTcpSocket {
1335 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1336 } => true;
1337 "dst_port match"
1338 )]
1339 #[test_case(
1340 TcpSocketMatcher::DstPort(BoundPortMatcher::Bound(
1341 PortMatcher { range: 12345..=12345, invert: false }
1342 )),
1343 FakeTcpSocket {
1344 src_port: Some(80), dst_port: Some(12346), state: TcpSocketState::Established
1345 } => false;
1346 "dst_port no match"
1347 )]
1348 #[test_case(
1349 TcpSocketMatcher::State(TcpStateMatcher::ESTABLISHED),
1350 FakeTcpSocket {
1351 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1352 } => true;
1353 "state match"
1354 )]
1355 #[test_case(
1356 TcpSocketMatcher::State(TcpStateMatcher::SYN_SENT),
1357 FakeTcpSocket {
1358 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1359 } => false;
1360 "state no match"
1361 )]
1362 #[test_case(
1363 TcpSocketMatcher::State(TcpStateMatcher::ESTABLISHED | TcpStateMatcher::SYN_SENT),
1364 FakeTcpSocket {
1365 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1366 } => true;
1367 "state multi match established"
1368 )]
1369 #[test_case(
1370 TcpSocketMatcher::State(TcpStateMatcher::ESTABLISHED | TcpStateMatcher::SYN_SENT),
1371 FakeTcpSocket {
1372 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::SynSent
1373 } => true;
1374 "state multi match syn_sent"
1375 )]
1376 #[test_case(
1377 TcpSocketMatcher::State(TcpStateMatcher::ESTABLISHED | TcpStateMatcher::SYN_SENT),
1378 FakeTcpSocket {
1379 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::FinWait1
1380 } => false;
1381 "state multi no match"
1382 )]
1383 #[test_case(
1384 TcpSocketMatcher::SrcPort(BoundPortMatcher::Unbound),
1385 FakeTcpSocket {
1386 src_port: None, dst_port: Some(12345), state: TcpSocketState::Established
1387 } => true;
1388 "src_port unbound match"
1389 )]
1390 #[test_case(
1391 TcpSocketMatcher::SrcPort(BoundPortMatcher::Unbound),
1392 FakeTcpSocket {
1393 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1394 } => false;
1395 "src_port unbound no match"
1396 )]
1397 #[test_case(
1398 TcpSocketMatcher::DstPort(BoundPortMatcher::Unbound),
1399 FakeTcpSocket {
1400 src_port: Some(80), dst_port: None, state: TcpSocketState::Established
1401 } => true;
1402 "dst_port unbound match"
1403 )]
1404 #[test_case(
1405 TcpSocketMatcher::DstPort(BoundPortMatcher::Unbound),
1406 FakeTcpSocket {
1407 src_port: Some(80), dst_port: Some(12345), state: TcpSocketState::Established
1408 } => false;
1409 "dst_port unbound no match"
1410 )]
1411 fn tcp_socket_matcher(matcher: TcpSocketMatcher, socket: FakeTcpSocket) -> bool {
1412 matcher.matches(&socket)
1413 }
1414
1415 #[test_case(
1416 UdpSocketMatcher::Empty,
1417 FakeUdpSocket {
1418 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1419 } => true;
1420 "empty matcher"
1421 )]
1422 #[test_case(
1423 UdpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1424 PortMatcher { range: 53..=53, invert: false }
1425 )),
1426 FakeUdpSocket {
1427 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1428 } => true;
1429 "src_port match"
1430 )]
1431 #[test_case(
1432 UdpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1433 PortMatcher { range: 53..=53, invert: false }
1434 )),
1435 FakeUdpSocket {
1436 src_port: Some(54), dst_port: Some(12345), state: UdpSocketState::Bound
1437 } => false;
1438 "src_port no match"
1439 )]
1440 #[test_case(
1441 UdpSocketMatcher::DstPort(BoundPortMatcher::Bound(
1442 PortMatcher { range: 12345..=12345, invert: false }
1443 )),
1444 FakeUdpSocket {
1445 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1446 } => true;
1447 "dst_port match"
1448 )]
1449 #[test_case(
1450 UdpSocketMatcher::DstPort(BoundPortMatcher::Bound(
1451 PortMatcher { range: 12345..=12345, invert: false }
1452 )),
1453 FakeUdpSocket {
1454 src_port: Some(53), dst_port: Some(12346), state: UdpSocketState::Bound
1455 } => false;
1456 "dst_port no match"
1457 )]
1458 #[test_case(
1459 UdpSocketMatcher::State(UdpStateMatcher::BOUND),
1460 FakeUdpSocket {
1461 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1462 } => true;
1463 "state match bound"
1464 )]
1465 #[test_case(
1466 UdpSocketMatcher::State(UdpStateMatcher::CONNECTED),
1467 FakeUdpSocket {
1468 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1469 } => false;
1470 "state no match connected"
1471 )]
1472 #[test_case(
1473 UdpSocketMatcher::State(UdpStateMatcher::BOUND | UdpStateMatcher::CONNECTED),
1474 FakeUdpSocket {
1475 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1476 } => true;
1477 "state multi match bound"
1478 )]
1479 #[test_case(
1480 UdpSocketMatcher::State(UdpStateMatcher::BOUND | UdpStateMatcher::CONNECTED),
1481 FakeUdpSocket {
1482 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Connected
1483 } => true;
1484 "state multi match connected"
1485 )]
1486 #[test_case(
1487 UdpSocketMatcher::SrcPort(BoundPortMatcher::Unbound),
1488 FakeUdpSocket {
1489 src_port: None, dst_port: Some(12345), state: UdpSocketState::Bound
1490 } => true;
1491 "src_port unbound match"
1492 )]
1493 #[test_case(
1494 UdpSocketMatcher::SrcPort(BoundPortMatcher::Unbound),
1495 FakeUdpSocket {
1496 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1497 } => false;
1498 "src_port unbound no match"
1499 )]
1500 #[test_case(
1501 UdpSocketMatcher::DstPort(BoundPortMatcher::Unbound),
1502 FakeUdpSocket { src_port: Some(53), dst_port: None, state: UdpSocketState::Bound } => true;
1503 "dst_port unbound match"
1504 )]
1505 #[test_case(
1506 UdpSocketMatcher::DstPort(BoundPortMatcher::Unbound),
1507 FakeUdpSocket {
1508 src_port: Some(53), dst_port: Some(12345), state: UdpSocketState::Bound
1509 } => false;
1510 "dst_port unbound no match"
1511 )]
1512 fn udp_socket_matcher(matcher: UdpSocketMatcher, socket: FakeUdpSocket) -> bool {
1513 matcher.matches(&socket)
1514 }
1515
1516 #[ip_test(I)]
1517 #[test_case(
1518 IpSocketMatcher::Proto(SocketTransportProtocolMatcher::Tcp(TcpSocketMatcher::Empty)),
1519 FakeIpSocket {
1520 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1521 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1522 proto: FakeTcpSocket {
1523 src_port: Some(80),
1524 dst_port: Some(12345),
1525 state: TcpSocketState::Established,
1526 },
1527 cookie: 0,
1528 intf: None,
1529 marks: Marks::default(),
1530 } => true;
1531 "tcpm empty"
1532 )]
1533 #[test_case(
1534 IpSocketMatcher::Proto(SocketTransportProtocolMatcher::Tcp(TcpSocketMatcher::Empty)),
1535 FakeIpSocket {
1536 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1537 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1538 proto: FakeUdpSocket {
1539 src_port: Some(53),
1540 dst_port: Some(12345),
1541 state: UdpSocketState::Bound,
1542 },
1543 cookie: 0,
1544 intf: None,
1545 marks: Marks::default(),
1546 } => false;
1547 "tcp empty no match udp"
1548 )]
1549 #[test_case(
1550 IpSocketMatcher::Proto(SocketTransportProtocolMatcher::Udp(UdpSocketMatcher::Empty)),
1551 FakeIpSocket {
1552 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1553 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1554 proto: FakeTcpSocket {
1555 src_port: Some(80),
1556 dst_port: Some(12345),
1557 state: TcpSocketState::Established
1558 },
1559 cookie: 0,
1560 intf: None,
1561 marks: Marks::default(),
1562 } => false;
1563 "udp empty no match tcp"
1564 )]
1565 #[test_case(
1566 IpSocketMatcher::Proto(SocketTransportProtocolMatcher::Udp(UdpSocketMatcher::Empty)),
1567 FakeIpSocket {
1568 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1569 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1570 proto: FakeUdpSocket {
1571 src_port: Some(53),
1572 dst_port: Some(12345),
1573 state: UdpSocketState::Bound,
1574 },
1575 cookie: 0,
1576 intf: None,
1577 marks: Marks::default(),
1578 } => true;
1579 "udp empty"
1580 )]
1581 #[test_case(
1582 IpSocketMatcher::Proto(
1583 SocketTransportProtocolMatcher::Tcp(
1584 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1585 PortMatcher { range: 80..=80, invert: false }
1586 ))
1587 )
1588 ),
1589 FakeIpSocket {
1590 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1591 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1592 proto: FakeTcpSocket {
1593 src_port: Some(80),
1594 dst_port: Some(12345),
1595 state: TcpSocketState::Established,
1596 },
1597 cookie: 0,
1598 intf: None,
1599 marks: Marks::default(),
1600 } => true;
1601 "tcp src_port match"
1602 )]
1603 #[test_case(
1604 IpSocketMatcher::Proto(
1605 SocketTransportProtocolMatcher::Tcp(
1606 TcpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1607 PortMatcher { range: 80..=80, invert: false }
1608 ))
1609 )
1610 ),
1611 FakeIpSocket {
1612 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1613 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1614 proto: FakeTcpSocket {
1615 src_port: Some(81),
1616 dst_port: Some(12345),
1617 state: TcpSocketState::Established,
1618 },
1619 cookie: 0,
1620 intf: None,
1621 marks: Marks::default(),
1622 } => false;
1623 "tcp src_port no match"
1624 )]
1625 #[test_case(
1626 IpSocketMatcher::Proto(
1627 SocketTransportProtocolMatcher::Udp(
1628 UdpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1629 PortMatcher { range: 53..=53, invert: false }
1630 ))
1631 )
1632 ),
1633 FakeIpSocket {
1634 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1635 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1636 proto: FakeUdpSocket {
1637 src_port: Some(53),
1638 dst_port: Some(12345),
1639 state: UdpSocketState::Bound,
1640 },
1641 cookie: 0,
1642 intf: None,
1643 marks: Marks::default(),
1644 } => true;
1645 "udp src_port match"
1646 )]
1647 #[test_case(
1648 IpSocketMatcher::Proto(
1649 SocketTransportProtocolMatcher::Udp(
1650 UdpSocketMatcher::SrcPort(BoundPortMatcher::Bound(
1651 PortMatcher { range: 53..=53, invert: false }
1652 ))
1653 )
1654 ),
1655 FakeIpSocket {
1656 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1657 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1658 proto: FakeUdpSocket {
1659 src_port: Some(54),
1660 dst_port: Some(12345),
1661 state: UdpSocketState::Bound,
1662 },
1663 cookie: 0,
1664 intf: None,
1665 marks: Marks::default(),
1666 } => false;
1667 "udp src_port no match"
1668 )]
1669 #[test_case(
1670 IpSocketMatcher::Cookie(SocketCookieMatcher { cookie: 123, invert: false }),
1671 FakeIpSocket {
1672 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1673 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1674 proto: FakeTcpSocket {
1675 src_port: Some(80),
1676 dst_port: Some(12345),
1677 state: TcpSocketState::Established,
1678 },
1679 cookie: 123,
1680 intf: None,
1681 marks: Marks::default(),
1682 } => true;
1683 "cookie match"
1684 )]
1685 #[test_case(
1686 IpSocketMatcher::Cookie(SocketCookieMatcher { cookie: 123, invert: false }),
1687 FakeIpSocket {
1688 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1689 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1690 proto: FakeTcpSocket {
1691 src_port: Some(80),
1692 dst_port: Some(12345),
1693 state: TcpSocketState::Established,
1694 },
1695 cookie: 456,
1696 intf: None,
1697 marks: Marks::default(),
1698 } => false;
1699 "cookie no match"
1700 )]
1701 #[test_case(
1702 IpSocketMatcher::Mark(MarkInDomainMatcher {
1703 domain: MarkDomain::Mark1,
1704 matcher: MarkMatcher::Unmarked,
1705 }),
1706 FakeIpSocket {
1707 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1708 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1709 proto: FakeTcpSocket {
1710 src_port: Some(80),
1711 dst_port: Some(12345),
1712 state: TcpSocketState::Established,
1713 },
1714 cookie: 0,
1715 intf: None,
1716 marks: Marks::default(),
1717 } => true;
1718 "mark1 unmarked match"
1719 )]
1720 #[test_case(
1721 IpSocketMatcher::Mark(MarkInDomainMatcher {
1722 domain: MarkDomain::Mark1,
1723 matcher: MarkMatcher::Unmarked,
1724 }),
1725 FakeIpSocket {
1726 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1727 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1728 proto: FakeTcpSocket {
1729 src_port: Some(80),
1730 dst_port: Some(12345),
1731 state: TcpSocketState::Established,
1732 },
1733 cookie: 0,
1734 intf: None,
1735 marks: Marks::new([(MarkDomain::Mark1, 1)]),
1736 } => false;
1737 "mark1 unmarked no match"
1738 )]
1739 #[test_case(
1740 IpSocketMatcher::Mark(MarkInDomainMatcher {
1741 domain: MarkDomain::Mark2,
1742 matcher: MarkMatcher::Unmarked,
1743 }),
1744 FakeIpSocket {
1745 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1746 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1747 proto: FakeTcpSocket {
1748 src_port: Some(80),
1749 dst_port: Some(12345),
1750 state: TcpSocketState::Established,
1751 },
1752 cookie: 0,
1753 intf: None,
1754 marks: Marks::default(),
1755 } => true;
1756 "mark2 unmarked match"
1757 )]
1758 #[test_case(
1759 IpSocketMatcher::Mark(MarkInDomainMatcher {
1760 domain: MarkDomain::Mark2,
1761 matcher: MarkMatcher::Unmarked,
1762 }),
1763 FakeIpSocket {
1764 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1765 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1766 proto: FakeTcpSocket {
1767 src_port: Some(80),
1768 dst_port: Some(12345),
1769 state: TcpSocketState::Established,
1770 },
1771 cookie: 0,
1772 intf: None,
1773 marks: Marks::new([(MarkDomain::Mark2, 1)]),
1774 } => false;
1775 "mark2 unmarked no match"
1776 )]
1777 #[test_case(
1778 IpSocketMatcher::BoundInterface(BoundInterfaceMatcher::Bound(
1779 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
1780 )),
1781 FakeIpSocket {
1782 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1783 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1784 proto: FakeTcpSocket {
1785 src_port: Some(80),
1786 dst_port: Some(12345),
1787 state: TcpSocketState::Established,
1788 },
1789 cookie: 0,
1790 intf: Some(FakeMatcherDeviceId::wlan_interface()),
1791 marks: Marks::default(),
1792 } => true;
1793 "bound_interface match"
1794 )]
1795 #[test_case(
1796 IpSocketMatcher::BoundInterface(BoundInterfaceMatcher::Bound(
1797 InterfaceMatcher::Id(FakeMatcherDeviceId::wlan_interface().id)
1798 )),
1799 FakeIpSocket {
1800 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1801 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1802 proto: FakeTcpSocket {
1803 src_port: Some(80),
1804 dst_port: Some(12345),
1805 state: TcpSocketState::Established,
1806 },
1807 cookie: 0,
1808 intf: Some(FakeMatcherDeviceId::ethernet_interface()),
1809 marks: Marks::default(),
1810 } => false;
1811 "bound_interface no match"
1812 )]
1813 #[test_case(
1814 IpSocketMatcher::BoundInterface(BoundInterfaceMatcher::Unbound),
1815 FakeIpSocket {
1816 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1817 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1818 proto: FakeTcpSocket {
1819 src_port: Some(80),
1820 dst_port: Some(12345),
1821 state: TcpSocketState::Established,
1822 },
1823 cookie: 0,
1824 intf: None,
1825 marks: Marks::default(),
1826 } => true;
1827 "bound_interface unbound match"
1828 )]
1829 #[test_case(
1830 IpSocketMatcher::BoundInterface(BoundInterfaceMatcher::Unbound),
1831 FakeIpSocket {
1832 src_ip: Some(<I as TestIpExt>::TEST_ADDRS.local_ip.get()),
1833 dst_ip: Some(<I as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1834 proto: FakeTcpSocket {
1835 src_port: Some(80),
1836 dst_port: Some(12345),
1837 state: TcpSocketState::Established,
1838 },
1839 cookie: 0,
1840 intf: Some(FakeMatcherDeviceId::wlan_interface()),
1841 marks: Marks::default(),
1842 } => false;
1843 "bound_interface unbound no match"
1844 )]
1845 fn ip_socket_matcher<I: TestIpExt, T: MaybeSocketTransportProperties>(
1846 matcher: IpSocketMatcher<FakeDeviceClass>,
1847 socket: FakeIpSocket<I, T>,
1848 ) -> bool {
1849 matcher.matches(&socket)
1850 }
1851
1852 #[ip_test(I)]
1853 fn address_matcher_type<I: TestIpExt>() {
1854 let local_ip = I::TEST_ADDRS.local_ip.get();
1855 let remote_ip = I::TEST_ADDRS.remote_ip.get();
1856
1857 let matcher = AddressMatcherType::Subnet(SubnetMatcher(I::TEST_ADDRS.subnet));
1858 assert!(matcher.matches(&local_ip));
1859 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
1860
1861 let matcher = AddressMatcherType::Range(local_ip..=remote_ip);
1862 assert!(matcher.matches(&local_ip));
1863 assert!(matcher.matches(&remote_ip));
1864 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
1865 }
1866
1867 #[ip_test(I)]
1868 fn address_matcher<I: TestIpExt>() {
1869 let local_ip = I::TEST_ADDRS.local_ip.get();
1870 let remote_ip = I::TEST_ADDRS.remote_ip.get();
1871
1872 let matcher = AddressMatcher {
1873 matcher: AddressMatcherType::Subnet(SubnetMatcher(I::TEST_ADDRS.subnet)),
1874 invert: false,
1875 };
1876 assert!(matcher.matches(&local_ip));
1877 assert!(matcher.matches(&remote_ip));
1878 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
1879
1880 let matcher = AddressMatcher {
1881 matcher: AddressMatcherType::Subnet(SubnetMatcher(I::TEST_ADDRS.subnet)),
1882 invert: true,
1883 };
1884 assert!(!matcher.matches(&local_ip));
1885 assert!(!matcher.matches(&remote_ip));
1886 assert!(matcher.matches(&I::get_other_remote_ip_address(1)));
1887
1888 let matcher = AddressMatcher {
1889 matcher: AddressMatcherType::Range(local_ip..=remote_ip),
1890 invert: false,
1891 };
1892 assert!(matcher.matches(&local_ip));
1893 assert!(matcher.matches(&remote_ip));
1894 assert!(!matcher.matches(&I::get_other_remote_ip_address(1)));
1895
1896 let matcher = AddressMatcher {
1897 matcher: AddressMatcherType::Range(local_ip..=remote_ip),
1898 invert: true,
1899 };
1900 assert!(!matcher.matches(&local_ip));
1901 assert!(!matcher.matches(&remote_ip));
1902 assert!(matcher.matches(&I::get_other_remote_ip_address(1)));
1903 }
1904
1905 #[test]
1906 fn agnostic_address_matcher() {
1907 let v4_addr = IpAddr::V4(Ipv4Addr::new([192, 0, 2, 1]));
1908 let v6_addr = IpAddr::V6(Ipv6Addr::new([0x2001, 0xdb8, 0, 0, 0, 0, 0, 1]));
1909
1910 let v4_subnet = Subnet::new(Ipv4Addr::new([192, 0, 2, 0]), 24).unwrap();
1911 let v6_subnet = Subnet::new(Ipv6Addr::new([0x2001, 0xdb8, 0, 0, 0, 0, 0, 0]), 32).unwrap();
1912
1913 let v4_matcher =
1914 BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(AddressMatcher {
1915 matcher: AddressMatcherType::Subnet(SubnetMatcher(v4_subnet)),
1916 invert: false,
1917 }));
1918 assert!(v4_matcher.matches(&Some(v4_addr)));
1919 assert!(!v4_matcher.matches(&Some(v6_addr)));
1920
1921 let v6_matcher =
1922 BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(AddressMatcher {
1923 matcher: AddressMatcherType::Subnet(SubnetMatcher(v6_subnet)),
1924 invert: false,
1925 }));
1926 assert!(!v6_matcher.matches(&Some(v4_addr)));
1927 assert!(v6_matcher.matches(&Some(v6_addr)));
1928 }
1929
1930 #[test_case(IpSocketMatcher::Family(IpVersion::V4) => true; "v4 family matcher on v4 socket")]
1931 #[test_case(IpSocketMatcher::Family(IpVersion::V6) => false; "v6 family matcher on v4 socket")]
1932 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
1933 AddressMatcher {
1934 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv4::TEST_ADDRS.subnet)),
1935 invert: false,
1936 }
1937 ))) => true; "src_addr match")]
1938 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
1939 AddressMatcher {
1940 matcher: AddressMatcherType::Subnet(SubnetMatcher(
1941 Subnet::new(Ipv4Addr::new([0, 0, 0, 0]), 32).unwrap()
1942 )),
1943 invert: false,
1944 }
1945 ))) => false; "src_addr no match")]
1946 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
1947 AddressMatcher {
1948 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv4::TEST_ADDRS.subnet)),
1949 invert: false,
1950 }
1951 ))) => true; "dst_addr match")]
1952 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
1953 AddressMatcher {
1954 matcher: AddressMatcherType::Subnet(SubnetMatcher(
1955 Subnet::new(Ipv4Addr::new([0, 0, 0, 0]), 32).unwrap()
1956 )),
1957 invert: false,
1958 }))) => false; "dst_addr no match")]
1959 #[test_case(
1960 IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Unbound) => false;
1961 "src_addr unbound mismatch"
1962 )]
1963 #[test_case(
1964 IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Unbound) => false;
1965 "dst_addr unbound mismatch"
1966 )]
1967 fn ip_socket_matcher_test_v4(matcher: IpSocketMatcher<FakeDeviceClass>) -> bool {
1968 let socket = FakeIpSocket::<Ipv4, _> {
1969 src_ip: Some(<Ipv4 as TestIpExt>::TEST_ADDRS.local_ip.get()),
1970 dst_ip: Some(<Ipv4 as TestIpExt>::TEST_ADDRS.remote_ip.get()),
1971 proto: FakeTcpSocket {
1972 src_port: Some(80),
1973 dst_port: Some(12345),
1974 state: TcpSocketState::Established,
1975 },
1976 cookie: 0,
1977 intf: None,
1978 marks: Marks::default(),
1979 };
1980 matcher.matches(&socket)
1981 }
1982
1983 #[test_case(IpSocketMatcher::Family(IpVersion::V4) => false; "v4 family matcher on v6 socket")]
1984 #[test_case(IpSocketMatcher::Family(IpVersion::V6) => true; "v6 family matcher on v6 socket")]
1985 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(
1986 AddressMatcher {
1987 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv6::TEST_ADDRS.subnet)),
1988 invert: false,
1989 }
1990 ))) => true; "src_addr match v6")]
1991 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(
1992 AddressMatcher {
1993 matcher: AddressMatcherType::Subnet(SubnetMatcher(
1994 Subnet::new(Ipv6Addr::new([0; 8]), 128).unwrap()
1995 )),
1996 invert: false,
1997 }
1998 ))) => false; "src_addr no match v6")]
1999 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(
2000 AddressMatcher {
2001 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv6::TEST_ADDRS.subnet)),
2002 invert: false,
2003 }
2004 ))) => true; "dst_addr match v6")]
2005 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V6(
2006 AddressMatcher {
2007 matcher: AddressMatcherType::Subnet(SubnetMatcher(
2008 Subnet::new(Ipv6Addr::new([0; 8]), 128).unwrap()
2009 )),
2010 invert: false,
2011 }
2012 ))) => false; "dst_addr no match v6")]
2013 fn ip_socket_matcher_test_v6(matcher: IpSocketMatcher<FakeDeviceClass>) -> bool {
2014 let socket = FakeIpSocket::<Ipv6, _> {
2015 src_ip: Some(<Ipv6 as TestIpExt>::TEST_ADDRS.local_ip.get()),
2016 dst_ip: Some(<Ipv6 as TestIpExt>::TEST_ADDRS.remote_ip.get()),
2017 proto: FakeTcpSocket {
2018 src_port: Some(80),
2019 dst_port: Some(12345),
2020 state: TcpSocketState::Established,
2021 },
2022 cookie: 0,
2023 intf: None,
2024 marks: Marks::default(),
2025 };
2026 matcher.matches(&socket)
2027 }
2028
2029 #[test_case(
2030 IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Unbound) => true;
2031 "src_addr unbound match"
2032 )]
2033 #[test_case(IpSocketMatcher::SrcAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
2034 AddressMatcher {
2035 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv4::TEST_ADDRS.subnet)),
2036 invert: false,
2037 }
2038 ))) => false; "src_addr bound mismatch")]
2039 #[test_case(
2040 IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Unbound) => true;
2041 "dst_addr unbound match"
2042 )]
2043 #[test_case(IpSocketMatcher::DstAddr(BoundAddressMatcherEither::Bound(AddressMatcherEither::V4(
2044 AddressMatcher {
2045 matcher: AddressMatcherType::Subnet(SubnetMatcher(Ipv4::TEST_ADDRS.subnet)),
2046 invert: false,
2047 }
2048 ))) => false; "dst_addr bound mismatch")]
2049
2050 fn ip_socket_matcher_unbound(matcher: IpSocketMatcher<FakeDeviceClass>) -> bool {
2051 let socket = FakeIpSocket::<Ipv4, _> {
2052 src_ip: None,
2053 dst_ip: None,
2054 proto: FakeTcpSocket {
2055 src_port: Some(80),
2056 dst_port: Some(12345),
2057 state: TcpSocketState::Established,
2058 },
2059 cookie: 0,
2060 intf: None,
2061 marks: Marks::default(),
2062 };
2063 matcher.matches(&socket)
2064 }
2065}