netget/protocol/binding_defaults.rs
1//! Protocol binding defaults
2//!
3//! Provides a flexible system for protocols to specify default binding parameters.
4//! Each protocol can define defaults for MAC address, network interface, host, and port.
5
6/// Default binding parameters for a protocol
7///
8/// Protocols can return `Some(BindingDefaults)` from `default_binding()` to opt into
9/// the flexible binding system. Protocols that return `None` use the legacy listen_addr system.
10///
11/// User-provided values override protocol defaults.
12#[derive(Debug, Clone)]
13pub struct BindingDefaults {
14 /// MAC address for Layer 2 protocols (e.g., ARP spoofing with specific MAC)
15 pub mac_address: Option<String>,
16
17 /// Network interface for raw protocols (e.g., "lo", "eth0", "en0")
18 pub interface: Option<String>,
19
20 /// Host address (IPv4, IPv6, or hostname) for socket-based protocols
21 /// Examples: "127.0.0.1", "0.0.0.0", "::", "localhost"
22 pub host: Option<String>,
23
24 /// Port number for socket-based protocols
25 /// Use Some(0) for automatic port assignment
26 pub port: Option<u16>,
27}
28
29impl BindingDefaults {
30 /// Create binding defaults for port-based protocols (TCP, UDP, HTTP, DNS, etc.)
31 ///
32 /// # Arguments
33 /// * `default_host` - Host to bind (e.g., "127.0.0.1", "0.0.0.0")
34 /// * `default_port` - Port to bind (use 0 for automatic assignment)
35 ///
36 /// # Example
37 /// ```ignore
38 /// // TCP: bind to loopback by default, auto-assign port
39 /// BindingDefaults::port_based("127.0.0.1", 0)
40 /// ```
41 pub fn port_based(default_host: &str, default_port: u16) -> Self {
42 Self {
43 mac_address: None,
44 interface: None,
45 host: Some(default_host.to_string()),
46 port: Some(default_port),
47 }
48 }
49
50 /// Create binding defaults for interface-based protocols (ICMP, ARP, DataLink, etc.)
51 ///
52 /// # Arguments
53 /// * `default_interface` - Interface to bind (e.g., "lo", "eth0")
54 ///
55 /// # Example
56 /// ```ignore
57 /// // ICMP: bind to loopback interface by default
58 /// BindingDefaults::interface_based("lo")
59 /// ```
60 pub fn interface_based(default_interface: &str) -> Self {
61 Self {
62 mac_address: None,
63 interface: Some(default_interface.to_string()),
64 host: None,
65 port: None,
66 }
67 }
68
69 /// Apply user-provided values, falling back to protocol defaults
70 ///
71 /// User values take precedence over defaults. Returns the final binding
72 /// configuration with all fields resolved.
73 ///
74 /// # Arguments
75 /// * `user_mac` - User-provided MAC address (overrides default)
76 /// * `user_interface` - User-provided interface (overrides default)
77 /// * `user_host` - User-provided host (overrides default)
78 /// * `user_port` - User-provided port (overrides default)
79 ///
80 /// # Returns
81 /// Tuple of (final_mac, final_interface, final_host, final_port)
82 pub fn apply(
83 &self,
84 user_mac: Option<String>,
85 user_interface: Option<String>,
86 user_host: Option<String>,
87 user_port: Option<u16>,
88 ) -> (Option<String>, Option<String>, Option<String>, Option<u16>) {
89 (
90 user_mac.or_else(|| self.mac_address.clone()),
91 user_interface.or_else(|| self.interface.clone()),
92 user_host.or_else(|| self.host.clone()),
93 user_port.or(self.port),
94 )
95 }
96}