1#[macro_export]
2#[allow(unused_macros)]
8macro_rules! syscall {
9 ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
10 #[allow(clippy::macro_metavars_in_unsafe)]
11 let res = unsafe { libc::$fn($($arg, )*) };
12 if res == -1 {
13 Err(std::io::Error::last_os_error())
14 } else {
15 Ok(res)
16 }
17 }};
18}
19
20#[macro_export]
21#[allow(unused_macros)]
22macro_rules! sctp_syscall {
23 ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
24 #[allow(clippy::macro_metavars_in_unsafe)]
25 let res = unsafe { sctp_sys::$fn($($arg, )*) };
26 if res == -1 {
27 Err(std::io::Error::last_os_error())
28 } else {
29 Ok(res)
30 }
31 }};
32}
33
34use std::mem;
35use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
36
37#[repr(C)]
44pub(crate) union SocketAddrCRepr {
45 v4: libc::sockaddr_in,
46 v6: libc::sockaddr_in6,
47}
48
49impl SocketAddrCRepr {
50 pub(crate) fn as_ptr(&self) -> *const libc::sockaddr {
51 self as *const _ as *const libc::sockaddr
52 }
53}
54
55pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_t) {
57 match addr {
58 SocketAddr::V4(ref addr) => {
59 let sin_addr = libc::in_addr {
62 s_addr: u32::from_ne_bytes(addr.ip().octets()),
63 };
64
65 let sockaddr_in = libc::sockaddr_in {
66 sin_family: libc::AF_INET as libc::sa_family_t,
67 sin_port: addr.port().to_be(),
68 sin_addr,
69 sin_zero: [0; 8],
70 #[cfg(any(
71 target_os = "dragonfly",
72 target_os = "freebsd",
73 target_os = "ios",
74 target_os = "macos",
75 target_os = "netbsd",
76 target_os = "openbsd"
77 ))]
78 sin_len: 0,
79 };
80
81 let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
82 (
83 sockaddr,
84 mem::size_of::<libc::sockaddr_in>() as libc::socklen_t,
85 )
86 }
87 SocketAddr::V6(ref addr) => {
88 let sockaddr_in6 = libc::sockaddr_in6 {
89 sin6_family: libc::AF_INET6 as libc::sa_family_t,
90 sin6_port: addr.port().to_be(),
91 sin6_addr: libc::in6_addr {
92 s6_addr: addr.ip().octets(),
93 },
94 sin6_flowinfo: addr.flowinfo(),
95 sin6_scope_id: addr.scope_id(),
96 #[cfg(any(
97 target_os = "dragonfly",
98 target_os = "freebsd",
99 target_os = "ios",
100 target_os = "macos",
101 target_os = "netbsd",
102 target_os = "openbsd"
103 ))]
104 sin6_len: 0,
105 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
106 __sin6_src_id: 0,
107 };
108
109 let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 };
110 (
111 sockaddr,
112 mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t,
113 )
114 }
115 }
116}
117
118pub(crate) unsafe fn to_socket_addr(
125 storage: *const libc::sockaddr_storage,
126) -> std::io::Result<SocketAddr> {
127 match (*storage).ss_family as libc::c_int {
128 libc::AF_INET => {
129 let addr: &libc::sockaddr_in = &*(storage as *const libc::sockaddr_in);
131 let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
132 let port = u16::from_be(addr.sin_port);
133 Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)))
134 }
135 libc::AF_INET6 => {
136 let addr: &libc::sockaddr_in6 = &*(storage as *const libc::sockaddr_in6);
138 let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr);
139 let port = u16::from_be(addr.sin6_port);
140 Ok(SocketAddr::V6(SocketAddrV6::new(
141 ip,
142 port,
143 addr.sin6_flowinfo,
144 addr.sin6_scope_id,
145 )))
146 }
147 _ => Err(std::io::ErrorKind::InvalidInput.into()),
148 }
149}
150