Skip to content

Commit

Permalink
Merge #1486 #1490 #1493
Browse files Browse the repository at this point in the history
1486: Relax assertions in sockaddr_storage_to_addr to match the documentation. r=asomers a=khuey

Fixes #1479

1490: add libc::IP6T_SO_ORIGINAL_DST to socket opt r=asomers a=bearice

the original PR #1410 was stalled for a while
let's make it happen.

this should closes #1410 and #938

1493: Fix crates.io badge r=asomers a=atouchet



Co-authored-by: Kyle Huey <[email protected]>
Co-authored-by: Icemic <[email protected]>
Co-authored-by: Bearice Ren <[email protected]>
Co-authored-by: Alex Touchet <[email protected]>
  • Loading branch information
5 people authored Aug 18, 2021
4 parents 5ed5bb6 + d133d3d + e6f972c + c6ce955 commit 1fe510f
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
(#[1302](https://github.com/nix-rust/nix/pull/1302))
- Added `ptrace::interrupt` method for platforms that support `PTRACE_INTERRUPT`
(#[1422](https://github.com/nix-rust/nix/pull/1422))
- Added `IP6T_SO_ORIGINAL_DST` sockopt.
(#[1490](https://github.com/nix-rust/nix/pull/1490))

### Changed

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Rust bindings to *nix APIs

[![Cirrus Build Status](https://api.cirrus-ci.com/github/nix-rust/nix.svg)](https://cirrus-ci.com/github/nix-rust/nix)
[![crates.io](https://meritbadge.herokuapp.com/nix)](https://crates.io/crates/nix)
[![crates.io](https://img.shields.io/crates/v/nix.svg)](https://crates.io/crates/nix)

[Documentation (Releases)](https://docs.rs/nix/)

Expand Down
8 changes: 4 additions & 4 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1780,21 +1780,21 @@ pub fn sockaddr_storage_to_addr(
addr: &sockaddr_storage,
len: usize) -> Result<SockAddr> {

assert!(len <= mem::size_of::<sockaddr_un>());
assert!(len <= mem::size_of::<sockaddr_storage>());
if len < mem::size_of_val(&addr.ss_family) {
return Err(Error::from(Errno::ENOTCONN));
}

match c_int::from(addr.ss_family) {
libc::AF_INET => {
assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
assert!(len as usize >= mem::size_of::<sockaddr_in>());
let sin = unsafe {
*(addr as *const sockaddr_storage as *const sockaddr_in)
};
Ok(SockAddr::Inet(InetAddr::V4(sin)))
}
libc::AF_INET6 => {
assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
assert!(len as usize >= mem::size_of::<sockaddr_in6>());
let sin6 = unsafe {
*(addr as *const _ as *const sockaddr_in6)
};
Expand All @@ -1810,10 +1810,10 @@ pub fn sockaddr_storage_to_addr(
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_PACKET => {
use libc::sockaddr_ll;
// Don't assert anything about the size.
// Apparently the Linux kernel can return smaller sizes when
// the value in the last element of sockaddr_ll (`sll_addr`) is
// smaller than the declared size of that field
assert!(len as usize <= mem::size_of::<sockaddr_ll>());
let sll = unsafe {
*(addr as *const _ as *const sockaddr_ll)
};
Expand Down
2 changes: 2 additions & 0 deletions src/sys/socket/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
sockopt_impl!(Both, BindToDevice, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(GetOnly, Ip6tOriginalDst, libc::SOL_IPV6, libc::IP6T_SO_ORIGINAL_DST, libc::sockaddr_in6);
sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
#[cfg(all(target_os = "linux"))]
sockopt_impl!(Both, ReceiveTimestampns, libc::SOL_SOCKET, libc::SO_TIMESTAMPNS, bool);
Expand Down
56 changes: 53 additions & 3 deletions test/sys/test_socket.rs
Original file line number Diff line number Diff line change
@@ -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::*;

Expand All @@ -33,6 +34,29 @@ pub fn test_inetv4_addr_to_sock_addr() {
assert_eq!(actual, inet);
}

#[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;
Expand All @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down

0 comments on commit 1fe510f

Please sign in to comment.