summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md6
-rw-r--r--src/sys/event.rs55
-rw-r--r--src/sys/ioctl/mod.rs107
-rw-r--r--src/sys/ioctl/platform/bsd.rs36
-rw-r--r--src/sys/ioctl/platform/dragonfly.rs0
-rw-r--r--src/sys/ioctl/platform/freebsd.rs0
-rw-r--r--src/sys/ioctl/platform/ios.rs0
-rw-r--r--src/sys/ioctl/platform/linux.rs72
-rw-r--r--src/sys/ioctl/platform/macos.rs0
-rw-r--r--src/sys/ioctl/platform/netbsd.rs0
-rw-r--r--src/sys/ioctl/platform/openbsd.rs0
-rw-r--r--src/sys/mod.rs2
-rw-r--r--src/sys/socket/addr.rs122
-rw-r--r--src/sys/socket/consts.rs7
-rw-r--r--test/sys/test_ioctl.rs123
-rw-r--r--test/sys/test_socket.rs17
16 files changed, 387 insertions, 160 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 23519334..6ff9cf7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
@@ -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
diff --git a/src/sys/event.rs b/src/sys/event.rs
index 0ada5bd6..405f38fc 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -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;
@@ -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,
@@ -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;
@@ -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,
@@ -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,
@@ -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,
@@ -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,
}
@@ -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"))]
diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs
index 4d4d1072..a04e9d39 100644
--- a/src/sys/ioctl/mod.rs
+++ b/src/sys/ioctl/mod.rs
@@ -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
@@ -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;
@@ -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))
+ }
+ );
+}
diff --git a/src/sys/ioctl/platform/bsd.rs b/src/sys/ioctl/platform/bsd.rs
new file mode 100644
index 00000000..57b4d637
--- /dev/null
+++ b/src/sys/ioctl/platform/bsd.rs
@@ -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))
+}
diff --git a/src/sys/ioctl/platform/dragonfly.rs b/src/sys/ioctl/platform/dragonfly.rs
deleted file mode 100644
index e69de29b..00000000
--- a/src/sys/ioctl/platform/dragonfly.rs
+++ /dev/null
diff --git a/src/sys/ioctl/platform/freebsd.rs b/src/sys/ioctl/platform/freebsd.rs
deleted file mode 100644
index e69de29b..00000000
--- a/src/sys/ioctl/platform/freebsd.rs
+++ /dev/null
diff --git a/src/sys/ioctl/platform/ios.rs b/src/sys/ioctl/platform/ios.rs
deleted file mode 100644
index e69de29b..00000000
--- a/src/sys/ioctl/platform/ios.rs
+++ /dev/null
diff --git a/src/sys/ioctl/platform/linux.rs b/src/sys/ioctl/platform/linux.rs
index 60311224..aacea459 100644
--- a/src/sys/ioctl/platform/linux.rs
+++ b/src/sys/ioctl/platform/linux.rs
@@ -77,78 +77,6 @@ macro_rules! iorw {
($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz))
}
-/// Convert raw ioctl return value to a Nix result
-#[macro_export]
-macro_rules! convert_ioctl_res {
- ($w:expr) => (
- {
- $crate::Errno::result($w)
- }
- );
-}
-
-/// Declare a wrapper function around an ioctl.
-#[macro_export]
-macro_rules! ioctl {
- (bad $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: *const $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))
- }
- );
-}
-
/// Extracts the "direction" (read/write/none) from an encoded ioctl command.
#[inline(always)]
pub fn ioc_dir(nr: u32) -> u8 {
diff --git a/src/sys/ioctl/platform/macos.rs b/src/sys/ioctl/platform/macos.rs
deleted file mode 100644
index e69de29b..00000000
--- a/src/sys/ioctl/platform/macos.rs
+++ /dev/null
diff --git a/src/sys/ioctl/platform/netbsd.rs b/src/sys/ioctl/platform/netbsd.rs
deleted file mode 100644
index e69de29b..00000000
--- a/src/sys/ioctl/platform/netbsd.rs
+++ /dev/null
diff --git a/src/sys/ioctl/platform/openbsd.rs b/src/sys/ioctl/platform/openbsd.rs
deleted file mode 100644
index e69de29b..00000000
--- a/src/sys/ioctl/platform/openbsd.rs
+++ /dev/null
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 793bc70e..706614dc 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -12,7 +12,7 @@ pub mod eventfd;
#[cfg(target_os = "linux")]
pub mod memfd;
-#[cfg(not(any(target_os = "ios", target_os = "freebsd", target_os = "dragonfly")))]
+#[macro_use]
pub mod ioctl;
#[cfg(any(target_os = "linux", target_os = "android"))]
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index 756ae345..5f8b130a 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -7,6 +7,10 @@ use std::path::Path;
use std::os::unix::ffi::OsStrExt;
#[cfg(any(target_os = "linux", target_os = "android"))]
use ::sys::socket::addr::netlink::NetlinkAddr;
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+use std::os::unix::io::RawFd;
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+use ::sys::socket::addr::sys_control::SysControlAddr;
// TODO: uncomment out IpAddr functions: rust-lang/rfcs#988
@@ -26,6 +30,8 @@ pub enum AddressFamily {
Netlink = consts::AF_NETLINK,
#[cfg(any(target_os = "linux", target_os = "android"))]
Packet = consts::AF_PACKET,
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ System = consts::AF_SYSTEM,
}
#[derive(Copy)]
@@ -475,7 +481,9 @@ pub enum SockAddr {
Inet(InetAddr),
Unix(UnixAddr),
#[cfg(any(target_os = "linux", target_os = "android"))]
- Netlink(NetlinkAddr)
+ Netlink(NetlinkAddr),
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ SysControl(SysControlAddr),
}
impl SockAddr {
@@ -492,6 +500,11 @@ impl SockAddr {
SockAddr::Netlink(NetlinkAddr::new(pid, groups))
}
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
+ SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
+ }
+
pub fn family(&self) -> AddressFamily {
match *self {
SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
@@ -499,6 +512,8 @@ impl SockAddr {
SockAddr::Unix(..) => AddressFamily::Unix,
#[cfg(any(target_os = "linux", target_os = "android"))]
SockAddr::Netlink(..) => AddressFamily::Netlink,
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ SockAddr::SysControl(..) => AddressFamily::System,
}
}
@@ -513,6 +528,8 @@ impl SockAddr {
SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t),
#[cfg(any(target_os = "linux", target_os = "android"))]
SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<sys_control::sockaddr_ctl>() as libc::socklen_t),
}
}
}
@@ -545,6 +562,8 @@ impl hash::Hash for SockAddr {
SockAddr::Unix(ref a) => a.hash(s),
#[cfg(any(target_os = "linux", target_os = "android"))]
SockAddr::Netlink(ref a) => a.hash(s),
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ SockAddr::SysControl(ref a) => a.hash(s),
}
}
}
@@ -562,6 +581,8 @@ impl fmt::Display for SockAddr {
SockAddr::Unix(ref unix) => unix.fmt(f),
#[cfg(any(target_os = "linux", target_os = "android"))]
SockAddr::Netlink(ref nl) => nl.fmt(f),
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ SockAddr::SysControl(ref sc) => sc.fmt(f),
}
}
}
@@ -620,3 +641,102 @@ pub mod netlink {
}
}
}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+pub mod sys_control {
+ use ::sys::socket::consts;
+ use ::sys::socket::addr::{AddressFamily};
+ use libc::{c_uchar, uint16_t, uint32_t};
+ use std::{fmt, mem};
+ use std::hash::{Hash, Hasher};
+ use std::os::unix::io::RawFd;
+ use {Errno, Error, Result};
+
+ #[repr(C)]
+ pub struct ctl_ioc_info {
+ pub ctl_id: uint32_t,
+ pub ctl_name: [c_uchar; MAX_KCTL_NAME],
+ }
+
+ const CTL_IOC_MAGIC: u8 = 'N' as u8;
+ const CTL_IOC_INFO: u8 = 3;
+ const MAX_KCTL_NAME: usize = 96;
+
+ ioctl!(readwrite ctl_info with CTL_IOC_MAGIC, CTL_IOC_INFO; ctl_ioc_info);
+
+ #[repr(C)]
+ #[derive(Copy, Clone)]
+ pub struct sockaddr_ctl {
+ pub sc_len: c_uchar,
+ pub sc_family: c_uchar,
+ pub ss_sysaddr: uint16_t,
+ pub sc_id: uint32_t,
+ pub sc_unit: uint32_t,
+ pub sc_reserved: [uint32_t; 5],
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct SysControlAddr(pub sockaddr_ctl);
+
+ // , PartialEq, Eq, Debug, Hash
+ impl PartialEq for SysControlAddr {
+ fn eq(&self, other: &Self) -> bool {
+ let (inner, other) = (self.0, other.0);
+ (inner.sc_id, inner.sc_unit) ==
+ (other.sc_id, other.sc_unit)
+ }
+ }
+
+ impl Eq for SysControlAddr {}
+
+ impl Hash for SysControlAddr {
+ fn hash<H: Hasher>(&self, s: &mut H) {
+ let inner = self.0;
+ (inner.sc_id, inner.sc_unit).hash(s);
+ }
+ }
+
+
+ impl SysControlAddr {
+ pub fn new(id: u32, unit: u32) -> SysControlAddr {
+ let addr = sockaddr_ctl {
+ sc_len: mem::size_of::<sockaddr_ctl>() as c_uchar,
+ sc_family: AddressFamily::System as c_uchar,
+ ss_sysaddr: consts::AF_SYS_CONTROL as uint16_t,
+ sc_id: id,
+ sc_unit: unit,
+ sc_reserved: [0; 5]
+ };
+
+ SysControlAddr(addr)
+ }
+
+ pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
+ if name.len() > MAX_KCTL_NAME {
+ return Err(Error::Sys(Errno::ENAMETOOLONG));
+ }
+
+ let mut ctl_name = [0; MAX_KCTL_NAME];
+ ctl_name[..name.len()].clone_from_slice(name.as_bytes());
+ let mut info = ctl_ioc_info { ctl_id: 0, ctl_name: ctl_name };
+
+ unsafe { try!(ctl_info(sockfd, &mut info)); }
+
+ Ok(SysControlAddr::new(info.ctl_id, unit))
+ }
+
+ pub fn id(&self) -> u32 {
+ self.0.sc_id
+ }
+
+ pub fn unit(&self) -> u32 {
+ self.0.sc_unit
+ }
+ }
+
+ impl fmt::Display for SysControlAddr {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "id: {} unit: {}", self.id(), self.unit())
+ }
+ }
+}
diff --git a/src/sys/socket/consts.rs b/src/sys/socket/consts.rs
index 63eaf28a..3c5efdf7 100644
--- a/src/sys/socket/consts.rs
+++ b/src/sys/socket/consts.rs
@@ -132,6 +132,11 @@ mod os {
pub const AF_INET6: c_int = 28;
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub const AF_INET6: c_int = 30;
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ pub const AF_SYSTEM: c_int = 32;
+
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ pub const AF_SYS_CONTROL: c_int = 2;
pub const SOCK_STREAM: c_int = 1;
pub const SOCK_DGRAM: c_int = 2;
@@ -144,6 +149,8 @@ mod os {
pub const IPPROTO_IPV6: c_int = 41;
pub const IPPROTO_TCP: c_int = 6;
pub const IPPROTO_UDP: c_int = 17;
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ pub const SYSPROTO_CONTROL: c_int = 2;
pub const SO_ACCEPTCONN: c_int = 0x0002;
pub const SO_BROADCAST: c_int = 0x0020;
diff --git a/test/sys/test_ioctl.rs b/test/sys/test_ioctl.rs
index 94eca447..1d9fbcc8 100644
--- a/test/sys/test_ioctl.rs
+++ b/test/sys/test_ioctl.rs
@@ -1,9 +1,7 @@
#![allow(dead_code)]
-#![cfg(target_os = "linux")] // no ioctl support for osx yet
-
// Simple tests to ensure macro generated fns compile
-ioctl!(bad do_bad with 0x1234);
+ioctl!(do_bad with 0x1234);
ioctl!(none do_none with 0, 0);
ioctl!(read read_test with 0, 0; u32);
ioctl!(write write_test with 0, 0; u64);
@@ -15,44 +13,97 @@ ioctl!(readwrite buf readwritebuf_test with 0, 0; u32);
// See C code for source of values for op calculations:
// https://gist.github.com/posborne/83ea6880770a1aef332e
-#[test]
-fn test_op_none() {
- assert_eq!(io!(b'q', 10), 0x0000710A);
- assert_eq!(io!(b'a', 255), 0x000061FF);
-}
+#[cfg(any(target_os = "linux", target_os = "android"))]
+mod linux {
+ #[test]
+ fn test_op_none() {
+ assert_eq!(io!(b'q', 10), 0x0000710A);
+ assert_eq!(io!(b'a', 255), 0x000061FF);
+ }
-#[test]
-fn test_op_write() {
- assert_eq!(iow!(b'z', 10, 1), 0x40017A0A);
- assert_eq!(iow!(b'z', 10, 512), 0x42007A0A);
-}
+ #[test]
+ fn test_op_write() {
+ assert_eq!(iow!(b'z', 10, 1), 0x40017A0A);
+ assert_eq!(iow!(b'z', 10, 512), 0x42007A0A);
+ }
-#[cfg(target_pointer_width = "64")]
-#[test]
-fn test_op_write_64() {
- assert_eq!(iow!(b'z', 10, (1 as u64) << 32), 0x40007A0A);
-}
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_op_write_64() {
+ assert_eq!(iow!(b'z', 10, (1 as u64) << 32), 0x40007A0A);
+ }
-#[test]
-fn test_op_read() {
- assert_eq!(ior!(b'z', 10, 1), 0x80017A0A);
- assert_eq!(ior!(b'z', 10, 512), 0x82007A0A);
-}
+ #[test]
+ fn test_op_read() {
+ assert_eq!(ior!(b'z', 10, 1), 0x80017A0A);
+ assert_eq!(ior!(b'z', 10, 512), 0x82007A0A);
+ }
-#[cfg(target_pointer_width = "64")]
-#[test]
-fn test_op_read_64() {
- assert_eq!(ior!(b'z', 10, (1 as u64) << 32), 0x80007A0A);
-}
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_op_read_64() {
+ assert_eq!(ior!(b'z', 10, (1 as u64) << 32), 0x80007A0A);
+ }
+
+ #[test]
+ fn test_op_read_write() {
+ assert_eq!(iorw!(b'z', 10, 1), 0xC0017A0A);
+ assert_eq!(iorw!(b'z', 10, 512), 0xC2007A0A);
+ }
-#[test]
-fn test_op_read_write() {
- assert_eq!(iorw!(b'z', 10, 1), 0xC0017A0A);
- assert_eq!(iorw!(b'z', 10, 512), 0xC2007A0A);
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_op_read_write_64() {
+ assert_eq!(iorw!(b'z', 10, (1 as u64) << 32), 0xC0007A0A);
+ }
}
-#[cfg(target_pointer_width = "64")]
-#[test]
-fn test_op_read_write_64() {
- assert_eq!(iorw!(b'z', 10, (1 as u64) << 32), 0xC0007A0A);
+#[cfg(any(target_os = "macos",
+ target_os = "ios",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "freebsd",
+ target_os = "dragonfly"))]
+mod bsd {
+ #[test]
+ fn test_op_none() {
+ assert_eq!(io!(b'q', 10), 0x2000710A);
+ assert_eq!(io!(b'a', 255), 0x200061FF);
+ }
+
+ #[test]
+ fn test_op_write() {
+ assert_eq!(iow!(b'z', 10, 1), 0x80017A0A);
+ assert_eq!(iow!(b'z', 10, 512), 0x82007A0A);
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_op_write_64() {
+ assert_eq!(iow!(b'z', 10, (1 as u64) << 32), 0x80007A0A);
+ }
+
+ #[test]
+ fn test_op_read() {
+ assert_eq!(ior!(b'z', 10, 1), 0x40017A0A);
+ assert_eq!(ior!(b'z', 10, 512), 0x42007A0A);
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_op_read_64() {
+ assert_eq!(ior!(b'z', 10, (1 as u64) << 32), 0x40007A0A);
+ }
+
+ #[test]
+ fn test_op_read_write() {
+ assert_eq!(iorw!(b'z', 10, 1), 0xC0017A0A);
+ assert_eq!(iorw!(b'z', 10, 512), 0xC2007A0A);
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_op_read_write_64() {
+ assert_eq!(iorw!(b'z', 10, (1 as u64) << 32), 0xC0007A0A);
+ }
}
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 9f4b4278..b5465aa0 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -180,3 +180,20 @@ pub fn test_unixdomain() {
assert_eq!(&buf[..], b"hello");
}
+
+// Test creating and using named system control sockets
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[test]
+pub fn test_syscontrol() {
+ use nix::{Errno, Error};
+ use nix::sys::socket::{AddressFamily, SockType, SockFlag};
+ use nix::sys::socket::{socket, SockAddr};
+ use nix::sys::socket::SYSPROTO_CONTROL;
+
+ let fd = socket(AddressFamily::System, SockType::Datagram, SockFlag::empty(), SYSPROTO_CONTROL).expect("socket failed");
+ let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed");
+ assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Error::Sys(Errno::ENOENT)));
+
+ // requires root privileges
+ // connect(fd, &sockaddr).expect("connect failed");
+}