-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Closed
Description
shadowsocks-rs
assumes that the layout of std::net::SocketAddrV{4,6}
matches libc::sockaddr
, but std
makes no such promise. See rust-lang/rust#78802 for more details.
Example fixes: tokio-rs/mio#1388, rust-lang/socket2#120.
Example occurrences of this issue in this project (probably not exhaustive):
shadowsocks-rust/crates/shadowsocks-service/src/local/redir/sys/unix/bsd_pf.rs
Lines 160 to 212 in bf409c2
match *bind_addr { | |
SocketAddr::V4(ref v4) => { | |
pnl.af = libc::AF_INET as libc::sa_family_t; | |
let sockaddr: *const libc::sockaddr_in = v4 as *const SocketAddrV4 as *const _; | |
let addr: *const libc::in_addr = &((*sockaddr).sin_addr) as *const _; | |
let port: libc::in_port_t = (*sockaddr).sin_port; | |
ptr::copy_nonoverlapping(addr, &mut pnl.daddr.pfa.v4, mem::size_of_val(&pnl.daddr.pfa.v4)); | |
pnl.set_dport(port); | |
} | |
SocketAddr::V6(ref v6) => { | |
pnl.af = libc::AF_INET6 as libc::sa_family_t; | |
let sockaddr: *const libc::sockaddr_in6 = v6 as *const SocketAddrV6 as *const _; | |
let addr: *const libc::in6_addr = &((*sockaddr).sin6_addr) as *const _; | |
let port: libc::in_port_t = (*sockaddr).sin6_port; | |
ptr::copy_nonoverlapping(addr, &mut pnl.daddr.pfa.v6, mem::size_of_val(&pnl.daddr.pfa.v6)); | |
pnl.set_dport(port); | |
} | |
} | |
match *peer_addr { | |
SocketAddr::V4(ref v4) => { | |
if pnl.af != libc::AF_INET as libc::sa_family_t { | |
return Err(Error::new(ErrorKind::InvalidInput, "client addr must be ipv4")); | |
} | |
let sockaddr: *const libc::sockaddr_in = v4 as *const SocketAddrV4 as *const _; | |
let addr: *const libc::in_addr = &((*sockaddr).sin_addr) as *const _; | |
let port: libc::in_port_t = (*sockaddr).sin_port; | |
ptr::copy_nonoverlapping(addr, &mut pnl.saddr.pfa.v4, mem::size_of_val(&pnl.saddr.pfa.v4)); | |
pnl.set_sport(port); | |
} | |
SocketAddr::V6(ref v6) => { | |
if pnl.af != libc::AF_INET6 as libc::sa_family_t { | |
return Err(Error::new(ErrorKind::InvalidInput, "client addr must be ipv6")); | |
} | |
let sockaddr: *const libc::sockaddr_in6 = v6 as *const SocketAddrV6 as *const _; | |
let addr: *const libc::in6_addr = &((*sockaddr).sin6_addr) as *const _; | |
let port: libc::in_port_t = (*sockaddr).sin6_port; | |
ptr::copy_nonoverlapping(addr, &mut pnl.saddr.pfa.v6, mem::size_of_val(&pnl.saddr.pfa.v6)); | |
pnl.set_sport(port); | |
} | |
} |
shadowsocks-rust/crates/shadowsocks/src/relay/sys/unix/mod.rs
Lines 22 to 37 in bf409c2
pub fn sockaddr_to_std(saddr: &libc::sockaddr_storage) -> io::Result<SocketAddr> { | |
match saddr.ss_family as libc::c_int { | |
libc::AF_INET => unsafe { | |
let addr: SocketAddrV4 = mem::transmute_copy(saddr); | |
Ok(SocketAddr::V4(addr)) | |
}, | |
libc::AF_INET6 => unsafe { | |
let addr: SocketAddrV6 = mem::transmute_copy(saddr); | |
Ok(SocketAddr::V6(addr)) | |
}, | |
_ => { | |
let err = Error::new(ErrorKind::InvalidData, "family must be either AF_INET or AF_INET6"); | |
Err(err) | |
} | |
} | |
} |
Metadata
Metadata
Assignees
Labels
No labels