Skip to content

Commit

Permalink
Auto merge of #478 - conradev:sys-control, r=fiveop
Browse files Browse the repository at this point in the history
Add support for system control sockets for XNU

I added support for macOS and iOS system sockets, which can be used to control the kernel as described [here](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html).

To do this, I had to add in support for `ioctl` on those platforms, so I added in `ioctl` support for all BSD-based platforms. The API seems to be the same between [xnu](https://opensource.apple.com/source/xnu/xnu-3248.60.10/bsd/sys/ioccom.h.auto.html), [FreeBSD](https://github.com/freebsd/freebsd/blob/master/sys/sys/ioccom.h), [NetBSD](https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/sys/ioccom.h), [OpenBSD](http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/sys/ioccom.h?rev=1.5&content-type=text/x-cvsweb-markup) and [Dragonfly BSD](http://gitweb.dragonflybsd.org/dragonfly.git/blob/HEAD:/sys/sys/ioccom.h).

I added a test that runs on macOS and iOS for the functionality. Let me know if I need to make any changes!
  • Loading branch information
homu committed Dec 16, 2016
2 parents 5e932dc + ef257e0 commit 9b81000
Show file tree
Hide file tree
Showing 16 changed files with 387 additions and 160 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]

### Added
- Added support for XNU system control sockets
([#478](https://github.com/nix-rust/nix/pull/478))
- Added support for `ioctl` calls on BSD platforms
([#478](https://github.com/nix-rust/nix/pull/478))
- Added struct `TimeSpec`
([#475](https://github.com/nix-rust/nix/pull/475))
- Added complete definitions for all kqueue-related constants on all supported
Expand All @@ -26,6 +30,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#491](https://github.com/nix-rust/nix/pull/491))

### Changed
- Removed the `bad` keyword from the `ioctl!` macro
([#478](https://github.com/nix-rust/nix/pull/478))
- Changed `TimeVal` into an opaque Newtype
([#475](https://github.com/nix-rust/nix/pull/475))
- `kill`'s signature, defined in `::nix::sys::signal`, changed, so that the
Expand Down
55 changes: 33 additions & 22 deletions src/sys/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ pub struct KEvent {
}

#[cfg(any(target_os = "openbsd", target_os = "freebsd",
target_os = "dragonfly", target_os = "macos"))]
target_os = "dragonfly", target_os = "macos",
target_os = "ios"))]
type type_of_udata = *mut ::c_void;
#[cfg(any(target_os = "netbsd"))]
type type_of_udata = intptr_t;
Expand All @@ -33,23 +34,24 @@ pub enum EventFilter {
EVFILT_AIO = libc::EVFILT_AIO,
#[cfg(target_os = "dragonfly")]
EVFILT_EXCEPT = libc::EVFILT_EXCEPT,
#[cfg(any(target_os = "macos",
#[cfg(any(target_os = "macos", target_os = "ios",
target_os = "dragonfly",
target_os = "freebsd"))]
EVFILT_FS = libc::EVFILT_FS,
#[cfg(target_os = "freebsd")]
EVFILT_LIO = libc::EVFILT_LIO,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
EVFILT_MACHPORT = libc::EVFILT_MACHPORT,
EVFILT_PROC = libc::EVFILT_PROC,
EVFILT_READ = libc::EVFILT_READ,
EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
EVFILT_TIMER = libc::EVFILT_TIMER,
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "dragonfly",
target_os = "freebsd"))]
EVFILT_USER = libc::EVFILT_USER,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
EVFILT_VM = libc::EVFILT_VM,
EVFILT_VNODE = libc::EVFILT_VNODE,
EVFILT_WRITE = libc::EVFILT_WRITE,
Expand All @@ -70,7 +72,8 @@ pub enum EventFilter {
EVFILT_TIMER = libc::EVFILT_TIMER,
}

#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly"))]
#[cfg(any(target_os = "macos", target_os = "ios",
target_os = "freebsd", target_os = "dragonfly"))]
pub type type_of_event_flag = u16;
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
pub type type_of_event_flag = u32;
Expand All @@ -86,15 +89,15 @@ libc_bitflags!{
EV_ENABLE,
EV_EOF,
EV_ERROR,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
EV_FLAG0,
EV_FLAG1,
#[cfg(target_os = "dragonfly")]
EV_NODATA,
EV_ONESHOT,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
EV_OOBAND,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
EV_POLL,
#[cfg(not(target_os = "openbsd"))]
EV_RECEIPT,
Expand All @@ -104,7 +107,7 @@ libc_bitflags!{

bitflags!(
flags FilterFlag: u32 {
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_ABSOLUTE = libc::NOTE_ABSOLUTE,
const NOTE_ATTRIB = libc::NOTE_ATTRIB,
const NOTE_CHILD = libc::NOTE_CHILD,
Expand All @@ -113,32 +116,38 @@ bitflags!(
const NOTE_EOF = libc::NOTE_EOF,
const NOTE_EXEC = libc::NOTE_EXEC,
const NOTE_EXIT = libc::NOTE_EXIT,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_EXIT_REPARENTED = libc::NOTE_EXIT_REPARENTED,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_EXITSTATUS = libc::NOTE_EXITSTATUS,
const NOTE_EXTEND = libc::NOTE_EXTEND,
#[cfg(any(target_os = "macos",
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
const NOTE_FFAND = libc::NOTE_FFAND,
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
const NOTE_FFCOPY = libc::NOTE_FFCOPY,
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
const NOTE_FFCTRLMASK = libc::NOTE_FFCTRLMASK,
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
const NOTE_FFLAGSMASK = libc::NOTE_FFLAGSMASK,
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
const NOTE_FFNOP = libc::NOTE_FFNOP,
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
const NOTE_FFOR = libc::NOTE_FFOR,
Expand All @@ -147,39 +156,40 @@ bitflags!(
const NOTE_LOWAT = libc::NOTE_LOWAT,
#[cfg(target_os = "freebsd")]
const NOTE_MSECONDS = libc::NOTE_MSECONDS,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_NONE = libc::NOTE_NONE,
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
const NOTE_NSECONDS = libc::NOTE_NSECONDS,
#[cfg(target_os = "dragonfly")]
const NOTE_OOB = libc::NOTE_OOB,
const NOTE_PCTRLMASK = libc::NOTE_PCTRLMASK,
const NOTE_PDATAMASK = libc::NOTE_PDATAMASK,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_REAP = libc::NOTE_REAP,
const NOTE_RENAME = libc::NOTE_RENAME,
const NOTE_REVOKE = libc::NOTE_REVOKE,
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
const NOTE_SECONDS = libc::NOTE_SECONDS,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_SIGNAL = libc::NOTE_SIGNAL,
const NOTE_TRACK = libc::NOTE_TRACK,
const NOTE_TRACKERR = libc::NOTE_TRACKERR,
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
const NOTE_TRIGGER = libc::NOTE_TRIGGER,
#[cfg(target_os = "openbsd")]
const NOTE_TRUNCATE = libc::NOTE_TRUNCATE,
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
const NOTE_USECONDS = libc::NOTE_USECONDS,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_VM_ERROR = libc::NOTE_VM_ERROR,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_VM_PRESSURE = libc::NOTE_VM_PRESSURE,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_VM_PRESSURE_SUDDEN_TERMINATE = libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
const NOTE_VM_PRESSURE_TERMINATE = libc::NOTE_VM_PRESSURE_TERMINATE,
const NOTE_WRITE = libc::NOTE_WRITE,
}
Expand Down Expand Up @@ -251,6 +261,7 @@ pub fn kevent(kq: RawFd,
}

#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd"))]
Expand Down
107 changes: 79 additions & 28 deletions src/sys/ioctl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
//! How do I get the magic numbers?
//! ===============================
//!
//! For Linux, look at your system's headers. For example, `/usr/include/linxu/input.h` has a lot
//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
//! of lines defining macros which use `_IOR`, `_IOW`, `_IOC`, and `_IORW`. These macros
//! correspond to the `ior!`, `iow!`, `ioc!`, and `iorw!` macros defined in this crate.
//! Additionally, there is the `ioctl!` macro for creating a wrapper around `ioctl` that is
Expand All @@ -104,33 +104,13 @@
#[macro_use]
mod platform;

#[cfg(target_os = "macos")]
#[path = "platform/macos.rs"]
#[macro_use]
mod platform;

#[cfg(target_os = "ios")]
#[path = "platform/ios.rs"]
#[macro_use]
mod platform;

#[cfg(target_os = "freebsd")]
#[path = "platform/freebsd.rs"]
#[macro_use]
mod platform;

#[cfg(target_os = "netbsd")]
#[path = "platform/netbsd.rs"]
#[macro_use]
mod platform;

#[cfg(target_os = "openbsd")]
#[path = "platform/openbsd.rs"]
#[macro_use]
mod platform;

#[cfg(target_os = "dragonfly")]
#[path = "platform/dragonfly.rs"]
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "netbsd",
target_os = "openbsd",
target_os = "freebsd",
target_os = "dragonfly"))]
#[path = "platform/bsd.rs"]
#[macro_use]
mod platform;

Expand All @@ -145,3 +125,74 @@ extern "C" {
/// A hack to get the macros to work nicely.
#[doc(hidden)]
pub use ::libc as libc;

/// Convert raw ioctl return value to a Nix result
#[macro_export]
macro_rules! convert_ioctl_res {
($w:expr) => (
{
$crate::Errno::result($w)
}
);
}

#[macro_export]
macro_rules! ioctl {
($name:ident with $nr:expr) => (
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
data: *mut u8)
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, $nr as $crate::sys::ioctl::libc::c_ulong, data))
}
);
(none $name:ident with $ioty:expr, $nr:expr) => (
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int)
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, io!($ioty, $nr) as $crate::sys::ioctl::libc::c_ulong))
}
);
(read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
val: *mut $ty)
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
}
);
(write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
val: *const $ty)
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
}
);
(readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
val: *mut $ty)
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
}
);
(read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
val: *mut $ty,
len: usize)
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
}
);
(write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
val: *const $ty,
len: usize) -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
}
);
(readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
val: *mut $ty,
len: usize)
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
}
);
}
36 changes: 36 additions & 0 deletions src/sys/ioctl/platform/bsd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
mod consts {
pub const VOID: u32 = 0x20000000;
pub const OUT: u32 = 0x40000000;
pub const IN: u32 = 0x80000000;
pub const INOUT: u32 = (IN|OUT);
pub const IOCPARM_MASK: u32 = 0x1fff;
}

pub use self::consts::*;

#[macro_export]
macro_rules! ioc {
($inout:expr, $group:expr, $num:expr, $len:expr) => (
$inout | (($len as u32 & $crate::sys::ioctl::IOCPARM_MASK) << 16) | (($group as u32) << 8) | ($num as u32)
)
}

#[macro_export]
macro_rules! io {
($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0))
}

#[macro_export]
macro_rules! ior {
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::OUT, $g, $n, $len))
}

#[macro_export]
macro_rules! iow {
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::IN, $g, $n, $len))
}

#[macro_export]
macro_rules! iorw {
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::INOUT, $g, $n, $len))
}
Empty file.
Empty file removed src/sys/ioctl/platform/freebsd.rs
Empty file.
Empty file removed src/sys/ioctl/platform/ios.rs
Empty file.
Loading

0 comments on commit 9b81000

Please sign in to comment.