Skip to content

Commit b5627a2

Browse files
committed
Convert SockAddr -> SocketAddrV* safely
1 parent 7c25373 commit b5627a2

File tree

1 file changed

+24
-15
lines changed

1 file changed

+24
-15
lines changed

src/sockaddr.rs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt;
22
use std::mem::{self, MaybeUninit};
3-
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
3+
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
44
use std::ptr;
55

66
#[cfg(any(unix, target_os = "redox"))]
@@ -124,33 +124,42 @@ impl SockAddr {
124124
}
125125
}
126126

127-
unsafe fn as_<T>(&self, family: sa_family_t) -> Option<T> {
128-
if self.storage.ss_family != family {
129-
return None;
130-
}
131-
132-
Some(mem::transmute_copy(&self.storage))
133-
}
134-
135127
/// Returns this address as a `SocketAddrV4` if it is in the `AF_INET`
136128
/// family.
137129
pub fn as_inet(&self) -> Option<SocketAddrV4> {
138-
unsafe { self.as_(AF_INET as sa_family_t) }
130+
match self.as_std() {
131+
Some(SocketAddr::V4(addr)) => Some(addr),
132+
_ => None,
133+
}
139134
}
140135

141136
/// Returns this address as a `SocketAddrV6` if it is in the `AF_INET6`
142137
/// family.
143138
pub fn as_inet6(&self) -> Option<SocketAddrV6> {
144-
unsafe { self.as_(AF_INET6 as sa_family_t) }
139+
match self.as_std() {
140+
Some(SocketAddr::V6(addr)) => Some(addr),
141+
_ => None,
142+
}
145143
}
146144

147145
/// Returns this address as a `SocketAddr` if it is in the `AF_INET`
148146
/// or `AF_INET6` family, otherwise returns `None`.
149147
pub fn as_std(&self) -> Option<SocketAddr> {
150-
if let Some(addr) = self.as_inet() {
151-
Some(SocketAddr::V4(addr))
152-
} else if let Some(addr) = self.as_inet6() {
153-
Some(SocketAddr::V6(addr))
148+
if self.storage.ss_family == AF_INET as sa_family_t {
149+
let addr = unsafe { &*(&self.storage as *const _ as *const sockaddr_in) };
150+
let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
151+
let port = u16::from_be(addr.sin_port);
152+
Some(SocketAddr::V4(SocketAddrV4::new(ip, port)))
153+
} else if self.storage.ss_family == AF_INET6 as sa_family_t {
154+
let addr = unsafe { &*(&self.storage as *const _ as *const sockaddr_in6) };
155+
let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr);
156+
let port = u16::from_be(addr.sin6_port);
157+
Some(SocketAddr::V6(SocketAddrV6::new(
158+
ip,
159+
port,
160+
addr.sin6_flowinfo,
161+
addr.sin6_scope_id,
162+
)))
154163
} else {
155164
None
156165
}

0 commit comments

Comments
 (0)