Skip to content

Commit 5654c11

Browse files
Add trait to reduce duplicated code between socket address types, implement netlink addresses (#1004)
* Add SocketAddrArg trait to reduce code duplicated across address types * Move `SocketAddrStorage` to `crate::net::addr` * Replace SocketAddrAny enum with a safe wrapper for SocketAddrStorage To support extensibility over address types, use sockaddr_storage and Into / TryInto conversions. * Remove address type variants of `bind`, `connect`, `sendmsg`, `sendto` Removes: * `bind_any`, `bind_unix`, `bind_v4`, `bind_v6`, `bind_xdp` in favor of `bind`, * `connect_any`, `connect_unix`, `connect_v4`, `connect_v6` in favor of `connect` (leaving address-less `connect_unspec`) * `sendmsg_v4`, `sendmsg_v6`, `sendmsg_unix`, `sendmsg_xdp`, `sendmsg_any` in favor of `sendmsg_addr` (leaving address-less `sendmsg`) * `sendto_any`, `sendto_v4`, `sendto_v6`, `sendto_unix`, `sendto_xdp` in favor of `sendto` * Add support for Netlink socket addresses * Introduce a `SocketAddrLen` type and use it for `SocketAddrOpaque` sizes. * Fix `bind(&s, &"127.0.0.1:0".parse().unwrap())` in tests. --------- Co-authored-by: Dan Gohman <[email protected]>
1 parent dbdbe07 commit 5654c11

34 files changed

+1287
-2587
lines changed

src/backend/libc/net/addr.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use core::slice;
88
use {
99
crate::ffi::CStr,
1010
crate::io,
11+
crate::net::addr::SocketAddrLen,
1112
crate::path,
1213
core::cmp::Ordering,
1314
core::fmt,
@@ -151,14 +152,14 @@ impl SocketAddrUnix {
151152
}
152153

153154
#[inline]
154-
pub(crate) fn addr_len(&self) -> c::socklen_t {
155+
pub(crate) fn addr_len(&self) -> SocketAddrLen {
155156
#[cfg(not(any(bsd, target_os = "haiku")))]
156157
{
157-
self.len
158+
self.len as _
158159
}
159160
#[cfg(any(bsd, target_os = "haiku"))]
160161
{
161-
c::socklen_t::from(self.unix.sun_len)
162+
c::socklen_t::from(self.unix.sun_len) as _
162163
}
163164
}
164165

@@ -169,7 +170,7 @@ impl SocketAddrUnix {
169170

170171
#[inline]
171172
fn bytes(&self) -> Option<&[u8]> {
172-
let len = self.len() as usize;
173+
let len = self.len();
173174
if len != 0 {
174175
let bytes = &self.unix.sun_path[..len - offsetof_sun_path()];
175176
// SAFETY: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
@@ -238,6 +239,7 @@ impl fmt::Debug for SocketAddrUnix {
238239

239240
/// `struct sockaddr_storage`.
240241
#[repr(transparent)]
242+
#[derive(Copy, Clone)]
241243
pub struct SocketAddrStorage(c::sockaddr_storage);
242244

243245
impl SocketAddrStorage {

src/backend/libc/net/msghdr.rs

Lines changed: 22 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,26 @@
55
66
use crate::backend::c;
77
use crate::backend::conv::{msg_control_len, msg_iov_len};
8-
#[cfg(target_os = "linux")]
9-
use crate::backend::net::write_sockaddr::encode_sockaddr_xdp;
10-
use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
118

129
use crate::io::{self, IoSlice, IoSliceMut};
13-
#[cfg(target_os = "linux")]
14-
use crate::net::xdp::SocketAddrXdp;
15-
use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6};
16-
use crate::utils::as_ptr;
10+
use crate::net::SocketAddrBuf;
11+
use crate::net::{addr::SocketAddrArg, RecvAncillaryBuffer, SendAncillaryBuffer};
1712

18-
use core::mem::{size_of, zeroed, MaybeUninit};
13+
use core::mem::zeroed;
1914

2015
/// Create a message header intended to receive a datagram.
2116
pub(crate) fn with_recv_msghdr<R>(
22-
name: &mut MaybeUninit<c::sockaddr_storage>,
17+
name: &mut SocketAddrBuf,
2318
iov: &mut [IoSliceMut<'_>],
2419
control: &mut RecvAncillaryBuffer<'_>,
2520
f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
2621
) -> io::Result<R> {
2722
control.clear();
2823

29-
let namelen = size_of::<c::sockaddr_storage>() as c::socklen_t;
3024
let mut msghdr = {
3125
let mut h = zero_msghdr();
32-
h.msg_name = name.as_mut_ptr().cast();
33-
h.msg_namelen = namelen;
26+
h.msg_name = name.storage.as_mut_ptr().cast();
27+
h.msg_namelen = name.len;
3428
h.msg_iov = iov.as_mut_ptr().cast();
3529
h.msg_iovlen = msg_iov_len(iov.len());
3630
h.msg_control = control.as_control_ptr().cast();
@@ -47,6 +41,8 @@ pub(crate) fn with_recv_msghdr<R>(
4741
}
4842
}
4943

44+
name.len = msghdr.msg_namelen;
45+
5046
res
5147
}
5248

@@ -66,87 +62,24 @@ pub(crate) fn with_noaddr_msghdr<R>(
6662
})
6763
}
6864

69-
/// Create a message header intended to send with an IPv4 address.
70-
pub(crate) fn with_v4_msghdr<R>(
71-
addr: &SocketAddrV4,
72-
iov: &[IoSlice<'_>],
73-
control: &mut SendAncillaryBuffer<'_, '_, '_>,
74-
f: impl FnOnce(c::msghdr) -> R,
75-
) -> R {
76-
let encoded = encode_sockaddr_v4(addr);
77-
78-
f({
79-
let mut h = zero_msghdr();
80-
h.msg_name = as_ptr(&encoded) as _;
81-
h.msg_namelen = size_of::<SocketAddrV4>() as _;
82-
h.msg_iov = iov.as_ptr() as _;
83-
h.msg_iovlen = msg_iov_len(iov.len());
84-
h.msg_control = control.as_control_ptr().cast();
85-
h.msg_controllen = msg_control_len(control.control_len());
86-
h
87-
})
88-
}
89-
90-
/// Create a message header intended to send with an IPv6 address.
91-
pub(crate) fn with_v6_msghdr<R>(
92-
addr: &SocketAddrV6,
93-
iov: &[IoSlice<'_>],
94-
control: &mut SendAncillaryBuffer<'_, '_, '_>,
95-
f: impl FnOnce(c::msghdr) -> R,
96-
) -> R {
97-
let encoded = encode_sockaddr_v6(addr);
98-
99-
f({
100-
let mut h = zero_msghdr();
101-
h.msg_name = as_ptr(&encoded) as _;
102-
h.msg_namelen = size_of::<SocketAddrV6>() as _;
103-
h.msg_iov = iov.as_ptr() as _;
104-
h.msg_iovlen = msg_iov_len(iov.len());
105-
h.msg_control = control.as_control_ptr().cast();
106-
h.msg_controllen = msg_control_len(control.control_len());
107-
h
108-
})
109-
}
110-
111-
/// Create a message header intended to send with a Unix address.
112-
#[cfg(all(unix, not(target_os = "redox")))]
113-
pub(crate) fn with_unix_msghdr<R>(
114-
addr: &crate::net::SocketAddrUnix,
65+
/// Create a message header intended to send with the specified address.
66+
pub(crate) fn with_msghdr<R>(
67+
addr: &impl SocketAddrArg,
11568
iov: &[IoSlice<'_>],
11669
control: &mut SendAncillaryBuffer<'_, '_, '_>,
11770
f: impl FnOnce(c::msghdr) -> R,
11871
) -> R {
119-
f({
120-
let mut h = zero_msghdr();
121-
h.msg_name = as_ptr(&addr.unix) as _;
122-
h.msg_namelen = addr.addr_len();
123-
h.msg_iov = iov.as_ptr() as _;
124-
h.msg_iovlen = msg_iov_len(iov.len());
125-
h.msg_control = control.as_control_ptr().cast();
126-
h.msg_controllen = msg_control_len(control.control_len());
127-
h
128-
})
129-
}
130-
131-
/// Create a message header intended to send with an IPv6 address.
132-
#[cfg(target_os = "linux")]
133-
pub(crate) fn with_xdp_msghdr<R>(
134-
addr: &SocketAddrXdp,
135-
iov: &[IoSlice<'_>],
136-
control: &mut SendAncillaryBuffer<'_, '_, '_>,
137-
f: impl FnOnce(c::msghdr) -> R,
138-
) -> R {
139-
let encoded = encode_sockaddr_xdp(addr);
140-
141-
f({
142-
let mut h = zero_msghdr();
143-
h.msg_name = as_ptr(&encoded) as _;
144-
h.msg_namelen = size_of::<SocketAddrXdp>() as _;
145-
h.msg_iov = iov.as_ptr() as _;
146-
h.msg_iovlen = msg_iov_len(iov.len());
147-
h.msg_control = control.as_control_ptr().cast();
148-
h.msg_controllen = msg_control_len(control.control_len());
149-
h
72+
addr.with_sockaddr(|addr_ptr, addr_len| {
73+
f({
74+
let mut h = zero_msghdr();
75+
h.msg_name = addr_ptr as *mut _;
76+
h.msg_namelen = addr_len as _;
77+
h.msg_iov = iov.as_ptr() as _;
78+
h.msg_iovlen = msg_iov_len(iov.len());
79+
h.msg_control = control.as_control_ptr().cast();
80+
h.msg_controllen = msg_control_len(control.control_len());
81+
h
82+
})
15083
})
15184
}
15285

0 commit comments

Comments
 (0)