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 nix-rust#1504
Fixes nix-rust#1544
  • Loading branch information
asomers committed Mar 20, 2022
1 parent 445a438 commit 34b6a95
Show file tree
Hide file tree
Showing 5 changed files with 1,373 additions and 386 deletions.
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
Loading

0 comments on commit 34b6a95

Please sign in to comment.