You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The ioctl TUNSETOFFLOAD takes an unsigned int as input rather than unsigned int*, so currently none of the standard Ioctl type work and must be worked-around via an awkward int-to-pointer cast.
Proof of concept
#!/usr/bin/env -S cargo +nightly -Zscript
---
[dependencies]
rustix = { version = "0.38.34", features = ["fs"]}
---
// Note: require root permission to run.
use rustix::{
fs::{open,Mode,OFlags},
io::Result,ioctl::{ioctl,CompileTimeOpcode,Ioctl,IoctlOutput,Opcode,Setter,WriteOpcode},};use std::{
ffi::{c_int, c_uint, c_void},
marker::PhantomData,};// define the ioctl constantsconstTUN_F_CSUM:c_uint = 0x01;typeTUNSETIFF = WriteOpcode<b'T',202,c_int>;typeTUNSETOFFLOAD = WriteOpcode<b'T',208,c_uint>;fnmain() -> Result<()>{let fd = open(
c"/dev/net/tun",OFlags::RDWR | OFlags::CLOEXEC,Mode::empty(),)?;println!("created fd: {:?}", fd);unsafe{ioctl(&fd,Setter::<TUNSETIFF,_>::new(*b"example0\0\0\0\0\0\0\0\0\x01\x10"),)?;println!("tunsetiff successful");// ioctl(&fd, Setter::<TUNSETOFFLOAD, _>::new(TUN_F_CSUM))?; // will throw "InvalidInput" here!ioctl(&fd,UintSetter::<TUNSETOFFLOAD>::new(TUN_F_CSUM))?;// this works!println!("tunsetoffload successful");}Ok(())}// we need to unsafe impl a non-standard Ioctl to make that work :/structUintSetter<Oc>{input:c_uint,_opcode:PhantomData<Oc>,}impl<Oc>UintSetter<Oc>{pubfnnew(input:c_uint) -> Self{Self{
input,_opcode:PhantomData,}}}unsafeimpl<Oc:CompileTimeOpcode>IoctlforUintSetter<Oc>{typeOutput = ();constIS_MUTATING:bool = true;constOPCODE:Opcode = Oc::OPCODE;fnas_ptr(&mutself) -> *mutc_void{// // with strict provenance:// std::ptr::invalid_mut(self.input as _)self.inputas_}unsafefnoutput_from_ptr(_:IoctlOutput, _:*mutc_void) -> Result<Self::Output>{Ok(())}}
As of Linux v6.8 at least the following ioctls take the integer input directly rather than through a pointer:
During my design of this trait the intention was to involve an int-to-pointer cast here. Those are relatively rare in the ecosystem, so it should be somewhat awkward to use as a way of making sure that's what you really want.
Although, if it's common I think it would be good to add something similar to rustix::ioctl::Setter that does a number instead of a pointer.
The issue is not whether it's rare, but that for these ioctls passing values directly are the only way to communicate with the kernel. If you want to use TUNSETOFFLOAD with rustix the only way is to define that UintSetter somewhere, there are no workarounds. And I prefer that type to be placed in rustix itself rather than my crate 😉
The ioctl
TUNSETOFFLOAD
takes anunsigned int
as input rather thanunsigned int*
, so currently none of the standardIoctl
type work and must be worked-around via an awkward int-to-pointer cast.Proof of concept
As of Linux v6.8 at least the following ioctls take the integer input directly rather than through a pointer:
BTRFS_BALANCE_CTL_{PAUSE,CANCEL}
)ARPHRD_*
)On
nix
these are supported viaioctl_write_int
, in contrast toioctl_write_ptr
that corresponds torustix::ioctl::Setter
.The text was updated successfully, but these errors were encountered: