Skip to content

Commit

Permalink
Replace the Sockaddr enum with a union
Browse files Browse the repository at this point in the history
The SockAddr enum is quite large, and the user must allocate space for
the whole thing even though he usually knows what type he needs.
Furthermore, thanks to the sa_family field, the sockaddr types are
basically an enum even in C.

So replace the ungainly enum with a SockaddrLike trait implemented by
all sockaddr types and  a SockaddrStorage union that has safe accessors.

Also, deprecate InetAddr, which only existed to support SockAddr.

Supplants #1504
Fixes #1544
  • Loading branch information
asomers committed Mar 22, 2022
1 parent b2ff9d2 commit 76d70b4
Show file tree
Hide file tree
Showing 7 changed files with 1,402 additions and 390 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
24 changes: 12 additions & 12 deletions src/ifaddrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand All @@ -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! {
Expand All @@ -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),
Expand All @@ -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
Expand Down Expand Up @@ -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
/// ```
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 76d70b4

Please sign in to comment.