1use super::sa_family_t;
2use crate::{Result, NixPath};
3use crate::errno::Errno;
4use memoffset::offset_of;
5use std::{fmt, mem, net, ptr, slice};
6use std::ffi::OsStr;
7use std::hash::{Hash, Hasher};
8use std::path::Path;
9use std::os::unix::ffi::OsStrExt;
10#[cfg(any(target_os = "android", target_os = "linux"))]
11use crate::sys::socket::addr::netlink::NetlinkAddr;
12#[cfg(any(target_os = "android", target_os = "linux"))]
13use crate::sys::socket::addr::alg::AlgAddr;
14#[cfg(any(target_os = "ios", target_os = "macos"))]
15use std::os::unix::io::RawFd;
16#[cfg(any(target_os = "ios", target_os = "macos"))]
17use 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"))]
28pub use self::datalink::LinkAddr;
29#[cfg(any(target_os = "android", target_os = "linux"))]
30pub use self::vsock::VsockAddr;
31
32#[repr(i32)]
35#[non_exhaustive]
36#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
37pub enum AddressFamily {
38 Unix = libc::AF_UNIX,
40 Inet = libc::AF_INET,
42 Inet6 = libc::AF_INET6,
44 #[cfg(any(target_os = "android", target_os = "linux"))]
46 Netlink = libc::AF_NETLINK,
47 #[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 #[cfg(any(target_os = "ios", target_os = "macos"))]
56 System = libc::AF_SYSTEM,
57 #[cfg(any(target_os = "android", target_os = "linux"))]
59 Ax25 = libc::AF_AX25,
60 Ipx = libc::AF_IPX,
62 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 #[cfg(any(target_os = "android", target_os = "linux"))]
70 AtmPvc = libc::AF_ATMPVC,
71 #[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 #[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 #[cfg(any(target_os = "android", target_os = "linux"))]
231 Unspec = libc::AF_UNSPEC,
232}
233
234impl AddressFamily {
235 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)]
267pub enum InetAddr {
268 V4(libc::sockaddr_in),
269 V6(libc::sockaddr_in6),
270}
271
272impl InetAddr {
273 #[allow(clippy::needless_update)] pub fn from_std(std: &net::SocketAddr) -> InetAddr {
275 match *std {
276 net::SocketAddr::V4(ref addr) => {
277 InetAddr::V4(libc::sockaddr_in {
278 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
279 target_os = "haiku", target_os = "hermit",
280 target_os = "ios", target_os = "macos",
281 target_os = "netbsd", target_os = "openbsd"))]
282 sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
283 sin_family: AddressFamily::Inet as sa_family_t,
284 sin_port: addr.port().to_be(), sin_addr: Ipv4Addr::from_std(addr.ip()).0,
286 .. unsafe { mem::zeroed() }
287 })
288 }
289 net::SocketAddr::V6(ref addr) => {
290 InetAddr::V6(libc::sockaddr_in6 {
291 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
292 target_os = "haiku", target_os = "hermit",
293 target_os = "ios", target_os = "macos",
294 target_os = "netbsd", target_os = "openbsd"))]
295 sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
296 sin6_family: AddressFamily::Inet6 as sa_family_t,
297 sin6_port: addr.port().to_be(), sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
299 sin6_flowinfo: addr.flowinfo(), sin6_scope_id: addr.scope_id(), .. unsafe { mem::zeroed() }
302 })
303 }
304 }
305 }
306
307 #[allow(clippy::needless_update)] pub fn new(ip: IpAddr, port: u16) -> InetAddr {
309 match ip {
310 IpAddr::V4(ref ip) => {
311 InetAddr::V4(libc::sockaddr_in {
312 sin_family: AddressFamily::Inet as sa_family_t,
313 sin_port: port.to_be(),
314 sin_addr: ip.0,
315 .. unsafe { mem::zeroed() }
316 })
317 }
318 IpAddr::V6(ref ip) => {
319 InetAddr::V6(libc::sockaddr_in6 {
320 sin6_family: AddressFamily::Inet6 as sa_family_t,
321 sin6_port: port.to_be(),
322 sin6_addr: ip.0,
323 .. unsafe { mem::zeroed() }
324 })
325 }
326 }
327 }
328 pub const fn ip(&self) -> IpAddr {
330 match *self {
331 InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
332 InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
333 }
334 }
335
336 pub const fn port(&self) -> u16 {
338 match *self {
339 InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
340 InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
341 }
342 }
343
344 pub fn to_std(&self) -> net::SocketAddr {
345 match *self {
346 InetAddr::V4(ref sa) => net::SocketAddr::V4(
347 net::SocketAddrV4::new(
348 Ipv4Addr(sa.sin_addr).to_std(),
349 self.port())),
350 InetAddr::V6(ref sa) => net::SocketAddr::V6(
351 net::SocketAddrV6::new(
352 Ipv6Addr(sa.sin6_addr).to_std(),
353 self.port(),
354 sa.sin6_flowinfo,
355 sa.sin6_scope_id)),
356 }
357 }
358
359 #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
360 pub fn to_str(&self) -> String {
361 format!("{}", self)
362 }
363}
364
365impl fmt::Display for InetAddr {
366 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
367 match *self {
368 InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
369 InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
370 }
371 }
372}
373
374#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
380pub enum IpAddr {
381 V4(Ipv4Addr),
382 V6(Ipv6Addr),
383}
384
385impl IpAddr {
386 pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
390 IpAddr::V4(Ipv4Addr::new(a, b, c, d))
391 }
392
393 #[allow(clippy::many_single_char_names)]
397 #[allow(clippy::too_many_arguments)]
398 pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
399 IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
400 }
401
402 pub fn from_std(std: &net::IpAddr) -> IpAddr {
403 match *std {
404 net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
405 net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
406 }
407 }
408
409 pub const fn to_std(&self) -> net::IpAddr {
410 match *self {
411 IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
412 IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
413 }
414 }
415}
416
417impl fmt::Display for IpAddr {
418 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
419 match *self {
420 IpAddr::V4(ref v4) => v4.fmt(f),
421 IpAddr::V6(ref v6) => v6.fmt(f)
422 }
423 }
424}
425
426#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
433pub struct Ipv4Addr(pub libc::in_addr);
434
435impl Ipv4Addr {
436 #[allow(clippy::identity_op)] pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
438 let ip = (((a as u32) << 24) |
439 ((b as u32) << 16) |
440 ((c as u32) << 8) |
441 ((d as u32) << 0)).to_be();
442
443 Ipv4Addr(libc::in_addr { s_addr: ip })
444 }
445
446 #[allow(clippy::trivially_copy_pass_by_ref)]
448 pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
449 let bits = std.octets();
450 Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
451 }
452
453 pub const fn any() -> Ipv4Addr {
454 Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
455 }
456
457 pub const fn octets(self) -> [u8; 4] {
458 let bits = u32::from_be(self.0.s_addr);
459 [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
460 }
461
462 pub const fn to_std(self) -> net::Ipv4Addr {
463 let bits = self.octets();
464 net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
465 }
466}
467
468impl fmt::Display for Ipv4Addr {
469 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
470 let octets = self.octets();
471 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
472 }
473}
474
475#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
482pub struct Ipv6Addr(pub libc::in6_addr);
483
484macro_rules! to_u8_array {
489 ($($num:ident),*) => {
490 [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
491 }
492}
493
494macro_rules! to_u16_array {
495 ($slf:ident, $($first:expr, $second:expr),*) => {
496 [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
497 }
498}
499
500impl Ipv6Addr {
501 #[allow(clippy::many_single_char_names)]
502 #[allow(clippy::too_many_arguments)]
503 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
504 Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
505 }
506
507 pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
508 let s = std.segments();
509 Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
510 }
511
512 pub const fn segments(&self) -> [u16; 8] {
514 to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
515 }
516
517 pub const fn to_std(&self) -> net::Ipv6Addr {
518 let s = self.segments();
519 net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
520 }
521}
522
523impl fmt::Display for Ipv6Addr {
524 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
525 self.to_std().fmt(fmt)
526 }
527}
528
529#[derive(Clone, Copy, Debug)]
531pub struct UnixAddr {
532 sun: libc::sockaddr_un,
534 path_len: usize,
535}
536
537#[derive(PartialEq, Eq, Hash)]
544enum UnixAddrKind<'a> {
545 Pathname(&'a Path),
546 Unnamed,
547 #[cfg(any(target_os = "android", target_os = "linux"))]
548 Abstract(&'a [u8]),
549}
550impl<'a> UnixAddrKind<'a> {
551 unsafe fn get(sun: &'a libc::sockaddr_un, path_len: usize) -> Self {
553 if path_len == 0 {
554 return Self::Unnamed;
555 }
556 #[cfg(any(target_os = "android", target_os = "linux"))]
557 if sun.sun_path[0] == 0 {
558 let name =
559 slice::from_raw_parts(sun.sun_path.as_ptr().add(1) as *const u8, path_len - 1);
560 return Self::Abstract(name);
561 }
562 let pathname = slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len - 1);
563 Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
564 }
565}
566
567impl UnixAddr {
568 pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
570 path.with_nix_path(|cstr| {
571 unsafe {
572 let mut ret = libc::sockaddr_un {
573 sun_family: AddressFamily::Unix as sa_family_t,
574 .. mem::zeroed()
575 };
576
577 let bytes = cstr.to_bytes();
578
579 if bytes.len() >= ret.sun_path.len() {
580 return Err(Errno::ENAMETOOLONG);
581 }
582
583 ptr::copy_nonoverlapping(bytes.as_ptr(),
584 ret.sun_path.as_mut_ptr() as *mut u8,
585 bytes.len());
586
587 Ok(UnixAddr::from_raw_parts(ret, bytes.len() + 1))
588 }
589 })?
590 }
591
592 #[cfg(any(target_os = "android", target_os = "linux"))]
599 pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
600 unsafe {
601 let mut ret = libc::sockaddr_un {
602 sun_family: AddressFamily::Unix as sa_family_t,
603 .. mem::zeroed()
604 };
605
606 if path.len() >= ret.sun_path.len() {
607 return Err(Errno::ENAMETOOLONG);
608 }
609
610 ptr::copy_nonoverlapping(path.as_ptr(),
613 ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
614 path.len());
615
616 Ok(UnixAddr::from_raw_parts(ret, path.len() + 1))
617 }
618 }
619
620 pub(crate) unsafe fn from_raw_parts(sun: libc::sockaddr_un, mut path_len: usize) -> UnixAddr {
630 if let UnixAddrKind::Pathname(_) = UnixAddrKind::get(&sun, path_len) {
631 if sun.sun_path[path_len - 1] != 0 {
632 assert_eq!(sun.sun_path[path_len], 0);
633 path_len += 1
634 }
635 }
636 UnixAddr { sun, path_len }
637 }
638
639 fn kind(&self) -> UnixAddrKind<'_> {
640 unsafe { UnixAddrKind::get(&self.sun, self.path_len) }
642 }
643
644 pub fn path(&self) -> Option<&Path> {
646 match self.kind() {
647 UnixAddrKind::Pathname(path) => Some(path),
648 _ => None,
649 }
650 }
651
652 #[cfg(any(target_os = "android", target_os = "linux"))]
657 pub fn as_abstract(&self) -> Option<&[u8]> {
658 match self.kind() {
659 UnixAddrKind::Abstract(name) => Some(name),
660 _ => None,
661 }
662 }
663
664 #[inline]
666 pub fn path_len(&self) -> usize {
667 self.path_len
668 }
669 #[inline]
671 pub fn as_ptr(&self) -> *const libc::sockaddr_un {
672 &self.sun
673 }
674 #[inline]
676 pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
677 &mut self.sun
678 }
679}
680
681#[cfg(any(target_os = "android", target_os = "linux"))]
682fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
683 use fmt::Write;
684 f.write_str("@\"")?;
685 for &b in abs {
686 use fmt::Display;
687 char::from(b).escape_default().fmt(f)?;
688 }
689 f.write_char('"')?;
690 Ok(())
691}
692
693impl fmt::Display for UnixAddr {
694 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
695 match self.kind() {
696 UnixAddrKind::Pathname(path) => path.display().fmt(f),
697 UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
698 #[cfg(any(target_os = "android", target_os = "linux"))]
699 UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
700 }
701 }
702}
703
704impl PartialEq for UnixAddr {
705 fn eq(&self, other: &UnixAddr) -> bool {
706 self.kind() == other.kind()
707 }
708}
709
710impl Eq for UnixAddr {}
711
712impl Hash for UnixAddr {
713 fn hash<H: Hasher>(&self, s: &mut H) {
714 self.kind().hash(s)
715 }
716}
717
718#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
720#[non_exhaustive]
721pub enum SockAddr {
722 Inet(InetAddr),
723 Unix(UnixAddr),
724 #[cfg(any(target_os = "android", target_os = "linux"))]
725 Netlink(NetlinkAddr),
726 #[cfg(any(target_os = "android", target_os = "linux"))]
727 Alg(AlgAddr),
728 #[cfg(any(target_os = "ios", target_os = "macos"))]
729 SysControl(SysControlAddr),
730 #[cfg(any(target_os = "android",
732 target_os = "dragonfly",
733 target_os = "freebsd",
734 target_os = "ios",
735 target_os = "linux",
736 target_os = "macos",
737 target_os = "illumos",
738 target_os = "netbsd",
739 target_os = "openbsd"))]
740 Link(LinkAddr),
741 #[cfg(any(target_os = "android", target_os = "linux"))]
742 Vsock(VsockAddr),
743}
744
745impl SockAddr {
746 pub fn new_inet(addr: InetAddr) -> SockAddr {
747 SockAddr::Inet(addr)
748 }
749
750 pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
751 Ok(SockAddr::Unix(UnixAddr::new(path)?))
752 }
753
754 #[cfg(any(target_os = "android", target_os = "linux"))]
755 pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
756 SockAddr::Netlink(NetlinkAddr::new(pid, groups))
757 }
758
759 #[cfg(any(target_os = "android", target_os = "linux"))]
760 pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
761 SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
762 }
763
764 #[cfg(any(target_os = "ios", target_os = "macos"))]
765 pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
766 SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl)
767 }
768
769 #[cfg(any(target_os = "android", target_os = "linux"))]
770 pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
771 SockAddr::Vsock(VsockAddr::new(cid, port))
772 }
773
774 pub fn family(&self) -> AddressFamily {
775 match *self {
776 SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
777 SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
778 SockAddr::Unix(..) => AddressFamily::Unix,
779 #[cfg(any(target_os = "android", target_os = "linux"))]
780 SockAddr::Netlink(..) => AddressFamily::Netlink,
781 #[cfg(any(target_os = "android", target_os = "linux"))]
782 SockAddr::Alg(..) => AddressFamily::Alg,
783 #[cfg(any(target_os = "ios", target_os = "macos"))]
784 SockAddr::SysControl(..) => AddressFamily::System,
785 #[cfg(any(target_os = "android", target_os = "linux"))]
786 SockAddr::Link(..) => AddressFamily::Packet,
787 #[cfg(any(target_os = "dragonfly",
788 target_os = "freebsd",
789 target_os = "ios",
790 target_os = "macos",
791 target_os = "netbsd",
792 target_os = "illumos",
793 target_os = "openbsd"))]
794 SockAddr::Link(..) => AddressFamily::Link,
795 #[cfg(any(target_os = "android", target_os = "linux"))]
796 SockAddr::Vsock(..) => AddressFamily::Vsock,
797 }
798 }
799
800 #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
801 pub fn to_str(&self) -> String {
802 format!("{}", self)
803 }
804
805 #[cfg(not(target_os = "fuchsia"))]
815 pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
816 if addr.is_null() {
817 None
818 } else {
819 match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
820 Some(AddressFamily::Unix) => None,
821 Some(AddressFamily::Inet) => Some(SockAddr::Inet(
822 InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
823 Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
824 InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
825 #[cfg(any(target_os = "android", target_os = "linux"))]
826 Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
827 NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
828 #[cfg(any(target_os = "ios", target_os = "macos"))]
829 Some(AddressFamily::System) => Some(SockAddr::SysControl(
830 SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
831 #[cfg(any(target_os = "android", target_os = "linux"))]
832 Some(AddressFamily::Packet) => Some(SockAddr::Link(
833 LinkAddr(*(addr as *const libc::sockaddr_ll)))),
834 #[cfg(any(target_os = "dragonfly",
835 target_os = "freebsd",
836 target_os = "ios",
837 target_os = "macos",
838 target_os = "netbsd",
839 target_os = "illumos",
840 target_os = "openbsd"))]
841 Some(AddressFamily::Link) => {
842 let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
843 if ether_addr.is_empty() {
844 None
845 } else {
846 Some(SockAddr::Link(ether_addr))
847 }
848 },
849 #[cfg(any(target_os = "android", target_os = "linux"))]
850 Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
851 VsockAddr(*(addr as *const libc::sockaddr_vm)))),
852 Some(_) | None => None,
855 }
856 }
857 }
858
859 pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
867 match *self {
868 SockAddr::Inet(InetAddr::V4(ref addr)) => (
869 unsafe {
871 &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
872 },
873 mem::size_of_val(addr) as libc::socklen_t
874 ),
875 SockAddr::Inet(InetAddr::V6(ref addr)) => (
876 unsafe {
878 &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
879 },
880 mem::size_of_val(addr) as libc::socklen_t
881 ),
882 SockAddr::Unix(UnixAddr { ref sun, path_len }) => (
883 unsafe {
885 &*(sun as *const libc::sockaddr_un as *const libc::sockaddr)
886 },
887 (path_len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
888 ),
889 #[cfg(any(target_os = "android", target_os = "linux"))]
890 SockAddr::Netlink(NetlinkAddr(ref sa)) => (
891 unsafe {
893 &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
894 },
895 mem::size_of_val(sa) as libc::socklen_t
896 ),
897 #[cfg(any(target_os = "android", target_os = "linux"))]
898 SockAddr::Alg(AlgAddr(ref sa)) => (
899 unsafe {
901 &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
902 },
903 mem::size_of_val(sa) as libc::socklen_t
904 ),
905 #[cfg(any(target_os = "ios", target_os = "macos"))]
906 SockAddr::SysControl(SysControlAddr(ref sa)) => (
907 unsafe {
909 &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
910 },
911 mem::size_of_val(sa) as libc::socklen_t
912
913 ),
914 #[cfg(any(target_os = "android", target_os = "linux"))]
915 SockAddr::Link(LinkAddr(ref addr)) => (
916 unsafe {
918 &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
919 },
920 mem::size_of_val(addr) as libc::socklen_t
921 ),
922 #[cfg(any(target_os = "dragonfly",
923 target_os = "freebsd",
924 target_os = "ios",
925 target_os = "macos",
926 target_os = "illumos",
927 target_os = "netbsd",
928 target_os = "openbsd"))]
929 SockAddr::Link(LinkAddr(ref addr)) => (
930 unsafe {
932 &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
933 },
934 mem::size_of_val(addr) as libc::socklen_t
935 ),
936 #[cfg(any(target_os = "android", target_os = "linux"))]
937 SockAddr::Vsock(VsockAddr(ref sa)) => (
938 unsafe {
940 &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
941 },
942 mem::size_of_val(sa) as libc::socklen_t
943 ),
944 }
945 }
946}
947
948impl fmt::Display for SockAddr {
949 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
950 match *self {
951 SockAddr::Inet(ref inet) => inet.fmt(f),
952 SockAddr::Unix(ref unix) => unix.fmt(f),
953 #[cfg(any(target_os = "android", target_os = "linux"))]
954 SockAddr::Netlink(ref nl) => nl.fmt(f),
955 #[cfg(any(target_os = "android", target_os = "linux"))]
956 SockAddr::Alg(ref nl) => nl.fmt(f),
957 #[cfg(any(target_os = "ios", target_os = "macos"))]
958 SockAddr::SysControl(ref sc) => sc.fmt(f),
959 #[cfg(any(target_os = "android",
960 target_os = "dragonfly",
961 target_os = "freebsd",
962 target_os = "ios",
963 target_os = "linux",
964 target_os = "macos",
965 target_os = "netbsd",
966 target_os = "illumos",
967 target_os = "openbsd"))]
968 SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
969 #[cfg(any(target_os = "android", target_os = "linux"))]
970 SockAddr::Vsock(ref svm) => svm.fmt(f),
971 }
972 }
973}
974
975#[cfg(any(target_os = "android", target_os = "linux"))]
976pub mod netlink {
977 use crate::sys::socket::addr::AddressFamily;
978 use libc::{sa_family_t, sockaddr_nl};
979 use std::{fmt, mem};
980
981 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
982 pub struct NetlinkAddr(pub sockaddr_nl);
983
984 impl NetlinkAddr {
985 pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
986 let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
987 addr.nl_family = AddressFamily::Netlink as sa_family_t;
988 addr.nl_pid = pid;
989 addr.nl_groups = groups;
990
991 NetlinkAddr(addr)
992 }
993
994 pub const fn pid(&self) -> u32 {
995 self.0.nl_pid
996 }
997
998 pub const fn groups(&self) -> u32 {
999 self.0.nl_groups
1000 }
1001 }
1002
1003 impl fmt::Display for NetlinkAddr {
1004 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1005 write!(f, "pid: {} groups: {}", self.pid(), self.groups())
1006 }
1007 }
1008}
1009
1010#[cfg(any(target_os = "android", target_os = "linux"))]
1011pub mod alg {
1012 use libc::{AF_ALG, sockaddr_alg, c_char};
1013 use std::{fmt, mem, str};
1014 use std::hash::{Hash, Hasher};
1015 use std::ffi::CStr;
1016
1017 #[derive(Copy, Clone)]
1018 pub struct AlgAddr(pub sockaddr_alg);
1019
1020 impl PartialEq for AlgAddr {
1022 fn eq(&self, other: &Self) -> bool {
1023 let (inner, other) = (self.0, other.0);
1024 (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
1025 (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
1026 }
1027 }
1028
1029 impl Eq for AlgAddr {}
1030
1031 impl Hash for AlgAddr {
1032 fn hash<H: Hasher>(&self, s: &mut H) {
1033 let inner = self.0;
1034 (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
1035 }
1036 }
1037
1038 impl AlgAddr {
1039 pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
1040 let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
1041 addr.salg_family = AF_ALG as u16;
1042 addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
1043 addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
1044
1045 AlgAddr(addr)
1046 }
1047
1048
1049 pub fn alg_type(&self) -> &CStr {
1050 unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
1051 }
1052
1053 pub fn alg_name(&self) -> &CStr {
1054 unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
1055 }
1056 }
1057
1058 impl fmt::Display for AlgAddr {
1059 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1060 write!(f, "type: {} alg: {}",
1061 self.alg_name().to_string_lossy(),
1062 self.alg_type().to_string_lossy())
1063 }
1064 }
1065
1066 impl fmt::Debug for AlgAddr {
1067 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1068 fmt::Display::fmt(self, f)
1069 }
1070 }
1071}
1072
1073#[cfg(any(target_os = "ios", target_os = "macos"))]
1074pub mod sys_control {
1075 use crate::sys::socket::addr::AddressFamily;
1076 use libc::{self, c_uchar};
1077 use std::{fmt, mem};
1078 use std::os::unix::io::RawFd;
1079 use crate::{Errno, Result};
1080
1081 #[repr(C)]
1083 #[derive(Clone, Copy)]
1084 #[allow(missing_debug_implementations)]
1085 pub struct ctl_ioc_info {
1086 pub ctl_id: u32,
1087 pub ctl_name: [c_uchar; MAX_KCTL_NAME],
1088 }
1089
1090 const CTL_IOC_MAGIC: u8 = b'N';
1091 const CTL_IOC_INFO: u8 = 3;
1092 const MAX_KCTL_NAME: usize = 96;
1093
1094 ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
1095
1096 #[repr(C)]
1097 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1098 pub struct SysControlAddr(pub libc::sockaddr_ctl);
1099
1100 impl SysControlAddr {
1101 pub const fn new(id: u32, unit: u32) -> SysControlAddr {
1102 let addr = libc::sockaddr_ctl {
1103 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
1104 sc_family: AddressFamily::System as c_uchar,
1105 ss_sysaddr: libc::AF_SYS_CONTROL as u16,
1106 sc_id: id,
1107 sc_unit: unit,
1108 sc_reserved: [0; 5]
1109 };
1110
1111 SysControlAddr(addr)
1112 }
1113
1114 pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
1115 if name.len() > MAX_KCTL_NAME {
1116 return Err(Errno::ENAMETOOLONG);
1117 }
1118
1119 let mut ctl_name = [0; MAX_KCTL_NAME];
1120 ctl_name[..name.len()].clone_from_slice(name.as_bytes());
1121 let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
1122
1123 unsafe { ctl_info(sockfd, &mut info)?; }
1124
1125 Ok(SysControlAddr::new(info.ctl_id, unit))
1126 }
1127
1128 pub const fn id(&self) -> u32 {
1129 self.0.sc_id
1130 }
1131
1132 pub const fn unit(&self) -> u32 {
1133 self.0.sc_unit
1134 }
1135 }
1136
1137 impl fmt::Display for SysControlAddr {
1138 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1139 fmt::Debug::fmt(self, f)
1140 }
1141 }
1142}
1143
1144
1145#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
1146mod datalink {
1147 use super::{fmt, AddressFamily};
1148
1149 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1151 pub struct LinkAddr(pub libc::sockaddr_ll);
1152
1153 impl LinkAddr {
1154 pub fn family(&self) -> AddressFamily {
1156 assert_eq!(self.0.sll_family as i32, libc::AF_PACKET);
1157 AddressFamily::Packet
1158 }
1159
1160 pub fn protocol(&self) -> u16 {
1162 self.0.sll_protocol
1163 }
1164
1165 pub fn ifindex(&self) -> usize {
1167 self.0.sll_ifindex as usize
1168 }
1169
1170 pub fn hatype(&self) -> u16 {
1172 self.0.sll_hatype
1173 }
1174
1175 pub fn pkttype(&self) -> u8 {
1177 self.0.sll_pkttype
1178 }
1179
1180 pub fn halen(&self) -> usize {
1182 self.0.sll_halen as usize
1183 }
1184
1185 pub fn addr(&self) -> [u8; 6] {
1187 [
1188 self.0.sll_addr[0],
1189 self.0.sll_addr[1],
1190 self.0.sll_addr[2],
1191 self.0.sll_addr[3],
1192 self.0.sll_addr[4],
1193 self.0.sll_addr[5],
1194 ]
1195 }
1196 }
1197
1198 impl fmt::Display for LinkAddr {
1199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1200 let addr = self.addr();
1201 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1202 addr[0],
1203 addr[1],
1204 addr[2],
1205 addr[3],
1206 addr[4],
1207 addr[5])
1208 }
1209 }
1210}
1211
1212#[cfg(any(target_os = "dragonfly",
1213 target_os = "freebsd",
1214 target_os = "ios",
1215 target_os = "macos",
1216 target_os = "illumos",
1217 target_os = "netbsd",
1218 target_os = "openbsd"))]
1219mod datalink {
1220 use super::{fmt, AddressFamily};
1221
1222 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1224 pub struct LinkAddr(pub libc::sockaddr_dl);
1225
1226 impl LinkAddr {
1227 #[cfg(not(target_os = "illumos"))]
1229 pub fn len(&self) -> usize {
1230 self.0.sdl_len as usize
1231 }
1232
1233 pub fn family(&self) -> AddressFamily {
1235 assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK);
1236 AddressFamily::Link
1237 }
1238
1239 pub fn ifindex(&self) -> usize {
1241 self.0.sdl_index as usize
1242 }
1243
1244 pub fn datalink_type(&self) -> u8 {
1246 self.0.sdl_type
1247 }
1248
1249 pub fn nlen(&self) -> usize {
1251 self.0.sdl_nlen as usize
1252 }
1253
1254 pub fn alen(&self) -> usize {
1256 self.0.sdl_alen as usize
1257 }
1258
1259 pub fn slen(&self) -> usize {
1261 self.0.sdl_slen as usize
1262 }
1263
1264 pub fn is_empty(&self) -> bool {
1267 let nlen = self.nlen();
1268 let alen = self.alen();
1269 let data_len = self.0.sdl_data.len();
1270
1271 alen == 0 || nlen + alen >= data_len
1272 }
1273
1274 pub fn addr(&self) -> [u8; 6] {
1276 let nlen = self.nlen();
1277 let data = self.0.sdl_data;
1278
1279 assert!(!self.is_empty());
1280
1281 [
1282 data[nlen] as u8,
1283 data[nlen + 1] as u8,
1284 data[nlen + 2] as u8,
1285 data[nlen + 3] as u8,
1286 data[nlen + 4] as u8,
1287 data[nlen + 5] as u8,
1288 ]
1289 }
1290 }
1291
1292 impl fmt::Display for LinkAddr {
1293 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1294 let addr = self.addr();
1295 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1296 addr[0],
1297 addr[1],
1298 addr[2],
1299 addr[3],
1300 addr[4],
1301 addr[5])
1302 }
1303 }
1304}
1305
1306#[cfg(any(target_os = "android", target_os = "linux"))]
1307pub mod vsock {
1308 use crate::sys::socket::addr::AddressFamily;
1309 use libc::{sa_family_t, sockaddr_vm};
1310 use std::{fmt, mem};
1311 use std::hash::{Hash, Hasher};
1312
1313 #[derive(Copy, Clone)]
1314 pub struct VsockAddr(pub sockaddr_vm);
1315
1316 impl PartialEq for VsockAddr {
1317 fn eq(&self, other: &Self) -> bool {
1318 let (inner, other) = (self.0, other.0);
1319 (inner.svm_family, inner.svm_cid, inner.svm_port) ==
1320 (other.svm_family, other.svm_cid, other.svm_port)
1321 }
1322 }
1323
1324 impl Eq for VsockAddr {}
1325
1326 impl Hash for VsockAddr {
1327 fn hash<H: Hasher>(&self, s: &mut H) {
1328 let inner = self.0;
1329 (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
1330 }
1331 }
1332
1333 impl VsockAddr {
1338 pub fn new(cid: u32, port: u32) -> VsockAddr {
1339 let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
1340 addr.svm_family = AddressFamily::Vsock as sa_family_t;
1341 addr.svm_cid = cid;
1342 addr.svm_port = port;
1343
1344 VsockAddr(addr)
1345 }
1346
1347 pub fn cid(&self) -> u32 {
1349 self.0.svm_cid
1350 }
1351
1352 pub fn port(&self) -> u32 {
1354 self.0.svm_port
1355 }
1356 }
1357
1358 impl fmt::Display for VsockAddr {
1359 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1360 write!(f, "cid: {} port: {}", self.cid(), self.port())
1361 }
1362 }
1363
1364 impl fmt::Debug for VsockAddr {
1365 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1366 fmt::Display::fmt(self, f)
1367 }
1368 }
1369}
1370
1371#[cfg(test)]
1372mod tests {
1373 #[cfg(any(target_os = "android",
1374 target_os = "dragonfly",
1375 target_os = "freebsd",
1376 target_os = "ios",
1377 target_os = "linux",
1378 target_os = "macos",
1379 target_os = "netbsd",
1380 target_os = "illumos",
1381 target_os = "openbsd"))]
1382 use super::*;
1383
1384 #[cfg(any(target_os = "dragonfly",
1385 target_os = "freebsd",
1386 target_os = "ios",
1387 target_os = "macos",
1388 target_os = "netbsd",
1389 target_os = "openbsd"))]
1390 #[test]
1391 fn test_macos_loopback_datalink_addr() {
1392 let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
1393 let sa = bytes.as_ptr() as *const libc::sockaddr;
1394 let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1395 assert!(_sock_addr.is_none());
1396 }
1397
1398 #[cfg(any(target_os = "dragonfly",
1399 target_os = "freebsd",
1400 target_os = "ios",
1401 target_os = "macos",
1402 target_os = "netbsd",
1403 target_os = "openbsd"))]
1404 #[test]
1405 fn test_macos_tap_datalink_addr() {
1406 let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
1407 let ptr = bytes.as_ptr();
1408 let sa = ptr as *const libc::sockaddr;
1409 let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1410
1411 assert!(_sock_addr.is_some());
1412
1413 let sock_addr = _sock_addr.unwrap();
1414
1415 assert_eq!(sock_addr.family(), AddressFamily::Link);
1416
1417 match sock_addr {
1418 SockAddr::Link(ether_addr) => {
1419 assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
1420 },
1421 _ => { unreachable!() }
1422 };
1423 }
1424
1425 #[cfg(target_os = "illumos")]
1426 #[test]
1427 fn test_illumos_tap_datalink_addr() {
1428 let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
1429 let ptr = bytes.as_ptr();
1430 let sa = ptr as *const libc::sockaddr;
1431 let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1432
1433 assert!(_sock_addr.is_some());
1434
1435 let sock_addr = _sock_addr.unwrap();
1436
1437 assert_eq!(sock_addr.family(), AddressFamily::Link);
1438
1439 match sock_addr {
1440 SockAddr::Link(ether_addr) => {
1441 assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
1442 },
1443 _ => { unreachable!() }
1444 };
1445 }
1446
1447 #[cfg(any(target_os = "android", target_os = "linux"))]
1448 #[test]
1449 fn test_abstract_sun_path() {
1450 let name = String::from("nix\0abstract\0test");
1451 let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
1452
1453 let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
1454 let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
1455 assert_eq!(sun_path1, sun_path2);
1456 }
1457}