summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
authorAlan Somers <asomers@gmail.com>2019-01-15 09:23:33 -0700
committerAlan Somers <asomers@gmail.com>2019-02-14 10:15:49 -0700
commit368b9fe9436734f7fccffa2fdf3e723ee20fb836 (patch)
tree7477402cb795d097f03c88509679d5b8b926f59a /src/sys
parented1c90d6bc9871d9881e8fcb05370752b6a5d25b (diff)
downloadnix-368b9fe9436734f7fccffa2fdf3e723ee20fb836.zip
Fix error handling of RecvMsg
There were two problems: 1) It would always return Ok, even on error 2) It could panic if there was an error, because sockaddr_storage_to_addr would be called on uninitialized memory.
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/socket/mod.rs45
1 files changed, 26 insertions, 19 deletions
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index 9527d0b3..ffb68157 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -900,6 +900,9 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
/// Receive message in scatter-gather vectors from a socket, and
/// optionally receive ancillary data into the provided buffer.
/// If no ancillary data is desired, use () as the type parameter.
+///
+/// # References
+/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
cmsg_buffer: Option<&'a mut CmsgSpace<T>>,
flags: MsgFlags) -> Result<RecvMsg<'a>>
@@ -923,26 +926,30 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
mhdr
};
- let _ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
-
- let cmsghdr = unsafe {
- if mhdr.msg_controllen > 0 {
- // got control message(s)
- debug_assert!(!mhdr.msg_control.is_null());
- debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
- CMSG_FIRSTHDR(&mhdr as *const msghdr)
- } else {
- ptr::null()
- }.as_ref()
- };
+ let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
+
+ Errno::result(ret).map(|_| {
+ let cmsghdr = unsafe {
+ if mhdr.msg_controllen > 0 {
+ // got control message(s)
+ debug_assert!(!mhdr.msg_control.is_null());
+ debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
+ CMSG_FIRSTHDR(&mhdr as *const msghdr)
+ } else {
+ ptr::null()
+ }.as_ref()
+ };
- Ok(unsafe { RecvMsg {
- cmsghdr,
- address: sockaddr_storage_to_addr(&address,
- mhdr.msg_namelen as usize).ok(),
- flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
- mhdr,
- } })
+ let address = unsafe {
+ sockaddr_storage_to_addr(&address, mhdr.msg_namelen as usize).ok()
+ };
+ RecvMsg {
+ cmsghdr,
+ address,
+ flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
+ mhdr,
+ }
+ })
}