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