1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
use std::{
convert::Infallible,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
};
use n0_error::stack_error;
/// Options when configuring binding an IP socket.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BindOpts {
/// Sets the network prefix length of the subnet for this interface.
///
/// The prefix length is used in the routing table that is built to decide where
/// datagrams without a specific source address are sent. If these number of leading
/// bits in the destination IP address match the same number of leading bits in this
/// bound socket address, then it matches the subnet and the datagram will be sent
/// here. Otherwise the next bound sockets will be checked for a subnet match. Sockets
/// are ordered from longest prefix to shortest prefix.
///
/// If no bound address has a matching subnet, the bind marked with
/// [`Self::is_default_route`] will be used.
///
/// Note that most datagrams belonging to a traffic flow are in response to an incoming
/// datagram. Those are usually sent on the same bound socket as they were received and
/// will not consult the routing table derived from these bound sockets to select the
/// socket on which they will be sent.
prefix_len: u8,
/// If set, binding this interface is required and any errors will abort the
/// initialization of the endpoint.
///
/// Defaults to `true`.
is_required: bool,
/// Whether this socket should be used as default route.
///
/// The default route is used for outgoing datagrams not belonging to an existing
/// traffic flow, which does not fit in any subnet of the bound sockets. It is assumed
/// this subnet has a gateway router to route such packets.
///
/// See [`Self::prefix_len`] for details of how such routing works.
is_default_route: Option<bool>,
}
impl Default for BindOpts {
fn default() -> Self {
Self {
prefix_len: 0,
is_required: true,
is_default_route: None,
}
}
}
impl BindOpts {
/// Sets the network prefix length of the subnet this interface is in.
///
///
/// The subnets of bound sockets are used to route outgoing datagrams not belonging to
/// an existing traffic flow to the socket they should be sent on. Subnets are ordered
/// from longest prefix length to shortest prefix length and the first subnet which
/// contains the destination IP address will be chosen. If no subnet matches but there
/// is a bound socket marked with [`Self::set_is_default_route`] then this socket will
/// be used. In this case it is assumed the attached subnet has a gateway router to
/// forward the datagram.
///
/// Defaults to `0`, which means *all* IP addresses will belong to the subnet of this
/// socket's address. If multiple sockets of the same address family (IPv4 or IPv6) are
/// bound with such a `/0` prefix the socket which will be chosen is undefined.
///
/// For IPv4 sockets the maximum prefix is `32`. For IPv6 the maximum prefix is `128`.
pub fn set_prefix_len(mut self, prefix_len: u8) -> Self {
self.prefix_len = prefix_len;
self
}
/// Returns the `prefix_len`, see [`Self::set_prefix_len`].
pub fn prefix_len(&self) -> u8 {
self.prefix_len
}
/// Sets whether bind errors are fatal for this socket.
///
/// If `false` and this socket fails to bind, the error will be silently ignored and the
/// endpoint will still be created.
///
/// Defaults to `true`.
pub fn set_is_required(mut self, is_required: bool) -> Self {
self.is_required = is_required;
self
}
/// Returns the value set by [`Self::set_is_required`].
pub fn is_required(&self) -> bool {
self.is_required
}
/// Sets whether this is a default route.
///
/// The default route is used for outgoing datagrams not belonging to an existing
/// traffic flow, which does not fit in any subnet of the bound sockets. It is assumed
/// this subnet has a gateway router to route such packets.
///
/// See [`Self::set_prefix_len`] for details on how this routing works.
///
/// If not set explicitly, then [`Self::is_default_route`] will return `true`
/// if the prefix length is set to `0` (the default) and `false` otherwise.
pub fn set_is_default_route(mut self, is_default_route: bool) -> Self {
self.is_default_route = Some(is_default_route);
self
}
/// Returns whether this is a default route.
///
/// If [`Self::set_is_default_route`] has been called then that value is returned.
/// Otherwise, returns `true` if the [`prefix_len`][`Self::prefix_len] is `0` and
/// `false` otherwise.
pub fn is_default_route(&self) -> bool {
match self.is_default_route {
Some(is_default) => is_default,
None => self.prefix_len() == 0,
}
}
}
/// A simpler version of [`ToSocketAddrs`], that does not do any DNS resolution.
///
/// [`ToSocketAddrs`]: std::net::ToSocketAddrs
pub trait ToSocketAddr {
/// Error type on failed conversion.
type Err: std::error::Error;
/// Tries to convert this type to a [`SocketAddr`].
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err>;
}
impl ToSocketAddr for SocketAddr {
type Err = Infallible;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
Ok(*self)
}
}
impl ToSocketAddr for SocketAddrV4 {
type Err = Infallible;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
Ok(SocketAddr::V4(*self))
}
}
impl ToSocketAddr for SocketAddrV6 {
type Err = Infallible;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
Ok(SocketAddr::V6(*self))
}
}
impl ToSocketAddr for (IpAddr, u16) {
type Err = Infallible;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
let (ip, port) = *self;
match ip {
IpAddr::V4(ref a) => (*a, port).to_socket_addr(),
IpAddr::V6(ref a) => (*a, port).to_socket_addr(),
}
}
}
impl ToSocketAddr for (Ipv4Addr, u16) {
type Err = Infallible;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
let (ip, port) = *self;
SocketAddrV4::new(ip, port).to_socket_addr()
}
}
impl ToSocketAddr for (Ipv6Addr, u16) {
type Err = Infallible;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
let (ip, port) = *self;
SocketAddrV6::new(ip, port, 0, 0).to_socket_addr()
}
}
impl ToSocketAddr for (&str, u16) {
type Err = std::net::AddrParseError;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
let (host, port) = *self;
let addr = host.parse::<IpAddr>()?;
let addr = SocketAddr::new(addr, port);
Ok(addr)
}
}
impl ToSocketAddr for (String, u16) {
type Err = std::net::AddrParseError;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
(&*self.0, self.1).to_socket_addr()
}
}
impl ToSocketAddr for str {
type Err = std::net::AddrParseError;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
let addr = self.parse()?;
Ok(addr)
}
}
impl<T: ToSocketAddr + ?Sized> ToSocketAddr for &T {
type Err = T::Err;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
(**self).to_socket_addr()
}
}
impl ToSocketAddr for String {
type Err = std::net::AddrParseError;
fn to_socket_addr(&self) -> Result<SocketAddr, Self::Err> {
(**self).to_socket_addr()
}
}
#[allow(missing_docs)]
#[stack_error(derive, add_meta, from_sources)]
#[non_exhaustive]
pub enum InvalidSocketAddr {
#[error(transparent)]
AddrParse {
#[error(std_err)]
source: std::net::AddrParseError,
},
#[error(transparent)]
InvalidPrefix {
#[error(std_err)]
source: ipnet::PrefixLenError,
},
#[error(transparent)]
Infallible {
#[error(std_err)]
source: Infallible,
},
#[error("Only a single default address can be set per IP family")]
DuplicateDefaultAddr,
}