Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,9 @@ impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> {
/// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name`
/// and `namelen` on Windows.
pub fn with_addr(mut self, addr: &'addr SockAddr) -> Self {
sys::set_msghdr_name(&mut self.inner, addr);
// SAFETY: we're casting a const pointer to a mut pointer only to assign
// it, this type doesn't use the pointer mutably.
sys::set_msghdr_name(&mut self.inner, addr.as_ptr().cast_mut(), addr.len());
self
}

Expand Down Expand Up @@ -697,9 +699,8 @@ impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> {
///
/// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name`
/// and `namelen` on Windows.
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn with_addr(mut self, addr: &'addr mut SockAddr) -> Self {
sys::set_msghdr_name(&mut self.inner, addr);
sys::set_msghdr_name(&mut self.inner, addr.as_mut_ptr(), addr.len());
self
}

Expand Down Expand Up @@ -745,3 +746,33 @@ impl<'name, 'bufs, 'control> fmt::Debug for MsgHdrMut<'name, 'bufs, 'control> {

#[cfg(not(any(target_os = "redox", target_os = "wasi", target_os = "horizon")))]
unsafe impl Send for MsgHdrMut<'_, '_, '_> {}

#[test]
#[cfg(not(any(target_os = "redox", target_os = "wasi", target_os = "horizon")))]
fn regression_673() {
// NOTE: ideally this would be moved into the tests directory, but at the
// time of writing Miri doesn't support recvmsg.

use std::mem::MaybeUninit;
use std::net::{Ipv4Addr, SocketAddrV4};

use crate::sys::sockaddr;
use crate::{MaybeUninitSlice, SockAddr};

let mut addr = SockAddr::from(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80));
let mut buf = [MaybeUninit::new(0); 8];
let mut bufs = [MaybeUninitSlice::new(&mut buf)];

let hdr = MsgHdrMut::new()
.with_addr(&mut addr)
.with_buffers(&mut bufs);

// Mimic what recvmsg(2) does, write to the address.
#[cfg(windows)]
let name = hdr.inner.name as *mut sockaddr;
#[cfg(not(windows))]
let name = hdr.inner.msg_name as *mut sockaddr;
unsafe { (*name).sa_family = 255 }; // Family.

assert_eq!(addr.family(), 255);
}
5 changes: 5 additions & 0 deletions src/sockaddr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ impl SockAddr {
&self.storage as *const sockaddr_storage as *const SockAddrStorage
}

/// Returns a raw mutable pointer to the address.
pub fn as_mut_ptr(&mut self) -> *mut SockAddrStorage {
&mut self.storage as *mut sockaddr_storage as *mut SockAddrStorage
}

/// Returns the address as the storage.
pub const fn as_storage(self) -> SockAddrStorage {
SockAddrStorage {
Expand Down
6 changes: 3 additions & 3 deletions src/sys/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,9 +825,9 @@ pub(crate) fn iucv_sockaddr(userid: &str, name: &str) -> io::Result<SockAddr> {
pub(crate) use libc::msghdr;

#[cfg(not(any(target_os = "redox", target_os = "wasi", target_os = "horizon")))]
pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: &SockAddr) {
msg.msg_name = name.as_ptr() as *mut _;
msg.msg_namelen = name.len();
pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: *mut SockAddrStorage, name_len: socklen_t) {
msg.msg_name = name as *mut _;
msg.msg_namelen = name_len;
}

#[cfg(not(any(target_os = "redox", target_os = "wasi", target_os = "horizon")))]
Expand Down
6 changes: 3 additions & 3 deletions src/sys/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,9 @@ impl<'a> MaybeUninitSlice<'a> {
// Used in `MsgHdr`.
pub(crate) use windows_sys::Win32::Networking::WinSock::WSAMSG as msghdr;

pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: &SockAddr) {
msg.name = name.as_ptr() as *mut _;
msg.namelen = name.len();
pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: *mut SockAddrStorage, name_len: socklen_t) {
msg.name = name as *mut _;
msg.namelen = name_len;
}

pub(crate) fn set_msghdr_iov(msg: &mut msghdr, ptr: *mut WSABUF, len: usize) {
Expand Down
Loading