1 use super::sa_family_t;
2 use crate::{Result, NixPath};
3 use crate::errno::Errno;
4 use memoffset::offset_of;
5 use std::{fmt, mem, net, ptr, slice};
6 use std::ffi::OsStr;
7 use std::hash::{Hash, Hasher};
8 use std::path::Path;
9 use std::os::unix::ffi::OsStrExt;
10 #[cfg(any(target_os = "android", target_os = "linux"))]
11 use crate::sys::socket::addr::netlink::NetlinkAddr;
12 #[cfg(any(target_os = "android", target_os = "linux"))]
13 use crate::sys::socket::addr::alg::AlgAddr;
14 #[cfg(any(target_os = "ios", target_os = "macos"))]
15 use std::os::unix::io::RawFd;
16 #[cfg(any(target_os = "ios", target_os = "macos"))]
17 use crate::sys::socket::addr::sys_control::SysControlAddr;
18 #[cfg(any(target_os = "android",
19 target_os = "dragonfly",
20 target_os = "freebsd",
21 target_os = "ios",
22 target_os = "linux",
23 target_os = "macos",
24 target_os = "illumos",
25 target_os = "netbsd",
26 target_os = "openbsd",
27 target_os = "fuchsia"))]
28 pub use self::datalink::LinkAddr;
29 #[cfg(any(target_os = "android", target_os = "linux"))]
30 pub use self::vsock::VsockAddr;
31
32 /// These constants specify the protocol family to be used
33 /// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
34 #[repr(i32)]
35 #[non_exhaustive]
36 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
37 pub enum AddressFamily {
38 /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
39 Unix = libc::AF_UNIX,
40 /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
41 Inet = libc::AF_INET,
42 /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
43 Inet6 = libc::AF_INET6,
44 /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
45 #[cfg(any(target_os = "android", target_os = "linux"))]
46 Netlink = libc::AF_NETLINK,
47 /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
48 #[cfg(any(target_os = "android",
49 target_os = "linux",
50 target_os = "illumos",
51 target_os = "fuchsia",
52 target_os = "solaris"))]
53 Packet = libc::AF_PACKET,
54 /// KEXT Controls and Notifications
55 #[cfg(any(target_os = "ios", target_os = "macos"))]
56 System = libc::AF_SYSTEM,
57 /// Amateur radio AX.25 protocol
58 #[cfg(any(target_os = "android", target_os = "linux"))]
59 Ax25 = libc::AF_AX25,
60 /// IPX - Novell protocols
61 Ipx = libc::AF_IPX,
62 /// AppleTalk
63 AppleTalk = libc::AF_APPLETALK,
64 #[cfg(any(target_os = "android", target_os = "linux"))]
65 NetRom = libc::AF_NETROM,
66 #[cfg(any(target_os = "android", target_os = "linux"))]
67 Bridge = libc::AF_BRIDGE,
68 /// Access to raw ATM PVCs
69 #[cfg(any(target_os = "android", target_os = "linux"))]
70 AtmPvc = libc::AF_ATMPVC,
71 /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
72 #[cfg(any(target_os = "android", target_os = "linux"))]
73 X25 = libc::AF_X25,
74 #[cfg(any(target_os = "android", target_os = "linux"))]
75 Rose = libc::AF_ROSE,
76 Decnet = libc::AF_DECnet,
77 #[cfg(any(target_os = "android", target_os = "linux"))]
78 NetBeui = libc::AF_NETBEUI,
79 #[cfg(any(target_os = "android", target_os = "linux"))]
80 Security = libc::AF_SECURITY,
81 #[cfg(any(target_os = "android", target_os = "linux"))]
82 Key = libc::AF_KEY,
83 #[cfg(any(target_os = "android", target_os = "linux"))]
84 Ash = libc::AF_ASH,
85 #[cfg(any(target_os = "android", target_os = "linux"))]
86 Econet = libc::AF_ECONET,
87 #[cfg(any(target_os = "android", target_os = "linux"))]
88 AtmSvc = libc::AF_ATMSVC,
89 #[cfg(any(target_os = "android", target_os = "linux"))]
90 Rds = libc::AF_RDS,
91 Sna = libc::AF_SNA,
92 #[cfg(any(target_os = "android", target_os = "linux"))]
93 Irda = libc::AF_IRDA,
94 #[cfg(any(target_os = "android", target_os = "linux"))]
95 Pppox = libc::AF_PPPOX,
96 #[cfg(any(target_os = "android", target_os = "linux"))]
97 Wanpipe = libc::AF_WANPIPE,
98 #[cfg(any(target_os = "android", target_os = "linux"))]
99 Llc = libc::AF_LLC,
100 #[cfg(target_os = "linux")]
101 Ib = libc::AF_IB,
102 #[cfg(target_os = "linux")]
103 Mpls = libc::AF_MPLS,
104 #[cfg(any(target_os = "android", target_os = "linux"))]
105 Can = libc::AF_CAN,
106 #[cfg(any(target_os = "android", target_os = "linux"))]
107 Tipc = libc::AF_TIPC,
108 #[cfg(not(any(target_os = "illumos",
109 target_os = "ios",
110 target_os = "macos",
111 target_os = "solaris")))]
112 Bluetooth = libc::AF_BLUETOOTH,
113 #[cfg(any(target_os = "android", target_os = "linux"))]
114 Iucv = libc::AF_IUCV,
115 #[cfg(any(target_os = "android", target_os = "linux"))]
116 RxRpc = libc::AF_RXRPC,
117 #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
118 Isdn = libc::AF_ISDN,
119 #[cfg(any(target_os = "android", target_os = "linux"))]
120 Phonet = libc::AF_PHONET,
121 #[cfg(any(target_os = "android", target_os = "linux"))]
122 Ieee802154 = libc::AF_IEEE802154,
123 #[cfg(any(target_os = "android", target_os = "linux"))]
124 Caif = libc::AF_CAIF,
125 /// Interface to kernel crypto API
126 #[cfg(any(target_os = "android", target_os = "linux"))]
127 Alg = libc::AF_ALG,
128 #[cfg(target_os = "linux")]
129 Nfc = libc::AF_NFC,
130 #[cfg(any(target_os = "android", target_os = "linux"))]
131 Vsock = libc::AF_VSOCK,
132 #[cfg(any(target_os = "dragonfly",
133 target_os = "freebsd",
134 target_os = "ios",
135 target_os = "macos",
136 target_os = "netbsd",
137 target_os = "openbsd"))]
138 ImpLink = libc::AF_IMPLINK,
139 #[cfg(any(target_os = "dragonfly",
140 target_os = "freebsd",
141 target_os = "ios",
142 target_os = "macos",
143 target_os = "netbsd",
144 target_os = "openbsd"))]
145 Pup = libc::AF_PUP,
146 #[cfg(any(target_os = "dragonfly",
147 target_os = "freebsd",
148 target_os = "ios",
149 target_os = "macos",
150 target_os = "netbsd",
151 target_os = "openbsd"))]
152 Chaos = libc::AF_CHAOS,
153 #[cfg(any(target_os = "ios",
154 target_os = "macos",
155 target_os = "netbsd",
156 target_os = "openbsd"))]
157 Ns = libc::AF_NS,
158 #[cfg(any(target_os = "dragonfly",
159 target_os = "freebsd",
160 target_os = "ios",
161 target_os = "macos",
162 target_os = "netbsd",
163 target_os = "openbsd"))]
164 Iso = libc::AF_ISO,
165 #[cfg(any(target_os = "dragonfly",
166 target_os = "freebsd",
167 target_os = "ios",
168 target_os = "macos",
169 target_os = "netbsd",
170 target_os = "openbsd"))]
171 Datakit = libc::AF_DATAKIT,
172 #[cfg(any(target_os = "dragonfly",
173 target_os = "freebsd",
174 target_os = "ios",
175 target_os = "macos",
176 target_os = "netbsd",
177 target_os = "openbsd"))]
178 Ccitt = libc::AF_CCITT,
179 #[cfg(any(target_os = "dragonfly",
180 target_os = "freebsd",
181 target_os = "ios",
182 target_os = "macos",
183 target_os = "netbsd",
184 target_os = "openbsd"))]
185 Dli = libc::AF_DLI,
186 #[cfg(any(target_os = "dragonfly",
187 target_os = "freebsd",
188 target_os = "ios",
189 target_os = "macos",
190 target_os = "netbsd",
191 target_os = "openbsd"))]
192 Lat = libc::AF_LAT,
193 #[cfg(any(target_os = "dragonfly",
194 target_os = "freebsd",
195 target_os = "ios",
196 target_os = "macos",
197 target_os = "netbsd",
198 target_os = "openbsd"))]
199 Hylink = libc::AF_HYLINK,
200 #[cfg(any(target_os = "dragonfly",
201 target_os = "freebsd",
202 target_os = "ios",
203 target_os = "macos",
204 target_os = "illumos",
205 target_os = "netbsd",
206 target_os = "openbsd"))]
207 Link = libc::AF_LINK,
208 #[cfg(any(target_os = "dragonfly",
209 target_os = "freebsd",
210 target_os = "ios",
211 target_os = "macos",
212 target_os = "netbsd",
213 target_os = "openbsd"))]
214 Coip = libc::AF_COIP,
215 #[cfg(any(target_os = "dragonfly",
216 target_os = "freebsd",
217 target_os = "ios",
218 target_os = "macos",
219 target_os = "netbsd",
220 target_os = "openbsd"))]
221 Cnt = libc::AF_CNT,
222 #[cfg(any(target_os = "dragonfly",
223 target_os = "freebsd",
224 target_os = "ios",
225 target_os = "macos",
226 target_os = "netbsd",
227 target_os = "openbsd"))]
228 Natm = libc::AF_NATM,
229 /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
230 #[cfg(any(target_os = "android", target_os = "linux"))]
231 Unspec = libc::AF_UNSPEC,
232 }
233
234 impl AddressFamily {
235 /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
236 /// the `sa_family` field of a `sockaddr`.
237 ///
238 /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
239 /// and System. Returns None for unsupported or unknown address families.
from_i32(family: i32) -> Option<AddressFamily>240 pub const fn from_i32(family: i32) -> Option<AddressFamily> {
241 match family {
242 libc::AF_UNIX => Some(AddressFamily::Unix),
243 libc::AF_INET => Some(AddressFamily::Inet),
244 libc::AF_INET6 => Some(AddressFamily::Inet6),
245 #[cfg(any(target_os = "android", target_os = "linux"))]
246 libc::AF_NETLINK => Some(AddressFamily::Netlink),
247 #[cfg(any(target_os = "macos", target_os = "macos"))]
248 libc::AF_SYSTEM => Some(AddressFamily::System),
249 #[cfg(any(target_os = "android", target_os = "linux"))]
250 libc::AF_PACKET => Some(AddressFamily::Packet),
251 #[cfg(any(target_os = "dragonfly",
252 target_os = "freebsd",
253 target_os = "ios",
254 target_os = "macos",
255 target_os = "netbsd",
256 target_os = "illumos",
257 target_os = "openbsd"))]
258 libc::AF_LINK => Some(AddressFamily::Link),
259 #[cfg(any(target_os = "android", target_os = "linux"))]
260 libc::AF_VSOCK => Some(AddressFamily::Vsock),
261 _ => None
262 }
263 }
264 }
265
266 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
267 pub enum InetAddr {
268 V4(libc::sockaddr_in),
269 V6(libc::sockaddr_in6),
270 }
271
272 impl InetAddr {
273 #[allow(clippy::needless_update)] // It isn't needless on all OSes
from_std(std: &net::SocketAddr) -> InetAddr274 pub fn from_std(std: &net::SocketAddr) -> InetAddr {
275 match *std {
276 net::SocketAddr::V4(ref addr) => {
277 InetAddr::V4(libc::sockaddr_in {
278 sin_family: AddressFamily::Inet as sa_family_t,
279 sin_port: addr.port().to_be(), // network byte order
280 sin_addr: Ipv4Addr::from_std(addr.ip()).0,
281 .. unsafe { mem::zeroed() }
282 })
283 }
284 net::SocketAddr::V6(ref addr) => {
285 InetAddr::V6(libc::sockaddr_in6 {
286 sin6_family: AddressFamily::Inet6 as sa_family_t,
287 sin6_port: addr.port().to_be(), // network byte order
288 sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
289 sin6_flowinfo: addr.flowinfo(), // host byte order
290 sin6_scope_id: addr.scope_id(), // host byte order
291 .. unsafe { mem::zeroed() }
292 })
293 }
294 }
295 }
296
297 #[allow(clippy::needless_update)] // It isn't needless on all OSes
new(ip: IpAddr, port: u16) -> InetAddr298 pub fn new(ip: IpAddr, port: u16) -> InetAddr {
299 match ip {
300 IpAddr::V4(ref ip) => {
301 InetAddr::V4(libc::sockaddr_in {
302 sin_family: AddressFamily::Inet as sa_family_t,
303 sin_port: port.to_be(),
304 sin_addr: ip.0,
305 .. unsafe { mem::zeroed() }
306 })
307 }
308 IpAddr::V6(ref ip) => {
309 InetAddr::V6(libc::sockaddr_in6 {
310 sin6_family: AddressFamily::Inet6 as sa_family_t,
311 sin6_port: port.to_be(),
312 sin6_addr: ip.0,
313 .. unsafe { mem::zeroed() }
314 })
315 }
316 }
317 }
318 /// Gets the IP address associated with this socket address.
ip(&self) -> IpAddr319 pub const fn ip(&self) -> IpAddr {
320 match *self {
321 InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
322 InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
323 }
324 }
325
326 /// Gets the port number associated with this socket address
port(&self) -> u16327 pub const fn port(&self) -> u16 {
328 match *self {
329 InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
330 InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
331 }
332 }
333
to_std(&self) -> net::SocketAddr334 pub fn to_std(&self) -> net::SocketAddr {
335 match *self {
336 InetAddr::V4(ref sa) => net::SocketAddr::V4(
337 net::SocketAddrV4::new(
338 Ipv4Addr(sa.sin_addr).to_std(),
339 self.port())),
340 InetAddr::V6(ref sa) => net::SocketAddr::V6(
341 net::SocketAddrV6::new(
342 Ipv6Addr(sa.sin6_addr).to_std(),
343 self.port(),
344 sa.sin6_flowinfo,
345 sa.sin6_scope_id)),
346 }
347 }
348
349 #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
to_str(&self) -> String350 pub fn to_str(&self) -> String {
351 format!("{}", self)
352 }
353 }
354
355 impl fmt::Display for InetAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result356 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
357 match *self {
358 InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
359 InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
360 }
361 }
362 }
363
364 /*
365 *
366 * ===== IpAddr =====
367 *
368 */
369 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
370 pub enum IpAddr {
371 V4(Ipv4Addr),
372 V6(Ipv6Addr),
373 }
374
375 impl IpAddr {
376 /// Create a new IpAddr that contains an IPv4 address.
377 ///
378 /// The result will represent the IP address a.b.c.d
new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr379 pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
380 IpAddr::V4(Ipv4Addr::new(a, b, c, d))
381 }
382
383 /// Create a new IpAddr that contains an IPv6 address.
384 ///
385 /// The result will represent the IP address a:b:c:d:e:f
386 #[allow(clippy::many_single_char_names)]
387 #[allow(clippy::too_many_arguments)]
new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr388 pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
389 IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
390 }
391
from_std(std: &net::IpAddr) -> IpAddr392 pub fn from_std(std: &net::IpAddr) -> IpAddr {
393 match *std {
394 net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
395 net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
396 }
397 }
398
to_std(&self) -> net::IpAddr399 pub const fn to_std(&self) -> net::IpAddr {
400 match *self {
401 IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
402 IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
403 }
404 }
405 }
406
407 impl fmt::Display for IpAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result408 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
409 match *self {
410 IpAddr::V4(ref v4) => v4.fmt(f),
411 IpAddr::V6(ref v6) => v6.fmt(f)
412 }
413 }
414 }
415
416 /*
417 *
418 * ===== Ipv4Addr =====
419 *
420 */
421
422 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
423 pub struct Ipv4Addr(pub libc::in_addr);
424
425 impl Ipv4Addr {
426 #[allow(clippy::identity_op)] // More readable this way
new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr427 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
428 let ip = (((a as u32) << 24) |
429 ((b as u32) << 16) |
430 ((c as u32) << 8) |
431 ((d as u32) << 0)).to_be();
432
433 Ipv4Addr(libc::in_addr { s_addr: ip })
434 }
435
436 // Use pass by reference for symmetry with Ipv6Addr::from_std
437 #[allow(clippy::trivially_copy_pass_by_ref)]
from_std(std: &net::Ipv4Addr) -> Ipv4Addr438 pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
439 let bits = std.octets();
440 Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
441 }
442
any() -> Ipv4Addr443 pub const fn any() -> Ipv4Addr {
444 Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
445 }
446
octets(self) -> [u8; 4]447 pub const fn octets(self) -> [u8; 4] {
448 let bits = u32::from_be(self.0.s_addr);
449 [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
450 }
451
to_std(self) -> net::Ipv4Addr452 pub const fn to_std(self) -> net::Ipv4Addr {
453 let bits = self.octets();
454 net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
455 }
456 }
457
458 impl fmt::Display for Ipv4Addr {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result459 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
460 let octets = self.octets();
461 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
462 }
463 }
464
465 /*
466 *
467 * ===== Ipv6Addr =====
468 *
469 */
470
471 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
472 pub struct Ipv6Addr(pub libc::in6_addr);
473
474 // Note that IPv6 addresses are stored in big endian order on all architectures.
475 // See https://tools.ietf.org/html/rfc1700 or consult your favorite search
476 // engine.
477
478 macro_rules! to_u8_array {
479 ($($num:ident),*) => {
480 [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
481 }
482 }
483
484 macro_rules! to_u16_array {
485 ($slf:ident, $($first:expr, $second:expr),*) => {
486 [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
487 }
488 }
489
490 impl Ipv6Addr {
491 #[allow(clippy::many_single_char_names)]
492 #[allow(clippy::too_many_arguments)]
new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr493 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
494 Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
495 }
496
from_std(std: &net::Ipv6Addr) -> Ipv6Addr497 pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
498 let s = std.segments();
499 Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
500 }
501
502 /// Return the eight 16-bit segments that make up this address
segments(&self) -> [u16; 8]503 pub const fn segments(&self) -> [u16; 8] {
504 to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
505 }
506
to_std(&self) -> net::Ipv6Addr507 pub const fn to_std(&self) -> net::Ipv6Addr {
508 let s = self.segments();
509 net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
510 }
511 }
512
513 impl fmt::Display for Ipv6Addr {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result514 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
515 self.to_std().fmt(fmt)
516 }
517 }
518
519 /// A wrapper around `sockaddr_un`.
520 #[derive(Clone, Copy, Debug)]
521 pub struct UnixAddr {
522 // INVARIANT: sun & path_len are valid as defined by docs for from_raw_parts
523 sun: libc::sockaddr_un,
524 path_len: usize,
525 }
526
527 // linux man page unix(7) says there are 3 kinds of unix socket:
528 // pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
529 // unnamed: addrlen = sizeof(sa_family_t)
530 // abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))]
531 //
532 // what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path)
533 #[derive(PartialEq, Eq, Hash)]
534 enum UnixAddrKind<'a> {
535 Pathname(&'a Path),
536 Unnamed,
537 #[cfg(any(target_os = "android", target_os = "linux"))]
538 Abstract(&'a [u8]),
539 }
540 impl<'a> UnixAddrKind<'a> {
541 /// Safety: sun & path_len must be valid
get(sun: &'a libc::sockaddr_un, path_len: usize) -> Self542 unsafe fn get(sun: &'a libc::sockaddr_un, path_len: usize) -> Self {
543 if path_len == 0 {
544 return Self::Unnamed;
545 }
546 #[cfg(any(target_os = "android", target_os = "linux"))]
547 if sun.sun_path[0] == 0 {
548 let name =
549 slice::from_raw_parts(sun.sun_path.as_ptr().add(1) as *const u8, path_len - 1);
550 return Self::Abstract(name);
551 }
552 let pathname = slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len - 1);
553 Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
554 }
555 }
556
557 impl UnixAddr {
558 /// Create a new sockaddr_un representing a filesystem path.
new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr>559 pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
560 path.with_nix_path(|cstr| {
561 unsafe {
562 let mut ret = libc::sockaddr_un {
563 sun_family: AddressFamily::Unix as sa_family_t,
564 .. mem::zeroed()
565 };
566
567 let bytes = cstr.to_bytes();
568
569 if bytes.len() >= ret.sun_path.len() {
570 return Err(Errno::ENAMETOOLONG);
571 }
572
573 ptr::copy_nonoverlapping(bytes.as_ptr(),
574 ret.sun_path.as_mut_ptr() as *mut u8,
575 bytes.len());
576
577 Ok(UnixAddr::from_raw_parts(ret, bytes.len() + 1))
578 }
579 })?
580 }
581
582 /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
583 ///
584 /// The leading null byte for the abstract namespace is automatically added;
585 /// thus the input `path` is expected to be the bare name, not null-prefixed.
586 /// This is a Linux-specific extension, primarily used to allow chrooted
587 /// processes to communicate with processes having a different filesystem view.
588 #[cfg(any(target_os = "android", target_os = "linux"))]
new_abstract(path: &[u8]) -> Result<UnixAddr>589 pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
590 unsafe {
591 let mut ret = libc::sockaddr_un {
592 sun_family: AddressFamily::Unix as sa_family_t,
593 .. mem::zeroed()
594 };
595
596 if path.len() >= ret.sun_path.len() {
597 return Err(Errno::ENAMETOOLONG);
598 }
599
600 // Abstract addresses are represented by sun_path[0] ==
601 // b'\0', so copy starting one byte in.
602 ptr::copy_nonoverlapping(path.as_ptr(),
603 ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
604 path.len());
605
606 Ok(UnixAddr::from_raw_parts(ret, path.len() + 1))
607 }
608 }
609
610 /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `path_len` is the "addrlen"
611 /// of this address, but minus `offsetof(struct sockaddr_un, sun_path)`. Basically the length
612 /// of the data in `sun_path`.
613 ///
614 /// # Safety
615 /// This pair of sockaddr_un & path_len must be a valid unix addr, which means:
616 /// - path_len <= sockaddr_un.sun_path.len()
617 /// - if this is a unix addr with a pathname, sun.sun_path is a nul-terminated fs path and
618 /// sun.sun_path[path_len - 1] == 0 || sun.sun_path[path_len] == 0
from_raw_parts(sun: libc::sockaddr_un, mut path_len: usize) -> UnixAddr619 pub(crate) unsafe fn from_raw_parts(sun: libc::sockaddr_un, mut path_len: usize) -> UnixAddr {
620 if let UnixAddrKind::Pathname(_) = UnixAddrKind::get(&sun, path_len) {
621 if sun.sun_path[path_len - 1] != 0 {
622 assert_eq!(sun.sun_path[path_len], 0);
623 path_len += 1
624 }
625 }
626 UnixAddr { sun, path_len }
627 }
628
kind(&self) -> UnixAddrKind<'_>629 fn kind(&self) -> UnixAddrKind<'_> {
630 // SAFETY: our sockaddr is always valid because of the invariant on the struct
631 unsafe { UnixAddrKind::get(&self.sun, self.path_len) }
632 }
633
634 /// If this address represents a filesystem path, return that path.
path(&self) -> Option<&Path>635 pub fn path(&self) -> Option<&Path> {
636 match self.kind() {
637 UnixAddrKind::Pathname(path) => Some(path),
638 _ => None,
639 }
640 }
641
642 /// If this address represents an abstract socket, return its name.
643 ///
644 /// For abstract sockets only the bare name is returned, without the
645 /// leading null byte. `None` is returned for unnamed or path-backed sockets.
646 #[cfg(any(target_os = "android", target_os = "linux"))]
as_abstract(&self) -> Option<&[u8]>647 pub fn as_abstract(&self) -> Option<&[u8]> {
648 match self.kind() {
649 UnixAddrKind::Abstract(name) => Some(name),
650 _ => None,
651 }
652 }
653
654 /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
655 #[inline]
path_len(&self) -> usize656 pub fn path_len(&self) -> usize {
657 self.path_len
658 }
659 /// Returns a pointer to the raw `sockaddr_un` struct
660 #[inline]
as_ptr(&self) -> *const libc::sockaddr_un661 pub fn as_ptr(&self) -> *const libc::sockaddr_un {
662 &self.sun
663 }
664 /// Returns a mutable pointer to the raw `sockaddr_un` struct
665 #[inline]
as_mut_ptr(&mut self) -> *mut libc::sockaddr_un666 pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
667 &mut self.sun
668 }
669 }
670
671 #[cfg(any(target_os = "android", target_os = "linux"))]
fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result672 fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
673 use fmt::Write;
674 f.write_str("@\"")?;
675 for &b in abs {
676 use fmt::Display;
677 char::from(b).escape_default().fmt(f)?;
678 }
679 f.write_char('"')?;
680 Ok(())
681 }
682
683 impl fmt::Display for UnixAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result684 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
685 match self.kind() {
686 UnixAddrKind::Pathname(path) => path.display().fmt(f),
687 UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
688 #[cfg(any(target_os = "android", target_os = "linux"))]
689 UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
690 }
691 }
692 }
693
694 impl PartialEq for UnixAddr {
eq(&self, other: &UnixAddr) -> bool695 fn eq(&self, other: &UnixAddr) -> bool {
696 self.kind() == other.kind()
697 }
698 }
699
700 impl Eq for UnixAddr {}
701
702 impl Hash for UnixAddr {
hash<H: Hasher>(&self, s: &mut H)703 fn hash<H: Hasher>(&self, s: &mut H) {
704 self.kind().hash(s)
705 }
706 }
707
708 /// Represents a socket address
709 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
710 #[non_exhaustive]
711 pub enum SockAddr {
712 Inet(InetAddr),
713 Unix(UnixAddr),
714 #[cfg(any(target_os = "android", target_os = "linux"))]
715 Netlink(NetlinkAddr),
716 #[cfg(any(target_os = "android", target_os = "linux"))]
717 Alg(AlgAddr),
718 #[cfg(any(target_os = "ios", target_os = "macos"))]
719 SysControl(SysControlAddr),
720 /// Datalink address (MAC)
721 #[cfg(any(target_os = "android",
722 target_os = "dragonfly",
723 target_os = "freebsd",
724 target_os = "ios",
725 target_os = "linux",
726 target_os = "macos",
727 target_os = "illumos",
728 target_os = "netbsd",
729 target_os = "openbsd"))]
730 Link(LinkAddr),
731 #[cfg(any(target_os = "android", target_os = "linux"))]
732 Vsock(VsockAddr),
733 }
734
735 impl SockAddr {
new_inet(addr: InetAddr) -> SockAddr736 pub fn new_inet(addr: InetAddr) -> SockAddr {
737 SockAddr::Inet(addr)
738 }
739
new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr>740 pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
741 Ok(SockAddr::Unix(UnixAddr::new(path)?))
742 }
743
744 #[cfg(any(target_os = "android", target_os = "linux"))]
new_netlink(pid: u32, groups: u32) -> SockAddr745 pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
746 SockAddr::Netlink(NetlinkAddr::new(pid, groups))
747 }
748
749 #[cfg(any(target_os = "android", target_os = "linux"))]
new_alg(alg_type: &str, alg_name: &str) -> SockAddr750 pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
751 SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
752 }
753
754 #[cfg(any(target_os = "ios", target_os = "macos"))]
new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr>755 pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
756 SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl)
757 }
758
759 #[cfg(any(target_os = "android", target_os = "linux"))]
new_vsock(cid: u32, port: u32) -> SockAddr760 pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
761 SockAddr::Vsock(VsockAddr::new(cid, port))
762 }
763
family(&self) -> AddressFamily764 pub fn family(&self) -> AddressFamily {
765 match *self {
766 SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
767 SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
768 SockAddr::Unix(..) => AddressFamily::Unix,
769 #[cfg(any(target_os = "android", target_os = "linux"))]
770 SockAddr::Netlink(..) => AddressFamily::Netlink,
771 #[cfg(any(target_os = "android", target_os = "linux"))]
772 SockAddr::Alg(..) => AddressFamily::Alg,
773 #[cfg(any(target_os = "ios", target_os = "macos"))]
774 SockAddr::SysControl(..) => AddressFamily::System,
775 #[cfg(any(target_os = "android", target_os = "linux"))]
776 SockAddr::Link(..) => AddressFamily::Packet,
777 #[cfg(any(target_os = "dragonfly",
778 target_os = "freebsd",
779 target_os = "ios",
780 target_os = "macos",
781 target_os = "netbsd",
782 target_os = "illumos",
783 target_os = "openbsd"))]
784 SockAddr::Link(..) => AddressFamily::Link,
785 #[cfg(any(target_os = "android", target_os = "linux"))]
786 SockAddr::Vsock(..) => AddressFamily::Vsock,
787 }
788 }
789
790 #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
to_str(&self) -> String791 pub fn to_str(&self) -> String {
792 format!("{}", self)
793 }
794
795 /// Creates a `SockAddr` struct from libc's sockaddr.
796 ///
797 /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
798 /// Returns None for unsupported families.
799 ///
800 /// # Safety
801 ///
802 /// unsafe because it takes a raw pointer as argument. The caller must
803 /// ensure that the pointer is valid.
804 #[cfg(not(target_os = "fuchsia"))]
from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr>805 pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
806 if addr.is_null() {
807 None
808 } else {
809 match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
810 Some(AddressFamily::Unix) => None,
811 Some(AddressFamily::Inet) => Some(SockAddr::Inet(
812 InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
813 Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
814 InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
815 #[cfg(any(target_os = "android", target_os = "linux"))]
816 Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
817 NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
818 #[cfg(any(target_os = "ios", target_os = "macos"))]
819 Some(AddressFamily::System) => Some(SockAddr::SysControl(
820 SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
821 #[cfg(any(target_os = "android", target_os = "linux"))]
822 Some(AddressFamily::Packet) => Some(SockAddr::Link(
823 LinkAddr(*(addr as *const libc::sockaddr_ll)))),
824 #[cfg(any(target_os = "dragonfly",
825 target_os = "freebsd",
826 target_os = "ios",
827 target_os = "macos",
828 target_os = "netbsd",
829 target_os = "illumos",
830 target_os = "openbsd"))]
831 Some(AddressFamily::Link) => {
832 let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
833 if ether_addr.is_empty() {
834 None
835 } else {
836 Some(SockAddr::Link(ether_addr))
837 }
838 },
839 #[cfg(any(target_os = "android", target_os = "linux"))]
840 Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
841 VsockAddr(*(addr as *const libc::sockaddr_vm)))),
842 // Other address families are currently not supported and simply yield a None
843 // entry instead of a proper conversion to a `SockAddr`.
844 Some(_) | None => None,
845 }
846 }
847 }
848
849 /// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
850 ///
851 /// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
852 /// Returns a reference to the underlying data type (as a sockaddr reference) along
853 /// with the size of the actual data type. sockaddr is commonly used as a proxy for
854 /// a superclass as C doesn't support inheritance, so many functions that take
855 /// 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)856 pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
857 match *self {
858 SockAddr::Inet(InetAddr::V4(ref addr)) => (
859 // This cast is always allowed in C
860 unsafe {
861 &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
862 },
863 mem::size_of_val(addr) as libc::socklen_t
864 ),
865 SockAddr::Inet(InetAddr::V6(ref addr)) => (
866 // This cast is always allowed in C
867 unsafe {
868 &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
869 },
870 mem::size_of_val(addr) as libc::socklen_t
871 ),
872 SockAddr::Unix(UnixAddr { ref sun, path_len }) => (
873 // This cast is always allowed in C
874 unsafe {
875 &*(sun as *const libc::sockaddr_un as *const libc::sockaddr)
876 },
877 (path_len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
878 ),
879 #[cfg(any(target_os = "android", target_os = "linux"))]
880 SockAddr::Netlink(NetlinkAddr(ref sa)) => (
881 // This cast is always allowed in C
882 unsafe {
883 &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
884 },
885 mem::size_of_val(sa) as libc::socklen_t
886 ),
887 #[cfg(any(target_os = "android", target_os = "linux"))]
888 SockAddr::Alg(AlgAddr(ref sa)) => (
889 // This cast is always allowed in C
890 unsafe {
891 &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
892 },
893 mem::size_of_val(sa) as libc::socklen_t
894 ),
895 #[cfg(any(target_os = "ios", target_os = "macos"))]
896 SockAddr::SysControl(SysControlAddr(ref sa)) => (
897 // This cast is always allowed in C
898 unsafe {
899 &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
900 },
901 mem::size_of_val(sa) as libc::socklen_t
902
903 ),
904 #[cfg(any(target_os = "android", target_os = "linux"))]
905 SockAddr::Link(LinkAddr(ref addr)) => (
906 // This cast is always allowed in C
907 unsafe {
908 &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
909 },
910 mem::size_of_val(addr) as libc::socklen_t
911 ),
912 #[cfg(any(target_os = "dragonfly",
913 target_os = "freebsd",
914 target_os = "ios",
915 target_os = "macos",
916 target_os = "illumos",
917 target_os = "netbsd",
918 target_os = "openbsd"))]
919 SockAddr::Link(LinkAddr(ref addr)) => (
920 // This cast is always allowed in C
921 unsafe {
922 &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
923 },
924 mem::size_of_val(addr) as libc::socklen_t
925 ),
926 #[cfg(any(target_os = "android", target_os = "linux"))]
927 SockAddr::Vsock(VsockAddr(ref sa)) => (
928 // This cast is always allowed in C
929 unsafe {
930 &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
931 },
932 mem::size_of_val(sa) as libc::socklen_t
933 ),
934 }
935 }
936 }
937
938 impl fmt::Display for SockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result939 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
940 match *self {
941 SockAddr::Inet(ref inet) => inet.fmt(f),
942 SockAddr::Unix(ref unix) => unix.fmt(f),
943 #[cfg(any(target_os = "android", target_os = "linux"))]
944 SockAddr::Netlink(ref nl) => nl.fmt(f),
945 #[cfg(any(target_os = "android", target_os = "linux"))]
946 SockAddr::Alg(ref nl) => nl.fmt(f),
947 #[cfg(any(target_os = "ios", target_os = "macos"))]
948 SockAddr::SysControl(ref sc) => sc.fmt(f),
949 #[cfg(any(target_os = "android",
950 target_os = "dragonfly",
951 target_os = "freebsd",
952 target_os = "ios",
953 target_os = "linux",
954 target_os = "macos",
955 target_os = "netbsd",
956 target_os = "illumos",
957 target_os = "openbsd"))]
958 SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
959 #[cfg(any(target_os = "android", target_os = "linux"))]
960 SockAddr::Vsock(ref svm) => svm.fmt(f),
961 }
962 }
963 }
964
965 #[cfg(any(target_os = "android", target_os = "linux"))]
966 pub mod netlink {
967 use crate::sys::socket::addr::AddressFamily;
968 use libc::{sa_family_t, sockaddr_nl};
969 use std::{fmt, mem};
970
971 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
972 pub struct NetlinkAddr(pub sockaddr_nl);
973
974 impl NetlinkAddr {
new(pid: u32, groups: u32) -> NetlinkAddr975 pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
976 let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
977 addr.nl_family = AddressFamily::Netlink as sa_family_t;
978 addr.nl_pid = pid;
979 addr.nl_groups = groups;
980
981 NetlinkAddr(addr)
982 }
983
pid(&self) -> u32984 pub const fn pid(&self) -> u32 {
985 self.0.nl_pid
986 }
987
groups(&self) -> u32988 pub const fn groups(&self) -> u32 {
989 self.0.nl_groups
990 }
991 }
992
993 impl fmt::Display for NetlinkAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result994 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
995 write!(f, "pid: {} groups: {}", self.pid(), self.groups())
996 }
997 }
998 }
999
1000 #[cfg(any(target_os = "android", target_os = "linux"))]
1001 pub mod alg {
1002 use libc::{AF_ALG, sockaddr_alg, c_char};
1003 use std::{fmt, mem, str};
1004 use std::hash::{Hash, Hasher};
1005 use std::ffi::CStr;
1006
1007 #[derive(Copy, Clone)]
1008 pub struct AlgAddr(pub sockaddr_alg);
1009
1010 // , PartialEq, Eq, Debug, Hash
1011 impl PartialEq for AlgAddr {
eq(&self, other: &Self) -> bool1012 fn eq(&self, other: &Self) -> bool {
1013 let (inner, other) = (self.0, other.0);
1014 (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
1015 (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
1016 }
1017 }
1018
1019 impl Eq for AlgAddr {}
1020
1021 impl Hash for AlgAddr {
hash<H: Hasher>(&self, s: &mut H)1022 fn hash<H: Hasher>(&self, s: &mut H) {
1023 let inner = self.0;
1024 (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
1025 }
1026 }
1027
1028 impl AlgAddr {
new(alg_type: &str, alg_name: &str) -> AlgAddr1029 pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
1030 let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
1031 addr.salg_family = AF_ALG as u16;
1032 addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
1033 addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
1034
1035 AlgAddr(addr)
1036 }
1037
1038
alg_type(&self) -> &CStr1039 pub fn alg_type(&self) -> &CStr {
1040 unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
1041 }
1042
alg_name(&self) -> &CStr1043 pub fn alg_name(&self) -> &CStr {
1044 unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
1045 }
1046 }
1047
1048 impl fmt::Display for AlgAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1049 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1050 write!(f, "type: {} alg: {}",
1051 self.alg_name().to_string_lossy(),
1052 self.alg_type().to_string_lossy())
1053 }
1054 }
1055
1056 impl fmt::Debug for AlgAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1057 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1058 fmt::Display::fmt(self, f)
1059 }
1060 }
1061 }
1062
1063 #[cfg(any(target_os = "ios", target_os = "macos"))]
1064 pub mod sys_control {
1065 use crate::sys::socket::addr::AddressFamily;
1066 use libc::{self, c_uchar};
1067 use std::{fmt, mem};
1068 use std::os::unix::io::RawFd;
1069 use crate::{Errno, Result};
1070
1071 // FIXME: Move type into `libc`
1072 #[repr(C)]
1073 #[derive(Clone, Copy)]
1074 #[allow(missing_debug_implementations)]
1075 pub struct ctl_ioc_info {
1076 pub ctl_id: u32,
1077 pub ctl_name: [c_uchar; MAX_KCTL_NAME],
1078 }
1079
1080 const CTL_IOC_MAGIC: u8 = b'N';
1081 const CTL_IOC_INFO: u8 = 3;
1082 const MAX_KCTL_NAME: usize = 96;
1083
1084 ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
1085
1086 #[repr(C)]
1087 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1088 pub struct SysControlAddr(pub libc::sockaddr_ctl);
1089
1090 impl SysControlAddr {
new(id: u32, unit: u32) -> SysControlAddr1091 pub const fn new(id: u32, unit: u32) -> SysControlAddr {
1092 let addr = libc::sockaddr_ctl {
1093 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
1094 sc_family: AddressFamily::System as c_uchar,
1095 ss_sysaddr: libc::AF_SYS_CONTROL as u16,
1096 sc_id: id,
1097 sc_unit: unit,
1098 sc_reserved: [0; 5]
1099 };
1100
1101 SysControlAddr(addr)
1102 }
1103
from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr>1104 pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
1105 if name.len() > MAX_KCTL_NAME {
1106 return Err(Errno::ENAMETOOLONG);
1107 }
1108
1109 let mut ctl_name = [0; MAX_KCTL_NAME];
1110 ctl_name[..name.len()].clone_from_slice(name.as_bytes());
1111 let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
1112
1113 unsafe { ctl_info(sockfd, &mut info)?; }
1114
1115 Ok(SysControlAddr::new(info.ctl_id, unit))
1116 }
1117
id(&self) -> u321118 pub const fn id(&self) -> u32 {
1119 self.0.sc_id
1120 }
1121
unit(&self) -> u321122 pub const fn unit(&self) -> u32 {
1123 self.0.sc_unit
1124 }
1125 }
1126
1127 impl fmt::Display for SysControlAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1129 fmt::Debug::fmt(self, f)
1130 }
1131 }
1132 }
1133
1134
1135 #[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
1136 mod datalink {
1137 use super::{fmt, AddressFamily};
1138
1139 /// Hardware Address
1140 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1141 pub struct LinkAddr(pub libc::sockaddr_ll);
1142
1143 impl LinkAddr {
1144 /// Always AF_PACKET
family(&self) -> AddressFamily1145 pub fn family(&self) -> AddressFamily {
1146 assert_eq!(self.0.sll_family as i32, libc::AF_PACKET);
1147 AddressFamily::Packet
1148 }
1149
1150 /// Physical-layer protocol
protocol(&self) -> u161151 pub fn protocol(&self) -> u16 {
1152 self.0.sll_protocol
1153 }
1154
1155 /// Interface number
ifindex(&self) -> usize1156 pub fn ifindex(&self) -> usize {
1157 self.0.sll_ifindex as usize
1158 }
1159
1160 /// ARP hardware type
hatype(&self) -> u161161 pub fn hatype(&self) -> u16 {
1162 self.0.sll_hatype
1163 }
1164
1165 /// Packet type
pkttype(&self) -> u81166 pub fn pkttype(&self) -> u8 {
1167 self.0.sll_pkttype
1168 }
1169
1170 /// Length of MAC address
halen(&self) -> usize1171 pub fn halen(&self) -> usize {
1172 self.0.sll_halen as usize
1173 }
1174
1175 /// Physical-layer address (MAC)
addr(&self) -> [u8; 6]1176 pub fn addr(&self) -> [u8; 6] {
1177 [
1178 self.0.sll_addr[0] as u8,
1179 self.0.sll_addr[1] as u8,
1180 self.0.sll_addr[2] as u8,
1181 self.0.sll_addr[3] as u8,
1182 self.0.sll_addr[4] as u8,
1183 self.0.sll_addr[5] as u8,
1184 ]
1185 }
1186 }
1187
1188 impl fmt::Display for LinkAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1189 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1190 let addr = self.addr();
1191 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1192 addr[0],
1193 addr[1],
1194 addr[2],
1195 addr[3],
1196 addr[4],
1197 addr[5])
1198 }
1199 }
1200 }
1201
1202 #[cfg(any(target_os = "dragonfly",
1203 target_os = "freebsd",
1204 target_os = "ios",
1205 target_os = "macos",
1206 target_os = "illumos",
1207 target_os = "netbsd",
1208 target_os = "openbsd"))]
1209 mod datalink {
1210 use super::{fmt, AddressFamily};
1211
1212 /// Hardware Address
1213 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1214 pub struct LinkAddr(pub libc::sockaddr_dl);
1215
1216 impl LinkAddr {
1217 /// Total length of sockaddr
1218 #[cfg(not(target_os = "illumos"))]
len(&self) -> usize1219 pub fn len(&self) -> usize {
1220 self.0.sdl_len as usize
1221 }
1222
1223 /// always == AF_LINK
family(&self) -> AddressFamily1224 pub fn family(&self) -> AddressFamily {
1225 assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK);
1226 AddressFamily::Link
1227 }
1228
1229 /// interface index, if != 0, system given index for interface
ifindex(&self) -> usize1230 pub fn ifindex(&self) -> usize {
1231 self.0.sdl_index as usize
1232 }
1233
1234 /// Datalink type
datalink_type(&self) -> u81235 pub fn datalink_type(&self) -> u8 {
1236 self.0.sdl_type
1237 }
1238
1239 // MAC address start position
nlen(&self) -> usize1240 pub fn nlen(&self) -> usize {
1241 self.0.sdl_nlen as usize
1242 }
1243
1244 /// link level address length
alen(&self) -> usize1245 pub fn alen(&self) -> usize {
1246 self.0.sdl_alen as usize
1247 }
1248
1249 /// link layer selector length
slen(&self) -> usize1250 pub fn slen(&self) -> usize {
1251 self.0.sdl_slen as usize
1252 }
1253
1254 /// if link level address length == 0,
1255 /// or `sdl_data` not be larger.
is_empty(&self) -> bool1256 pub fn is_empty(&self) -> bool {
1257 let nlen = self.nlen();
1258 let alen = self.alen();
1259 let data_len = self.0.sdl_data.len();
1260
1261 alen == 0 || nlen + alen >= data_len
1262 }
1263
1264 /// Physical-layer address (MAC)
addr(&self) -> [u8; 6]1265 pub fn addr(&self) -> [u8; 6] {
1266 let nlen = self.nlen();
1267 let data = self.0.sdl_data;
1268
1269 assert!(!self.is_empty());
1270
1271 [
1272 data[nlen] as u8,
1273 data[nlen + 1] as u8,
1274 data[nlen + 2] as u8,
1275 data[nlen + 3] as u8,
1276 data[nlen + 4] as u8,
1277 data[nlen + 5] as u8,
1278 ]
1279 }
1280 }
1281
1282 impl fmt::Display for LinkAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1283 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1284 let addr = self.addr();
1285 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1286 addr[0],
1287 addr[1],
1288 addr[2],
1289 addr[3],
1290 addr[4],
1291 addr[5])
1292 }
1293 }
1294 }
1295
1296 #[cfg(any(target_os = "android", target_os = "linux"))]
1297 pub mod vsock {
1298 use crate::sys::socket::addr::AddressFamily;
1299 use libc::{sa_family_t, sockaddr_vm};
1300 use std::{fmt, mem};
1301 use std::hash::{Hash, Hasher};
1302
1303 #[derive(Copy, Clone)]
1304 pub struct VsockAddr(pub sockaddr_vm);
1305
1306 impl PartialEq for VsockAddr {
eq(&self, other: &Self) -> bool1307 fn eq(&self, other: &Self) -> bool {
1308 let (inner, other) = (self.0, other.0);
1309 (inner.svm_family, inner.svm_cid, inner.svm_port) ==
1310 (other.svm_family, other.svm_cid, other.svm_port)
1311 }
1312 }
1313
1314 impl Eq for VsockAddr {}
1315
1316 impl Hash for VsockAddr {
hash<H: Hasher>(&self, s: &mut H)1317 fn hash<H: Hasher>(&self, s: &mut H) {
1318 let inner = self.0;
1319 (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
1320 }
1321 }
1322
1323 /// VSOCK Address
1324 ///
1325 /// The address for AF_VSOCK socket is defined as a combination of a
1326 /// 32-bit Context Identifier (CID) and a 32-bit port number.
1327 impl VsockAddr {
new(cid: u32, port: u32) -> VsockAddr1328 pub fn new(cid: u32, port: u32) -> VsockAddr {
1329 let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
1330 addr.svm_family = AddressFamily::Vsock as sa_family_t;
1331 addr.svm_cid = cid;
1332 addr.svm_port = port;
1333
1334 VsockAddr(addr)
1335 }
1336
1337 /// Context Identifier (CID)
cid(&self) -> u321338 pub fn cid(&self) -> u32 {
1339 self.0.svm_cid
1340 }
1341
1342 /// Port number
port(&self) -> u321343 pub fn port(&self) -> u32 {
1344 self.0.svm_port
1345 }
1346 }
1347
1348 impl fmt::Display for VsockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1349 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1350 write!(f, "cid: {} port: {}", self.cid(), self.port())
1351 }
1352 }
1353
1354 impl fmt::Debug for VsockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1355 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1356 fmt::Display::fmt(self, f)
1357 }
1358 }
1359 }
1360
1361 #[cfg(test)]
1362 mod tests {
1363 #[cfg(any(target_os = "android",
1364 target_os = "dragonfly",
1365 target_os = "freebsd",
1366 target_os = "ios",
1367 target_os = "linux",
1368 target_os = "macos",
1369 target_os = "netbsd",
1370 target_os = "illumos",
1371 target_os = "openbsd"))]
1372 use super::*;
1373
1374 #[cfg(any(target_os = "dragonfly",
1375 target_os = "freebsd",
1376 target_os = "ios",
1377 target_os = "macos",
1378 target_os = "netbsd",
1379 target_os = "openbsd"))]
1380 #[test]
test_macos_loopback_datalink_addr()1381 fn test_macos_loopback_datalink_addr() {
1382 let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
1383 let sa = bytes.as_ptr() as *const libc::sockaddr;
1384 let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1385 assert!(_sock_addr.is_none());
1386 }
1387
1388 #[cfg(any(target_os = "dragonfly",
1389 target_os = "freebsd",
1390 target_os = "ios",
1391 target_os = "macos",
1392 target_os = "netbsd",
1393 target_os = "openbsd"))]
1394 #[test]
test_macos_tap_datalink_addr()1395 fn test_macos_tap_datalink_addr() {
1396 let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
1397 let ptr = bytes.as_ptr();
1398 let sa = ptr as *const libc::sockaddr;
1399 let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1400
1401 assert!(_sock_addr.is_some());
1402
1403 let sock_addr = _sock_addr.unwrap();
1404
1405 assert_eq!(sock_addr.family(), AddressFamily::Link);
1406
1407 match sock_addr {
1408 SockAddr::Link(ether_addr) => {
1409 assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
1410 },
1411 _ => { unreachable!() }
1412 };
1413 }
1414
1415 #[cfg(target_os = "illumos")]
1416 #[test]
test_illumos_tap_datalink_addr()1417 fn test_illumos_tap_datalink_addr() {
1418 let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
1419 let ptr = bytes.as_ptr();
1420 let sa = ptr as *const libc::sockaddr;
1421 let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1422
1423 assert!(_sock_addr.is_some());
1424
1425 let sock_addr = _sock_addr.unwrap();
1426
1427 assert_eq!(sock_addr.family(), AddressFamily::Link);
1428
1429 match sock_addr {
1430 SockAddr::Link(ether_addr) => {
1431 assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
1432 },
1433 _ => { unreachable!() }
1434 };
1435 }
1436
1437 #[cfg(any(target_os = "android", target_os = "linux"))]
1438 #[test]
test_abstract_sun_path()1439 fn test_abstract_sun_path() {
1440 let name = String::from("nix\0abstract\0test");
1441 let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
1442
1443 let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
1444 let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
1445 assert_eq!(sun_path1, sun_path2);
1446 }
1447 }
1448