1 #[cfg(any(
2 bsd,
3 linux_android,
4 solarish,
5 target_os = "haiku",
6 target_os = "fuchsia",
7 target_os = "aix",
8 ))]
9 #[cfg(feature = "net")]
10 pub use self::datalink::LinkAddr;
11 #[cfg(any(linux_android, apple_targets))]
12 pub use self::vsock::VsockAddr;
13 use super::sa_family_t;
14 use crate::errno::Errno;
15 #[cfg(linux_android)]
16 use crate::sys::socket::addr::alg::AlgAddr;
17 #[cfg(linux_android)]
18 use crate::sys::socket::addr::netlink::NetlinkAddr;
19 #[cfg(all(feature = "ioctl", apple_targets))]
20 use crate::sys::socket::addr::sys_control::SysControlAddr;
21 use crate::{NixPath, Result};
22 use cfg_if::cfg_if;
23 use memoffset::offset_of;
24 use std::convert::TryInto;
25 use std::ffi::OsStr;
26 use std::hash::{Hash, Hasher};
27 use std::net::{Ipv4Addr, Ipv6Addr};
28 use std::os::unix::ffi::OsStrExt;
29 use std::path::Path;
30 use std::{fmt, mem, net, ptr, slice};
31
32 /// Convert a std::net::Ipv4Addr into the libc form.
33 #[cfg(feature = "net")]
ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr34 pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
35 libc::in_addr {
36 s_addr: u32::from_ne_bytes(addr.octets()),
37 }
38 }
39
40 /// Convert a std::net::Ipv6Addr into the libc form.
41 #[cfg(feature = "net")]
ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr42 pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr {
43 libc::in6_addr {
44 s6_addr: addr.octets(),
45 }
46 }
47
48 /// These constants specify the protocol family to be used
49 /// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
50 ///
51 /// # References
52 ///
53 /// [address_families(7)](https://man7.org/linux/man-pages/man7/address_families.7.html)
54 // Should this be u8?
55 #[repr(i32)]
56 #[non_exhaustive]
57 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
58 pub enum AddressFamily {
59 /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
60 Unix = libc::AF_UNIX,
61 /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
62 Inet = libc::AF_INET,
63 /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
64 Inet6 = libc::AF_INET6,
65 /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
66 #[cfg(linux_android)]
67 Netlink = libc::AF_NETLINK,
68 /// Kernel interface for interacting with the routing table
69 #[cfg(not(any(linux_android, target_os = "redox")))]
70 Route = libc::PF_ROUTE,
71 /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
72 #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
73 Packet = libc::AF_PACKET,
74 /// KEXT Controls and Notifications
75 #[cfg(apple_targets)]
76 System = libc::AF_SYSTEM,
77 /// Amateur radio AX.25 protocol
78 #[cfg(linux_android)]
79 Ax25 = libc::AF_AX25,
80 /// IPX - Novell protocols
81 #[cfg(not(any(target_os = "aix", target_os = "redox")))]
82 Ipx = libc::AF_IPX,
83 /// AppleTalk
84 #[cfg(not(target_os = "redox"))]
85 AppleTalk = libc::AF_APPLETALK,
86 /// AX.25 packet layer protocol.
87 /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
88 #[cfg(linux_android)]
89 NetRom = libc::AF_NETROM,
90 /// Can't be used for creating sockets; mostly used for bridge
91 /// links in
92 /// [rtnetlink(7)](https://man7.org/linux/man-pages/man7/rtnetlink.7.html)
93 /// protocol commands.
94 #[cfg(linux_android)]
95 Bridge = libc::AF_BRIDGE,
96 /// Access to raw ATM PVCs
97 #[cfg(linux_android)]
98 AtmPvc = libc::AF_ATMPVC,
99 /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
100 #[cfg(linux_android)]
101 X25 = libc::AF_X25,
102 /// RATS (Radio Amateur Telecommunications Society) Open
103 /// Systems environment (ROSE) AX.25 packet layer protocol.
104 /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
105 #[cfg(linux_android)]
106 Rose = libc::AF_ROSE,
107 /// DECet protocol sockets.
108 #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
109 Decnet = libc::AF_DECnet,
110 /// Reserved for "802.2LLC project"; never used.
111 #[cfg(linux_android)]
112 NetBeui = libc::AF_NETBEUI,
113 /// This was a short-lived (between Linux 2.1.30 and
114 /// 2.1.99pre2) protocol family for firewall upcalls.
115 #[cfg(linux_android)]
116 Security = libc::AF_SECURITY,
117 /// Key management protocol.
118 #[cfg(linux_android)]
119 Key = libc::AF_KEY,
120 #[allow(missing_docs)] // Not documented anywhere that I can find
121 #[cfg(linux_android)]
122 Ash = libc::AF_ASH,
123 /// Acorn Econet protocol
124 #[cfg(linux_android)]
125 Econet = libc::AF_ECONET,
126 /// Access to ATM Switched Virtual Circuits
127 #[cfg(linux_android)]
128 AtmSvc = libc::AF_ATMSVC,
129 /// Reliable Datagram Sockets (RDS) protocol
130 #[cfg(linux_android)]
131 Rds = libc::AF_RDS,
132 /// IBM SNA
133 #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
134 Sna = libc::AF_SNA,
135 /// Socket interface over IrDA
136 #[cfg(linux_android)]
137 Irda = libc::AF_IRDA,
138 /// Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
139 #[cfg(linux_android)]
140 Pppox = libc::AF_PPPOX,
141 /// Legacy protocol for wide area network (WAN) connectivity that was used
142 /// by Sangoma WAN cards
143 #[cfg(linux_android)]
144 Wanpipe = libc::AF_WANPIPE,
145 /// Logical link control (IEEE 802.2 LLC) protocol
146 #[cfg(linux_android)]
147 Llc = libc::AF_LLC,
148 /// InfiniBand native addressing
149 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
150 Ib = libc::AF_IB,
151 /// Multiprotocol Label Switching
152 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
153 Mpls = libc::AF_MPLS,
154 /// Controller Area Network automotive bus protocol
155 #[cfg(linux_android)]
156 Can = libc::AF_CAN,
157 /// TIPC, "cluster domain sockets" protocol
158 #[cfg(linux_android)]
159 Tipc = libc::AF_TIPC,
160 /// Bluetooth low-level socket protocol
161 #[cfg(not(any(
162 target_os = "aix",
163 solarish,
164 apple_targets,
165 target_os = "hurd",
166 target_os = "redox",
167 )))]
168 Bluetooth = libc::AF_BLUETOOTH,
169 /// IUCV (inter-user communication vehicle) z/VM protocol for
170 /// hypervisor-guest interaction
171 #[cfg(linux_android)]
172 Iucv = libc::AF_IUCV,
173 /// Rx, Andrew File System remote procedure call protocol
174 #[cfg(linux_android)]
175 RxRpc = libc::AF_RXRPC,
176 /// New "modular ISDN" driver interface protocol
177 #[cfg(not(any(
178 target_os = "aix",
179 solarish,
180 target_os = "haiku",
181 target_os = "hurd",
182 target_os = "redox",
183 )))]
184 Isdn = libc::AF_ISDN,
185 /// Nokia cellular modem IPC/RPC interface
186 #[cfg(linux_android)]
187 Phonet = libc::AF_PHONET,
188 /// IEEE 802.15.4 WPAN (wireless personal area network) raw packet protocol
189 #[cfg(linux_android)]
190 Ieee802154 = libc::AF_IEEE802154,
191 /// Ericsson's Communication CPU to Application CPU interface (CAIF)
192 /// protocol.
193 #[cfg(linux_android)]
194 Caif = libc::AF_CAIF,
195 /// Interface to kernel crypto API
196 #[cfg(linux_android)]
197 Alg = libc::AF_ALG,
198 /// Near field communication
199 #[cfg(target_os = "linux")]
200 Nfc = libc::AF_NFC,
201 /// VMWare VSockets protocol for hypervisor-guest interaction.
202 #[cfg(any(linux_android, apple_targets))]
203 Vsock = libc::AF_VSOCK,
204 /// ARPANet IMP addresses
205 #[cfg(bsd)]
206 ImpLink = libc::AF_IMPLINK,
207 /// PUP protocols, e.g. BSP
208 #[cfg(bsd)]
209 Pup = libc::AF_PUP,
210 /// MIT CHAOS protocols
211 #[cfg(bsd)]
212 Chaos = libc::AF_CHAOS,
213 /// Novell and Xerox protocol
214 #[cfg(any(apple_targets, netbsdlike))]
215 Ns = libc::AF_NS,
216 #[allow(missing_docs)] // Not documented anywhere that I can find
217 #[cfg(bsd)]
218 Iso = libc::AF_ISO,
219 /// Bell Labs virtual circuit switch ?
220 #[cfg(bsd)]
221 Datakit = libc::AF_DATAKIT,
222 /// CCITT protocols, X.25 etc
223 #[cfg(bsd)]
224 Ccitt = libc::AF_CCITT,
225 /// DEC Direct data link interface
226 #[cfg(bsd)]
227 Dli = libc::AF_DLI,
228 #[allow(missing_docs)] // Not documented anywhere that I can find
229 #[cfg(bsd)]
230 Lat = libc::AF_LAT,
231 /// NSC Hyperchannel
232 #[cfg(bsd)]
233 Hylink = libc::AF_HYLINK,
234 /// Link layer interface
235 #[cfg(any(bsd, solarish))]
236 Link = libc::AF_LINK,
237 /// connection-oriented IP, aka ST II
238 #[cfg(bsd)]
239 Coip = libc::AF_COIP,
240 /// Computer Network Technology
241 #[cfg(bsd)]
242 Cnt = libc::AF_CNT,
243 /// Native ATM access
244 #[cfg(bsd)]
245 Natm = libc::AF_NATM,
246 /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
247 #[cfg(linux_android)]
248 Unspec = libc::AF_UNSPEC,
249 }
250
251 impl AddressFamily {
252 /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
253 /// the `sa_family` field of a `sockaddr`.
254 ///
255 /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
256 /// and System. Returns None for unsupported or unknown address families.
from_i32(family: i32) -> Option<AddressFamily>257 pub const fn from_i32(family: i32) -> Option<AddressFamily> {
258 match family {
259 libc::AF_UNIX => Some(AddressFamily::Unix),
260 libc::AF_INET => Some(AddressFamily::Inet),
261 libc::AF_INET6 => Some(AddressFamily::Inet6),
262 #[cfg(linux_android)]
263 libc::AF_NETLINK => Some(AddressFamily::Netlink),
264 #[cfg(apple_targets)]
265 libc::AF_SYSTEM => Some(AddressFamily::System),
266 #[cfg(not(any(linux_android, target_os = "redox")))]
267 libc::PF_ROUTE => Some(AddressFamily::Route),
268 #[cfg(linux_android)]
269 libc::AF_PACKET => Some(AddressFamily::Packet),
270 #[cfg(any(bsd, solarish))]
271 libc::AF_LINK => Some(AddressFamily::Link),
272 #[cfg(any(linux_android, apple_targets))]
273 libc::AF_VSOCK => Some(AddressFamily::Vsock),
274 _ => None,
275 }
276 }
277 }
278
279 /// A wrapper around `sockaddr_un`.
280 #[derive(Clone, Copy, Debug)]
281 #[repr(C)]
282 pub struct UnixAddr {
283 // INVARIANT: sun & sun_len are valid as defined by docs for from_raw_parts
284 sun: libc::sockaddr_un,
285 /// The length of the valid part of `sun`, including the sun_family field
286 /// but excluding any trailing nul.
287 // On the BSDs, this field is built into sun
288 #[cfg(not(any(bsd, target_os = "haiku", target_os = "hurd")))]
289 sun_len: u8,
290 }
291
292 // linux man page unix(7) says there are 3 kinds of unix socket:
293 // pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
294 // unnamed: addrlen = sizeof(sa_family_t)
295 // abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))]
296 //
297 // what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path)
298 #[derive(PartialEq, Eq, Hash)]
299 enum UnixAddrKind<'a> {
300 Pathname(&'a Path),
301 Unnamed,
302 #[cfg(linux_android)]
303 Abstract(&'a [u8]),
304 }
305 impl<'a> UnixAddrKind<'a> {
306 /// Safety: sun & sun_len must be valid
307 #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self308 unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self {
309 assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path));
310 let path_len =
311 sun_len as usize - offset_of!(libc::sockaddr_un, sun_path);
312 if path_len == 0 {
313 return Self::Unnamed;
314 }
315 #[cfg(linux_android)]
316 if sun.sun_path[0] == 0 {
317 let name = unsafe {
318 slice::from_raw_parts(
319 sun.sun_path.as_ptr().add(1).cast(),
320 path_len - 1,
321 )
322 };
323 return Self::Abstract(name);
324 }
325 let pathname = unsafe {
326 slice::from_raw_parts(sun.sun_path.as_ptr().cast(), path_len)
327 };
328 if pathname.last() == Some(&0) {
329 // A trailing NUL is not considered part of the path, and it does
330 // not need to be included in the addrlen passed to functions like
331 // bind(). However, Linux adds a trailing NUL, even if one was not
332 // originally present, when returning addrs from functions like
333 // getsockname() (the BSDs do not do that). So we need to filter
334 // out any trailing NUL here, so sockaddrs can round-trip through
335 // the kernel and still compare equal.
336 Self::Pathname(Path::new(OsStr::from_bytes(
337 &pathname[0..pathname.len() - 1],
338 )))
339 } else {
340 Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
341 }
342 }
343 }
344
345 impl UnixAddr {
346 /// Create a new sockaddr_un representing a filesystem path.
347 #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr>348 pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
349 path.with_nix_path(|cstr| unsafe {
350 let mut ret = libc::sockaddr_un {
351 sun_family: AddressFamily::Unix as sa_family_t,
352 ..mem::zeroed()
353 };
354
355 let bytes = cstr.to_bytes();
356
357 if bytes.len() >= ret.sun_path.len() {
358 return Err(Errno::ENAMETOOLONG);
359 }
360
361 let sun_len = (bytes.len()
362 + offset_of!(libc::sockaddr_un, sun_path))
363 .try_into()
364 .unwrap();
365
366 #[cfg(any(bsd, target_os = "haiku", target_os = "hurd"))]
367 {
368 ret.sun_len = sun_len;
369 }
370 ptr::copy_nonoverlapping(
371 bytes.as_ptr(),
372 ret.sun_path.as_mut_ptr().cast(),
373 bytes.len(),
374 );
375
376 Ok(UnixAddr::from_raw_parts(ret, sun_len))
377 })?
378 }
379
380 /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
381 ///
382 /// The leading nul byte for the abstract namespace is automatically added;
383 /// thus the input `path` is expected to be the bare name, not NUL-prefixed.
384 /// This is a Linux-specific extension, primarily used to allow chrooted
385 /// processes to communicate with processes having a different filesystem view.
386 #[cfg(linux_android)]
387 #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
new_abstract(path: &[u8]) -> Result<UnixAddr>388 pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
389 unsafe {
390 let mut ret = libc::sockaddr_un {
391 sun_family: AddressFamily::Unix as sa_family_t,
392 ..mem::zeroed()
393 };
394
395 if path.len() >= ret.sun_path.len() {
396 return Err(Errno::ENAMETOOLONG);
397 }
398 let sun_len =
399 (path.len() + 1 + offset_of!(libc::sockaddr_un, sun_path))
400 .try_into()
401 .unwrap();
402
403 // Abstract addresses are represented by sun_path[0] ==
404 // b'\0', so copy starting one byte in.
405 ptr::copy_nonoverlapping(
406 path.as_ptr(),
407 ret.sun_path.as_mut_ptr().offset(1).cast(),
408 path.len(),
409 );
410
411 Ok(UnixAddr::from_raw_parts(ret, sun_len))
412 }
413 }
414
415 /// Create a new `sockaddr_un` representing an "unnamed" unix socket address.
416 #[cfg(linux_android)]
new_unnamed() -> UnixAddr417 pub fn new_unnamed() -> UnixAddr {
418 let ret = libc::sockaddr_un {
419 sun_family: AddressFamily::Unix as sa_family_t,
420 ..unsafe { mem::zeroed() }
421 };
422
423 let sun_len: u8 =
424 offset_of!(libc::sockaddr_un, sun_path).try_into().unwrap();
425
426 unsafe { UnixAddr::from_raw_parts(ret, sun_len) }
427 }
428
429 /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `sun_len`
430 /// is the size of the valid portion of the struct, excluding any trailing
431 /// NUL.
432 ///
433 /// # Safety
434 /// This pair of sockaddr_un & sun_len must be a valid unix addr, which
435 /// means:
436 /// - sun_len >= offset_of(sockaddr_un, sun_path)
437 /// - sun_len <= sockaddr_un.sun_path.len() - offset_of(sockaddr_un, sun_path)
438 /// - if this is a unix addr with a pathname, sun.sun_path is a
439 /// fs path, not necessarily nul-terminated.
from_raw_parts( sun: libc::sockaddr_un, sun_len: u8, ) -> UnixAddr440 pub(crate) unsafe fn from_raw_parts(
441 sun: libc::sockaddr_un,
442 sun_len: u8,
443 ) -> UnixAddr {
444 cfg_if! {
445 if #[cfg(any(linux_android,
446 target_os = "fuchsia",
447 solarish,
448 target_os = "redox",
449 ))]
450 {
451 UnixAddr { sun, sun_len }
452 } else {
453 assert_eq!(sun_len, sun.sun_len);
454 UnixAddr {sun}
455 }
456 }
457 }
458
kind(&self) -> UnixAddrKind<'_>459 fn kind(&self) -> UnixAddrKind<'_> {
460 // SAFETY: our sockaddr is always valid because of the invariant on the struct
461 unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) }
462 }
463
464 /// If this address represents a filesystem path, return that path.
path(&self) -> Option<&Path>465 pub fn path(&self) -> Option<&Path> {
466 match self.kind() {
467 UnixAddrKind::Pathname(path) => Some(path),
468 _ => None,
469 }
470 }
471
472 /// If this address represents an abstract socket, return its name.
473 ///
474 /// For abstract sockets only the bare name is returned, without the
475 /// leading NUL byte. `None` is returned for unnamed or path-backed sockets.
476 #[cfg(linux_android)]
as_abstract(&self) -> Option<&[u8]>477 pub fn as_abstract(&self) -> Option<&[u8]> {
478 match self.kind() {
479 UnixAddrKind::Abstract(name) => Some(name),
480 _ => None,
481 }
482 }
483
484 /// Check if this address is an "unnamed" unix socket address.
485 #[cfg(linux_android)]
486 #[inline]
is_unnamed(&self) -> bool487 pub fn is_unnamed(&self) -> bool {
488 matches!(self.kind(), UnixAddrKind::Unnamed)
489 }
490
491 /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
492 #[inline]
path_len(&self) -> usize493 pub fn path_len(&self) -> usize {
494 self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path)
495 }
496 /// Returns a pointer to the raw `sockaddr_un` struct
497 #[inline]
as_ptr(&self) -> *const libc::sockaddr_un498 pub fn as_ptr(&self) -> *const libc::sockaddr_un {
499 &self.sun
500 }
501 /// Returns a mutable pointer to the raw `sockaddr_un` struct
502 #[inline]
as_mut_ptr(&mut self) -> *mut libc::sockaddr_un503 pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
504 &mut self.sun
505 }
506
sun_len(&self) -> u8507 fn sun_len(&self) -> u8 {
508 cfg_if! {
509 if #[cfg(any(linux_android,
510 target_os = "fuchsia",
511 solarish,
512 target_os = "redox",
513 ))]
514 {
515 self.sun_len
516 } else {
517 self.sun.sun_len
518 }
519 }
520 }
521 }
522
523 impl private::SockaddrLikePriv for UnixAddr {}
524 impl SockaddrLike for UnixAddr {
525 #[cfg(any(
526 linux_android,
527 target_os = "fuchsia",
528 solarish,
529 target_os = "redox"
530 ))]
len(&self) -> libc::socklen_t531 fn len(&self) -> libc::socklen_t {
532 self.sun_len.into()
533 }
534
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,535 unsafe fn from_raw(
536 addr: *const libc::sockaddr,
537 len: Option<libc::socklen_t>,
538 ) -> Option<Self>
539 where
540 Self: Sized,
541 {
542 if let Some(l) = len {
543 if (l as usize) < offset_of!(libc::sockaddr_un, sun_path)
544 || l > u8::MAX as libc::socklen_t
545 {
546 return None;
547 }
548 }
549 if unsafe { (*addr).sa_family as i32 != libc::AF_UNIX } {
550 return None;
551 }
552 let mut su: libc::sockaddr_un = unsafe { mem::zeroed() };
553 let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
554 cfg_if! {
555 if #[cfg(any(linux_android,
556 target_os = "fuchsia",
557 solarish,
558 target_os = "redox",
559 ))] {
560 let su_len = len.unwrap_or(
561 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
562 );
563 } else {
564 let su_len = unsafe { len.unwrap_or((*addr).sa_len as libc::socklen_t) };
565 }
566 }
567 unsafe { ptr::copy(addr as *const u8, sup, su_len as usize) };
568 Some(unsafe { Self::from_raw_parts(su, su_len as u8) })
569 }
570
size() -> libc::socklen_t where Self: Sized,571 fn size() -> libc::socklen_t
572 where
573 Self: Sized,
574 {
575 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
576 }
577
set_length( &mut self, new_length: usize, ) -> std::result::Result<(), SocketAddressLengthNotDynamic>578 unsafe fn set_length(
579 &mut self,
580 new_length: usize,
581 ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
582 // `new_length` is only used on some platforms, so it must be provided even when not used
583 #![allow(unused_variables)]
584 cfg_if! {
585 if #[cfg(any(linux_android,
586 target_os = "fuchsia",
587 solarish,
588 target_os = "redox",
589 ))] {
590 self.sun_len = new_length as u8;
591 }
592 };
593 Ok(())
594 }
595 }
596
597 impl AsRef<libc::sockaddr_un> for UnixAddr {
as_ref(&self) -> &libc::sockaddr_un598 fn as_ref(&self) -> &libc::sockaddr_un {
599 &self.sun
600 }
601 }
602
603 #[cfg(linux_android)]
fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result604 fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
605 use fmt::Write;
606 f.write_str("@\"")?;
607 for &b in abs {
608 use fmt::Display;
609 char::from(b).escape_default().fmt(f)?;
610 }
611 f.write_char('"')?;
612 Ok(())
613 }
614
615 impl fmt::Display for UnixAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result616 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
617 match self.kind() {
618 UnixAddrKind::Pathname(path) => path.display().fmt(f),
619 UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
620 #[cfg(linux_android)]
621 UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
622 }
623 }
624 }
625
626 impl PartialEq for UnixAddr {
eq(&self, other: &UnixAddr) -> bool627 fn eq(&self, other: &UnixAddr) -> bool {
628 self.kind() == other.kind()
629 }
630 }
631
632 impl Eq for UnixAddr {}
633
634 impl Hash for UnixAddr {
hash<H: Hasher>(&self, s: &mut H)635 fn hash<H: Hasher>(&self, s: &mut H) {
636 self.kind().hash(s)
637 }
638 }
639
640 /// Anything that, in C, can be cast back and forth to `sockaddr`.
641 ///
642 /// Most implementors also implement `AsRef<libc::XXX>` to access their
643 /// inner type read-only.
644 #[allow(clippy::len_without_is_empty)]
645 pub trait SockaddrLike: private::SockaddrLikePriv {
646 /// Returns a raw pointer to the inner structure. Useful for FFI.
as_ptr(&self) -> *const libc::sockaddr647 fn as_ptr(&self) -> *const libc::sockaddr {
648 self as *const Self as *const libc::sockaddr
649 }
650
651 /// Unsafe constructor from a variable length source
652 ///
653 /// Some C APIs from provide `len`, and others do not. If it's provided it
654 /// will be validated. If not, it will be guessed based on the family.
655 ///
656 /// # Arguments
657 ///
658 /// - `addr`: raw pointer to something that can be cast to a
659 /// `libc::sockaddr`. For example, `libc::sockaddr_in`,
660 /// `libc::sockaddr_in6`, etc.
661 /// - `len`: For fixed-width types like `sockaddr_in`, it will be
662 /// validated if present and ignored if not. For variable-width
663 /// types it is required and must be the total length of valid
664 /// data. For example, if `addr` points to a
665 /// named `sockaddr_un`, then `len` must be the length of the
666 /// structure up to but not including the trailing NUL.
667 ///
668 /// # Safety
669 ///
670 /// `addr` must be valid for the specific type of sockaddr. `len`, if
671 /// 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: Sized672 unsafe fn from_raw(
673 addr: *const libc::sockaddr,
674 len: Option<libc::socklen_t>,
675 ) -> Option<Self>
676 where
677 Self: Sized;
678
679 /// Return the address family of this socket
680 ///
681 /// # Examples
682 /// One common use is to match on the family of a union type, like this:
683 /// ```
684 /// # use nix::sys::socket::*;
685 /// # use std::os::unix::io::AsRawFd;
686 /// let fd = socket(AddressFamily::Inet, SockType::Stream,
687 /// SockFlag::empty(), None).unwrap();
688 /// let ss: SockaddrStorage = getsockname(fd.as_raw_fd()).unwrap();
689 /// match ss.family().unwrap() {
690 /// AddressFamily::Inet => println!("{}", ss.as_sockaddr_in().unwrap()),
691 /// AddressFamily::Inet6 => println!("{}", ss.as_sockaddr_in6().unwrap()),
692 /// _ => println!("Unexpected address family")
693 /// }
694 /// ```
family(&self) -> Option<AddressFamily>695 fn family(&self) -> Option<AddressFamily> {
696 // Safe since all implementors have a sa_family field at the same
697 // address, and they're all repr(C)
698 AddressFamily::from_i32(unsafe {
699 (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
700 })
701 }
702
703 cfg_if! {
704 if #[cfg(bsd)] {
705 /// Return the length of valid data in the sockaddr structure.
706 ///
707 /// For fixed-size sockaddrs, this should be the size of the
708 /// structure. But for variable-sized types like [`UnixAddr`] it
709 /// may be less.
710 fn len(&self) -> libc::socklen_t {
711 // Safe since all implementors have a sa_len field at the same
712 // address, and they're all repr(transparent).
713 // Robust for all implementors.
714 unsafe {
715 (*(self as *const Self as *const libc::sockaddr)).sa_len
716 }.into()
717 }
718 } else {
719 /// Return the length of valid data in the sockaddr structure.
720 ///
721 /// For fixed-size sockaddrs, this should be the size of the
722 /// structure. But for variable-sized types like [`UnixAddr`] it
723 /// may be less.
724 fn len(&self) -> libc::socklen_t {
725 // No robust default implementation is possible without an
726 // sa_len field. Implementors with a variable size must
727 // override this method.
728 mem::size_of_val(self) as libc::socklen_t
729 }
730 }
731 }
732
733 /// Return the available space in the structure
size() -> libc::socklen_t where Self: Sized,734 fn size() -> libc::socklen_t
735 where
736 Self: Sized,
737 {
738 mem::size_of::<Self>() as libc::socklen_t
739 }
740
741 /// Set the length of this socket address
742 ///
743 /// This method may only be called on socket addresses whose lengths are dynamic, and it
744 /// returns an error if called on a type whose length is static.
745 ///
746 /// # Safety
747 ///
748 /// `new_length` must be a valid length for this type of address. Specifically, reads of that
749 /// length from `self` must be valid.
750 #[doc(hidden)]
set_length( &mut self, _new_length: usize, ) -> std::result::Result<(), SocketAddressLengthNotDynamic>751 unsafe fn set_length(
752 &mut self,
753 _new_length: usize,
754 ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
755 Err(SocketAddressLengthNotDynamic)
756 }
757 }
758
759 /// The error returned by [`SockaddrLike::set_length`] on an address whose length is statically
760 /// fixed.
761 #[derive(Copy, Clone, Debug)]
762 pub struct SocketAddressLengthNotDynamic;
763 impl fmt::Display for SocketAddressLengthNotDynamic {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result764 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
765 f.write_str("Attempted to set length on socket whose length is statically fixed")
766 }
767 }
768 impl std::error::Error for SocketAddressLengthNotDynamic {}
769
770 impl private::SockaddrLikePriv for () {
as_mut_ptr(&mut self) -> *mut libc::sockaddr771 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
772 ptr::null_mut()
773 }
774 }
775
776 /// `()` can be used in place of a real Sockaddr when no address is expected,
777 /// for example for a field of `Option<S> where S: SockaddrLike`.
778 // If this RFC ever stabilizes, then ! will be a better choice.
779 // https://github.com/rust-lang/rust/issues/35121
780 impl SockaddrLike for () {
as_ptr(&self) -> *const libc::sockaddr781 fn as_ptr(&self) -> *const libc::sockaddr {
782 ptr::null()
783 }
784
from_raw( _: *const libc::sockaddr, _: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,785 unsafe fn from_raw(
786 _: *const libc::sockaddr,
787 _: Option<libc::socklen_t>,
788 ) -> Option<Self>
789 where
790 Self: Sized,
791 {
792 None
793 }
794
family(&self) -> Option<AddressFamily>795 fn family(&self) -> Option<AddressFamily> {
796 None
797 }
798
len(&self) -> libc::socklen_t799 fn len(&self) -> libc::socklen_t {
800 0
801 }
802 }
803
804 /// An IPv4 socket address
805 #[cfg(feature = "net")]
806 #[repr(transparent)]
807 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
808 pub struct SockaddrIn(libc::sockaddr_in);
809
810 #[cfg(feature = "net")]
811 impl SockaddrIn {
812 /// Returns the IP address associated with this socket address, in native
813 /// endian.
ip(&self) -> net::Ipv4Addr814 pub const fn ip(&self) -> net::Ipv4Addr {
815 let bytes = self.0.sin_addr.s_addr.to_ne_bytes();
816 let (a, b, c, d) = (bytes[0], bytes[1], bytes[2], bytes[3]);
817 Ipv4Addr::new(a, b, c, d)
818 }
819
820 /// Creates a new socket address from IPv4 octets and a port number.
new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self821 pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
822 Self(libc::sockaddr_in {
823 #[cfg(any(
824 bsd,
825 target_os = "aix",
826 target_os = "haiku",
827 target_os = "hurd"
828 ))]
829 sin_len: Self::size() as u8,
830 sin_family: AddressFamily::Inet as sa_family_t,
831 sin_port: u16::to_be(port),
832 sin_addr: libc::in_addr {
833 s_addr: u32::from_ne_bytes([a, b, c, d]),
834 },
835 sin_zero: unsafe { mem::zeroed() },
836 })
837 }
838
839 /// Returns the port number associated with this socket address, in native
840 /// endian.
port(&self) -> u16841 pub const fn port(&self) -> u16 {
842 u16::from_be(self.0.sin_port)
843 }
844 }
845
846 #[cfg(feature = "net")]
847 impl private::SockaddrLikePriv for SockaddrIn {}
848 #[cfg(feature = "net")]
849 impl SockaddrLike for SockaddrIn {
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,850 unsafe fn from_raw(
851 addr: *const libc::sockaddr,
852 len: Option<libc::socklen_t>,
853 ) -> Option<Self>
854 where
855 Self: Sized,
856 {
857 if let Some(l) = len {
858 if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t {
859 return None;
860 }
861 }
862 if unsafe { (*addr).sa_family as i32 != libc::AF_INET } {
863 return None;
864 }
865 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
866 }
867 }
868
869 #[cfg(feature = "net")]
870 impl AsRef<libc::sockaddr_in> for SockaddrIn {
as_ref(&self) -> &libc::sockaddr_in871 fn as_ref(&self) -> &libc::sockaddr_in {
872 &self.0
873 }
874 }
875
876 #[cfg(feature = "net")]
877 impl fmt::Display for SockaddrIn {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result878 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
879 let ne = u32::from_be(self.0.sin_addr.s_addr);
880 let port = u16::from_be(self.0.sin_port);
881 write!(
882 f,
883 "{}.{}.{}.{}:{}",
884 ne >> 24,
885 (ne >> 16) & 0xFF,
886 (ne >> 8) & 0xFF,
887 ne & 0xFF,
888 port
889 )
890 }
891 }
892
893 #[cfg(feature = "net")]
894 impl From<net::SocketAddrV4> for SockaddrIn {
from(addr: net::SocketAddrV4) -> Self895 fn from(addr: net::SocketAddrV4) -> Self {
896 Self(libc::sockaddr_in {
897 #[cfg(any(
898 bsd,
899 target_os = "haiku",
900 target_os = "hermit",
901 target_os = "hurd"
902 ))]
903 sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
904 sin_family: AddressFamily::Inet as sa_family_t,
905 sin_port: addr.port().to_be(), // network byte order
906 sin_addr: ipv4addr_to_libc(*addr.ip()),
907 ..unsafe { mem::zeroed() }
908 })
909 }
910 }
911
912 #[cfg(feature = "net")]
913 impl From<SockaddrIn> for net::SocketAddrV4 {
from(addr: SockaddrIn) -> Self914 fn from(addr: SockaddrIn) -> Self {
915 net::SocketAddrV4::new(
916 net::Ipv4Addr::from(addr.0.sin_addr.s_addr.to_ne_bytes()),
917 u16::from_be(addr.0.sin_port),
918 )
919 }
920 }
921
922 #[cfg(feature = "net")]
923 impl std::str::FromStr for SockaddrIn {
924 type Err = net::AddrParseError;
925
from_str(s: &str) -> std::result::Result<Self, Self::Err>926 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
927 net::SocketAddrV4::from_str(s).map(SockaddrIn::from)
928 }
929 }
930
931 /// An IPv6 socket address
932 #[cfg(feature = "net")]
933 #[repr(transparent)]
934 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
935 pub struct SockaddrIn6(libc::sockaddr_in6);
936
937 #[cfg(feature = "net")]
938 impl SockaddrIn6 {
939 /// Returns the flow information associated with this address.
flowinfo(&self) -> u32940 pub const fn flowinfo(&self) -> u32 {
941 self.0.sin6_flowinfo
942 }
943
944 /// Returns the IP address associated with this socket address.
ip(&self) -> net::Ipv6Addr945 pub const fn ip(&self) -> net::Ipv6Addr {
946 let bytes = self.0.sin6_addr.s6_addr;
947 let (a, b, c, d, e, f, g, h) = (
948 ((bytes[0] as u16) << 8) | bytes[1] as u16,
949 ((bytes[2] as u16) << 8) | bytes[3] as u16,
950 ((bytes[4] as u16) << 8) | bytes[5] as u16,
951 ((bytes[6] as u16) << 8) | bytes[7] as u16,
952 ((bytes[8] as u16) << 8) | bytes[9] as u16,
953 ((bytes[10] as u16) << 8) | bytes[11] as u16,
954 ((bytes[12] as u16) << 8) | bytes[13] as u16,
955 ((bytes[14] as u16) << 8) | bytes[15] as u16,
956 );
957 Ipv6Addr::new(a, b, c, d, e, f, g, h)
958 }
959
960 /// Returns the port number associated with this socket address, in native
961 /// endian.
port(&self) -> u16962 pub const fn port(&self) -> u16 {
963 u16::from_be(self.0.sin6_port)
964 }
965
966 /// Returns the scope ID associated with this address.
scope_id(&self) -> u32967 pub const fn scope_id(&self) -> u32 {
968 self.0.sin6_scope_id
969 }
970 }
971
972 #[cfg(feature = "net")]
973 impl private::SockaddrLikePriv for SockaddrIn6 {}
974 #[cfg(feature = "net")]
975 impl SockaddrLike for SockaddrIn6 {
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,976 unsafe fn from_raw(
977 addr: *const libc::sockaddr,
978 len: Option<libc::socklen_t>,
979 ) -> Option<Self>
980 where
981 Self: Sized,
982 {
983 if let Some(l) = len {
984 if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t {
985 return None;
986 }
987 }
988 if unsafe { (*addr).sa_family as i32 != libc::AF_INET6 } {
989 return None;
990 }
991 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
992 }
993 }
994
995 #[cfg(feature = "net")]
996 impl AsRef<libc::sockaddr_in6> for SockaddrIn6 {
as_ref(&self) -> &libc::sockaddr_in6997 fn as_ref(&self) -> &libc::sockaddr_in6 {
998 &self.0
999 }
1000 }
1001
1002 #[cfg(feature = "net")]
1003 impl fmt::Display for SockaddrIn6 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1004 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1005 // These things are really hard to display properly. Easier to let std
1006 // do it.
1007 let std = net::SocketAddrV6::new(
1008 self.ip(),
1009 self.port(),
1010 self.flowinfo(),
1011 self.scope_id(),
1012 );
1013 std.fmt(f)
1014 }
1015 }
1016
1017 #[cfg(feature = "net")]
1018 impl From<net::SocketAddrV6> for SockaddrIn6 {
from(addr: net::SocketAddrV6) -> Self1019 fn from(addr: net::SocketAddrV6) -> Self {
1020 #[allow(clippy::needless_update)] // It isn't needless on Illumos
1021 Self(libc::sockaddr_in6 {
1022 #[cfg(any(
1023 bsd,
1024 target_os = "haiku",
1025 target_os = "hermit",
1026 target_os = "hurd"
1027 ))]
1028 sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
1029 sin6_family: AddressFamily::Inet6 as sa_family_t,
1030 sin6_port: addr.port().to_be(), // network byte order
1031 sin6_addr: ipv6addr_to_libc(addr.ip()),
1032 sin6_flowinfo: addr.flowinfo(), // host byte order
1033 sin6_scope_id: addr.scope_id(), // host byte order
1034 ..unsafe { mem::zeroed() }
1035 })
1036 }
1037 }
1038
1039 #[cfg(feature = "net")]
1040 impl From<SockaddrIn6> for net::SocketAddrV6 {
from(addr: SockaddrIn6) -> Self1041 fn from(addr: SockaddrIn6) -> Self {
1042 net::SocketAddrV6::new(
1043 net::Ipv6Addr::from(addr.0.sin6_addr.s6_addr),
1044 u16::from_be(addr.0.sin6_port),
1045 addr.0.sin6_flowinfo,
1046 addr.0.sin6_scope_id,
1047 )
1048 }
1049 }
1050
1051 #[cfg(feature = "net")]
1052 impl std::str::FromStr for SockaddrIn6 {
1053 type Err = net::AddrParseError;
1054
from_str(s: &str) -> std::result::Result<Self, Self::Err>1055 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
1056 net::SocketAddrV6::from_str(s).map(SockaddrIn6::from)
1057 }
1058 }
1059
1060 /// A container for any sockaddr type
1061 ///
1062 /// Just like C's `sockaddr_storage`, this type is large enough to hold any type
1063 /// of sockaddr. It can be used as an argument with functions like
1064 /// [`bind`](super::bind) and [`getsockname`](super::getsockname). Though it is
1065 /// a union, it can be safely accessed through the `as_*` methods.
1066 ///
1067 /// # Example
1068 /// ```
1069 /// # use nix::sys::socket::*;
1070 /// # use std::str::FromStr;
1071 /// # use std::os::unix::io::AsRawFd;
1072 /// let localhost = SockaddrIn::from_str("127.0.0.1:8081").unwrap();
1073 /// let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(),
1074 /// None).unwrap();
1075 /// bind(fd.as_raw_fd(), &localhost).expect("bind");
1076 /// let ss: SockaddrStorage = getsockname(fd.as_raw_fd()).expect("getsockname");
1077 /// assert_eq!(&localhost, ss.as_sockaddr_in().unwrap());
1078 /// ```
1079 #[derive(Clone, Copy, Eq)]
1080 #[repr(C)]
1081 pub union SockaddrStorage {
1082 #[cfg(linux_android)]
1083 alg: AlgAddr,
1084 #[cfg(all(
1085 feature = "net",
1086 not(any(target_os = "hurd", target_os = "redox"))
1087 ))]
1088 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1089 dl: LinkAddr,
1090 #[cfg(linux_android)]
1091 nl: NetlinkAddr,
1092 #[cfg(all(feature = "ioctl", apple_targets))]
1093 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1094 sctl: SysControlAddr,
1095 #[cfg(feature = "net")]
1096 sin: SockaddrIn,
1097 #[cfg(feature = "net")]
1098 sin6: SockaddrIn6,
1099 ss: libc::sockaddr_storage,
1100 su: UnixAddr,
1101 #[cfg(any(linux_android, apple_targets))]
1102 vsock: VsockAddr,
1103 }
1104 impl private::SockaddrLikePriv for SockaddrStorage {}
1105 impl SockaddrLike for SockaddrStorage {
from_raw( addr: *const libc::sockaddr, l: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,1106 unsafe fn from_raw(
1107 addr: *const libc::sockaddr,
1108 l: Option<libc::socklen_t>,
1109 ) -> Option<Self>
1110 where
1111 Self: Sized,
1112 {
1113 if addr.is_null() {
1114 return None;
1115 }
1116 if let Some(len) = l {
1117 let ulen = len as usize;
1118 if ulen < offset_of!(libc::sockaddr, sa_data)
1119 || ulen > mem::size_of::<libc::sockaddr_storage>()
1120 {
1121 None
1122 } else {
1123 let mut ss: libc::sockaddr_storage = unsafe { mem::zeroed() };
1124 let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
1125 unsafe { ptr::copy(addr as *const u8, ssp, len as usize) };
1126 #[cfg(any(
1127 linux_android,
1128 target_os = "fuchsia",
1129 solarish,
1130 ))]
1131 if i32::from(ss.ss_family) == libc::AF_UNIX {
1132 // Safe because we UnixAddr is strictly smaller than
1133 // SockaddrStorage, and we just initialized the structure.
1134 unsafe {
1135 (*(&mut ss as *mut libc::sockaddr_storage
1136 as *mut UnixAddr))
1137 .sun_len = len as u8;
1138 }
1139 }
1140 Some(Self { ss })
1141 }
1142 } else {
1143 // If length is not available and addr is of a fixed-length type,
1144 // copy it. If addr is of a variable length type and len is not
1145 // available, then there's nothing we can do.
1146 match unsafe { (*addr).sa_family as i32 } {
1147 #[cfg(linux_android)]
1148 libc::AF_ALG => unsafe {
1149 AlgAddr::from_raw(addr, l).map(|alg| Self { alg })
1150 },
1151 #[cfg(feature = "net")]
1152 libc::AF_INET => unsafe {
1153 SockaddrIn::from_raw(addr, l).map(|sin| Self { sin })
1154 },
1155 #[cfg(feature = "net")]
1156 libc::AF_INET6 => unsafe {
1157 SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 })
1158 },
1159 #[cfg(any(bsd, solarish, target_os = "haiku"))]
1160 #[cfg(feature = "net")]
1161 libc::AF_LINK => unsafe {
1162 LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
1163 },
1164 #[cfg(linux_android)]
1165 libc::AF_NETLINK => unsafe {
1166 NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl })
1167 },
1168 #[cfg(any(linux_android, target_os = "fuchsia"))]
1169 #[cfg(feature = "net")]
1170 libc::AF_PACKET => unsafe {
1171 LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
1172 },
1173 #[cfg(all(feature = "ioctl", apple_targets))]
1174 libc::AF_SYSTEM => unsafe {
1175 SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
1176 },
1177 #[cfg(any(linux_android, apple_targets))]
1178 libc::AF_VSOCK => unsafe {
1179 VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
1180 },
1181 _ => None,
1182 }
1183 }
1184 }
1185
1186 #[cfg(any(linux_android, target_os = "fuchsia", solarish))]
len(&self) -> libc::socklen_t1187 fn len(&self) -> libc::socklen_t {
1188 match self.as_unix_addr() {
1189 // The UnixAddr type knows its own length
1190 Some(ua) => ua.len(),
1191 // For all else, we're just a boring SockaddrStorage
1192 None => mem::size_of_val(self) as libc::socklen_t,
1193 }
1194 }
1195
set_length( &mut self, new_length: usize, ) -> std::result::Result<(), SocketAddressLengthNotDynamic>1196 unsafe fn set_length(
1197 &mut self,
1198 new_length: usize,
1199 ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
1200 match self.as_unix_addr_mut() {
1201 Some(addr) => unsafe { addr.set_length(new_length) },
1202 None => Err(SocketAddressLengthNotDynamic),
1203 }
1204 }
1205 }
1206
1207 macro_rules! accessors {
1208 (
1209 $fname:ident,
1210 $fname_mut:ident,
1211 $sockty:ty,
1212 $family:expr,
1213 $libc_ty:ty,
1214 $field:ident) => {
1215 /// Safely and falliably downcast to an immutable reference
1216 pub fn $fname(&self) -> Option<&$sockty> {
1217 if self.family() == Some($family)
1218 && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
1219 {
1220 // Safe because family and len are validated
1221 Some(unsafe { &self.$field })
1222 } else {
1223 None
1224 }
1225 }
1226
1227 /// Safely and falliably downcast to a mutable reference
1228 pub fn $fname_mut(&mut self) -> Option<&mut $sockty> {
1229 if self.family() == Some($family)
1230 && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
1231 {
1232 // Safe because family and len are validated
1233 Some(unsafe { &mut self.$field })
1234 } else {
1235 None
1236 }
1237 }
1238 };
1239 }
1240
1241 impl SockaddrStorage {
1242 /// Downcast to an immutable `[UnixAddr]` reference.
as_unix_addr(&self) -> Option<&UnixAddr>1243 pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
1244 cfg_if! {
1245 if #[cfg(any(linux_android,
1246 target_os = "fuchsia",
1247 solarish,
1248 ))]
1249 {
1250 let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
1251 // Safe because UnixAddr is strictly smaller than
1252 // sockaddr_storage, and we're fully initialized
1253 let len = unsafe {
1254 (*(p as *const UnixAddr )).sun_len as usize
1255 };
1256 } else {
1257 let len = self.len() as usize;
1258 }
1259 }
1260 // Sanity checks
1261 if self.family() != Some(AddressFamily::Unix)
1262 || len < offset_of!(libc::sockaddr_un, sun_path)
1263 || len > mem::size_of::<libc::sockaddr_un>()
1264 {
1265 None
1266 } else {
1267 Some(unsafe { &self.su })
1268 }
1269 }
1270
1271 /// Downcast to a mutable `[UnixAddr]` reference.
as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr>1272 pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
1273 cfg_if! {
1274 if #[cfg(any(linux_android,
1275 target_os = "fuchsia",
1276 solarish,
1277 ))]
1278 {
1279 let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
1280 // Safe because UnixAddr is strictly smaller than
1281 // sockaddr_storage, and we're fully initialized
1282 let len = unsafe {
1283 (*(p as *const UnixAddr )).sun_len as usize
1284 };
1285 } else {
1286 let len = self.len() as usize;
1287 }
1288 }
1289 // Sanity checks
1290 if self.family() != Some(AddressFamily::Unix)
1291 || len < offset_of!(libc::sockaddr_un, sun_path)
1292 || len > mem::size_of::<libc::sockaddr_un>()
1293 {
1294 None
1295 } else {
1296 Some(unsafe { &mut self.su })
1297 }
1298 }
1299
1300 #[cfg(linux_android)]
1301 accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr,
1302 AddressFamily::Alg, libc::sockaddr_alg, alg}
1303
1304 #[cfg(any(linux_android, target_os = "fuchsia"))]
1305 #[cfg(feature = "net")]
1306 accessors! {
1307 as_link_addr, as_link_addr_mut, LinkAddr,
1308 AddressFamily::Packet, libc::sockaddr_ll, dl}
1309
1310 #[cfg(any(bsd, solarish))]
1311 #[cfg(feature = "net")]
1312 accessors! {
1313 as_link_addr, as_link_addr_mut, LinkAddr,
1314 AddressFamily::Link, libc::sockaddr_dl, dl}
1315
1316 #[cfg(feature = "net")]
1317 accessors! {
1318 as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
1319 AddressFamily::Inet, libc::sockaddr_in, sin}
1320
1321 #[cfg(feature = "net")]
1322 accessors! {
1323 as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
1324 AddressFamily::Inet6, libc::sockaddr_in6, sin6}
1325
1326 #[cfg(linux_android)]
1327 accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
1328 AddressFamily::Netlink, libc::sockaddr_nl, nl}
1329
1330 #[cfg(all(feature = "ioctl", apple_targets))]
1331 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1332 accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
1333 AddressFamily::System, libc::sockaddr_ctl, sctl}
1334
1335 #[cfg(any(linux_android, apple_targets))]
1336 accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
1337 AddressFamily::Vsock, libc::sockaddr_vm, vsock}
1338 }
1339
1340 impl fmt::Debug for SockaddrStorage {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1341 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1342 f.debug_struct("SockaddrStorage")
1343 // Safe because sockaddr_storage has the least specific
1344 // field types
1345 .field("ss", unsafe { &self.ss })
1346 .finish()
1347 }
1348 }
1349
1350 impl fmt::Display for SockaddrStorage {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1351 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1352 unsafe {
1353 match self.ss.ss_family as i32 {
1354 #[cfg(linux_android)]
1355 libc::AF_ALG => self.alg.fmt(f),
1356 #[cfg(feature = "net")]
1357 libc::AF_INET => self.sin.fmt(f),
1358 #[cfg(feature = "net")]
1359 libc::AF_INET6 => self.sin6.fmt(f),
1360 #[cfg(any(bsd, solarish))]
1361 #[cfg(feature = "net")]
1362 libc::AF_LINK => self.dl.fmt(f),
1363 #[cfg(linux_android)]
1364 libc::AF_NETLINK => self.nl.fmt(f),
1365 #[cfg(any(linux_android, target_os = "fuchsia"))]
1366 #[cfg(feature = "net")]
1367 libc::AF_PACKET => self.dl.fmt(f),
1368 #[cfg(apple_targets)]
1369 #[cfg(feature = "ioctl")]
1370 libc::AF_SYSTEM => self.sctl.fmt(f),
1371 libc::AF_UNIX => self.su.fmt(f),
1372 #[cfg(any(linux_android, apple_targets))]
1373 libc::AF_VSOCK => self.vsock.fmt(f),
1374 _ => "<Address family unspecified>".fmt(f),
1375 }
1376 }
1377 }
1378 }
1379
1380 #[cfg(feature = "net")]
1381 impl From<net::SocketAddrV4> for SockaddrStorage {
from(s: net::SocketAddrV4) -> Self1382 fn from(s: net::SocketAddrV4) -> Self {
1383 unsafe {
1384 let mut ss: Self = mem::zeroed();
1385 ss.sin = SockaddrIn::from(s);
1386 ss
1387 }
1388 }
1389 }
1390
1391 #[cfg(feature = "net")]
1392 impl From<net::SocketAddrV6> for SockaddrStorage {
from(s: net::SocketAddrV6) -> Self1393 fn from(s: net::SocketAddrV6) -> Self {
1394 unsafe {
1395 let mut ss: Self = mem::zeroed();
1396 ss.sin6 = SockaddrIn6::from(s);
1397 ss
1398 }
1399 }
1400 }
1401
1402 #[cfg(feature = "net")]
1403 impl From<net::SocketAddr> for SockaddrStorage {
from(s: net::SocketAddr) -> Self1404 fn from(s: net::SocketAddr) -> Self {
1405 match s {
1406 net::SocketAddr::V4(sa4) => Self::from(sa4),
1407 net::SocketAddr::V6(sa6) => Self::from(sa6),
1408 }
1409 }
1410 }
1411
1412 impl Hash for SockaddrStorage {
hash<H: Hasher>(&self, s: &mut H)1413 fn hash<H: Hasher>(&self, s: &mut H) {
1414 unsafe {
1415 match self.ss.ss_family as i32 {
1416 #[cfg(linux_android)]
1417 libc::AF_ALG => self.alg.hash(s),
1418 #[cfg(feature = "net")]
1419 libc::AF_INET => self.sin.hash(s),
1420 #[cfg(feature = "net")]
1421 libc::AF_INET6 => self.sin6.hash(s),
1422 #[cfg(any(bsd, solarish))]
1423 #[cfg(feature = "net")]
1424 libc::AF_LINK => self.dl.hash(s),
1425 #[cfg(linux_android)]
1426 libc::AF_NETLINK => self.nl.hash(s),
1427 #[cfg(any(linux_android, target_os = "fuchsia"))]
1428 #[cfg(feature = "net")]
1429 libc::AF_PACKET => self.dl.hash(s),
1430 #[cfg(apple_targets)]
1431 #[cfg(feature = "ioctl")]
1432 libc::AF_SYSTEM => self.sctl.hash(s),
1433 libc::AF_UNIX => self.su.hash(s),
1434 #[cfg(any(linux_android, apple_targets))]
1435 libc::AF_VSOCK => self.vsock.hash(s),
1436 _ => self.ss.hash(s),
1437 }
1438 }
1439 }
1440 }
1441
1442 impl PartialEq for SockaddrStorage {
eq(&self, other: &Self) -> bool1443 fn eq(&self, other: &Self) -> bool {
1444 unsafe {
1445 match (self.ss.ss_family as i32, other.ss.ss_family as i32) {
1446 #[cfg(linux_android)]
1447 (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg,
1448 #[cfg(feature = "net")]
1449 (libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
1450 #[cfg(feature = "net")]
1451 (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
1452 #[cfg(any(bsd, solarish))]
1453 #[cfg(feature = "net")]
1454 (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
1455 #[cfg(linux_android)]
1456 (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
1457 #[cfg(any(linux_android, target_os = "fuchsia"))]
1458 #[cfg(feature = "net")]
1459 (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
1460 #[cfg(apple_targets)]
1461 #[cfg(feature = "ioctl")]
1462 (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
1463 (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
1464 #[cfg(any(linux_android, apple_targets))]
1465 (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
1466 _ => false,
1467 }
1468 }
1469 }
1470 }
1471
1472 pub(super) mod private {
1473 pub trait SockaddrLikePriv {
1474 /// Returns a mutable raw pointer to the inner structure.
1475 ///
1476 /// # Safety
1477 ///
1478 /// This method is technically safe, but modifying the inner structure's
1479 /// `family` or `len` fields may result in violating Nix's invariants.
1480 /// It is best to use this method only with foreign functions that do
1481 /// not change the sockaddr type.
as_mut_ptr(&mut self) -> *mut libc::sockaddr1482 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
1483 self as *mut Self as *mut libc::sockaddr
1484 }
1485 }
1486 }
1487
1488 #[cfg(linux_android)]
1489 pub mod netlink {
1490 use super::*;
1491 use crate::sys::socket::addr::AddressFamily;
1492 use libc::{sa_family_t, sockaddr_nl};
1493 use std::{fmt, mem};
1494
1495 /// Address for the Linux kernel user interface device.
1496 ///
1497 /// # References
1498 ///
1499 /// [netlink(7)](https://man7.org/linux/man-pages/man7/netlink.7.html)
1500 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1501 #[repr(transparent)]
1502 pub struct NetlinkAddr(pub(in super::super) sockaddr_nl);
1503
1504 impl NetlinkAddr {
1505 /// Construct a new socket address from its port ID and multicast groups
1506 /// mask.
new(pid: u32, groups: u32) -> NetlinkAddr1507 pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
1508 let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
1509 addr.nl_family = AddressFamily::Netlink as sa_family_t;
1510 addr.nl_pid = pid;
1511 addr.nl_groups = groups;
1512
1513 NetlinkAddr(addr)
1514 }
1515
1516 /// Return the socket's port ID.
pid(&self) -> u321517 pub const fn pid(&self) -> u32 {
1518 self.0.nl_pid
1519 }
1520
1521 /// Return the socket's multicast groups mask
groups(&self) -> u321522 pub const fn groups(&self) -> u32 {
1523 self.0.nl_groups
1524 }
1525 }
1526
1527 impl private::SockaddrLikePriv for NetlinkAddr {}
1528 impl SockaddrLike for NetlinkAddr {
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,1529 unsafe fn from_raw(
1530 addr: *const libc::sockaddr,
1531 len: Option<libc::socklen_t>,
1532 ) -> Option<Self>
1533 where
1534 Self: Sized,
1535 {
1536 if let Some(l) = len {
1537 if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t {
1538 return None;
1539 }
1540 }
1541 if unsafe { (*addr).sa_family as i32 != libc::AF_NETLINK } {
1542 return None;
1543 }
1544 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1545 }
1546 }
1547
1548 impl AsRef<libc::sockaddr_nl> for NetlinkAddr {
as_ref(&self) -> &libc::sockaddr_nl1549 fn as_ref(&self) -> &libc::sockaddr_nl {
1550 &self.0
1551 }
1552 }
1553
1554 impl fmt::Display for NetlinkAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1555 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1556 write!(f, "pid: {} groups: {}", self.pid(), self.groups())
1557 }
1558 }
1559 }
1560
1561 #[cfg(linux_android)]
1562 pub mod alg {
1563 use super::*;
1564 use libc::{sockaddr_alg, AF_ALG};
1565 use std::ffi::CStr;
1566 use std::hash::{Hash, Hasher};
1567 use std::{fmt, mem, str};
1568
1569 /// Socket address for the Linux kernel crypto API
1570 #[derive(Copy, Clone)]
1571 #[repr(transparent)]
1572 pub struct AlgAddr(pub(in super::super) sockaddr_alg);
1573
1574 impl private::SockaddrLikePriv for AlgAddr {}
1575 impl SockaddrLike for AlgAddr {
from_raw( addr: *const libc::sockaddr, l: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,1576 unsafe fn from_raw(
1577 addr: *const libc::sockaddr,
1578 l: Option<libc::socklen_t>,
1579 ) -> Option<Self>
1580 where
1581 Self: Sized,
1582 {
1583 if let Some(l) = l {
1584 if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t
1585 {
1586 return None;
1587 }
1588 }
1589 if unsafe { (*addr).sa_family as i32 != libc::AF_ALG } {
1590 return None;
1591 }
1592 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1593 }
1594 }
1595
1596 impl AsRef<libc::sockaddr_alg> for AlgAddr {
as_ref(&self) -> &libc::sockaddr_alg1597 fn as_ref(&self) -> &libc::sockaddr_alg {
1598 &self.0
1599 }
1600 }
1601
1602 // , PartialEq, Eq, Debug, Hash
1603 impl PartialEq for AlgAddr {
eq(&self, other: &Self) -> bool1604 fn eq(&self, other: &Self) -> bool {
1605 let (inner, other) = (self.0, other.0);
1606 (
1607 inner.salg_family,
1608 &inner.salg_type[..],
1609 inner.salg_feat,
1610 inner.salg_mask,
1611 &inner.salg_name[..],
1612 ) == (
1613 other.salg_family,
1614 &other.salg_type[..],
1615 other.salg_feat,
1616 other.salg_mask,
1617 &other.salg_name[..],
1618 )
1619 }
1620 }
1621
1622 impl Eq for AlgAddr {}
1623
1624 impl Hash for AlgAddr {
hash<H: Hasher>(&self, s: &mut H)1625 fn hash<H: Hasher>(&self, s: &mut H) {
1626 let inner = self.0;
1627 (
1628 inner.salg_family,
1629 &inner.salg_type[..],
1630 inner.salg_feat,
1631 inner.salg_mask,
1632 &inner.salg_name[..],
1633 )
1634 .hash(s);
1635 }
1636 }
1637
1638 impl AlgAddr {
1639 /// Construct an `AF_ALG` socket from its cipher name and type.
new(alg_type: &str, alg_name: &str) -> AlgAddr1640 pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
1641 let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
1642 addr.salg_family = AF_ALG as u16;
1643 addr.salg_type[..alg_type.len()]
1644 .copy_from_slice(alg_type.to_string().as_bytes());
1645 addr.salg_name[..alg_name.len()]
1646 .copy_from_slice(alg_name.to_string().as_bytes());
1647
1648 AlgAddr(addr)
1649 }
1650
1651 /// Return the socket's cipher type, for example `hash` or `aead`.
alg_type(&self) -> &CStr1652 pub fn alg_type(&self) -> &CStr {
1653 unsafe { CStr::from_ptr(self.0.salg_type.as_ptr().cast()) }
1654 }
1655
1656 /// Return the socket's cipher name, for example `sha1`.
alg_name(&self) -> &CStr1657 pub fn alg_name(&self) -> &CStr {
1658 unsafe { CStr::from_ptr(self.0.salg_name.as_ptr().cast()) }
1659 }
1660 }
1661
1662 impl fmt::Display for AlgAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1663 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1664 write!(
1665 f,
1666 "type: {} alg: {}",
1667 self.alg_name().to_string_lossy(),
1668 self.alg_type().to_string_lossy()
1669 )
1670 }
1671 }
1672
1673 impl fmt::Debug for AlgAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1674 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1675 fmt::Display::fmt(self, f)
1676 }
1677 }
1678 }
1679
1680 feature! {
1681 #![feature = "ioctl"]
1682 #[cfg(apple_targets)]
1683 pub mod sys_control {
1684 use crate::sys::socket::addr::AddressFamily;
1685 use libc::{self, c_uchar};
1686 use std::{fmt, mem, ptr};
1687 use std::os::unix::io::RawFd;
1688 use crate::{Errno, Result};
1689 use super::{private, SockaddrLike};
1690
1691 // FIXME: Move type into `libc`
1692 #[repr(C)]
1693 #[derive(Clone, Copy)]
1694 #[allow(missing_debug_implementations)]
1695 pub struct ctl_ioc_info {
1696 pub ctl_id: u32,
1697 pub ctl_name: [c_uchar; MAX_KCTL_NAME],
1698 }
1699
1700 const CTL_IOC_MAGIC: u8 = b'N';
1701 const CTL_IOC_INFO: u8 = 3;
1702 const MAX_KCTL_NAME: usize = 96;
1703
1704 ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
1705
1706 /// Apple system control socket
1707 ///
1708 /// # References
1709 ///
1710 /// <https://developer.apple.com/documentation/kernel/sockaddr_ctl>
1711 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1712 #[repr(transparent)]
1713 pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl);
1714
1715 impl private::SockaddrLikePriv for SysControlAddr {}
1716 impl SockaddrLike for SysControlAddr {
1717 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
1718 -> Option<Self> where Self: Sized
1719 {
1720 if let Some(l) = len {
1721 if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t {
1722 return None;
1723 }
1724 }
1725 if unsafe { (*addr).sa_family as i32 != libc::AF_SYSTEM } {
1726 return None;
1727 }
1728 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) } ))
1729 }
1730 }
1731
1732 impl AsRef<libc::sockaddr_ctl> for SysControlAddr {
1733 fn as_ref(&self) -> &libc::sockaddr_ctl {
1734 &self.0
1735 }
1736 }
1737
1738 impl SysControlAddr {
1739 /// Construct a new `SysControlAddr` from its kernel unique identifier
1740 /// and unit number.
1741 pub const fn new(id: u32, unit: u32) -> SysControlAddr {
1742 let addr = libc::sockaddr_ctl {
1743 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
1744 sc_family: AddressFamily::System as c_uchar,
1745 ss_sysaddr: libc::AF_SYS_CONTROL as u16,
1746 sc_id: id,
1747 sc_unit: unit,
1748 sc_reserved: [0; 5]
1749 };
1750
1751 SysControlAddr(addr)
1752 }
1753
1754 /// Construct a new `SysControlAddr` from its human readable name and
1755 /// unit number.
1756 pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
1757 if name.len() > MAX_KCTL_NAME {
1758 return Err(Errno::ENAMETOOLONG);
1759 }
1760
1761 let mut ctl_name = [0; MAX_KCTL_NAME];
1762 ctl_name[..name.len()].clone_from_slice(name.as_bytes());
1763 let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
1764
1765 unsafe { ctl_info(sockfd, &mut info)?; }
1766
1767 Ok(SysControlAddr::new(info.ctl_id, unit))
1768 }
1769
1770 /// Return the kernel unique identifier
1771 pub const fn id(&self) -> u32 {
1772 self.0.sc_id
1773 }
1774
1775 /// Return the kernel controller private unit number.
1776 pub const fn unit(&self) -> u32 {
1777 self.0.sc_unit
1778 }
1779 }
1780
1781 impl fmt::Display for SysControlAddr {
1782 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1783 fmt::Debug::fmt(self, f)
1784 }
1785 }
1786 }
1787 }
1788
1789 #[cfg(any(linux_android, target_os = "fuchsia"))]
1790 mod datalink {
1791 feature! {
1792 #![feature = "net"]
1793 use super::{fmt, mem, private, ptr, SockaddrLike};
1794
1795 /// Hardware Address
1796 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1797 #[repr(transparent)]
1798 pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll);
1799
1800 impl LinkAddr {
1801 /// Physical-layer protocol
1802 pub fn protocol(&self) -> u16 {
1803 self.0.sll_protocol
1804 }
1805
1806 /// Interface number
1807 pub fn ifindex(&self) -> usize {
1808 self.0.sll_ifindex as usize
1809 }
1810
1811 /// ARP hardware type
1812 pub fn hatype(&self) -> u16 {
1813 self.0.sll_hatype
1814 }
1815
1816 /// Packet type
1817 pub fn pkttype(&self) -> u8 {
1818 self.0.sll_pkttype
1819 }
1820
1821 /// Length of MAC address
1822 pub fn halen(&self) -> usize {
1823 self.0.sll_halen as usize
1824 }
1825
1826 /// Physical-layer address (MAC)
1827 // Returns an Option just for cross-platform compatibility
1828 pub fn addr(&self) -> Option<[u8; 6]> {
1829 Some([
1830 self.0.sll_addr[0],
1831 self.0.sll_addr[1],
1832 self.0.sll_addr[2],
1833 self.0.sll_addr[3],
1834 self.0.sll_addr[4],
1835 self.0.sll_addr[5],
1836 ])
1837 }
1838 }
1839
1840 impl fmt::Display for LinkAddr {
1841 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1842 if let Some(addr) = self.addr() {
1843 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1844 addr[0],
1845 addr[1],
1846 addr[2],
1847 addr[3],
1848 addr[4],
1849 addr[5])
1850 } else {
1851 Ok(())
1852 }
1853 }
1854 }
1855 impl private::SockaddrLikePriv for LinkAddr {}
1856 impl SockaddrLike for LinkAddr {
1857 unsafe fn from_raw(addr: *const libc::sockaddr,
1858 len: Option<libc::socklen_t>)
1859 -> Option<Self> where Self: Sized
1860 {
1861 if let Some(l) = len {
1862 if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t {
1863 return None;
1864 }
1865 }
1866 if unsafe { (*addr).sa_family as i32 != libc::AF_PACKET } {
1867 return None;
1868 }
1869 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1870 }
1871 }
1872
1873 impl AsRef<libc::sockaddr_ll> for LinkAddr {
1874 fn as_ref(&self) -> &libc::sockaddr_ll {
1875 &self.0
1876 }
1877 }
1878
1879 }
1880 }
1881
1882 #[cfg(any(bsd, solarish, target_os = "haiku", target_os = "aix"))]
1883 mod datalink {
1884 feature! {
1885 #![feature = "net"]
1886 use super::{fmt, mem, private, ptr, SockaddrLike};
1887
1888 /// Hardware Address
1889 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1890 #[repr(transparent)]
1891 pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl);
1892
1893 impl LinkAddr {
1894 /// interface index, if != 0, system given index for interface
1895 #[cfg(not(target_os = "haiku"))]
1896 pub fn ifindex(&self) -> usize {
1897 self.0.sdl_index as usize
1898 }
1899
1900 /// Datalink type
1901 #[cfg(not(target_os = "haiku"))]
1902 pub fn datalink_type(&self) -> u8 {
1903 self.0.sdl_type
1904 }
1905
1906 /// MAC address start position
1907 pub fn nlen(&self) -> usize {
1908 self.0.sdl_nlen as usize
1909 }
1910
1911 /// link level address length
1912 pub fn alen(&self) -> usize {
1913 self.0.sdl_alen as usize
1914 }
1915
1916 /// link layer selector length
1917 #[cfg(not(target_os = "haiku"))]
1918 pub fn slen(&self) -> usize {
1919 self.0.sdl_slen as usize
1920 }
1921
1922 /// if link level address length == 0,
1923 /// or `sdl_data` not be larger.
1924 pub fn is_empty(&self) -> bool {
1925 let nlen = self.nlen();
1926 let alen = self.alen();
1927 let data_len = self.0.sdl_data.len();
1928
1929 alen == 0 || nlen + alen >= data_len
1930 }
1931
1932 /// Physical-layer address (MAC)
1933 // The cast is not unnecessary on all platforms.
1934 #[allow(clippy::unnecessary_cast)]
1935 pub fn addr(&self) -> Option<[u8; 6]> {
1936 let nlen = self.nlen();
1937 let data = self.0.sdl_data;
1938
1939 if self.is_empty() {
1940 None
1941 } else {
1942 Some([
1943 data[nlen] as u8,
1944 data[nlen + 1] as u8,
1945 data[nlen + 2] as u8,
1946 data[nlen + 3] as u8,
1947 data[nlen + 4] as u8,
1948 data[nlen + 5] as u8,
1949 ])
1950 }
1951 }
1952 }
1953
1954 impl fmt::Display for LinkAddr {
1955 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1956 if let Some(addr) = self.addr() {
1957 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1958 addr[0],
1959 addr[1],
1960 addr[2],
1961 addr[3],
1962 addr[4],
1963 addr[5])
1964 } else {
1965 Ok(())
1966 }
1967 }
1968 }
1969 impl private::SockaddrLikePriv for LinkAddr {}
1970 impl SockaddrLike for LinkAddr {
1971 unsafe fn from_raw(addr: *const libc::sockaddr,
1972 len: Option<libc::socklen_t>)
1973 -> Option<Self> where Self: Sized
1974 {
1975 if let Some(l) = len {
1976 if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t {
1977 return None;
1978 }
1979 }
1980 if unsafe { (*addr).sa_family as i32 != libc::AF_LINK } {
1981 return None;
1982 }
1983 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1984 }
1985 }
1986
1987 impl AsRef<libc::sockaddr_dl> for LinkAddr {
1988 fn as_ref(&self) -> &libc::sockaddr_dl {
1989 &self.0
1990 }
1991 }
1992 }
1993 }
1994
1995 #[cfg(any(linux_android, apple_targets))]
1996 pub mod vsock {
1997 use super::*;
1998 use crate::sys::socket::addr::AddressFamily;
1999 use libc::{sa_family_t, sockaddr_vm};
2000 use std::hash::{Hash, Hasher};
2001 use std::{fmt, mem};
2002
2003 /// Socket address for VMWare VSockets protocol
2004 ///
2005 /// # References
2006 ///
2007 /// [vsock(7)](https://man7.org/linux/man-pages/man7/vsock.7.html)
2008 #[derive(Copy, Clone)]
2009 #[repr(transparent)]
2010 pub struct VsockAddr(pub(in super::super) sockaddr_vm);
2011
2012 impl private::SockaddrLikePriv for VsockAddr {}
2013 impl SockaddrLike for VsockAddr {
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,2014 unsafe fn from_raw(
2015 addr: *const libc::sockaddr,
2016 len: Option<libc::socklen_t>,
2017 ) -> Option<Self>
2018 where
2019 Self: Sized,
2020 {
2021 if let Some(l) = len {
2022 if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t {
2023 return None;
2024 }
2025 }
2026 if unsafe { (*addr).sa_family as i32 != libc::AF_VSOCK } {
2027 return None;
2028 }
2029 unsafe { Some(Self(ptr::read_unaligned(addr as *const _))) }
2030 }
2031 }
2032
2033 impl AsRef<libc::sockaddr_vm> for VsockAddr {
as_ref(&self) -> &libc::sockaddr_vm2034 fn as_ref(&self) -> &libc::sockaddr_vm {
2035 &self.0
2036 }
2037 }
2038
2039 impl PartialEq for VsockAddr {
2040 #[cfg(linux_android)]
eq(&self, other: &Self) -> bool2041 fn eq(&self, other: &Self) -> bool {
2042 let (inner, other) = (self.0, other.0);
2043 (inner.svm_family, inner.svm_cid, inner.svm_port)
2044 == (other.svm_family, other.svm_cid, other.svm_port)
2045 }
2046 #[cfg(apple_targets)]
eq(&self, other: &Self) -> bool2047 fn eq(&self, other: &Self) -> bool {
2048 let (inner, other) = (self.0, other.0);
2049 (
2050 inner.svm_family,
2051 inner.svm_cid,
2052 inner.svm_port,
2053 inner.svm_len,
2054 ) == (
2055 other.svm_family,
2056 other.svm_cid,
2057 other.svm_port,
2058 inner.svm_len,
2059 )
2060 }
2061 }
2062
2063 impl Eq for VsockAddr {}
2064
2065 impl Hash for VsockAddr {
2066 #[cfg(linux_android)]
hash<H: Hasher>(&self, s: &mut H)2067 fn hash<H: Hasher>(&self, s: &mut H) {
2068 let inner = self.0;
2069 (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
2070 }
2071 #[cfg(apple_targets)]
hash<H: Hasher>(&self, s: &mut H)2072 fn hash<H: Hasher>(&self, s: &mut H) {
2073 let inner = self.0;
2074 (
2075 inner.svm_family,
2076 inner.svm_cid,
2077 inner.svm_port,
2078 inner.svm_len,
2079 )
2080 .hash(s);
2081 }
2082 }
2083
2084 /// VSOCK Address
2085 ///
2086 /// The address for AF_VSOCK socket is defined as a combination of a
2087 /// 32-bit Context Identifier (CID) and a 32-bit port number.
2088 impl VsockAddr {
2089 /// Construct a `VsockAddr` from its raw fields.
new(cid: u32, port: u32) -> VsockAddr2090 pub fn new(cid: u32, port: u32) -> VsockAddr {
2091 let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
2092 addr.svm_family = AddressFamily::Vsock as sa_family_t;
2093 addr.svm_cid = cid;
2094 addr.svm_port = port;
2095
2096 #[cfg(apple_targets)]
2097 {
2098 addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8;
2099 }
2100 VsockAddr(addr)
2101 }
2102
2103 /// Context Identifier (CID)
cid(&self) -> u322104 pub fn cid(&self) -> u32 {
2105 self.0.svm_cid
2106 }
2107
2108 /// Port number
port(&self) -> u322109 pub fn port(&self) -> u32 {
2110 self.0.svm_port
2111 }
2112 }
2113
2114 impl fmt::Display for VsockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2116 write!(f, "cid: {} port: {}", self.cid(), self.port())
2117 }
2118 }
2119
2120 impl fmt::Debug for VsockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2122 fmt::Display::fmt(self, f)
2123 }
2124 }
2125 }
2126
2127 #[cfg(test)]
2128 mod tests {
2129 use super::*;
2130
2131 mod types {
2132 use super::*;
2133
2134 #[test]
test_ipv4addr_to_libc()2135 fn test_ipv4addr_to_libc() {
2136 let s = std::net::Ipv4Addr::new(1, 2, 3, 4);
2137 let l = ipv4addr_to_libc(s);
2138 assert_eq!(l.s_addr, u32::to_be(0x01020304));
2139 }
2140
2141 #[test]
test_ipv6addr_to_libc()2142 fn test_ipv6addr_to_libc() {
2143 let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8);
2144 let l = ipv6addr_to_libc(&s);
2145 assert_eq!(
2146 l.s6_addr,
2147 [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8]
2148 );
2149 }
2150 }
2151
2152 #[cfg(not(any(target_os = "hurd", target_os = "redox")))]
2153 mod link {
2154 #![allow(clippy::cast_ptr_alignment)]
2155
2156 #[cfg(any(apple_targets, solarish))]
2157 use super::super::super::socklen_t;
2158 use super::*;
2159
2160 /// Don't panic when trying to display an empty datalink address
2161 #[cfg(bsd)]
2162 #[test]
test_datalink_display()2163 fn test_datalink_display() {
2164 use super::super::LinkAddr;
2165 use std::mem;
2166
2167 let la = LinkAddr(libc::sockaddr_dl {
2168 sdl_len: 56,
2169 sdl_family: 18,
2170 sdl_index: 5,
2171 sdl_type: 24,
2172 sdl_nlen: 3,
2173 sdl_alen: 0,
2174 sdl_slen: 0,
2175 ..unsafe { mem::zeroed() }
2176 });
2177 format!("{la}");
2178 }
2179
2180 #[cfg(all(
2181 any(linux_android, target_os = "fuchsia"),
2182 target_endian = "little"
2183 ))]
2184 #[test]
linux_loopback()2185 fn linux_loopback() {
2186 #[repr(align(2))]
2187 struct Raw([u8; 20]);
2188
2189 let bytes = Raw([
2190 17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0,
2191 ]);
2192 let sa = bytes.0.as_ptr().cast();
2193 let len = None;
2194 let sock_addr =
2195 unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
2196 assert_eq!(sock_addr.family(), Some(AddressFamily::Packet));
2197 match sock_addr.as_link_addr() {
2198 Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])),
2199 None => panic!("Can't unwrap sockaddr storage"),
2200 }
2201 }
2202
2203 #[cfg(apple_targets)]
2204 #[test]
macos_loopback()2205 fn macos_loopback() {
2206 let bytes =
2207 [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
2208 let sa = bytes.as_ptr().cast();
2209 let len = Some(bytes.len() as socklen_t);
2210 let sock_addr =
2211 unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
2212 assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
2213 match sock_addr.as_link_addr() {
2214 Some(dl) => {
2215 assert!(dl.addr().is_none());
2216 }
2217 None => panic!("Can't unwrap sockaddr storage"),
2218 }
2219 }
2220
2221 #[cfg(apple_targets)]
2222 #[test]
macos_tap()2223 fn macos_tap() {
2224 let bytes = [
2225 20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35,
2226 76, -80,
2227 ];
2228 let ptr = bytes.as_ptr();
2229 let sa = ptr as *const libc::sockaddr;
2230 let len = Some(bytes.len() as socklen_t);
2231
2232 let sock_addr =
2233 unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
2234 assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
2235 match sock_addr.as_link_addr() {
2236 Some(dl) => {
2237 assert_eq!(dl.addr(), Some([24u8, 101, 144, 221, 76, 176]))
2238 }
2239 None => panic!("Can't unwrap sockaddr storage"),
2240 }
2241 }
2242
2243 #[cfg(solarish)]
2244 #[test]
solarish_tap()2245 fn solarish_tap() {
2246 let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
2247 let ptr = bytes.as_ptr();
2248 let sa = ptr as *const libc::sockaddr;
2249 let len = Some(bytes.len() as socklen_t);
2250 let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) };
2251
2252 assert!(_sock_addr.is_some());
2253
2254 let sock_addr = _sock_addr.unwrap();
2255
2256 assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link);
2257
2258 assert_eq!(
2259 sock_addr.as_link_addr().unwrap().addr(),
2260 Some([24u8, 101, 144, 221, 76, 176])
2261 );
2262 }
2263
2264 #[test]
size()2265 fn size() {
2266 #[cfg(any(bsd, target_os = "aix", solarish, target_os = "haiku"))]
2267 let l = mem::size_of::<libc::sockaddr_dl>();
2268 #[cfg(any(linux_android, target_os = "fuchsia"))]
2269 let l = mem::size_of::<libc::sockaddr_ll>();
2270 assert_eq!(LinkAddr::size() as usize, l);
2271 }
2272 }
2273
2274 mod sockaddr_in {
2275 use super::*;
2276 use std::str::FromStr;
2277
2278 #[test]
display()2279 fn display() {
2280 let s = "127.0.0.1:8080";
2281 let addr = SockaddrIn::from_str(s).unwrap();
2282 assert_eq!(s, format!("{addr}"));
2283 }
2284
2285 #[test]
size()2286 fn size() {
2287 assert_eq!(
2288 mem::size_of::<libc::sockaddr_in>(),
2289 SockaddrIn::size() as usize
2290 );
2291 }
2292
2293 #[test]
ip()2294 fn ip() {
2295 let s = "127.0.0.1:8082";
2296 let ip = SockaddrIn::from_str(s).unwrap().ip();
2297 assert_eq!("127.0.0.1", format!("{ip}"));
2298 }
2299 }
2300
2301 mod sockaddr_in6 {
2302 use super::*;
2303 use std::str::FromStr;
2304
2305 #[test]
display()2306 fn display() {
2307 let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2308 let addr = SockaddrIn6::from_str(s).unwrap();
2309 assert_eq!(s, format!("{addr}"));
2310 }
2311
2312 #[test]
size()2313 fn size() {
2314 assert_eq!(
2315 mem::size_of::<libc::sockaddr_in6>(),
2316 SockaddrIn6::size() as usize
2317 );
2318 }
2319
2320 #[test]
ip()2321 fn ip() {
2322 let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2323 let ip = SockaddrIn6::from_str(s).unwrap().ip();
2324 assert_eq!("1234:5678:90ab:cdef::1111:2222", format!("{ip}"));
2325 }
2326
2327 #[test]
2328 // Ensure that we can convert to-and-from std::net variants without change.
to_and_from()2329 fn to_and_from() {
2330 let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2331 let mut nix_sin6 = SockaddrIn6::from_str(s).unwrap();
2332 nix_sin6.0.sin6_flowinfo = 0x12345678;
2333 nix_sin6.0.sin6_scope_id = 0x9abcdef0;
2334
2335 let std_sin6: std::net::SocketAddrV6 = nix_sin6.into();
2336 assert_eq!(nix_sin6, std_sin6.into());
2337 }
2338 }
2339
2340 mod sockaddr_storage {
2341 use super::*;
2342
2343 #[test]
from_sockaddr_un_named()2344 fn from_sockaddr_un_named() {
2345 let ua = UnixAddr::new("/var/run/mysock").unwrap();
2346 let ptr = ua.as_ptr().cast();
2347 let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2348 .unwrap();
2349 assert_eq!(ss.len(), ua.len());
2350 }
2351
2352 #[cfg(linux_android)]
2353 #[test]
from_sockaddr_un_abstract_named()2354 fn from_sockaddr_un_abstract_named() {
2355 let name = String::from("nix\0abstract\0test");
2356 let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
2357 let ptr = ua.as_ptr().cast();
2358 let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2359 .unwrap();
2360 assert_eq!(ss.len(), ua.len());
2361 }
2362
2363 #[cfg(linux_android)]
2364 #[test]
from_sockaddr_un_abstract_unnamed()2365 fn from_sockaddr_un_abstract_unnamed() {
2366 let ua = UnixAddr::new_unnamed();
2367 let ptr = ua.as_ptr().cast();
2368 let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2369 .unwrap();
2370 assert_eq!(ss.len(), ua.len());
2371 }
2372 }
2373
2374 mod unixaddr {
2375 use super::*;
2376
2377 #[cfg(linux_android)]
2378 #[test]
abstract_sun_path()2379 fn abstract_sun_path() {
2380 let name = String::from("nix\0abstract\0test");
2381 let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
2382
2383 let sun_path1 =
2384 unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
2385 let sun_path2 = [
2386 0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0,
2387 116, 101, 115, 116,
2388 ];
2389 assert_eq!(sun_path1, sun_path2);
2390 }
2391
2392 #[test]
size()2393 fn size() {
2394 assert_eq!(
2395 mem::size_of::<libc::sockaddr_un>(),
2396 UnixAddr::size() as usize
2397 );
2398 }
2399 }
2400 }
2401