Skip to content

Commit 7207004

Browse files
bors[bot]khueyIcemicbeariceatouchet
authored
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]>
4 parents 05657e2 + d133d3d + e6f972c + c6ce955 commit 7207004

File tree

5 files changed

+62
-8
lines changed

5 files changed

+62
-8
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
2424
(#[1302](https://github.com/nix-rust/nix/pull/1302))
2525
- Added `ptrace::interrupt` method for platforms that support `PTRACE_INTERRUPT`
2626
(#[1422](https://github.com/nix-rust/nix/pull/1422))
27+
- Added `IP6T_SO_ORIGINAL_DST` sockopt.
28+
(#[1490](https://github.com/nix-rust/nix/pull/1490))
2729

2830
### Changed
2931

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Rust bindings to *nix APIs
22

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

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

src/sys/socket/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,21 +1780,21 @@ pub fn sockaddr_storage_to_addr(
17801780
addr: &sockaddr_storage,
17811781
len: usize) -> Result<SockAddr> {
17821782

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

17881788
match c_int::from(addr.ss_family) {
17891789
libc::AF_INET => {
1790-
assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
1790+
assert!(len as usize >= mem::size_of::<sockaddr_in>());
17911791
let sin = unsafe {
17921792
*(addr as *const sockaddr_storage as *const sockaddr_in)
17931793
};
17941794
Ok(SockAddr::Inet(InetAddr::V4(sin)))
17951795
}
17961796
libc::AF_INET6 => {
1797-
assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
1797+
assert!(len as usize >= mem::size_of::<sockaddr_in6>());
17981798
let sin6 = unsafe {
17991799
*(addr as *const _ as *const sockaddr_in6)
18001800
};
@@ -1810,10 +1810,10 @@ pub fn sockaddr_storage_to_addr(
18101810
#[cfg(any(target_os = "android", target_os = "linux"))]
18111811
libc::AF_PACKET => {
18121812
use libc::sockaddr_ll;
1813+
// Don't assert anything about the size.
18131814
// Apparently the Linux kernel can return smaller sizes when
18141815
// the value in the last element of sockaddr_ll (`sll_addr`) is
18151816
// smaller than the declared size of that field
1816-
assert!(len as usize <= mem::size_of::<sockaddr_ll>());
18171817
let sll = unsafe {
18181818
*(addr as *const _ as *const sockaddr_ll)
18191819
};

src/sys/socket/sockopt.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
283283
sockopt_impl!(Both, BindToDevice, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>);
284284
#[cfg(any(target_os = "android", target_os = "linux"))]
285285
sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
286+
#[cfg(any(target_os = "android", target_os = "linux"))]
287+
sockopt_impl!(GetOnly, Ip6tOriginalDst, libc::SOL_IPV6, libc::IP6T_SO_ORIGINAL_DST, libc::sockaddr_in6);
286288
sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
287289
#[cfg(all(target_os = "linux"))]
288290
sockopt_impl!(Both, ReceiveTimestampns, libc::SOL_SOCKET, libc::SO_TIMESTAMPNS, bool);

test/sys/test_socket.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
1+
use nix::sys::socket::{AddressFamily, InetAddr, SockAddr, UnixAddr, getsockname, sockaddr, sockaddr_in6, sockaddr_storage_to_addr};
22
use std::collections::hash_map::DefaultHasher;
33
use std::hash::{Hash, Hasher};
4+
use std::mem::{self, MaybeUninit};
45
use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
56
use std::os::unix::io::RawFd;
67
use std::path::Path;
78
use std::slice;
89
use std::str::FromStr;
9-
use libc::c_char;
10+
use libc::{c_char, sockaddr_storage};
1011
#[cfg(any(target_os = "linux", target_os= "android"))]
1112
use crate::*;
1213

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

37+
#[test]
38+
pub fn test_inetv4_addr_roundtrip_sockaddr_storage_to_addr() {
39+
let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
40+
let addr = InetAddr::from_std(&actual);
41+
let sockaddr = SockAddr::new_inet(addr);
42+
43+
let (storage, ffi_size) = {
44+
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
45+
let storage_ptr = storage.as_mut_ptr().cast::<sockaddr>();
46+
let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
47+
assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize);
48+
unsafe {
49+
storage_ptr.copy_from_nonoverlapping(ffi_ptr as *const sockaddr, 1);
50+
(storage.assume_init(), ffi_size)
51+
}
52+
};
53+
54+
let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
55+
assert_eq!(from_storage, sockaddr);
56+
let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap();
57+
assert_eq!(from_storage, sockaddr);
58+
}
59+
3660
#[test]
3761
pub fn test_inetv6_addr_to_sock_addr() {
3862
let port: u16 = 3000;
@@ -54,6 +78,33 @@ pub fn test_inetv6_addr_to_sock_addr() {
5478

5579
assert_eq!(actual, addr.to_std());
5680
}
81+
#[test]
82+
pub fn test_inetv6_addr_roundtrip_sockaddr_storage_to_addr() {
83+
let port: u16 = 3000;
84+
let flowinfo: u32 = 1;
85+
let scope_id: u32 = 2;
86+
let ip: Ipv6Addr = "fe80::1".parse().unwrap();
87+
88+
let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
89+
let addr = InetAddr::from_std(&actual);
90+
let sockaddr = SockAddr::new_inet(addr);
91+
92+
let (storage, ffi_size) = {
93+
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
94+
let storage_ptr = storage.as_mut_ptr().cast::<sockaddr_in6>();
95+
let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
96+
assert_eq!(mem::size_of::<sockaddr_in6>(), ffi_size as usize);
97+
unsafe {
98+
storage_ptr.copy_from_nonoverlapping((ffi_ptr as *const sockaddr).cast::<sockaddr_in6>(), 1);
99+
(storage.assume_init(), ffi_size)
100+
}
101+
};
102+
103+
let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
104+
assert_eq!(from_storage, sockaddr);
105+
let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap();
106+
assert_eq!(from_storage, sockaddr);
107+
}
57108

58109
#[test]
59110
pub fn test_path_to_sock_addr() {
@@ -1169,7 +1220,6 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr
11691220
use std::io;
11701221
use std::io::Write;
11711222
use nix::ifaddrs::getifaddrs;
1172-
use nix::sys::socket::SockAddr;
11731223
use nix::net::if_::*;
11741224

11751225
let addrs = match getifaddrs() {

0 commit comments

Comments
 (0)