rmap/commands/
common.rs

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        // For hostname resolution, return an error for now
43        // Real implementation would use async DNS resolution
44        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    // Reserved predicates
118    Loopback,
119    Unspecified,
120    LinkLocal,
121    UniqueLocal,
122
123    // Multicast predicates
124    Multicast,
125    SolicitedNode,
126
127    // Transition predicates
128    Ipv4Mapped,
129    Ipv4ToIpv6,
130    ExtendedIpv4,
131    Ipv6ToIpv4,
132
133    // Documentation predicates
134    Documentation,
135    Documentation2,
136    Benchmarking,
137
138    // Protocol predicates
139    Teredo,
140    IetfProtocol,
141    PortControl,
142    Turn,
143    DnsSd,
144    Amt,
145    SegmentRouting,
146
147    // Special purpose predicates
148    DiscardOnly,
149    DummyPrefix,
150    As112V6,
151    DirectAs112,
152    DeprecatedOrchid,
153    OrchidV2,
154    DroneRemoteId,
155
156    // EUI-64 predicates
157    Eui64,
158    LowByteHost,
159}
160
161impl AddressPredicate {
162    pub fn to_filter_name(&self) -> String {
163        match self {
164            // Reserved predicates
165            AddressPredicate::Loopback => "loopback",
166            AddressPredicate::Unspecified => "unspecified",
167            AddressPredicate::LinkLocal => "link_local",
168            AddressPredicate::UniqueLocal => "unique_local",
169
170            // Multicast predicates
171            AddressPredicate::Multicast => "multicast",
172            AddressPredicate::SolicitedNode => "solicited_node",
173
174            // Transition predicates
175            AddressPredicate::Ipv4Mapped => "ipv4_mapped",
176            AddressPredicate::Ipv4ToIpv6 => "ipv4_to_ipv6",
177            AddressPredicate::ExtendedIpv4 => "extended_ipv4",
178            AddressPredicate::Ipv6ToIpv4 => "ipv6_to_ipv4",
179
180            // Documentation predicates
181            AddressPredicate::Documentation => "documentation",
182            AddressPredicate::Documentation2 => "documentation2",
183            AddressPredicate::Benchmarking => "benchmarking",
184
185            // Protocol predicates
186            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            // Special purpose predicates
195            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            // EUI-64 predicates
204            AddressPredicate::Eui64 => "eui64",
205            AddressPredicate::LowByteHost => "low_byte_host",
206        }
207        .to_string()
208    }
209}