Skip to content

Invalid layout assumptions for std::net::SocketAddrV{4, 6} #462

Closed
@a1phyr

Description

@a1phyr

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):

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);
}
}

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions