Skip to content

Commit

Permalink
Merge branch 'master' into mprotect
Browse files Browse the repository at this point in the history
  • Loading branch information
acfoltzer authored Dec 6, 2018
2 parents 0778851 + 5a3ac8d commit b65cd61
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 16 deletions.
4 changes: 4 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]
### Added
- Added support of CString type in `setsockopt`.
([#972](https://github.com/nix-rust/nix/pull/972))
- Added option `TCP_CONGESTION` in `setsockopt`.
([#972](https://github.com/nix-rust/nix/pull/972))
- Added an `mprotect` wrapper.
([#991](https://github.com/nix-rust/nix/pull/991))
### Changed
Expand Down
19 changes: 3 additions & 16 deletions src/errno.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[cfg(not(target_os = "dragonfly"))]
use libc;
use libc::c_int;
use libc::{c_int, c_void};
use std::{fmt, io, error};
use {Error, Result};

Expand Down Expand Up @@ -103,8 +103,8 @@ impl ErrnoSentinel for i64 {
fn sentinel() -> Self { -1 }
}

impl ErrnoSentinel for *mut libc::c_void {
fn sentinel() -> Self { (-1 as isize) as *mut libc::c_void }
impl ErrnoSentinel for *mut c_void {
fn sentinel() -> Self { (-1 as isize) as *mut c_void }
}

impl error::Error for Errno {
Expand Down Expand Up @@ -521,9 +521,6 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(target_os = "openbsd")]
EIPSEC => "IPsec processing failure",

#[cfg(target_os = "dragonfly")]
EUNUSED94 | EUNUSED95 | EUNUSED96 | EUNUSED97 | EUNUSED98 => "Unused",

#[cfg(target_os = "dragonfly")]
EASYNC => "Async",
}
Expand Down Expand Up @@ -1373,11 +1370,6 @@ mod consts {
ENOLINK = libc::ENOLINK,
EPROTO = libc::EPROTO,
ENOMEDIUM = libc::ENOMEDIUM,
EUNUSED94 = libc::EUNUSED94,
EUNUSED95 = libc::EUNUSED95,
EUNUSED96 = libc::EUNUSED96,
EUNUSED97 = libc::EUNUSED97,
EUNUSED98 = libc::EUNUSED98,
EASYNC = libc::EASYNC,
}

Expand Down Expand Up @@ -1485,11 +1477,6 @@ mod consts {
libc::ENOLINK => ENOLINK,
libc::EPROTO => EPROTO,
libc::ENOMEDIUM => ENOMEDIUM,
libc::EUNUSED94 => EUNUSED94,
libc::EUNUSED95 => EUNUSED95,
libc::EUNUSED96 => EUNUSED96,
libc::EUNUSED97 => EUNUSED97,
libc::EUNUSED98 => EUNUSED98,
libc::EASYNC => EASYNC,
_ => UnknownErrno,
}
Expand Down
61 changes: 61 additions & 0 deletions src/sys/socket/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ use sys::time::TimeVal;
use libc::{self, c_int, uint8_t, c_void, socklen_t};
use std::mem;
use std::os::unix::io::RawFd;
use std::ffi::{OsStr, OsString};
#[cfg(target_family = "unix")]
use std::os::unix::ffi::OsStrExt;

// Constants
// TCP_CA_NAME_MAX isn't defined in user space include files
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
const TCP_CA_NAME_MAX: usize = 16;

/// Helper for implementing `SetSockOpt` for a given socket option. See
/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
Expand Down Expand Up @@ -152,6 +160,10 @@ macro_rules! sockopt_impl {
sockopt_impl!(Both, $name, $level, $flag, usize, GetUsize, SetUsize);
};

(Both, $name:ident, $level:path, $flag:path, OsString<$array:ty>) => {
sockopt_impl!(Both, $name, $level, $flag, OsString, GetOsString<$array>, SetOsString);
};

/*
* Matchers with generic getter types must be placed at the end, so
* they'll only match _after_ specialized matchers fail
Expand Down Expand Up @@ -257,6 +269,8 @@ sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(Both, PassCred, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
sockopt_impl!(Both, TcpCongestion, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>);

/*
*
Expand Down Expand Up @@ -478,6 +492,53 @@ unsafe impl<'a> Set<'a, usize> for SetUsize {
}
}

/// Getter for a `OsString` value.
struct GetOsString<T: AsMut<[u8]>> {
len: socklen_t,
val: T,
}

unsafe impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
unsafe fn blank() -> Self {
GetOsString {
len: mem::size_of::<T>() as socklen_t,
val: mem::zeroed(),
}
}

fn ffi_ptr(&mut self) -> *mut c_void {
&mut self.val as *mut T as *mut c_void
}

fn ffi_len(&mut self) -> *mut socklen_t {
&mut self.len
}

unsafe fn unwrap(mut self) -> OsString {
OsStr::from_bytes(self.val.as_mut()).to_owned()
}
}

/// Setter for a `OsString` value.
struct SetOsString<'a> {
val: &'a OsStr,
}

unsafe impl<'a> Set<'a, OsString> for SetOsString<'a> {
fn new(val: &'a OsString) -> SetOsString {
SetOsString { val: val.as_os_str() }
}

fn ffi_ptr(&self) -> *const c_void {
self.val.as_bytes().as_ptr() as *const c_void
}

fn ffi_len(&self) -> socklen_t {
self.val.len() as socklen_t
}
}


#[cfg(test)]
mod test {
#[cfg(any(target_os = "android", target_os = "linux"))]
Expand Down
25 changes: 25 additions & 0 deletions test/sys/test_sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,28 @@ fn test_so_buf() {
let actual = getsockopt(fd, sockopt::RcvBuf).unwrap();
assert!(actual >= bufsize);
}

// The CI doesn't supported getsockopt and setsockopt on emulated processors.
// It's beleived that a QEMU issue, the tests run ok on a fully emulated system.
// Current CI just run the binary with QEMU but the Kernel remains the same as the host.
// So the syscall doesn't work properly unless the kernel is also emulated.
#[test]
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
any(target_os = "freebsd", target_os = "linux")
))]
fn test_tcp_congestion() {
use std::ffi::OsString;

let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();

let val = getsockopt(fd, sockopt::TcpCongestion).unwrap();
setsockopt(fd, sockopt::TcpCongestion, &val).unwrap();

setsockopt(fd, sockopt::TcpCongestion, &OsString::from("tcp_congestion_does_not_exist")).unwrap_err();

assert_eq!(
getsockopt(fd, sockopt::TcpCongestion).unwrap(),
val
);
}

0 comments on commit b65cd61

Please sign in to comment.