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