diff options
author | Kyle Huey <khuey@kylehuey.com> | 2021-08-09 22:45:54 -0700 |
---|---|---|
committer | Kyle Huey <khuey@kylehuey.com> | 2021-08-17 19:26:12 -0700 |
commit | d133d3db7699bdf61441764d4278533539208ee1 (patch) | |
tree | 10ba7a8d3258d38c1f982e150af30276e57ae340 /test/sys/test_socket.rs | |
parent | 5ed5bb634fbef82c5dcd6e64e9b609dff08e378d (diff) | |
download | nix-d133d3db7699bdf61441764d4278533539208ee1.zip |
Relax assertions in sockaddr_storage_to_addr to match the documentation.
Fixes #1479
Diffstat (limited to 'test/sys/test_socket.rs')
-rw-r--r-- | test/sys/test_socket.rs | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 5471afe3..c43d0672 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -1,12 +1,13 @@ -use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname}; +use nix::sys::socket::{AddressFamily, InetAddr, SockAddr, UnixAddr, getsockname, sockaddr, sockaddr_in6, sockaddr_storage_to_addr}; 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::os::unix::io::RawFd; use std::path::Path; use std::slice; use std::str::FromStr; -use libc::c_char; +use libc::{c_char, sockaddr_storage}; #[cfg(any(target_os = "linux", target_os= "android"))] use crate::*; @@ -34,6 +35,29 @@ pub fn test_inetv4_addr_to_sock_addr() { } #[test] +pub fn test_inetv4_addr_roundtrip_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); + + let (storage, ffi_size) = { + let mut storage = MaybeUninit::<sockaddr_storage>::zeroed(); + let storage_ptr = storage.as_mut_ptr().cast::<sockaddr>(); + let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair(); + assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize); + unsafe { + storage_ptr.copy_from_nonoverlapping(ffi_ptr as *const sockaddr, 1); + (storage.assume_init(), ffi_size) + } + }; + + let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap(); + assert_eq!(from_storage, sockaddr); + let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap(); + assert_eq!(from_storage, sockaddr); +} + +#[test] pub fn test_inetv6_addr_to_sock_addr() { let port: u16 = 3000; let flowinfo: u32 = 1; @@ -54,6 +78,33 @@ pub fn test_inetv6_addr_to_sock_addr() { assert_eq!(actual, addr.to_std()); } +#[test] +pub fn test_inetv6_addr_roundtrip_sockaddr_storage_to_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); + let sockaddr = SockAddr::new_inet(addr); + + let (storage, ffi_size) = { + let mut storage = MaybeUninit::<sockaddr_storage>::zeroed(); + let storage_ptr = storage.as_mut_ptr().cast::<sockaddr_in6>(); + let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair(); + assert_eq!(mem::size_of::<sockaddr_in6>(), ffi_size as usize); + unsafe { + storage_ptr.copy_from_nonoverlapping((ffi_ptr as *const sockaddr).cast::<sockaddr_in6>(), 1); + (storage.assume_init(), ffi_size) + } + }; + + let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap(); + assert_eq!(from_storage, sockaddr); + let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap(); + assert_eq!(from_storage, sockaddr); +} #[test] pub fn test_path_to_sock_addr() { @@ -1169,7 +1220,6 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr use std::io; use std::io::Write; use nix::ifaddrs::getifaddrs; - use nix::sys::socket::SockAddr; use nix::net::if_::*; let addrs = match getifaddrs() { |