1use clap::{Subcommand, ValueEnum};
2use ipnet::IpNet;
3use serde::{Deserialize, Serialize};
4use std::net::{IpAddr, Ipv6Addr};
5
6#[derive(Debug)]
7pub enum TargetError {
8 IpAddrParse(std::net::AddrParseError),
9 IpNetParse(ipnet::AddrParseError),
10 DnsResolve(hickory_resolver::error::ResolveError),
11 NoAddressFound,
12}
13
14impl std::fmt::Display for TargetError {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 TargetError::IpAddrParse(e) => write!(f, "Failed to parse IP address: {}", e),
18 TargetError::IpNetParse(e) => write!(f, "Failed to parse IP network: {}", e),
19 TargetError::DnsResolve(e) => write!(f, "Failed to resolve hostname: {}", e),
20 TargetError::NoAddressFound => write!(f, "No valid IP addresses found for hostname"),
21 }
22 }
23}
24
25#[derive(Debug)]
26pub enum Target {
27 SingleIp(IpAddr),
28 Network(IpNet),
29 Hostname(String, Vec<IpAddr>),
30}
31
32impl Target {
33 pub fn parse(input: &str) -> Result<Self, TargetError> {
34 if let Ok(ip) = input.parse::<IpAddr>() {
35 return Ok(Target::SingleIp(ip));
36 }
37
38 if let Ok(net) = input.parse::<IpNet>() {
39 return Ok(Target::Network(net));
40 }
41
42 Err(TargetError::IpAddrParse(
45 input.parse::<IpAddr>().unwrap_err(),
46 ))
47 }
48}
49
50#[derive(Clone, ValueEnum, Serialize, Deserialize)]
51#[value(rename_all = "snake_case")]
52pub enum ReservedPredicate {
53 Loopback,
54 Unspecified,
55 LinkLocal,
56 UniqueLocal,
57}
58
59#[derive(Clone, ValueEnum, Serialize, Deserialize)]
60#[value(rename_all = "snake_case")]
61pub enum MulticastPredicate {
62 Multicast,
63 SolicitedNode,
64}
65
66#[derive(Clone, ValueEnum, Serialize, Deserialize)]
67#[value(rename_all = "snake_case")]
68pub enum TransitionPredicate {
69 Ipv4Mapped,
70 Ipv4ToIpv6,
71 ExtendedIpv4,
72 Ipv6ToIpv4,
73}
74
75#[derive(Clone, ValueEnum, Serialize, Deserialize)]
76#[value(rename_all = "snake_case")]
77pub enum DocumentationPredicate {
78 Documentation,
79 Documentation2,
80 Benchmarking,
81}
82
83#[derive(Clone, ValueEnum, Serialize, Deserialize)]
84#[value(rename_all = "snake_case")]
85pub enum ProtocolPredicate {
86 Teredo,
87 IetfProtocol,
88 PortControl,
89 Turn,
90 DnsSd,
91 Amt,
92 SegmentRouting,
93}
94
95#[derive(Clone, ValueEnum, Serialize, Deserialize)]
96#[value(rename_all = "snake_case")]
97pub enum SpecialPurposePredicate {
98 DiscardOnly,
99 DummyPrefix,
100 As112V6,
101 DirectAs112,
102 DeprecatedOrchid,
103 OrchidV2,
104 DroneRemoteId,
105}
106
107#[derive(Clone, ValueEnum, Serialize, Deserialize)]
108#[value(rename_all = "snake_case")]
109pub enum Eui64Predicate {
110 Eui64,
111 LowByteHost,
112}
113
114#[derive(Clone, ValueEnum, Serialize, Deserialize)]
115#[value(rename_all = "snake_case")]
116pub enum AddressPredicate {
117 Loopback,
119 Unspecified,
120 LinkLocal,
121 UniqueLocal,
122
123 Multicast,
125 SolicitedNode,
126
127 Ipv4Mapped,
129 Ipv4ToIpv6,
130 ExtendedIpv4,
131 Ipv6ToIpv4,
132
133 Documentation,
135 Documentation2,
136 Benchmarking,
137
138 Teredo,
140 IetfProtocol,
141 PortControl,
142 Turn,
143 DnsSd,
144 Amt,
145 SegmentRouting,
146
147 DiscardOnly,
149 DummyPrefix,
150 As112V6,
151 DirectAs112,
152 DeprecatedOrchid,
153 OrchidV2,
154 DroneRemoteId,
155
156 Eui64,
158 LowByteHost,
159}
160
161impl AddressPredicate {
162 pub fn to_filter_name(&self) -> String {
163 match self {
164 AddressPredicate::Loopback => "loopback",
166 AddressPredicate::Unspecified => "unspecified",
167 AddressPredicate::LinkLocal => "link_local",
168 AddressPredicate::UniqueLocal => "unique_local",
169
170 AddressPredicate::Multicast => "multicast",
172 AddressPredicate::SolicitedNode => "solicited_node",
173
174 AddressPredicate::Ipv4Mapped => "ipv4_mapped",
176 AddressPredicate::Ipv4ToIpv6 => "ipv4_to_ipv6",
177 AddressPredicate::ExtendedIpv4 => "extended_ipv4",
178 AddressPredicate::Ipv6ToIpv4 => "ipv6_to_ipv4",
179
180 AddressPredicate::Documentation => "documentation",
182 AddressPredicate::Documentation2 => "documentation2",
183 AddressPredicate::Benchmarking => "benchmarking",
184
185 AddressPredicate::Teredo => "teredo",
187 AddressPredicate::IetfProtocol => "ietf_protocol",
188 AddressPredicate::PortControl => "port_control",
189 AddressPredicate::Turn => "turn",
190 AddressPredicate::DnsSd => "dns_sd",
191 AddressPredicate::Amt => "amt",
192 AddressPredicate::SegmentRouting => "segment_routing",
193
194 AddressPredicate::DiscardOnly => "discard_only",
196 AddressPredicate::DummyPrefix => "dummy_prefix",
197 AddressPredicate::As112V6 => "as112v6",
198 AddressPredicate::DirectAs112 => "direct_as112",
199 AddressPredicate::DeprecatedOrchid => "deprecated_orchid",
200 AddressPredicate::OrchidV2 => "orchid_v2",
201 AddressPredicate::DroneRemoteId => "drone_remote_id",
202
203 AddressPredicate::Eui64 => "eui64",
205 AddressPredicate::LowByteHost => "low_byte_host",
206 }
207 .to_string()
208 }
209}