1 use std::fmt;
2 use std::mem::{self, MaybeUninit};
3 use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
4 use std::ptr;
5 
6 #[cfg(any(unix, target_os = "redox"))]
7 use libc::{
8     sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, socklen_t, AF_INET,
9     AF_INET6,
10 };
11 #[cfg(windows)]
12 use winapi::shared::ws2def::{
13     ADDRESS_FAMILY as sa_family_t, AF_INET, AF_INET6, SOCKADDR as sockaddr,
14     SOCKADDR_IN as sockaddr_in, SOCKADDR_STORAGE as sockaddr_storage,
15 };
16 #[cfg(windows)]
17 use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH as sockaddr_in6;
18 #[cfg(windows)]
19 use winapi::um::ws2tcpip::socklen_t;
20 
21 /// The address of a socket.
22 ///
23 /// `SockAddr`s may be constructed directly to and from the standard library
24 /// `SocketAddr`, `SocketAddrV4`, and `SocketAddrV6` types.
25 pub struct SockAddr {
26     storage: sockaddr_storage,
27     len: socklen_t,
28 }
29 
30 impl fmt::Debug for SockAddr {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result31     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
32         let mut builder = fmt.debug_struct("SockAddr");
33         builder.field("family", &self.family());
34         if let Some(addr) = self.as_inet() {
35             builder.field("inet", &addr);
36         } else if let Some(addr) = self.as_inet6() {
37             builder.field("inet6", &addr);
38         }
39         builder.finish()
40     }
41 }
42 
43 impl SockAddr {
44     /// Constructs a `SockAddr` from its raw components.
from_raw_parts(addr: *const sockaddr, len: socklen_t) -> SockAddr45     pub unsafe fn from_raw_parts(addr: *const sockaddr, len: socklen_t) -> SockAddr {
46         let mut storage = MaybeUninit::<sockaddr_storage>::uninit();
47         ptr::copy_nonoverlapping(
48             addr as *const _ as *const u8,
49             &mut storage as *mut _ as *mut u8,
50             len as usize,
51         );
52 
53         SockAddr {
54             // This is safe as we written the address to `storage` above.
55             storage: storage.assume_init(),
56             len: len,
57         }
58     }
59 
60     /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path.
61     ///
62     /// This function is only available on Unix when the `unix` feature is
63     /// enabled.
64     ///
65     /// # Failure
66     ///
67     /// Returns an error if the path is longer than `SUN_LEN`.
68     #[cfg(all(unix, feature = "unix"))]
unix<P>(path: P) -> ::std::io::Result<SockAddr> where P: AsRef<::std::path::Path>,69     pub fn unix<P>(path: P) -> ::std::io::Result<SockAddr>
70     where
71         P: AsRef<::std::path::Path>,
72     {
73         use libc::{c_char, sockaddr_un, AF_UNIX};
74         use std::cmp::Ordering;
75         use std::io;
76         use std::os::unix::ffi::OsStrExt;
77 
78         unsafe {
79             let mut addr = mem::zeroed::<sockaddr_un>();
80             addr.sun_family = AF_UNIX as sa_family_t;
81 
82             let bytes = path.as_ref().as_os_str().as_bytes();
83 
84             match (bytes.get(0), bytes.len().cmp(&addr.sun_path.len())) {
85                 // Abstract paths don't need a null terminator
86                 (Some(&0), Ordering::Greater) => {
87                     return Err(io::Error::new(
88                         io::ErrorKind::InvalidInput,
89                         "path must be no longer than SUN_LEN",
90                     ));
91                 }
92                 (Some(&0), _) => {}
93                 (_, Ordering::Greater) | (_, Ordering::Equal) => {
94                     return Err(io::Error::new(
95                         io::ErrorKind::InvalidInput,
96                         "path must be shorter than SUN_LEN",
97                     ));
98                 }
99                 _ => {}
100             }
101 
102             for (dst, src) in addr.sun_path.iter_mut().zip(bytes) {
103                 *dst = *src as c_char;
104             }
105             // null byte for pathname is already there since we zeroed up front
106 
107             let base = &addr as *const _ as usize;
108             let path = &addr.sun_path as *const _ as usize;
109             let sun_path_offset = path - base;
110 
111             let mut len = sun_path_offset + bytes.len();
112             match bytes.get(0) {
113                 Some(&0) | None => {}
114                 Some(_) => len += 1,
115             }
116             Ok(SockAddr::from_raw_parts(
117                 &addr as *const _ as *const _,
118                 len as socklen_t,
119             ))
120         }
121     }
122 
as_<T>(&self, family: sa_family_t) -> Option<T>123     unsafe fn as_<T>(&self, family: sa_family_t) -> Option<T> {
124         if self.storage.ss_family != family {
125             return None;
126         }
127 
128         Some(mem::transmute_copy(&self.storage))
129     }
130 
131     /// Returns this address as a `SocketAddrV4` if it is in the `AF_INET`
132     /// family.
as_inet(&self) -> Option<SocketAddrV4>133     pub fn as_inet(&self) -> Option<SocketAddrV4> {
134         unsafe { self.as_(AF_INET as sa_family_t) }
135     }
136 
137     /// Returns this address as a `SocketAddrV6` if it is in the `AF_INET6`
138     /// family.
as_inet6(&self) -> Option<SocketAddrV6>139     pub fn as_inet6(&self) -> Option<SocketAddrV6> {
140         unsafe { self.as_(AF_INET6 as sa_family_t) }
141     }
142 
143     /// Returns this address as a `SocketAddr` if it is in the `AF_INET`
144     /// or `AF_INET6` family, otherwise returns `None`.
as_std(&self) -> Option<SocketAddr>145     pub fn as_std(&self) -> Option<SocketAddr> {
146         if let Some(addr) = self.as_inet() {
147             Some(SocketAddr::V4(addr))
148         } else if let Some(addr) = self.as_inet6() {
149             Some(SocketAddr::V6(addr))
150         } else {
151             None
152         }
153     }
154 
155     /// Returns this address's family.
family(&self) -> sa_family_t156     pub fn family(&self) -> sa_family_t {
157         self.storage.ss_family
158     }
159 
160     /// Returns the size of this address in bytes.
len(&self) -> socklen_t161     pub fn len(&self) -> socklen_t {
162         self.len
163     }
164 
165     /// Returns a raw pointer to the address.
as_ptr(&self) -> *const sockaddr166     pub fn as_ptr(&self) -> *const sockaddr {
167         &self.storage as *const _ as *const _
168     }
169 }
170 
171 // SocketAddrV4 and SocketAddrV6 are just wrappers around sockaddr_in and sockaddr_in6
172 
173 // check to make sure that the sizes at least match up
_size_checks(v4: SocketAddrV4, v6: SocketAddrV6)174 fn _size_checks(v4: SocketAddrV4, v6: SocketAddrV6) {
175     unsafe {
176         mem::transmute::<SocketAddrV4, sockaddr_in>(v4);
177         mem::transmute::<SocketAddrV6, sockaddr_in6>(v6);
178     }
179 }
180 
181 impl From<SocketAddrV4> for SockAddr {
from(addr: SocketAddrV4) -> SockAddr182     fn from(addr: SocketAddrV4) -> SockAddr {
183         unsafe {
184             SockAddr::from_raw_parts(
185                 &addr as *const _ as *const _,
186                 mem::size_of::<SocketAddrV4>() as socklen_t,
187             )
188         }
189     }
190 }
191 
192 impl From<SocketAddrV6> for SockAddr {
from(addr: SocketAddrV6) -> SockAddr193     fn from(addr: SocketAddrV6) -> SockAddr {
194         unsafe {
195             SockAddr::from_raw_parts(
196                 &addr as *const _ as *const _,
197                 mem::size_of::<SocketAddrV6>() as socklen_t,
198             )
199         }
200     }
201 }
202 
203 impl From<SocketAddr> for SockAddr {
from(addr: SocketAddr) -> SockAddr204     fn from(addr: SocketAddr) -> SockAddr {
205         match addr {
206             SocketAddr::V4(addr) => addr.into(),
207             SocketAddr::V6(addr) => addr.into(),
208         }
209     }
210 }
211 
212 #[cfg(test)]
213 mod test {
214     use super::*;
215 
216     #[test]
inet()217     fn inet() {
218         let raw = "127.0.0.1:80".parse::<SocketAddrV4>().unwrap();
219         let addr = SockAddr::from(raw);
220         assert!(addr.as_inet6().is_none());
221         let addr = addr.as_inet().unwrap();
222         assert_eq!(raw, addr);
223     }
224 
225     #[test]
inet6()226     fn inet6() {
227         let raw = "[2001:db8::ff00:42:8329]:80"
228             .parse::<SocketAddrV6>()
229             .unwrap();
230         let addr = SockAddr::from(raw);
231         assert!(addr.as_inet().is_none());
232         let addr = addr.as_inet6().unwrap();
233         assert_eq!(raw, addr);
234     }
235 }
236