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