Skip to content

Commit 42def76

Browse files
committed
std::net: adding acceptfilter feature for netbsd/freebsd.
similar to linux's ext deferaccept, to filter incoming connections before accept.
1 parent 6554a56 commit 42def76

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

library/std/src/os/unix/net/stream.rs

+80
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use super::{peer_cred, UCred};
1414
#[cfg(any(doc, target_os = "android", target_os = "linux"))]
1515
use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
1616
use super::{sockaddr_un, SocketAddr};
17+
use crate::ffi::CStr;
1718
use crate::fmt;
1819
use crate::io::{self, IoSlice, IoSliceMut};
1920
use crate::net::Shutdown;
@@ -384,6 +385,85 @@ impl UnixStream {
384385
self.0.set_nonblocking(nonblocking)
385386
}
386387

388+
/// Moves the socket to pass unix credentials as control message in [`SocketAncillary`].
389+
///
390+
/// Set the socket option `SO_PASSCRED`.
391+
///
392+
/// # Examples
393+
///
394+
#[cfg_attr(
395+
any(
396+
target_os = "android",
397+
target_os = "linux",
398+
target_os = "netbsd",
399+
target_os = "freebsd"
400+
),
401+
doc = "```no_run"
402+
)]
403+
#[cfg_attr(
404+
not(any(
405+
target_os = "android",
406+
target_os = "linux",
407+
target_os = "netbsd",
408+
target_os = "freebsd"
409+
)),
410+
doc = "```ignore"
411+
)]
412+
/// #![feature(unix_socket_ancillary_data)]
413+
/// use std::os::unix::net::UnixStream;
414+
///
415+
/// fn main() -> std::io::Result<()> {
416+
/// let socket = UnixStream::connect("/tmp/sock")?;
417+
/// socket.set_passcred(true).expect("Couldn't set passcred");
418+
/// Ok(())
419+
/// }
420+
/// ```
421+
#[cfg(any(
422+
doc,
423+
target_os = "android",
424+
target_os = "linux",
425+
target_os = "netbsd",
426+
target_os = "freebsd"
427+
))]
428+
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
429+
pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
430+
self.0.set_passcred(passcred)
431+
}
432+
433+
/// Get the current value of the socket for passing unix credentials in [`SocketAncillary`].
434+
/// This value can be change by [`set_passcred`].
435+
///
436+
/// Get the socket option `SO_PASSCRED`.
437+
///
438+
/// [`set_passcred`]: UnixStream::set_passcred
439+
#[cfg(any(
440+
doc,
441+
target_os = "android",
442+
target_os = "linux",
443+
target_os = "netbsd",
444+
target_os = "freebsd"
445+
))]
446+
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
447+
pub fn passcred(&self) -> io::Result<bool> {
448+
self.0.passcred()
449+
}
450+
451+
/// Set a filter name on the socket to filter incoming connections to defer it before accept(2)
452+
///
453+
#[cfg(any(doc, target_os = "netbsd", target_os = "freebsd"))]
454+
#[unstable(feature = "acceptfilter", issue = "none")]
455+
pub fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
456+
self.0.set_acceptfilter(name)
457+
}
458+
459+
/// Get a filter name if one had been set previously on the socket.
460+
///
461+
#[cfg(any(doc, target_os = "netbsd", target_os = "freebsd"))]
462+
#[unstable(feature = "acceptfilter", issue = "none")]
463+
pub fn acceptfilter(&self) -> io::Result<&CStr> {
464+
self.0.acceptfilter()
465+
}
466+
387467
/// Set the id of the socket for network filtering purpose
388468
///
389469
#[cfg_attr(

library/std/src/sys/pal/unix/net.rs

+22
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,28 @@ impl Socket {
453453
Ok(raw as u32)
454454
}
455455

456+
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
457+
pub fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
458+
const AF_NAME_MAX: usize = 16;
459+
let mut buf = [0; AF_NAME_MAX];
460+
for (src, dst) in name.to_bytes().iter().zip(&mut buf[..AF_NAME_MAX - 1]) {
461+
*dst = *src as i8;
462+
}
463+
let mut arg: libc::accept_filter_arg = unsafe { mem::zeroed() };
464+
arg.af_name = buf;
465+
setsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER, &mut arg)
466+
}
467+
468+
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
469+
pub fn acceptfilter(&self) -> io::Result<&CStr> {
470+
let arg: libc::accept_filter_arg =
471+
getsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER)?;
472+
let s: &[u8] =
473+
unsafe { core::slice::from_raw_parts(arg.af_name.as_ptr() as *const u8, 16) };
474+
let name = CStr::from_bytes_with_nul(s).unwrap();
475+
Ok(name)
476+
}
477+
456478
#[cfg(any(target_os = "android", target_os = "linux",))]
457479
pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
458480
setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int)

0 commit comments

Comments
 (0)