summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md3
-rw-r--r--src/ifaddrs.rs24
-rw-r--r--src/lib.rs1
-rw-r--r--src/sys/socket/addr.rs1238
-rw-r--r--src/sys/socket/mod.rs197
-rw-r--r--test/sys/test_socket.rs320
-rw-r--r--test/sys/test_sockopt.rs9
7 files changed, 1402 insertions, 390 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e54639b7..737148af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -74,6 +74,9 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Changed `getrlimit` and `setrlimit` to use `rlim_t` directly
instead of `Option<rlim_t>`.
(#[1668](https://github.com/nix-rust/nix/pull/1668))
+- Deprecated `InetAddr` and `SockAddr` in favor of `SockaddrIn`, `SockaddrIn6`,
+ and `SockaddrStorage`.
+ (#[1684](https://github.com/nix-rust/nix/pull/1684))
### Fixed
diff --git a/src/ifaddrs.rs b/src/ifaddrs.rs
index ed6328f3..f834d307 100644
--- a/src/ifaddrs.rs
+++ b/src/ifaddrs.rs
@@ -10,7 +10,7 @@ use std::mem;
use std::option::Option;
use crate::{Result, Errno};
-use crate::sys::socket::SockAddr;
+use crate::sys::socket::{SockaddrLike, SockaddrStorage};
use crate::net::if_::*;
/// Describes a single address for an interface as returned by `getifaddrs`.
@@ -21,13 +21,13 @@ pub struct InterfaceAddress {
/// Flags as from `SIOCGIFFLAGS` ioctl
pub flags: InterfaceFlags,
/// Network address of this interface
- pub address: Option<SockAddr>,
+ pub address: Option<SockaddrStorage>,
/// Netmask of this interface
- pub netmask: Option<SockAddr>,
+ pub netmask: Option<SockaddrStorage>,
/// Broadcast address of this interface, if applicable
- pub broadcast: Option<SockAddr>,
+ pub broadcast: Option<SockaddrStorage>,
/// Point-to-point destination address
- pub destination: Option<SockAddr>,
+ pub destination: Option<SockaddrStorage>,
}
cfg_if! {
@@ -46,8 +46,8 @@ impl InterfaceAddress {
/// Create an `InterfaceAddress` from the libc struct.
fn from_libc_ifaddrs(info: &libc::ifaddrs) -> InterfaceAddress {
let ifname = unsafe { ffi::CStr::from_ptr(info.ifa_name) };
- let address = unsafe { SockAddr::from_libc_sockaddr(info.ifa_addr) };
- let netmask = unsafe { SockAddr::from_libc_sockaddr(info.ifa_netmask) };
+ let address = unsafe { SockaddrStorage::from_raw(info.ifa_addr, None) };
+ let netmask = unsafe { SockaddrStorage::from_raw(info.ifa_netmask, None) };
let mut addr = InterfaceAddress {
interface_name: ifname.to_string_lossy().to_string(),
flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32),
@@ -59,9 +59,9 @@ impl InterfaceAddress {
let ifu = get_ifu_from_sockaddr(info);
if addr.flags.contains(InterfaceFlags::IFF_POINTOPOINT) {
- addr.destination = unsafe { SockAddr::from_libc_sockaddr(ifu) };
+ addr.destination = unsafe { SockaddrStorage::from_raw(ifu, None) };
} else if addr.flags.contains(InterfaceFlags::IFF_BROADCAST) {
- addr.broadcast = unsafe { SockAddr::from_libc_sockaddr(ifu) };
+ addr.broadcast = unsafe { SockaddrStorage::from_raw(ifu, None) };
}
addr
@@ -103,9 +103,9 @@ impl Iterator for InterfaceAddressIterator {
/// Note that the underlying implementation differs between OSes. Only the
/// most common address families are supported by the nix crate (due to
/// lack of time and complexity of testing). The address family is encoded
-/// in the specific variant of `SockAddr` returned for the fields `address`,
-/// `netmask`, `broadcast`, and `destination`. For any entry not supported,
-/// the returned list will contain a `None` entry.
+/// in the specific variant of `SockaddrStorage` returned for the fields
+/// `address`, `netmask`, `broadcast`, and `destination`. For any entry not
+/// supported, the returned list will contain a `None` entry.
///
/// # Example
/// ```
diff --git a/src/lib.rs b/src/lib.rs
index 68093829..172ca3a1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -31,6 +31,7 @@
//! * `reboot` - Reboot the system
//! * `resource` - Process resource limits
//! * `sched` - Manipulate process's scheduling
+//! * `socket` - Sockets, whether for networking or local use
//! * `signal` - Send and receive signals to processes
//! * `term` - Terminal control APIs
//! * `time` - Query the operating system's clocks
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index 7803ec76..9d22beea 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -34,6 +34,11 @@ pub use self::vsock::VsockAddr;
/// These constants specify the protocol family to be used
/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
+///
+/// # References
+///
+/// [address_families(7)](https://man7.org/linux/man-pages/man7/address_families.7.html)
+// Should this be u8?
#[repr(i32)]
#[non_exhaustive]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
@@ -68,9 +73,15 @@ pub enum AddressFamily {
Ipx = libc::AF_IPX,
/// AppleTalk
AppleTalk = libc::AF_APPLETALK,
+ /// AX.25 packet layer protocol.
+ /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
NetRom = libc::AF_NETROM,
+ /// Can't be used for creating sockets; mostly used for bridge
+ /// links in
+ /// [rtnetlink(7)](https://man7.org/linux/man-pages/man7/rtnetlink.7.html)
+ /// protocol commands.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Bridge = libc::AF_BRIDGE,
@@ -82,77 +93,108 @@ pub enum AddressFamily {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
X25 = libc::AF_X25,
+ /// RATS (Radio Amateur Telecommunications Society) Open
+ /// Systems environment (ROSE) AX.25 packet layer protocol.
+ /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Rose = libc::AF_ROSE,
+ /// DECet protocol sockets.
Decnet = libc::AF_DECnet,
+ /// Reserved for "802.2LLC project"; never used.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
NetBeui = libc::AF_NETBEUI,
+ /// This was a short-lived (between Linux 2.1.30 and
+ /// 2.1.99pre2) protocol family for firewall upcalls.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Security = libc::AF_SECURITY,
+ /// Key management protocol.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Key = libc::AF_KEY,
+ #[allow(missing_docs)] // Not documented anywhere that I can find
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ash = libc::AF_ASH,
+ /// Acorn Econet protocol
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Econet = libc::AF_ECONET,
+ /// Access to ATM Switched Virtual Circuits
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
AtmSvc = libc::AF_ATMSVC,
+ /// Reliable Datagram Sockets (RDS) protocol
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Rds = libc::AF_RDS,
+ /// IBM SNA
Sna = libc::AF_SNA,
+ /// Socket interface over IrDA
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Irda = libc::AF_IRDA,
+ /// Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Pppox = libc::AF_PPPOX,
+ /// Legacy protocol for wide area network (WAN) connectivity that was used
+ /// by Sangoma WAN cards
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Wanpipe = libc::AF_WANPIPE,
+ /// Logical link control (IEEE 802.2 LLC) protocol
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Llc = libc::AF_LLC,
+ /// InfiniBand native addressing
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ib = libc::AF_IB,
+ /// Multiprotocol Label Switching
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Mpls = libc::AF_MPLS,
+ /// Controller Area Network automotive bus protocol
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Can = libc::AF_CAN,
+ /// TIPC, "cluster domain sockets" protocol
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Tipc = libc::AF_TIPC,
+ /// Bluetooth low-level socket protocol
#[cfg(not(any(target_os = "illumos",
target_os = "ios",
target_os = "macos",
target_os = "solaris")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Bluetooth = libc::AF_BLUETOOTH,
+ /// IUCV (inter-user communication vehicle) z/VM protocol for
+ /// hypervisor-guest interaction
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Iucv = libc::AF_IUCV,
+ /// Rx, Andrew File System remote procedure call protocol
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RxRpc = libc::AF_RXRPC,
+ /// New "modular ISDN" driver interface protocol
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Isdn = libc::AF_ISDN,
+ /// Nokia cellular modem IPC/RPC interface
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Phonet = libc::AF_PHONET,
+ /// IEEE 802.15.4 WPAN (wireless personal area network) raw packet protocol
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ieee802154 = libc::AF_IEEE802154,
+ /// Ericsson's Communication CPU to Application CPU interface (CAIF)
+ /// protocol.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Caif = libc::AF_CAIF,
@@ -160,12 +202,15 @@ pub enum AddressFamily {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Alg = libc::AF_ALG,
+ /// Near field communication
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
Nfc = libc::AF_NFC,
+ /// VMWare VSockets protocol for hypervisor-guest interaction.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Vsock = libc::AF_VSOCK,
+ /// ARPANet IMP addresses
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -174,6 +219,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
ImpLink = libc::AF_IMPLINK,
+ /// PUP protocols, e.g. BSP
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -182,6 +228,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Pup = libc::AF_PUP,
+ /// MIT CHAOS protocols
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -190,12 +237,14 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Chaos = libc::AF_CHAOS,
+ /// Novell and Xerox protocol
#[cfg(any(target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ns = libc::AF_NS,
+ #[allow(missing_docs)] // Not documented anywhere that I can find
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -204,6 +253,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Iso = libc::AF_ISO,
+ /// Bell Labs virtual circuit switch ?
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -212,6 +262,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Datakit = libc::AF_DATAKIT,
+ /// CCITT protocols, X.25 etc
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -220,6 +271,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ccitt = libc::AF_CCITT,
+ /// DEC Direct data link interface
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -228,6 +280,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Dli = libc::AF_DLI,
+ #[allow(missing_docs)] // Not documented anywhere that I can find
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -236,6 +289,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Lat = libc::AF_LAT,
+ /// NSC Hyperchannel
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -244,6 +298,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Hylink = libc::AF_HYLINK,
+ /// Link layer interface
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -253,6 +308,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Link = libc::AF_LINK,
+ /// connection-oriented IP, aka ST II
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -261,6 +317,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Coip = libc::AF_COIP,
+ /// Computer Network Technology
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -269,6 +326,7 @@ pub enum AddressFamily {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Cnt = libc::AF_CNT,
+ /// Native ATM access
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -318,12 +376,19 @@ impl AddressFamily {
feature! {
#![feature = "net"]
+#[deprecated(
+ since = "0.24.0",
+ note = "use SockaddrIn, SockaddrIn6, or SockaddrStorage instead"
+)]
+#[allow(missing_docs)] // Since they're all deprecated anyway
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum InetAddr {
V4(libc::sockaddr_in),
V6(libc::sockaddr_in6),
}
+#[allow(missing_docs)] // It's deprecated anyway
+#[allow(deprecated)]
impl InetAddr {
#[allow(clippy::needless_update)] // It isn't needless on all OSes
pub fn from_std(std: &net::SocketAddr) -> InetAddr {
@@ -417,6 +482,7 @@ impl InetAddr {
}
}
+#[allow(deprecated)]
impl fmt::Display for InetAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@@ -431,12 +497,14 @@ impl fmt::Display for InetAddr {
* ===== IpAddr =====
*
*/
+#[allow(missing_docs)] // https://github.com/nix-rust/nix/issues/1681
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}
+#[allow(missing_docs)] // https://github.com/nix-rust/nix/issues/1681
impl IpAddr {
/// Create a new IpAddr that contains an IPv4 address.
///
@@ -484,10 +552,12 @@ impl fmt::Display for IpAddr {
*
*/
+#[allow(missing_docs)] // https://github.com/nix-rust/nix/issues/1681
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct Ipv4Addr(pub libc::in_addr);
+#[allow(missing_docs)] // https://github.com/nix-rust/nix/issues/1681
impl Ipv4Addr {
#[allow(clippy::identity_op)] // More readable this way
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
@@ -534,6 +604,7 @@ impl fmt::Display for Ipv4Addr {
*
*/
+#[allow(missing_docs)] // https://github.com/nix-rust/nix/issues/1681
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct Ipv6Addr(pub libc::in6_addr);
@@ -554,6 +625,7 @@ macro_rules! to_u16_array {
}
}
+#[allow(missing_docs)] // https://github.com/nix-rust/nix/issues/1681
impl Ipv6Addr {
#[allow(clippy::many_single_char_names)]
#[allow(clippy::too_many_arguments)]
@@ -586,6 +658,7 @@ impl fmt::Display for Ipv6Addr {
/// A wrapper around `sockaddr_un`.
#[derive(Clone, Copy, Debug)]
+#[repr(C)]
pub struct UnixAddr {
// INVARIANT: sun & sun_len are valid as defined by docs for from_raw_parts
sun: libc::sockaddr_un,
@@ -799,6 +872,56 @@ impl UnixAddr {
}
}
+impl private::SockaddrLikePriv for UnixAddr {}
+impl SockaddrLike for UnixAddr {
+ #[cfg(any(target_os = "android",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux"
+ ))]
+ fn len(&self) -> libc::socklen_t {
+ self.sun_len.into()
+ }
+
+ unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = len {
+ if (l as usize) < offset_of!(libc::sockaddr_un, sun_path) ||
+ l > u8::MAX as libc::socklen_t
+ {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_UNIX as i32 {
+ return None;
+ }
+ let mut su: libc::sockaddr_un = mem::zeroed();
+ let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
+ cfg_if!{
+ if #[cfg(any(target_os = "android",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux"
+ ))] {
+ let su_len = len.unwrap_or(
+ mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
+ );
+ } else {
+ let su_len = len.unwrap_or((*addr).sa_len as libc::socklen_t);
+ }
+ };
+ ptr::copy(addr as *const u8, sup, su_len as usize);
+ Some(Self::from_raw_parts(su, su_len as u8))
+ }
+}
+
+impl AsRef<libc::sockaddr_un> for UnixAddr {
+ fn as_ref(&self) -> &libc::sockaddr_un {
+ &self.sun
+ }
+}
+
#[cfg(any(target_os = "android", target_os = "linux"))]
fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
use fmt::Write;
@@ -836,8 +959,699 @@ impl Hash for UnixAddr {
}
}
+/// Anything that, in C, can be cast back and forth to `sockaddr`.
+///
+/// Most implementors also implement `AsRef<libc::XXX>` to access their
+/// inner type read-only.
+#[allow(clippy::len_without_is_empty)]
+pub trait SockaddrLike: private::SockaddrLikePriv {
+ /// Returns a raw pointer to the inner structure. Useful for FFI.
+ fn as_ptr(&self) -> *const libc::sockaddr {
+ self as *const Self as *const libc::sockaddr
+ }
+
+ /// Unsafe constructor from a variable length source
+ ///
+ /// Some C APIs from provide `len`, and others do not. If it's provided it
+ /// will be validated. If not, it will be guessed based on the family.
+ ///
+ /// # Safety
+ ///
+ /// `addr` must be valid for the specific type of sockaddr. `len`, if
+ /// present, must be the length of valid data in `addr`.
+ unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized;
+
+ /// Return the address family of this socket
+ ///
+ /// # Examples
+ /// One common use is to match on the family of a union type, like this:
+ /// ```
+ /// # use nix::sys::socket::*;
+ /// let fd = socket(AddressFamily::Inet, SockType::Stream,
+ /// SockFlag::empty(), None).unwrap();
+ /// let ss: SockaddrStorage = getsockname(fd).unwrap();
+ /// match ss.family().unwrap() {
+ /// AddressFamily::Inet => println!("{}", ss.as_sockaddr_in().unwrap()),
+ /// AddressFamily::Inet6 => println!("{}", ss.as_sockaddr_in6().unwrap()),
+ /// _ => println!("Unexpected address family")
+ /// }
+ /// ```
+ fn family(&self) -> Option<AddressFamily> {
+ // Safe since all implementors have a sa_family field at the same
+ // address, and they're all repr(C)
+ AddressFamily::from_i32(
+ unsafe {
+ (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
+ }
+ )
+ }
+
+ cfg_if! {
+ if #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))] {
+ /// Return the length of valid data in the sockaddr structure.
+ ///
+ /// For fixed-size sockaddrs, this should be the size of the
+ /// structure. But for variable-sized types like [`UnixAddr`] it
+ /// may be less.
+ fn len(&self) -> libc::socklen_t {
+ // Safe since all implementors have a sa_len field at the same
+ // address, and they're all repr(transparent).
+ // Robust for all implementors.
+ unsafe {
+ (*(self as *const Self as *const libc::sockaddr)).sa_len
+ }.into()
+ }
+ } else {
+ /// Return the length of valid data in the sockaddr structure.
+ ///
+ /// For fixed-size sockaddrs, this should be the size of the
+ /// structure. But for variable-sized types like [`UnixAddr`] it
+ /// may be less.
+ fn len(&self) -> libc::socklen_t {
+ // No robust default implementation is possible without an
+ // sa_len field. Implementors with a variable size must
+ // override this method.
+ mem::size_of_val(self) as libc::socklen_t
+ }
+ }
+ }
+
+ /// Return the available space in the structure
+ fn size() -> libc::socklen_t where Self: Sized {
+ mem::size_of::<Self>() as libc::socklen_t
+ }
+}
+
+impl private::SockaddrLikePriv for () {
+ fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
+ ptr::null_mut()
+ }
+}
+
+/// `()` can be used in place of a real Sockaddr when no address is expected,
+/// for example for a field of `Option<S> where S: SockaddrLike`.
+// If this RFC ever stabilizes, then ! will be a better choice.
+// https://github.com/rust-lang/rust/issues/35121
+impl SockaddrLike for () {
+ fn as_ptr(&self) -> *const libc::sockaddr {
+ ptr::null()
+ }
+
+ unsafe fn from_raw(_: *const libc::sockaddr, _: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ None
+ }
+
+ fn family(&self) -> Option<AddressFamily> {
+ None
+ }
+
+ fn len(&self) -> libc::socklen_t {
+ 0
+ }
+}
+
+/// An IPv4 socket address
+// This is identical to net::SocketAddrV4. But the standard library
+// doesn't allow direct access to the libc fields, which we need. So we
+// reimplement it here.
+#[cfg(feature = "net")]
+#[repr(transparent)]
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct SockaddrIn(libc::sockaddr_in);
+
+#[cfg(feature = "net")]
+impl SockaddrIn {
+ /// Returns the IP address associated with this socket address, in native
+ /// endian.
+ pub const fn ip(&self) -> libc::in_addr_t {
+ u32::from_be(self.0.sin_addr.s_addr)
+ }
+
+ /// Creates a new socket address from IPv4 octets and a port number.
+ pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
+ Self(libc::sockaddr_in {
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ sin_len: Self::size() as u8,
+ sin_family: AddressFamily::Inet as sa_family_t,
+ sin_port: u16::to_be(port),
+ sin_addr: libc::in_addr {
+ s_addr: u32::from_ne_bytes([a, b, c, d])
+ },
+ sin_zero: unsafe{mem::zeroed()}
+ })
+ }
+
+ /// Returns the port number associated with this socket address, in native
+ /// endian.
+ pub const fn port(&self) -> u16 {
+ u16::from_be(self.0.sin_port)
+ }
+}
+
+#[cfg(feature = "net")]
+impl private::SockaddrLikePriv for SockaddrIn {}
+#[cfg(feature = "net")]
+impl SockaddrLike for SockaddrIn {
+ unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = len {
+ if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_INET as i32 {
+ return None;
+ }
+ Some(SockaddrIn(*(addr as *const libc::sockaddr_in)))
+ }
+}
+
+#[cfg(feature = "net")]
+impl AsRef<libc::sockaddr_in> for SockaddrIn {
+ fn as_ref(&self) -> &libc::sockaddr_in {
+ &self.0
+ }
+}
+
+#[cfg(feature = "net")]
+impl fmt::Display for SockaddrIn {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let ne = u32::from_be(self.0.sin_addr.s_addr);
+ let port = u16::from_be(self.0.sin_port);
+ write!(f, "{}.{}.{}.{}:{}",
+ ne >> 24,
+ (ne >> 16) & 0xFF,
+ (ne >> 8) & 0xFF,
+ ne & 0xFF,
+ port)
+ }
+}
+
+#[cfg(feature = "net")]
+impl From<net::SocketAddrV4> for SockaddrIn {
+ fn from(addr: net::SocketAddrV4) -> Self {
+ Self(libc::sockaddr_in{
+ #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
+ target_os = "haiku", target_os = "hermit",
+ target_os = "ios", target_os = "macos",
+ target_os = "netbsd", target_os = "openbsd"))]
+ sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
+ sin_family: AddressFamily::Inet as sa_family_t,
+ sin_port: addr.port().to_be(), // network byte order
+ sin_addr: Ipv4Addr::from_std(addr.ip()).0,
+ .. unsafe { mem::zeroed() }
+ })
+ }
+}
+
+#[cfg(feature = "net")]
+impl std::str::FromStr for SockaddrIn {
+ type Err = net::AddrParseError;
+
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+ net::SocketAddrV4::from_str(s).map(SockaddrIn::from)
+ }
+}
+
+/// An IPv6 socket address
+#[cfg(feature = "net")]
+#[repr(transparent)]
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct SockaddrIn6(libc::sockaddr_in6);
+
+#[cfg(feature = "net")]
+impl SockaddrIn6 {
+ /// Returns the flow information associated with this address.
+ pub const fn flowinfo(&self) -> u32 {
+ self.0.sin6_flowinfo
+ }
+
+ /// Returns the IP address associated with this socket address.
+ pub fn ip(&self) -> net::Ipv6Addr {
+ net::Ipv6Addr::from(self.0.sin6_addr.s6_addr)
+ }
+
+ /// Returns the port number associated with this socket address, in native
+ /// endian.
+ pub const fn port(&self) -> u16 {
+ u16::from_be(self.0.sin6_port)
+ }
+
+ /// Returns the scope ID associated with this address.
+ pub const fn scope_id(&self) -> u32 {
+ self.0.sin6_scope_id
+ }
+}
+
+#[cfg(feature = "net")]
+impl private::SockaddrLikePriv for SockaddrIn6 {}
+#[cfg(feature = "net")]
+impl SockaddrLike for SockaddrIn6 {
+ unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = len {
+ if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_INET6 as i32 {
+ return None;
+ }
+ Some(SockaddrIn6(*(addr as *const libc::sockaddr_in6)))
+ }
+}
+
+#[cfg(feature = "net")]
+impl AsRef<libc::sockaddr_in6> for SockaddrIn6 {
+ fn as_ref(&self) -> &libc::sockaddr_in6 {
+ &self.0
+ }
+}
+
+#[cfg(feature = "net")]
+impl fmt::Display for SockaddrIn6 {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // These things are really hard to display properly. Easier to let std
+ // do it.
+ let std = net::SocketAddrV6::new(self.ip(), self.port(),
+ self.flowinfo(), self.scope_id());
+ std.fmt(f)
+ }
+}
+
+#[cfg(feature = "net")]
+impl From<net::SocketAddrV6> for SockaddrIn6 {
+ fn from(addr: net::SocketAddrV6) -> Self {
+ #[allow(clippy::needless_update)] // It isn't needless on Illumos
+ Self(libc::sockaddr_in6{
+ #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
+ target_os = "haiku", target_os = "hermit",
+ target_os = "ios", target_os = "macos",
+ target_os = "netbsd", target_os = "openbsd"))]
+ sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
+ sin6_family: AddressFamily::Inet6 as sa_family_t,
+ sin6_port: addr.port().to_be(), // network byte order
+ sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
+ sin6_flowinfo: addr.flowinfo(), // host byte order
+ sin6_scope_id: addr.scope_id(), // host byte order
+ .. unsafe { mem::zeroed() }
+ })
+ }
+}
+
+#[cfg(feature = "net")]
+impl std::str::FromStr for SockaddrIn6 {
+ type Err = net::AddrParseError;
+
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+ net::SocketAddrV6::from_str(s).map(SockaddrIn6::from)
+ }
+}
+
+
+/// A container for any sockaddr type
+///
+/// Just like C's `sockaddr_storage`, this type is large enough to hold any type
+/// of sockaddr. It can be used as an argument with functions like
+/// [`bind`](super::bind) and [`getsockname`](super::getsockname). Though it is
+/// a union, it can be safely accessed through the `as_*` methods.
+///
+/// # Example
+/// ```
+/// # use nix::sys::socket::*;
+/// # use std::str::FromStr;
+/// let localhost = SockaddrIn::from_str("127.0.0.1:8081").unwrap();
+/// let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(),
+/// None).unwrap();
+/// bind(fd, &localhost).expect("bind");
+/// let ss: SockaddrStorage = getsockname(fd).expect("getsockname");
+/// assert_eq!(&localhost, ss.as_sockaddr_in().unwrap());
+/// ```
+#[derive(Clone, Copy, Eq)]
+#[repr(C)]
+pub union SockaddrStorage {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ alg: AlgAddr,
+ #[cfg(feature = "net")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ dl: LinkAddr,
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ nl: NetlinkAddr,
+ #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
+ #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
+ sctl: SysControlAddr,
+ #[cfg(feature = "net")]
+ sin: SockaddrIn,
+ #[cfg(feature = "net")]
+ sin6: SockaddrIn6,
+ ss: libc::sockaddr_storage,
+ su: UnixAddr,
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ vsock: VsockAddr
+}
+impl private::SockaddrLikePriv for SockaddrStorage {}
+impl SockaddrLike for SockaddrStorage {
+ unsafe fn from_raw(addr: *const libc::sockaddr, l: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if addr.is_null() {
+ return None;
+ }
+ if let Some(len) = l {
+ let ulen = len as usize;
+ if ulen < offset_of!(libc::sockaddr, sa_data) ||
+ ulen > mem::size_of::<libc::sockaddr_storage>() {
+ None
+ } else{
+ let mut ss: libc::sockaddr_storage = mem::zeroed();
+ let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
+ ptr::copy(addr as *const u8, ssp, len as usize);
+ Some(Self{ss})
+ }
+ } else {
+ // If length is not available and addr is of a fixed-length type,
+ // copy it. If addr is of a variable length type and len is not
+ // available, then there's nothing we can do.
+ match (*addr).sa_family as i32 {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_ALG => AlgAddr::from_raw(addr, l)
+ .map(|alg| Self { alg}),
+ #[cfg(feature = "net")]
+ libc::AF_INET => SockaddrIn::from_raw(addr, l)
+ .map(|sin| Self{ sin}),
+ #[cfg(feature = "net")]
+ libc::AF_INET6 => SockaddrIn6::from_raw(addr, l)
+ .map(|sin6| Self{ sin6}),
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ #[cfg(feature = "net")]
+ libc::AF_LINK => LinkAddr::from_raw(addr, l)
+ .map(|dl| Self{ dl}),
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_NETLINK => NetlinkAddr::from_raw(addr, l)
+ .map(|nl| Self{ nl }),
+ #[cfg(any(target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ))]
+ #[cfg(feature = "net")]
+ libc::AF_PACKET => LinkAddr::from_raw(addr, l)
+ .map(|dl| Self{ dl}),
+ #[cfg(all(feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")))]
+ libc::AF_SYSTEM => SysControlAddr::from_raw(addr, l)
+ .map(|sctl| Self {sctl}),
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_VSOCK => VsockAddr::from_raw(addr, l)
+ .map(|vsock| Self{vsock}),
+ _ => None
+ }
+ }
+ }
+}
+
+macro_rules! accessors {
+ (
+ $fname:ident,
+ $fname_mut:ident,
+ $sockty:ty,
+ $family:expr,
+ $libc_ty:ty,
+ $field:ident) =>
+ {
+ /// Safely and falliably downcast to an immutable reference
+ pub fn $fname(&self) -> Option<&$sockty> {
+ if self.family() == Some($family) &&
+ self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
+ {
+ // Safe because family and len are validated
+ Some(unsafe{&self.$field})
+ } else {
+ None
+ }
+ }
+
+ /// Safely and falliably downcast to a mutable reference
+ pub fn $fname_mut(&mut self) -> Option<&mut $sockty> {
+ if self.family() == Some($family) &&
+ self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
+ {
+ // Safe because family and len are validated
+ Some(unsafe{&mut self.$field})
+ } else {
+ None
+ }
+ }
+ }
+}
+
+impl SockaddrStorage {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ accessors!{as_alg_addr, as_alg_addr_mut, AlgAddr,
+ AddressFamily::Alg, libc::sockaddr_alg, alg}
+
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ #[cfg(feature = "net")]
+ accessors!{
+ as_link_addr, as_link_addr_mut, LinkAddr,
+ AddressFamily::Link, libc::sockaddr_dl, dl}
+
+ #[cfg(feature = "net")]
+ accessors!{
+ as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
+ AddressFamily::Inet, libc::sockaddr_in, sin}
+
+ #[cfg(feature = "net")]
+ accessors!{
+ as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
+ AddressFamily::Inet6, libc::sockaddr_in6, sin6}
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ accessors!{as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
+ AddressFamily::Netlink, libc::sockaddr_nl, nl}
+
+ #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
+ #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
+ accessors!{as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
+ AddressFamily::System, libc::sockaddr_ctl, sctl}
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ accessors!{as_vsock_addr, as_vsock_addr_mut, VsockAddr,
+ AddressFamily::Vsock, libc::sockaddr_vm, vsock}
+}
+
+impl fmt::Debug for SockaddrStorage {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("SockaddrStorage")
+ // Safe because sockaddr_storage has the least specific
+ // field types
+ .field("ss", unsafe{&self.ss})
+ .finish()
+ }
+}
+
+impl fmt::Display for SockaddrStorage {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ unsafe {
+ match self.ss.ss_family as i32 {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_ALG => self.alg.fmt(f),
+ #[cfg(feature = "net")]
+ libc::AF_INET => self.sin.fmt(f),
+ #[cfg(feature = "net")]
+ libc::AF_INET6 => self.sin6.fmt(f),
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ #[cfg(feature = "net")]
+ libc::AF_LINK => self.dl.fmt(f),
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_NETLINK => self.nl.fmt(f),
+ #[cfg(any(target_os = "android",
+ target_os = "linux",
+ target_os = "fuchsia"
+ ))]
+ #[cfg(feature = "net")]
+ libc::AF_PACKET => self.dl.fmt(f),
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(feature = "ioctl")]
+ libc::AF_SYSTEM => self.sctl.fmt(f),
+ libc::AF_UNIX => self.su.fmt(f),
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_VSOCK => self.vsock.fmt(f),
+ _ => "<Address family unspecified>".fmt(f)
+ }
+ }
+ }
+}
+
+#[cfg(feature = "net")]
+impl From<net::SocketAddrV4> for SockaddrStorage {
+ fn from(s: net::SocketAddrV4) -> Self {
+ unsafe {
+ let mut ss: Self = mem::zeroed();
+ ss.sin = SockaddrIn::from(s);
+ ss
+ }
+ }
+}
+
+#[cfg(feature = "net")]
+impl From<net::SocketAddrV6> for SockaddrStorage {
+ fn from(s: net::SocketAddrV6) -> Self {
+ unsafe {
+ let mut ss: Self = mem::zeroed();
+ ss.sin6 = SockaddrIn6::from(s);
+ ss
+ }
+ }
+}
+
+#[cfg(feature = "net")]
+impl From<net::SocketAddr> for SockaddrStorage {
+ fn from(s: net::SocketAddr) -> Self {
+ match s {
+ net::SocketAddr::V4(sa4) => Self::from(sa4),
+ net::SocketAddr::V6(sa6) => Self::from(sa6),
+ }
+ }
+}
+
+impl Hash for SockaddrStorage {
+ fn hash<H: Hasher>(&self, s: &mut H) {
+ unsafe {
+ match self.ss.ss_family as i32 {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_ALG => self.alg.hash(s),
+ #[cfg(feature = "net")]
+ libc::AF_INET => self.sin.hash(s),
+ #[cfg(feature = "net")]
+ libc::AF_INET6 => self.sin6.hash(s),
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ #[cfg(feature = "net")]
+ libc::AF_LINK => self.dl.hash(s),
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_NETLINK => self.nl.hash(s),
+ #[cfg(any(target_os = "android",
+ target_os = "linux",
+ target_os = "fuchsia"
+ ))]
+ #[cfg(feature = "net")]
+ libc::AF_PACKET => self.dl.hash(s),
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(feature = "ioctl")]
+ libc::AF_SYSTEM => self.sctl.hash(s),
+ libc::AF_UNIX => self.su.hash(s),
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ libc::AF_VSOCK => self.vsock.hash(s),
+ _ => self.ss.hash(s)
+ }
+ }
+ }
+}
+
+impl PartialEq for SockaddrStorage {
+ fn eq(&self, other: &Self) -> bool {
+ unsafe {
+ match (self.ss.ss_family as i32, other.ss.ss_family as i32) {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg,
+ #[cfg(feature = "net")]
+ (libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
+ #[cfg(feature = "net")]
+ (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ #[cfg(feature = "net")]
+ (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
+ #[cfg(any(target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ))]
+ #[cfg(feature = "net")]
+ (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ #[cfg(feature = "ioctl")]
+ (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
+ (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
+ _ => false,
+ }
+ }
+ }
+}
+
+mod private {
+ pub trait SockaddrLikePriv {
+ /// Returns a mutable raw pointer to the inner structure.
+ ///
+ /// # Safety
+ ///
+ /// This method is technically safe, but modifying the inner structure's
+ /// `family` or `len` fields may result in violating Nix's invariants.
+ /// It is best to use this method only with foreign functions that do
+ /// not change the sockaddr type.
+ fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
+ self as *mut Self as *mut libc::sockaddr
+ }
+ }
+}
+
/// Represents a socket address
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+#[deprecated(
+ since = "0.24.0",
+ note = "use SockaddrLike or SockaddrStorage instead"
+)]
+#[allow(missing_docs)] // Since they're all deprecated anyway
+#[allow(deprecated)]
#[non_exhaustive]
pub enum SockAddr {
#[cfg(feature = "net")]
@@ -871,6 +1685,8 @@ pub enum SockAddr {
Vsock(VsockAddr),
}
+#[allow(missing_docs)] // Since they're all deprecated anyway
+#[allow(deprecated)]
impl SockAddr {
feature! {
#![feature = "net"]
@@ -1099,6 +1915,7 @@ impl SockAddr {
}
}
+#[allow(deprecated)]
impl fmt::Display for SockAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@@ -1129,18 +1946,41 @@ impl fmt::Display for SockAddr {
}
}
+#[cfg(not(target_os = "fuchsia"))]
+#[cfg(feature = "net")]
+#[allow(deprecated)]
+impl private::SockaddrLikePriv for SockAddr {}
+#[cfg(not(target_os = "fuchsia"))]
+#[cfg(feature = "net")]
+#[allow(deprecated)]
+impl SockaddrLike for SockAddr {
+ unsafe fn from_raw(addr: *const libc::sockaddr, _len: Option<libc::socklen_t>)
+ -> Option<Self>
+ {
+ Self::from_libc_sockaddr(addr)
+ }
+}
+
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub mod netlink {
use crate::sys::socket::addr::AddressFamily;
use libc::{sa_family_t, sockaddr_nl};
use std::{fmt, mem};
+ use super::*;
+ /// Address for the Linux kernel user interface device.
+ ///
+ /// # References
+ ///
+ /// [netlink(7)](https://man7.org/linux/man-pages/man7/netlink.7.html)
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct NetlinkAddr(pub(in super::super) sockaddr_nl);
impl NetlinkAddr {
+ /// Construct a new socket address from its port ID and multicast groups
+ /// mask.
pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
addr.nl_family = AddressFamily::Netlink as sa_family_t;
@@ -1150,15 +1990,40 @@ pub mod netlink {
NetlinkAddr(addr)
}
+ /// Return the socket's port ID.
pub const fn pid(&self) -> u32 {
self.0.nl_pid
}
+ /// Return the socket's multicast groups mask
pub const fn groups(&self) -> u32 {
self.0.nl_groups
}
}
+ impl private::SockaddrLikePriv for NetlinkAddr {}
+ impl SockaddrLike for NetlinkAddr {
+ unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = len {
+ if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_NETLINK as i32 {
+ return None;
+ }
+ Some(NetlinkAddr(*(addr as *const libc::sockaddr_nl)))
+ }
+ }
+
+ impl AsRef<libc::sockaddr_nl> for NetlinkAddr {
+ fn as_ref(&self) -> &libc::sockaddr_nl {
+ &self.0
+ }
+ }
+
impl fmt::Display for NetlinkAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "pid: {} groups: {}", self.pid(), self.groups())
@@ -1173,11 +2038,36 @@ pub mod alg {
use std::{fmt, mem, str};
use std::hash::{Hash, Hasher};
use std::ffi::CStr;
+ use super::*;
+ /// Socket address for the Linux kernel crypto API
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct AlgAddr(pub(in super::super) sockaddr_alg);
+ impl private::SockaddrLikePriv for AlgAddr {}
+ impl SockaddrLike for AlgAddr {
+ unsafe fn from_raw(addr: *const libc::sockaddr, l: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = l {
+ if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_ALG as i32 {
+ return None;
+ }
+ Some(AlgAddr(*(addr as *const libc::sockaddr_alg)))
+ }
+ }
+
+ impl AsRef<libc::sockaddr_alg> for AlgAddr {
+ fn as_ref(&self) -> &libc::sockaddr_alg {
+ &self.0
+ }
+ }
+
// , PartialEq, Eq, Debug, Hash
impl PartialEq for AlgAddr {
fn eq(&self, other: &Self) -> bool {
@@ -1197,6 +2087,7 @@ pub mod alg {
}
impl AlgAddr {
+ /// Construct an `AF_ALG` socket from its cipher name and type.
pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
addr.salg_family = AF_ALG as u16;
@@ -1207,10 +2098,12 @@ pub mod alg {
}
+ /// Return the socket's cipher type, for example `hash` or `aead`.
pub fn alg_type(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
}
+ /// Return the socket's cipher name, for example `sha1`.
pub fn alg_name(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
}
@@ -1240,6 +2133,7 @@ pub mod sys_control {
use std::{fmt, mem};
use std::os::unix::io::RawFd;
use crate::{Errno, Result};
+ use super::{private, SockaddrLike};
// FIXME: Move type into `libc`
#[repr(C)]
@@ -1256,11 +2150,41 @@ pub mod sys_control {
ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
+ /// Apple system control socket
+ ///
+ /// # References
+ ///
+ /// https://developer.apple.com/documentation/kernel/sockaddr_ctl
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl);
+ impl private::SockaddrLikePriv for SysControlAddr {}
+ impl SockaddrLike for SysControlAddr {
+ unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = len {
+ if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_INET6 as i32 {
+ return None;
+ }
+ Some(SysControlAddr(*(addr as *const libc::sockaddr_ctl)))
+ }
+ }
+
+ impl AsRef<libc::sockaddr_ctl> for SysControlAddr {
+ fn as_ref(&self) -> &libc::sockaddr_ctl {
+ &self.0
+ }
+ }
+
impl SysControlAddr {
+ /// Construct a new `SysControlAddr` from its kernel unique identifier
+ /// and unit number.
pub const fn new(id: u32, unit: u32) -> SysControlAddr {
let addr = libc::sockaddr_ctl {
sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
@@ -1274,6 +2198,8 @@ pub mod sys_control {
SysControlAddr(addr)
}
+ /// Construct a new `SysControlAddr` from its human readable name and
+ /// unit number.
pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
if name.len() > MAX_KCTL_NAME {
return Err(Errno::ENAMETOOLONG);
@@ -1288,10 +2214,12 @@ pub mod sys_control {
Ok(SysControlAddr::new(info.ctl_id, unit))
}
+ /// Return the kernel unique identifier
pub const fn id(&self) -> u32 {
self.0.sc_id
}
+ /// Return the kernel controller private unit number.
pub const fn unit(&self) -> u32 {
self.0.sc_unit
}
@@ -1311,7 +2239,7 @@ pub mod sys_control {
mod datalink {
feature! {
#![feature = "net"]
- use super::{fmt, AddressFamily};
+ use super::{fmt, mem, private, SockaddrLike};
/// Hardware Address
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -1319,12 +2247,6 @@ mod datalink {
pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll);
impl LinkAddr {
- /// Always AF_PACKET
- pub fn family(&self) -> AddressFamily {
- assert_eq!(self.0.sll_family as i32, libc::AF_PACKET);
- AddressFamily::Packet
- }
-
/// Physical-layer protocol
pub fn protocol(&self) -> u16 {
self.0.sll_protocol
@@ -1379,6 +2301,30 @@ mod datalink {
}
}
}
+ impl private::SockaddrLikePriv for LinkAddr {}
+ impl SockaddrLike for LinkAddr {
+ unsafe fn from_raw(addr: *const libc::sockaddr,
+ len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = len {
+ if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_PACKET as i32 {
+ return None;
+ }
+ Some(LinkAddr(*(addr as *const libc::sockaddr_ll)))
+ }
+ }
+
+ impl AsRef<libc::sockaddr_ll> for LinkAddr {
+ fn as_ref(&self) -> &libc::sockaddr_ll {
+ &self.0
+ }
+ }
+
}
}
@@ -1393,7 +2339,7 @@ mod datalink {
mod datalink {
feature! {
#![feature = "net"]
- use super::{fmt, AddressFamily};
+ use super::{fmt, mem, private, SockaddrLike};
/// Hardware Address
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -1401,19 +2347,6 @@ mod datalink {
pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl);
impl LinkAddr {
- /// Total length of sockaddr
- #[cfg(not(target_os = "illumos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn len(&self) -> usize {
- self.0.sdl_len as usize
- }
-
- /// always == AF_LINK
- pub fn family(&self) -> AddressFamily {
- assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK);
- AddressFamily::Link
- }
-
/// interface index, if != 0, system given index for interface
pub fn ifindex(&self) -> usize {
self.0.sdl_index as usize
@@ -1424,7 +2357,7 @@ mod datalink {
self.0.sdl_type
}
- // MAC address start position
+ /// MAC address start position
pub fn nlen(&self) -> usize {
self.0.sdl_nlen as usize
}
@@ -1484,6 +2417,30 @@ mod datalink {
}
}
}
+ impl private::SockaddrLikePriv for LinkAddr {}
+ impl SockaddrLike for LinkAddr {
+ unsafe fn from_raw(addr: *const libc::sockaddr,
+ len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = len {
+ if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_LINK as i32 {
+ return None;
+ }
+ Some(LinkAddr(*(addr as *const libc::sockaddr_dl)))
+ }
+ }
+
+ impl AsRef<libc::sockaddr_dl> for LinkAddr {
+ fn as_ref(&self) -> &libc::sockaddr_dl {
+ &self.0
+ }
+ }
+
}
}
@@ -1494,11 +2451,40 @@ pub mod vsock {
use libc::{sa_family_t, sockaddr_vm};
use std::{fmt, mem};
use std::hash::{Hash, Hasher};
+ use super::*;
+ /// Socket address for VMWare VSockets protocol
+ ///
+ /// # References
+ ///
+ /// [vsock(7)](https://man7.org/linux/man-pages/man7/vsock.7.html)
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct VsockAddr(pub(in super::super) sockaddr_vm);
+ impl private::SockaddrLikePriv for VsockAddr {}
+ impl SockaddrLike for VsockAddr {
+ unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
+ -> Option<Self> where Self: Sized
+ {
+ if let Some(l) = len {
+ if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t {
+ return None;
+ }
+ }
+ if (*addr).sa_family as i32 != libc::AF_INET6 as i32 {
+ return None;
+ }
+ Some(VsockAddr(*(addr as *const libc::sockaddr_vm)))
+ }
+ }
+
+ impl AsRef<libc::sockaddr_vm> for VsockAddr {
+ fn as_ref(&self) -> &libc::sockaddr_vm {
+ &self.0
+ }
+ }
+
impl PartialEq for VsockAddr {
fn eq(&self, other: &Self) -> bool {
let (inner, other) = (self.0, other.0);
@@ -1521,6 +2507,7 @@ pub mod vsock {
/// The address for AF_VSOCK socket is defined as a combination of a
/// 32-bit Context Identifier (CID) and a 32-bit port number.
impl VsockAddr {
+ /// Construct a `VsockAddr` from its raw fields.
pub fn new(cid: u32, port: u32) -> VsockAddr {
let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
addr.svm_family = AddressFamily::Vsock as sa_family_t;
@@ -1556,112 +2543,135 @@ pub mod vsock {
#[cfg(test)]
mod tests {
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"))]
use super::*;
- /// Don't panic when trying to display an empty datalink address
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[test]
- fn test_datalink_display() {
- let la = LinkAddr(libc::sockaddr_dl{
- sdl_len: 56,
- sdl_family: 18,
- sdl_index: 5,
- sdl_type: 24,
- sdl_nlen: 3,
- sdl_alen: 0,
- sdl_slen: 0,
- .. unsafe{mem::zeroed()}
- });
- format!("{}", la);
- }
+ mod link {
+ #[cfg(any(target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos"
+ ))]
+ use super::{*, super::super::socklen_t};
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[test]
- fn test_macos_loopback_datalink_addr() {
- let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
- let sa = bytes.as_ptr() as *const libc::sockaddr;
- let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
- assert!(_sock_addr.is_none());
- }
+ /// Don't panic when trying to display an empty datalink address
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ #[test]
+ fn test_datalink_display() {
+ use super::super::LinkAddr;
+ use std::mem;
+
+ let la = LinkAddr(libc::sockaddr_dl{
+ sdl_len: 56,
+ sdl_family: 18,
+ sdl_index: 5,
+ sdl_type: 24,
+ sdl_nlen: 3,
+ sdl_alen: 0,
+ sdl_slen: 0,
+ .. unsafe{mem::zeroed()}
+ });
+ format!("{}", la);
+ }
+
+ #[cfg(any(target_os = "ios",
+ target_os = "macos"
+ ))]
+ #[test]
+ fn macos_loopback() {
+ let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
+ let sa = bytes.as_ptr() as *const libc::sockaddr;
+ let len = Some(bytes.len() as socklen_t);
+ let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
+ assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
+ match sock_addr.as_link_addr() {
+ Some(dl) => {
+ assert!(dl.addr().is_none());
+ },
+ None => panic!("Can't unwrap sockaddr storage")
+ }
+ }
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[test]
- fn test_macos_tap_datalink_addr() {
- let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
- let ptr = bytes.as_ptr();
- let sa = ptr as *const libc::sockaddr;
- let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
+ #[cfg(any(target_os = "ios",
+ target_os = "macos"
+ ))]
+ #[test]
+ fn macos_tap() {
+ let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
+ let ptr = bytes.as_ptr();
+ let sa = ptr as *const libc::sockaddr;
+ let len = Some(bytes.len() as socklen_t);
+
+ let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
+ assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
+ match sock_addr.as_link_addr() {
+ Some(dl) => assert_eq!(dl.addr(),
+ Some([24u8, 101, 144, 221, 76, 176])),
+ None => panic!("Can't unwrap sockaddr storage")
+ }
+ }
- assert!(_sock_addr.is_some());
+ #[cfg(target_os = "illumos")]
+ #[test]
+ fn illumos_tap() {
+ let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
+ let ptr = bytes.as_ptr();
+ let sa = ptr as *const libc::sockaddr;
+ let len = Some(bytes.len() as socklen_t);
+ let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) };
- let sock_addr = _sock_addr.unwrap();
+ assert!(_sock_addr.is_some());
- assert_eq!(sock_addr.family(), AddressFamily::Link);
+ let sock_addr = _sock_addr.unwrap();
- match sock_addr {
- SockAddr::Link(ether_addr) => {
- assert_eq!(ether_addr.addr(),
- Some([24u8, 101, 144, 221, 76, 176]));
- },
- _ => { unreachable!() }
- };
- }
+ assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link);
- #[cfg(target_os = "illumos")]
- #[test]
- fn test_illumos_tap_datalink_addr() {
- let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
- let ptr = bytes.as_ptr();
- let sa = ptr as *const libc::sockaddr;
- let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
+ assert_eq!(sock_addr.as_link_addr().unwrap().addr(),
+ Some([24u8, 101, 144, 221, 76, 176]));
+ }
+ }
- assert!(_sock_addr.is_some());
+ mod sockaddr_in {
+ use super::*;
+ use std::str::FromStr;
- let sock_addr = _sock_addr.unwrap();
+ #[test]
+ fn display() {
+ let s = "127.0.0.1:8080";
+ let addr = SockaddrIn::from_str(s).unwrap();
+ assert_eq!(s, format!("{}", addr));
+ }
+ }
- assert_eq!(sock_addr.family(), AddressFamily::Link);
+ mod sockaddr_in6 {
+ use super::*;
+ use std::str::FromStr;
- match sock_addr {
- SockAddr::Link(ether_addr) => {
- assert_eq!(ether_addr.addr(),
- Some([24u8, 101, 144, 221, 76, 176]));
- },
- _ => { unreachable!() }
- };
+ #[test]
+ fn display() {
+ let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
+ let addr = SockaddrIn6::from_str(s).unwrap();
+ assert_eq!(s, format!("{}", addr));
+ }
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- fn test_abstract_sun_path() {
- let name = String::from("nix\0abstract\0test");
- let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
-
- let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
- let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
- assert_eq!(sun_path1, sun_path2);
+ mod unixaddr {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ use super::*;
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[test]
+ fn abstract_sun_path() {
+ let name = String::from("nix\0abstract\0test");
+ let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
+
+ let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
+ let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
+ assert_eq!(sun_path1, sun_path2);
+ }
+
}
}
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index 7ed2d82d..f5004b45 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -17,6 +17,7 @@ use crate::sys::{
uio::IoVec
};
+#[deny(missing_docs)]
mod addr;
#[deny(missing_docs)]
pub mod sockopt;
@@ -27,12 +28,16 @@ pub mod sockopt;
*
*/
+pub use self::addr::{SockaddrLike, SockaddrStorage};
+
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
+#[allow(deprecated)]
pub use self::addr::{
AddressFamily,
SockAddr,
UnixAddr,
};
+#[allow(deprecated)]
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
#[cfg(feature = "net")]
pub use self::addr::{
@@ -40,14 +45,18 @@ pub use self::addr::{
IpAddr,
Ipv4Addr,
Ipv6Addr,
- LinkAddr
+ LinkAddr,
+ SockaddrIn,
+ SockaddrIn6
};
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
+#[allow(deprecated)]
pub use self::addr::{
AddressFamily,
SockAddr,
UnixAddr,
};
+#[allow(deprecated)]
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
#[cfg(feature = "net")]
pub use self::addr::{
@@ -55,8 +64,13 @@ pub use self::addr::{
IpAddr,
Ipv4Addr,
Ipv6Addr,
+ SockaddrIn,
+ SockaddrIn6
};
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(feature = "ioctl")]
+pub use crate::sys::socket::addr::sys_control::SysControlAddr;
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use crate::sys::socket::addr::netlink::NetlinkAddr;
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -550,15 +564,15 @@ macro_rules! cmsg_space {
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct RecvMsg<'a> {
+pub struct RecvMsg<'a, S> {
pub bytes: usize,
cmsghdr: Option<&'a cmsghdr>,
- pub address: Option<SockAddr>,
+ pub address: Option<S>,
pub flags: MsgFlags,
mhdr: msghdr,
}
-impl<'a> RecvMsg<'a> {
+impl<'a, S> RecvMsg<'a, S> {
/// Iterate over the valid control messages pointed to by this
/// msghdr.
pub fn cmsgs(&self) -> CmsgIterator {
@@ -635,6 +649,7 @@ pub enum ControlMessageOwned {
/// # use nix::sys::uio::IoVec;
/// # use nix::sys::time::*;
/// # use std::time::*;
+ /// # use std::str::FromStr;
/// # fn main() {
/// // Set up
/// let message = "Ohayō!".as_bytes();
@@ -644,9 +659,9 @@ pub enum ControlMessageOwned {
/// SockFlag::empty(),
/// None).unwrap();
/// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
- /// let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
- /// bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
- /// let address = getsockname(in_socket).unwrap();
+ /// let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
+ /// bind(in_socket, &localhost);
+ /// let address: SockaddrIn = getsockname(in_socket).unwrap();
/// // Get initial time
/// let time0 = SystemTime::now();
/// // Send the message
@@ -658,7 +673,8 @@ pub enum ControlMessageOwned {
/// let mut buffer = vec![0u8; message.len()];
/// let mut cmsgspace = cmsg_space!(TimeVal);
/// let iov = [IoVec::from_mut_slice(&mut buffer)];
- /// let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
+ /// let r = recvmsg::<SockaddrIn>(in_socket, &iov, Some(&mut cmsgspace), flags)
+ /// .unwrap();
/// let rtime = match r.cmsgs().next() {
/// Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
/// Some(_) => panic!("Unexpected control message"),
@@ -1334,8 +1350,42 @@ impl<'a> ControlMessage<'a> {
/// as with sendto.
///
/// Allocates if cmsgs is nonempty.
-pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
- flags: MsgFlags, addr: Option<&SockAddr>) -> Result<usize>
+///
+/// # Examples
+/// When not directing to any specific address, use `()` for the generic type
+/// ```
+/// # use nix::sys::socket::*;
+/// # use nix::unistd::pipe;
+/// # use nix::sys::uio::IoVec;
+/// let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None,
+/// SockFlag::empty())
+/// .unwrap();
+/// let (r, w) = pipe().unwrap();
+///
+/// let iov = [IoVec::from_slice(b"hello")];
+/// let fds = [r];
+/// let cmsg = ControlMessage::ScmRights(&fds);
+/// sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
+/// ```
+/// When directing to a specific address, the generic type will be inferred.
+/// ```
+/// # use nix::sys::socket::*;
+/// # use nix::unistd::pipe;
+/// # use nix::sys::uio::IoVec;
+/// # use std::str::FromStr;
+/// let localhost = SockaddrIn::from_str("1.2.3.4:8080").unwrap();
+/// let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(),
+/// None).unwrap();
+/// let (r, w) = pipe().unwrap();
+///
+/// let iov = [IoVec::from_slice(b"hello")];
+/// let fds = [r];
+/// let cmsg = ControlMessage::ScmRights(&fds);
+/// sendmsg(fd, &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap();
+/// ```
+pub fn sendmsg<S>(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
+ flags: MsgFlags, addr: Option<&S>) -> Result<usize>
+ where S: SockaddrLike
{
let capacity = cmsgs.iter().map(|c| c.space()).sum();
@@ -1357,14 +1407,15 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
target_os = "netbsd",
))]
#[derive(Debug)]
-pub struct SendMmsgData<'a, I, C>
+pub struct SendMmsgData<'a, I, C, S>
where
I: AsRef<[IoVec<&'a [u8]>]>,
- C: AsRef<[ControlMessage<'a>]>
+ C: AsRef<[ControlMessage<'a>]>,
+ S: SockaddrLike + 'a
{
pub iov: I,
pub cmsgs: C,
- pub addr: Option<SockAddr>,
+ pub addr: Option<S>,
pub _lt: std::marker::PhantomData<&'a I>,
}
@@ -1391,14 +1442,15 @@ pub struct SendMmsgData<'a, I, C>
target_os = "freebsd",
target_os = "netbsd",
))]
-pub fn sendmmsg<'a, I, C>(
+pub fn sendmmsg<'a, I, C, S>(
fd: RawFd,
- data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C>>,
+ data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C, S>>,
flags: MsgFlags
) -> Result<Vec<usize>>
where
I: AsRef<[IoVec<&'a [u8]>]> + 'a,
C: AsRef<[ControlMessage<'a>]> + 'a,
+ S: SockaddrLike + 'a
{
let iter = data.into_iter();
@@ -1486,15 +1538,16 @@ pub struct RecvMmsgData<'a, I>
target_os = "netbsd",
))]
#[allow(clippy::needless_collect)] // Complicated false positive
-pub fn recvmmsg<'a, I>(
+pub fn recvmmsg<'a, I, S>(
fd: RawFd,
data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>,
flags: MsgFlags,
timeout: Option<crate::sys::time::TimeSpec>
-) -> Result<Vec<RecvMsg<'a>>>
+) -> Result<Vec<RecvMsg<'a, S>>>
where
I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
+ S: Copy + SockaddrLike + 'a
{
let iter = data.into_iter();
@@ -1556,13 +1609,15 @@ pub fn recvmmsg<'a, I>(
.collect())
}
-unsafe fn read_mhdr<'a, 'b>(
+unsafe fn read_mhdr<'a, 'b, S>(
mhdr: msghdr,
r: isize,
msg_controllen: usize,
- address: sockaddr_storage,
+ address: S,
cmsg_buffer: &'a mut Option<&'b mut Vec<u8>>
-) -> RecvMsg<'b> {
+) -> RecvMsg<'b, S>
+ where S: SockaddrLike
+{
let cmsghdr = {
if mhdr.msg_controllen > 0 {
// got control message(s)
@@ -1578,27 +1633,23 @@ unsafe fn read_mhdr<'a, 'b>(
}.as_ref()
};
- let address = sockaddr_storage_to_addr(
- &address ,
- mhdr.msg_namelen as usize
- ).ok();
-
RecvMsg {
bytes: r as usize,
cmsghdr,
- address,
+ address: Some(address),
flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
mhdr,
}
}
-unsafe fn pack_mhdr_to_receive<'a, I>(
+unsafe fn pack_mhdr_to_receive<'a, I, S>(
iov: I,
cmsg_buffer: &mut Option<&mut Vec<u8>>,
- address: *mut sockaddr_storage,
+ address: *mut S,
) -> (usize, msghdr)
where
I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
+ S: SockaddrLike + 'a
{
let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
.map(|v| (v.as_mut_ptr(), v.capacity()))
@@ -1609,8 +1660,8 @@ unsafe fn pack_mhdr_to_receive<'a, I>(
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
- (*p).msg_name = address as *mut c_void;
- (*p).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
+ (*p).msg_name = (*address).as_mut_ptr() as *mut c_void;
+ (*p).msg_namelen = S::size();
(*p).msg_iov = iov.as_ref().as_ptr() as *mut iovec;
(*p).msg_iovlen = iov.as_ref().len() as _;
(*p).msg_control = msg_control as *mut c_void;
@@ -1622,27 +1673,19 @@ unsafe fn pack_mhdr_to_receive<'a, I>(
(msg_controllen, mhdr)
}
-fn pack_mhdr_to_send<'a, I, C>(
+fn pack_mhdr_to_send<'a, I, C, S>(
cmsg_buffer: &mut [u8],
iov: I,
cmsgs: C,
- addr: Option<&SockAddr>
+ addr: Option<&S>
) -> msghdr
where
I: AsRef<[IoVec<&'a [u8]>]>,
- C: AsRef<[ControlMessage<'a>]>
+ C: AsRef<[ControlMessage<'a>]>,
+ S: SockaddrLike + 'a
{
let capacity = cmsg_buffer.len();
- // Next encode the sending address, if provided
- let (name, namelen) = match addr {
- Some(addr) => {
- let (x, y) = addr.as_ffi_pair();
- (x as *const _, y)
- },
- None => (ptr::null(), 0),
- };
-
// The message header must be initialized before the individual cmsgs.
let cmsg_ptr = if capacity > 0 {
cmsg_buffer.as_ptr() as *mut c_void
@@ -1655,8 +1698,8 @@ fn pack_mhdr_to_send<'a, I, C>(
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
- (*p).msg_name = name as *mut _;
- (*p).msg_namelen = namelen;
+ (*p).msg_name = addr.map(S::as_ptr).unwrap_or(ptr::null()) as *mut _;
+ (*p).msg_namelen = addr.map(S::len).unwrap_or(0);
// transmute iov into a mutable pointer. sendmsg doesn't really mutate
// the buffer, but the standard says that it takes a mutable pointer
(*p).msg_iov = iov.as_ref().as_ptr() as *mut _;
@@ -1697,9 +1740,10 @@ fn pack_mhdr_to_send<'a, I, C>(
///
/// # References
/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
-pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
+pub fn recvmsg<'a, S>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
mut cmsg_buffer: Option<&'a mut Vec<u8>>,
- flags: MsgFlags) -> Result<RecvMsg<'a>>
+ flags: MsgFlags) -> Result<RecvMsg<'a, S>>
+ where S: SockaddrLike + 'a
{
let mut address = mem::MaybeUninit::uninit();
@@ -1779,10 +1823,9 @@ pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
/// Bind a name to a socket
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
-pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
+pub fn bind(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
let res = unsafe {
- let (ptr, len) = addr.as_ffi_pair();
- libc::bind(fd, ptr, len)
+ libc::bind(fd, addr.as_ptr(), addr.len())
};
Errno::result(res).map(drop)
@@ -1825,10 +1868,9 @@ pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
/// Initiate a connection on a socket
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
-pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
+pub fn connect(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
let res = unsafe {
- let (ptr, len) = addr.as_ffi_pair();
- libc::connect(fd, ptr, len)
+ libc::connect(fd, addr.as_ptr(), addr.len())
};
Errno::result(res).map(drop)
@@ -1855,36 +1897,38 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
/// address of the sender.
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
-pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
- -> Result<(usize, Option<SockAddr>)>
+pub fn recvfrom<T:SockaddrLike>(sockfd: RawFd, buf: &mut [u8])
+ -> Result<(usize, Option<T>)>
{
unsafe {
- let mut addr: sockaddr_storage = mem::zeroed();
- let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
+ let mut addr = mem::MaybeUninit::uninit();
+ let mut len = mem::size_of::<T>() as socklen_t;
let ret = Errno::result(libc::recvfrom(
sockfd,
buf.as_ptr() as *mut c_void,
buf.len() as size_t,
0,
- &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr,
+ addr.as_mut_ptr() as *mut libc::sockaddr,
&mut len as *mut socklen_t))? as usize;
- match sockaddr_storage_to_addr(&addr, len as usize) {
- Err(Errno::ENOTCONN) => Ok((ret, None)),
- Ok(addr) => Ok((ret, Some(addr))),
- Err(e) => Err(e)
- }
+ Ok((ret, T::from_raw(&addr.assume_init(), Some(len))))
}
}
/// Send a message to a socket
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
-pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
+pub fn sendto(fd: RawFd, buf: &[u8], addr: &dyn SockaddrLike, flags: MsgFlags) -> Result<usize> {
let ret = unsafe {
- let (ptr, len) = addr.as_ffi_pair();
- libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len)
+ libc::sendto(
+ fd,
+ buf.as_ptr() as *const c_void,
+ buf.len() as size_t,
+ flags.bits(),
+ addr.as_ptr(),
+ addr.len()
+ )
};
Errno::result(ret).map(|r| r as usize)
@@ -1954,10 +1998,10 @@ pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()>
/// Get the address of the peer connected to the socket `fd`.
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
-pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
+pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> {
unsafe {
- let mut addr = mem::MaybeUninit::uninit();
- let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
+ let mut addr = mem::MaybeUninit::<T>::uninit();
+ let mut len = T::size();
let ret = libc::getpeername(
fd,
@@ -1967,17 +2011,18 @@ pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
Errno::result(ret)?;
- sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
+ T::from_raw(addr.assume_init().as_ptr(), Some(len))
+ .ok_or(Errno::EINVAL)
}
}
/// Get the current address to which the socket `fd` is bound.
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
-pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
+pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
unsafe {
- let mut addr = mem::MaybeUninit::uninit();
- let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
+ let mut addr = mem::MaybeUninit::<T>::uninit();
+ let mut len = T::size();
let ret = libc::getsockname(
fd,
@@ -1987,7 +2032,8 @@ pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
Errno::result(ret)?;
- sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
+ T::from_raw(addr.assume_init().as_ptr(), Some(len))
+ .ok_or(Errno::EINVAL)
}
}
@@ -1999,6 +2045,11 @@ pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
/// allocated and valid. It must be at least as large as all the useful parts
/// of the structure. Note that in the case of a `sockaddr_un`, `len` need not
/// include the terminating null.
+#[deprecated(
+ since = "0.24.0",
+ note = "use SockaddrLike or SockaddrStorage instead"
+)]
+#[allow(deprecated)]
pub fn sockaddr_storage_to_addr(
addr: &sockaddr_storage,
len: usize) -> Result<SockAddr> {
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 01f5f878..e03edc3b 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -1,8 +1,11 @@
-use nix::sys::socket::{AddressFamily, InetAddr, SockAddr, UnixAddr, getsockname, sockaddr, sockaddr_in6, sockaddr_storage_to_addr};
+#[allow(deprecated)]
+use nix::sys::socket::InetAddr;
+use nix::sys::socket::{AddressFamily,
+ UnixAddr, getsockname, sockaddr, sockaddr_in6};
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::mem::{self, MaybeUninit};
-use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
+use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::os::unix::io::RawFd;
use std::path::Path;
use std::slice;
@@ -11,6 +14,7 @@ use libc::{c_char, sockaddr_storage};
#[cfg(any(target_os = "linux", target_os= "android"))]
use crate::*;
+#[allow(deprecated)]
#[test]
pub fn test_inetv4_addr_to_sock_addr() {
let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
@@ -34,8 +38,11 @@ pub fn test_inetv4_addr_to_sock_addr() {
assert_eq!(actual, inet);
}
+#[allow(deprecated)]
#[test]
pub fn test_inetv4_addr_roundtrip_sockaddr_storage_to_addr() {
+ use nix::sys::socket::{SockAddr, sockaddr_storage_to_addr};
+
let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
let addr = InetAddr::from_std(&actual);
let sockaddr = SockAddr::new_inet(addr);
@@ -63,13 +70,11 @@ pub fn test_inetv4_addr_roundtrip_sockaddr_storage_to_addr() {
pub fn test_timestamping() {
use nix::sys::socket::{
recvmsg, sendmsg, setsockopt, socket, sockopt::Timestamping, ControlMessageOwned, MsgFlags,
- SockFlag, SockType, TimestampingFlag,
+ SockaddrIn, SockFlag, SockType, TimestampingFlag,
};
use nix::sys::uio::IoVec;
- let std_sa = SocketAddr::from_str("127.0.0.1:6790").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
let ssock = socket(
AddressFamily::Inet,
@@ -97,7 +102,7 @@ pub fn test_timestamping() {
let iov2 = [IoVec::from_mut_slice(&mut rbuf)];
let mut cmsg = cmsg_space!(nix::sys::socket::Timestamps);
sendmsg(ssock, &iov1, &[], flags, Some(&sock_addr)).unwrap();
- let recv = recvmsg(rsock, &iov2, Some(&mut cmsg), flags).unwrap();
+ let recv = recvmsg::<()>(rsock, &iov2, Some(&mut cmsg), flags).unwrap();
let mut ts = None;
for c in recv.cmsgs() {
@@ -115,29 +120,11 @@ pub fn test_timestamping() {
assert!(std::time::Duration::from(diff).as_secs() < 60);
}
-#[test]
-pub fn test_inetv6_addr_to_sock_addr() {
- let port: u16 = 3000;
- let flowinfo: u32 = 1;
- let scope_id: u32 = 2;
- let ip: Ipv6Addr = "fe80::1".parse().unwrap();
-
- let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
- let addr = InetAddr::from_std(&actual);
-
- match addr {
- InetAddr::V6(addr) => {
- assert_eq!(addr.sin6_port, port.to_be());
- assert_eq!(addr.sin6_flowinfo, flowinfo);
- assert_eq!(addr.sin6_scope_id, scope_id);
- }
- _ => panic!("nope"),
- }
-
- assert_eq!(actual, addr.to_std());
-}
+#[allow(deprecated)]
#[test]
pub fn test_inetv6_addr_roundtrip_sockaddr_storage_to_addr() {
+ use nix::sys::socket::{SockAddr, sockaddr_storage_to_addr};
+
let port: u16 = 3000;
let flowinfo: u32 = 1;
let scope_id: u32 = 2;
@@ -244,13 +231,13 @@ pub fn test_abstract_uds_addr() {
#[test]
pub fn test_getsockname() {
use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};
- use nix::sys::socket::{bind, SockAddr};
+ use nix::sys::socket::bind;
let tempdir = tempfile::tempdir().unwrap();
let sockname = tempdir.path().join("sock");
let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
.expect("socket failed");
- let sockaddr = SockAddr::new_unix(&sockname).unwrap();
+ let sockaddr = UnixAddr::new(&sockname).unwrap();
bind(sock, &sockaddr).expect("bind failed");
assert_eq!(sockaddr, getsockname(sock).expect("getsockname failed"));
}
@@ -277,10 +264,10 @@ mod recvfrom {
const MSG: &[u8] = b"Hello, World!";
- fn sendrecv<Fs, Fr>(rsock: RawFd, ssock: RawFd, f_send: Fs, mut f_recv: Fr) -> Option<SockAddr>
+ fn sendrecv<Fs, Fr>(rsock: RawFd, ssock: RawFd, f_send: Fs, mut f_recv: Fr) -> Option<SockaddrStorage>
where
Fs: Fn(RawFd, &[u8], MsgFlags) -> Result<usize> + Send + 'static,
- Fr: FnMut(usize, Option<SockAddr>),
+ Fr: FnMut(usize, Option<SockaddrStorage>),
{
let mut buf: [u8; 13] = [0u8; 13];
let mut l = 0;
@@ -316,9 +303,8 @@ mod recvfrom {
#[test]
pub fn udp() {
- let std_sa = SocketAddr::from_str("127.0.0.1:6789").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:6789").unwrap();
+ let sock_addr = SockaddrIn::from(std_sa);
let rsock = socket(AddressFamily::Inet,
SockType::Datagram,
SockFlag::empty(),
@@ -335,7 +321,7 @@ mod recvfrom {
sendto(s, m, &sock_addr, flags)
},|_, _| {});
// UDP sockets should set the from address
- assert_eq!(AddressFamily::Inet, from.unwrap().family());
+ assert_eq!(AddressFamily::Inet, from.unwrap().family().unwrap());
}
#[cfg(target_os = "linux")]
@@ -356,9 +342,7 @@ mod recvfrom {
// with size 2 and two UDP packet with size 1 will be sent.
let segment_size: u16 = 2;
- let std_sa = SocketAddr::from_str("127.0.0.1:6791").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let sock_addr = SockaddrIn::new(127, 0, 0, 1, 6791);
let rsock = socket(AddressFamily::Inet,
SockType::Datagram,
SockFlag::empty(),
@@ -429,12 +413,10 @@ mod recvfrom {
pub fn udp_sendmmsg() {
use nix::sys::uio::IoVec;
- let std_sa = SocketAddr::from_str("127.0.0.1:6793").unwrap();
- let std_sa2 = SocketAddr::from_str("127.0.0.1:6794").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let inet_addr2 = InetAddr::from_std(&std_sa2);
- let sock_addr = SockAddr::new_inet(inet_addr);
- let sock_addr2 = SockAddr::new_inet(inet_addr2);
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:6793").unwrap();
+ let std_sa2 = SocketAddrV4::from_str("127.0.0.1:6794").unwrap();
+ let sock_addr = SockaddrIn::from(std_sa);
+ let sock_addr2 = SockaddrIn::from(std_sa2);
let rsock = socket(AddressFamily::Inet,
SockType::Datagram,
@@ -482,7 +464,7 @@ mod recvfrom {
})
}, |_, _ | {});
// UDP sockets should set the from address
- assert_eq!(AddressFamily::Inet, from.unwrap().family());
+ assert_eq!(AddressFamily::Inet, from.unwrap().family().unwrap());
}
#[cfg(any(
@@ -499,9 +481,8 @@ mod recvfrom {
const NUM_MESSAGES_SENT: usize = 2;
const DATA: [u8; 2] = [1,2];
- let std_sa = SocketAddr::from_str("127.0.0.1:6798").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let inet_addr = SocketAddrV4::from_str("127.0.0.1:6798").unwrap();
+ let sock_addr = SockaddrIn::from(inet_addr);
let rsock = socket(AddressFamily::Inet,
SockType::Datagram,
@@ -537,11 +518,11 @@ mod recvfrom {
})
};
- let res = recvmmsg(rsock, &mut msgs, MsgFlags::empty(), None).expect("recvmmsg");
+ let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg(rsock, &mut msgs, MsgFlags::empty(), None).expect("recvmmsg");
assert_eq!(res.len(), DATA.len());
for RecvMsg { address, bytes, .. } in res.into_iter() {
- assert_eq!(AddressFamily::Inet, address.unwrap().family());
+ assert_eq!(AddressFamily::Inet, address.unwrap().family().unwrap());
assert_eq!(DATA.len(), bytes);
}
@@ -566,9 +547,8 @@ mod recvfrom {
const NUM_MESSAGES_SENT: usize = 2;
const DATA: [u8; 4] = [1,2,3,4];
- let std_sa = SocketAddr::from_str("127.0.0.1:6799").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let inet_addr = SocketAddrV4::from_str("127.0.0.1:6799").unwrap();
+ let sock_addr = SockaddrIn::from(inet_addr);
let rsock = socket(AddressFamily::Inet,
SockType::Datagram,
@@ -609,11 +589,11 @@ mod recvfrom {
})
};
- let res = recvmmsg(rsock, &mut msgs, MsgFlags::MSG_DONTWAIT, None).expect("recvmmsg");
+ let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg(rsock, &mut msgs, MsgFlags::MSG_DONTWAIT, None).expect("recvmmsg");
assert_eq!(res.len(), NUM_MESSAGES_SENT);
for RecvMsg { address, bytes, .. } in res.into_iter() {
- assert_eq!(AddressFamily::Inet, address.unwrap().family());
+ assert_eq!(AddressFamily::Inet, address.unwrap().family().unwrap());
assert_eq!(DATA.len(), bytes);
}
@@ -633,7 +613,7 @@ pub fn test_recvmsg_ebadf() {
let mut buf = [0u8; 5];
let iov = [IoVec::from_mut_slice(&mut buf[..])];
let fd = -1; // Bad file descriptor
- let r = recvmsg(fd, &iov, None, MsgFlags::empty());
+ let r = recvmsg::<()>(fd, &iov, None, MsgFlags::empty());
assert_eq!(r.err().unwrap(), Errno::EBADF);
}
@@ -657,7 +637,7 @@ pub fn test_scm_rights() {
let iov = [IoVec::from_slice(b"hello")];
let fds = [r];
let cmsg = ControlMessage::ScmRights(&fds);
- assert_eq!(sendmsg(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
+ assert_eq!(sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
close(r).unwrap();
close(fd1).unwrap();
}
@@ -666,7 +646,7 @@ pub fn test_scm_rights() {
let mut buf = [0u8; 5];
let iov = [IoVec::from_mut_slice(&mut buf[..])];
let mut cmsgspace = cmsg_space!([RawFd; 1]);
- let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
+ let msg = recvmsg::<()>(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
for cmsg in msg.cmsgs() {
if let ControlMessageOwned::ScmRights(fd) = cmsg {
@@ -700,7 +680,7 @@ pub fn test_af_alg_cipher() {
use nix::sys::uio::IoVec;
use nix::unistd::read;
use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
- AddressFamily, SockType, SockFlag, SockAddr,
+ AddressFamily, SockType, SockFlag, AlgAddr,
ControlMessage, MsgFlags};
use nix::sys::socket::sockopt::AlgSetKey;
@@ -723,22 +703,18 @@ pub fn test_af_alg_cipher() {
let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None)
.expect("socket failed");
- let sockaddr = SockAddr::new_alg(alg_type, alg_name);
+ let sockaddr = AlgAddr::new(alg_type, alg_name);
bind(sock, &sockaddr).expect("bind failed");
- if let SockAddr::Alg(alg) = sockaddr {
- assert_eq!(alg.alg_name().to_string_lossy(), alg_name);
- assert_eq!(alg.alg_type().to_string_lossy(), alg_type);
- } else {
- panic!("unexpected SockAddr");
- }
+ assert_eq!(sockaddr.alg_name().to_string_lossy(), alg_name);
+ assert_eq!(sockaddr.alg_type().to_string_lossy(), alg_type);
setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt");
let session_socket = accept(sock).expect("accept failed");
let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_ENCRYPT), ControlMessage::AlgSetIv(iv.as_slice())];
let iov = IoVec::from_slice(&payload);
- sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
+ sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
// allocate buffer for encrypted data
let mut encrypted = vec![0u8; payload_len];
@@ -750,7 +726,7 @@ pub fn test_af_alg_cipher() {
let iv = vec![1u8; iv_len];
let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_DECRYPT), ControlMessage::AlgSetIv(iv.as_slice())];
- sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
+ sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
// allocate buffer for decrypted data
let mut decrypted = vec![0u8; payload_len];
@@ -771,7 +747,7 @@ pub fn test_af_alg_aead() {
use nix::sys::uio::IoVec;
use nix::unistd::{read, close};
use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
- AddressFamily, SockType, SockFlag, SockAddr,
+ AddressFamily, SockType, SockFlag, AlgAddr,
ControlMessage, MsgFlags};
use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize};
@@ -807,7 +783,7 @@ pub fn test_af_alg_aead() {
let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None)
.expect("socket failed");
- let sockaddr = SockAddr::new_alg(alg_type, alg_name);
+ let sockaddr = AlgAddr::new(alg_type, alg_name);
bind(sock, &sockaddr).expect("bind failed");
setsockopt(sock, AlgSetAeadAuthSize, &auth_size).expect("setsockopt AlgSetAeadAuthSize");
@@ -819,7 +795,7 @@ pub fn test_af_alg_aead() {
ControlMessage::AlgSetIv(iv.as_slice()),
ControlMessage::AlgSetAeadAssoclen(&assoc_size)];
let iov = IoVec::from_slice(&payload);
- sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
+ sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
// allocate buffer for encrypted data
let mut encrypted = vec![0u8; (assoc_size as usize) + payload_len + auth_size];
@@ -842,7 +818,7 @@ pub fn test_af_alg_aead() {
ControlMessage::AlgSetIv(iv.as_slice()),
ControlMessage::AlgSetAeadAssoclen(&assoc_size),
];
- sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
+ sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
// allocate buffer for decrypted data
let mut decrypted = vec![0u8; payload_len + (assoc_size as usize) + auth_size];
@@ -872,7 +848,7 @@ pub fn test_sendmsg_ipv4packetinfo() {
use cfg_if::cfg_if;
use nix::sys::uio::IoVec;
use nix::sys::socket::{socket, sendmsg, bind,
- AddressFamily, SockType, SockFlag, SockAddr,
+ AddressFamily, SockType, SockFlag, SockaddrIn,
ControlMessage, MsgFlags};
let sock = socket(AddressFamily::Inet,
@@ -881,39 +857,32 @@ pub fn test_sendmsg_ipv4packetinfo() {
None)
.expect("socket failed");
- let std_sa = SocketAddr::from_str("127.0.0.1:4000").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let sock_addr = SockaddrIn::new(127,0,0,1, 4000);
bind(sock, &sock_addr).expect("bind failed");
let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
let iov = [IoVec::from_slice(&slice)];
- if let InetAddr::V4(sin) = inet_addr {
- cfg_if! {
- if #[cfg(target_os = "netbsd")] {
- let _dontcare = sin;
- let pi = libc::in_pktinfo {
- ipi_ifindex: 0, /* Unspecified interface */
- ipi_addr: libc::in_addr { s_addr: 0 },
- };
- } else {
- let pi = libc::in_pktinfo {
- ipi_ifindex: 0, /* Unspecified interface */
- ipi_addr: libc::in_addr { s_addr: 0 },
- ipi_spec_dst: sin.sin_addr,
- };
- }
+ cfg_if! {
+ if #[cfg(target_os = "netbsd")] {
+ let pi = libc::in_pktinfo {
+ ipi_ifindex: 0, /* Unspecified interface */
+ ipi_addr: libc::in_addr { s_addr: 0 },
+ };
+ } else {
+ let pi = libc::in_pktinfo {
+ ipi_ifindex: 0, /* Unspecified interface */
+ ipi_addr: libc::in_addr { s_addr: 0 },
+ ipi_spec_dst: sock_addr.as_ref().sin_addr,
+ };
}
+ }
- let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)];
+ let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)];
- sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
- .expect("sendmsg");
- } else {
- panic!("No IPv4 addresses available for testing?");
- }
+ sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
+ .expect("sendmsg");
}
// Verify `ControlMessage::Ipv6PacketInfo` for `sendmsg`.
@@ -933,7 +902,7 @@ pub fn test_sendmsg_ipv6packetinfo() {
use nix::errno::Errno;
use nix::sys::uio::IoVec;
use nix::sys::socket::{socket, sendmsg, bind,
- AddressFamily, SockType, SockFlag, SockAddr,
+ AddressFamily, SockType, SockFlag, SockaddrIn6,
ControlMessage, MsgFlags};
let sock = socket(AddressFamily::Inet6,
@@ -942,9 +911,8 @@ pub fn test_sendmsg_ipv6packetinfo() {
None)
.expect("socket failed");
- let std_sa = SocketAddr::from_str("[::1]:6000").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let std_sa = SocketAddrV6::from_str("[::1]:6000").unwrap();
+ let sock_addr: SockaddrIn6 = SockaddrIn6::from(std_sa);
if let Err(Errno::EADDRNOTAVAIL) = bind(sock, &sock_addr) {
println!("IPv6 not available, skipping test.");
@@ -954,19 +922,15 @@ pub fn test_sendmsg_ipv6packetinfo() {
let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
let iov = [IoVec::from_slice(&slice)];
- if let InetAddr::V6(sin) = inet_addr {
- let pi = libc::in6_pktinfo {
- ipi6_ifindex: 0, /* Unspecified interface */
- ipi6_addr: sin.sin6_addr,
- };
+ let pi = libc::in6_pktinfo {
+ ipi6_ifindex: 0, /* Unspecified interface */
+ ipi6_addr: sock_addr.as_ref().sin6_addr,
+ };
- let cmsg = [ControlMessage::Ipv6PacketInfo(&pi)];
+ let cmsg = [ControlMessage::Ipv6PacketInfo(&pi)];
- sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
- .expect("sendmsg");
- } else {
- println!("No IPv6 addresses available for testing: skipping testing Ipv6PacketInfo");
- }
+ sendmsg::<SockaddrIn6>(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
+ .expect("sendmsg");
}
/// Tests that passing multiple fds using a single `ControlMessage` works.
@@ -987,7 +951,7 @@ fn test_scm_rights_single_cmsg_multiple_fds() {
let mut buf = [0u8; 8];
let iovec = [IoVec::from_mut_slice(&mut buf)];
let mut space = cmsg_space!([RawFd; 2]);
- let msg = recvmsg(
+ let msg = recvmsg::<()>(
receive.as_raw_fd(),
&iovec,
Some(&mut space),
@@ -1014,7 +978,7 @@ fn test_scm_rights_single_cmsg_multiple_fds() {
let iov = [IoVec::from_slice(&slice)];
let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO]; // pass stdin and stdout
let cmsg = [ControlMessage::ScmRights(&fds)];
- sendmsg(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap();
+ sendmsg::<()>(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap();
thread.join().unwrap();
}
@@ -1034,7 +998,7 @@ pub fn test_sendmsg_empty_cmsgs() {
{
let iov = [IoVec::from_slice(b"hello")];
- assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5);
+ assert_eq!(sendmsg::<()>(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5);
close(fd1).unwrap();
}
@@ -1042,7 +1006,7 @@ pub fn test_sendmsg_empty_cmsgs() {
let mut buf = [0u8; 5];
let iov = [IoVec::from_mut_slice(&mut buf[..])];
let mut cmsgspace = cmsg_space!([RawFd; 1]);
- let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
+ let msg = recvmsg::<()>(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
for _ in msg.cmsgs() {
panic!("unexpected cmsg");
@@ -1083,7 +1047,7 @@ fn test_scm_credentials() {
let cmsg = ControlMessage::ScmCredentials(&cred);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
let cmsg = ControlMessage::ScmCreds;
- assert_eq!(sendmsg(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
+ assert_eq!(sendmsg::<()>(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
close(send).unwrap();
}
@@ -1091,7 +1055,7 @@ fn test_scm_credentials() {
let mut buf = [0u8; 5];
let iov = [IoVec::from_mut_slice(&mut buf[..])];
let mut cmsgspace = cmsg_space!(UnixCredentials);
- let msg = recvmsg(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
+ let msg = recvmsg::<()>(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
let mut received_cred = None;
for cmsg in msg.cmsgs() {
@@ -1168,7 +1132,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
ControlMessage::ScmCredentials(&cred),
ControlMessage::ScmRights(&fds),
];
- assert_eq!(sendmsg(send, &iov, &cmsgs, MsgFlags::empty(), None).unwrap(), 5);
+ assert_eq!(sendmsg::<()>(send, &iov, &cmsgs, MsgFlags::empty(), None).unwrap(), 5);
close(r).unwrap();
close(send).unwrap();
}
@@ -1176,7 +1140,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
{
let mut buf = [0u8; 5];
let iov = [IoVec::from_mut_slice(&mut buf[..])];
- let msg = recvmsg(recv, &iov, Some(&mut space), MsgFlags::empty()).unwrap();
+ let msg = recvmsg::<()>(recv, &iov, Some(&mut space), MsgFlags::empty()).unwrap();
let mut received_cred = None;
assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
@@ -1218,7 +1182,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
#[test]
pub fn test_unixdomain() {
use nix::sys::socket::{SockType, SockFlag};
- use nix::sys::socket::{bind, socket, connect, listen, accept, SockAddr};
+ use nix::sys::socket::{bind, socket, connect, listen, accept, UnixAddr};
use nix::unistd::{read, write, close};
use std::thread;
@@ -1226,7 +1190,7 @@ pub fn test_unixdomain() {
let sockname = tempdir.path().join("sock");
let s1 = socket(AddressFamily::Unix, SockType::Stream,
SockFlag::empty(), None).expect("socket failed");
- let sockaddr = SockAddr::new_unix(&sockname).unwrap();
+ let sockaddr = UnixAddr::new(&sockname).unwrap();
bind(s1, &sockaddr).expect("bind failed");
listen(s1, 10).expect("listen failed");
@@ -1254,13 +1218,14 @@ pub fn test_unixdomain() {
#[test]
pub fn test_syscontrol() {
use nix::errno::Errno;
- use nix::sys::socket::{socket, SockAddr, SockType, SockFlag, SockProtocol};
+ use nix::sys::socket::{socket, SysControlAddr, SockType, SockFlag, SockProtocol};
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(Errno::ENOENT));
+ SysControlAddr::from_name(fd, "com.apple.net.utun_control", 0)
+ .expect("resolving sys_control name failed");
+ assert_eq!(SysControlAddr::from_name(fd, "foo.bar.lol", 0).err(), Some(Errno::ENOENT));
// requires root privileges
// connect(fd, &sockaddr).expect("connect failed");
@@ -1280,6 +1245,7 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr
use std::io::Write;
use nix::ifaddrs::getifaddrs;
use nix::net::if_::*;
+ use nix::sys::socket::SockaddrLike;
let addrs = match getifaddrs() {
Ok(iter) => iter,
@@ -1292,22 +1258,10 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr
};
// return first address matching family
for ifaddr in addrs {
- if ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) {
- match ifaddr.address {
- Some(SockAddr::Inet(InetAddr::V4(..))) => {
- match family {
- AddressFamily::Inet => return Some(ifaddr),
- _ => continue
- }
- },
- Some(SockAddr::Inet(InetAddr::V6(..))) => {
- match family {
- AddressFamily::Inet6 => return Some(ifaddr),
- _ => continue
- }
- },
- _ => continue,
- }
+ if ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) &&
+ ifaddr.address.as_ref().and_then(SockaddrLike::family) == Some(family)
+ {
+ return Some(ifaddr)
}
}
None
@@ -1332,7 +1286,7 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr
#[test]
pub fn test_recv_ipv4pktinfo() {
use nix::sys::socket::sockopt::Ipv4PacketInfo;
- use nix::sys::socket::{bind, SockFlag, SockType};
+ use nix::sys::socket::{bind, SockaddrIn, SockFlag, SockType};
use nix::sys::socket::{getsockname, setsockopt, socket};
use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
use nix::sys::uio::IoVec;
@@ -1351,7 +1305,7 @@ pub fn test_recv_ipv4pktinfo() {
None,
).expect("receive socket failed");
bind(receive, &lo).expect("bind failed");
- let sa = getsockname(receive).expect("getsockname failed");
+ let sa: SockaddrIn = getsockname(receive).expect("getsockname failed");
setsockopt(receive, Ipv4PacketInfo, &true).expect("setsockopt failed");
{
@@ -1371,7 +1325,7 @@ pub fn test_recv_ipv4pktinfo() {
let mut buf = [0u8; 8];
let iovec = [IoVec::from_mut_slice(&mut buf)];
let mut space = cmsg_space!(libc::in_pktinfo);
- let msg = recvmsg(
+ let msg = recvmsg::<()>(
receive,
&iovec,
Some(&mut space),
@@ -1422,8 +1376,8 @@ pub fn test_recv_ipv4pktinfo() {
pub fn test_recvif() {
use nix::net::if_::*;
use nix::sys::socket::sockopt::{Ipv4RecvIf, Ipv4RecvDstAddr};
- use nix::sys::socket::{bind, SockFlag, SockType};
- use nix::sys::socket::{getsockname, setsockopt, socket, SockAddr};
+ use nix::sys::socket::{bind, SockaddrIn, SockFlag, SockType};
+ use nix::sys::socket::{getsockname, setsockopt, socket};
use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
use nix::sys::uio::IoVec;
@@ -1440,7 +1394,7 @@ pub fn test_recvif() {
None,
).expect("receive socket failed");
bind(receive, &lo).expect("bind failed");
- let sa = getsockname(receive).expect("getsockname failed");
+ let sa: SockaddrIn = getsockname(receive).expect("getsockname failed");
setsockopt(receive, Ipv4RecvIf, &true).expect("setsockopt IP_RECVIF failed");
setsockopt(receive, Ipv4RecvDstAddr, &true).expect("setsockopt IP_RECVDSTADDR failed");
@@ -1461,7 +1415,7 @@ pub fn test_recvif() {
let mut buf = [0u8; 8];
let iovec = [IoVec::from_mut_slice(&mut buf)];
let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr);
- let msg = recvmsg(
+ let msg = recvmsg::<()>(
receive,
&iovec,
Some(&mut space),
@@ -1490,11 +1444,11 @@ pub fn test_recvif() {
},
ControlMessageOwned::Ipv4RecvDstAddr(addr) => {
rx_recvdstaddr = true;
- if let SockAddr::Inet(InetAddr::V4(a)) = lo {
- assert_eq!(a.sin_addr.s_addr,
+ if let Some(sin) = lo.as_sockaddr_in() {
+ assert_eq!(sin.as_ref().sin_addr.s_addr,
addr.s_addr,
"unexpected destination address (expected {}, got {})",
- a.sin_addr.s_addr,
+ sin.as_ref().sin_addr.s_addr,
addr.s_addr);
} else {
panic!("unexpected Sockaddr");
@@ -1535,7 +1489,7 @@ pub fn test_recvif() {
pub fn test_recv_ipv6pktinfo() {
use nix::net::if_::*;
use nix::sys::socket::sockopt::Ipv6RecvPacketInfo;
- use nix::sys::socket::{bind, SockFlag, SockType};
+ use nix::sys::socket::{bind, SockaddrIn6, SockFlag, SockType};
use nix::sys::socket::{getsockname, setsockopt, socket};
use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
use nix::sys::uio::IoVec;
@@ -1553,7 +1507,7 @@ pub fn test_recv_ipv6pktinfo() {
None,
).expect("receive socket failed");
bind(receive, &lo).expect("bind failed");
- let sa = getsockname(receive).expect("getsockname failed");
+ let sa: SockaddrIn6 = getsockname(receive).expect("getsockname failed");
setsockopt(receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed");
{
@@ -1573,7 +1527,7 @@ pub fn test_recv_ipv6pktinfo() {
let mut buf = [0u8; 8];
let iovec = [IoVec::from_mut_slice(&mut buf)];
let mut space = cmsg_space!(libc::in6_pktinfo);
- let msg = recvmsg(
+ let msg = recvmsg::<()>(
receive,
&iovec,
Some(&mut space),
@@ -1611,7 +1565,7 @@ pub fn test_recv_ipv6pktinfo() {
pub fn test_vsock() {
use nix::errno::Errno;
use nix::sys::socket::{AddressFamily, socket, bind, connect, listen,
- SockAddr, SockType, SockFlag};
+ SockType, SockFlag, VsockAddr};
use nix::unistd::{close};
use std::thread;
@@ -1622,12 +1576,12 @@ pub fn test_vsock() {
.expect("socket failed");
// VMADDR_CID_HYPERVISOR is reserved, so we expect an EADDRNOTAVAIL error.
- let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_HYPERVISOR, port);
- assert_eq!(bind(s1, &sockaddr).err(),
+ let sockaddr_hv = VsockAddr::new(libc::VMADDR_CID_HYPERVISOR, port);
+ assert_eq!(bind(s1, &sockaddr_hv).err(),
Some(Errno::EADDRNOTAVAIL));
- let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_ANY, port);
- assert_eq!(bind(s1, &sockaddr), Ok(()));
+ let sockaddr_any = VsockAddr::new(libc::VMADDR_CID_ANY, port);
+ assert_eq!(bind(s1, &sockaddr_any), Ok(()));
listen(s1, 10).expect("listen failed");
let thr = thread::spawn(move || {
@@ -1637,11 +1591,11 @@ pub fn test_vsock() {
SockFlag::empty(), None)
.expect("socket failed");
- let sockaddr = SockAddr::new_vsock(cid, port);
+ let sockaddr_host = VsockAddr::new(cid, port);
// The current implementation does not support loopback devices, so,
// for now, we expect a failure on the connect.
- assert_ne!(connect(s2, &sockaddr), Ok(()));
+ assert_ne!(connect(s2, &sockaddr_host), Ok(()));
close(s2).unwrap();
});
@@ -1669,9 +1623,9 @@ fn test_recvmsg_timestampns() {
SockFlag::empty(),
None).unwrap();
setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
- let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
- bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
- let address = getsockname(in_socket).unwrap();
+ let localhost = SockaddrIn::new(127, 0, 0, 1, 0);
+ bind(in_socket, &localhost).unwrap();
+ let address: SockaddrIn = getsockname(in_socket).unwrap();
// Get initial time
let time0 = SystemTime::now();
// Send the message
@@ -1683,7 +1637,7 @@ fn test_recvmsg_timestampns() {
let mut buffer = vec![0u8; message.len()];
let mut cmsgspace = nix::cmsg_space!(TimeSpec);
let iov = [IoVec::from_mut_slice(&mut buffer)];
- let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
+ let r = recvmsg::<()>(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
let rtime = match r.cmsgs().next() {
Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
Some(_) => panic!("Unexpected control message"),
@@ -1720,9 +1674,9 @@ fn test_recvmmsg_timestampns() {
SockFlag::empty(),
None).unwrap();
setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
- let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
- bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
- let address = getsockname(in_socket).unwrap();
+ let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
+ bind(in_socket, &localhost).unwrap();
+ let address: SockaddrIn = getsockname(in_socket).unwrap();
// Get initial time
let time0 = SystemTime::now();
// Send the message
@@ -1740,7 +1694,7 @@ fn test_recvmmsg_timestampns() {
cmsg_buffer: Some(&mut cmsgspace),
},
];
- let r = recvmmsg(in_socket, &mut data, flags, None).unwrap();
+ let r: Vec<RecvMsg<()>> = recvmmsg(in_socket, &mut data, flags, None).unwrap();
let rtime = match r[0].cmsgs().next() {
Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
Some(_) => panic!("Unexpected control message"),
@@ -1783,10 +1737,10 @@ fn test_recvmsg_rxq_ovfl() {
SockFlag::empty(),
None).unwrap();
- let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
- bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
+ let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
+ bind(in_socket, &localhost).unwrap();
- let address = getsockname(in_socket).unwrap();
+ let address: SockaddrIn = getsockname(in_socket).unwrap();
connect(out_socket, &address).unwrap();
// Set SO_RXQ_OVFL flag.
@@ -1815,7 +1769,7 @@ fn test_recvmsg_rxq_ovfl() {
let iov = [IoVec::from_mut_slice(&mut buffer)];
- match recvmsg(
+ match recvmsg::<()>(
in_socket,
&iov,
Some(&mut cmsgspace),
@@ -1847,7 +1801,7 @@ fn test_recvmsg_rxq_ovfl() {
))]
mod linux_errqueue {
use nix::sys::socket::*;
- use super::{FromStr, SocketAddr};
+ use super::FromStr;
// Send a UDP datagram to a bogus destination address and observe an ICMP error (v4).
//
@@ -1953,12 +1907,8 @@ mod linux_errqueue {
use nix::sys::uio::IoVec;
const MESSAGE_CONTENTS: &str = "ABCDEF";
-
- let sock_addr = {
- let std_sa = SocketAddr::from_str(sa).unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- SockAddr::new_inet(inet_addr)
- };
+ let std_sa = std::net::SocketAddr::from_str(sa).unwrap();
+ let sock_addr = SockaddrStorage::from(std_sa);
let sock = socket(af, SockType::Datagram, SockFlag::SOCK_CLOEXEC, None).unwrap();
setsockopt(sock, opt, &true).unwrap();
if let Err(e) = sendto(sock, MESSAGE_CONTENTS.as_bytes(), &sock_addr, MsgFlags::empty()) {
@@ -2006,16 +1956,14 @@ mod linux_errqueue {
pub fn test_txtime() {
use nix::sys::socket::{
bind, recvmsg, sendmsg, setsockopt, socket, sockopt, ControlMessage,
- MsgFlags, SockFlag, SockType,
+ MsgFlags, SockaddrIn, SockFlag, SockType,
};
use nix::sys::time::TimeValLike;
use nix::time::{ClockId, clock_gettime};
require_kernel_version!(test_txtime, ">= 5.8");
- let std_sa = SocketAddr::from_str("127.0.0.1:6802").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6802").unwrap();
let ssock = socket(
AddressFamily::Inet,
@@ -2052,5 +2000,5 @@ pub fn test_txtime() {
let mut rbuf = [0u8; 2048];
let iov2 = [nix::sys::uio::IoVec::from_mut_slice(&mut rbuf)];
- recvmsg(rsock, &iov2, None, MsgFlags::empty()).unwrap();
+ recvmsg::<()>(rsock, &iov2, None, MsgFlags::empty()).unwrap();
}
diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs
index 59b97c8b..df01e9ee 100644
--- a/test/sys/test_sockopt.rs
+++ b/test/sys/test_sockopt.rs
@@ -72,14 +72,13 @@ fn test_so_buf() {
#[test]
fn test_so_tcp_maxseg() {
- use std::net::SocketAddr;
+ use std::net::SocketAddrV4;
use std::str::FromStr;
- use nix::sys::socket::{accept, bind, connect, listen, InetAddr, SockAddr};
+ use nix::sys::socket::{accept, bind, connect, listen, SockaddrIn};
use nix::unistd::{close, write};
- let std_sa = SocketAddr::from_str("127.0.0.1:4001").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:4001").unwrap();
+ let sock_addr = SockaddrIn::from(std_sa);
let rsock = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp)
.unwrap();