async_traceroute/traceroute/
builder.rs1use 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}