Skip to content

Commit

Permalink
Add new linux symbol for multicast-all
Browse files Browse the repository at this point in the history
unistd: Increase maximum passwd/group buffer to 1MB

We have one UNIX group that contains most of our users whose size is
about 20 kB, so `Group::from_name` is failing with ERANGE.

The discussion on PR nix-rust#864 suggests that 1 MB is a reasonable maximum -
it follows what FreeBSD's libc does. (glibc appears to have no maximum
on the _r function and will just double the buffer until malloc fails,
but that's not particularly Rusty.)

Use memoffset::offset_of instead of homegrown macro

The homegrown macro was fine in 2016, but at some point it technically
became UB.  The memoffset crate does the same thing, but avoids UB when
using rustc 1.51.0 or later.

Fixes nix-rust#1415

Check all tests in CI

Travis didn't compile check tests on platforms that couldn't run tests
in CI, so they bitrotted.  Let's see how bad they are.

Most annoyingly, 32-bit Android defines mode_t as 16 bits, but
stat.st_mode as 32-bits.

Fix spurious errors using `sendmmsg` with multiple cmsgs

Before this fix, the buffer that holds cmsgs may move due to the resize()
call. That causes msg_hdr pointing to invalid memory, which ends up
breaking the sendmmsg() call, resulting in EINVAL.

This change fixes it by avoiding re-allocating the buffers.

Support TIMESTAMPNS for linux

unistd: Increase maximum passwd/group buffer to 1MB

We have one UNIX group that contains most of our users whose size is
about 20 kB, so `Group::from_name` is failing with ERANGE.

The discussion on PR nix-rust#864 suggests that 1 MB is a reasonable maximum -
it follows what FreeBSD's libc does. (glibc appears to have no maximum
on the _r function and will just double the buffer until malloc fails,
but that's not particularly Rusty.)

Use memoffset::offset_of instead of homegrown macro

The homegrown macro was fine in 2016, but at some point it technically
became UB.  The memoffset crate does the same thing, but avoids UB when
using rustc 1.51.0 or later.

Fixes nix-rust#1415

Check all tests in CI

Travis didn't compile check tests on platforms that couldn't run tests
in CI, so they bitrotted.  Let's see how bad they are.

Most annoyingly, 32-bit Android defines mode_t as 16 bits, but
stat.st_mode as 32-bits.

Fix spurious errors using `sendmmsg` with multiple cmsgs

Before this fix, the buffer that holds cmsgs may move due to the resize()
call. That causes msg_hdr pointing to invalid memory, which ends up
breaking the sendmmsg() call, resulting in EINVAL.

This change fixes it by avoiding re-allocating the buffers.

Support TIMESTAMPNS for linux

fix bug missing octothorpe
  • Loading branch information
anth1y committed Apr 17, 2021
1 parent 6af11c1 commit e2e344b
Show file tree
Hide file tree
Showing 13 changed files with 513 additions and 162 deletions.
7 changes: 2 additions & 5 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ task:
- cargo test --target i686-unknown-freebsd
before_cache_script: rm -rf $CARGO_HOME/registry/index

# Test OSX and iOS in a full VM
task:
matrix:
- name: OSX x86_64
Expand Down Expand Up @@ -162,24 +163,20 @@ task:
- name: Linux x32
env:
TARGET: x86_64-unknown-linux-gnux32
CHECK_TESTS: true
- name: NetBSD x86_64
env:
TARGET: x86_64-unknown-netbsd
- name: Fuchsia x86_64
env:
TARGET: x86_64-fuchsia
CHECK_TESTS: true
container:
image: rust:1.40
setup_script:
- rustup target add $TARGET
script:
- cargo +$TOOLCHAIN check --target $TARGET
- cargo +$TOOLCHAIN check --target $TARGET --release
- 'if [ "$CHECK_TESTS" == true ]; then cargo +$TOOLCHAIN check --all-targets --target $TARGET; fi'
# TODO: check the tests, too. The old Travis CI setup didn't do that, so
# they don't build on all platforms.
- cargo +$TOOLCHAIN check --all-targets --target $TARGET
before_cache_script: rm -rf $CARGO_HOME/registry/index

