1use std::fmt::Debug;
15use std::num::NonZeroU64;
16use std::ops::RangeInclusive;
17
18use fidl::marker::SourceBreaking;
19use fidl_fuchsia_net_ext::{FromExt, IntoExt};
20use thiserror::Error;
21use {
22 fidl_fuchsia_net as fnet, fidl_fuchsia_net_interfaces as fnet_interfaces,
23 fidl_fuchsia_net_interfaces_ext as fnet_interfaces_ext,
24 fidl_fuchsia_net_matchers as fnet_matchers,
25};
26
27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29pub enum Interface {
30 Id(NonZeroU64),
31 Name(fnet_interfaces::Name),
32 PortClass(fnet_interfaces_ext::PortClass),
33}
34
35#[derive(Debug, Error, PartialEq, Eq)]
37pub enum InterfaceError {
38 #[error("interface matcher specified an invalid ID of 0")]
39 ZeroId,
40 #[error(transparent)]
41 UnknownPortClass(fnet_interfaces_ext::UnknownPortClassError),
42 #[error("interface union is of an unknown variant")]
43 UnknownUnionVariant,
44}
45
46impl From<Interface> for fnet_matchers::Interface {
47 fn from(matcher: Interface) -> Self {
48 match matcher {
49 Interface::Id(id) => Self::Id(id.get()),
50 Interface::Name(name) => Self::Name(name),
51 Interface::PortClass(port_class) => Self::PortClass(port_class.into()),
52 }
53 }
54}
55
56impl TryFrom<fnet_matchers::Interface> for Interface {
57 type Error = InterfaceError;
58
59 fn try_from(matcher: fnet_matchers::Interface) -> Result<Self, Self::Error> {
60 match matcher {
61 fnet_matchers::Interface::Id(id) => {
62 let id = NonZeroU64::new(id).ok_or(InterfaceError::ZeroId)?;
63 Ok(Self::Id(id))
64 }
65 fnet_matchers::Interface::Name(name) => Ok(Self::Name(name)),
66 fnet_matchers::Interface::PortClass(port_class) => {
67 port_class.try_into().map(Self::PortClass).map_err(InterfaceError::UnknownPortClass)
68 }
69 fnet_matchers::Interface::__SourceBreaking { .. } => {
70 Err(InterfaceError::UnknownUnionVariant)
71 }
72 }
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Hash)]
78pub enum BoundInterface {
79 Unbound,
80 Bound(Interface),
81}
82
83#[derive(Debug, Error, PartialEq)]
85pub enum BoundInterfaceError {
86 #[error(transparent)]
87 Interface(InterfaceError),
88 #[error("interface union is of an unknown variant")]
89 UnknownUnionVariant(u64),
90}
91
92impl From<BoundInterface> for fnet_matchers::BoundInterface {
93 fn from(matcher: BoundInterface) -> Self {
94 match matcher {
95 BoundInterface::Unbound => {
96 fnet_matchers::BoundInterface::Unbound(fnet_matchers::Unbound)
97 }
98 BoundInterface::Bound(interface) => {
99 fnet_matchers::BoundInterface::Bound(interface.into())
100 }
101 }
102 }
103}
104
105impl TryFrom<fnet_matchers::BoundInterface> for BoundInterface {
106 type Error = BoundInterfaceError;
107
108 fn try_from(matcher: fnet_matchers::BoundInterface) -> Result<Self, Self::Error> {
109 match matcher {
110 fnet_matchers::BoundInterface::Unbound(fnet_matchers::Unbound) => {
111 Ok(BoundInterface::Unbound)
112 }
113 fnet_matchers::BoundInterface::Bound(interface) => Ok(BoundInterface::Bound(
114 interface.try_into().map_err(|e| BoundInterfaceError::Interface(e))?,
115 )),
116 fnet_matchers::BoundInterface::__SourceBreaking { unknown_ordinal } => {
117 Err(BoundInterfaceError::UnknownUnionVariant(unknown_ordinal))
118 }
119 }
120 }
121}
122
123#[derive(Clone, Copy, Eq, Hash, PartialEq)]
129pub struct Subnet(net_types::ip::SubnetEither);
130
131#[derive(Debug, Error, PartialEq)]
133pub enum SubnetError {
134 #[error("prefix length of subnet is longer than number of bits in IP address")]
135 PrefixTooLong,
136 #[error("host bits are set in subnet network")]
137 HostBitsSet,
138}
139
140impl From<Subnet> for net_types::ip::SubnetEither {
141 fn from(subnet: Subnet) -> Self {
142 let Subnet(subnet) = subnet;
143 subnet
144 }
145}
146
147impl From<Subnet> for fnet::Subnet {
148 fn from(subnet: Subnet) -> Self {
149 let Subnet(subnet) = subnet;
150 let (addr, prefix_len) = subnet.net_prefix();
151
152 Self { addr: fnet::IpAddress::from_ext(addr), prefix_len }
153 }
154}
155
156impl TryFrom<fnet::Subnet> for Subnet {
157 type Error = SubnetError;
158
159 fn try_from(subnet: fnet::Subnet) -> Result<Self, Self::Error> {
160 let fnet::Subnet { addr, prefix_len } = subnet;
161
162 match net_types::ip::SubnetEither::new(addr.into_ext(), prefix_len) {
163 Ok(inner) => Ok(Self(inner)),
164 Err(err) => Err(match err {
165 net_types::ip::SubnetError::PrefixTooLong => SubnetError::PrefixTooLong,
166 net_types::ip::SubnetError::HostBitsSet => SubnetError::HostBitsSet,
167 }),
168 }
169 }
170}
171
172impl Debug for Subnet {
173 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174 let Self(subnet) = self;
175 match subnet {
176 net_types::ip::SubnetEither::V4(subnet) => subnet.fmt(f),
177 net_types::ip::SubnetEither::V6(subnet) => subnet.fmt(f),
178 }
179 }
180}
181
182#[derive(Debug, Clone, PartialEq, Eq)]
187pub enum AddressRange {
188 V4(RangeInclusive<fnet::Ipv4Address>),
189 V6(RangeInclusive<fnet::Ipv6Address>),
190}
191
192#[derive(Debug, Error, PartialEq)]
194pub enum AddressRangeError {
195 #[error("invalid address range (start must be <= end)")]
196 Invalid,
197 #[error("address range start and end addresses are not the same IP family")]
198 FamilyMismatch,
199}
200
201impl From<AddressRange> for fnet_matchers::AddressRange {
202 fn from(range: AddressRange) -> Self {
203 let (start, end) = match range {
204 AddressRange::V4(range) => ((*range.start()).into_ext(), (*range.end()).into_ext()),
205 AddressRange::V6(range) => ((*range.start()).into_ext(), (*range.end()).into_ext()),
206 };
207
208 Self { start, end }
209 }
210}
211
212impl TryFrom<fnet_matchers::AddressRange> for AddressRange {
213 type Error = AddressRangeError;
214
215 fn try_from(range: fnet_matchers::AddressRange) -> Result<Self, Self::Error> {
216 let fnet_matchers::AddressRange { start, end } = range;
217 match (start, end) {
218 (fnet::IpAddress::Ipv4(start), fnet::IpAddress::Ipv4(end)) => {
219 if u32::from_be_bytes(start.addr) > u32::from_be_bytes(end.addr) {
220 Err(AddressRangeError::Invalid)
221 } else {
222 Ok(Self::V4(start..=end))
223 }
224 }
225 (fnet::IpAddress::Ipv6(start), fnet::IpAddress::Ipv6(end)) => {
226 if u128::from_be_bytes(start.addr) > u128::from_be_bytes(end.addr) {
227 Err(AddressRangeError::Invalid)
228 } else {
229 Ok(Self::V6(start..=end))
230 }
231 }
232 _ => Err(AddressRangeError::FamilyMismatch),
233 }
234 }
235}
236
237#[derive(Clone, PartialEq, Eq)]
239pub enum AddressMatcherType {
240 Subnet(Subnet),
241 Range(AddressRange),
242}
243
244#[derive(Debug, Error, PartialEq)]
246pub enum AddressMatcherTypeError {
247 #[error("AddressMatcher is of an unknown variant")]
248 UnknownUnionVariant,
249 #[error("subnet conversion error: {0}")]
250 Subnet(SubnetError),
251 #[error("address range conversion error: {0}")]
252 AddressRange(AddressRangeError),
253}
254
255impl From<SubnetError> for AddressMatcherTypeError {
256 fn from(value: SubnetError) -> Self {
257 AddressMatcherTypeError::Subnet(value)
258 }
259}
260impl From<AddressRangeError> for AddressMatcherTypeError {
261 fn from(value: AddressRangeError) -> Self {
262 AddressMatcherTypeError::AddressRange(value)
263 }
264}
265
266impl From<AddressMatcherType> for fnet_matchers::AddressMatcherType {
267 fn from(matcher: AddressMatcherType) -> Self {
268 match matcher {
269 AddressMatcherType::Subnet(subnet) => Self::Subnet(subnet.into()),
270 AddressMatcherType::Range(range) => Self::Range(range.into()),
271 }
272 }
273}
274
275impl TryFrom<fnet_matchers::AddressMatcherType> for AddressMatcherType {
276 type Error = AddressMatcherTypeError;
277
278 fn try_from(matcher: fnet_matchers::AddressMatcherType) -> Result<Self, Self::Error> {
279 match matcher {
280 fnet_matchers::AddressMatcherType::Subnet(subnet) => {
281 Ok(Self::Subnet(subnet.try_into()?))
282 }
283 fnet_matchers::AddressMatcherType::Range(range) => Ok(Self::Range(range.try_into()?)),
284 fnet_matchers::AddressMatcherType::__SourceBreaking { .. } => {
285 Err(AddressMatcherTypeError::UnknownUnionVariant)
286 }
287 }
288 }
289}
290
291impl Debug for AddressMatcherType {
292 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
293 match self {
294 AddressMatcherType::Subnet(subnet) => subnet.fmt(f),
295 AddressMatcherType::Range(address_range) => address_range.fmt(f),
296 }
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, Eq)]
302pub struct Address {
303 pub matcher: AddressMatcherType,
304 pub invert: bool,
305}
306
307#[derive(Debug, Error, PartialEq)]
309pub enum AddressError {
310 #[error("address matcher conversion failure: {0}")]
311 AddressMatcherType(AddressMatcherTypeError),
312}
313
314impl From<AddressMatcherTypeError> for AddressError {
315 fn from(value: AddressMatcherTypeError) -> Self {
316 Self::AddressMatcherType(value)
317 }
318}
319
320impl From<Address> for fnet_matchers::Address {
321 fn from(matcher: Address) -> Self {
322 let Address { matcher, invert } = matcher;
323 Self { matcher: matcher.into(), invert }
324 }
325}
326
327impl TryFrom<fnet_matchers::Address> for Address {
328 type Error = AddressError;
329
330 fn try_from(matcher: fnet_matchers::Address) -> Result<Self, Self::Error> {
331 let fnet_matchers::Address { matcher, invert } = matcher;
332 Ok(Self { matcher: matcher.try_into()?, invert })
333 }
334}
335
336#[derive(Debug, Clone, PartialEq, Eq)]
340pub struct Port {
341 range: RangeInclusive<u16>,
342 invert: bool,
343}
344
345#[derive(Debug, Error, PartialEq, Eq)]
347pub enum PortError {
348 #[error("invalid port range (start must be <= end)")]
349 InvalidPortRange,
350}
351
352impl Port {
353 pub fn new(start: u16, end: u16, invert: bool) -> Result<Self, PortError> {
354 if start > end {
355 return Err(PortError::InvalidPortRange);
356 }
357 Ok(Self { range: start..=end, invert })
358 }
359
360 pub fn range(&self) -> &RangeInclusive<u16> {
361 &self.range
362 }
363
364 pub fn start(&self) -> u16 {
365 *self.range.start()
366 }
367
368 pub fn end(&self) -> u16 {
369 *self.range.end()
370 }
371
372 pub fn invert(&self) -> bool {
373 self.invert
374 }
375}
376
377impl From<Port> for fnet_matchers::Port {
378 fn from(matcher: Port) -> Self {
379 let Port { range, invert } = matcher;
380 Self { start: *range.start(), end: *range.end(), invert }
381 }
382}
383
384impl TryFrom<fnet_matchers::Port> for Port {
385 type Error = PortError;
386
387 fn try_from(matcher: fnet_matchers::Port) -> Result<Self, Self::Error> {
388 let fnet_matchers::Port { start, end, invert } = matcher;
389 if start > end {
390 return Err(PortError::InvalidPortRange);
391 }
392 Ok(Self { range: start..=end, invert })
393 }
394}
395
396#[derive(Clone, PartialEq)]
398pub enum TransportProtocol {
399 Tcp { src_port: Option<Port>, dst_port: Option<Port> },
400 Udp { src_port: Option<Port>, dst_port: Option<Port> },
401 Icmp,
402 Icmpv6,
403}
404
405#[derive(Debug, Error, PartialEq)]
407pub enum TransportProtocolError {
408 #[error("invalid port: {0}")]
409 Port(PortError),
410 #[error("TransportProtocol is of an unknown variant")]
411 UnknownUnionVariant,
412}
413
414impl From<PortError> for TransportProtocolError {
415 fn from(value: PortError) -> Self {
416 TransportProtocolError::Port(value)
417 }
418}
419
420impl From<TransportProtocol> for fnet_matchers::PacketTransportProtocol {
421 fn from(matcher: TransportProtocol) -> Self {
422 match matcher {
423 TransportProtocol::Tcp { src_port, dst_port } => Self::Tcp(fnet_matchers::TcpPacket {
424 src_port: src_port.map(Into::into),
425 dst_port: dst_port.map(Into::into),
426 __source_breaking: SourceBreaking,
427 }),
428 TransportProtocol::Udp { src_port, dst_port } => Self::Udp(fnet_matchers::UdpPacket {
429 src_port: src_port.map(Into::into),
430 dst_port: dst_port.map(Into::into),
431 __source_breaking: SourceBreaking,
432 }),
433 TransportProtocol::Icmp => Self::Icmp(fnet_matchers::IcmpPacket::default()),
434 TransportProtocol::Icmpv6 => Self::Icmpv6(fnet_matchers::Icmpv6Packet::default()),
435 }
436 }
437}
438
439impl TryFrom<fnet_matchers::PacketTransportProtocol> for TransportProtocol {
440 type Error = TransportProtocolError;
441
442 fn try_from(matcher: fnet_matchers::PacketTransportProtocol) -> Result<Self, Self::Error> {
443 match matcher {
444 fnet_matchers::PacketTransportProtocol::Tcp(fnet_matchers::TcpPacket {
445 src_port,
446 dst_port,
447 __source_breaking,
448 }) => Ok(Self::Tcp {
449 src_port: src_port.map(TryInto::try_into).transpose()?,
450 dst_port: dst_port.map(TryInto::try_into).transpose()?,
451 }),
452 fnet_matchers::PacketTransportProtocol::Udp(fnet_matchers::UdpPacket {
453 src_port,
454 dst_port,
455 __source_breaking,
456 }) => Ok(Self::Udp {
457 src_port: src_port.map(TryInto::try_into).transpose()?,
458 dst_port: dst_port.map(TryInto::try_into).transpose()?,
459 }),
460 fnet_matchers::PacketTransportProtocol::Icmp(fnet_matchers::IcmpPacket {
461 __source_breaking,
462 }) => Ok(Self::Icmp),
463 fnet_matchers::PacketTransportProtocol::Icmpv6(fnet_matchers::Icmpv6Packet {
464 __source_breaking,
465 }) => Ok(Self::Icmpv6),
466 fnet_matchers::PacketTransportProtocol::__SourceBreaking { .. } => {
467 Err(TransportProtocolError::UnknownUnionVariant)
468 }
469 }
470 }
471}
472
473impl Debug for TransportProtocol {
474 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
475 match self {
477 TransportProtocol::Tcp { src_port, dst_port } => {
478 let mut debug_struct = f.debug_struct("Tcp");
479
480 if let Some(port) = &src_port {
482 let _ = debug_struct.field("src_port", port);
483 }
484
485 if let Some(port) = &dst_port {
486 let _ = debug_struct.field("dst_port", port);
487 }
488
489 debug_struct.finish()
490 }
491 TransportProtocol::Udp { src_port, dst_port } => {
492 let mut debug_struct = f.debug_struct("Udp");
493
494 if let Some(port) = &src_port {
496 let _ = debug_struct.field("src_port", port);
497 }
498
499 if let Some(port) = &dst_port {
500 let _ = debug_struct.field("dst_port", port);
501 }
502
503 debug_struct.finish()
504 }
505 TransportProtocol::Icmp => f.write_str("Icmp"),
506 TransportProtocol::Icmpv6 => f.write_str("Icmpv6"),
507 }
508 }
509}
510
511#[derive(Debug, Clone, PartialEq, Eq, Hash)]
513pub enum Mark {
514 Unmarked,
515 Marked { mask: u32, between: RangeInclusive<u32>, invert: bool },
516}
517
518#[derive(Debug, Clone, PartialEq, Error)]
519pub enum MarkError {
520 #[error("mark union is of an unknown variant")]
521 UnknownUnionVariant(u64),
522}
523
524impl TryFrom<fnet_matchers::Mark> for Mark {
525 type Error = MarkError;
526
527 fn try_from(matcher: fnet_matchers::Mark) -> Result<Self, Self::Error> {
528 match matcher {
529 fnet_matchers::Mark::Unmarked(fnet_matchers::Unmarked) => Ok(Mark::Unmarked),
530 fnet_matchers::Mark::Marked(fnet_matchers::Marked {
531 mask,
532 between: fnet_matchers::Between { start, end },
533 invert,
534 }) => Ok(Mark::Marked { mask, between: RangeInclusive::new(start, end), invert }),
535 fnet_matchers::Mark::__SourceBreaking { unknown_ordinal } => {
536 Err(MarkError::UnknownUnionVariant(unknown_ordinal))
537 }
538 }
539 }
540}
541
542impl From<Mark> for fnet_matchers::Mark {
543 fn from(matcher: Mark) -> Self {
544 match matcher {
545 Mark::Unmarked => fnet_matchers::Mark::Unmarked(fnet_matchers::Unmarked),
546 Mark::Marked { mask, between, invert } => {
547 let (start, end) = between.into_inner();
548 fnet_matchers::Mark::Marked(fnet_matchers::Marked {
549 mask,
550 between: fnet_matchers::Between { start, end },
551 invert,
552 })
553 }
554 }
555 }
556}
557
558#[derive(Debug, Clone, PartialEq, Eq, Hash)]
560pub struct MarkInDomain {
561 pub domain: fnet::MarkDomain,
562 pub mark: Mark,
563}
564
565#[derive(Debug, Clone, PartialEq, Error)]
566pub enum MarkInDomainError {
567 #[error("mark conversion failed: {0}")]
568 Mark(MarkError),
569}
570
571impl TryFrom<fnet_matchers::MarkInDomain> for MarkInDomain {
572 type Error = MarkInDomainError;
573
574 fn try_from(matcher: fnet_matchers::MarkInDomain) -> Result<Self, Self::Error> {
575 let fnet_matchers::MarkInDomain { domain, mark } = matcher;
576 Ok(Self { domain, mark: mark.try_into().map_err(MarkInDomainError::Mark)? })
577 }
578}
579
580impl From<MarkInDomain> for fnet_matchers::MarkInDomain {
581 fn from(matcher: MarkInDomain) -> Self {
582 let MarkInDomain { domain, mark } = matcher;
583 Self { domain, mark: mark.into() }
584 }
585}
586
587#[derive(Debug, Clone, PartialEq, Eq)]
589pub enum TcpSocket {
590 Empty,
591 SrcPort(Port),
592 DstPort(Port),
593 States(fnet_matchers::TcpState),
594}
595
596#[derive(Debug, PartialEq, Eq, Error)]
597pub enum TcpSocketError {
598 #[error("port matcher conversion failed: {0}")]
599 Port(PortError),
600 #[error("tcp union is of an unknown variant")]
601 UnknownUnionVariant(u64),
602}
603
604impl TryFrom<fnet_matchers::TcpSocket> for TcpSocket {
605 type Error = TcpSocketError;
606
607 fn try_from(matcher: fnet_matchers::TcpSocket) -> Result<Self, Self::Error> {
608 match matcher {
609 fnet_matchers::TcpSocket::Empty(fnet_matchers::Empty) => Ok(Self::Empty),
610 fnet_matchers::TcpSocket::SrcPort(port) => {
611 Ok(Self::SrcPort(port.try_into().map_err(|e| TcpSocketError::Port(e))?))
612 }
613 fnet_matchers::TcpSocket::DstPort(port) => {
614 Ok(Self::DstPort(port.try_into().map_err(|e| TcpSocketError::Port(e))?))
615 }
616 fnet_matchers::TcpSocket::States(states) => Ok(Self::States(states)),
617 fnet_matchers::TcpSocket::__SourceBreaking { unknown_ordinal } => {
618 Err(TcpSocketError::UnknownUnionVariant(unknown_ordinal))
619 }
620 }
621 }
622}
623
624impl From<TcpSocket> for fnet_matchers::TcpSocket {
625 fn from(matcher: TcpSocket) -> Self {
626 match matcher {
627 TcpSocket::Empty => Self::Empty(fnet_matchers::Empty),
628 TcpSocket::SrcPort(port) => Self::SrcPort(port.into()),
629 TcpSocket::DstPort(port) => Self::DstPort(port.into()),
630 TcpSocket::States(states) => Self::States(states),
631 }
632 }
633}
634
635#[derive(Debug, Clone, PartialEq, Eq)]
637pub enum UdpSocket {
638 Empty,
639 SrcPort(Port),
640 DstPort(Port),
641 States(fnet_matchers::UdpState),
642}
643
644#[derive(Debug, PartialEq, Eq, Error)]
645pub enum UdpSocketError {
646 #[error("port matcher conversion failed: {0}")]
647 Port(PortError),
648 #[error("udp union is of an unknown variant")]
649 UnknownUnionVariant(u64),
650}
651
652impl TryFrom<fnet_matchers::UdpSocket> for UdpSocket {
653 type Error = UdpSocketError;
654
655 fn try_from(matcher: fnet_matchers::UdpSocket) -> Result<Self, Self::Error> {
656 match matcher {
657 fnet_matchers::UdpSocket::Empty(fnet_matchers::Empty) => Ok(Self::Empty),
658 fnet_matchers::UdpSocket::SrcPort(port) => {
659 Ok(Self::SrcPort(port.try_into().map_err(|e| UdpSocketError::Port(e))?))
660 }
661 fnet_matchers::UdpSocket::DstPort(port) => {
662 Ok(Self::DstPort(port.try_into().map_err(|e| UdpSocketError::Port(e))?))
663 }
664 fnet_matchers::UdpSocket::States(states) => Ok(Self::States(states)),
665 fnet_matchers::UdpSocket::__SourceBreaking { unknown_ordinal } => {
666 Err(UdpSocketError::UnknownUnionVariant(unknown_ordinal))
667 }
668 }
669 }
670}
671
672impl From<UdpSocket> for fnet_matchers::UdpSocket {
673 fn from(matcher: UdpSocket) -> Self {
674 match matcher {
675 UdpSocket::Empty => Self::Empty(fnet_matchers::Empty),
676 UdpSocket::SrcPort(port) => Self::SrcPort(port.into()),
677 UdpSocket::DstPort(port) => Self::DstPort(port.into()),
678 UdpSocket::States(states) => Self::States(states),
679 }
680 }
681}
682
683#[derive(Debug, Clone, PartialEq, Eq)]
685pub enum SocketTransportProtocol {
686 Tcp(TcpSocket),
687 Udp(UdpSocket),
688}
689
690#[derive(Debug, PartialEq, Eq, Error)]
691pub enum SocketTransportProtocolError {
692 #[error("invalid tcp matcher: {0}")]
693 Tcp(TcpSocketError),
694 #[error("invalid udp matcher: {0}")]
695 Udp(UdpSocketError),
696 #[error("socket transport protocol union is of an unknown variant")]
697 UnknownUnionVariant(u64),
698}
699
700impl TryFrom<fnet_matchers::SocketTransportProtocol> for SocketTransportProtocol {
701 type Error = SocketTransportProtocolError;
702
703 fn try_from(matcher: fnet_matchers::SocketTransportProtocol) -> Result<Self, Self::Error> {
704 match matcher {
705 fnet_matchers::SocketTransportProtocol::Tcp(tcp) => {
706 Ok(Self::Tcp(tcp.try_into().map_err(|e| SocketTransportProtocolError::Tcp(e))?))
707 }
708 fnet_matchers::SocketTransportProtocol::Udp(udp) => {
709 Ok(Self::Udp(udp.try_into().map_err(|e| SocketTransportProtocolError::Udp(e))?))
710 }
711 fnet_matchers::SocketTransportProtocol::__SourceBreaking { unknown_ordinal } => {
712 Err(SocketTransportProtocolError::UnknownUnionVariant(unknown_ordinal))
713 }
714 }
715 }
716}
717
718impl From<SocketTransportProtocol> for fnet_matchers::SocketTransportProtocol {
719 fn from(matcher: SocketTransportProtocol) -> Self {
720 match matcher {
721 SocketTransportProtocol::Tcp(tcp) => Self::Tcp(tcp.into()),
722 SocketTransportProtocol::Udp(udp) => Self::Udp(udp.into()),
723 }
724 }
725}
726
727#[cfg(test)]
728mod tests {
729 use net_declare::{fidl_ip, fidl_ip_v4, fidl_ip_v6, fidl_subnet, net_subnet_v4, net_subnet_v6};
730 use test_case::test_case;
731
732 use super::*;
733
734 #[test_case(
735 fnet_matchers::Interface::Id(1),
736 Interface::Id(NonZeroU64::new(1).unwrap());
737 "Interface"
738 )]
739 #[test_case(
740 fnet_matchers::BoundInterface::Unbound(fnet_matchers::Unbound),
741 BoundInterface::Unbound;
742 "BoundInterface Unbound"
743 )]
744 #[test_case(
745 fnet_matchers::BoundInterface::Bound(fnet_matchers::Interface::Id(1)),
746 BoundInterface::Bound(Interface::Id(NonZeroU64::new(1).unwrap()));
747 "BoundInterface Bound"
748 )]
749 #[test_case(
750 fnet_matchers::Mark::Unmarked(fnet_matchers::Unmarked),
751 Mark::Unmarked;
752 "Unmarked"
753 )]
754 #[test_case(
755 fnet_matchers::Mark::Marked(fnet_matchers::Marked {
756 mask: 0xFF,
757 between: fnet_matchers::Between { start: 10, end: 20 },
758 invert: true,
759 }),
760 Mark::Marked { mask: 0xFF, between: 10..=20, invert: true };
761 "Marked"
762 )]
763 #[test_case(
764 fnet_matchers::MarkInDomain {
765 domain: fnet::MarkDomain::Mark1,
766 mark: fnet_matchers::Mark::Unmarked(fnet_matchers::Unmarked),
767 },
768 MarkInDomain {
769 domain: fnet::MarkDomain::Mark1,
770 mark: Mark::Unmarked,
771 };
772 "MarkInDomain"
773 )]
774 #[test_case(
775 fnet_matchers::AddressMatcherType::Subnet(fidl_subnet!("192.0.2.0/24")),
776 AddressMatcherType::Subnet(Subnet(net_subnet_v4!("192.0.2.0/24").into()));
777 "AddressMatcherTypeV4"
778 )]
779 #[test_case(
780 fnet_matchers::AddressMatcherType::Subnet(fidl_subnet!("2001:db8::/64")),
781 AddressMatcherType::Subnet(Subnet(net_subnet_v6!("2001:db8::/64").into()));
782 "AddressMatcherTypeV6"
783 )]
784 #[test_case(
785 fnet_matchers::Address {
786 matcher: fnet_matchers::AddressMatcherType::Subnet(fidl_subnet!("2001:db8::/64")),
787 invert: true,
788 },
789 Address {
790 matcher: AddressMatcherType::Subnet(Subnet(net_subnet_v6!("2001:db8::/64").into())),
791 invert: true,
792 };
793 "AddressV6"
794 )]
795 #[test_case(
796 fnet_matchers::AddressRange {
797 start: fidl_ip!("192.0.2.0"),
798 end: fidl_ip!("192.0.2.1"),
799 },
800 AddressRange::V4(
801 fidl_ip_v4!("192.0.2.0")..=fidl_ip_v4!("192.0.2.1"),
802 );
803 "AddressRangeV4"
804 )]
805 #[test_case(
806 fnet_matchers::AddressRange {
807 start: fidl_ip!("2001:db8::0"),
808 end: fidl_ip!("2001:db8::8"),
809 },
810 AddressRange::V6(
811 fidl_ip_v6!("2001:db8::0")..=fidl_ip_v6!("2001:db8::8"),
812 );
813 "AddressRangeV6"
814 )]
815 #[test_case(
816 fnet_matchers::PacketTransportProtocol::Udp(fnet_matchers::UdpPacket {
817 src_port: Some(fnet_matchers::Port { start: 1024, end: u16::MAX, invert: false }),
818 dst_port: None,
819 ..Default::default()
820 }),
821 TransportProtocol::Udp {
822 src_port: Some(Port { range: 1024..=u16::MAX, invert: false }),
823 dst_port: None,
824 };
825 "TransportProtocol"
826 )]
827 #[test_case(
828 fnet_matchers::TcpSocket::Empty(fnet_matchers::Empty),
829 TcpSocket::Empty;
830 "TcpSocketEmpty"
831 )]
832 #[test_case(
833 fnet_matchers::TcpSocket::SrcPort(
834 fnet_matchers::Port { start: 1024, end: u16::MAX, invert: false }
835 ),
836 TcpSocket::SrcPort(Port { range: 1024..=u16::MAX, invert: false });
837 "TcpSocketSrcPort"
838 )]
839 #[test_case(
840 fnet_matchers::TcpSocket::DstPort(
841 fnet_matchers::Port { start: 80, end: 80, invert: true }
842 ),
843 TcpSocket::DstPort(Port { range: 80..=80, invert: true });
844 "TcpSocketDstPort"
845 )]
846 #[test_case(
847 fnet_matchers::TcpSocket::States(fnet_matchers::TcpState::ESTABLISHED),
848 TcpSocket::States(fnet_matchers::TcpState::ESTABLISHED);
849 "TcpSocketStates"
850 )]
851 #[test_case(
852 fnet_matchers::UdpSocket::Empty(fnet_matchers::Empty),
853 UdpSocket::Empty;
854 "UdpSocketEmpty"
855 )]
856 #[test_case(
857 fnet_matchers::UdpSocket::SrcPort(
858 fnet_matchers::Port { start: 1024, end: u16::MAX, invert: false }
859 ),
860 UdpSocket::SrcPort(Port { range: 1024..=u16::MAX, invert: false });
861 "UdpSocketSrcPort"
862 )]
863 #[test_case(
864 fnet_matchers::UdpSocket::DstPort(
865 fnet_matchers::Port { start: 53, end: 53, invert: true }
866 ),
867 UdpSocket::DstPort(Port { range: 53..=53, invert: true });
868 "UdpSocketDstPort"
869 )]
870 #[test_case(
871 fnet_matchers::UdpSocket::States(fnet_matchers::UdpState::BOUND),
872 UdpSocket::States(fnet_matchers::UdpState::BOUND);
873 "UdpSocketStates"
874 )]
875 #[test_case(
876 fnet_matchers::SocketTransportProtocol::Tcp(
877 fnet_matchers::TcpSocket::SrcPort(
878 fnet_matchers::Port { start: 123, end: 123, invert: false }
879 )
880 ),
881 SocketTransportProtocol::Tcp(TcpSocket::SrcPort(Port { range: 123..=123, invert: false }));
882 "SocketTransportProtocolTcp"
883 )]
884 #[test_case(
885 fnet_matchers::SocketTransportProtocol::Udp(
886 fnet_matchers::UdpSocket::SrcPort(
887 fnet_matchers::Port { start: 123, end: 123, invert: false }
888 )
889 ),
890 SocketTransportProtocol::Udp(UdpSocket::SrcPort(Port { range: 123..=123, invert: false }));
891 "SocketTransportProtocolUdp"
892 )]
893 fn convert_from_fidl_and_back<F, E>(fidl_type: F, local_type: E)
894 where
895 E: TryFrom<F> + Clone + Debug + PartialEq,
896 <E as TryFrom<F>>::Error: Debug + PartialEq,
897 F: From<E> + Clone + Debug + PartialEq,
898 {
899 assert_eq!(fidl_type.clone().try_into(), Ok(local_type.clone()));
900 assert_eq!(<_ as Into<F>>::into(local_type), fidl_type.clone());
901 }
902
903 #[test_case(
904 fnet_matchers::BoundInterface::__SourceBreaking { unknown_ordinal: 0 } =>
905 Err(BoundInterfaceError::UnknownUnionVariant(0));
906 "UnknownUnionVariant"
907 )]
908 #[test_case(
909 fnet_matchers::BoundInterface::Bound(fnet_matchers::Interface::Id(0)) =>
910 Err(BoundInterfaceError::Interface(InterfaceError::ZeroId));
911 "InterfaceError"
912 )]
913 fn bound_interface_try_from_error(
914 fidl: fnet_matchers::BoundInterface,
915 ) -> Result<BoundInterface, BoundInterfaceError> {
916 BoundInterface::try_from(fidl)
917 }
918
919 #[test_case(
920 fnet_matchers::Mark::__SourceBreaking { unknown_ordinal: 0 } =>
921 Err(MarkError::UnknownUnionVariant(0));
922 "UnknownUnionVariant"
923 )]
924 fn mark_try_from_error(fidl: fnet_matchers::Mark) -> Result<Mark, MarkError> {
925 Mark::try_from(fidl)
926 }
927
928 #[test_case(
929 fnet_matchers::MarkInDomain {
930 domain: fnet::MarkDomain::Mark1,
931 mark: fnet_matchers::Mark::__SourceBreaking { unknown_ordinal: 0 },
932 } => Err(MarkInDomainError::Mark(MarkError::UnknownUnionVariant(0)));
933 "MarkInDomain Mark Error"
934 )]
935 fn mark_and_domain_try_from_error(
936 fidl: fnet_matchers::MarkInDomain,
937 ) -> Result<MarkInDomain, MarkInDomainError> {
938 MarkInDomain::try_from(fidl)
939 }
940
941 #[test]
942 fn address_matcher_type_try_from_unknown_variant() {
943 assert_eq!(
944 AddressMatcherType::try_from(fnet_matchers::AddressMatcherType::__SourceBreaking {
945 unknown_ordinal: 0
946 }),
947 Err(AddressMatcherTypeError::UnknownUnionVariant)
948 );
949 }
950
951 #[test]
952 fn subnet_try_from_invalid() {
953 assert_eq!(
954 Subnet::try_from(fnet::Subnet { addr: fidl_ip!("192.0.2.1"), prefix_len: 33 }),
955 Err(SubnetError::PrefixTooLong)
956 );
957 assert_eq!(Subnet::try_from(fidl_subnet!("192.0.2.1/24")), Err(SubnetError::HostBitsSet));
958 }
959
960 #[test]
961 fn address_range_try_from_invalid() {
962 assert_eq!(
963 AddressRange::try_from(fnet_matchers::AddressRange {
964 start: fidl_ip!("192.0.2.1"),
965 end: fidl_ip!("192.0.2.0"),
966 }),
967 Err(AddressRangeError::Invalid)
968 );
969 assert_eq!(
970 AddressRange::try_from(fnet_matchers::AddressRange {
971 start: fidl_ip!("2001:db8::1"),
972 end: fidl_ip!("2001:db8::"),
973 }),
974 Err(AddressRangeError::Invalid)
975 );
976 }
977
978 #[test]
979 fn address_range_try_from_family_mismatch() {
980 assert_eq!(
981 AddressRange::try_from(fnet_matchers::AddressRange {
982 start: fidl_ip!("192.0.2.0"),
983 end: fidl_ip!("2001:db8::"),
984 }),
985 Err(AddressRangeError::FamilyMismatch)
986 );
987 }
988
989 #[test]
990 fn port_matcher_try_from_invalid() {
991 assert_eq!(
992 Port::try_from(fnet_matchers::Port { start: 1, end: 0, invert: false }),
993 Err(PortError::InvalidPortRange)
994 );
995 }
996
997 #[test]
998 fn transport_protocol_try_from_unknown_variant() {
999 assert_eq!(
1000 TransportProtocol::try_from(fnet_matchers::PacketTransportProtocol::__SourceBreaking {
1001 unknown_ordinal: 0
1002 }),
1003 Err(TransportProtocolError::UnknownUnionVariant)
1004 );
1005 }
1006
1007 #[test_case(
1008 fnet_matchers::TcpSocket::__SourceBreaking { unknown_ordinal: 100 } =>
1009 Err(TcpSocketError::UnknownUnionVariant(100));
1010 "TcpSocket UnknownUnionVariant"
1011 )]
1012 #[test_case(
1013 fnet_matchers::TcpSocket::SrcPort(fnet_matchers::Port {
1014 start: 1,
1015 end: 0,
1016 invert: false,
1017 }) => Err(TcpSocketError::Port(PortError::InvalidPortRange));
1018 "TcpSocket SrcPort Error"
1019 )]
1020 #[test_case(
1021 fnet_matchers::TcpSocket::DstPort(fnet_matchers::Port {
1022 start: 1,
1023 end: 0,
1024 invert: false,
1025 }) => Err(TcpSocketError::Port(PortError::InvalidPortRange));
1026 "TcpSocket DstPort Error"
1027 )]
1028 fn tcp_socket_try_from_error(
1029 fidl: fnet_matchers::TcpSocket,
1030 ) -> Result<TcpSocket, TcpSocketError> {
1031 TcpSocket::try_from(fidl)
1032 }
1033
1034 #[test_case(
1035 fnet_matchers::UdpSocket::__SourceBreaking { unknown_ordinal: 100 } =>
1036 Err(UdpSocketError::UnknownUnionVariant(100));
1037 "UdpSocket UnknownUnionVariant"
1038 )]
1039 #[test_case(
1040 fnet_matchers::UdpSocket::SrcPort(fnet_matchers::Port {
1041 start: 1,
1042 end: 0,
1043 invert: false,
1044 }) => Err(UdpSocketError::Port(PortError::InvalidPortRange));
1045 "UdpSocket SrcPort Error"
1046 )]
1047 #[test_case(
1048 fnet_matchers::UdpSocket::DstPort(fnet_matchers::Port {
1049 start: 1,
1050 end: 0,
1051 invert: false,
1052 }) => Err(UdpSocketError::Port(PortError::InvalidPortRange));
1053 "UdpSocket DstPort Error"
1054 )]
1055 fn udp_socket_try_from_error(
1056 fidl: fnet_matchers::UdpSocket,
1057 ) -> Result<UdpSocket, UdpSocketError> {
1058 UdpSocket::try_from(fidl)
1059 }
1060
1061 #[test_case(
1062 fnet_matchers::SocketTransportProtocol::__SourceBreaking {
1063 unknown_ordinal: 100
1064 } => Err(SocketTransportProtocolError::UnknownUnionVariant(100));
1065 "SocketTransportProtocol UnknownUnionVariant"
1066 )]
1067 #[test_case(
1068 fnet_matchers::SocketTransportProtocol::Tcp(
1069 fnet_matchers::TcpSocket::__SourceBreaking { unknown_ordinal: 100 }
1070 ) => Err(SocketTransportProtocolError::Tcp(TcpSocketError::UnknownUnionVariant(100)));
1071 "SocketTransportProtocol Tcp Error"
1072 )]
1073 #[test_case(
1074 fnet_matchers::SocketTransportProtocol::Udp(
1075 fnet_matchers::UdpSocket::__SourceBreaking { unknown_ordinal: 100 }
1076 ) => Err(SocketTransportProtocolError::Udp(UdpSocketError::UnknownUnionVariant(100)));
1077 "SocketTransportProtocol Udp Error"
1078 )]
1079 fn socket_transport_protocol_try_from_error(
1080 fidl: fnet_matchers::SocketTransportProtocol,
1081 ) -> Result<SocketTransportProtocol, SocketTransportProtocolError> {
1082 SocketTransportProtocol::try_from(fidl)
1083 }
1084}