1 | #[cfg (any( |
2 | target_os = "android" , |
3 | target_os = "dragonfly" , |
4 | target_os = "freebsd" , |
5 | target_os = "ios" , |
6 | target_os = "linux" , |
7 | target_os = "macos" , |
8 | target_os = "illumos" , |
9 | target_os = "netbsd" , |
10 | target_os = "openbsd" , |
11 | target_os = "haiku" , |
12 | target_os = "fuchsia" |
13 | ))] |
14 | #[cfg (feature = "net" )] |
15 | pub use self::datalink::LinkAddr; |
16 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
17 | pub use self::vsock::VsockAddr; |
18 | use super::sa_family_t; |
19 | use crate::errno::Errno; |
20 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
21 | use crate::sys::socket::addr::alg::AlgAddr; |
22 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
23 | use crate::sys::socket::addr::netlink::NetlinkAddr; |
24 | #[cfg (all( |
25 | feature = "ioctl" , |
26 | any(target_os = "ios" , target_os = "macos" ) |
27 | ))] |
28 | use crate::sys::socket::addr::sys_control::SysControlAddr; |
29 | use crate::{NixPath, Result}; |
30 | use cfg_if::cfg_if; |
31 | use memoffset::offset_of; |
32 | use std::convert::TryInto; |
33 | use std::ffi::OsStr; |
34 | use std::hash::{Hash, Hasher}; |
35 | use std::os::unix::ffi::OsStrExt; |
36 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
37 | use std::os::unix::io::RawFd; |
38 | use std::path::Path; |
39 | use std::{fmt, mem, net, ptr, slice}; |
40 | |
41 | /// Convert a std::net::Ipv4Addr into the libc form. |
42 | #[cfg (feature = "net" )] |
43 | pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr { |
44 | libc::in_addr { |
45 | s_addr: u32::from_ne_bytes(addr.octets()) |
46 | } |
47 | } |
48 | |
49 | /// Convert a std::net::Ipv6Addr into the libc form. |
50 | #[cfg (feature = "net" )] |
51 | pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr { |
52 | libc::in6_addr { |
53 | s6_addr: addr.octets() |
54 | } |
55 | } |
56 | |
57 | /// These constants specify the protocol family to be used |
58 | /// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html) |
59 | /// |
60 | /// # References |
61 | /// |
62 | /// [address_families(7)](https://man7.org/linux/man-pages/man7/address_families.7.html) |
63 | // Should this be u8? |
64 | #[repr (i32)] |
65 | #[non_exhaustive ] |
66 | #[derive (Copy, Clone, PartialEq, Eq, Debug, Hash)] |
67 | pub enum AddressFamily { |
68 | /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html)) |
69 | Unix = libc::AF_UNIX, |
70 | /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html)) |
71 | Inet = libc::AF_INET, |
72 | /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html)) |
73 | Inet6 = libc::AF_INET6, |
74 | /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html)) |
75 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
76 | #[cfg_attr (docsrs, doc(cfg(all())))] |
77 | Netlink = libc::AF_NETLINK, |
78 | /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html)) |
79 | #[cfg (any( |
80 | target_os = "android" , |
81 | target_os = "linux" , |
82 | target_os = "illumos" , |
83 | target_os = "fuchsia" , |
84 | target_os = "solaris" |
85 | ))] |
86 | #[cfg_attr (docsrs, doc(cfg(all())))] |
87 | Packet = libc::AF_PACKET, |
88 | /// KEXT Controls and Notifications |
89 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
90 | #[cfg_attr (docsrs, doc(cfg(all())))] |
91 | System = libc::AF_SYSTEM, |
92 | /// Amateur radio AX.25 protocol |
93 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
94 | #[cfg_attr (docsrs, doc(cfg(all())))] |
95 | Ax25 = libc::AF_AX25, |
96 | /// IPX - Novell protocols |
97 | Ipx = libc::AF_IPX, |
98 | /// AppleTalk |
99 | AppleTalk = libc::AF_APPLETALK, |
100 | /// AX.25 packet layer protocol. |
101 | /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/)) |
102 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
103 | #[cfg_attr (docsrs, doc(cfg(all())))] |
104 | NetRom = libc::AF_NETROM, |
105 | /// Can't be used for creating sockets; mostly used for bridge |
106 | /// links in |
107 | /// [rtnetlink(7)](https://man7.org/linux/man-pages/man7/rtnetlink.7.html) |
108 | /// protocol commands. |
109 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
110 | #[cfg_attr (docsrs, doc(cfg(all())))] |
111 | Bridge = libc::AF_BRIDGE, |
112 | /// Access to raw ATM PVCs |
113 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
114 | #[cfg_attr (docsrs, doc(cfg(all())))] |
115 | AtmPvc = libc::AF_ATMPVC, |
116 | /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html)) |
117 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
118 | #[cfg_attr (docsrs, doc(cfg(all())))] |
119 | X25 = libc::AF_X25, |
120 | /// RATS (Radio Amateur Telecommunications Society) Open |
121 | /// Systems environment (ROSE) AX.25 packet layer protocol. |
122 | /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/)) |
123 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
124 | #[cfg_attr (docsrs, doc(cfg(all())))] |
125 | Rose = libc::AF_ROSE, |
126 | /// DECet protocol sockets. |
127 | #[cfg (not(target_os = "haiku" ))] |
128 | Decnet = libc::AF_DECnet, |
129 | /// Reserved for "802.2LLC project"; never used. |
130 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
131 | #[cfg_attr (docsrs, doc(cfg(all())))] |
132 | NetBeui = libc::AF_NETBEUI, |
133 | /// This was a short-lived (between Linux 2.1.30 and |
134 | /// 2.1.99pre2) protocol family for firewall upcalls. |
135 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
136 | #[cfg_attr (docsrs, doc(cfg(all())))] |
137 | Security = libc::AF_SECURITY, |
138 | /// Key management protocol. |
139 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
140 | #[cfg_attr (docsrs, doc(cfg(all())))] |
141 | Key = libc::AF_KEY, |
142 | #[allow (missing_docs)] // Not documented anywhere that I can find |
143 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
144 | #[cfg_attr (docsrs, doc(cfg(all())))] |
145 | Ash = libc::AF_ASH, |
146 | /// Acorn Econet protocol |
147 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
148 | #[cfg_attr (docsrs, doc(cfg(all())))] |
149 | Econet = libc::AF_ECONET, |
150 | /// Access to ATM Switched Virtual Circuits |
151 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
152 | #[cfg_attr (docsrs, doc(cfg(all())))] |
153 | AtmSvc = libc::AF_ATMSVC, |
154 | /// Reliable Datagram Sockets (RDS) protocol |
155 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
156 | #[cfg_attr (docsrs, doc(cfg(all())))] |
157 | Rds = libc::AF_RDS, |
158 | /// IBM SNA |
159 | #[cfg (not(target_os = "haiku" ))] |
160 | Sna = libc::AF_SNA, |
161 | /// Socket interface over IrDA |
162 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
163 | #[cfg_attr (docsrs, doc(cfg(all())))] |
164 | Irda = libc::AF_IRDA, |
165 | /// Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE) |
166 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
167 | #[cfg_attr (docsrs, doc(cfg(all())))] |
168 | Pppox = libc::AF_PPPOX, |
169 | /// Legacy protocol for wide area network (WAN) connectivity that was used |
170 | /// by Sangoma WAN cards |
171 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
172 | #[cfg_attr (docsrs, doc(cfg(all())))] |
173 | Wanpipe = libc::AF_WANPIPE, |
174 | /// Logical link control (IEEE 802.2 LLC) protocol |
175 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
176 | #[cfg_attr (docsrs, doc(cfg(all())))] |
177 | Llc = libc::AF_LLC, |
178 | /// InfiniBand native addressing |
179 | #[cfg (all(target_os = "linux" , not(target_env = "uclibc" )))] |
180 | #[cfg_attr (docsrs, doc(cfg(all())))] |
181 | Ib = libc::AF_IB, |
182 | /// Multiprotocol Label Switching |
183 | #[cfg (all(target_os = "linux" , not(target_env = "uclibc" )))] |
184 | #[cfg_attr (docsrs, doc(cfg(all())))] |
185 | Mpls = libc::AF_MPLS, |
186 | /// Controller Area Network automotive bus protocol |
187 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
188 | #[cfg_attr (docsrs, doc(cfg(all())))] |
189 | Can = libc::AF_CAN, |
190 | /// TIPC, "cluster domain sockets" protocol |
191 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
192 | #[cfg_attr (docsrs, doc(cfg(all())))] |
193 | Tipc = libc::AF_TIPC, |
194 | /// Bluetooth low-level socket protocol |
195 | #[cfg (not(any( |
196 | target_os = "illumos" , |
197 | target_os = "ios" , |
198 | target_os = "macos" , |
199 | target_os = "solaris" |
200 | )))] |
201 | #[cfg_attr (docsrs, doc(cfg(all())))] |
202 | Bluetooth = libc::AF_BLUETOOTH, |
203 | /// IUCV (inter-user communication vehicle) z/VM protocol for |
204 | /// hypervisor-guest interaction |
205 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
206 | #[cfg_attr (docsrs, doc(cfg(all())))] |
207 | Iucv = libc::AF_IUCV, |
208 | /// Rx, Andrew File System remote procedure call protocol |
209 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
210 | #[cfg_attr (docsrs, doc(cfg(all())))] |
211 | RxRpc = libc::AF_RXRPC, |
212 | /// New "modular ISDN" driver interface protocol |
213 | #[cfg (not(any( |
214 | target_os = "illumos" , |
215 | target_os = "solaris" , |
216 | target_os = "haiku" |
217 | )))] |
218 | #[cfg_attr (docsrs, doc(cfg(all())))] |
219 | Isdn = libc::AF_ISDN, |
220 | /// Nokia cellular modem IPC/RPC interface |
221 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
222 | #[cfg_attr (docsrs, doc(cfg(all())))] |
223 | Phonet = libc::AF_PHONET, |
224 | /// IEEE 802.15.4 WPAN (wireless personal area network) raw packet protocol |
225 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
226 | #[cfg_attr (docsrs, doc(cfg(all())))] |
227 | Ieee802154 = libc::AF_IEEE802154, |
228 | /// Ericsson's Communication CPU to Application CPU interface (CAIF) |
229 | /// protocol. |
230 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
231 | #[cfg_attr (docsrs, doc(cfg(all())))] |
232 | Caif = libc::AF_CAIF, |
233 | /// Interface to kernel crypto API |
234 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
235 | #[cfg_attr (docsrs, doc(cfg(all())))] |
236 | Alg = libc::AF_ALG, |
237 | /// Near field communication |
238 | #[cfg (target_os = "linux" )] |
239 | #[cfg_attr (docsrs, doc(cfg(all())))] |
240 | Nfc = libc::AF_NFC, |
241 | /// VMWare VSockets protocol for hypervisor-guest interaction. |
242 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
243 | #[cfg_attr (docsrs, doc(cfg(all())))] |
244 | Vsock = libc::AF_VSOCK, |
245 | /// ARPANet IMP addresses |
246 | #[cfg (any( |
247 | target_os = "dragonfly" , |
248 | target_os = "freebsd" , |
249 | target_os = "ios" , |
250 | target_os = "macos" , |
251 | target_os = "netbsd" , |
252 | target_os = "openbsd" |
253 | ))] |
254 | #[cfg_attr (docsrs, doc(cfg(all())))] |
255 | ImpLink = libc::AF_IMPLINK, |
256 | /// PUP protocols, e.g. BSP |
257 | #[cfg (any( |
258 | target_os = "dragonfly" , |
259 | target_os = "freebsd" , |
260 | target_os = "ios" , |
261 | target_os = "macos" , |
262 | target_os = "netbsd" , |
263 | target_os = "openbsd" |
264 | ))] |
265 | #[cfg_attr (docsrs, doc(cfg(all())))] |
266 | Pup = libc::AF_PUP, |
267 | /// MIT CHAOS protocols |
268 | #[cfg (any( |
269 | target_os = "dragonfly" , |
270 | target_os = "freebsd" , |
271 | target_os = "ios" , |
272 | target_os = "macos" , |
273 | target_os = "netbsd" , |
274 | target_os = "openbsd" |
275 | ))] |
276 | #[cfg_attr (docsrs, doc(cfg(all())))] |
277 | Chaos = libc::AF_CHAOS, |
278 | /// Novell and Xerox protocol |
279 | #[cfg (any( |
280 | target_os = "ios" , |
281 | target_os = "macos" , |
282 | target_os = "netbsd" , |
283 | target_os = "openbsd" |
284 | ))] |
285 | #[cfg_attr (docsrs, doc(cfg(all())))] |
286 | Ns = libc::AF_NS, |
287 | #[allow (missing_docs)] // Not documented anywhere that I can find |
288 | #[cfg (any( |
289 | target_os = "dragonfly" , |
290 | target_os = "freebsd" , |
291 | target_os = "ios" , |
292 | target_os = "macos" , |
293 | target_os = "netbsd" , |
294 | target_os = "openbsd" |
295 | ))] |
296 | #[cfg_attr (docsrs, doc(cfg(all())))] |
297 | Iso = libc::AF_ISO, |
298 | /// Bell Labs virtual circuit switch ? |
299 | #[cfg (any( |
300 | target_os = "dragonfly" , |
301 | target_os = "freebsd" , |
302 | target_os = "ios" , |
303 | target_os = "macos" , |
304 | target_os = "netbsd" , |
305 | target_os = "openbsd" |
306 | ))] |
307 | #[cfg_attr (docsrs, doc(cfg(all())))] |
308 | Datakit = libc::AF_DATAKIT, |
309 | /// CCITT protocols, X.25 etc |
310 | #[cfg (any( |
311 | target_os = "dragonfly" , |
312 | target_os = "freebsd" , |
313 | target_os = "ios" , |
314 | target_os = "macos" , |
315 | target_os = "netbsd" , |
316 | target_os = "openbsd" |
317 | ))] |
318 | #[cfg_attr (docsrs, doc(cfg(all())))] |
319 | Ccitt = libc::AF_CCITT, |
320 | /// DEC Direct data link interface |
321 | #[cfg (any( |
322 | target_os = "dragonfly" , |
323 | target_os = "freebsd" , |
324 | target_os = "ios" , |
325 | target_os = "macos" , |
326 | target_os = "netbsd" , |
327 | target_os = "openbsd" |
328 | ))] |
329 | #[cfg_attr (docsrs, doc(cfg(all())))] |
330 | Dli = libc::AF_DLI, |
331 | #[allow (missing_docs)] // Not documented anywhere that I can find |
332 | #[cfg (any( |
333 | target_os = "dragonfly" , |
334 | target_os = "freebsd" , |
335 | target_os = "ios" , |
336 | target_os = "macos" , |
337 | target_os = "netbsd" , |
338 | target_os = "openbsd" |
339 | ))] |
340 | #[cfg_attr (docsrs, doc(cfg(all())))] |
341 | Lat = libc::AF_LAT, |
342 | /// NSC Hyperchannel |
343 | #[cfg (any( |
344 | target_os = "dragonfly" , |
345 | target_os = "freebsd" , |
346 | target_os = "ios" , |
347 | target_os = "macos" , |
348 | target_os = "netbsd" , |
349 | target_os = "openbsd" |
350 | ))] |
351 | #[cfg_attr (docsrs, doc(cfg(all())))] |
352 | Hylink = libc::AF_HYLINK, |
353 | /// Link layer interface |
354 | #[cfg (any( |
355 | target_os = "dragonfly" , |
356 | target_os = "freebsd" , |
357 | target_os = "ios" , |
358 | target_os = "macos" , |
359 | target_os = "illumos" , |
360 | target_os = "netbsd" , |
361 | target_os = "openbsd" |
362 | ))] |
363 | #[cfg_attr (docsrs, doc(cfg(all())))] |
364 | Link = libc::AF_LINK, |
365 | /// connection-oriented IP, aka ST II |
366 | #[cfg (any( |
367 | target_os = "dragonfly" , |
368 | target_os = "freebsd" , |
369 | target_os = "ios" , |
370 | target_os = "macos" , |
371 | target_os = "netbsd" , |
372 | target_os = "openbsd" |
373 | ))] |
374 | #[cfg_attr (docsrs, doc(cfg(all())))] |
375 | Coip = libc::AF_COIP, |
376 | /// Computer Network Technology |
377 | #[cfg (any( |
378 | target_os = "dragonfly" , |
379 | target_os = "freebsd" , |
380 | target_os = "ios" , |
381 | target_os = "macos" , |
382 | target_os = "netbsd" , |
383 | target_os = "openbsd" |
384 | ))] |
385 | #[cfg_attr (docsrs, doc(cfg(all())))] |
386 | Cnt = libc::AF_CNT, |
387 | /// Native ATM access |
388 | #[cfg (any( |
389 | target_os = "dragonfly" , |
390 | target_os = "freebsd" , |
391 | target_os = "ios" , |
392 | target_os = "macos" , |
393 | target_os = "netbsd" , |
394 | target_os = "openbsd" |
395 | ))] |
396 | #[cfg_attr (docsrs, doc(cfg(all())))] |
397 | Natm = libc::AF_NATM, |
398 | /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html)) |
399 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
400 | #[cfg_attr (docsrs, doc(cfg(all())))] |
401 | Unspec = libc::AF_UNSPEC, |
402 | } |
403 | |
404 | impl AddressFamily { |
405 | /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from |
406 | /// the `sa_family` field of a `sockaddr`. |
407 | /// |
408 | /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet |
409 | /// and System. Returns None for unsupported or unknown address families. |
410 | pub const fn from_i32(family: i32) -> Option<AddressFamily> { |
411 | match family { |
412 | libc::AF_UNIX => Some(AddressFamily::Unix), |
413 | libc::AF_INET => Some(AddressFamily::Inet), |
414 | libc::AF_INET6 => Some(AddressFamily::Inet6), |
415 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
416 | libc::AF_NETLINK => Some(AddressFamily::Netlink), |
417 | #[cfg (any(target_os = "macos" , target_os = "macos" ))] |
418 | libc::AF_SYSTEM => Some(AddressFamily::System), |
419 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
420 | libc::AF_PACKET => Some(AddressFamily::Packet), |
421 | #[cfg (any( |
422 | target_os = "dragonfly" , |
423 | target_os = "freebsd" , |
424 | target_os = "ios" , |
425 | target_os = "macos" , |
426 | target_os = "netbsd" , |
427 | target_os = "illumos" , |
428 | target_os = "openbsd" |
429 | ))] |
430 | libc::AF_LINK => Some(AddressFamily::Link), |
431 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
432 | libc::AF_VSOCK => Some(AddressFamily::Vsock), |
433 | _ => None, |
434 | } |
435 | } |
436 | } |
437 | |
438 | feature! { |
439 | #![feature = "net" ] |
440 | |
441 | #[deprecated ( |
442 | since = "0.24.0" , |
443 | note = "use SockaddrIn, SockaddrIn6, or SockaddrStorage instead" |
444 | )] |
445 | #[allow (missing_docs)] // Since they're all deprecated anyway |
446 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
447 | pub enum InetAddr { |
448 | V4(libc::sockaddr_in), |
449 | V6(libc::sockaddr_in6), |
450 | } |
451 | |
452 | #[allow (missing_docs)] // It's deprecated anyway |
453 | #[allow (deprecated)] |
454 | impl InetAddr { |
455 | #[allow (clippy::needless_update)] // It isn't needless on all OSes |
456 | pub fn from_std(std: &net::SocketAddr) -> InetAddr { |
457 | match *std { |
458 | net::SocketAddr::V4(ref addr) => { |
459 | InetAddr::V4(libc::sockaddr_in { |
460 | #[cfg (any(target_os = "dragonfly" , target_os = "freebsd" , |
461 | target_os = "haiku" , target_os = "hermit" , |
462 | target_os = "ios" , target_os = "macos" , |
463 | target_os = "netbsd" , target_os = "openbsd" ))] |
464 | sin_len: mem::size_of::<libc::sockaddr_in>() as u8, |
465 | sin_family: AddressFamily::Inet as sa_family_t, |
466 | sin_port: addr.port().to_be(), // network byte order |
467 | sin_addr: Ipv4Addr::from_std(addr.ip()).0, |
468 | .. unsafe { mem::zeroed() } |
469 | }) |
470 | } |
471 | net::SocketAddr::V6(ref addr) => { |
472 | InetAddr::V6(libc::sockaddr_in6 { |
473 | #[cfg (any(target_os = "dragonfly" , target_os = "freebsd" , |
474 | target_os = "haiku" , target_os = "hermit" , |
475 | target_os = "ios" , target_os = "macos" , |
476 | target_os = "netbsd" , target_os = "openbsd" ))] |
477 | sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8, |
478 | sin6_family: AddressFamily::Inet6 as sa_family_t, |
479 | sin6_port: addr.port().to_be(), // network byte order |
480 | sin6_addr: Ipv6Addr::from_std(addr.ip()).0, |
481 | sin6_flowinfo: addr.flowinfo(), // host byte order |
482 | sin6_scope_id: addr.scope_id(), // host byte order |
483 | .. unsafe { mem::zeroed() } |
484 | }) |
485 | } |
486 | } |
487 | } |
488 | |
489 | #[allow (clippy::needless_update)] // It isn't needless on all OSes |
490 | pub fn new(ip: IpAddr, port: u16) -> InetAddr { |
491 | match ip { |
492 | IpAddr::V4(ref ip) => { |
493 | InetAddr::V4(libc::sockaddr_in { |
494 | sin_family: AddressFamily::Inet as sa_family_t, |
495 | sin_port: port.to_be(), |
496 | sin_addr: ip.0, |
497 | .. unsafe { mem::zeroed() } |
498 | }) |
499 | } |
500 | IpAddr::V6(ref ip) => { |
501 | InetAddr::V6(libc::sockaddr_in6 { |
502 | sin6_family: AddressFamily::Inet6 as sa_family_t, |
503 | sin6_port: port.to_be(), |
504 | sin6_addr: ip.0, |
505 | .. unsafe { mem::zeroed() } |
506 | }) |
507 | } |
508 | } |
509 | } |
510 | /// Gets the IP address associated with this socket address. |
511 | pub const fn ip(&self) -> IpAddr { |
512 | match *self { |
513 | InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)), |
514 | InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)), |
515 | } |
516 | } |
517 | |
518 | /// Gets the port number associated with this socket address |
519 | pub const fn port(&self) -> u16 { |
520 | match *self { |
521 | InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port), |
522 | InetAddr::V4(ref sa) => u16::from_be(sa.sin_port), |
523 | } |
524 | } |
525 | |
526 | pub fn to_std(&self) -> net::SocketAddr { |
527 | match *self { |
528 | InetAddr::V4(ref sa) => net::SocketAddr::V4( |
529 | net::SocketAddrV4::new( |
530 | Ipv4Addr(sa.sin_addr).to_std(), |
531 | self.port())), |
532 | InetAddr::V6(ref sa) => net::SocketAddr::V6( |
533 | net::SocketAddrV6::new( |
534 | Ipv6Addr(sa.sin6_addr).to_std(), |
535 | self.port(), |
536 | sa.sin6_flowinfo, |
537 | sa.sin6_scope_id)), |
538 | } |
539 | } |
540 | |
541 | #[deprecated (since = "0.23.0" , note = "use .to_string() instead" )] |
542 | pub fn to_str(&self) -> String { |
543 | format!(" {}" , self) |
544 | } |
545 | } |
546 | |
547 | #[allow (deprecated)] |
548 | impl fmt::Display for InetAddr { |
549 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
550 | match *self { |
551 | InetAddr::V4(_) => write!(f, " {}: {}" , self.ip(), self.port()), |
552 | InetAddr::V6(_) => write!(f, "[ {}]: {}" , self.ip(), self.port()), |
553 | } |
554 | } |
555 | } |
556 | |
557 | /* |
558 | * |
559 | * ===== IpAddr ===== |
560 | * |
561 | */ |
562 | #[allow (missing_docs)] // Since they're all deprecated anyway |
563 | #[allow (deprecated)] |
564 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
565 | #[deprecated ( |
566 | since = "0.24.0" , |
567 | note = "Use std::net::IpAddr instead" |
568 | )] |
569 | pub enum IpAddr { |
570 | V4(Ipv4Addr), |
571 | V6(Ipv6Addr), |
572 | } |
573 | |
574 | #[allow (deprecated)] |
575 | #[allow (missing_docs)] // Since they're all deprecated anyway |
576 | impl IpAddr { |
577 | /// Create a new IpAddr that contains an IPv4 address. |
578 | /// |
579 | /// The result will represent the IP address a.b.c.d |
580 | pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr { |
581 | IpAddr::V4(Ipv4Addr::new(a, b, c, d)) |
582 | } |
583 | |
584 | /// Create a new IpAddr that contains an IPv6 address. |
585 | /// |
586 | /// The result will represent the IP address a:b:c:d:e:f |
587 | #[allow (clippy::many_single_char_names)] |
588 | #[allow (clippy::too_many_arguments)] |
589 | pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr { |
590 | IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h)) |
591 | } |
592 | |
593 | pub fn from_std(std: &net::IpAddr) -> IpAddr { |
594 | match *std { |
595 | net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)), |
596 | net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)), |
597 | } |
598 | } |
599 | |
600 | pub const fn to_std(&self) -> net::IpAddr { |
601 | match *self { |
602 | IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()), |
603 | IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()), |
604 | } |
605 | } |
606 | } |
607 | |
608 | #[allow (deprecated)] |
609 | impl fmt::Display for IpAddr { |
610 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
611 | match *self { |
612 | IpAddr::V4(ref v4) => v4.fmt(f), |
613 | IpAddr::V6(ref v6) => v6.fmt(f) |
614 | } |
615 | } |
616 | } |
617 | |
618 | /* |
619 | * |
620 | * ===== Ipv4Addr ===== |
621 | * |
622 | */ |
623 | |
624 | #[deprecated ( |
625 | since = "0.24.0" , |
626 | note = "Use std::net::Ipv4Addr instead" |
627 | )] |
628 | #[allow (missing_docs)] // Since they're all deprecated anyway |
629 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
630 | #[repr (transparent)] |
631 | pub struct Ipv4Addr(pub libc::in_addr); |
632 | |
633 | #[allow (deprecated)] |
634 | #[allow (missing_docs)] // Since they're all deprecated anyway |
635 | impl Ipv4Addr { |
636 | #[allow (clippy::identity_op)] // More readable this way |
637 | pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { |
638 | let ip = (((a as u32) << 24) | |
639 | ((b as u32) << 16) | |
640 | ((c as u32) << 8) | |
641 | ((d as u32) << 0)).to_be(); |
642 | |
643 | Ipv4Addr(libc::in_addr { s_addr: ip }) |
644 | } |
645 | |
646 | // Use pass by reference for symmetry with Ipv6Addr::from_std |
647 | #[allow (clippy::trivially_copy_pass_by_ref)] |
648 | pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr { |
649 | let bits = std.octets(); |
650 | Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3]) |
651 | } |
652 | |
653 | pub const fn any() -> Ipv4Addr { |
654 | Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY }) |
655 | } |
656 | |
657 | pub const fn octets(self) -> [u8; 4] { |
658 | let bits = u32::from_be(self.0.s_addr); |
659 | [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] |
660 | } |
661 | |
662 | pub const fn to_std(self) -> net::Ipv4Addr { |
663 | let bits = self.octets(); |
664 | net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3]) |
665 | } |
666 | } |
667 | |
668 | #[allow (deprecated)] |
669 | impl fmt::Display for Ipv4Addr { |
670 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
671 | let octets = self.octets(); |
672 | write!(fmt, " {}. {}. {}. {}" , octets[0], octets[1], octets[2], octets[3]) |
673 | } |
674 | } |
675 | |
676 | /* |
677 | * |
678 | * ===== Ipv6Addr ===== |
679 | * |
680 | */ |
681 | |
682 | #[deprecated ( |
683 | since = "0.24.0" , |
684 | note = "Use std::net::Ipv6Addr instead" |
685 | )] |
686 | #[allow (missing_docs)] // Since they're all deprecated anyway |
687 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
688 | #[repr (transparent)] |
689 | pub struct Ipv6Addr(pub libc::in6_addr); |
690 | |
691 | // Note that IPv6 addresses are stored in big endian order on all architectures. |
692 | // See https://tools.ietf.org/html/rfc1700 or consult your favorite search |
693 | // engine. |
694 | |
695 | macro_rules! to_u8_array { |
696 | ($($num:ident),*) => { |
697 | [ $(($num>>8) as u8, ($num&0xff) as u8,)* ] |
698 | } |
699 | } |
700 | |
701 | macro_rules! to_u16_array { |
702 | ($slf:ident, $($first:expr, $second:expr),*) => { |
703 | [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*] |
704 | } |
705 | } |
706 | |
707 | #[allow (deprecated)] |
708 | #[allow (missing_docs)] // Since they're all deprecated anyway |
709 | impl Ipv6Addr { |
710 | #[allow (clippy::many_single_char_names)] |
711 | #[allow (clippy::too_many_arguments)] |
712 | pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { |
713 | Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)}) |
714 | } |
715 | |
716 | pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr { |
717 | let s = std.segments(); |
718 | Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]) |
719 | } |
720 | |
721 | /// Return the eight 16-bit segments that make up this address |
722 | pub const fn segments(&self) -> [u16; 8] { |
723 | to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) |
724 | } |
725 | |
726 | pub const fn to_std(&self) -> net::Ipv6Addr { |
727 | let s = self.segments(); |
728 | net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]) |
729 | } |
730 | } |
731 | |
732 | #[allow (deprecated)] |
733 | impl fmt::Display for Ipv6Addr { |
734 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
735 | self.to_std().fmt(fmt) |
736 | } |
737 | } |
738 | } |
739 | |
740 | /// A wrapper around `sockaddr_un`. |
741 | #[derive (Clone, Copy, Debug)] |
742 | #[repr (C)] |
743 | pub struct UnixAddr { |
744 | // INVARIANT: sun & sun_len are valid as defined by docs for from_raw_parts |
745 | sun: libc::sockaddr_un, |
746 | /// The length of the valid part of `sun`, including the sun_family field |
747 | /// but excluding any trailing nul. |
748 | // On the BSDs, this field is built into sun |
749 | #[cfg (any( |
750 | target_os = "android" , |
751 | target_os = "fuchsia" , |
752 | target_os = "illumos" , |
753 | target_os = "linux" |
754 | ))] |
755 | sun_len: u8, |
756 | } |
757 | |
758 | // linux man page unix(7) says there are 3 kinds of unix socket: |
759 | // pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1 |
760 | // unnamed: addrlen = sizeof(sa_family_t) |
761 | // abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))] |
762 | // |
763 | // what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path) |
764 | #[derive (PartialEq, Eq, Hash)] |
765 | enum UnixAddrKind<'a> { |
766 | Pathname(&'a Path), |
767 | Unnamed, |
768 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
769 | Abstract(&'a [u8]), |
770 | } |
771 | impl<'a> UnixAddrKind<'a> { |
772 | /// Safety: sun & sun_len must be valid |
773 | #[allow (clippy::unnecessary_cast)] // Not unnecessary on all platforms |
774 | unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self { |
775 | assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path)); |
776 | let path_len = |
777 | sun_len as usize - offset_of!(libc::sockaddr_un, sun_path); |
778 | if path_len == 0 { |
779 | return Self::Unnamed; |
780 | } |
781 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
782 | if sun.sun_path[0] == 0 { |
783 | let name = slice::from_raw_parts( |
784 | sun.sun_path.as_ptr().add(1) as *const u8, |
785 | path_len - 1, |
786 | ); |
787 | return Self::Abstract(name); |
788 | } |
789 | let pathname = |
790 | slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len); |
791 | if pathname.last() == Some(&0) { |
792 | // A trailing NUL is not considered part of the path, and it does |
793 | // not need to be included in the addrlen passed to functions like |
794 | // bind(). However, Linux adds a trailing NUL, even if one was not |
795 | // originally present, when returning addrs from functions like |
796 | // getsockname() (the BSDs do not do that). So we need to filter |
797 | // out any trailing NUL here, so sockaddrs can round-trip through |
798 | // the kernel and still compare equal. |
799 | Self::Pathname(Path::new(OsStr::from_bytes( |
800 | &pathname[0..pathname.len() - 1], |
801 | ))) |
802 | } else { |
803 | Self::Pathname(Path::new(OsStr::from_bytes(pathname))) |
804 | } |
805 | } |
806 | } |
807 | |
808 | impl UnixAddr { |
809 | /// Create a new sockaddr_un representing a filesystem path. |
810 | #[allow (clippy::unnecessary_cast)] // Not unnecessary on all platforms |
811 | pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> { |
812 | path.with_nix_path(|cstr| unsafe { |
813 | let mut ret = libc::sockaddr_un { |
814 | sun_family: AddressFamily::Unix as sa_family_t, |
815 | ..mem::zeroed() |
816 | }; |
817 | |
818 | let bytes = cstr.to_bytes(); |
819 | |
820 | if bytes.len() >= ret.sun_path.len() { |
821 | return Err(Errno::ENAMETOOLONG); |
822 | } |
823 | |
824 | let sun_len = (bytes.len() |
825 | + offset_of!(libc::sockaddr_un, sun_path)) |
826 | .try_into() |
827 | .unwrap(); |
828 | |
829 | #[cfg (any( |
830 | target_os = "dragonfly" , |
831 | target_os = "freebsd" , |
832 | target_os = "ios" , |
833 | target_os = "macos" , |
834 | target_os = "netbsd" , |
835 | target_os = "openbsd" |
836 | ))] |
837 | { |
838 | ret.sun_len = sun_len; |
839 | } |
840 | ptr::copy_nonoverlapping( |
841 | bytes.as_ptr(), |
842 | ret.sun_path.as_mut_ptr() as *mut u8, |
843 | bytes.len(), |
844 | ); |
845 | |
846 | Ok(UnixAddr::from_raw_parts(ret, sun_len)) |
847 | })? |
848 | } |
849 | |
850 | /// Create a new `sockaddr_un` representing an address in the "abstract namespace". |
851 | /// |
852 | /// The leading nul byte for the abstract namespace is automatically added; |
853 | /// thus the input `path` is expected to be the bare name, not NUL-prefixed. |
854 | /// This is a Linux-specific extension, primarily used to allow chrooted |
855 | /// processes to communicate with processes having a different filesystem view. |
856 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
857 | #[cfg_attr (docsrs, doc(cfg(all())))] |
858 | #[allow (clippy::unnecessary_cast)] // Not unnecessary on all platforms |
859 | pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> { |
860 | unsafe { |
861 | let mut ret = libc::sockaddr_un { |
862 | sun_family: AddressFamily::Unix as sa_family_t, |
863 | ..mem::zeroed() |
864 | }; |
865 | |
866 | if path.len() >= ret.sun_path.len() { |
867 | return Err(Errno::ENAMETOOLONG); |
868 | } |
869 | let sun_len = |
870 | (path.len() + 1 + offset_of!(libc::sockaddr_un, sun_path)) |
871 | .try_into() |
872 | .unwrap(); |
873 | |
874 | // Abstract addresses are represented by sun_path[0] == |
875 | // b'\0', so copy starting one byte in. |
876 | ptr::copy_nonoverlapping( |
877 | path.as_ptr(), |
878 | ret.sun_path.as_mut_ptr().offset(1) as *mut u8, |
879 | path.len(), |
880 | ); |
881 | |
882 | Ok(UnixAddr::from_raw_parts(ret, sun_len)) |
883 | } |
884 | } |
885 | |
886 | /// Create a new `sockaddr_un` representing an "unnamed" unix socket address. |
887 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
888 | #[cfg_attr (docsrs, doc(cfg(all())))] |
889 | pub fn new_unnamed() -> UnixAddr { |
890 | let ret = libc::sockaddr_un { |
891 | sun_family: AddressFamily::Unix as sa_family_t, |
892 | .. unsafe { mem::zeroed() } |
893 | }; |
894 | |
895 | let sun_len: u8 = offset_of!(libc::sockaddr_un, sun_path).try_into().unwrap(); |
896 | |
897 | unsafe { UnixAddr::from_raw_parts(ret, sun_len) } |
898 | } |
899 | |
900 | /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `sun_len` |
901 | /// is the size of the valid portion of the struct, excluding any trailing |
902 | /// NUL. |
903 | /// |
904 | /// # Safety |
905 | /// This pair of sockaddr_un & sun_len must be a valid unix addr, which |
906 | /// means: |
907 | /// - sun_len >= offset_of(sockaddr_un, sun_path) |
908 | /// - sun_len <= sockaddr_un.sun_path.len() - offset_of(sockaddr_un, sun_path) |
909 | /// - if this is a unix addr with a pathname, sun.sun_path is a |
910 | /// fs path, not necessarily nul-terminated. |
911 | pub(crate) unsafe fn from_raw_parts( |
912 | sun: libc::sockaddr_un, |
913 | sun_len: u8, |
914 | ) -> UnixAddr { |
915 | cfg_if! { |
916 | if #[cfg(any(target_os = "android" , |
917 | target_os = "fuchsia" , |
918 | target_os = "illumos" , |
919 | target_os = "linux" |
920 | ))] |
921 | { |
922 | UnixAddr { sun, sun_len } |
923 | } else { |
924 | assert_eq!(sun_len, sun.sun_len); |
925 | UnixAddr {sun} |
926 | } |
927 | } |
928 | } |
929 | |
930 | fn kind(&self) -> UnixAddrKind<'_> { |
931 | // SAFETY: our sockaddr is always valid because of the invariant on the struct |
932 | unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) } |
933 | } |
934 | |
935 | /// If this address represents a filesystem path, return that path. |
936 | pub fn path(&self) -> Option<&Path> { |
937 | match self.kind() { |
938 | UnixAddrKind::Pathname(path) => Some(path), |
939 | _ => None, |
940 | } |
941 | } |
942 | |
943 | /// If this address represents an abstract socket, return its name. |
944 | /// |
945 | /// For abstract sockets only the bare name is returned, without the |
946 | /// leading NUL byte. `None` is returned for unnamed or path-backed sockets. |
947 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
948 | #[cfg_attr (docsrs, doc(cfg(all())))] |
949 | pub fn as_abstract(&self) -> Option<&[u8]> { |
950 | match self.kind() { |
951 | UnixAddrKind::Abstract(name) => Some(name), |
952 | _ => None, |
953 | } |
954 | } |
955 | |
956 | /// Check if this address is an "unnamed" unix socket address. |
957 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
958 | #[cfg_attr (docsrs, doc(cfg(all())))] |
959 | #[inline ] |
960 | pub fn is_unnamed(&self) -> bool { |
961 | matches!(self.kind(), UnixAddrKind::Unnamed) |
962 | } |
963 | |
964 | /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)` |
965 | #[inline ] |
966 | pub fn path_len(&self) -> usize { |
967 | self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path) |
968 | } |
969 | /// Returns a pointer to the raw `sockaddr_un` struct |
970 | #[inline ] |
971 | pub fn as_ptr(&self) -> *const libc::sockaddr_un { |
972 | &self.sun |
973 | } |
974 | /// Returns a mutable pointer to the raw `sockaddr_un` struct |
975 | #[inline ] |
976 | pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un { |
977 | &mut self.sun |
978 | } |
979 | |
980 | fn sun_len(&self) -> u8 { |
981 | cfg_if! { |
982 | if #[cfg(any(target_os = "android" , |
983 | target_os = "fuchsia" , |
984 | target_os = "illumos" , |
985 | target_os = "linux" |
986 | ))] |
987 | { |
988 | self.sun_len |
989 | } else { |
990 | self.sun.sun_len |
991 | } |
992 | } |
993 | } |
994 | } |
995 | |
996 | impl private::SockaddrLikePriv for UnixAddr {} |
997 | impl SockaddrLike for UnixAddr { |
998 | #[cfg (any( |
999 | target_os = "android" , |
1000 | target_os = "fuchsia" , |
1001 | target_os = "illumos" , |
1002 | target_os = "linux" |
1003 | ))] |
1004 | fn len(&self) -> libc::socklen_t { |
1005 | self.sun_len.into() |
1006 | } |
1007 | |
1008 | unsafe fn from_raw( |
1009 | addr: *const libc::sockaddr, |
1010 | len: Option<libc::socklen_t>, |
1011 | ) -> Option<Self> |
1012 | where |
1013 | Self: Sized, |
1014 | { |
1015 | if let Some(l) = len { |
1016 | if (l as usize) < offset_of!(libc::sockaddr_un, sun_path) |
1017 | || l > u8::MAX as libc::socklen_t |
1018 | { |
1019 | return None; |
1020 | } |
1021 | } |
1022 | if (*addr).sa_family as i32 != libc::AF_UNIX { |
1023 | return None; |
1024 | } |
1025 | let mut su: libc::sockaddr_un = mem::zeroed(); |
1026 | let sup = &mut su as *mut libc::sockaddr_un as *mut u8; |
1027 | cfg_if! { |
1028 | if #[cfg(any(target_os = "android" , |
1029 | target_os = "fuchsia" , |
1030 | target_os = "illumos" , |
1031 | target_os = "linux" |
1032 | ))] { |
1033 | let su_len = len.unwrap_or( |
1034 | mem::size_of::<libc::sockaddr_un>() as libc::socklen_t |
1035 | ); |
1036 | } else { |
1037 | let su_len = len.unwrap_or((*addr).sa_len as libc::socklen_t); |
1038 | } |
1039 | }; |
1040 | ptr::copy(addr as *const u8, sup, su_len as usize); |
1041 | Some(Self::from_raw_parts(su, su_len as u8)) |
1042 | } |
1043 | |
1044 | fn size() -> libc::socklen_t |
1045 | where |
1046 | Self: Sized, |
1047 | { |
1048 | mem::size_of::<libc::sockaddr_un>() as libc::socklen_t |
1049 | } |
1050 | |
1051 | unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> { |
1052 | // `new_length` is only used on some platforms, so it must be provided even when not used |
1053 | #![allow (unused_variables)] |
1054 | cfg_if! { |
1055 | if #[cfg(any(target_os = "android" , |
1056 | target_os = "fuchsia" , |
1057 | target_os = "illumos" , |
1058 | target_os = "linux" , |
1059 | target_os = "redox" , |
1060 | ))] { |
1061 | self.sun_len = new_length as u8; |
1062 | } |
1063 | }; |
1064 | Ok(()) |
1065 | } |
1066 | } |
1067 | |
1068 | impl AsRef<libc::sockaddr_un> for UnixAddr { |
1069 | fn as_ref(&self) -> &libc::sockaddr_un { |
1070 | &self.sun |
1071 | } |
1072 | } |
1073 | |
1074 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1075 | fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result { |
1076 | use fmt::Write; |
1077 | f.write_str(data:"@ \"" )?; |
1078 | for &b: u8 in abs { |
1079 | use fmt::Display; |
1080 | char::from(b).escape_default().fmt(f)?; |
1081 | } |
1082 | f.write_char('"' )?; |
1083 | Ok(()) |
1084 | } |
1085 | |
1086 | impl fmt::Display for UnixAddr { |
1087 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1088 | match self.kind() { |
1089 | UnixAddrKind::Pathname(path: &Path) => path.display().fmt(f), |
1090 | UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>" ), |
1091 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1092 | UnixAddrKind::Abstract(name: &[u8]) => fmt_abstract(abs:name, f), |
1093 | } |
1094 | } |
1095 | } |
1096 | |
1097 | impl PartialEq for UnixAddr { |
1098 | fn eq(&self, other: &UnixAddr) -> bool { |
1099 | self.kind() == other.kind() |
1100 | } |
1101 | } |
1102 | |
1103 | impl Eq for UnixAddr {} |
1104 | |
1105 | impl Hash for UnixAddr { |
1106 | fn hash<H: Hasher>(&self, s: &mut H) { |
1107 | self.kind().hash(state:s) |
1108 | } |
1109 | } |
1110 | |
1111 | /// Anything that, in C, can be cast back and forth to `sockaddr`. |
1112 | /// |
1113 | /// Most implementors also implement `AsRef<libc::XXX>` to access their |
1114 | /// inner type read-only. |
1115 | #[allow (clippy::len_without_is_empty)] |
1116 | pub trait SockaddrLike: private::SockaddrLikePriv { |
1117 | /// Returns a raw pointer to the inner structure. Useful for FFI. |
1118 | fn as_ptr(&self) -> *const libc::sockaddr { |
1119 | self as *const Self as *const libc::sockaddr |
1120 | } |
1121 | |
1122 | /// Unsafe constructor from a variable length source |
1123 | /// |
1124 | /// Some C APIs from provide `len`, and others do not. If it's provided it |
1125 | /// will be validated. If not, it will be guessed based on the family. |
1126 | /// |
1127 | /// # Arguments |
1128 | /// |
1129 | /// - `addr`: raw pointer to something that can be cast to a |
1130 | /// `libc::sockaddr`. For example, `libc::sockaddr_in`, |
1131 | /// `libc::sockaddr_in6`, etc. |
1132 | /// - `len`: For fixed-width types like `sockaddr_in`, it will be |
1133 | /// validated if present and ignored if not. For variable-width |
1134 | /// types it is required and must be the total length of valid |
1135 | /// data. For example, if `addr` points to a |
1136 | /// named `sockaddr_un`, then `len` must be the length of the |
1137 | /// structure up to but not including the trailing NUL. |
1138 | /// |
1139 | /// # Safety |
1140 | /// |
1141 | /// `addr` must be valid for the specific type of sockaddr. `len`, if |
1142 | /// present, must not exceed the length of valid data in `addr`. |
1143 | unsafe fn from_raw( |
1144 | addr: *const libc::sockaddr, |
1145 | len: Option<libc::socklen_t>, |
1146 | ) -> Option<Self> |
1147 | where |
1148 | Self: Sized; |
1149 | |
1150 | /// Return the address family of this socket |
1151 | /// |
1152 | /// # Examples |
1153 | /// One common use is to match on the family of a union type, like this: |
1154 | /// ``` |
1155 | /// # use nix::sys::socket::*; |
1156 | /// let fd = socket(AddressFamily::Inet, SockType::Stream, |
1157 | /// SockFlag::empty(), None).unwrap(); |
1158 | /// let ss: SockaddrStorage = getsockname(fd).unwrap(); |
1159 | /// match ss.family().unwrap() { |
1160 | /// AddressFamily::Inet => println!("{}" , ss.as_sockaddr_in().unwrap()), |
1161 | /// AddressFamily::Inet6 => println!("{}" , ss.as_sockaddr_in6().unwrap()), |
1162 | /// _ => println!("Unexpected address family" ) |
1163 | /// } |
1164 | /// ``` |
1165 | fn family(&self) -> Option<AddressFamily> { |
1166 | // Safe since all implementors have a sa_family field at the same |
1167 | // address, and they're all repr(C) |
1168 | AddressFamily::from_i32(unsafe { |
1169 | (*(self as *const Self as *const libc::sockaddr)).sa_family as i32 |
1170 | }) |
1171 | } |
1172 | |
1173 | cfg_if! { |
1174 | if #[cfg(any(target_os = "dragonfly" , |
1175 | target_os = "freebsd" , |
1176 | target_os = "ios" , |
1177 | target_os = "macos" , |
1178 | target_os = "netbsd" , |
1179 | target_os = "openbsd" ))] { |
1180 | /// Return the length of valid data in the sockaddr structure. |
1181 | /// |
1182 | /// For fixed-size sockaddrs, this should be the size of the |
1183 | /// structure. But for variable-sized types like [`UnixAddr`] it |
1184 | /// may be less. |
1185 | fn len(&self) -> libc::socklen_t { |
1186 | // Safe since all implementors have a sa_len field at the same |
1187 | // address, and they're all repr(transparent). |
1188 | // Robust for all implementors. |
1189 | unsafe { |
1190 | (*(self as *const Self as *const libc::sockaddr)).sa_len |
1191 | }.into() |
1192 | } |
1193 | } else { |
1194 | /// Return the length of valid data in the sockaddr structure. |
1195 | /// |
1196 | /// For fixed-size sockaddrs, this should be the size of the |
1197 | /// structure. But for variable-sized types like [`UnixAddr`] it |
1198 | /// may be less. |
1199 | fn len(&self) -> libc::socklen_t { |
1200 | // No robust default implementation is possible without an |
1201 | // sa_len field. Implementors with a variable size must |
1202 | // override this method. |
1203 | mem::size_of_val(self) as libc::socklen_t |
1204 | } |
1205 | } |
1206 | } |
1207 | |
1208 | /// Return the available space in the structure |
1209 | fn size() -> libc::socklen_t |
1210 | where |
1211 | Self: Sized, |
1212 | { |
1213 | mem::size_of::<Self>() as libc::socklen_t |
1214 | } |
1215 | |
1216 | /// Set the length of this socket address |
1217 | /// |
1218 | /// This method may only be called on socket addresses whose lengths are dynamic, and it |
1219 | /// returns an error if called on a type whose length is static. |
1220 | /// |
1221 | /// # Safety |
1222 | /// |
1223 | /// `new_length` must be a valid length for this type of address. Specifically, reads of that |
1224 | /// length from `self` must be valid. |
1225 | #[doc (hidden)] |
1226 | unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> { |
1227 | Err(SocketAddressLengthNotDynamic) |
1228 | } |
1229 | } |
1230 | |
1231 | /// The error returned by [`SockaddrLike::set_length`] on an address whose length is statically |
1232 | /// fixed. |
1233 | #[derive (Copy, Clone, Debug)] |
1234 | pub struct SocketAddressLengthNotDynamic; |
1235 | impl fmt::Display for SocketAddressLengthNotDynamic { |
1236 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1237 | f.write_str(data:"Attempted to set length on socket whose length is statically fixed" ) |
1238 | } |
1239 | } |
1240 | impl std::error::Error for SocketAddressLengthNotDynamic {} |
1241 | |
1242 | impl private::SockaddrLikePriv for () { |
1243 | fn as_mut_ptr(&mut self) -> *mut libc::sockaddr { |
1244 | ptr::null_mut() |
1245 | } |
1246 | } |
1247 | |
1248 | /// `()` can be used in place of a real Sockaddr when no address is expected, |
1249 | /// for example for a field of `Option<S> where S: SockaddrLike`. |
1250 | // If this RFC ever stabilizes, then ! will be a better choice. |
1251 | // https://github.com/rust-lang/rust/issues/35121 |
1252 | impl SockaddrLike for () { |
1253 | fn as_ptr(&self) -> *const libc::sockaddr { |
1254 | ptr::null() |
1255 | } |
1256 | |
1257 | unsafe fn from_raw( |
1258 | _: *const libc::sockaddr, |
1259 | _: Option<libc::socklen_t>, |
1260 | ) -> Option<Self> |
1261 | where |
1262 | Self: Sized, |
1263 | { |
1264 | None |
1265 | } |
1266 | |
1267 | fn family(&self) -> Option<AddressFamily> { |
1268 | None |
1269 | } |
1270 | |
1271 | fn len(&self) -> libc::socklen_t { |
1272 | 0 |
1273 | } |
1274 | } |
1275 | |
1276 | /// An IPv4 socket address |
1277 | #[cfg (feature = "net" )] |
1278 | #[repr (transparent)] |
1279 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
1280 | pub struct SockaddrIn(libc::sockaddr_in); |
1281 | |
1282 | #[cfg (feature = "net" )] |
1283 | impl SockaddrIn { |
1284 | /// Returns the IP address associated with this socket address, in native |
1285 | /// endian. |
1286 | pub const fn ip(&self) -> libc::in_addr_t { |
1287 | u32::from_be(self.0.sin_addr.s_addr) |
1288 | } |
1289 | |
1290 | /// Creates a new socket address from IPv4 octets and a port number. |
1291 | pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self { |
1292 | Self(libc::sockaddr_in { |
1293 | #[cfg (any( |
1294 | target_os = "dragonfly" , |
1295 | target_os = "freebsd" , |
1296 | target_os = "ios" , |
1297 | target_os = "macos" , |
1298 | target_os = "netbsd" , |
1299 | target_os = "haiku" , |
1300 | target_os = "openbsd" |
1301 | ))] |
1302 | sin_len: Self::size() as u8, |
1303 | sin_family: AddressFamily::Inet as sa_family_t, |
1304 | sin_port: u16::to_be(port), |
1305 | sin_addr: libc::in_addr { |
1306 | s_addr: u32::from_ne_bytes([a, b, c, d]), |
1307 | }, |
1308 | sin_zero: unsafe { mem::zeroed() }, |
1309 | }) |
1310 | } |
1311 | |
1312 | /// Returns the port number associated with this socket address, in native |
1313 | /// endian. |
1314 | pub const fn port(&self) -> u16 { |
1315 | u16::from_be(self.0.sin_port) |
1316 | } |
1317 | } |
1318 | |
1319 | #[cfg (feature = "net" )] |
1320 | impl private::SockaddrLikePriv for SockaddrIn {} |
1321 | #[cfg (feature = "net" )] |
1322 | impl SockaddrLike for SockaddrIn { |
1323 | unsafe fn from_raw( |
1324 | addr: *const libc::sockaddr, |
1325 | len: Option<libc::socklen_t>, |
1326 | ) -> Option<Self> |
1327 | where |
1328 | Self: Sized, |
1329 | { |
1330 | if let Some(l) = len { |
1331 | if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t { |
1332 | return None; |
1333 | } |
1334 | } |
1335 | if (*addr).sa_family as i32 != libc::AF_INET { |
1336 | return None; |
1337 | } |
1338 | Some(Self(ptr::read_unaligned(addr as *const _))) |
1339 | } |
1340 | } |
1341 | |
1342 | #[cfg (feature = "net" )] |
1343 | impl AsRef<libc::sockaddr_in> for SockaddrIn { |
1344 | fn as_ref(&self) -> &libc::sockaddr_in { |
1345 | &self.0 |
1346 | } |
1347 | } |
1348 | |
1349 | #[cfg (feature = "net" )] |
1350 | impl fmt::Display for SockaddrIn { |
1351 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1352 | let ne = u32::from_be(self.0.sin_addr.s_addr); |
1353 | let port = u16::from_be(self.0.sin_port); |
1354 | write!( |
1355 | f, |
1356 | " {}. {}. {}. {}: {}" , |
1357 | ne >> 24, |
1358 | (ne >> 16) & 0xFF, |
1359 | (ne >> 8) & 0xFF, |
1360 | ne & 0xFF, |
1361 | port |
1362 | ) |
1363 | } |
1364 | } |
1365 | |
1366 | #[cfg (feature = "net" )] |
1367 | impl From<net::SocketAddrV4> for SockaddrIn { |
1368 | fn from(addr: net::SocketAddrV4) -> Self { |
1369 | Self(libc::sockaddr_in { |
1370 | #[cfg (any( |
1371 | target_os = "dragonfly" , |
1372 | target_os = "freebsd" , |
1373 | target_os = "haiku" , |
1374 | target_os = "hermit" , |
1375 | target_os = "ios" , |
1376 | target_os = "macos" , |
1377 | target_os = "netbsd" , |
1378 | target_os = "openbsd" |
1379 | ))] |
1380 | sin_len: mem::size_of::<libc::sockaddr_in>() as u8, |
1381 | sin_family: AddressFamily::Inet as sa_family_t, |
1382 | sin_port: addr.port().to_be(), // network byte order |
1383 | sin_addr: ipv4addr_to_libc(*addr.ip()), |
1384 | ..unsafe { mem::zeroed() } |
1385 | }) |
1386 | } |
1387 | } |
1388 | |
1389 | #[cfg (feature = "net" )] |
1390 | impl From<SockaddrIn> for net::SocketAddrV4 { |
1391 | fn from(addr: SockaddrIn) -> Self { |
1392 | net::SocketAddrV4::new( |
1393 | net::Ipv4Addr::from(addr.0.sin_addr.s_addr.to_ne_bytes()), |
1394 | u16::from_be(addr.0.sin_port), |
1395 | ) |
1396 | } |
1397 | } |
1398 | |
1399 | #[cfg (feature = "net" )] |
1400 | impl std::str::FromStr for SockaddrIn { |
1401 | type Err = net::AddrParseError; |
1402 | |
1403 | fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { |
1404 | net::SocketAddrV4::from_str(s).map(SockaddrIn::from) |
1405 | } |
1406 | } |
1407 | |
1408 | /// An IPv6 socket address |
1409 | #[cfg (feature = "net" )] |
1410 | #[repr (transparent)] |
1411 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
1412 | pub struct SockaddrIn6(libc::sockaddr_in6); |
1413 | |
1414 | #[cfg (feature = "net" )] |
1415 | impl SockaddrIn6 { |
1416 | /// Returns the flow information associated with this address. |
1417 | pub const fn flowinfo(&self) -> u32 { |
1418 | self.0.sin6_flowinfo |
1419 | } |
1420 | |
1421 | /// Returns the IP address associated with this socket address. |
1422 | pub fn ip(&self) -> net::Ipv6Addr { |
1423 | net::Ipv6Addr::from(self.0.sin6_addr.s6_addr) |
1424 | } |
1425 | |
1426 | /// Returns the port number associated with this socket address, in native |
1427 | /// endian. |
1428 | pub const fn port(&self) -> u16 { |
1429 | u16::from_be(self.0.sin6_port) |
1430 | } |
1431 | |
1432 | /// Returns the scope ID associated with this address. |
1433 | pub const fn scope_id(&self) -> u32 { |
1434 | self.0.sin6_scope_id |
1435 | } |
1436 | } |
1437 | |
1438 | #[cfg (feature = "net" )] |
1439 | impl private::SockaddrLikePriv for SockaddrIn6 {} |
1440 | #[cfg (feature = "net" )] |
1441 | impl SockaddrLike for SockaddrIn6 { |
1442 | unsafe fn from_raw( |
1443 | addr: *const libc::sockaddr, |
1444 | len: Option<libc::socklen_t>, |
1445 | ) -> Option<Self> |
1446 | where |
1447 | Self: Sized, |
1448 | { |
1449 | if let Some(l) = len { |
1450 | if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t { |
1451 | return None; |
1452 | } |
1453 | } |
1454 | if (*addr).sa_family as i32 != libc::AF_INET6 { |
1455 | return None; |
1456 | } |
1457 | Some(Self(ptr::read_unaligned(addr as *const _))) |
1458 | } |
1459 | } |
1460 | |
1461 | #[cfg (feature = "net" )] |
1462 | impl AsRef<libc::sockaddr_in6> for SockaddrIn6 { |
1463 | fn as_ref(&self) -> &libc::sockaddr_in6 { |
1464 | &self.0 |
1465 | } |
1466 | } |
1467 | |
1468 | #[cfg (feature = "net" )] |
1469 | impl fmt::Display for SockaddrIn6 { |
1470 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1471 | // These things are really hard to display properly. Easier to let std |
1472 | // do it. |
1473 | let std = net::SocketAddrV6::new( |
1474 | self.ip(), |
1475 | self.port(), |
1476 | self.flowinfo(), |
1477 | self.scope_id(), |
1478 | ); |
1479 | std.fmt(f) |
1480 | } |
1481 | } |
1482 | |
1483 | #[cfg (feature = "net" )] |
1484 | impl From<net::SocketAddrV6> for SockaddrIn6 { |
1485 | fn from(addr: net::SocketAddrV6) -> Self { |
1486 | #[allow (clippy::needless_update)] // It isn't needless on Illumos |
1487 | Self(libc::sockaddr_in6 { |
1488 | #[cfg (any( |
1489 | target_os = "dragonfly" , |
1490 | target_os = "freebsd" , |
1491 | target_os = "haiku" , |
1492 | target_os = "hermit" , |
1493 | target_os = "ios" , |
1494 | target_os = "macos" , |
1495 | target_os = "netbsd" , |
1496 | target_os = "openbsd" |
1497 | ))] |
1498 | sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8, |
1499 | sin6_family: AddressFamily::Inet6 as sa_family_t, |
1500 | sin6_port: addr.port().to_be(), // network byte order |
1501 | sin6_addr: ipv6addr_to_libc(addr.ip()), |
1502 | sin6_flowinfo: addr.flowinfo(), // host byte order |
1503 | sin6_scope_id: addr.scope_id(), // host byte order |
1504 | ..unsafe { mem::zeroed() } |
1505 | }) |
1506 | } |
1507 | } |
1508 | |
1509 | #[cfg (feature = "net" )] |
1510 | impl From<SockaddrIn6> for net::SocketAddrV6 { |
1511 | fn from(addr: SockaddrIn6) -> Self { |
1512 | net::SocketAddrV6::new( |
1513 | net::Ipv6Addr::from(addr.0.sin6_addr.s6_addr), |
1514 | u16::from_be(addr.0.sin6_port), |
1515 | addr.0.sin6_flowinfo, |
1516 | addr.0.sin6_scope_id, |
1517 | ) |
1518 | } |
1519 | } |
1520 | |
1521 | #[cfg (feature = "net" )] |
1522 | impl std::str::FromStr for SockaddrIn6 { |
1523 | type Err = net::AddrParseError; |
1524 | |
1525 | fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { |
1526 | net::SocketAddrV6::from_str(s).map(SockaddrIn6::from) |
1527 | } |
1528 | } |
1529 | |
1530 | /// A container for any sockaddr type |
1531 | /// |
1532 | /// Just like C's `sockaddr_storage`, this type is large enough to hold any type |
1533 | /// of sockaddr. It can be used as an argument with functions like |
1534 | /// [`bind`](super::bind) and [`getsockname`](super::getsockname). Though it is |
1535 | /// a union, it can be safely accessed through the `as_*` methods. |
1536 | /// |
1537 | /// # Example |
1538 | /// ``` |
1539 | /// # use nix::sys::socket::*; |
1540 | /// # use std::str::FromStr; |
1541 | /// let localhost = SockaddrIn::from_str("127.0.0.1:8081" ).unwrap(); |
1542 | /// let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), |
1543 | /// None).unwrap(); |
1544 | /// bind(fd, &localhost).expect("bind" ); |
1545 | /// let ss: SockaddrStorage = getsockname(fd).expect("getsockname" ); |
1546 | /// assert_eq!(&localhost, ss.as_sockaddr_in().unwrap()); |
1547 | /// ``` |
1548 | #[derive (Clone, Copy, Eq)] |
1549 | #[repr (C)] |
1550 | pub union SockaddrStorage { |
1551 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1552 | #[cfg_attr (docsrs, doc(cfg(all())))] |
1553 | alg: AlgAddr, |
1554 | #[cfg (feature = "net" )] |
1555 | #[cfg_attr (docsrs, doc(cfg(feature = "net" )))] |
1556 | dl: LinkAddr, |
1557 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1558 | nl: NetlinkAddr, |
1559 | #[cfg (all( |
1560 | feature = "ioctl" , |
1561 | any(target_os = "ios" , target_os = "macos" ) |
1562 | ))] |
1563 | #[cfg_attr (docsrs, doc(cfg(feature = "ioctl" )))] |
1564 | sctl: SysControlAddr, |
1565 | #[cfg (feature = "net" )] |
1566 | sin: SockaddrIn, |
1567 | #[cfg (feature = "net" )] |
1568 | sin6: SockaddrIn6, |
1569 | ss: libc::sockaddr_storage, |
1570 | su: UnixAddr, |
1571 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1572 | #[cfg_attr (docsrs, doc(cfg(all())))] |
1573 | vsock: VsockAddr, |
1574 | } |
1575 | impl private::SockaddrLikePriv for SockaddrStorage {} |
1576 | impl SockaddrLike for SockaddrStorage { |
1577 | unsafe fn from_raw( |
1578 | addr: *const libc::sockaddr, |
1579 | l: Option<libc::socklen_t>, |
1580 | ) -> Option<Self> |
1581 | where |
1582 | Self: Sized, |
1583 | { |
1584 | if addr.is_null() { |
1585 | return None; |
1586 | } |
1587 | if let Some(len) = l { |
1588 | let ulen = len as usize; |
1589 | if ulen < offset_of!(libc::sockaddr, sa_data) |
1590 | || ulen > mem::size_of::<libc::sockaddr_storage>() |
1591 | { |
1592 | None |
1593 | } else { |
1594 | let mut ss: libc::sockaddr_storage = mem::zeroed(); |
1595 | let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8; |
1596 | ptr::copy(addr as *const u8, ssp, len as usize); |
1597 | #[cfg (any( |
1598 | target_os = "android" , |
1599 | target_os = "fuchsia" , |
1600 | target_os = "illumos" , |
1601 | target_os = "linux" |
1602 | ))] |
1603 | if i32::from(ss.ss_family) == libc::AF_UNIX { |
1604 | // Safe because we UnixAddr is strictly smaller than |
1605 | // SockaddrStorage, and we just initialized the structure. |
1606 | (*(&mut ss as *mut libc::sockaddr_storage as *mut UnixAddr)).sun_len = len as u8; |
1607 | } |
1608 | Some(Self { ss }) |
1609 | } |
1610 | } else { |
1611 | // If length is not available and addr is of a fixed-length type, |
1612 | // copy it. If addr is of a variable length type and len is not |
1613 | // available, then there's nothing we can do. |
1614 | match (*addr).sa_family as i32 { |
1615 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1616 | libc::AF_ALG => { |
1617 | AlgAddr::from_raw(addr, l).map(|alg| Self { alg }) |
1618 | } |
1619 | #[cfg (feature = "net" )] |
1620 | libc::AF_INET => { |
1621 | SockaddrIn::from_raw(addr, l).map(|sin| Self { sin }) |
1622 | } |
1623 | #[cfg (feature = "net" )] |
1624 | libc::AF_INET6 => { |
1625 | SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 }) |
1626 | } |
1627 | #[cfg (any( |
1628 | target_os = "dragonfly" , |
1629 | target_os = "freebsd" , |
1630 | target_os = "ios" , |
1631 | target_os = "macos" , |
1632 | target_os = "illumos" , |
1633 | target_os = "netbsd" , |
1634 | target_os = "haiku" , |
1635 | target_os = "openbsd" |
1636 | ))] |
1637 | #[cfg (feature = "net" )] |
1638 | libc::AF_LINK => { |
1639 | LinkAddr::from_raw(addr, l).map(|dl| Self { dl }) |
1640 | } |
1641 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1642 | libc::AF_NETLINK => { |
1643 | NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl }) |
1644 | } |
1645 | #[cfg (any( |
1646 | target_os = "android" , |
1647 | target_os = "fuchsia" , |
1648 | target_os = "linux" |
1649 | ))] |
1650 | #[cfg (feature = "net" )] |
1651 | libc::AF_PACKET => { |
1652 | LinkAddr::from_raw(addr, l).map(|dl| Self { dl }) |
1653 | } |
1654 | #[cfg (all( |
1655 | feature = "ioctl" , |
1656 | any(target_os = "ios" , target_os = "macos" ) |
1657 | ))] |
1658 | libc::AF_SYSTEM => { |
1659 | SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl }) |
1660 | } |
1661 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1662 | libc::AF_VSOCK => { |
1663 | VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock }) |
1664 | } |
1665 | _ => None, |
1666 | } |
1667 | } |
1668 | } |
1669 | |
1670 | #[cfg (any( |
1671 | target_os = "android" , |
1672 | target_os = "fuchsia" , |
1673 | target_os = "illumos" , |
1674 | target_os = "linux" |
1675 | ))] |
1676 | fn len(&self) -> libc::socklen_t { |
1677 | match self.as_unix_addr() { |
1678 | // The UnixAddr type knows its own length |
1679 | Some(ua) => ua.len(), |
1680 | // For all else, we're just a boring SockaddrStorage |
1681 | None => mem::size_of_val(self) as libc::socklen_t |
1682 | } |
1683 | } |
1684 | |
1685 | unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> { |
1686 | match self.as_unix_addr_mut() { |
1687 | Some(addr) => { |
1688 | addr.set_length(new_length) |
1689 | }, |
1690 | None => Err(SocketAddressLengthNotDynamic), |
1691 | } |
1692 | } |
1693 | } |
1694 | |
1695 | macro_rules! accessors { |
1696 | ( |
1697 | $fname:ident, |
1698 | $fname_mut:ident, |
1699 | $sockty:ty, |
1700 | $family:expr, |
1701 | $libc_ty:ty, |
1702 | $field:ident) => { |
1703 | /// Safely and falliably downcast to an immutable reference |
1704 | pub fn $fname(&self) -> Option<&$sockty> { |
1705 | if self.family() == Some($family) |
1706 | && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t |
1707 | { |
1708 | // Safe because family and len are validated |
1709 | Some(unsafe { &self.$field }) |
1710 | } else { |
1711 | None |
1712 | } |
1713 | } |
1714 | |
1715 | /// Safely and falliably downcast to a mutable reference |
1716 | pub fn $fname_mut(&mut self) -> Option<&mut $sockty> { |
1717 | if self.family() == Some($family) |
1718 | && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t |
1719 | { |
1720 | // Safe because family and len are validated |
1721 | Some(unsafe { &mut self.$field }) |
1722 | } else { |
1723 | None |
1724 | } |
1725 | } |
1726 | }; |
1727 | } |
1728 | |
1729 | impl SockaddrStorage { |
1730 | /// Downcast to an immutable `[UnixAddr]` reference. |
1731 | pub fn as_unix_addr(&self) -> Option<&UnixAddr> { |
1732 | cfg_if! { |
1733 | if #[cfg(any(target_os = "android" , |
1734 | target_os = "fuchsia" , |
1735 | target_os = "illumos" , |
1736 | target_os = "linux" |
1737 | ))] |
1738 | { |
1739 | let p = unsafe{ &self.ss as *const libc::sockaddr_storage }; |
1740 | // Safe because UnixAddr is strictly smaller than |
1741 | // sockaddr_storage, and we're fully initialized |
1742 | let len = unsafe { |
1743 | (*(p as *const UnixAddr )).sun_len as usize |
1744 | }; |
1745 | } else { |
1746 | let len = self.len() as usize; |
1747 | } |
1748 | } |
1749 | // Sanity checks |
1750 | if self.family() != Some(AddressFamily::Unix) || |
1751 | len < offset_of!(libc::sockaddr_un, sun_path) || |
1752 | len > mem::size_of::<libc::sockaddr_un>() { |
1753 | None |
1754 | } else { |
1755 | Some(unsafe{&self.su}) |
1756 | } |
1757 | } |
1758 | |
1759 | /// Downcast to a mutable `[UnixAddr]` reference. |
1760 | pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> { |
1761 | cfg_if! { |
1762 | if #[cfg(any(target_os = "android" , |
1763 | target_os = "fuchsia" , |
1764 | target_os = "illumos" , |
1765 | target_os = "linux" |
1766 | ))] |
1767 | { |
1768 | let p = unsafe{ &self.ss as *const libc::sockaddr_storage }; |
1769 | // Safe because UnixAddr is strictly smaller than |
1770 | // sockaddr_storage, and we're fully initialized |
1771 | let len = unsafe { |
1772 | (*(p as *const UnixAddr )).sun_len as usize |
1773 | }; |
1774 | } else { |
1775 | let len = self.len() as usize; |
1776 | } |
1777 | } |
1778 | // Sanity checks |
1779 | if self.family() != Some(AddressFamily::Unix) || |
1780 | len < offset_of!(libc::sockaddr_un, sun_path) || |
1781 | len > mem::size_of::<libc::sockaddr_un>() { |
1782 | None |
1783 | } else { |
1784 | Some(unsafe{&mut self.su}) |
1785 | } |
1786 | } |
1787 | |
1788 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1789 | accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr, |
1790 | AddressFamily::Alg, libc::sockaddr_alg, alg} |
1791 | |
1792 | #[cfg (any( |
1793 | target_os = "android" , |
1794 | target_os = "fuchsia" , |
1795 | target_os = "linux" |
1796 | ))] |
1797 | #[cfg (feature = "net" )] |
1798 | accessors! { |
1799 | as_link_addr, as_link_addr_mut, LinkAddr, |
1800 | AddressFamily::Packet, libc::sockaddr_ll, dl} |
1801 | |
1802 | #[cfg (any( |
1803 | target_os = "dragonfly" , |
1804 | target_os = "freebsd" , |
1805 | target_os = "ios" , |
1806 | target_os = "macos" , |
1807 | target_os = "illumos" , |
1808 | target_os = "netbsd" , |
1809 | target_os = "openbsd" |
1810 | ))] |
1811 | #[cfg (feature = "net" )] |
1812 | accessors! { |
1813 | as_link_addr, as_link_addr_mut, LinkAddr, |
1814 | AddressFamily::Link, libc::sockaddr_dl, dl} |
1815 | |
1816 | #[cfg (feature = "net" )] |
1817 | accessors! { |
1818 | as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn, |
1819 | AddressFamily::Inet, libc::sockaddr_in, sin} |
1820 | |
1821 | #[cfg (feature = "net" )] |
1822 | accessors! { |
1823 | as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6, |
1824 | AddressFamily::Inet6, libc::sockaddr_in6, sin6} |
1825 | |
1826 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1827 | accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr, |
1828 | AddressFamily::Netlink, libc::sockaddr_nl, nl} |
1829 | |
1830 | #[cfg (all(feature = "ioctl" , any(target_os = "ios" , target_os = "macos" )))] |
1831 | #[cfg_attr (docsrs, doc(cfg(feature = "ioctl" )))] |
1832 | accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr, |
1833 | AddressFamily::System, libc::sockaddr_ctl, sctl} |
1834 | |
1835 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1836 | #[cfg_attr (docsrs, doc(cfg(all())))] |
1837 | accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr, |
1838 | AddressFamily::Vsock, libc::sockaddr_vm, vsock} |
1839 | } |
1840 | |
1841 | impl fmt::Debug for SockaddrStorage { |
1842 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1843 | f&mut DebugStruct<'_, '_>.debug_struct("SockaddrStorage" ) |
1844 | // Safe because sockaddr_storage has the least specific |
1845 | // field types |
1846 | .field(name:"ss" , value:unsafe { &self.ss }) |
1847 | .finish() |
1848 | } |
1849 | } |
1850 | |
1851 | impl fmt::Display for SockaddrStorage { |
1852 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1853 | unsafe { |
1854 | match self.ss.ss_family as i32 { |
1855 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1856 | libc::AF_ALG => self.alg.fmt(f), |
1857 | #[cfg (feature = "net" )] |
1858 | libc::AF_INET => self.sin.fmt(f), |
1859 | #[cfg (feature = "net" )] |
1860 | libc::AF_INET6 => self.sin6.fmt(f), |
1861 | #[cfg (any( |
1862 | target_os = "dragonfly" , |
1863 | target_os = "freebsd" , |
1864 | target_os = "ios" , |
1865 | target_os = "macos" , |
1866 | target_os = "illumos" , |
1867 | target_os = "netbsd" , |
1868 | target_os = "openbsd" |
1869 | ))] |
1870 | #[cfg (feature = "net" )] |
1871 | libc::AF_LINK => self.dl.fmt(f), |
1872 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1873 | libc::AF_NETLINK => self.nl.fmt(f), |
1874 | #[cfg (any( |
1875 | target_os = "android" , |
1876 | target_os = "linux" , |
1877 | target_os = "fuchsia" |
1878 | ))] |
1879 | #[cfg (feature = "net" )] |
1880 | libc::AF_PACKET => self.dl.fmt(f), |
1881 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
1882 | #[cfg (feature = "ioctl" )] |
1883 | libc::AF_SYSTEM => self.sctl.fmt(f), |
1884 | libc::AF_UNIX => self.su.fmt(f), |
1885 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1886 | libc::AF_VSOCK => self.vsock.fmt(f), |
1887 | _ => "<Address family unspecified>" .fmt(f), |
1888 | } |
1889 | } |
1890 | } |
1891 | } |
1892 | |
1893 | #[cfg (feature = "net" )] |
1894 | impl From<net::SocketAddrV4> for SockaddrStorage { |
1895 | fn from(s: net::SocketAddrV4) -> Self { |
1896 | unsafe { |
1897 | let mut ss: Self = mem::zeroed(); |
1898 | ss.sin = SockaddrIn::from(s); |
1899 | ss |
1900 | } |
1901 | } |
1902 | } |
1903 | |
1904 | #[cfg (feature = "net" )] |
1905 | impl From<net::SocketAddrV6> for SockaddrStorage { |
1906 | fn from(s: net::SocketAddrV6) -> Self { |
1907 | unsafe { |
1908 | let mut ss: Self = mem::zeroed(); |
1909 | ss.sin6 = SockaddrIn6::from(s); |
1910 | ss |
1911 | } |
1912 | } |
1913 | } |
1914 | |
1915 | #[cfg (feature = "net" )] |
1916 | impl From<net::SocketAddr> for SockaddrStorage { |
1917 | fn from(s: net::SocketAddr) -> Self { |
1918 | match s { |
1919 | net::SocketAddr::V4(sa4) => Self::from(sa4), |
1920 | net::SocketAddr::V6(sa6) => Self::from(sa6), |
1921 | } |
1922 | } |
1923 | } |
1924 | |
1925 | impl Hash for SockaddrStorage { |
1926 | fn hash<H: Hasher>(&self, s: &mut H) { |
1927 | unsafe { |
1928 | match self.ss.ss_family as i32 { |
1929 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1930 | libc::AF_ALG => self.alg.hash(s), |
1931 | #[cfg (feature = "net" )] |
1932 | libc::AF_INET => self.sin.hash(s), |
1933 | #[cfg (feature = "net" )] |
1934 | libc::AF_INET6 => self.sin6.hash(s), |
1935 | #[cfg (any( |
1936 | target_os = "dragonfly" , |
1937 | target_os = "freebsd" , |
1938 | target_os = "ios" , |
1939 | target_os = "macos" , |
1940 | target_os = "illumos" , |
1941 | target_os = "netbsd" , |
1942 | target_os = "openbsd" |
1943 | ))] |
1944 | #[cfg (feature = "net" )] |
1945 | libc::AF_LINK => self.dl.hash(s), |
1946 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1947 | libc::AF_NETLINK => self.nl.hash(s), |
1948 | #[cfg (any( |
1949 | target_os = "android" , |
1950 | target_os = "linux" , |
1951 | target_os = "fuchsia" |
1952 | ))] |
1953 | #[cfg (feature = "net" )] |
1954 | libc::AF_PACKET => self.dl.hash(s), |
1955 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
1956 | #[cfg (feature = "ioctl" )] |
1957 | libc::AF_SYSTEM => self.sctl.hash(s), |
1958 | libc::AF_UNIX => self.su.hash(s), |
1959 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1960 | libc::AF_VSOCK => self.vsock.hash(s), |
1961 | _ => self.ss.hash(s), |
1962 | } |
1963 | } |
1964 | } |
1965 | } |
1966 | |
1967 | impl PartialEq for SockaddrStorage { |
1968 | fn eq(&self, other: &Self) -> bool { |
1969 | unsafe { |
1970 | match (self.ss.ss_family as i32, other.ss.ss_family as i32) { |
1971 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1972 | (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg, |
1973 | #[cfg (feature = "net" )] |
1974 | (libc::AF_INET, libc::AF_INET) => self.sin == other.sin, |
1975 | #[cfg (feature = "net" )] |
1976 | (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6, |
1977 | #[cfg (any( |
1978 | target_os = "dragonfly" , |
1979 | target_os = "freebsd" , |
1980 | target_os = "ios" , |
1981 | target_os = "macos" , |
1982 | target_os = "illumos" , |
1983 | target_os = "netbsd" , |
1984 | target_os = "openbsd" |
1985 | ))] |
1986 | #[cfg (feature = "net" )] |
1987 | (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl, |
1988 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
1989 | (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl, |
1990 | #[cfg (any( |
1991 | target_os = "android" , |
1992 | target_os = "fuchsia" , |
1993 | target_os = "linux" |
1994 | ))] |
1995 | #[cfg (feature = "net" )] |
1996 | (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl, |
1997 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
1998 | #[cfg (feature = "ioctl" )] |
1999 | (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl, |
2000 | (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su, |
2001 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2002 | (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock, |
2003 | _ => false, |
2004 | } |
2005 | } |
2006 | } |
2007 | } |
2008 | |
2009 | pub(super) mod private { |
2010 | pub trait SockaddrLikePriv { |
2011 | /// Returns a mutable raw pointer to the inner structure. |
2012 | /// |
2013 | /// # Safety |
2014 | /// |
2015 | /// This method is technically safe, but modifying the inner structure's |
2016 | /// `family` or `len` fields may result in violating Nix's invariants. |
2017 | /// It is best to use this method only with foreign functions that do |
2018 | /// not change the sockaddr type. |
2019 | fn as_mut_ptr(&mut self) -> *mut libc::sockaddr { |
2020 | self as *mut Self as *mut libc::sockaddr |
2021 | } |
2022 | } |
2023 | } |
2024 | |
2025 | /// Represents a socket address |
2026 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
2027 | #[deprecated ( |
2028 | since = "0.24.0" , |
2029 | note = "use SockaddrLike or SockaddrStorage instead" |
2030 | )] |
2031 | #[allow (missing_docs)] // Since they're all deprecated anyway |
2032 | #[allow (deprecated)] |
2033 | #[non_exhaustive ] |
2034 | pub enum SockAddr { |
2035 | #[cfg (feature = "net" )] |
2036 | #[cfg_attr (docsrs, doc(cfg(feature = "net" )))] |
2037 | Inet(InetAddr), |
2038 | Unix(UnixAddr), |
2039 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2040 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2041 | Netlink(NetlinkAddr), |
2042 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2043 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2044 | Alg(AlgAddr), |
2045 | #[cfg (all( |
2046 | feature = "ioctl" , |
2047 | any(target_os = "ios" , target_os = "macos" ) |
2048 | ))] |
2049 | #[cfg_attr (docsrs, doc(cfg(feature = "ioctl" )))] |
2050 | SysControl(SysControlAddr), |
2051 | /// Datalink address (MAC) |
2052 | #[cfg (any( |
2053 | target_os = "android" , |
2054 | target_os = "dragonfly" , |
2055 | target_os = "freebsd" , |
2056 | target_os = "ios" , |
2057 | target_os = "linux" , |
2058 | target_os = "macos" , |
2059 | target_os = "illumos" , |
2060 | target_os = "netbsd" , |
2061 | target_os = "openbsd" |
2062 | ))] |
2063 | #[cfg (feature = "net" )] |
2064 | #[cfg_attr (docsrs, doc(cfg(feature = "net" )))] |
2065 | Link(LinkAddr), |
2066 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2067 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2068 | Vsock(VsockAddr), |
2069 | } |
2070 | |
2071 | #[allow (missing_docs)] // Since they're all deprecated anyway |
2072 | #[allow (deprecated)] |
2073 | impl SockAddr { |
2074 | feature! { |
2075 | #![feature = "net" ] |
2076 | pub fn new_inet(addr: InetAddr) -> SockAddr { |
2077 | SockAddr::Inet(addr) |
2078 | } |
2079 | } |
2080 | |
2081 | pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> { |
2082 | Ok(SockAddr::Unix(UnixAddr::new(path)?)) |
2083 | } |
2084 | |
2085 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2086 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2087 | pub fn new_netlink(pid: u32, groups: u32) -> SockAddr { |
2088 | SockAddr::Netlink(NetlinkAddr::new(pid, groups)) |
2089 | } |
2090 | |
2091 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2092 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2093 | pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr { |
2094 | SockAddr::Alg(AlgAddr::new(alg_type, alg_name)) |
2095 | } |
2096 | |
2097 | feature! { |
2098 | #![feature = "ioctl" ] |
2099 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
2100 | pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> { |
2101 | SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl) |
2102 | } |
2103 | } |
2104 | |
2105 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2106 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2107 | pub fn new_vsock(cid: u32, port: u32) -> SockAddr { |
2108 | SockAddr::Vsock(VsockAddr::new(cid, port)) |
2109 | } |
2110 | |
2111 | pub fn family(&self) -> AddressFamily { |
2112 | match *self { |
2113 | #[cfg (feature = "net" )] |
2114 | SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet, |
2115 | #[cfg (feature = "net" )] |
2116 | SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6, |
2117 | SockAddr::Unix(..) => AddressFamily::Unix, |
2118 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2119 | SockAddr::Netlink(..) => AddressFamily::Netlink, |
2120 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2121 | SockAddr::Alg(..) => AddressFamily::Alg, |
2122 | #[cfg (all( |
2123 | feature = "ioctl" , |
2124 | any(target_os = "ios" , target_os = "macos" ) |
2125 | ))] |
2126 | SockAddr::SysControl(..) => AddressFamily::System, |
2127 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2128 | #[cfg (feature = "net" )] |
2129 | SockAddr::Link(..) => AddressFamily::Packet, |
2130 | #[cfg (any( |
2131 | target_os = "dragonfly" , |
2132 | target_os = "freebsd" , |
2133 | target_os = "ios" , |
2134 | target_os = "macos" , |
2135 | target_os = "netbsd" , |
2136 | target_os = "illumos" , |
2137 | target_os = "openbsd" |
2138 | ))] |
2139 | #[cfg (feature = "net" )] |
2140 | SockAddr::Link(..) => AddressFamily::Link, |
2141 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2142 | SockAddr::Vsock(..) => AddressFamily::Vsock, |
2143 | } |
2144 | } |
2145 | |
2146 | #[deprecated (since = "0.23.0" , note = "use .to_string() instead" )] |
2147 | pub fn to_str(&self) -> String { |
2148 | format!(" {}" , self) |
2149 | } |
2150 | |
2151 | /// Creates a `SockAddr` struct from libc's sockaddr. |
2152 | /// |
2153 | /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System. |
2154 | /// Returns None for unsupported families. |
2155 | /// |
2156 | /// # Safety |
2157 | /// |
2158 | /// unsafe because it takes a raw pointer as argument. The caller must |
2159 | /// ensure that the pointer is valid. |
2160 | #[cfg (not(target_os = "fuchsia" ))] |
2161 | #[cfg (feature = "net" )] |
2162 | pub(crate) unsafe fn from_libc_sockaddr( |
2163 | addr: *const libc::sockaddr, |
2164 | ) -> Option<SockAddr> { |
2165 | if addr.is_null() { |
2166 | None |
2167 | } else { |
2168 | match AddressFamily::from_i32(i32::from((*addr).sa_family)) { |
2169 | Some(AddressFamily::Unix) => None, |
2170 | #[cfg (feature = "net" )] |
2171 | Some(AddressFamily::Inet) => Some(SockAddr::Inet( |
2172 | InetAddr::V4(ptr::read_unaligned(addr as *const _)), |
2173 | )), |
2174 | #[cfg (feature = "net" )] |
2175 | Some(AddressFamily::Inet6) => Some(SockAddr::Inet( |
2176 | InetAddr::V6(ptr::read_unaligned(addr as *const _)), |
2177 | )), |
2178 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2179 | Some(AddressFamily::Netlink) => Some(SockAddr::Netlink( |
2180 | NetlinkAddr(ptr::read_unaligned(addr as *const _)), |
2181 | )), |
2182 | #[cfg (all( |
2183 | feature = "ioctl" , |
2184 | any(target_os = "ios" , target_os = "macos" ) |
2185 | ))] |
2186 | Some(AddressFamily::System) => Some(SockAddr::SysControl( |
2187 | SysControlAddr(ptr::read_unaligned(addr as *const _)), |
2188 | )), |
2189 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2190 | #[cfg (feature = "net" )] |
2191 | Some(AddressFamily::Packet) => Some(SockAddr::Link(LinkAddr( |
2192 | ptr::read_unaligned(addr as *const _), |
2193 | ))), |
2194 | #[cfg (any( |
2195 | target_os = "dragonfly" , |
2196 | target_os = "freebsd" , |
2197 | target_os = "ios" , |
2198 | target_os = "macos" , |
2199 | target_os = "netbsd" , |
2200 | target_os = "illumos" , |
2201 | target_os = "openbsd" |
2202 | ))] |
2203 | #[cfg (feature = "net" )] |
2204 | Some(AddressFamily::Link) => { |
2205 | let ether_addr = |
2206 | LinkAddr(ptr::read_unaligned(addr as *const _)); |
2207 | if ether_addr.is_empty() { |
2208 | None |
2209 | } else { |
2210 | Some(SockAddr::Link(ether_addr)) |
2211 | } |
2212 | } |
2213 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2214 | Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(VsockAddr( |
2215 | ptr::read_unaligned(addr as *const _), |
2216 | ))), |
2217 | // Other address families are currently not supported and simply yield a None |
2218 | // entry instead of a proper conversion to a `SockAddr`. |
2219 | Some(_) | None => None, |
2220 | } |
2221 | } |
2222 | } |
2223 | |
2224 | /// Conversion from nix's SockAddr type to the underlying libc sockaddr type. |
2225 | /// |
2226 | /// This is useful for interfacing with other libc functions that don't yet have nix wrappers. |
2227 | /// Returns a reference to the underlying data type (as a sockaddr reference) along |
2228 | /// with the size of the actual data type. sockaddr is commonly used as a proxy for |
2229 | /// a superclass as C doesn't support inheritance, so many functions that take |
2230 | /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back. |
2231 | pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) { |
2232 | match *self { |
2233 | #[cfg (feature = "net" )] |
2234 | SockAddr::Inet(InetAddr::V4(ref addr)) => ( |
2235 | // This cast is always allowed in C |
2236 | unsafe { |
2237 | &*(addr as *const libc::sockaddr_in |
2238 | as *const libc::sockaddr) |
2239 | }, |
2240 | mem::size_of_val(addr) as libc::socklen_t, |
2241 | ), |
2242 | #[cfg (feature = "net" )] |
2243 | SockAddr::Inet(InetAddr::V6(ref addr)) => ( |
2244 | // This cast is always allowed in C |
2245 | unsafe { |
2246 | &*(addr as *const libc::sockaddr_in6 |
2247 | as *const libc::sockaddr) |
2248 | }, |
2249 | mem::size_of_val(addr) as libc::socklen_t, |
2250 | ), |
2251 | SockAddr::Unix(ref unix_addr) => ( |
2252 | // This cast is always allowed in C |
2253 | unsafe { |
2254 | &*(&unix_addr.sun as *const libc::sockaddr_un |
2255 | as *const libc::sockaddr) |
2256 | }, |
2257 | unix_addr.sun_len() as libc::socklen_t, |
2258 | ), |
2259 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2260 | SockAddr::Netlink(NetlinkAddr(ref sa)) => ( |
2261 | // This cast is always allowed in C |
2262 | unsafe { |
2263 | &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr) |
2264 | }, |
2265 | mem::size_of_val(sa) as libc::socklen_t, |
2266 | ), |
2267 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2268 | SockAddr::Alg(AlgAddr(ref sa)) => ( |
2269 | // This cast is always allowed in C |
2270 | unsafe { |
2271 | &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr) |
2272 | }, |
2273 | mem::size_of_val(sa) as libc::socklen_t, |
2274 | ), |
2275 | #[cfg (all( |
2276 | feature = "ioctl" , |
2277 | any(target_os = "ios" , target_os = "macos" ) |
2278 | ))] |
2279 | SockAddr::SysControl(SysControlAddr(ref sa)) => ( |
2280 | // This cast is always allowed in C |
2281 | unsafe { |
2282 | &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr) |
2283 | }, |
2284 | mem::size_of_val(sa) as libc::socklen_t, |
2285 | ), |
2286 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2287 | #[cfg (feature = "net" )] |
2288 | SockAddr::Link(LinkAddr(ref addr)) => ( |
2289 | // This cast is always allowed in C |
2290 | unsafe { |
2291 | &*(addr as *const libc::sockaddr_ll |
2292 | as *const libc::sockaddr) |
2293 | }, |
2294 | mem::size_of_val(addr) as libc::socklen_t, |
2295 | ), |
2296 | #[cfg (any( |
2297 | target_os = "dragonfly" , |
2298 | target_os = "freebsd" , |
2299 | target_os = "ios" , |
2300 | target_os = "macos" , |
2301 | target_os = "illumos" , |
2302 | target_os = "netbsd" , |
2303 | target_os = "openbsd" |
2304 | ))] |
2305 | #[cfg (feature = "net" )] |
2306 | SockAddr::Link(LinkAddr(ref addr)) => ( |
2307 | // This cast is always allowed in C |
2308 | unsafe { |
2309 | &*(addr as *const libc::sockaddr_dl |
2310 | as *const libc::sockaddr) |
2311 | }, |
2312 | mem::size_of_val(addr) as libc::socklen_t, |
2313 | ), |
2314 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2315 | SockAddr::Vsock(VsockAddr(ref sa)) => ( |
2316 | // This cast is always allowed in C |
2317 | unsafe { |
2318 | &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr) |
2319 | }, |
2320 | mem::size_of_val(sa) as libc::socklen_t, |
2321 | ), |
2322 | } |
2323 | } |
2324 | } |
2325 | |
2326 | #[allow (deprecated)] |
2327 | impl fmt::Display for SockAddr { |
2328 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2329 | match *self { |
2330 | #[cfg (feature = "net" )] |
2331 | SockAddr::Inet(ref inet) => inet.fmt(f), |
2332 | SockAddr::Unix(ref unix) => unix.fmt(f), |
2333 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2334 | SockAddr::Netlink(ref nl) => nl.fmt(f), |
2335 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2336 | SockAddr::Alg(ref nl) => nl.fmt(f), |
2337 | #[cfg (all( |
2338 | feature = "ioctl" , |
2339 | any(target_os = "ios" , target_os = "macos" ) |
2340 | ))] |
2341 | SockAddr::SysControl(ref sc) => sc.fmt(f), |
2342 | #[cfg (any( |
2343 | target_os = "android" , |
2344 | target_os = "dragonfly" , |
2345 | target_os = "freebsd" , |
2346 | target_os = "ios" , |
2347 | target_os = "linux" , |
2348 | target_os = "macos" , |
2349 | target_os = "netbsd" , |
2350 | target_os = "illumos" , |
2351 | target_os = "openbsd" |
2352 | ))] |
2353 | #[cfg (feature = "net" )] |
2354 | SockAddr::Link(ref ether_addr) => ether_addr.fmt(f), |
2355 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2356 | SockAddr::Vsock(ref svm) => svm.fmt(f), |
2357 | } |
2358 | } |
2359 | } |
2360 | |
2361 | #[cfg (not(target_os = "fuchsia" ))] |
2362 | #[cfg (feature = "net" )] |
2363 | #[allow (deprecated)] |
2364 | impl private::SockaddrLikePriv for SockAddr {} |
2365 | #[cfg (not(target_os = "fuchsia" ))] |
2366 | #[cfg (feature = "net" )] |
2367 | #[allow (deprecated)] |
2368 | impl SockaddrLike for SockAddr { |
2369 | unsafe fn from_raw( |
2370 | addr: *const libc::sockaddr, |
2371 | _len: Option<libc::socklen_t>, |
2372 | ) -> Option<Self> { |
2373 | Self::from_libc_sockaddr(addr) |
2374 | } |
2375 | } |
2376 | |
2377 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2378 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2379 | pub mod netlink { |
2380 | use super::*; |
2381 | use crate::sys::socket::addr::AddressFamily; |
2382 | use libc::{sa_family_t, sockaddr_nl}; |
2383 | use std::{fmt, mem}; |
2384 | |
2385 | /// Address for the Linux kernel user interface device. |
2386 | /// |
2387 | /// # References |
2388 | /// |
2389 | /// [netlink(7)](https://man7.org/linux/man-pages/man7/netlink.7.html) |
2390 | #[derive (Copy, Clone, Debug, Eq, Hash, PartialEq)] |
2391 | #[repr (transparent)] |
2392 | pub struct NetlinkAddr(pub(in super::super) sockaddr_nl); |
2393 | |
2394 | impl NetlinkAddr { |
2395 | /// Construct a new socket address from its port ID and multicast groups |
2396 | /// mask. |
2397 | pub fn new(pid: u32, groups: u32) -> NetlinkAddr { |
2398 | let mut addr: sockaddr_nl = unsafe { mem::zeroed() }; |
2399 | addr.nl_family = AddressFamily::Netlink as sa_family_t; |
2400 | addr.nl_pid = pid; |
2401 | addr.nl_groups = groups; |
2402 | |
2403 | NetlinkAddr(addr) |
2404 | } |
2405 | |
2406 | /// Return the socket's port ID. |
2407 | pub const fn pid(&self) -> u32 { |
2408 | self.0.nl_pid |
2409 | } |
2410 | |
2411 | /// Return the socket's multicast groups mask |
2412 | pub const fn groups(&self) -> u32 { |
2413 | self.0.nl_groups |
2414 | } |
2415 | } |
2416 | |
2417 | impl private::SockaddrLikePriv for NetlinkAddr {} |
2418 | impl SockaddrLike for NetlinkAddr { |
2419 | unsafe fn from_raw( |
2420 | addr: *const libc::sockaddr, |
2421 | len: Option<libc::socklen_t>, |
2422 | ) -> Option<Self> |
2423 | where |
2424 | Self: Sized, |
2425 | { |
2426 | if let Some(l) = len { |
2427 | if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t { |
2428 | return None; |
2429 | } |
2430 | } |
2431 | if (*addr).sa_family as i32 != libc::AF_NETLINK { |
2432 | return None; |
2433 | } |
2434 | Some(Self(ptr::read_unaligned(addr as *const _))) |
2435 | } |
2436 | } |
2437 | |
2438 | impl AsRef<libc::sockaddr_nl> for NetlinkAddr { |
2439 | fn as_ref(&self) -> &libc::sockaddr_nl { |
2440 | &self.0 |
2441 | } |
2442 | } |
2443 | |
2444 | impl fmt::Display for NetlinkAddr { |
2445 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2446 | write!(f, "pid: {} groups: {}" , self.pid(), self.groups()) |
2447 | } |
2448 | } |
2449 | } |
2450 | |
2451 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2452 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2453 | pub mod alg { |
2454 | use super::*; |
2455 | use libc::{c_char, sockaddr_alg, AF_ALG}; |
2456 | use std::ffi::CStr; |
2457 | use std::hash::{Hash, Hasher}; |
2458 | use std::{fmt, mem, str}; |
2459 | |
2460 | /// Socket address for the Linux kernel crypto API |
2461 | #[derive (Copy, Clone)] |
2462 | #[repr (transparent)] |
2463 | pub struct AlgAddr(pub(in super::super) sockaddr_alg); |
2464 | |
2465 | impl private::SockaddrLikePriv for AlgAddr {} |
2466 | impl SockaddrLike for AlgAddr { |
2467 | unsafe fn from_raw( |
2468 | addr: *const libc::sockaddr, |
2469 | l: Option<libc::socklen_t>, |
2470 | ) -> Option<Self> |
2471 | where |
2472 | Self: Sized, |
2473 | { |
2474 | if let Some(l) = l { |
2475 | if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t |
2476 | { |
2477 | return None; |
2478 | } |
2479 | } |
2480 | if (*addr).sa_family as i32 != libc::AF_ALG { |
2481 | return None; |
2482 | } |
2483 | Some(Self(ptr::read_unaligned(addr as *const _))) |
2484 | } |
2485 | } |
2486 | |
2487 | impl AsRef<libc::sockaddr_alg> for AlgAddr { |
2488 | fn as_ref(&self) -> &libc::sockaddr_alg { |
2489 | &self.0 |
2490 | } |
2491 | } |
2492 | |
2493 | // , PartialEq, Eq, Debug, Hash |
2494 | impl PartialEq for AlgAddr { |
2495 | fn eq(&self, other: &Self) -> bool { |
2496 | let (inner, other) = (self.0, other.0); |
2497 | ( |
2498 | inner.salg_family, |
2499 | &inner.salg_type[..], |
2500 | inner.salg_feat, |
2501 | inner.salg_mask, |
2502 | &inner.salg_name[..], |
2503 | ) == ( |
2504 | other.salg_family, |
2505 | &other.salg_type[..], |
2506 | other.salg_feat, |
2507 | other.salg_mask, |
2508 | &other.salg_name[..], |
2509 | ) |
2510 | } |
2511 | } |
2512 | |
2513 | impl Eq for AlgAddr {} |
2514 | |
2515 | impl Hash for AlgAddr { |
2516 | fn hash<H: Hasher>(&self, s: &mut H) { |
2517 | let inner = self.0; |
2518 | ( |
2519 | inner.salg_family, |
2520 | &inner.salg_type[..], |
2521 | inner.salg_feat, |
2522 | inner.salg_mask, |
2523 | &inner.salg_name[..], |
2524 | ) |
2525 | .hash(s); |
2526 | } |
2527 | } |
2528 | |
2529 | impl AlgAddr { |
2530 | /// Construct an `AF_ALG` socket from its cipher name and type. |
2531 | pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr { |
2532 | let mut addr: sockaddr_alg = unsafe { mem::zeroed() }; |
2533 | addr.salg_family = AF_ALG as u16; |
2534 | addr.salg_type[..alg_type.len()] |
2535 | .copy_from_slice(alg_type.to_string().as_bytes()); |
2536 | addr.salg_name[..alg_name.len()] |
2537 | .copy_from_slice(alg_name.to_string().as_bytes()); |
2538 | |
2539 | AlgAddr(addr) |
2540 | } |
2541 | |
2542 | /// Return the socket's cipher type, for example `hash` or `aead`. |
2543 | pub fn alg_type(&self) -> &CStr { |
2544 | unsafe { |
2545 | CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) |
2546 | } |
2547 | } |
2548 | |
2549 | /// Return the socket's cipher name, for example `sha1`. |
2550 | pub fn alg_name(&self) -> &CStr { |
2551 | unsafe { |
2552 | CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) |
2553 | } |
2554 | } |
2555 | } |
2556 | |
2557 | impl fmt::Display for AlgAddr { |
2558 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2559 | write!( |
2560 | f, |
2561 | "type: {} alg: {}" , |
2562 | self.alg_name().to_string_lossy(), |
2563 | self.alg_type().to_string_lossy() |
2564 | ) |
2565 | } |
2566 | } |
2567 | |
2568 | impl fmt::Debug for AlgAddr { |
2569 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2570 | fmt::Display::fmt(self, f) |
2571 | } |
2572 | } |
2573 | } |
2574 | |
2575 | feature! { |
2576 | #![feature = "ioctl" ] |
2577 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
2578 | pub mod sys_control { |
2579 | use crate::sys::socket::addr::AddressFamily; |
2580 | use libc::{self, c_uchar}; |
2581 | use std::{fmt, mem, ptr}; |
2582 | use std::os::unix::io::RawFd; |
2583 | use crate::{Errno, Result}; |
2584 | use super::{private, SockaddrLike}; |
2585 | |
2586 | // FIXME: Move type into `libc` |
2587 | #[repr (C)] |
2588 | #[derive (Clone, Copy)] |
2589 | #[allow (missing_debug_implementations)] |
2590 | pub struct ctl_ioc_info { |
2591 | pub ctl_id: u32, |
2592 | pub ctl_name: [c_uchar; MAX_KCTL_NAME], |
2593 | } |
2594 | |
2595 | const CTL_IOC_MAGIC: u8 = b'N' ; |
2596 | const CTL_IOC_INFO: u8 = 3; |
2597 | const MAX_KCTL_NAME: usize = 96; |
2598 | |
2599 | ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info); |
2600 | |
2601 | /// Apple system control socket |
2602 | /// |
2603 | /// # References |
2604 | /// |
2605 | /// <https://developer.apple.com/documentation/kernel/sockaddr_ctl> |
2606 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
2607 | #[repr (transparent)] |
2608 | pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl); |
2609 | |
2610 | impl private::SockaddrLikePriv for SysControlAddr {} |
2611 | impl SockaddrLike for SysControlAddr { |
2612 | unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>) |
2613 | -> Option<Self> where Self: Sized |
2614 | { |
2615 | if let Some(l) = len { |
2616 | if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t { |
2617 | return None; |
2618 | } |
2619 | } |
2620 | if (*addr).sa_family as i32 != libc::AF_SYSTEM { |
2621 | return None; |
2622 | } |
2623 | Some(Self(ptr::read_unaligned(addr as *const _))) |
2624 | } |
2625 | } |
2626 | |
2627 | impl AsRef<libc::sockaddr_ctl> for SysControlAddr { |
2628 | fn as_ref(&self) -> &libc::sockaddr_ctl { |
2629 | &self.0 |
2630 | } |
2631 | } |
2632 | |
2633 | impl SysControlAddr { |
2634 | /// Construct a new `SysControlAddr` from its kernel unique identifier |
2635 | /// and unit number. |
2636 | pub const fn new(id: u32, unit: u32) -> SysControlAddr { |
2637 | let addr = libc::sockaddr_ctl { |
2638 | sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar, |
2639 | sc_family: AddressFamily::System as c_uchar, |
2640 | ss_sysaddr: libc::AF_SYS_CONTROL as u16, |
2641 | sc_id: id, |
2642 | sc_unit: unit, |
2643 | sc_reserved: [0; 5] |
2644 | }; |
2645 | |
2646 | SysControlAddr(addr) |
2647 | } |
2648 | |
2649 | /// Construct a new `SysControlAddr` from its human readable name and |
2650 | /// unit number. |
2651 | pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> { |
2652 | if name.len() > MAX_KCTL_NAME { |
2653 | return Err(Errno::ENAMETOOLONG); |
2654 | } |
2655 | |
2656 | let mut ctl_name = [0; MAX_KCTL_NAME]; |
2657 | ctl_name[..name.len()].clone_from_slice(name.as_bytes()); |
2658 | let mut info = ctl_ioc_info { ctl_id: 0, ctl_name }; |
2659 | |
2660 | unsafe { ctl_info(sockfd, &mut info)?; } |
2661 | |
2662 | Ok(SysControlAddr::new(info.ctl_id, unit)) |
2663 | } |
2664 | |
2665 | /// Return the kernel unique identifier |
2666 | pub const fn id(&self) -> u32 { |
2667 | self.0.sc_id |
2668 | } |
2669 | |
2670 | /// Return the kernel controller private unit number. |
2671 | pub const fn unit(&self) -> u32 { |
2672 | self.0.sc_unit |
2673 | } |
2674 | } |
2675 | |
2676 | impl fmt::Display for SysControlAddr { |
2677 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2678 | fmt::Debug::fmt(self, f) |
2679 | } |
2680 | } |
2681 | } |
2682 | } |
2683 | |
2684 | #[cfg (any(target_os = "android" , target_os = "linux" , target_os = "fuchsia" ))] |
2685 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2686 | mod datalink { |
2687 | feature! { |
2688 | #![feature = "net" ] |
2689 | use super::{fmt, mem, private, ptr, SockaddrLike}; |
2690 | |
2691 | /// Hardware Address |
2692 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
2693 | #[repr (transparent)] |
2694 | pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll); |
2695 | |
2696 | impl LinkAddr { |
2697 | /// Physical-layer protocol |
2698 | pub fn protocol(&self) -> u16 { |
2699 | self.0.sll_protocol |
2700 | } |
2701 | |
2702 | /// Interface number |
2703 | pub fn ifindex(&self) -> usize { |
2704 | self.0.sll_ifindex as usize |
2705 | } |
2706 | |
2707 | /// ARP hardware type |
2708 | pub fn hatype(&self) -> u16 { |
2709 | self.0.sll_hatype |
2710 | } |
2711 | |
2712 | /// Packet type |
2713 | pub fn pkttype(&self) -> u8 { |
2714 | self.0.sll_pkttype |
2715 | } |
2716 | |
2717 | /// Length of MAC address |
2718 | pub fn halen(&self) -> usize { |
2719 | self.0.sll_halen as usize |
2720 | } |
2721 | |
2722 | /// Physical-layer address (MAC) |
2723 | // Returns an Option just for cross-platform compatibility |
2724 | pub fn addr(&self) -> Option<[u8; 6]> { |
2725 | Some([ |
2726 | self.0.sll_addr[0], |
2727 | self.0.sll_addr[1], |
2728 | self.0.sll_addr[2], |
2729 | self.0.sll_addr[3], |
2730 | self.0.sll_addr[4], |
2731 | self.0.sll_addr[5], |
2732 | ]) |
2733 | } |
2734 | } |
2735 | |
2736 | impl fmt::Display for LinkAddr { |
2737 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2738 | if let Some(addr) = self.addr() { |
2739 | write!(f, " {:02x}: {:02x}: {:02x}: {:02x}: {:02x}: {:02x}" , |
2740 | addr[0], |
2741 | addr[1], |
2742 | addr[2], |
2743 | addr[3], |
2744 | addr[4], |
2745 | addr[5]) |
2746 | } else { |
2747 | Ok(()) |
2748 | } |
2749 | } |
2750 | } |
2751 | impl private::SockaddrLikePriv for LinkAddr {} |
2752 | impl SockaddrLike for LinkAddr { |
2753 | unsafe fn from_raw(addr: *const libc::sockaddr, |
2754 | len: Option<libc::socklen_t>) |
2755 | -> Option<Self> where Self: Sized |
2756 | { |
2757 | if let Some(l) = len { |
2758 | if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t { |
2759 | return None; |
2760 | } |
2761 | } |
2762 | if (*addr).sa_family as i32 != libc::AF_PACKET { |
2763 | return None; |
2764 | } |
2765 | Some(Self(ptr::read_unaligned(addr as *const _))) |
2766 | } |
2767 | } |
2768 | |
2769 | impl AsRef<libc::sockaddr_ll> for LinkAddr { |
2770 | fn as_ref(&self) -> &libc::sockaddr_ll { |
2771 | &self.0 |
2772 | } |
2773 | } |
2774 | |
2775 | } |
2776 | } |
2777 | |
2778 | #[cfg (any( |
2779 | target_os = "dragonfly" , |
2780 | target_os = "freebsd" , |
2781 | target_os = "ios" , |
2782 | target_os = "macos" , |
2783 | target_os = "illumos" , |
2784 | target_os = "netbsd" , |
2785 | target_os = "haiku" , |
2786 | target_os = "openbsd" |
2787 | ))] |
2788 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2789 | mod datalink { |
2790 | feature! { |
2791 | #![feature = "net" ] |
2792 | use super::{fmt, mem, private, ptr, SockaddrLike}; |
2793 | |
2794 | /// Hardware Address |
2795 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
2796 | #[repr (transparent)] |
2797 | pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl); |
2798 | |
2799 | impl LinkAddr { |
2800 | /// interface index, if != 0, system given index for interface |
2801 | #[cfg (not(target_os = "haiku" ))] |
2802 | pub fn ifindex(&self) -> usize { |
2803 | self.0.sdl_index as usize |
2804 | } |
2805 | |
2806 | /// Datalink type |
2807 | #[cfg (not(target_os = "haiku" ))] |
2808 | pub fn datalink_type(&self) -> u8 { |
2809 | self.0.sdl_type |
2810 | } |
2811 | |
2812 | /// MAC address start position |
2813 | pub fn nlen(&self) -> usize { |
2814 | self.0.sdl_nlen as usize |
2815 | } |
2816 | |
2817 | /// link level address length |
2818 | pub fn alen(&self) -> usize { |
2819 | self.0.sdl_alen as usize |
2820 | } |
2821 | |
2822 | /// link layer selector length |
2823 | #[cfg (not(target_os = "haiku" ))] |
2824 | pub fn slen(&self) -> usize { |
2825 | self.0.sdl_slen as usize |
2826 | } |
2827 | |
2828 | /// if link level address length == 0, |
2829 | /// or `sdl_data` not be larger. |
2830 | pub fn is_empty(&self) -> bool { |
2831 | let nlen = self.nlen(); |
2832 | let alen = self.alen(); |
2833 | let data_len = self.0.sdl_data.len(); |
2834 | |
2835 | alen == 0 || nlen + alen >= data_len |
2836 | } |
2837 | |
2838 | /// Physical-layer address (MAC) |
2839 | // The cast is not unnecessary on all platforms. |
2840 | #[allow (clippy::unnecessary_cast)] |
2841 | pub fn addr(&self) -> Option<[u8; 6]> { |
2842 | let nlen = self.nlen(); |
2843 | let data = self.0.sdl_data; |
2844 | |
2845 | if self.is_empty() { |
2846 | None |
2847 | } else { |
2848 | Some([ |
2849 | data[nlen] as u8, |
2850 | data[nlen + 1] as u8, |
2851 | data[nlen + 2] as u8, |
2852 | data[nlen + 3] as u8, |
2853 | data[nlen + 4] as u8, |
2854 | data[nlen + 5] as u8, |
2855 | ]) |
2856 | } |
2857 | } |
2858 | } |
2859 | |
2860 | impl fmt::Display for LinkAddr { |
2861 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2862 | if let Some(addr) = self.addr() { |
2863 | write!(f, " {:02x}: {:02x}: {:02x}: {:02x}: {:02x}: {:02x}" , |
2864 | addr[0], |
2865 | addr[1], |
2866 | addr[2], |
2867 | addr[3], |
2868 | addr[4], |
2869 | addr[5]) |
2870 | } else { |
2871 | Ok(()) |
2872 | } |
2873 | } |
2874 | } |
2875 | impl private::SockaddrLikePriv for LinkAddr {} |
2876 | impl SockaddrLike for LinkAddr { |
2877 | unsafe fn from_raw(addr: *const libc::sockaddr, |
2878 | len: Option<libc::socklen_t>) |
2879 | -> Option<Self> where Self: Sized |
2880 | { |
2881 | if let Some(l) = len { |
2882 | if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t { |
2883 | return None; |
2884 | } |
2885 | } |
2886 | if (*addr).sa_family as i32 != libc::AF_LINK { |
2887 | return None; |
2888 | } |
2889 | Some(Self(ptr::read_unaligned(addr as *const _))) |
2890 | } |
2891 | } |
2892 | |
2893 | impl AsRef<libc::sockaddr_dl> for LinkAddr { |
2894 | fn as_ref(&self) -> &libc::sockaddr_dl { |
2895 | &self.0 |
2896 | } |
2897 | } |
2898 | } |
2899 | } |
2900 | |
2901 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
2902 | #[cfg_attr (docsrs, doc(cfg(all())))] |
2903 | pub mod vsock { |
2904 | use super::*; |
2905 | use crate::sys::socket::addr::AddressFamily; |
2906 | use libc::{sa_family_t, sockaddr_vm}; |
2907 | use std::hash::{Hash, Hasher}; |
2908 | use std::{fmt, mem}; |
2909 | |
2910 | /// Socket address for VMWare VSockets protocol |
2911 | /// |
2912 | /// # References |
2913 | /// |
2914 | /// [vsock(7)](https://man7.org/linux/man-pages/man7/vsock.7.html) |
2915 | #[derive (Copy, Clone)] |
2916 | #[repr (transparent)] |
2917 | pub struct VsockAddr(pub(in super::super) sockaddr_vm); |
2918 | |
2919 | impl private::SockaddrLikePriv for VsockAddr {} |
2920 | impl SockaddrLike for VsockAddr { |
2921 | unsafe fn from_raw( |
2922 | addr: *const libc::sockaddr, |
2923 | len: Option<libc::socklen_t>, |
2924 | ) -> Option<Self> |
2925 | where |
2926 | Self: Sized, |
2927 | { |
2928 | if let Some(l) = len { |
2929 | if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t { |
2930 | return None; |
2931 | } |
2932 | } |
2933 | if (*addr).sa_family as i32 != libc::AF_VSOCK { |
2934 | return None; |
2935 | } |
2936 | Some(Self(ptr::read_unaligned(addr as *const _))) |
2937 | } |
2938 | } |
2939 | |
2940 | impl AsRef<libc::sockaddr_vm> for VsockAddr { |
2941 | fn as_ref(&self) -> &libc::sockaddr_vm { |
2942 | &self.0 |
2943 | } |
2944 | } |
2945 | |
2946 | impl PartialEq for VsockAddr { |
2947 | fn eq(&self, other: &Self) -> bool { |
2948 | let (inner, other) = (self.0, other.0); |
2949 | (inner.svm_family, inner.svm_cid, inner.svm_port) |
2950 | == (other.svm_family, other.svm_cid, other.svm_port) |
2951 | } |
2952 | } |
2953 | |
2954 | impl Eq for VsockAddr {} |
2955 | |
2956 | impl Hash for VsockAddr { |
2957 | fn hash<H: Hasher>(&self, s: &mut H) { |
2958 | let inner = self.0; |
2959 | (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s); |
2960 | } |
2961 | } |
2962 | |
2963 | /// VSOCK Address |
2964 | /// |
2965 | /// The address for AF_VSOCK socket is defined as a combination of a |
2966 | /// 32-bit Context Identifier (CID) and a 32-bit port number. |
2967 | impl VsockAddr { |
2968 | /// Construct a `VsockAddr` from its raw fields. |
2969 | pub fn new(cid: u32, port: u32) -> VsockAddr { |
2970 | let mut addr: sockaddr_vm = unsafe { mem::zeroed() }; |
2971 | addr.svm_family = AddressFamily::Vsock as sa_family_t; |
2972 | addr.svm_cid = cid; |
2973 | addr.svm_port = port; |
2974 | |
2975 | VsockAddr(addr) |
2976 | } |
2977 | |
2978 | /// Context Identifier (CID) |
2979 | pub fn cid(&self) -> u32 { |
2980 | self.0.svm_cid |
2981 | } |
2982 | |
2983 | /// Port number |
2984 | pub fn port(&self) -> u32 { |
2985 | self.0.svm_port |
2986 | } |
2987 | } |
2988 | |
2989 | impl fmt::Display for VsockAddr { |
2990 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2991 | write!(f, "cid: {} port: {}" , self.cid(), self.port()) |
2992 | } |
2993 | } |
2994 | |
2995 | impl fmt::Debug for VsockAddr { |
2996 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2997 | fmt::Display::fmt(self, f) |
2998 | } |
2999 | } |
3000 | } |
3001 | |
3002 | #[cfg (test)] |
3003 | mod tests { |
3004 | use super::*; |
3005 | |
3006 | mod types { |
3007 | use super::*; |
3008 | |
3009 | #[test ] |
3010 | fn test_ipv4addr_to_libc() { |
3011 | let s = std::net::Ipv4Addr::new(1, 2, 3, 4); |
3012 | let l = ipv4addr_to_libc(s); |
3013 | assert_eq!(l.s_addr, u32::to_be(0x01020304)); |
3014 | } |
3015 | |
3016 | #[test ] |
3017 | fn test_ipv6addr_to_libc() { |
3018 | let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8); |
3019 | let l = ipv6addr_to_libc(&s); |
3020 | assert_eq!( |
3021 | l.s6_addr, |
3022 | [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8] |
3023 | ); |
3024 | } |
3025 | } |
3026 | |
3027 | mod link { |
3028 | #![allow (clippy::cast_ptr_alignment)] |
3029 | |
3030 | #[cfg (any( |
3031 | target_os = "ios" , |
3032 | target_os = "macos" , |
3033 | target_os = "illumos" |
3034 | ))] |
3035 | use super::super::super::socklen_t; |
3036 | use super::*; |
3037 | |
3038 | /// Don't panic when trying to display an empty datalink address |
3039 | #[cfg (any( |
3040 | target_os = "dragonfly" , |
3041 | target_os = "freebsd" , |
3042 | target_os = "ios" , |
3043 | target_os = "macos" , |
3044 | target_os = "netbsd" , |
3045 | target_os = "openbsd" |
3046 | ))] |
3047 | #[test ] |
3048 | fn test_datalink_display() { |
3049 | use super::super::LinkAddr; |
3050 | use std::mem; |
3051 | |
3052 | let la = LinkAddr(libc::sockaddr_dl { |
3053 | sdl_len: 56, |
3054 | sdl_family: 18, |
3055 | sdl_index: 5, |
3056 | sdl_type: 24, |
3057 | sdl_nlen: 3, |
3058 | sdl_alen: 0, |
3059 | sdl_slen: 0, |
3060 | ..unsafe { mem::zeroed() } |
3061 | }); |
3062 | format!(" {}" , la); |
3063 | } |
3064 | |
3065 | #[cfg (all( |
3066 | any( |
3067 | target_os = "android" , |
3068 | target_os = "fuchsia" , |
3069 | target_os = "linux" |
3070 | ), |
3071 | target_endian = "little" |
3072 | ))] |
3073 | #[test ] |
3074 | fn linux_loopback() { |
3075 | #[repr (align(2))] |
3076 | struct Raw([u8; 20]); |
3077 | |
3078 | let bytes = Raw([ |
3079 | 17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0, |
3080 | ]); |
3081 | let sa = bytes.0.as_ptr() as *const libc::sockaddr; |
3082 | let len = None; |
3083 | let sock_addr = |
3084 | unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap(); |
3085 | assert_eq!(sock_addr.family(), Some(AddressFamily::Packet)); |
3086 | match sock_addr.as_link_addr() { |
3087 | Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])), |
3088 | None => panic!("Can't unwrap sockaddr storage" ), |
3089 | } |
3090 | } |
3091 | |
3092 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
3093 | #[test ] |
3094 | fn macos_loopback() { |
3095 | let bytes = |
3096 | [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0]; |
3097 | let sa = bytes.as_ptr() as *const libc::sockaddr; |
3098 | let len = Some(bytes.len() as socklen_t); |
3099 | let sock_addr = |
3100 | unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap(); |
3101 | assert_eq!(sock_addr.family(), Some(AddressFamily::Link)); |
3102 | match sock_addr.as_link_addr() { |
3103 | Some(dl) => { |
3104 | assert!(dl.addr().is_none()); |
3105 | } |
3106 | None => panic!("Can't unwrap sockaddr storage" ), |
3107 | } |
3108 | } |
3109 | |
3110 | #[cfg (any(target_os = "ios" , target_os = "macos" ))] |
3111 | #[test ] |
3112 | fn macos_tap() { |
3113 | let bytes = [ |
3114 | 20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, |
3115 | 76, -80, |
3116 | ]; |
3117 | let ptr = bytes.as_ptr(); |
3118 | let sa = ptr as *const libc::sockaddr; |
3119 | let len = Some(bytes.len() as socklen_t); |
3120 | |
3121 | let sock_addr = |
3122 | unsafe { SockaddrStorage::from_raw(sa, len).unwrap() }; |
3123 | assert_eq!(sock_addr.family(), Some(AddressFamily::Link)); |
3124 | match sock_addr.as_link_addr() { |
3125 | Some(dl) => { |
3126 | assert_eq!(dl.addr(), Some([24u8, 101, 144, 221, 76, 176])) |
3127 | } |
3128 | None => panic!("Can't unwrap sockaddr storage" ), |
3129 | } |
3130 | } |
3131 | |
3132 | #[cfg (target_os = "illumos" )] |
3133 | #[test ] |
3134 | fn illumos_tap() { |
3135 | let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176]; |
3136 | let ptr = bytes.as_ptr(); |
3137 | let sa = ptr as *const libc::sockaddr; |
3138 | let len = Some(bytes.len() as socklen_t); |
3139 | let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }; |
3140 | |
3141 | assert!(_sock_addr.is_some()); |
3142 | |
3143 | let sock_addr = _sock_addr.unwrap(); |
3144 | |
3145 | assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link); |
3146 | |
3147 | assert_eq!( |
3148 | sock_addr.as_link_addr().unwrap().addr(), |
3149 | Some([24u8, 101, 144, 221, 76, 176]) |
3150 | ); |
3151 | } |
3152 | |
3153 | #[test ] |
3154 | fn size() { |
3155 | #[cfg (any( |
3156 | target_os = "dragonfly" , |
3157 | target_os = "freebsd" , |
3158 | target_os = "ios" , |
3159 | target_os = "macos" , |
3160 | target_os = "netbsd" , |
3161 | target_os = "illumos" , |
3162 | target_os = "openbsd" , |
3163 | target_os = "haiku" |
3164 | ))] |
3165 | let l = mem::size_of::<libc::sockaddr_dl>(); |
3166 | #[cfg (any( |
3167 | target_os = "android" , |
3168 | target_os = "fuchsia" , |
3169 | target_os = "linux" |
3170 | ))] |
3171 | let l = mem::size_of::<libc::sockaddr_ll>(); |
3172 | assert_eq!(LinkAddr::size() as usize, l); |
3173 | } |
3174 | } |
3175 | |
3176 | mod sockaddr_in { |
3177 | use super::*; |
3178 | use std::str::FromStr; |
3179 | |
3180 | #[test ] |
3181 | fn display() { |
3182 | let s = "127.0.0.1:8080" ; |
3183 | let addr = SockaddrIn::from_str(s).unwrap(); |
3184 | assert_eq!(s, format!(" {}" , addr)); |
3185 | } |
3186 | |
3187 | #[test ] |
3188 | fn size() { |
3189 | assert_eq!( |
3190 | mem::size_of::<libc::sockaddr_in>(), |
3191 | SockaddrIn::size() as usize |
3192 | ); |
3193 | } |
3194 | } |
3195 | |
3196 | mod sockaddr_in6 { |
3197 | use super::*; |
3198 | use std::str::FromStr; |
3199 | |
3200 | #[test ] |
3201 | fn display() { |
3202 | let s = "[1234:5678:90ab:cdef::1111:2222]:8080" ; |
3203 | let addr = SockaddrIn6::from_str(s).unwrap(); |
3204 | assert_eq!(s, format!(" {}" , addr)); |
3205 | } |
3206 | |
3207 | #[test ] |
3208 | fn size() { |
3209 | assert_eq!( |
3210 | mem::size_of::<libc::sockaddr_in6>(), |
3211 | SockaddrIn6::size() as usize |
3212 | ); |
3213 | } |
3214 | |
3215 | #[test ] |
3216 | // Ensure that we can convert to-and-from std::net variants without change. |
3217 | fn to_and_from() { |
3218 | let s = "[1234:5678:90ab:cdef::1111:2222]:8080" ; |
3219 | let mut nix_sin6 = SockaddrIn6::from_str(s).unwrap(); |
3220 | nix_sin6.0.sin6_flowinfo = 0x12345678; |
3221 | nix_sin6.0.sin6_scope_id = 0x9abcdef0; |
3222 | |
3223 | let std_sin6 : std::net::SocketAddrV6 = nix_sin6.into(); |
3224 | assert_eq!(nix_sin6, std_sin6.into()); |
3225 | } |
3226 | } |
3227 | |
3228 | mod sockaddr_storage { |
3229 | use super::*; |
3230 | |
3231 | #[test ] |
3232 | fn from_sockaddr_un_named() { |
3233 | let ua = UnixAddr::new("/var/run/mysock" ).unwrap(); |
3234 | let ptr = ua.as_ptr() as *const libc::sockaddr; |
3235 | let ss = unsafe { |
3236 | SockaddrStorage::from_raw(ptr, Some(ua.len())) |
3237 | }.unwrap(); |
3238 | assert_eq!(ss.len(), ua.len()); |
3239 | } |
3240 | |
3241 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
3242 | #[test ] |
3243 | fn from_sockaddr_un_abstract_named() { |
3244 | let name = String::from("nix \0abstract \0test" ); |
3245 | let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap(); |
3246 | let ptr = ua.as_ptr() as *const libc::sockaddr; |
3247 | let ss = unsafe { |
3248 | SockaddrStorage::from_raw(ptr, Some(ua.len())) |
3249 | }.unwrap(); |
3250 | assert_eq!(ss.len(), ua.len()); |
3251 | } |
3252 | |
3253 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
3254 | #[test ] |
3255 | fn from_sockaddr_un_abstract_unnamed() { |
3256 | let ua = UnixAddr::new_unnamed(); |
3257 | let ptr = ua.as_ptr() as *const libc::sockaddr; |
3258 | let ss = unsafe { |
3259 | SockaddrStorage::from_raw(ptr, Some(ua.len())) |
3260 | }.unwrap(); |
3261 | assert_eq!(ss.len(), ua.len()); |
3262 | } |
3263 | } |
3264 | |
3265 | mod unixaddr { |
3266 | use super::*; |
3267 | |
3268 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
3269 | #[test ] |
3270 | fn abstract_sun_path() { |
3271 | let name = String::from("nix \0abstract \0test" ); |
3272 | let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap(); |
3273 | |
3274 | let sun_path1 = |
3275 | unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] }; |
3276 | let sun_path2 = [ |
3277 | 0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, |
3278 | 116, 101, 115, 116, |
3279 | ]; |
3280 | assert_eq!(sun_path1, sun_path2); |
3281 | } |
3282 | |
3283 | #[test ] |
3284 | fn size() { |
3285 | assert_eq!( |
3286 | mem::size_of::<libc::sockaddr_un>(), |
3287 | UnixAddr::size() as usize |
3288 | ); |
3289 | } |
3290 | } |
3291 | } |
3292 | |