Skip to content
Closed
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
### Removed

## [0.19.1] - 28 November 2020
### Fixed

- Fixed bugs in `recvmmsg`.
(#[1341](https://github.com/nix-rust/nix/pull/1341))

## [0.19.0] - 6 October 2020
### Added
- Added Netlink protocol families to the `SockProtocol` enum
Expand Down
17 changes: 15 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "nix"
description = "Rust friendly bindings to *nix APIs"
edition = "2018"
version = "0.19.0"
version = "0.19.1"
authors = ["The nix-rust Project Developers"]
repository = "https://github.com/nix-rust/nix"
license = "MIT"
Expand All @@ -16,10 +16,23 @@ exclude = [
"/bors.toml"
]

[package.metadata.docs.rs]
targets = [
"x86_64-unknown-linux-gnu",
"aarch64-linux-android",
"x86_64-apple-darwin",
"aarch64-apple-ios",
"x86_64-unknown-freebsd",
"x86_64-unknown-openbsd",
"x86_64-unknown-netbsd",
"x86_64-unknown-dragonfly",
"x86_64-unknown-redox"
]

[dependencies]
libc = { version = "0.2.78", features = [ "extra_traits" ] }
bitflags = "1.1"
cfg-if = "0.1.10"
cfg-if = "1.0"

[target.'cfg(target_os = "dragonfly")'.build-dependencies]
cc = "1"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ To use `nix`, add this to your `Cargo.toml`:

```toml
[dependencies]
nix = "0.19.0"
nix = "0.19.1"
```

## Contributing
Expand Down
10 changes: 6 additions & 4 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,12 +847,13 @@ impl<'a> ControlMessage<'a> {
}
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetIv(iv) => {
#[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
let af_alg_iv = libc::af_alg_iv {
ivlen: iv.len() as u32,
iv: [0u8; 0],
};

let size = mem::size_of::<libc::af_alg_iv>();
let size = mem::size_of_val(&af_alg_iv);

unsafe {
ptr::copy_nonoverlapping(
Expand Down Expand Up @@ -915,7 +916,7 @@ impl<'a> ControlMessage<'a> {
}
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetIv(iv) => {
mem::size_of::<libc::af_alg_iv>() + iv.len()
mem::size_of_val(&iv) + iv.len()
},
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetOp(op) => {
Expand Down Expand Up @@ -1216,17 +1217,18 @@ pub fn recvmmsg<'a, I>(

let ret = unsafe { libc::recvmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _, timeout) };

let r = Errno::result(ret)?;
let _ = Errno::result(ret)?;

Ok(output
.into_iter()
.take(ret as usize)
.zip(addresses.iter().map(|addr| unsafe{addr.assume_init()}))
.zip(results.into_iter())
.map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| {
unsafe {
read_mhdr(
mmsghdr.msg_hdr,
r as isize,
mmsghdr.msg_len as isize,
msg_controllen,
address,
cmsg_buffer
Expand Down
2 changes: 2 additions & 0 deletions src/sys/socket/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,9 @@ sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
target_os = "linux",
target_os = "nacl"))]
sockopt_impl!(Both, TcpKeepIdle, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
#[cfg(not(target_os = "openbsd"))]
sockopt_impl!(Both, TcpKeepCount, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32);
#[cfg(not(target_os = "openbsd"))]
sockopt_impl!(Both, TcpKeepInterval, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32);
sockopt_impl!(Both, RcvBuf, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
sockopt_impl!(Both, SndBuf, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
Expand Down
9 changes: 9 additions & 0 deletions src/sys/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{cmp, fmt, ops};
use std::time::Duration;
use std::convert::From;
use libc::{c_long, timespec, timeval};
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
pub use libc::{time_t, suseconds_t};

pub trait TimeValLike: Sized {
Expand Down Expand Up @@ -69,6 +70,7 @@ impl From<timespec> for TimeSpec {

impl From<Duration> for TimeSpec {
fn from(duration: Duration) -> Self {
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
TimeSpec(timespec {
tv_sec: duration.as_secs() as time_t,
tv_nsec: duration.subsec_nanos() as c_long
Expand Down Expand Up @@ -117,6 +119,7 @@ impl TimeValLike for TimeSpec {
fn seconds(seconds: i64) -> TimeSpec {
assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS,
"TimeSpec out of bounds; seconds={}", seconds);
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 })
}

Expand All @@ -143,6 +146,7 @@ impl TimeValLike for TimeSpec {
let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC);
assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS,
"TimeSpec out of bounds");
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
TimeSpec(timespec {tv_sec: secs as time_t,
tv_nsec: nanos as c_long })
}
Expand Down Expand Up @@ -179,6 +183,7 @@ impl TimeSpec {
}
}

#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
pub fn tv_sec(&self) -> time_t {
self.0.tv_sec
}
Expand Down Expand Up @@ -315,6 +320,7 @@ impl TimeValLike for TimeVal {
fn seconds(seconds: i64) -> TimeVal {
assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS,
"TimeVal out of bounds; seconds={}", seconds);
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 })
}

Expand All @@ -332,6 +338,7 @@ impl TimeValLike for TimeVal {
let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
"TimeVal out of bounds");
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
TimeVal(timeval {tv_sec: secs as time_t,
tv_usec: micros as suseconds_t })
}
Expand All @@ -344,6 +351,7 @@ impl TimeValLike for TimeVal {
let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
"TimeVal out of bounds");
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
TimeVal(timeval {tv_sec: secs as time_t,
tv_usec: micros as suseconds_t })
}
Expand Down Expand Up @@ -380,6 +388,7 @@ impl TimeVal {
}
}

#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
pub fn tv_sec(&self) -> time_t {
self.0.tv_sec
}
Expand Down
70 changes: 70 additions & 0 deletions test/sys/test_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,76 @@ mod recvfrom {

send_thread.join().unwrap();
}

#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "freebsd",
target_os = "netbsd",
))]
#[test]
pub fn udp_recvmmsg_dontwait_short_read() {
use nix::sys::uio::IoVec;
use nix::sys::socket::{MsgFlags, recvmmsg};

const NUM_MESSAGES_SENT: usize = 2;
const DATA: [u8; 4] = [1,2,3,4];

let std_sa = SocketAddr::from_str("127.0.0.1:6799").unwrap();
let inet_addr = InetAddr::from_std(&std_sa);
let sock_addr = SockAddr::new_inet(inet_addr);

let rsock = socket(AddressFamily::Inet,
SockType::Datagram,
SockFlag::empty(),
None
).unwrap();
bind(rsock, &sock_addr).unwrap();
let ssock = socket(
AddressFamily::Inet,
SockType::Datagram,
SockFlag::empty(),
None,
).expect("send socket failed");

let send_thread = thread::spawn(move || {
for _ in 0..NUM_MESSAGES_SENT {
sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap();
}
});
// Ensure we've sent all the messages before continuing so `recvmmsg`
// will return right away
send_thread.join().unwrap();

let mut msgs = std::collections::LinkedList::new();

// Buffers to receive >`NUM_MESSAGES_SENT` messages to ensure `recvmmsg`
// will return when there are fewer than requested messages in the
// kernel buffers when using `MSG_DONTWAIT`.
let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2];
let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| {
[IoVec::from_mut_slice(&mut buf[..])]
}).collect();

for iov in &iovs {
msgs.push_back(RecvMmsgData {
iov: iov,
cmsg_buffer: None,
})
};

let res = recvmmsg(rsock, &mut msgs, MsgFlags::MSG_DONTWAIT, None).expect("recvmmsg");
assert_eq!(res.len(), NUM_MESSAGES_SENT);

for RecvMsg { address, bytes, .. } in res.into_iter() {
assert_eq!(AddressFamily::Inet, address.unwrap().family());
assert_eq!(DATA.len(), bytes);
}

for buf in &receive_buffers[..NUM_MESSAGES_SENT] {
assert_eq!(&buf[..DATA.len()], DATA);
}
}
}

// Test error handling of our recvmsg wrapper
Expand Down
2 changes: 1 addition & 1 deletion test/test_unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ cfg_if!{
"./sh", AtFlags::empty());
execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
"/system/bin/sh", AtFlags::empty());
} else if #[cfg(all(target_os = "linux"), any(target_arch ="x86_64", target_arch ="x86"))] {
} else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] {
use nix::fcntl::AtFlags;
execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(),
"", AtFlags::AT_EMPTY_PATH);
Expand Down