Skip to content

Commit ea012be

Browse files
authored
socket::sockopt adding SOL_FILTER level options for illumos. (#2611)
* socket::sockopt adding SOL_FILTER level options for illumos. Respectively FIL_ATTACH/FIL_DETACH to bind/unbind a filter to a socket to for example delay connection acceptance until data (datafilt) is received. * changelog entry * changes from feedback
1 parent 975111f commit ea012be

File tree

4 files changed

+81
-5
lines changed

4 files changed

+81
-5
lines changed

changelog/2611.added.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `FilAttach` and `FilDetach` to socket::sockopt for Illumos

src/sys/socket/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2470,7 +2470,7 @@ pub trait GetSockOpt: Copy {
24702470

24712471
/// Represents a socket option that can be set.
24722472
pub trait SetSockOpt: Clone {
2473-
type Val;
2473+
type Val: ?Sized;
24742474

24752475
/// Set the value of this socket option on the given socket.
24762476
fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()>;

src/sys/socket/sockopt.rs

+56-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Socket options as used by `setsockopt` and `getsockopt`.
2-
#[cfg(linux_android)]
2+
#[cfg(any(linux_android, target_os = "illumos"))]
33
use super::SetSockOpt;
44
use crate::sys::time::TimeVal;
5-
#[cfg(linux_android)]
5+
#[cfg(any(linux_android, target_os = "illumos"))]
66
use crate::{errno::Errno, Result};
77
use cfg_if::cfg_if;
88
use libc::{self, c_int, c_void, socklen_t};
@@ -11,7 +11,7 @@ use std::ffi::CString;
1111
use std::ffi::{CStr, OsStr, OsString};
1212
use std::mem::{self, MaybeUninit};
1313
use std::os::unix::ffi::OsStrExt;
14-
#[cfg(linux_android)]
14+
#[cfg(any(linux_android, target_os = "illumos"))]
1515
use std::os::unix::io::{AsFd, AsRawFd};
1616

1717
// Constants
@@ -1483,6 +1483,58 @@ impl SetSockOpt for TcpTlsRx {
14831483
}
14841484
}
14851485

1486+
#[cfg(target_os = "illumos")]
1487+
#[derive(Copy, Clone, Debug)]
1488+
/// Attach a named filter to this socket to be able to
1489+
/// defer when anough byte had been buffered by the kernel
1490+
pub struct FilterAttach;
1491+
1492+
#[cfg(target_os = "illumos")]
1493+
impl SetSockOpt for FilterAttach {
1494+
type Val = OsStr;
1495+
1496+
fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1497+
if val.len() > libc::FILNAME_MAX as usize {
1498+
return Err(Errno::EINVAL);
1499+
}
1500+
unsafe {
1501+
let res = libc::setsockopt(
1502+
fd.as_fd().as_raw_fd(),
1503+
libc::SOL_FILTER,
1504+
libc::FIL_ATTACH,
1505+
val.as_bytes().as_ptr().cast(),
1506+
val.len() as libc::socklen_t,
1507+
);
1508+
Errno::result(res).map(drop)
1509+
}
1510+
}
1511+
}
1512+
1513+
#[cfg(target_os = "illumos")]
1514+
#[derive(Copy, Clone, Debug)]
1515+
/// Detach a socket filter previously attached with FIL_ATTACH
1516+
pub struct FilterDetach;
1517+
1518+
#[cfg(target_os = "illumos")]
1519+
impl SetSockOpt for FilterDetach {
1520+
type Val = OsStr;
1521+
1522+
fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1523+
if val.len() > libc::FILNAME_MAX as usize {
1524+
return Err(Errno::EINVAL);
1525+
}
1526+
unsafe {
1527+
let res = libc::setsockopt(
1528+
fd.as_fd().as_raw_fd(),
1529+
libc::SOL_FILTER,
1530+
libc::FIL_DETACH,
1531+
val.as_bytes().as_ptr().cast(),
1532+
val.len() as libc::socklen_t,
1533+
);
1534+
Errno::result(res).map(drop)
1535+
}
1536+
}
1537+
}
14861538
/*
14871539
*
14881540
* ===== Accessor helpers =====
@@ -1800,7 +1852,7 @@ pub struct SetOsString<'a> {
18001852
val: &'a OsStr,
18011853
}
18021854

1803-
#[cfg(any(target_os = "freebsd", linux_android))]
1855+
#[cfg(any(target_os = "freebsd", linux_android, target_os = "illumos"))]
18041856
impl<'a> Set<'a, OsString> for SetOsString<'a> {
18051857
fn new(val: &OsString) -> SetOsString {
18061858
SetOsString {

test/sys/test_sockopt.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1171,3 +1171,26 @@ fn test_exclbind() {
11711171
Err(Errno::EADDRINUSE)
11721172
);
11731173
}
1174+
1175+
#[cfg(target_os = "illumos")]
1176+
#[test]
1177+
fn test_solfilter() {
1178+
use nix::errno::Errno;
1179+
let s = socket(
1180+
AddressFamily::Inet,
1181+
SockType::Stream,
1182+
SockFlag::empty(),
1183+
SockProtocol::Tcp,
1184+
)
1185+
.unwrap();
1186+
let data = std::ffi::OsStr::new("httpf");
1187+
let attach = sockopt::FilterAttach;
1188+
let detach = sockopt::FilterDetach;
1189+
1190+
// These 2 options won't work unless the needed kernel module is installed:
1191+
// https://github.com/nix-rust/nix/pull/2611#issuecomment-2750237782
1192+
//
1193+
// So we only test the binding here
1194+
assert_eq!(Err(Errno::ENOENT), setsockopt(&s, attach, data));
1195+
assert_eq!(Err(Errno::ENOENT), setsockopt(&s, detach, data));
1196+
}

0 commit comments

Comments
 (0)