1use crate::types::AddressFamily;
2use std::ffi::{c_char, CStr};
3use std::mem;
4use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
5use std::os::raw::c_int;
6use std::str;
7
8pub fn address_family(family: c_types::ADDRESS_FAMILY) -> Option<AddressFamily> {
10 match family {
11 c_types::AF_INET => Some(AddressFamily::INET),
12 c_types::AF_INET6 => Some(AddressFamily::INET6),
13 c_types::AF_UNSPEC => Some(AddressFamily::UNSPEC),
14 _ => None,
15 }
16}
17
18#[cfg(unix)]
20pub fn ipv4_as_in_addr(ipv4: Ipv4Addr) -> c_types::in_addr {
21 c_types::in_addr {
22 s_addr: u32::from(ipv4).to_be(),
23 }
24}
25
26#[cfg(windows)]
27pub fn ipv4_as_in_addr(ipv4: Ipv4Addr) -> c_types::in_addr {
28 let octets = ipv4.octets();
29 let mut in_addr: c_types::in_addr = unsafe { mem::zeroed() };
30 in_addr.S_un.S_un_b.s_b1 = octets[0];
31 in_addr.S_un.S_un_b.s_b2 = octets[1];
32 in_addr.S_un.S_un_b.s_b3 = octets[2];
33 in_addr.S_un.S_un_b.s_b4 = octets[3];
34 in_addr
35}
36
37#[cfg(unix)]
39pub fn ipv4_from_in_addr(in_addr: c_types::in_addr) -> Ipv4Addr {
40 Ipv4Addr::from(u32::from_be(in_addr.s_addr))
41}
42
43#[cfg(windows)]
44pub fn ipv4_from_in_addr(in_addr: c_types::in_addr) -> Ipv4Addr {
45 let bytes = unsafe { in_addr.S_un.S_un_b };
46 Ipv4Addr::new(bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4)
47}
48
49#[cfg(unix)]
51pub fn ipv6_as_in6_addr(ipv6: &Ipv6Addr) -> c_types::in6_addr {
52 let octets = ipv6.octets();
53 let mut in6_addr: c_types::in6_addr = unsafe { mem::zeroed() };
54 in6_addr.s6_addr.copy_from_slice(&octets);
55 in6_addr
56}
57
58#[cfg(windows)]
59pub fn ipv6_as_in6_addr(ipv6: &Ipv6Addr) -> c_types::in6_addr {
60 let octets = ipv6.octets();
61 let mut in6_addr: c_types::in6_addr = unsafe { mem::zeroed() };
62 unsafe { in6_addr.u.Byte.copy_from_slice(&octets) }
63 in6_addr
64}
65
66#[cfg(any(
68 target_os = "macos",
69 target_os = "ios",
70 target_os = "freebsd",
71 target_os = "dragonfly",
72 target_os = "openbsd",
73 target_os = "netbsd",
74))]
75pub fn socket_addrv4_as_sockaddr_in(sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
76 let in_addr = ipv4_as_in_addr(*sock_v4.ip());
77 c_types::sockaddr_in {
78 sin_len: mem::size_of::<c_types::sockaddr_in>() as u8,
79 sin_family: c_types::AF_INET as c_types::sa_family_t,
80 sin_port: sock_v4.port().to_be(),
81 sin_addr: in_addr,
82 sin_zero: [0; 8],
83 }
84}
85
86#[cfg(not(any(
87 target_os = "macos",
88 target_os = "ios",
89 target_os = "freebsd",
90 target_os = "dragonfly",
91 target_os = "openbsd",
92 target_os = "netbsd",
93)))]
94pub fn socket_addrv4_as_sockaddr_in(sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
95 let in_addr = ipv4_as_in_addr(*sock_v4.ip());
96 c_types::sockaddr_in {
97 sin_family: c_types::AF_INET as c_types::sa_family_t,
98 sin_port: sock_v4.port().to_be(),
99 sin_addr: in_addr,
100 sin_zero: [0; 8],
101 }
102}
103
104#[cfg(any(
106 target_os = "macos",
107 target_os = "ios",
108 target_os = "freebsd",
109 target_os = "dragonfly",
110 target_os = "openbsd",
111 target_os = "netbsd",
112))]
113pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
114 let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
115 c_types::sockaddr_in6 {
116 sin6_len: mem::size_of::<c_types::sockaddr_in6>() as u8,
117 sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
118 sin6_port: sock_v6.port().to_be(),
119 sin6_addr: in6_addr,
120 sin6_flowinfo: sock_v6.flowinfo(),
121 sin6_scope_id: sock_v6.scope_id(),
122 }
123}
124
125#[cfg(all(
126 unix,
127 not(any(
128 target_os = "macos",
129 target_os = "ios",
130 target_os = "freebsd",
131 target_os = "dragonfly",
132 target_os = "openbsd",
133 target_os = "netbsd",
134 ))
135))]
136pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
137 let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
138 c_types::sockaddr_in6 {
139 sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
140 sin6_port: sock_v6.port().to_be(),
141 sin6_addr: in6_addr,
142 sin6_flowinfo: sock_v6.flowinfo(),
143 sin6_scope_id: sock_v6.scope_id(),
144 }
145}
146
147#[cfg(windows)]
148pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
149 let mut sockaddr_in6: c_types::sockaddr_in6 = unsafe { mem::zeroed() };
150 sockaddr_in6.sin6_family = c_types::AF_INET6 as c_types::sa_family_t;
151 sockaddr_in6.sin6_port = sock_v6.port().to_be();
152 sockaddr_in6.sin6_addr = ipv6_as_in6_addr(sock_v6.ip());
153 sockaddr_in6.sin6_flowinfo = sock_v6.flowinfo();
154 sockaddr_in6.Anonymous.sin6_scope_id = sock_v6.scope_id();
155 sockaddr_in6
156}
157
158pub unsafe fn c_string_as_str_unchecked<'a>(c_str: *const c_char) -> &'a str {
159 let bytes = unsafe { CStr::from_ptr(c_str) }.to_bytes();
160 unsafe { str::from_utf8_unchecked(bytes) }
161}
162
163#[cfg(not(cares1_30))]
164pub unsafe fn c_string_as_str_checked<'a>(c_str: *const c_char) -> &'a str {
165 let c_str = unsafe { CStr::from_ptr(c_str) };
166 c_str.to_str().unwrap()
167}
168
169#[cfg(not(cares1_17_2))]
170pub unsafe fn hostname_as_str<'a>(hostname: *const c_char) -> &'a str {
171 c_string_as_str_checked(hostname)
172}
173
174#[cfg(cares1_17_2)]
175pub unsafe fn hostname_as_str<'a>(hostname: *const c_char) -> &'a str {
176 unsafe { c_string_as_str_unchecked(hostname) }
177}
178
179#[cfg(not(cares1_30))]
180pub unsafe fn dns_string_as_str<'a>(hostname: *const c_char) -> &'a str {
181 unsafe { c_string_as_str_checked(hostname) }
182}
183
184#[cfg(cares1_30)]
185pub unsafe fn dns_string_as_str<'a>(hostname: *const c_char) -> &'a str {
186 c_string_as_str_unchecked(hostname)
187}
188
189pub fn version() -> (&'static str, u32) {
195 let mut int_version: c_int = 0;
196 let str_version = unsafe {
197 let ptr = c_ares_sys::ares_version(&mut int_version);
198 c_string_as_str_unchecked(ptr)
199 };
200 (str_version, int_version as u32)
201}
202
203#[cfg(cares1_23)]
208pub fn thread_safety() -> bool {
209 let safety = unsafe { c_ares_sys::ares_threadsafety() };
210 safety != c_ares_sys::ares_bool_t::ARES_FALSE
211}