# illumos toolchain isn't available via rustup until 1.50
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased] - ReleaseDate
### Added
- Add new symbol for linux IP_MULTICAST_ALL
(#[]())
- Added TIMESTAMPNS support for linux
(#[1402](https://github.com/nix-rust/nix/pull/1402))

### Changed
- Made `forkpty` unsafe, like `fork`
Expand All @@ -13,6 +17,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Allow `sockaddr_ll` size, as reported by the Linux kernel, to be smaller then it's definition
(#[1395](https://github.com/nix-rust/nix/pull/1395))
- Fix spurious errors using `sendmmsg` with multiple cmsgs
(#[1414](https://github.com/nix-rust/nix/pull/1414))

### Removed

Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ targets = [
]

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

[target.'cfg(not(target_os = "redox"))'.dependencies]
memoffset = "0.6.3"

[target.'cfg(target_os = "dragonfly")'.build-dependencies]
cc = "1"

Expand Down
13 changes: 0 additions & 13 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,3 @@ macro_rules! libc_enum {
}
};
}

/// A Rust version of the familiar C `offset_of` macro. It returns the byte
/// offset of `field` within struct `ty`
#[cfg(not(target_os = "redox"))]
macro_rules! offset_of {
($ty:ty, $field:ident) => {{
// Safe because we don't actually read from the dereferenced pointer
#[allow(unused_unsafe)] // for when the macro is used in an unsafe block
unsafe {
&(*(ptr::null() as *const $ty)).$field as *const _ as usize
}
}}
}
1 change: 1 addition & 0 deletions src/sys/socket/addr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::sa_family_t;
use crate::{Error, Result, NixPath};
use crate::errno::Errno;
use memoffset::offset_of;
use std::{fmt, mem, net, ptr, slice};
use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
Expand Down
24 changes: 18 additions & 6 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use cfg_if::cfg_if;
use crate::{Error, Result, errno::Errno};
use libc::{self, c_void, c_int, iovec, socklen_t, size_t,
CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN};
use memoffset::offset_of;
use std::{mem, ptr, slice};
use std::os::unix::io::RawFd;
#[cfg(all(target_os = "linux"))]
use crate::sys::time::TimeSpec;
use crate::sys::time::TimeVal;
use crate::sys::uio::IoVec;

Expand Down Expand Up @@ -554,6 +557,11 @@ pub enum ControlMessageOwned {
/// # }
/// ```
ScmTimestamp(TimeVal),
/// Nanoseconds resolution timestamp
///
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
#[cfg(all(target_os = "linux"))]
ScmTimestampns(TimeSpec),
#[cfg(any(
target_os = "android",
target_os = "ios",
Expand Down Expand Up @@ -645,6 +653,11 @@ impl ControlMessageOwned {
let tv: libc::timeval = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
},
#[cfg(all(target_os = "linux"))]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
let ts: libc::timespec = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
}
#[cfg(any(
target_os = "android",
target_os = "freebsd",
Expand Down Expand Up @@ -1101,23 +1114,22 @@ pub fn sendmmsg<'a, I, C>(

let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);

let mut cmsgs_buffer = vec![0u8; 0];
let mut cmsgs_buffers = Vec::<Vec<u8>>::with_capacity(reserve_items);

for d in iter {
let cmsgs_start = cmsgs_buffer.len();
let cmsgs_required_capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
let cmsgs_buffer_need_capacity = cmsgs_start + cmsgs_required_capacity;
cmsgs_buffer.resize(cmsgs_buffer_need_capacity, 0);
let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
let mut cmsgs_buffer = vec![0u8; capacity];

output.push(libc::mmsghdr {
msg_hdr: pack_mhdr_to_send(
&mut cmsgs_buffer[cmsgs_start..],
&mut cmsgs_buffer,
&d.iov,
&d.cmsgs,
d.addr.as_ref()
),
msg_len: 0,
});
cmsgs_buffers.push(cmsgs_buffer);
};

let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
Expand Down
Loading

0 comments on commit e2e344b

Please sign in to comment.