1 use std::fmt;
2 use std::mem::{self, MaybeUninit};
3 use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
4 use std::ptr;
5 
6 #[cfg(any(unix, target_os = "redox"))]
7 use libc::{
8     in6_addr, in_addr, sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage,
9     socklen_t, AF_INET, AF_INET6,
10 };
11 #[cfg(windows)]
12 use winapi::shared::in6addr::{in6_addr_u, IN6_ADDR as in6_addr};
13 #[cfg(windows)]
14 use winapi::shared::inaddr::{in_addr_S_un, IN_ADDR as in_addr};
15 #[cfg(windows)]
16 use winapi::shared::ws2def::{
17     ADDRESS_FAMILY as sa_family_t, AF_INET, AF_INET6, SOCKADDR as sockaddr,
18     SOCKADDR_IN as sockaddr_in, SOCKADDR_STORAGE as sockaddr_storage,
19 };
20 #[cfg(windows)]
21 use winapi::shared::ws2ipdef::{SOCKADDR_IN6_LH_u, SOCKADDR_IN6_LH as sockaddr_in6};
22 #[cfg(windows)]
23 use winapi::um::ws2tcpip::socklen_t;
24 
25 /// The address of a socket.
26 ///
27 /// `SockAddr`s may be constructed directly to and from the standard library
28 /// `SocketAddr`, `SocketAddrV4`, and `SocketAddrV6` types.
29 pub struct SockAddr {
30     storage: sockaddr_storage,
31     len: socklen_t,
32 }
33 
34 impl fmt::Debug for SockAddr {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result35     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
36         let mut builder = fmt.debug_struct("SockAddr");
37         builder.field("family", &self.family());
38         if let Some(addr) = self.as_inet() {
39             builder.field("inet", &addr);
40         } else if let Some(addr) = self.as_inet6() {
41             builder.field("inet6", &addr);
42         }
43         builder.finish()
44     }
45 }
46 
47 impl SockAddr {
48     /// Constructs a `SockAddr` from its raw components.
from_raw_parts(addr: *const sockaddr, len: socklen_t) -> SockAddr49     pub unsafe fn from_raw_parts(addr: *const sockaddr, len: socklen_t) -> SockAddr {
50         let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
51         ptr::copy_nonoverlapping(
52             addr as *const _ as *const u8,
53             storage.as_mut_ptr() as *mut u8,
54             len as usize,
55         );
56 
57         SockAddr {
58             // This is safe as we written the address to `storage` above.
59             storage: storage.assume_init(),
60             len,
61         }
62     }
63 
64     /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path.
65     ///
66     /// This function is only available on Unix when the `unix` feature is
67     /// enabled.
68     ///
69     /// # Failure
70     ///
71     /// Returns an error if the path is longer than `SUN_LEN`.
72     #[cfg(all(unix, feature = "unix"))]
unix<P>(path: P) -> ::std::io::Result<SockAddr> where P: AsRef<::std::path::Path>,73     pub fn unix<P>(path: P) -> ::std::io::Result<SockAddr>
74     where
75         P: AsRef<::std::path::Path>,
76     {
77         use libc::{c_char, sockaddr_un, AF_UNIX};
78         use std::cmp::Ordering;
79         use std::io;
80         use std::os::unix::ffi::OsStrExt;
81 
82         unsafe {
83             let mut addr = mem::zeroed::<sockaddr_un>();
84             addr.sun_family = AF_UNIX as sa_family_t;
85 
86             let bytes = path.as_ref().as_os_str().as_bytes();
87 
88             match (bytes.get(0), bytes.len().cmp(&addr.sun_path.len())) {
89                 // Abstract paths don't need a null terminator
90                 (Some(&0), Ordering::Greater) => {
91                     return Err(io::Error::new(
92                         io::ErrorKind::InvalidInput,
93                         "path must be no longer than SUN_LEN",
94                     ));
95                 }
96                 (Some(&0), _) => {}
97                 (_, Ordering::Greater) | (_, Ordering::Equal) => {
98                     return Err(io::Error::new(
99                         io::ErrorKind::InvalidInput,
100                         "path must be shorter than SUN_LEN",
101                     ));
102                 }
103                 _ => {}
104             }
105 
106             for (dst, src) in addr.sun_path.iter_mut().zip(bytes) {
107                 *dst = *src as c_char;
108             }
109             // null byte for pathname is already there since we zeroed up front
110 
111             let base = &addr as *const _ as usize;
112             let path = &addr.sun_path as *const _ as usize;
113             let sun_path_offset = path - base;
114 
115             let mut len = sun_path_offset + bytes.len();
116             match bytes.get(0) {
117                 Some(&0) | None => {}
118                 Some(_) => len += 1,
119             }
120             Ok(SockAddr::from_raw_parts(
121                 &addr as *const _ as *const _,
122                 len as socklen_t,
123             ))
124         }
125     }
126 
127     /// Returns this address as a `SocketAddrV4` if it is in the `AF_INET`
128     /// family.
as_inet(&self) -> Option<SocketAddrV4>129     pub fn as_inet(&self) -> Option<SocketAddrV4> {
130         match self.as_std() {
131             Some(SocketAddr::V4(addr)) => Some(addr),
132             _ => None,
133         }
134     }
135 
136     /// Returns this address as a `SocketAddrV6` if it is in the `AF_INET6`
137     /// family.
as_inet6(&self) -> Option<SocketAddrV6>138     pub fn as_inet6(&self) -> Option<SocketAddrV6> {
139         match self.as_std() {
140             Some(SocketAddr::V6(addr)) => Some(addr),
141             _ => None,
142         }
143     }
144 
145     /// Returns this address as a `SocketAddr` if it is in the `AF_INET`
146     /// or `AF_INET6` family, otherwise returns `None`.
as_std(&self) -> Option<SocketAddr>147     pub fn as_std(&self) -> Option<SocketAddr> {
148         if self.storage.ss_family == AF_INET as sa_family_t {
149             // Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in.
150             let addr = unsafe { &*(&self.storage as *const _ as *const sockaddr_in) };
151 
152             #[cfg(unix)]
153             let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
154             #[cfg(windows)]
155             let ip = {
156                 let ip_bytes = unsafe { addr.sin_addr.S_un.S_un_b() };
157                 Ipv4Addr::from([ip_bytes.s_b1, ip_bytes.s_b2, ip_bytes.s_b3, ip_bytes.s_b4])
158             };
159             let port = u16::from_be(addr.sin_port);
160             Some(SocketAddr::V4(SocketAddrV4::new(ip, port)))
161         } else if self.storage.ss_family == AF_INET6 as sa_family_t {
162             // Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6.
163             let addr = unsafe { &*(&self.storage as *const _ as *const sockaddr_in6) };
164 
165             #[cfg(unix)]
166             let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr);
167             #[cfg(windows)]
168             let ip = Ipv6Addr::from(*unsafe { addr.sin6_addr.u.Byte() });
169             let port = u16::from_be(addr.sin6_port);
170             Some(SocketAddr::V6(SocketAddrV6::new(
171                 ip,
172                 port,
173                 addr.sin6_flowinfo,
174                 #[cfg(unix)]
175                 addr.sin6_scope_id,
176                 #[cfg(windows)]
177                 unsafe {
178                     *addr.u.sin6_scope_id()
179                 },
180             )))
181         } else {
182             None
183         }
184     }
185 
186     /// Returns this address's family.
family(&self) -> sa_family_t187     pub fn family(&self) -> sa_family_t {
188         self.storage.ss_family
189     }
190 
191     /// Returns the size of this address in bytes.
len(&self) -> socklen_t192     pub fn len(&self) -> socklen_t {
193         self.len
194     }
195 
196     /// Returns a raw pointer to the address.
as_ptr(&self) -> *const sockaddr197     pub fn as_ptr(&self) -> *const sockaddr {
198         &self.storage as *const _ as *const _
199     }
200 }
201 
202 impl From<SocketAddrV4> for SockAddr {
from(addr: SocketAddrV4) -> SockAddr203     fn from(addr: SocketAddrV4) -> SockAddr {
204         #[cfg(unix)]
205         let sin_addr = in_addr {
206             s_addr: u32::from_ne_bytes(addr.ip().octets()),
207         };
208         #[cfg(windows)]
209         let sin_addr = unsafe {
210             let mut s_un = mem::zeroed::<in_addr_S_un>();
211             *s_un.S_addr_mut() = u32::from_ne_bytes(addr.ip().octets());
212             in_addr { S_un: s_un }
213         };
214 
215         let sockaddr_in = sockaddr_in {
216             sin_family: AF_INET as sa_family_t,
217             sin_port: addr.port().to_be(),
218             sin_addr,
219             sin_zero: Default::default(),
220             #[cfg(any(
221                 target_os = "dragonfly",
222                 target_os = "freebsd",
223                 target_os = "haiku",
224                 target_os = "ios",
225                 target_os = "macos",
226                 target_os = "netbsd",
227                 target_os = "openbsd"
228             ))]
229             sin_len: 0,
230         };
231         let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
232         // Safety: A `sockaddr_in` is memory compatible with a `sockaddr_storage`
233         unsafe { (storage.as_mut_ptr() as *mut sockaddr_in).write(sockaddr_in) };
234         SockAddr {
235             storage: unsafe { storage.assume_init() },
236             len: mem::size_of::<sockaddr_in>() as socklen_t,
237         }
238     }
239 }
240 
241 impl From<SocketAddrV6> for SockAddr {
from(addr: SocketAddrV6) -> SockAddr242     fn from(addr: SocketAddrV6) -> SockAddr {
243         #[cfg(unix)]
244         let sin6_addr = in6_addr {
245             s6_addr: addr.ip().octets(),
246         };
247         #[cfg(windows)]
248         let sin6_addr = unsafe {
249             let mut u = mem::zeroed::<in6_addr_u>();
250             *u.Byte_mut() = addr.ip().octets();
251             in6_addr { u }
252         };
253         #[cfg(windows)]
254         let u = unsafe {
255             let mut u = mem::zeroed::<SOCKADDR_IN6_LH_u>();
256             *u.sin6_scope_id_mut() = addr.scope_id();
257             u
258         };
259 
260         let sockaddr_in6 = sockaddr_in6 {
261             sin6_family: AF_INET6 as sa_family_t,
262             sin6_port: addr.port().to_be(),
263             sin6_addr,
264             sin6_flowinfo: addr.flowinfo(),
265             #[cfg(unix)]
266             sin6_scope_id: addr.scope_id(),
267             #[cfg(windows)]
268             u,
269             #[cfg(any(
270                 target_os = "dragonfly",
271                 target_os = "freebsd",
272                 target_os = "haiku",
273                 target_os = "ios",
274                 target_os = "macos",
275                 target_os = "netbsd",
276                 target_os = "openbsd"
277             ))]
278             sin6_len: 0,
279             #[cfg(any(target_os = "solaris", target_os = "illumos"))]
280             __sin6_src_id: 0,
281         };
282         let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
283         // Safety: A `sockaddr_in6` is memory compatible with a `sockaddr_storage`
284         unsafe { (storage.as_mut_ptr() as *mut sockaddr_in6).write(sockaddr_in6) };
285         SockAddr {
286             storage: unsafe { storage.assume_init() },
287             len: mem::size_of::<sockaddr_in6>() as socklen_t,
288         }
289     }
290 }
291 
292 impl From<SocketAddr> for SockAddr {
from(addr: SocketAddr) -> SockAddr293     fn from(addr: SocketAddr) -> SockAddr {
294         match addr {
295             SocketAddr::V4(addr) => addr.into(),
296             SocketAddr::V6(addr) => addr.into(),
297         }
298     }
299 }
300 
301 #[cfg(test)]
302 mod test {
303     use super::*;
304 
305     #[test]
inet()306     fn inet() {
307         let raw = "127.0.0.1:80".parse::<SocketAddrV4>().unwrap();
308         let addr = SockAddr::from(raw);
309         assert!(addr.as_inet6().is_none());
310         let addr = addr.as_inet().unwrap();
311         assert_eq!(raw, addr);
312     }
313 
314     #[test]
inet6()315     fn inet6() {
316         let raw = "[2001:db8::ff00:42:8329]:80"
317             .parse::<SocketAddrV6>()
318             .unwrap();
319         let addr = SockAddr::from(raw);
320         assert!(addr.as_inet().is_none());
321         let addr = addr.as_inet6().unwrap();
322         assert_eq!(raw, addr);
323     }
324 }
325