-
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