summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--src/sys/socket/mod.rs37
-rw-r--r--src/sys/socket/sockopt.rs8
-rw-r--r--test/sys/test_socket.rs27
-rw-r--r--test/sys/test_sockopt.rs5
5 files changed, 58 insertions, 23 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cfaa95bd..d631d462 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Changed
- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
+- Changed function signature of `socket()` and `socketpair()`. The `protocol` argument
+ has changed type from `c_int` to `SockProtocol`.
+ It accepts a `None` value for default protocol that was specified with zero using `c_int`.
+ ([#647](https://github.com/nix-rust/nix/pull/647))
## [0.9.0] 2017-07-23
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index 1eb5f67f..c2e95cbb 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -60,6 +60,24 @@ pub enum SockType {
Rdm = libc::SOCK_RDM,
}
+/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
+/// to specify the protocol to use.
+#[repr(i32)]
+pub enum SockProtocol {
+ /// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
+ Tcp = libc::IPPROTO_TCP,
+ /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
+ Udp = libc::IPPROTO_UDP,
+ /// Allows applications and other KEXTs to be notified when certain kernel events occur
+ /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ KextEvent = libc::SYSPROTO_EVENT,
+ /// Allows applications to configure and control a KEXT
+ /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ KextControl = libc::SYSPROTO_CONTROL,
+}
+
bitflags!(
/// Extra flags - Supported by Linux 2.6.27, normalized on other platforms
pub struct SockFlag: c_int {
@@ -381,9 +399,20 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&
/// Create an endpoint for communication
///
+/// The `protocol` specifies a particular protocol to be used with the
+/// socket. Normally only a single protocol exists to support a
+/// particular socket type within a given protocol family, in which case
+/// protocol can be specified as `None`. However, it is possible that many
+/// protocols may exist, in which case a particular protocol must be
+/// specified in this manner.
+///
/// [Further reading](http://man7.org/linux/man-pages/man2/socket.2.html)
-pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: c_int) -> Result<RawFd> {
+pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
let mut ty = ty as c_int;
+ let protocol = match protocol.into() {
+ None => 0,
+ Some(p) => p as c_int,
+ };
let feat_atomic = features::socket_atomic_cloexec();
if feat_atomic {
@@ -409,9 +438,13 @@ pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: c_
/// Create a pair of connected sockets
///
/// [Further reading](http://man7.org/linux/man-pages/man2/socketpair.2.html)
-pub fn socketpair(domain: AddressFamily, ty: SockType, protocol: c_int,
+pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
flags: SockFlag) -> Result<(RawFd, RawFd)> {
let mut ty = ty as c_int;
+ let protocol = match protocol.into() {
+ None => 0,
+ Some(p) => p as c_int,
+ };
let feat_atomic = features::socket_atomic_cloexec();
if feat_atomic {
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs
index 9d93afc1..3c13c539 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -378,7 +378,7 @@ mod test {
fn can_get_peercred_on_unix_socket() {
use super::super::*;
- let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, 0, SockFlag::empty()).unwrap();
+ let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
let a_cred = getsockopt(a, super::PeerCredentials).unwrap();
let b_cred = getsockopt(b, super::PeerCredentials).unwrap();
assert_eq!(a_cred, b_cred);
@@ -390,7 +390,7 @@ mod test {
use super::super::*;
use ::unistd::close;
- let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, 0, SockFlag::empty()).unwrap();
+ let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
let a_type = getsockopt(a, super::SockType).unwrap();
assert!(a_type == SockType::Stream);
close(a).unwrap();
@@ -402,7 +402,7 @@ mod test {
use super::super::*;
use ::unistd::close;
- let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), 0).unwrap();
+ let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
let s_type = getsockopt(s, super::SockType).unwrap();
assert!(s_type == SockType::Datagram);
close(s).unwrap();
@@ -416,7 +416,7 @@ mod test {
use super::super::*;
use ::unistd::close;
- let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), 0).unwrap();
+ let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
let s_listening = getsockopt(s, super::AcceptConn).unwrap();
assert!(!s_listening);
listen(s, 10).unwrap();
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 9f9c9bf0..31b153dd 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -69,8 +69,8 @@ pub fn test_getsockname() {
let tempdir = TempDir::new("test_getsockname").unwrap();
let sockname = tempdir.path().join("sock");
- let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(),
- 0).expect("socket failed");
+ let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
+ .expect("socket failed");
let sockaddr = SockAddr::new_unix(&sockname).unwrap();
bind(sock, &sockaddr).expect("bind failed");
assert_eq!(sockaddr.to_str(),
@@ -82,8 +82,7 @@ pub fn test_socketpair() {
use nix::unistd::{read, write};
use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag};
- let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0,
- SockFlag::empty())
+ let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
.unwrap();
write(fd1, b"hello").unwrap();
let mut buf = [0;5];
@@ -101,8 +100,7 @@ pub fn test_scm_rights() {
ControlMessage, CmsgSpace, MsgFlags,
MSG_TRUNC, MSG_CTRUNC};
- let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0,
- SockFlag::empty())
+ let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
.unwrap();
let (r, w) = pipe().unwrap();
let mut received_r: Option<RawFd> = None;
@@ -158,8 +156,7 @@ pub fn test_sendmsg_empty_cmsgs() {
CmsgSpace, MsgFlags,
MSG_TRUNC, MSG_CTRUNC};
- let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0,
- SockFlag::empty())
+ let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
.unwrap();
{
@@ -194,14 +191,14 @@ pub fn test_unixdomain() {
let tempdir = TempDir::new("test_unixdomain").unwrap();
let sockname = tempdir.path().join("sock");
let s1 = socket(AddressFamily::Unix, SockType::Stream,
- SockFlag::empty(), 0).expect("socket failed");
+ SockFlag::empty(), None).expect("socket failed");
let sockaddr = SockAddr::new_unix(&sockname).unwrap();
bind(s1, &sockaddr).expect("bind failed");
listen(s1, 10).expect("listen failed");
let thr = thread::spawn(move || {
- let s2 = socket(AddressFamily::Unix, SockType::Stream,
- SockFlag::empty(), 0).expect("socket failed");
+ let s2 = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
+ .expect("socket failed");
connect(s2, &sockaddr).expect("connect failed");
write(s2, b"hello").expect("write failed");
close(s2).unwrap();
@@ -223,11 +220,11 @@ pub fn test_unixdomain() {
#[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;
+ use nix::sys::socket::{AddressFamily, socket, SockAddr, SockType, SockFlag, SockProtocol};
- let fd = socket(AddressFamily::System, SockType::Datagram, SockFlag::empty(), SYSPROTO_CONTROL).expect("socket failed");
+ let fd = socket(AddressFamily::System, SockType::Datagram,
+ SockFlag::empty(), SockProtocol::KextControl)
+ .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)));
diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs
index 92769e52..81db8248 100644
--- a/test/sys/test_sockopt.rs
+++ b/test/sys/test_sockopt.rs
@@ -1,9 +1,10 @@
use rand::{thread_rng, Rng};
-use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockLevel};
+use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};
#[test]
fn test_so_buf() {
- let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockLevel::Udp as i32).unwrap();
+ let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp)
+ .unwrap();
let bufsize: usize = thread_rng().gen_range(4096, 131072);
setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
let actual = getsockopt(fd, sockopt::SndBuf).unwrap();