async_traceroute/traceroute/
builder.rs

1use std::net::IpAddr;
2use std::time::Duration;
3
4use pnet::datalink::NetworkInterface;
5
6use crate::Traceroute;
7use crate::traceroute::probe::generator::{IcmpProbeTaskGenerator, ProbeTaskGenerator, TcpProbeTaskGenerator, UdpProbeTaskGenerator};
8use crate::traceroute::probe::parser::{IcmpProbeResponseParser, ProbeReplyParser, TcpProbeResponseParser, UdpProbeResponseParser};
9use crate::traceroute::probe::sniffer::IcmpProbeResponseSniffer;
10use crate::traceroute::utils::packet_utils::{default_interface, get_interface};
11
12pub struct TracerouteBuilder;
13
14impl TracerouteBuilder {
15    pub fn udp() -> TracerouteUdpBuilder {
16        let traceroute_base_builder = TracerouteBaseBuilder::new();
17        TracerouteUdpBuilder::new(traceroute_base_builder)
18    }
19
20    pub fn icmp() -> TracerouteIcmpBuilder {
21        let traceroute_base_builder = TracerouteBaseBuilder::new();
22        TracerouteIcmpBuilder::new(traceroute_base_builder)
23    }
24
25    pub fn tcp() -> TracerouteTcpBuilder {
26        let traceroute_base_builder = TracerouteBaseBuilder::new();
27        TracerouteTcpBuilder::new(traceroute_base_builder)
28    }
29}
30
31struct TracerouteBaseBuilder {
32    destination_address: Option<IpAddr>,
33    max_ttl: u8,
34    nqueries: u16,
35    sim_queries: u16,
36    max_wait_probe: Duration,
37    is_active_dns_lookup: bool,
38    interface: Option<NetworkInterface>, 
39    error: Option<String>,
40}
41
42impl TracerouteBaseBuilder {
43    const DEFAULT_MAX_TTL: u8 = 30;
44    const DEFAULT_QUERIES_PER_HOP: u16 = 3;
45    const DEFAULT_SIM_QUERIES: u16 = 16;
46    const DEFAULT_MAX_WAIT_PROBE: Duration = Duration::from_secs(3);
47    const DEFAULT_IS_ACTIVE_DNS_LOOKUP: bool = true;
48
49    fn new() -> Self {
50        Self {
51            destination_address: None,
52            max_ttl: Self::DEFAULT_MAX_TTL,
53            nqueries: Self::DEFAULT_QUERIES_PER_HOP,
54            sim_queries: Self::DEFAULT_SIM_QUERIES,
55            max_wait_probe: Self::DEFAULT_MAX_WAIT_PROBE,
56            is_active_dns_lookup: Self::DEFAULT_IS_ACTIVE_DNS_LOOKUP,
57            interface: None,
58            error: None,
59        }
60    }
61    
62    fn destination_address(&mut self, destination_address: IpAddr) {
63        self.destination_address = Some(destination_address);
64    }
65    
66    fn max_ttl(&mut self, max_ttl: u8) {
67        self.max_ttl = max_ttl;
68    }
69    
70    fn queries_per_hop(&mut self, nqueries: u16) {
71        self.nqueries = nqueries;
72    }
73
74    fn simultaneous_queries(&mut self, sim_queries: u16) {
75        self.sim_queries = sim_queries;
76    }
77
78    fn max_wait_probe(&mut self, max_wait_probe: Duration) {
79        self.max_wait_probe = max_wait_probe;
80    }
81
82    fn active_dns_lookup(&mut self, active_dns_lookup: bool) {
83        self.is_active_dns_lookup = active_dns_lookup;
84    }
85    
86    fn network_interface(&mut self, interface: &str) {
87        match get_interface(interface) {
88            Some(net_interface) => self.interface = Some(net_interface),
89            None => self.error = Some(format!("Network interface {} not found", interface))
90        };
91    }
92    
93    fn build(
94        self,
95        probe_task_generator: Box<dyn ProbeTaskGenerator>,
96        probe_reply_parser: ProbeReplyParser,
97    ) -> Result<Traceroute, String> {
98        if self.error.is_some() {
99            return Err(self.error.unwrap())
100        }
101
102        if self.destination_address.is_none() {
103            return Err(String::from("Destination address required!"));
104        }
105        
106        let source_address = match self.interface {
107            None => match default_interface() {
108                None => return Err(String::from("No network interface found!")),
109                Some(network_interface) => match network_interface.ips.first() {
110                    None => return Err(String::from("No network interface found!")),
111                    Some(ip_network) => ip_network.ip()                }
112            },
113            Some(network_interface) => match network_interface.ips.first() {
114                None => return Err(String::from("No network interface found!")),
115                Some(ip_network) => ip_network.ip()
116            }
117        };
118
119        let icmp_sniffer = match IcmpProbeResponseSniffer::new(probe_reply_parser) {
120            Ok(icmp_sniffer) => icmp_sniffer,
121            Err(error) => return Err(String::from(&format!("{}", error.to_string())))
122        };
123        
124        Ok(Traceroute::new(
125            source_address,
126            self.destination_address.unwrap(),
127            self.max_ttl,
128            self.nqueries,
129            self.sim_queries,
130            self.max_wait_probe,
131            self.is_active_dns_lookup,
132            probe_task_generator,
133            icmp_sniffer,
134        ))
135    }
136}
137
138pub struct TracerouteUdpBuilder {
139    traceroute_base_builder: TracerouteBaseBuilder,
140    initial_destination_port: u16,
141}
142
143impl TracerouteUdpBuilder {
144    const DEFAULT_INITIAL_DESTINATION_PORT: u16 = 33434;
145
146    fn new(traceroute_base_builder: TracerouteBaseBuilder) -> Self {
147        Self {
148            initial_destination_port: Self::DEFAULT_INITIAL_DESTINATION_PORT,
149            traceroute_base_builder,
150        }
151    }
152
153    pub fn initial_destination_port(mut self, initial_destination_port: u16) -> Self {
154        self.initial_destination_port = initial_destination_port;
155        self
156    }
157    
158    pub fn destination_address(mut self, destination_address: IpAddr) -> Self {
159        self.traceroute_base_builder.destination_address(destination_address);
160        self
161    }
162
163    pub fn max_ttl(mut self, max_ttl: u8) -> Self {
164        self.traceroute_base_builder.max_ttl(max_ttl);
165        self
166    }
167
168    pub fn queries_per_hop(mut self, nqueries: u16) -> Self {
169        self.traceroute_base_builder.queries_per_hop(nqueries);
170        self
171    }
172
173    pub fn simultaneous_queries(mut self, sim_queries: u16) -> Self {
174        self.traceroute_base_builder.simultaneous_queries(sim_queries);
175        self
176    }
177
178    pub fn max_wait_probe(mut self, max_wait_probe: Duration) -> Self {
179        self.traceroute_base_builder.max_wait_probe(max_wait_probe);
180        self
181    }
182
183    pub fn active_dns_lookup(mut self, active_dns_lookup: bool) -> Self {
184        self.traceroute_base_builder.active_dns_lookup(active_dns_lookup);
185        self
186    }
187
188    pub fn network_interface(mut self, interface: &str) -> Self {
189        self.traceroute_base_builder.network_interface(interface);
190        self
191    }
192    
193    pub fn build(self) -> Result<Traceroute, String> {
194        let (parser, generator) = (
195            ProbeReplyParser::UDP(UdpProbeResponseParser), 
196            Box::new(UdpProbeTaskGenerator::new(self.initial_destination_port))
197        );
198        
199        self.traceroute_base_builder.build(generator, parser)
200    }
201}
202
203pub struct TracerouteTcpBuilder {
204    traceroute_base_builder: TracerouteBaseBuilder,
205    destination_port: u16,
206}
207
208impl TracerouteTcpBuilder {
209    const DEFAULT_DESTINATION_PORT: u16 = 80;
210
211    fn new(traceroute_base_builder: TracerouteBaseBuilder) -> Self {
212        Self {
213            destination_port: Self::DEFAULT_DESTINATION_PORT,
214            traceroute_base_builder,
215        }
216    }
217
218    pub fn initial_destination_port(mut self, initial_destination_port: u16) -> Self {
219        self.destination_port = initial_destination_port;
220        self
221    }
222    
223    pub fn destination_address(mut self, destination_address: IpAddr) -> Self {
224        self.traceroute_base_builder.destination_address(destination_address);
225        self
226    }
227
228    pub fn max_ttl(mut self, max_ttl: u8) -> Self {
229        self.traceroute_base_builder.max_ttl(max_ttl);
230        self
231    }
232
233    pub fn queries_per_hop(mut self, nqueries: u16) -> Self {
234        self.traceroute_base_builder.queries_per_hop(nqueries);
235        self
236    }
237
238    pub fn simultaneous_queries(mut self, sim_queries: u16) -> Self {
239        self.traceroute_base_builder.simultaneous_queries(sim_queries);
240        self
241    }
242
243    pub fn max_wait_probe(mut self, max_wait_probe: Duration) -> Self {
244        self.traceroute_base_builder.max_wait_probe(max_wait_probe);
245        self
246    }
247
248    pub fn active_dns_lookup(mut self, active_dns_lookup: bool) -> Self {
249        self.traceroute_base_builder.active_dns_lookup(active_dns_lookup);
250        self
251    }
252
253    pub fn network_interface(mut self, interface: &str) -> Self {
254        self.traceroute_base_builder.network_interface(interface);
255        self
256    }
257
258    pub fn build(self) -> Result<Traceroute, String> {
259        let (parser, generator) = (
260            ProbeReplyParser::TCP(TcpProbeResponseParser),
261            Box::new(TcpProbeTaskGenerator::new(self.destination_port))
262        );
263
264        self.traceroute_base_builder.build(generator, parser)
265    }
266}
267
268pub struct TracerouteIcmpBuilder {
269    traceroute_base_builder: TracerouteBaseBuilder,
270    isn: u16,
271}
272
273impl TracerouteIcmpBuilder {
274    const DEFAULT_ISN: u16 = 1;
275
276    fn new(traceroute_base_builder: TracerouteBaseBuilder) -> Self {
277        Self {
278            isn: Self::DEFAULT_ISN,
279            traceroute_base_builder,
280        }
281    }
282
283    pub fn initial_sequence_number(mut self, isn: u16) -> Self {
284        self.isn = isn;
285        self
286    }
287    
288    pub fn destination_address(mut self, destination_address: IpAddr) -> Self {
289        self.traceroute_base_builder.destination_address(destination_address);
290        self
291    }
292
293    pub fn max_ttl(mut self, max_ttl: u8) -> Self {
294        self.traceroute_base_builder.max_ttl(max_ttl);
295        self
296    }
297
298    pub fn queries_per_hop(mut self, nqueries: u16) -> Self {
299        self.traceroute_base_builder.queries_per_hop(nqueries);
300        self
301    }
302
303    pub fn simultaneous_queries(mut self, sim_queries: u16) -> Self {
304        self.traceroute_base_builder.simultaneous_queries(sim_queries);
305        self
306    }
307
308    pub fn max_wait_probe(mut self, max_wait_probe: Duration) -> Self {
309        self.traceroute_base_builder.max_wait_probe(max_wait_probe);
310        self
311    }
312
313    pub fn active_dns_lookup(mut self, active_dns_lookup: bool) -> Self {
314        self.traceroute_base_builder.active_dns_lookup(active_dns_lookup);
315        self
316    }
317    
318    pub fn network_interface(mut self, interface: &str) -> Self {
319        self.traceroute_base_builder.network_interface(interface);
320        self
321    }
322
323    pub fn build(self) -> Result<Traceroute, String> {
324        let (parser, generator) = (
325            ProbeReplyParser::ICMP(IcmpProbeResponseParser),
326            Box::new(match IcmpProbeTaskGenerator::new(self.isn) {
327                Ok(generator) => generator,
328                Err(error) => return Err(error.to_string()),
329            })
330        );
331
332        self.traceroute_base_builder.build(generator, parser)
333    }
334}