1use super::sa_family_t;
2use cfg_if::cfg_if;
3use crate::{Result, NixPath};
4use crate::errno::Errno;
5use memoffset::offset_of;
6use std::{fmt, mem, net, ptr, slice};
7use std::convert::TryInto;
8use std::ffi::OsStr;
9use std::hash::{Hash, Hasher};
10use std::path::Path;
11use std::os::unix::ffi::OsStrExt;
12#[cfg(any(target_os = "android", target_os = "linux"))]
13use crate::sys::socket::addr::netlink::NetlinkAddr;
14#[cfg(any(target_os = "android", target_os = "linux"))]
15use crate::sys::socket::addr::alg::AlgAddr;
16#[cfg(any(target_os = "ios", target_os = "macos"))]
17use std::os::unix::io::RawFd;
18#[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
19use crate::sys::socket::addr::sys_control::SysControlAddr;
20#[cfg(any(target_os = "android",
21 target_os = "dragonfly",
22 target_os = "freebsd",
23 target_os = "ios",
24 target_os = "linux",
25 target_os = "macos",
26 target_os = "illumos",
27 target_os = "netbsd",
28 target_os = "openbsd",
29 target_os = "fuchsia"))]
30#[cfg(feature = "net")]
31pub use self::datalink::LinkAddr;
32#[cfg(any(target_os = "android", target_os = "linux"))]
33pub use self::vsock::VsockAddr;
34
35#[cfg(feature = "net")]
37pub(crate) fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
38 let octets = addr.octets();
39 libc::in_addr {
40 s_addr: u32::to_be(((octets[0] as u32) << 24) |
41 ((octets[1] as u32) << 16) |
42 ((octets[2] as u32) << 8) |
43 (octets[3] as u32))
44 }
45}
46
47#[cfg(feature = "net")]
49pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr {
50 libc::in6_addr {
51 s6_addr: addr.octets()
52 }
53}
54
55#[repr(i32)]
63#[non_exhaustive]
64#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
65pub enum AddressFamily {
66 Unix = libc::AF_UNIX,
68 Inet = libc::AF_INET,
70 Inet6 = libc::AF_INET6,
72 #[cfg(any(target_os = "android", target_os = "linux"))]
74 #[cfg_attr(docsrs, doc(cfg(all())))]
75 Netlink = libc::AF_NETLINK,
76 #[cfg(any(target_os = "android",
78 target_os = "linux",
79 target_os = "illumos",
80 target_os = "fuchsia",
81 target_os = "solaris"))]
82 #[cfg_attr(docsrs, doc(cfg(all())))]
83 Packet = libc::AF_PACKET,
84 #[cfg(any(target_os = "ios", target_os = "macos"))]
86 #[cfg_attr(docsrs, doc(cfg(all())))]
87 System = libc::AF_SYSTEM,
88 #[cfg(any(target_os = "android", target_os = "linux"))]
90 #[cfg_attr(docsrs, doc(cfg(all())))]
91 Ax25 = libc::AF_AX25,
92 Ipx = libc::AF_IPX,
94 AppleTalk = libc::AF_APPLETALK,
96 #[cfg(any(target_os = "android", target_os = "linux"))]
99 #[cfg_attr(docsrs, doc(cfg(all())))]
100 NetRom = libc::AF_NETROM,
101 #[cfg(any(target_os = "android", target_os = "linux"))]
106 #[cfg_attr(docsrs, doc(cfg(all())))]
107 Bridge = libc::AF_BRIDGE,
108 #[cfg(any(target_os = "android", target_os = "linux"))]
110 #[cfg_attr(docsrs, doc(cfg(all())))]
111 AtmPvc = libc::AF_ATMPVC,
112 #[cfg(any(target_os = "android", target_os = "linux"))]
114 #[cfg_attr(docsrs, doc(cfg(all())))]
115 X25 = libc::AF_X25,
116 #[cfg(any(target_os = "android", target_os = "linux"))]
120 #[cfg_attr(docsrs, doc(cfg(all())))]
121 Rose = libc::AF_ROSE,
122 Decnet = libc::AF_DECnet,
124 #[cfg(any(target_os = "android", target_os = "linux"))]
126 #[cfg_attr(docsrs, doc(cfg(all())))]
127 NetBeui = libc::AF_NETBEUI,
128 #[cfg(any(target_os = "android", target_os = "linux"))]
131 #[cfg_attr(docsrs, doc(cfg(all())))]
132 Security = libc::AF_SECURITY,
133 #[cfg(any(target_os = "android", target_os = "linux"))]
135 #[cfg_attr(docsrs, doc(cfg(all())))]
136 Key = libc::AF_KEY,
137 #[allow(missing_docs)] #[cfg(any(target_os = "android", target_os = "linux"))]
139 #[cfg_attr(docsrs, doc(cfg(all())))]
140 Ash = libc::AF_ASH,
141 #[cfg(any(target_os = "android", target_os = "linux"))]
143 #[cfg_attr(docsrs, doc(cfg(all())))]
144 Econet = libc::AF_ECONET,
145 #[cfg(any(target_os = "android", target_os = "linux"))]
147 #[cfg_attr(docsrs, doc(cfg(all())))]
148 AtmSvc = libc::AF_ATMSVC,
149 #[cfg(any(target_os = "android", target_os = "linux"))]
151 #[cfg_attr(docsrs, doc(cfg(all())))]
152 Rds = libc::AF_RDS,
153 Sna = libc::AF_SNA,
155 #[cfg(any(target_os = "android", target_os = "linux"))]
157 #[cfg_attr(docsrs, doc(cfg(all())))]
158 Irda = libc::AF_IRDA,
159 #[cfg(any(target_os = "android", target_os = "linux"))]
161 #[cfg_attr(docsrs, doc(cfg(all())))]
162 Pppox = libc::AF_PPPOX,
163 #[cfg(any(target_os = "android", target_os = "linux"))]
166 #[cfg_attr(docsrs, doc(cfg(all())))]
167 Wanpipe = libc::AF_WANPIPE,
168 #[cfg(any(target_os = "android", target_os = "linux"))]
170 #[cfg_attr(docsrs, doc(cfg(all())))]
171 Llc = libc::AF_LLC,
172 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
174 #[cfg_attr(docsrs, doc(cfg(all())))]
175 Ib = libc::AF_IB,
176 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
178 #[cfg_attr(docsrs, doc(cfg(all())))]
179 Mpls = libc::AF_MPLS,
180 #[cfg(any(target_os = "android", target_os = "linux"))]
182 #[cfg_attr(docsrs, doc(cfg(all())))]
183 Can = libc::AF_CAN,
184 #[cfg(any(target_os = "android", target_os = "linux"))]
186 #[cfg_attr(docsrs, doc(cfg(all())))]
187 Tipc = libc::AF_TIPC,
188 #[cfg(not(any(target_os = "illumos",
190 target_os = "ios",
191 target_os = "macos",
192 target_os = "solaris")))]
193 #[cfg_attr(docsrs, doc(cfg(all())))]
194 Bluetooth = libc::AF_BLUETOOTH,
195 #[cfg(any(target_os = "android", target_os = "linux"))]
198 #[cfg_attr(docsrs, doc(cfg(all())))]
199 Iucv = libc::AF_IUCV,
200 #[cfg(any(target_os = "android", target_os = "linux"))]
202 #[cfg_attr(docsrs, doc(cfg(all())))]
203 RxRpc = libc::AF_RXRPC,
204 #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
206 #[cfg_attr(docsrs, doc(cfg(all())))]
207 Isdn = libc::AF_ISDN,
208 #[cfg(any(target_os = "android", target_os = "linux"))]
210 #[cfg_attr(docsrs, doc(cfg(all())))]
211 Phonet = libc::AF_PHONET,
212 #[cfg(any(target_os = "android", target_os = "linux"))]
214 #[cfg_attr(docsrs, doc(cfg(all())))]
215 Ieee802154 = libc::AF_IEEE802154,
216 #[cfg(any(target_os = "android", target_os = "linux"))]
219 #[cfg_attr(docsrs, doc(cfg(all())))]
220 Caif = libc::AF_CAIF,
221 #[cfg(any(target_os = "android", target_os = "linux"))]
223 #[cfg_attr(docsrs, doc(cfg(all())))]
224 Alg = libc::AF_ALG,
225 #[cfg(target_os = "linux")]
227 #[cfg_attr(docsrs, doc(cfg(all())))]
228 Nfc = libc::AF_NFC,
229 #[cfg(any(target_os = "android", target_os = "linux"))]
231 #[cfg_attr(docsrs, doc(cfg(all())))]
232 Vsock = libc::AF_VSOCK,
233 #[cfg(any(target_os = "dragonfly",
235 target_os = "freebsd",
236 target_os = "ios",
237 target_os = "macos",
238 target_os = "netbsd",
239 target_os = "openbsd"))]
240 #[cfg_attr(docsrs, doc(cfg(all())))]
241 ImpLink = libc::AF_IMPLINK,
242 #[cfg(any(target_os = "dragonfly",
244 target_os = "freebsd",
245 target_os = "ios",
246 target_os = "macos",
247 target_os = "netbsd",
248 target_os = "openbsd"))]
249 #[cfg_attr(docsrs, doc(cfg(all())))]
250 Pup = libc::AF_PUP,
251 #[cfg(any(target_os = "dragonfly",
253 target_os = "freebsd",
254 target_os = "ios",
255 target_os = "macos",
256 target_os = "netbsd",
257 target_os = "openbsd"))]
258 #[cfg_attr(docsrs, doc(cfg(all())))]
259 Chaos = libc::AF_CHAOS,
260 #[cfg(any(target_os = "ios",
262 target_os = "macos",
263 target_os = "netbsd",
264 target_os = "openbsd"))]
265 #[cfg_attr(docsrs, doc(cfg(all())))]
266 Ns = libc::AF_NS,
267 #[allow(missing_docs)] #[cfg(any(target_os = "dragonfly",
269 target_os = "freebsd",
270 target_os = "ios",
271 target_os = "macos",
272 target_os = "netbsd",
273 target_os = "openbsd"))]
274 #[cfg_attr(docsrs, doc(cfg(all())))]
275 Iso = libc::AF_ISO,
276 #[cfg(any(target_os = "dragonfly",
278 target_os = "freebsd",
279 target_os = "ios",
280 target_os = "macos",
281 target_os = "netbsd",
282 target_os = "openbsd"))]
283 #[cfg_attr(docsrs, doc(cfg(all())))]
284 Datakit = libc::AF_DATAKIT,
285 #[cfg(any(target_os = "dragonfly",
287 target_os = "freebsd",
288 target_os = "ios",
289 target_os = "macos",
290 target_os = "netbsd",
291 target_os = "openbsd"))]
292 #[cfg_attr(docsrs, doc(cfg(all())))]
293 Ccitt = libc::AF_CCITT,
294 #[cfg(any(target_os = "dragonfly",
296 target_os = "freebsd",
297 target_os = "ios",
298 target_os = "macos",
299 target_os = "netbsd",
300 target_os = "openbsd"))]
301 #[cfg_attr(docsrs, doc(cfg(all())))]
302 Dli = libc::AF_DLI,
303 #[allow(missing_docs)] #[cfg(any(target_os = "dragonfly",
305 target_os = "freebsd",
306 target_os = "ios",
307 target_os = "macos",
308 target_os = "netbsd",
309 target_os = "openbsd"))]
310 #[cfg_attr(docsrs, doc(cfg(all())))]
311 Lat = libc::AF_LAT,
312 #[cfg(any(target_os = "dragonfly",
314 target_os = "freebsd",
315 target_os = "ios",
316 target_os = "macos",
317 target_os = "netbsd",
318 target_os = "openbsd"))]
319 #[cfg_attr(docsrs, doc(cfg(all())))]
320 Hylink = libc::AF_HYLINK,
321 #[cfg(any(target_os = "dragonfly",
323 target_os = "freebsd",
324 target_os = "ios",
325 target_os = "macos",
326 target_os = "illumos",
327 target_os = "netbsd",
328 target_os = "openbsd"))]
329 #[cfg_attr(docsrs, doc(cfg(all())))]
330 Link = libc::AF_LINK,
331 #[cfg(any(target_os = "dragonfly",
333 target_os = "freebsd",
334 target_os = "ios",
335 target_os = "macos",
336 target_os = "netbsd",
337 target_os = "openbsd"))]
338 #[cfg_attr(docsrs, doc(cfg(all())))]
339 Coip = libc::AF_COIP,
340 #[cfg(any(target_os = "dragonfly",
342 target_os = "freebsd",
343 target_os = "ios",
344 target_os = "macos",
345 target_os = "netbsd",
346 target_os = "openbsd"))]
347 #[cfg_attr(docsrs, doc(cfg(all())))]
348 Cnt = libc::AF_CNT,
349 #[cfg(any(target_os = "dragonfly",
351 target_os = "freebsd",
352 target_os = "ios",
353 target_os = "macos",
354 target_os = "netbsd",
355 target_os = "openbsd"))]
356 #[cfg_attr(docsrs, doc(cfg(all())))]
357 Natm = libc::AF_NATM,
358 #[cfg(any(target_os = "android", target_os = "linux"))]
360 #[cfg_attr(docsrs, doc(cfg(all())))]
361 Unspec = libc::AF_UNSPEC,
362}
363
364impl AddressFamily {
365 pub const fn from_i32(family: i32) -> Option<AddressFamily> {
371 match family {
372 libc::AF_UNIX => Some(AddressFamily::Unix),
373 libc::AF_INET => Some(AddressFamily::Inet),
374 libc::AF_INET6 => Some(AddressFamily::Inet6),
375 #[cfg(any(target_os = "android", target_os = "linux"))]
376 libc::AF_NETLINK => Some(AddressFamily::Netlink),
377 #[cfg(any(target_os = "macos", target_os = "macos"))]
378 libc::AF_SYSTEM => Some(AddressFamily::System),
379 #[cfg(any(target_os = "android", target_os = "linux"))]
380 libc::AF_PACKET => Some(AddressFamily::Packet),
381 #[cfg(any(target_os = "dragonfly",
382 target_os = "freebsd",
383 target_os = "ios",
384 target_os = "macos",
385 target_os = "netbsd",
386 target_os = "illumos",
387 target_os = "openbsd"))]
388 libc::AF_LINK => Some(AddressFamily::Link),
389 #[cfg(any(target_os = "android", target_os = "linux"))]
390 libc::AF_VSOCK => Some(AddressFamily::Vsock),
391 _ => None
392 }
393 }
394}
395
396feature! {
397#![feature = "net"]
398
399#[deprecated(
400 since = "0.24.0",
401 note = "use SockaddrIn, SockaddrIn6, or SockaddrStorage instead"
402)]
403#[allow(missing_docs)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
405pub enum InetAddr {
406 V4(libc::sockaddr_in),
407 V6(libc::sockaddr_in6),
408}
409
410#[allow(missing_docs)] #[allow(deprecated)]
412impl InetAddr {
413 #[allow(clippy::needless_update)] pub fn from_std(std: &net::SocketAddr) -> InetAddr {
415 match *std {
416 net::SocketAddr::V4(ref addr) => {
417 InetAddr::V4(libc::sockaddr_in {
418 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
419 target_os = "haiku", target_os = "hermit",
420 target_os = "ios", target_os = "macos",
421 target_os = "netbsd", target_os = "openbsd"))]
422 sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
423 sin_family: AddressFamily::Inet as sa_family_t,
424 sin_port: addr.port().to_be(), sin_addr: Ipv4Addr::from_std(addr.ip()).0,
426 .. unsafe { mem::zeroed() }
427 })
428 }
429 net::SocketAddr::V6(ref addr) => {
430 InetAddr::V6(libc::sockaddr_in6 {
431 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
432 target_os = "haiku", target_os = "hermit",
433 target_os = "ios", target_os = "macos",
434 target_os = "netbsd", target_os = "openbsd"))]
435 sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
436 sin6_family: AddressFamily::Inet6 as sa_family_t,
437 sin6_port: addr.port().to_be(), sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
439 sin6_flowinfo: addr.flowinfo(), sin6_scope_id: addr.scope_id(), .. unsafe { mem::zeroed() }
442 })
443 }
444 }
445 }
446
447 #[allow(clippy::needless_update)] pub fn new(ip: IpAddr, port: u16) -> InetAddr {
449 match ip {
450 IpAddr::V4(ref ip) => {
451 InetAddr::V4(libc::sockaddr_in {
452 sin_family: AddressFamily::Inet as sa_family_t,
453 sin_port: port.to_be(),
454 sin_addr: ip.0,
455 .. unsafe { mem::zeroed() }
456 })
457 }
458 IpAddr::V6(ref ip) => {
459 InetAddr::V6(libc::sockaddr_in6 {
460 sin6_family: AddressFamily::Inet6 as sa_family_t,
461 sin6_port: port.to_be(),
462 sin6_addr: ip.0,
463 .. unsafe { mem::zeroed() }
464 })
465 }
466 }
467 }
468 pub const fn ip(&self) -> IpAddr {
470 match *self {
471 InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
472 InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
473 }
474 }
475
476 pub const fn port(&self) -> u16 {
478 match *self {
479 InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
480 InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
481 }
482 }
483
484 pub fn to_std(&self) -> net::SocketAddr {
485 match *self {
486 InetAddr::V4(ref sa) => net::SocketAddr::V4(
487 net::SocketAddrV4::new(
488 Ipv4Addr(sa.sin_addr).to_std(),
489 self.port())),
490 InetAddr::V6(ref sa) => net::SocketAddr::V6(
491 net::SocketAddrV6::new(
492 Ipv6Addr(sa.sin6_addr).to_std(),
493 self.port(),
494 sa.sin6_flowinfo,
495 sa.sin6_scope_id)),
496 }
497 }
498
499 #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
500 pub fn to_str(&self) -> String {
501 format!("{}", self)
502 }
503}
504
505#[allow(deprecated)]
506impl fmt::Display for InetAddr {
507 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
508 match *self {
509 InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
510 InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
511 }
512 }
513}
514
515#[allow(missing_docs)] #[allow(deprecated)]
522#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
523#[deprecated(
524 since = "0.24.0",
525 note = "Use std::net::IpAddr instead"
526)]
527pub enum IpAddr {
528 V4(Ipv4Addr),
529 V6(Ipv6Addr),
530}
531
532#[allow(deprecated)]
533#[allow(missing_docs)] impl IpAddr {
535 pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
539 IpAddr::V4(Ipv4Addr::new(a, b, c, d))
540 }
541
542 #[allow(clippy::many_single_char_names)]
546 #[allow(clippy::too_many_arguments)]
547 pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
548 IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
549 }
550
551 pub fn from_std(std: &net::IpAddr) -> IpAddr {
552 match *std {
553 net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
554 net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
555 }
556 }
557
558 pub const fn to_std(&self) -> net::IpAddr {
559 match *self {
560 IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
561 IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
562 }
563 }
564}
565
566#[allow(deprecated)]
567impl fmt::Display for IpAddr {
568 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
569 match *self {
570 IpAddr::V4(ref v4) => v4.fmt(f),
571 IpAddr::V6(ref v6) => v6.fmt(f)
572 }
573 }
574}
575
576#[deprecated(
583 since = "0.24.0",
584 note = "Use std::net::Ipv4Addr instead"
585)]
586#[allow(missing_docs)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
588#[repr(transparent)]
589pub struct Ipv4Addr(pub libc::in_addr);
590
591#[allow(deprecated)]
592#[allow(missing_docs)] impl Ipv4Addr {
594 #[allow(clippy::identity_op)] pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
596 let ip = (((a as u32) << 24) |
597 ((b as u32) << 16) |
598 ((c as u32) << 8) |
599 ((d as u32) << 0)).to_be();
600
601 Ipv4Addr(libc::in_addr { s_addr: ip })
602 }
603
604 #[allow(clippy::trivially_copy_pass_by_ref)]
606 pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
607 let bits = std.octets();
608 Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
609 }
610
611 pub const fn any() -> Ipv4Addr {
612 Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
613 }
614
615 pub const fn octets(self) -> [u8; 4] {
616 let bits = u32::from_be(self.0.s_addr);
617 [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
618 }
619
620 pub const fn to_std(self) -> net::Ipv4Addr {
621 let bits = self.octets();
622 net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
623 }
624}
625
626#[allow(deprecated)]
627impl fmt::Display for Ipv4Addr {
628 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
629 let octets = self.octets();
630 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
631 }
632}
633
634#[deprecated(
641 since = "0.24.0",
642 note = "Use std::net::Ipv6Addr instead"
643)]
644#[allow(missing_docs)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
646#[repr(transparent)]
647pub struct Ipv6Addr(pub libc::in6_addr);
648
649macro_rules! to_u8_array {
654 ($($num:ident),*) => {
655 [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
656 }
657}
658
659macro_rules! to_u16_array {
660 ($slf:ident, $($first:expr, $second:expr),*) => {
661 [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
662 }
663}
664
665#[allow(deprecated)]
666#[allow(missing_docs)] impl Ipv6Addr {
668 #[allow(clippy::many_single_char_names)]
669 #[allow(clippy::too_many_arguments)]
670 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
671 Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
672 }
673
674 pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
675 let s = std.segments();
676 Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
677 }
678
679 pub const fn segments(&self) -> [u16; 8] {
681 to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
682 }
683
684 pub const fn to_std(&self) -> net::Ipv6Addr {
685 let s = self.segments();
686 net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
687 }
688}
689
690#[allow(deprecated)]
691impl fmt::Display for Ipv6Addr {
692 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
693 self.to_std().fmt(fmt)
694 }
695}
696}
697
698#[derive(Clone, Copy, Debug)]
700#[repr(C)]
701pub struct UnixAddr {
702 sun: libc::sockaddr_un,
704 #[cfg(any(target_os = "android",
708 target_os = "fuchsia",
709 target_os = "illumos",
710 target_os = "linux"
711 ))]
712 sun_len: u8
713}
714
715#[derive(PartialEq, Eq, Hash)]
722enum UnixAddrKind<'a> {
723 Pathname(&'a Path),
724 Unnamed,
725 #[cfg(any(target_os = "android", target_os = "linux"))]
726 Abstract(&'a [u8]),
727}
728impl<'a> UnixAddrKind<'a> {
729 unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self {
731 assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path));
732 let path_len = sun_len as usize - offset_of!(libc::sockaddr_un, sun_path);
733 if path_len == 0 {
734 return Self::Unnamed;
735 }
736 #[cfg(any(target_os = "android", target_os = "linux"))]
737 if sun.sun_path[0] == 0 {
738 let name =
739 slice::from_raw_parts(sun.sun_path.as_ptr().add(1) as *const u8, path_len - 1);
740 return Self::Abstract(name);
741 }
742 let pathname = slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len);
743 if pathname.last() == Some(&0) {
744 Self::Pathname(Path::new(OsStr::from_bytes(&pathname[0..pathname.len() - 1])))
752 } else {
753 Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
754 }
755 }
756}
757
758impl UnixAddr {
759 pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
761 path.with_nix_path(|cstr| {
762 unsafe {
763 let mut ret = libc::sockaddr_un {
764 sun_family: AddressFamily::Unix as sa_family_t,
765 .. mem::zeroed()
766 };
767
768 let bytes = cstr.to_bytes();
769
770 if bytes.len() >= ret.sun_path.len() {
771 return Err(Errno::ENAMETOOLONG);
772 }
773
774 let sun_len = (bytes.len() +
775 offset_of!(libc::sockaddr_un, sun_path)).try_into()
776 .unwrap();
777
778 #[cfg(any(target_os = "dragonfly",
779 target_os = "freebsd",
780 target_os = "ios",
781 target_os = "macos",
782 target_os = "netbsd",
783 target_os = "openbsd"))]
784 {
785 ret.sun_len = sun_len;
786 }
787 ptr::copy_nonoverlapping(bytes.as_ptr(),
788 ret.sun_path.as_mut_ptr() as *mut u8,
789 bytes.len());
790
791 Ok(UnixAddr::from_raw_parts(ret, sun_len))
792 }
793 })?
794 }
795
796 #[cfg(any(target_os = "android", target_os = "linux"))]
803 #[cfg_attr(docsrs, doc(cfg(all())))]
804 pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
805 unsafe {
806 let mut ret = libc::sockaddr_un {
807 sun_family: AddressFamily::Unix as sa_family_t,
808 .. mem::zeroed()
809 };
810
811 if path.len() >= ret.sun_path.len() {
812 return Err(Errno::ENAMETOOLONG);
813 }
814 let sun_len = (path.len() +
815 1 +
816 offset_of!(libc::sockaddr_un, sun_path)).try_into()
817 .unwrap();
818
819 ptr::copy_nonoverlapping(path.as_ptr(),
822 ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
823 path.len());
824
825 Ok(UnixAddr::from_raw_parts(ret, sun_len))
826 }
827 }
828
829 pub(crate) unsafe fn from_raw_parts(sun: libc::sockaddr_un, sun_len: u8) -> UnixAddr {
841 cfg_if!{
842 if #[cfg(any(target_os = "android",
843 target_os = "fuchsia",
844 target_os = "illumos",
845 target_os = "linux"
846 ))]
847 {
848 UnixAddr { sun, sun_len }
849 } else {
850 assert_eq!(sun_len, sun.sun_len);
851 UnixAddr {sun}
852 }
853 }
854 }
855
856 fn kind(&self) -> UnixAddrKind<'_> {
857 unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) }
859 }
860
861 pub fn path(&self) -> Option<&Path> {
863 match self.kind() {
864 UnixAddrKind::Pathname(path) => Some(path),
865 _ => None,
866 }
867 }
868
869 #[cfg(any(target_os = "android", target_os = "linux"))]
874 #[cfg_attr(docsrs, doc(cfg(all())))]
875 pub fn as_abstract(&self) -> Option<&[u8]> {
876 match self.kind() {
877 UnixAddrKind::Abstract(name) => Some(name),
878 _ => None,
879 }
880 }
881
882 #[inline]
884 pub fn path_len(&self) -> usize {
885 self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path)
886 }
887 #[inline]
889 pub fn as_ptr(&self) -> *const libc::sockaddr_un {
890 &self.sun
891 }
892 #[inline]
894 pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
895 &mut self.sun
896 }
897
898 fn sun_len(&self)-> u8 {
899 cfg_if!{
900 if #[cfg(any(target_os = "android",
901 target_os = "fuchsia",
902 target_os = "illumos",
903 target_os = "linux"
904 ))]
905 {
906 self.sun_len
907 } else {
908 self.sun.sun_len
909 }
910 }
911 }
912}
913
914impl private::SockaddrLikePriv for UnixAddr {}
915impl SockaddrLike for UnixAddr {
916 #[cfg(any(target_os = "android",
917 target_os = "fuchsia",
918 target_os = "illumos",
919 target_os = "linux"
920 ))]
921 fn len(&self) -> libc::socklen_t {
922 self.sun_len.into()
923 }
924
925 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
926 -> Option<Self> where Self: Sized
927 {
928 if let Some(l) = len {
929 if (l as usize) < offset_of!(libc::sockaddr_un, sun_path) ||
930 l > u8::MAX as libc::socklen_t
931 {
932 return None;
933 }
934 }
935 if (*addr).sa_family as i32 != libc::AF_UNIX {
936 return None;
937 }
938 let mut su: libc::sockaddr_un = mem::zeroed();
939 let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
940 cfg_if!{
941 if #[cfg(any(target_os = "android",
942 target_os = "fuchsia",
943 target_os = "illumos",
944 target_os = "linux"
945 ))] {
946 let su_len = len.unwrap_or(
947 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
948 );
949 } else {
950 let su_len = len.unwrap_or((*addr).sa_len as libc::socklen_t);
951 }
952 };
953 ptr::copy(addr as *const u8, sup, su_len as usize);
954 Some(Self::from_raw_parts(su, su_len as u8))
955 }
956
957 fn size() -> libc::socklen_t where Self: Sized {
958 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
959 }
960}
961
962impl AsRef<libc::sockaddr_un> for UnixAddr {
963 fn as_ref(&self) -> &libc::sockaddr_un {
964 &self.sun
965 }
966}
967
968#[cfg(any(target_os = "android", target_os = "linux"))]
969fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
970 use fmt::Write;
971 f.write_str("@\"")?;
972 for &b in abs {
973 use fmt::Display;
974 char::from(b).escape_default().fmt(f)?;
975 }
976 f.write_char('"')?;
977 Ok(())
978}
979
980impl fmt::Display for UnixAddr {
981 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
982 match self.kind() {
983 UnixAddrKind::Pathname(path) => path.display().fmt(f),
984 UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
985 #[cfg(any(target_os = "android", target_os = "linux"))]
986 UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
987 }
988 }
989}
990
991impl PartialEq for UnixAddr {
992 fn eq(&self, other: &UnixAddr) -> bool {
993 self.kind() == other.kind()
994 }
995}
996
997impl Eq for UnixAddr {}
998
999impl Hash for UnixAddr {
1000 fn hash<H: Hasher>(&self, s: &mut H) {
1001 self.kind().hash(s)
1002 }
1003}
1004
1005#[allow(clippy::len_without_is_empty)]
1010pub trait SockaddrLike: private::SockaddrLikePriv {
1011 fn as_ptr(&self) -> *const libc::sockaddr {
1013 self as *const Self as *const libc::sockaddr
1014 }
1015
1016 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
1038 -> Option<Self> where Self: Sized;
1039
1040 fn family(&self) -> Option<AddressFamily> {
1056 AddressFamily::from_i32(
1059 unsafe {
1060 (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
1061 }
1062 )
1063 }
1064
1065 cfg_if! {
1066 if #[cfg(any(target_os = "dragonfly",
1067 target_os = "freebsd",
1068 target_os = "ios",
1069 target_os = "macos",
1070 target_os = "netbsd",
1071 target_os = "openbsd"))] {
1072 fn len(&self) -> libc::socklen_t {
1078 unsafe {
1082 (*(self as *const Self as *const libc::sockaddr)).sa_len
1083 }.into()
1084 }
1085 } else {
1086 fn len(&self) -> libc::socklen_t {
1092 mem::size_of_val(self) as libc::socklen_t
1096 }
1097 }
1098 }
1099
1100 fn size() -> libc::socklen_t where Self: Sized {
1102 mem::size_of::<Self>() as libc::socklen_t
1103 }
1104}
1105
1106impl private::SockaddrLikePriv for () {
1107 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
1108 ptr::null_mut()
1109 }
1110}
1111
1112impl SockaddrLike for () {
1117 fn as_ptr(&self) -> *const libc::sockaddr {
1118 ptr::null()
1119 }
1120
1121 unsafe fn from_raw(_: *const libc::sockaddr, _: Option<libc::socklen_t>)
1122 -> Option<Self> where Self: Sized
1123 {
1124 None
1125 }
1126
1127 fn family(&self) -> Option<AddressFamily> {
1128 None
1129 }
1130
1131 fn len(&self) -> libc::socklen_t {
1132 0
1133 }
1134}
1135
1136#[cfg(feature = "net")]
1141#[repr(transparent)]
1142#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1143pub struct SockaddrIn(libc::sockaddr_in);
1144
1145#[cfg(feature = "net")]
1146impl SockaddrIn {
1147 pub const fn ip(&self) -> libc::in_addr_t {
1150 u32::from_be(self.0.sin_addr.s_addr)
1151 }
1152
1153 pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
1155 Self(libc::sockaddr_in {
1156 #[cfg(any(target_os = "dragonfly",
1157 target_os = "freebsd",
1158 target_os = "ios",
1159 target_os = "macos",
1160 target_os = "netbsd",
1161 target_os = "openbsd"))]
1162 sin_len: Self::size() as u8,
1163 sin_family: AddressFamily::Inet as sa_family_t,
1164 sin_port: u16::to_be(port),
1165 sin_addr: libc::in_addr {
1166 s_addr: u32::from_ne_bytes([a, b, c, d])
1167 },
1168 sin_zero: unsafe{mem::zeroed()}
1169 })
1170 }
1171
1172 pub const fn port(&self) -> u16 {
1175 u16::from_be(self.0.sin_port)
1176 }
1177}
1178
1179#[cfg(feature = "net")]
1180impl private::SockaddrLikePriv for SockaddrIn {}
1181#[cfg(feature = "net")]
1182impl SockaddrLike for SockaddrIn {
1183 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
1184 -> Option<Self> where Self: Sized
1185 {
1186 if let Some(l) = len {
1187 if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t {
1188 return None;
1189 }
1190 }
1191 if (*addr).sa_family as i32 != libc::AF_INET {
1192 return None;
1193 }
1194 Some(SockaddrIn(*(addr as *const libc::sockaddr_in)))
1195 }
1196}
1197
1198#[cfg(feature = "net")]
1199impl AsRef<libc::sockaddr_in> for SockaddrIn {
1200 fn as_ref(&self) -> &libc::sockaddr_in {
1201 &self.0
1202 }
1203}
1204
1205#[cfg(feature = "net")]
1206impl fmt::Display for SockaddrIn {
1207 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1208 let ne = u32::from_be(self.0.sin_addr.s_addr);
1209 let port = u16::from_be(self.0.sin_port);
1210 write!(f, "{}.{}.{}.{}:{}",
1211 ne >> 24,
1212 (ne >> 16) & 0xFF,
1213 (ne >> 8) & 0xFF,
1214 ne & 0xFF,
1215 port)
1216 }
1217}
1218
1219#[cfg(feature = "net")]
1220impl From<net::SocketAddrV4> for SockaddrIn {
1221 fn from(addr: net::SocketAddrV4) -> Self {
1222 Self(libc::sockaddr_in{
1223 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
1224 target_os = "haiku", target_os = "hermit",
1225 target_os = "ios", target_os = "macos",
1226 target_os = "netbsd", target_os = "openbsd"))]
1227 sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
1228 sin_family: AddressFamily::Inet as sa_family_t,
1229 sin_port: addr.port().to_be(), sin_addr: ipv4addr_to_libc(*addr.ip()),
1231 .. unsafe { mem::zeroed() }
1232 })
1233 }
1234}
1235
1236#[cfg(feature = "net")]
1237impl std::str::FromStr for SockaddrIn {
1238 type Err = net::AddrParseError;
1239
1240 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
1241 net::SocketAddrV4::from_str(s).map(SockaddrIn::from)
1242 }
1243}
1244
1245#[cfg(feature = "net")]
1247#[repr(transparent)]
1248#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1249pub struct SockaddrIn6(libc::sockaddr_in6);
1250
1251#[cfg(feature = "net")]
1252impl SockaddrIn6 {
1253 pub const fn flowinfo(&self) -> u32 {
1255 self.0.sin6_flowinfo
1256 }
1257
1258 pub fn ip(&self) -> net::Ipv6Addr {
1260 net::Ipv6Addr::from(self.0.sin6_addr.s6_addr)
1261 }
1262
1263 pub const fn port(&self) -> u16 {
1266 u16::from_be(self.0.sin6_port)
1267 }
1268
1269 pub const fn scope_id(&self) -> u32 {
1271 self.0.sin6_scope_id
1272 }
1273}
1274
1275#[cfg(feature = "net")]
1276impl private::SockaddrLikePriv for SockaddrIn6 {}
1277#[cfg(feature = "net")]
1278impl SockaddrLike for SockaddrIn6 {
1279 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
1280 -> Option<Self> where Self: Sized
1281 {
1282 if let Some(l) = len {
1283 if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t {
1284 return None;
1285 }
1286 }
1287 if (*addr).sa_family as i32 != libc::AF_INET6 {
1288 return None;
1289 }
1290 Some(SockaddrIn6(*(addr as *const libc::sockaddr_in6)))
1291 }
1292}
1293
1294#[cfg(feature = "net")]
1295impl AsRef<libc::sockaddr_in6> for SockaddrIn6 {
1296 fn as_ref(&self) -> &libc::sockaddr_in6 {
1297 &self.0
1298 }
1299}
1300
1301#[cfg(feature = "net")]
1302impl fmt::Display for SockaddrIn6 {
1303 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1304 let std = net::SocketAddrV6::new(self.ip(), self.port(),
1307 self.flowinfo(), self.scope_id());
1308 std.fmt(f)
1309 }
1310}
1311
1312#[cfg(feature = "net")]
1313impl From<net::SocketAddrV6> for SockaddrIn6 {
1314 fn from(addr: net::SocketAddrV6) -> Self {
1315 #[allow(clippy::needless_update)] Self(libc::sockaddr_in6{
1317 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
1318 target_os = "haiku", target_os = "hermit",
1319 target_os = "ios", target_os = "macos",
1320 target_os = "netbsd", target_os = "openbsd"))]
1321 sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
1322 sin6_family: AddressFamily::Inet6 as sa_family_t,
1323 sin6_port: addr.port().to_be(), sin6_addr: ipv6addr_to_libc(addr.ip()),
1325 sin6_flowinfo: addr.flowinfo(), sin6_scope_id: addr.scope_id(), .. unsafe { mem::zeroed() }
1328 })
1329 }
1330}
1331
1332#[cfg(feature = "net")]
1333impl std::str::FromStr for SockaddrIn6 {
1334 type Err = net::AddrParseError;
1335
1336 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
1337 net::SocketAddrV6::from_str(s).map(SockaddrIn6::from)
1338 }
1339}
1340
1341
1342#[derive(Clone, Copy, Eq)]
1361#[repr(C)]
1362pub union SockaddrStorage {
1363 #[cfg(any(target_os = "android", target_os = "linux"))]
1364 #[cfg_attr(docsrs, doc(cfg(all())))]
1365 alg: AlgAddr,
1366 #[cfg(feature = "net")]
1367 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1368 dl: LinkAddr,
1369 #[cfg(any(target_os = "android", target_os = "linux"))]
1370 nl: NetlinkAddr,
1371 #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
1372 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1373 sctl: SysControlAddr,
1374 #[cfg(feature = "net")]
1375 sin: SockaddrIn,
1376 #[cfg(feature = "net")]
1377 sin6: SockaddrIn6,
1378 ss: libc::sockaddr_storage,
1379 su: UnixAddr,
1380 #[cfg(any(target_os = "android", target_os = "linux"))]
1381 #[cfg_attr(docsrs, doc(cfg(all())))]
1382 vsock: VsockAddr
1383}
1384impl private::SockaddrLikePriv for SockaddrStorage {}
1385impl SockaddrLike for SockaddrStorage {
1386 unsafe fn from_raw(addr: *const libc::sockaddr, l: Option<libc::socklen_t>)
1387 -> Option<Self> where Self: Sized
1388 {
1389 if addr.is_null() {
1390 return None;
1391 }
1392 if let Some(len) = l {
1393 let ulen = len as usize;
1394 if ulen < offset_of!(libc::sockaddr, sa_data) ||
1395 ulen > mem::size_of::<libc::sockaddr_storage>() {
1396 None
1397 } else{
1398 let mut ss: libc::sockaddr_storage = mem::zeroed();
1399 let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
1400 ptr::copy(addr as *const u8, ssp, len as usize);
1401 #[cfg(any(
1402 target_os = "android",
1403 target_os = "fuchsia",
1404 target_os = "illumos",
1405 target_os = "linux"
1406 ))]
1407 if i32::from(ss.ss_family) == libc::AF_UNIX {
1408 (*(&mut ss as *mut libc::sockaddr_storage as *mut UnixAddr)).sun_len = len as u8;
1411 }
1412 Some(Self { ss })
1413 }
1414 } else {
1415 match (*addr).sa_family as i32 {
1419 #[cfg(any(target_os = "android", target_os = "linux"))]
1420 libc::AF_ALG => AlgAddr::from_raw(addr, l)
1421 .map(|alg| Self { alg}),
1422 #[cfg(feature = "net")]
1423 libc::AF_INET => SockaddrIn::from_raw(addr, l)
1424 .map(|sin| Self{ sin}),
1425 #[cfg(feature = "net")]
1426 libc::AF_INET6 => SockaddrIn6::from_raw(addr, l)
1427 .map(|sin6| Self{ sin6}),
1428 #[cfg(any(target_os = "dragonfly",
1429 target_os = "freebsd",
1430 target_os = "ios",
1431 target_os = "macos",
1432 target_os = "illumos",
1433 target_os = "netbsd",
1434 target_os = "openbsd"))]
1435 #[cfg(feature = "net")]
1436 libc::AF_LINK => LinkAddr::from_raw(addr, l)
1437 .map(|dl| Self{ dl}),
1438 #[cfg(any(target_os = "android", target_os = "linux"))]
1439 libc::AF_NETLINK => NetlinkAddr::from_raw(addr, l)
1440 .map(|nl| Self{ nl }),
1441 #[cfg(any(target_os = "android",
1442 target_os = "fuchsia",
1443 target_os = "linux"
1444 ))]
1445 #[cfg(feature = "net")]
1446 libc::AF_PACKET => LinkAddr::from_raw(addr, l)
1447 .map(|dl| Self{ dl}),
1448 #[cfg(all(feature = "ioctl",
1449 any(target_os = "ios", target_os = "macos")))]
1450 libc::AF_SYSTEM => SysControlAddr::from_raw(addr, l)
1451 .map(|sctl| Self {sctl}),
1452 #[cfg(any(target_os = "android", target_os = "linux"))]
1453 libc::AF_VSOCK => VsockAddr::from_raw(addr, l)
1454 .map(|vsock| Self{vsock}),
1455 _ => None
1456 }
1457 }
1458 }
1459
1460 #[cfg(any(
1461 target_os = "android",
1462 target_os = "fuchsia",
1463 target_os = "illumos",
1464 target_os = "linux"
1465 ))]
1466 fn len(&self) -> libc::socklen_t {
1467 match self.as_unix_addr() {
1468 Some(ua) => ua.len(),
1470 None => mem::size_of_val(self) as libc::socklen_t
1472 }
1473 }
1474}
1475
1476macro_rules! accessors {
1477 (
1478 $fname:ident,
1479 $fname_mut:ident,
1480 $sockty:ty,
1481 $family:expr,
1482 $libc_ty:ty,
1483 $field:ident) =>
1484 {
1485 pub fn $fname(&self) -> Option<&$sockty> {
1487 if self.family() == Some($family) &&
1488 self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
1489 {
1490 Some(unsafe{&self.$field})
1492 } else {
1493 None
1494 }
1495 }
1496
1497 pub fn $fname_mut(&mut self) -> Option<&mut $sockty> {
1499 if self.family() == Some($family) &&
1500 self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
1501 {
1502 Some(unsafe{&mut self.$field})
1504 } else {
1505 None
1506 }
1507 }
1508 }
1509}
1510
1511impl SockaddrStorage {
1512 pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
1514 cfg_if! {
1515 if #[cfg(any(target_os = "android",
1516 target_os = "fuchsia",
1517 target_os = "illumos",
1518 target_os = "linux"
1519 ))]
1520 {
1521 let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
1522 let len = unsafe {
1525 (*(p as *const UnixAddr )).sun_len as usize
1526 };
1527 } else {
1528 let len = self.len() as usize;
1529 }
1530 }
1531 if self.family() != Some(AddressFamily::Unix) ||
1533 len < offset_of!(libc::sockaddr_un, sun_path) ||
1534 len > mem::size_of::<libc::sockaddr_un>() {
1535 None
1536 } else {
1537 Some(unsafe{&self.su})
1538 }
1539 }
1540
1541 pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
1543 cfg_if! {
1544 if #[cfg(any(target_os = "android",
1545 target_os = "fuchsia",
1546 target_os = "illumos",
1547 target_os = "linux"
1548 ))]
1549 {
1550 let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
1551 let len = unsafe {
1554 (*(p as *const UnixAddr )).sun_len as usize
1555 };
1556 } else {
1557 let len = self.len() as usize;
1558 }
1559 }
1560 if self.family() != Some(AddressFamily::Unix) ||
1562 len < offset_of!(libc::sockaddr_un, sun_path) ||
1563 len > mem::size_of::<libc::sockaddr_un>() {
1564 None
1565 } else {
1566 Some(unsafe{&mut self.su})
1567 }
1568 }
1569
1570 #[cfg(any(target_os = "android", target_os = "linux"))]
1571 accessors!{as_alg_addr, as_alg_addr_mut, AlgAddr,
1572 AddressFamily::Alg, libc::sockaddr_alg, alg}
1573
1574 #[cfg(any(target_os = "android",
1575 target_os = "fuchsia",
1576 target_os = "linux"))]
1577 #[cfg(feature = "net")]
1578 accessors!{
1579 as_link_addr, as_link_addr_mut, LinkAddr,
1580 AddressFamily::Packet, libc::sockaddr_ll, dl}
1581
1582 #[cfg(any(target_os = "dragonfly",
1583 target_os = "freebsd",
1584 target_os = "ios",
1585 target_os = "macos",
1586 target_os = "illumos",
1587 target_os = "netbsd",
1588 target_os = "openbsd"))]
1589 #[cfg(feature = "net")]
1590 accessors!{
1591 as_link_addr, as_link_addr_mut, LinkAddr,
1592 AddressFamily::Link, libc::sockaddr_dl, dl}
1593
1594 #[cfg(feature = "net")]
1595 accessors!{
1596 as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
1597 AddressFamily::Inet, libc::sockaddr_in, sin}
1598
1599 #[cfg(feature = "net")]
1600 accessors!{
1601 as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
1602 AddressFamily::Inet6, libc::sockaddr_in6, sin6}
1603
1604 #[cfg(any(target_os = "android", target_os = "linux"))]
1605 accessors!{as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
1606 AddressFamily::Netlink, libc::sockaddr_nl, nl}
1607
1608 #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
1609 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1610 accessors!{as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
1611 AddressFamily::System, libc::sockaddr_ctl, sctl}
1612
1613 #[cfg(any(target_os = "android", target_os = "linux"))]
1614 #[cfg_attr(docsrs, doc(cfg(all())))]
1615 accessors!{as_vsock_addr, as_vsock_addr_mut, VsockAddr,
1616 AddressFamily::Vsock, libc::sockaddr_vm, vsock}
1617}
1618
1619impl fmt::Debug for SockaddrStorage {
1620 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1621 f.debug_struct("SockaddrStorage")
1622 .field("ss", unsafe{&self.ss})
1625 .finish()
1626 }
1627}
1628
1629impl fmt::Display for SockaddrStorage {
1630 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1631 unsafe {
1632 match self.ss.ss_family as i32 {
1633 #[cfg(any(target_os = "android", target_os = "linux"))]
1634 libc::AF_ALG => self.alg.fmt(f),
1635 #[cfg(feature = "net")]
1636 libc::AF_INET => self.sin.fmt(f),
1637 #[cfg(feature = "net")]
1638 libc::AF_INET6 => self.sin6.fmt(f),
1639 #[cfg(any(target_os = "dragonfly",
1640 target_os = "freebsd",
1641 target_os = "ios",
1642 target_os = "macos",
1643 target_os = "illumos",
1644 target_os = "netbsd",
1645 target_os = "openbsd"))]
1646 #[cfg(feature = "net")]
1647 libc::AF_LINK => self.dl.fmt(f),
1648 #[cfg(any(target_os = "android", target_os = "linux"))]
1649 libc::AF_NETLINK => self.nl.fmt(f),
1650 #[cfg(any(target_os = "android",
1651 target_os = "linux",
1652 target_os = "fuchsia"
1653 ))]
1654 #[cfg(feature = "net")]
1655 libc::AF_PACKET => self.dl.fmt(f),
1656 #[cfg(any(target_os = "ios", target_os = "macos"))]
1657 #[cfg(feature = "ioctl")]
1658 libc::AF_SYSTEM => self.sctl.fmt(f),
1659 libc::AF_UNIX => self.su.fmt(f),
1660 #[cfg(any(target_os = "android", target_os = "linux"))]
1661 libc::AF_VSOCK => self.vsock.fmt(f),
1662 _ => "<Address family unspecified>".fmt(f)
1663 }
1664 }
1665 }
1666}
1667
1668#[cfg(feature = "net")]
1669impl From<net::SocketAddrV4> for SockaddrStorage {
1670 fn from(s: net::SocketAddrV4) -> Self {
1671 unsafe {
1672 let mut ss: Self = mem::zeroed();
1673 ss.sin = SockaddrIn::from(s);
1674 ss
1675 }
1676 }
1677}
1678
1679#[cfg(feature = "net")]
1680impl From<net::SocketAddrV6> for SockaddrStorage {
1681 fn from(s: net::SocketAddrV6) -> Self {
1682 unsafe {
1683 let mut ss: Self = mem::zeroed();
1684 ss.sin6 = SockaddrIn6::from(s);
1685 ss
1686 }
1687 }
1688}
1689
1690#[cfg(feature = "net")]
1691impl From<net::SocketAddr> for SockaddrStorage {
1692 fn from(s: net::SocketAddr) -> Self {
1693 match s {
1694 net::SocketAddr::V4(sa4) => Self::from(sa4),
1695 net::SocketAddr::V6(sa6) => Self::from(sa6),
1696 }
1697 }
1698}
1699
1700impl Hash for SockaddrStorage {
1701 fn hash<H: Hasher>(&self, s: &mut H) {
1702 unsafe {
1703 match self.ss.ss_family as i32 {
1704 #[cfg(any(target_os = "android", target_os = "linux"))]
1705 libc::AF_ALG => self.alg.hash(s),
1706 #[cfg(feature = "net")]
1707 libc::AF_INET => self.sin.hash(s),
1708 #[cfg(feature = "net")]
1709 libc::AF_INET6 => self.sin6.hash(s),
1710 #[cfg(any(target_os = "dragonfly",
1711 target_os = "freebsd",
1712 target_os = "ios",
1713 target_os = "macos",
1714 target_os = "illumos",
1715 target_os = "netbsd",
1716 target_os = "openbsd"))]
1717 #[cfg(feature = "net")]
1718 libc::AF_LINK => self.dl.hash(s),
1719 #[cfg(any(target_os = "android", target_os = "linux"))]
1720 libc::AF_NETLINK => self.nl.hash(s),
1721 #[cfg(any(target_os = "android",
1722 target_os = "linux",
1723 target_os = "fuchsia"
1724 ))]
1725 #[cfg(feature = "net")]
1726 libc::AF_PACKET => self.dl.hash(s),
1727 #[cfg(any(target_os = "ios", target_os = "macos"))]
1728 #[cfg(feature = "ioctl")]
1729 libc::AF_SYSTEM => self.sctl.hash(s),
1730 libc::AF_UNIX => self.su.hash(s),
1731 #[cfg(any(target_os = "android", target_os = "linux"))]
1732 libc::AF_VSOCK => self.vsock.hash(s),
1733 _ => self.ss.hash(s)
1734 }
1735 }
1736 }
1737}
1738
1739impl PartialEq for SockaddrStorage {
1740 fn eq(&self, other: &Self) -> bool {
1741 unsafe {
1742 match (self.ss.ss_family as i32, other.ss.ss_family as i32) {
1743 #[cfg(any(target_os = "android", target_os = "linux"))]
1744 (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg,
1745 #[cfg(feature = "net")]
1746 (libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
1747 #[cfg(feature = "net")]
1748 (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
1749 #[cfg(any(target_os = "dragonfly",
1750 target_os = "freebsd",
1751 target_os = "ios",
1752 target_os = "macos",
1753 target_os = "illumos",
1754 target_os = "netbsd",
1755 target_os = "openbsd"))]
1756 #[cfg(feature = "net")]
1757 (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
1758 #[cfg(any(target_os = "android", target_os = "linux"))]
1759 (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
1760 #[cfg(any(target_os = "android",
1761 target_os = "fuchsia",
1762 target_os = "linux"
1763 ))]
1764 #[cfg(feature = "net")]
1765 (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
1766 #[cfg(any(target_os = "ios", target_os = "macos"))]
1767 #[cfg(feature = "ioctl")]
1768 (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
1769 (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
1770 #[cfg(any(target_os = "android", target_os = "linux"))]
1771 (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
1772 _ => false,
1773 }
1774 }
1775 }
1776}
1777
1778mod private {
1779 pub trait SockaddrLikePriv {
1780 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
1789 self as *mut Self as *mut libc::sockaddr
1790 }
1791 }
1792}
1793
1794#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1796#[deprecated(
1797 since = "0.24.0",
1798 note = "use SockaddrLike or SockaddrStorage instead"
1799)]
1800#[allow(missing_docs)] #[allow(deprecated)]
1802#[non_exhaustive]
1803pub enum SockAddr {
1804 #[cfg(feature = "net")]
1805 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1806 Inet(InetAddr),
1807 Unix(UnixAddr),
1808 #[cfg(any(target_os = "android", target_os = "linux"))]
1809 #[cfg_attr(docsrs, doc(cfg(all())))]
1810 Netlink(NetlinkAddr),
1811 #[cfg(any(target_os = "android", target_os = "linux"))]
1812 #[cfg_attr(docsrs, doc(cfg(all())))]
1813 Alg(AlgAddr),
1814 #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
1815 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1816 SysControl(SysControlAddr),
1817 #[cfg(any(target_os = "android",
1819 target_os = "dragonfly",
1820 target_os = "freebsd",
1821 target_os = "ios",
1822 target_os = "linux",
1823 target_os = "macos",
1824 target_os = "illumos",
1825 target_os = "netbsd",
1826 target_os = "openbsd"))]
1827 #[cfg(feature = "net")]
1828 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1829 Link(LinkAddr),
1830 #[cfg(any(target_os = "android", target_os = "linux"))]
1831 #[cfg_attr(docsrs, doc(cfg(all())))]
1832 Vsock(VsockAddr),
1833}
1834
1835#[allow(missing_docs)] #[allow(deprecated)]
1837impl SockAddr {
1838 feature! {
1839 #![feature = "net"]
1840 pub fn new_inet(addr: InetAddr) -> SockAddr {
1841 SockAddr::Inet(addr)
1842 }
1843 }
1844
1845 pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
1846 Ok(SockAddr::Unix(UnixAddr::new(path)?))
1847 }
1848
1849 #[cfg(any(target_os = "android", target_os = "linux"))]
1850 #[cfg_attr(docsrs, doc(cfg(all())))]
1851 pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
1852 SockAddr::Netlink(NetlinkAddr::new(pid, groups))
1853 }
1854
1855 #[cfg(any(target_os = "android", target_os = "linux"))]
1856 #[cfg_attr(docsrs, doc(cfg(all())))]
1857 pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
1858 SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
1859 }
1860
1861 feature! {
1862 #![feature = "ioctl"]
1863 #[cfg(any(target_os = "ios", target_os = "macos"))]
1864 pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
1865 SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl)
1866 }
1867 }
1868
1869 #[cfg(any(target_os = "android", target_os = "linux"))]
1870 #[cfg_attr(docsrs, doc(cfg(all())))]
1871 pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
1872 SockAddr::Vsock(VsockAddr::new(cid, port))
1873 }
1874
1875 pub fn family(&self) -> AddressFamily {
1876 match *self {
1877 #[cfg(feature = "net")]
1878 SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
1879 #[cfg(feature = "net")]
1880 SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
1881 SockAddr::Unix(..) => AddressFamily::Unix,
1882 #[cfg(any(target_os = "android", target_os = "linux"))]
1883 SockAddr::Netlink(..) => AddressFamily::Netlink,
1884 #[cfg(any(target_os = "android", target_os = "linux"))]
1885 SockAddr::Alg(..) => AddressFamily::Alg,
1886 #[cfg(all(feature = "ioctl",
1887 any(target_os = "ios", target_os = "macos")))]
1888 SockAddr::SysControl(..) => AddressFamily::System,
1889 #[cfg(any(target_os = "android", target_os = "linux"))]
1890 #[cfg(feature = "net")]
1891 SockAddr::Link(..) => AddressFamily::Packet,
1892 #[cfg(any(target_os = "dragonfly",
1893 target_os = "freebsd",
1894 target_os = "ios",
1895 target_os = "macos",
1896 target_os = "netbsd",
1897 target_os = "illumos",
1898 target_os = "openbsd"))]
1899 #[cfg(feature = "net")]
1900 SockAddr::Link(..) => AddressFamily::Link,
1901 #[cfg(any(target_os = "android", target_os = "linux"))]
1902 SockAddr::Vsock(..) => AddressFamily::Vsock,
1903 }
1904 }
1905
1906 #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
1907 pub fn to_str(&self) -> String {
1908 format!("{}", self)
1909 }
1910
1911 #[cfg(not(target_os = "fuchsia"))]
1921 #[cfg(feature = "net")]
1922 pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
1923 if addr.is_null() {
1924 None
1925 } else {
1926 match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
1927 Some(AddressFamily::Unix) => None,
1928 #[cfg(feature = "net")]
1929 Some(AddressFamily::Inet) => Some(SockAddr::Inet(
1930 InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
1931 #[cfg(feature = "net")]
1932 Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
1933 InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
1934 #[cfg(any(target_os = "android", target_os = "linux"))]
1935 Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
1936 NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
1937 #[cfg(all(feature = "ioctl",
1938 any(target_os = "ios", target_os = "macos")))]
1939 Some(AddressFamily::System) => Some(SockAddr::SysControl(
1940 SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
1941 #[cfg(any(target_os = "android", target_os = "linux"))]
1942 #[cfg(feature = "net")]
1943 Some(AddressFamily::Packet) => Some(SockAddr::Link(
1944 LinkAddr(*(addr as *const libc::sockaddr_ll)))),
1945 #[cfg(any(target_os = "dragonfly",
1946 target_os = "freebsd",
1947 target_os = "ios",
1948 target_os = "macos",
1949 target_os = "netbsd",
1950 target_os = "illumos",
1951 target_os = "openbsd"))]
1952 #[cfg(feature = "net")]
1953 Some(AddressFamily::Link) => {
1954 let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
1955 if ether_addr.is_empty() {
1956 None
1957 } else {
1958 Some(SockAddr::Link(ether_addr))
1959 }
1960 },
1961 #[cfg(any(target_os = "android", target_os = "linux"))]
1962 Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
1963 VsockAddr(*(addr as *const libc::sockaddr_vm)))),
1964 Some(_) | None => None,
1967 }
1968 }
1969 }
1970
1971 pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
1979 match *self {
1980 #[cfg(feature = "net")]
1981 SockAddr::Inet(InetAddr::V4(ref addr)) => (
1982 unsafe {
1984 &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
1985 },
1986 mem::size_of_val(addr) as libc::socklen_t
1987 ),
1988 #[cfg(feature = "net")]
1989 SockAddr::Inet(InetAddr::V6(ref addr)) => (
1990 unsafe {
1992 &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
1993 },
1994 mem::size_of_val(addr) as libc::socklen_t
1995 ),
1996 SockAddr::Unix(ref unix_addr) => (
1997 unsafe {
1999 &*(&unix_addr.sun as *const libc::sockaddr_un as *const libc::sockaddr)
2000 },
2001 unix_addr.sun_len() as libc::socklen_t
2002 ),
2003 #[cfg(any(target_os = "android", target_os = "linux"))]
2004 SockAddr::Netlink(NetlinkAddr(ref sa)) => (
2005 unsafe {
2007 &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
2008 },
2009 mem::size_of_val(sa) as libc::socklen_t
2010 ),
2011 #[cfg(any(target_os = "android", target_os = "linux"))]
2012 SockAddr::Alg(AlgAddr(ref sa)) => (
2013 unsafe {
2015 &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
2016 },
2017 mem::size_of_val(sa) as libc::socklen_t
2018 ),
2019 #[cfg(all(feature = "ioctl",
2020 any(target_os = "ios", target_os = "macos")))]
2021 SockAddr::SysControl(SysControlAddr(ref sa)) => (
2022 unsafe {
2024 &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
2025 },
2026 mem::size_of_val(sa) as libc::socklen_t
2027
2028 ),
2029 #[cfg(any(target_os = "android", target_os = "linux"))]
2030 #[cfg(feature = "net")]
2031 SockAddr::Link(LinkAddr(ref addr)) => (
2032 unsafe {
2034 &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
2035 },
2036 mem::size_of_val(addr) as libc::socklen_t
2037 ),
2038 #[cfg(any(target_os = "dragonfly",
2039 target_os = "freebsd",
2040 target_os = "ios",
2041 target_os = "macos",
2042 target_os = "illumos",
2043 target_os = "netbsd",
2044 target_os = "openbsd"))]
2045 #[cfg(feature = "net")]
2046 SockAddr::Link(LinkAddr(ref addr)) => (
2047 unsafe {
2049 &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
2050 },
2051 mem::size_of_val(addr) as libc::socklen_t
2052 ),
2053 #[cfg(any(target_os = "android", target_os = "linux"))]
2054 SockAddr::Vsock(VsockAddr(ref sa)) => (
2055 unsafe {
2057 &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
2058 },
2059 mem::size_of_val(sa) as libc::socklen_t
2060 ),
2061 }
2062 }
2063}
2064
2065#[allow(deprecated)]
2066impl fmt::Display for SockAddr {
2067 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2068 match *self {
2069 #[cfg(feature = "net")]
2070 SockAddr::Inet(ref inet) => inet.fmt(f),
2071 SockAddr::Unix(ref unix) => unix.fmt(f),
2072 #[cfg(any(target_os = "android", target_os = "linux"))]
2073 SockAddr::Netlink(ref nl) => nl.fmt(f),
2074 #[cfg(any(target_os = "android", target_os = "linux"))]
2075 SockAddr::Alg(ref nl) => nl.fmt(f),
2076 #[cfg(all(feature = "ioctl",
2077 any(target_os = "ios", target_os = "macos")))]
2078 SockAddr::SysControl(ref sc) => sc.fmt(f),
2079 #[cfg(any(target_os = "android",
2080 target_os = "dragonfly",
2081 target_os = "freebsd",
2082 target_os = "ios",
2083 target_os = "linux",
2084 target_os = "macos",
2085 target_os = "netbsd",
2086 target_os = "illumos",
2087 target_os = "openbsd"))]
2088 #[cfg(feature = "net")]
2089 SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
2090 #[cfg(any(target_os = "android", target_os = "linux"))]
2091 SockAddr::Vsock(ref svm) => svm.fmt(f),
2092 }
2093 }
2094}
2095
2096#[cfg(not(target_os = "fuchsia"))]
2097#[cfg(feature = "net")]
2098#[allow(deprecated)]
2099impl private::SockaddrLikePriv for SockAddr {}
2100#[cfg(not(target_os = "fuchsia"))]
2101#[cfg(feature = "net")]
2102#[allow(deprecated)]
2103impl SockaddrLike for SockAddr {
2104 unsafe fn from_raw(addr: *const libc::sockaddr, _len: Option<libc::socklen_t>)
2105 -> Option<Self>
2106 {
2107 Self::from_libc_sockaddr(addr)
2108 }
2109}
2110
2111#[cfg(any(target_os = "android", target_os = "linux"))]
2112#[cfg_attr(docsrs, doc(cfg(all())))]
2113pub mod netlink {
2114 use crate::sys::socket::addr::AddressFamily;
2115 use libc::{sa_family_t, sockaddr_nl};
2116 use std::{fmt, mem};
2117 use super::*;
2118
2119 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
2125 #[repr(transparent)]
2126 pub struct NetlinkAddr(pub(in super::super) sockaddr_nl);
2127
2128 impl NetlinkAddr {
2129 pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
2132 let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
2133 addr.nl_family = AddressFamily::Netlink as sa_family_t;
2134 addr.nl_pid = pid;
2135 addr.nl_groups = groups;
2136
2137 NetlinkAddr(addr)
2138 }
2139
2140 pub const fn pid(&self) -> u32 {
2142 self.0.nl_pid
2143 }
2144
2145 pub const fn groups(&self) -> u32 {
2147 self.0.nl_groups
2148 }
2149 }
2150
2151 impl private::SockaddrLikePriv for NetlinkAddr {}
2152 impl SockaddrLike for NetlinkAddr {
2153 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
2154 -> Option<Self> where Self: Sized
2155 {
2156 if let Some(l) = len {
2157 if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t {
2158 return None;
2159 }
2160 }
2161 if (*addr).sa_family as i32 != libc::AF_NETLINK {
2162 return None;
2163 }
2164 Some(NetlinkAddr(*(addr as *const libc::sockaddr_nl)))
2165 }
2166 }
2167
2168 impl AsRef<libc::sockaddr_nl> for NetlinkAddr {
2169 fn as_ref(&self) -> &libc::sockaddr_nl {
2170 &self.0
2171 }
2172 }
2173
2174 impl fmt::Display for NetlinkAddr {
2175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2176 write!(f, "pid: {} groups: {}", self.pid(), self.groups())
2177 }
2178 }
2179}
2180
2181#[cfg(any(target_os = "android", target_os = "linux"))]
2182#[cfg_attr(docsrs, doc(cfg(all())))]
2183pub mod alg {
2184 use libc::{AF_ALG, sockaddr_alg, c_char};
2185 use std::{fmt, mem, str};
2186 use std::hash::{Hash, Hasher};
2187 use std::ffi::CStr;
2188 use super::*;
2189
2190 #[derive(Copy, Clone)]
2192 #[repr(transparent)]
2193 pub struct AlgAddr(pub(in super::super) sockaddr_alg);
2194
2195 impl private::SockaddrLikePriv for AlgAddr {}
2196 impl SockaddrLike for AlgAddr {
2197 unsafe fn from_raw(addr: *const libc::sockaddr, l: Option<libc::socklen_t>)
2198 -> Option<Self> where Self: Sized
2199 {
2200 if let Some(l) = l {
2201 if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t {
2202 return None;
2203 }
2204 }
2205 if (*addr).sa_family as i32 != libc::AF_ALG {
2206 return None;
2207 }
2208 Some(AlgAddr(*(addr as *const libc::sockaddr_alg)))
2209 }
2210 }
2211
2212 impl AsRef<libc::sockaddr_alg> for AlgAddr {
2213 fn as_ref(&self) -> &libc::sockaddr_alg {
2214 &self.0
2215 }
2216 }
2217
2218 impl PartialEq for AlgAddr {
2220 fn eq(&self, other: &Self) -> bool {
2221 let (inner, other) = (self.0, other.0);
2222 (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
2223 (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
2224 }
2225 }
2226
2227 impl Eq for AlgAddr {}
2228
2229 impl Hash for AlgAddr {
2230 fn hash<H: Hasher>(&self, s: &mut H) {
2231 let inner = self.0;
2232 (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
2233 }
2234 }
2235
2236 impl AlgAddr {
2237 pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
2239 let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
2240 addr.salg_family = AF_ALG as u16;
2241 addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
2242 addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
2243
2244 AlgAddr(addr)
2245 }
2246
2247
2248 pub fn alg_type(&self) -> &CStr {
2250 unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
2251 }
2252
2253 pub fn alg_name(&self) -> &CStr {
2255 unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
2256 }
2257 }
2258
2259 impl fmt::Display for AlgAddr {
2260 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2261 write!(f, "type: {} alg: {}",
2262 self.alg_name().to_string_lossy(),
2263 self.alg_type().to_string_lossy())
2264 }
2265 }
2266
2267 impl fmt::Debug for AlgAddr {
2268 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2269 fmt::Display::fmt(self, f)
2270 }
2271 }
2272}
2273
2274feature! {
2275#![feature = "ioctl"]
2276#[cfg(any(target_os = "ios", target_os = "macos"))]
2277pub mod sys_control {
2278 use crate::sys::socket::addr::AddressFamily;
2279 use libc::{self, c_uchar};
2280 use std::{fmt, mem};
2281 use std::os::unix::io::RawFd;
2282 use crate::{Errno, Result};
2283 use super::{private, SockaddrLike};
2284
2285 #[repr(C)]
2287 #[derive(Clone, Copy)]
2288 #[allow(missing_debug_implementations)]
2289 pub struct ctl_ioc_info {
2290 pub ctl_id: u32,
2291 pub ctl_name: [c_uchar; MAX_KCTL_NAME],
2292 }
2293
2294 const CTL_IOC_MAGIC: u8 = b'N';
2295 const CTL_IOC_INFO: u8 = 3;
2296 const MAX_KCTL_NAME: usize = 96;
2297
2298 ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
2299
2300 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2306 #[repr(transparent)]
2307 pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl);
2308
2309 impl private::SockaddrLikePriv for SysControlAddr {}
2310 impl SockaddrLike for SysControlAddr {
2311 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
2312 -> Option<Self> where Self: Sized
2313 {
2314 if let Some(l) = len {
2315 if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t {
2316 return None;
2317 }
2318 }
2319 if (*addr).sa_family as i32 != libc::AF_SYSTEM {
2320 return None;
2321 }
2322 Some(SysControlAddr(*(addr as *const libc::sockaddr_ctl)))
2323 }
2324 }
2325
2326 impl AsRef<libc::sockaddr_ctl> for SysControlAddr {
2327 fn as_ref(&self) -> &libc::sockaddr_ctl {
2328 &self.0
2329 }
2330 }
2331
2332 impl SysControlAddr {
2333 pub const fn new(id: u32, unit: u32) -> SysControlAddr {
2336 let addr = libc::sockaddr_ctl {
2337 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
2338 sc_family: AddressFamily::System as c_uchar,
2339 ss_sysaddr: libc::AF_SYS_CONTROL as u16,
2340 sc_id: id,
2341 sc_unit: unit,
2342 sc_reserved: [0; 5]
2343 };
2344
2345 SysControlAddr(addr)
2346 }
2347
2348 pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
2351 if name.len() > MAX_KCTL_NAME {
2352 return Err(Errno::ENAMETOOLONG);
2353 }
2354
2355 let mut ctl_name = [0; MAX_KCTL_NAME];
2356 ctl_name[..name.len()].clone_from_slice(name.as_bytes());
2357 let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
2358
2359 unsafe { ctl_info(sockfd, &mut info)?; }
2360
2361 Ok(SysControlAddr::new(info.ctl_id, unit))
2362 }
2363
2364 pub const fn id(&self) -> u32 {
2366 self.0.sc_id
2367 }
2368
2369 pub const fn unit(&self) -> u32 {
2371 self.0.sc_unit
2372 }
2373 }
2374
2375 impl fmt::Display for SysControlAddr {
2376 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2377 fmt::Debug::fmt(self, f)
2378 }
2379 }
2380}
2381}
2382
2383
2384#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
2385#[cfg_attr(docsrs, doc(cfg(all())))]
2386mod datalink {
2387 feature! {
2388 #![feature = "net"]
2389 use super::{fmt, mem, private, SockaddrLike};
2390
2391 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2393 #[repr(transparent)]
2394 pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll);
2395
2396 impl LinkAddr {
2397 pub fn protocol(&self) -> u16 {
2399 self.0.sll_protocol
2400 }
2401
2402 pub fn ifindex(&self) -> usize {
2404 self.0.sll_ifindex as usize
2405 }
2406
2407 pub fn hatype(&self) -> u16 {
2409 self.0.sll_hatype
2410 }
2411
2412 pub fn pkttype(&self) -> u8 {
2414 self.0.sll_pkttype
2415 }
2416
2417 pub fn halen(&self) -> usize {
2419 self.0.sll_halen as usize
2420 }
2421
2422 pub fn addr(&self) -> Option<[u8; 6]> {
2425 Some([
2426 self.0.sll_addr[0],
2427 self.0.sll_addr[1],
2428 self.0.sll_addr[2],
2429 self.0.sll_addr[3],
2430 self.0.sll_addr[4],
2431 self.0.sll_addr[5],
2432 ])
2433 }
2434 }
2435
2436 impl fmt::Display for LinkAddr {
2437 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2438 if let Some(addr) = self.addr() {
2439 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
2440 addr[0],
2441 addr[1],
2442 addr[2],
2443 addr[3],
2444 addr[4],
2445 addr[5])
2446 } else {
2447 Ok(())
2448 }
2449 }
2450 }
2451 impl private::SockaddrLikePriv for LinkAddr {}
2452 impl SockaddrLike for LinkAddr {
2453 unsafe fn from_raw(addr: *const libc::sockaddr,
2454 len: Option<libc::socklen_t>)
2455 -> Option<Self> where Self: Sized
2456 {
2457 if let Some(l) = len {
2458 if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t {
2459 return None;
2460 }
2461 }
2462 if (*addr).sa_family as i32 != libc::AF_PACKET {
2463 return None;
2464 }
2465 Some(LinkAddr(*(addr as *const libc::sockaddr_ll)))
2466 }
2467 }
2468
2469 impl AsRef<libc::sockaddr_ll> for LinkAddr {
2470 fn as_ref(&self) -> &libc::sockaddr_ll {
2471 &self.0
2472 }
2473 }
2474
2475 }
2476}
2477
2478#[cfg(any(target_os = "dragonfly",
2479 target_os = "freebsd",
2480 target_os = "ios",
2481 target_os = "macos",
2482 target_os = "illumos",
2483 target_os = "netbsd",
2484 target_os = "openbsd"))]
2485#[cfg_attr(docsrs, doc(cfg(all())))]
2486mod datalink {
2487 feature! {
2488 #![feature = "net"]
2489 use super::{fmt, mem, private, SockaddrLike};
2490
2491 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2493 #[repr(transparent)]
2494 pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl);
2495
2496 impl LinkAddr {
2497 pub fn ifindex(&self) -> usize {
2499 self.0.sdl_index as usize
2500 }
2501
2502 pub fn datalink_type(&self) -> u8 {
2504 self.0.sdl_type
2505 }
2506
2507 pub fn nlen(&self) -> usize {
2509 self.0.sdl_nlen as usize
2510 }
2511
2512 pub fn alen(&self) -> usize {
2514 self.0.sdl_alen as usize
2515 }
2516
2517 pub fn slen(&self) -> usize {
2519 self.0.sdl_slen as usize
2520 }
2521
2522 pub fn is_empty(&self) -> bool {
2525 let nlen = self.nlen();
2526 let alen = self.alen();
2527 let data_len = self.0.sdl_data.len();
2528
2529 alen == 0 || nlen + alen >= data_len
2530 }
2531
2532 #[allow(clippy::unnecessary_cast)]
2535 pub fn addr(&self) -> Option<[u8; 6]> {
2536 let nlen = self.nlen();
2537 let data = self.0.sdl_data;
2538
2539 if self.is_empty() {
2540 None
2541 } else {
2542 Some([
2543 data[nlen] as u8,
2544 data[nlen + 1] as u8,
2545 data[nlen + 2] as u8,
2546 data[nlen + 3] as u8,
2547 data[nlen + 4] as u8,
2548 data[nlen + 5] as u8,
2549 ])
2550 }
2551 }
2552 }
2553
2554 impl fmt::Display for LinkAddr {
2555 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2556 if let Some(addr) = self.addr() {
2557 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
2558 addr[0],
2559 addr[1],
2560 addr[2],
2561 addr[3],
2562 addr[4],
2563 addr[5])
2564 } else {
2565 Ok(())
2566 }
2567 }
2568 }
2569 impl private::SockaddrLikePriv for LinkAddr {}
2570 impl SockaddrLike for LinkAddr {
2571 unsafe fn from_raw(addr: *const libc::sockaddr,
2572 len: Option<libc::socklen_t>)
2573 -> Option<Self> where Self: Sized
2574 {
2575 if let Some(l) = len {
2576 if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t {
2577 return None;
2578 }
2579 }
2580 if (*addr).sa_family as i32 != libc::AF_LINK {
2581 return None;
2582 }
2583 Some(LinkAddr(*(addr as *const libc::sockaddr_dl)))
2584 }
2585 }
2586
2587 impl AsRef<libc::sockaddr_dl> for LinkAddr {
2588 fn as_ref(&self) -> &libc::sockaddr_dl {
2589 &self.0
2590 }
2591 }
2592
2593 }
2594}
2595
2596#[cfg(any(target_os = "android", target_os = "linux"))]
2597#[cfg_attr(docsrs, doc(cfg(all())))]
2598pub mod vsock {
2599 use crate::sys::socket::addr::AddressFamily;
2600 use libc::{sa_family_t, sockaddr_vm};
2601 use std::{fmt, mem};
2602 use std::hash::{Hash, Hasher};
2603 use super::*;
2604
2605 #[derive(Copy, Clone)]
2611 #[repr(transparent)]
2612 pub struct VsockAddr(pub(in super::super) sockaddr_vm);
2613
2614 impl private::SockaddrLikePriv for VsockAddr {}
2615 impl SockaddrLike for VsockAddr {
2616 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
2617 -> Option<Self> where Self: Sized
2618 {
2619 if let Some(l) = len {
2620 if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t {
2621 return None;
2622 }
2623 }
2624 if (*addr).sa_family as i32 != libc::AF_VSOCK {
2625 return None;
2626 }
2627 Some(VsockAddr(*(addr as *const libc::sockaddr_vm)))
2628 }
2629 }
2630
2631 impl AsRef<libc::sockaddr_vm> for VsockAddr {
2632 fn as_ref(&self) -> &libc::sockaddr_vm {
2633 &self.0
2634 }
2635 }
2636
2637 impl PartialEq for VsockAddr {
2638 fn eq(&self, other: &Self) -> bool {
2639 let (inner, other) = (self.0, other.0);
2640 (inner.svm_family, inner.svm_cid, inner.svm_port) ==
2641 (other.svm_family, other.svm_cid, other.svm_port)
2642 }
2643 }
2644
2645 impl Eq for VsockAddr {}
2646
2647 impl Hash for VsockAddr {
2648 fn hash<H: Hasher>(&self, s: &mut H) {
2649 let inner = self.0;
2650 (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
2651 }
2652 }
2653
2654 impl VsockAddr {
2659 pub fn new(cid: u32, port: u32) -> VsockAddr {
2661 let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
2662 addr.svm_family = AddressFamily::Vsock as sa_family_t;
2663 addr.svm_cid = cid;
2664 addr.svm_port = port;
2665
2666 VsockAddr(addr)
2667 }
2668
2669 pub fn cid(&self) -> u32 {
2671 self.0.svm_cid
2672 }
2673
2674 pub fn port(&self) -> u32 {
2676 self.0.svm_port
2677 }
2678 }
2679
2680 impl fmt::Display for VsockAddr {
2681 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2682 write!(f, "cid: {} port: {}", self.cid(), self.port())
2683 }
2684 }
2685
2686 impl fmt::Debug for VsockAddr {
2687 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2688 fmt::Display::fmt(self, f)
2689 }
2690 }
2691}
2692
2693#[cfg(test)]
2694mod tests {
2695 use super::*;
2696
2697 mod types {
2698 use super::*;
2699
2700 #[test]
2701 fn test_ipv4addr_to_libc() {
2702 let s = std::net::Ipv4Addr::new(1, 2, 3, 4);
2703 let l = ipv4addr_to_libc(s);
2704 assert_eq!(l.s_addr, u32::to_be(0x01020304));
2705 }
2706
2707 #[test]
2708 fn test_ipv6addr_to_libc() {
2709 let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8);
2710 let l = ipv6addr_to_libc(&s);
2711 assert_eq!(l.s6_addr, [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8]);
2712 }
2713 }
2714
2715 mod link {
2716 use super::*;
2717 #[cfg(any(target_os = "ios",
2718 target_os = "macos",
2719 target_os = "illumos"
2720 ))]
2721 use super::super::super::socklen_t;
2722
2723 #[cfg(any(target_os = "dragonfly",
2725 target_os = "freebsd",
2726 target_os = "ios",
2727 target_os = "macos",
2728 target_os = "netbsd",
2729 target_os = "openbsd"))]
2730 #[test]
2731 fn test_datalink_display() {
2732 use super::super::LinkAddr;
2733 use std::mem;
2734
2735 let la = LinkAddr(libc::sockaddr_dl{
2736 sdl_len: 56,
2737 sdl_family: 18,
2738 sdl_index: 5,
2739 sdl_type: 24,
2740 sdl_nlen: 3,
2741 sdl_alen: 0,
2742 sdl_slen: 0,
2743 .. unsafe{mem::zeroed()}
2744 });
2745 format!("{}", la);
2746 }
2747
2748 #[cfg(all(
2749 any(target_os = "android",
2750 target_os = "fuchsia",
2751 target_os = "linux"),
2752 target_endian = "little"
2753 ))]
2754 #[test]
2755 fn linux_loopback() {
2756 let bytes = [17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0];
2757 let sa = bytes.as_ptr() as *const libc::sockaddr;
2758 let len = None;
2759 let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
2760 assert_eq!(sock_addr.family(), Some(AddressFamily::Packet));
2761 match sock_addr.as_link_addr() {
2762 Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])),
2763 None => panic!("Can't unwrap sockaddr storage")
2764 }
2765 }
2766
2767 #[cfg(any(target_os = "ios",
2768 target_os = "macos"
2769 ))]
2770 #[test]
2771 fn macos_loopback() {
2772 let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
2773 let sa = bytes.as_ptr() as *const libc::sockaddr;
2774 let len = Some(bytes.len() as socklen_t);
2775 let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
2776 assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
2777 match sock_addr.as_link_addr() {
2778 Some(dl) => {
2779 assert!(dl.addr().is_none());
2780 },
2781 None => panic!("Can't unwrap sockaddr storage")
2782 }
2783 }
2784
2785 #[cfg(any(target_os = "ios",
2786 target_os = "macos"
2787 ))]
2788 #[test]
2789 fn macos_tap() {
2790 let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
2791 let ptr = bytes.as_ptr();
2792 let sa = ptr as *const libc::sockaddr;
2793 let len = Some(bytes.len() as socklen_t);
2794
2795 let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
2796 assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
2797 match sock_addr.as_link_addr() {
2798 Some(dl) => assert_eq!(dl.addr(),
2799 Some([24u8, 101, 144, 221, 76, 176])),
2800 None => panic!("Can't unwrap sockaddr storage")
2801 }
2802 }
2803
2804 #[cfg(target_os = "illumos")]
2805 #[test]
2806 fn illumos_tap() {
2807 let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
2808 let ptr = bytes.as_ptr();
2809 let sa = ptr as *const libc::sockaddr;
2810 let len = Some(bytes.len() as socklen_t);
2811 let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) };
2812
2813 assert!(_sock_addr.is_some());
2814
2815 let sock_addr = _sock_addr.unwrap();
2816
2817 assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link);
2818
2819 assert_eq!(sock_addr.as_link_addr().unwrap().addr(),
2820 Some([24u8, 101, 144, 221, 76, 176]));
2821 }
2822
2823 #[test]
2824 fn size() {
2825 #[cfg(any(target_os = "dragonfly",
2826 target_os = "freebsd",
2827 target_os = "ios",
2828 target_os = "macos",
2829 target_os = "netbsd",
2830 target_os = "illumos",
2831 target_os = "openbsd"))]
2832 let l = mem::size_of::<libc::sockaddr_dl>();
2833 #[cfg(any(
2834 target_os = "android",
2835 target_os = "fuchsia",
2836 target_os = "linux"))]
2837 let l = mem::size_of::<libc::sockaddr_ll>();
2838 assert_eq!( LinkAddr::size() as usize, l);
2839 }
2840 }
2841
2842 mod sockaddr_in {
2843 use super::*;
2844 use std::str::FromStr;
2845
2846 #[test]
2847 fn display() {
2848 let s = "127.0.0.1:8080";
2849 let addr = SockaddrIn::from_str(s).unwrap();
2850 assert_eq!(s, format!("{}", addr));
2851 }
2852
2853 #[test]
2854 fn size() {
2855 assert_eq!(mem::size_of::<libc::sockaddr_in>(),
2856 SockaddrIn::size() as usize);
2857 }
2858 }
2859
2860 mod sockaddr_in6 {
2861 use super::*;
2862 use std::str::FromStr;
2863
2864 #[test]
2865 fn display() {
2866 let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2867 let addr = SockaddrIn6::from_str(s).unwrap();
2868 assert_eq!(s, format!("{}", addr));
2869 }
2870
2871 #[test]
2872 fn size() {
2873 assert_eq!(mem::size_of::<libc::sockaddr_in6>(),
2874 SockaddrIn6::size() as usize);
2875 }
2876 }
2877
2878 mod sockaddr_storage {
2879 use super::*;
2880
2881 #[test]
2882 fn from_sockaddr_un_named() {
2883 let ua = UnixAddr::new("/var/run/mysock").unwrap();
2884 let ptr = ua.as_ptr() as *const libc::sockaddr;
2885 let ss = unsafe {
2886 SockaddrStorage::from_raw(ptr, Some(ua.len()))
2887 }.unwrap();
2888 assert_eq!(ss.len(), ua.len());
2889 }
2890
2891 #[cfg(any(target_os = "android", target_os = "linux"))]
2892 #[test]
2893 fn from_sockaddr_un_abstract_named() {
2894 let name = String::from("nix\0abstract\0test");
2895 let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
2896 let ptr = ua.as_ptr() as *const libc::sockaddr;
2897 let ss = unsafe {
2898 SockaddrStorage::from_raw(ptr, Some(ua.len()))
2899 }.unwrap();
2900 assert_eq!(ss.len(), ua.len());
2901 }
2902
2903 #[cfg(any(target_os = "android", target_os = "linux"))]
2904 #[test]
2905 fn from_sockaddr_un_abstract_unnamed() {
2906 let empty = String::new();
2907 let ua = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
2908 let ptr = ua.as_ptr() as *const libc::sockaddr;
2909 let ss = unsafe {
2910 SockaddrStorage::from_raw(ptr, Some(ua.len()))
2911 }.unwrap();
2912 assert_eq!(ss.len(), ua.len());
2913 }
2914 }
2915
2916 mod unixaddr {
2917 use super::*;
2918
2919 #[cfg(any(target_os = "android", target_os = "linux"))]
2920 #[test]
2921 fn abstract_sun_path() {
2922 let name = String::from("nix\0abstract\0test");
2923 let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
2924
2925 let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
2926 let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
2927 assert_eq!(sun_path1, sun_path2);
2928 }
2929
2930 #[test]
2931 fn size() {
2932 assert_eq!(mem::size_of::<libc::sockaddr_un>(),
2933 UnixAddr::size() as usize);
2934 }
2935 }
2936}