From bb0f3b10074d7e170475d05a56fa40d6549e622b Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 25 Jan 2021 18:36:53 +0100 Subject: [PATCH] Don't assume representation of SocketAddr --- quinn/Cargo.toml | 1 + quinn/src/platform/unix.rs | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/quinn/Cargo.toml b/quinn/Cargo.toml index f7eb4c3155..01ff0f18c9 100644 --- a/quinn/Cargo.toml +++ b/quinn/Cargo.toml @@ -27,6 +27,7 @@ codecov = { repository = "djc/quinn" } maintenance = { status = "experimental" } [dependencies] +socket2 = "0.3" bytes = "1" futures = "0.3.8" libc = "0.2.69" diff --git a/quinn/src/platform/unix.rs b/quinn/src/platform/unix.rs index 5eb1a41a84..8cf0edf11c 100644 --- a/quinn/src/platform/unix.rs +++ b/quinn/src/platform/unix.rs @@ -198,9 +198,18 @@ fn send(io: &mio::net::UdpSocket, transmits: &[Transmit]) -> io::Result { let mut msgs: [libc::mmsghdr; BATCH_SIZE] = unsafe { mem::zeroed() }; let mut iovecs: [libc::iovec; BATCH_SIZE] = unsafe { mem::zeroed() }; let mut cmsgs = [cmsg::Aligned([0u8; CMSG_LEN]); BATCH_SIZE]; + let mut addrs: [MaybeUninit; BATCH_SIZE] = unsafe { + MaybeUninit::uninit().assume_init() + }; for (i, transmit) in transmits.iter().enumerate().take(BATCH_SIZE) { + let dest_addr = unsafe { + std::ptr::write(addrs[i].as_mut_ptr(), + socket2::SockAddr::from(transmit.destination)); + &mut *(&mut addrs[i] as * mut _ as * mut _) + }; prepare_msg( transmit, + dest_addr, &mut msgs[i].msg_hdr, &mut iovecs[i], &mut cmsgs[i], @@ -233,7 +242,8 @@ fn send(io: &mio::net::UdpSocket, transmits: &[Transmit]) -> io::Result { let mut ctrl = cmsg::Aligned([0u8; CMSG_LEN]); let mut sent = 0; while sent < transmits.len() { - prepare_msg(&transmits[sent], &mut hdr, &mut iov, &mut ctrl); + let addr = socket2::SockAddr::from(transmits[sent].destination); + prepare_msg(&transmits[sent], &addr, &mut hdr, &mut iov, &mut ctrl); let n = unsafe { libc::sendmsg(io.as_raw_fd(), &hdr, 0) }; if n == -1 { let e = io::Error::last_os_error(); @@ -340,6 +350,7 @@ fn in_addr(addr: &Ipv4Addr) -> libc::in_addr { fn prepare_msg( transmit: &Transmit, + dest_addr: &socket2::SockAddr, hdr: &mut libc::msghdr, iov: &mut libc::iovec, ctrl: &mut cmsg::Aligned<[u8; CMSG_LEN]>, @@ -347,12 +358,14 @@ fn prepare_msg( iov.iov_base = transmit.contents.as_ptr() as *const _ as *mut _; iov.iov_len = transmit.contents.len(); - let (name, namelen) = match transmit.destination { - SocketAddr::V4(ref addr) => (addr as *const _ as _, mem::size_of::()), - SocketAddr::V6(ref addr) => (addr as *const _ as _, mem::size_of::()), - }; - hdr.msg_name = name; - hdr.msg_namelen = namelen as _; + // SAFETY: Casting the pointer to a mutable one is legal, + // as sendmsg is guaranteed to not alter the mutable pointer. + // The type is only mutable in the first place because it is reused + // by recvmsg as well. + let name = dest_addr.as_ptr() as * mut libc::c_void; + let namelen = dest_addr.len(); + hdr.msg_name = name as *mut _; + hdr.msg_namelen = namelen; hdr.msg_iov = iov; hdr.msg_iovlen = 1;