Merge branch 'getpeername' into 'main'

feat: Add getpeername support for uds schemes.

See merge request redox-os/base!36
This commit is contained in:
Jeremy Soller
2025-11-10 07:34:54 -07:00
13 changed files with 197 additions and 93 deletions
Generated
+2 -2
View File
@@ -329,7 +329,7 @@ dependencies = [
[[package]]
name = "generic-rt"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#cb0acf3e579f755d63db89e0301b3666ae097c8d"
source = "git+https://gitlab.redox-os.org/Ibuki.O/relibc.git?branch=getpeername#274e8a11eb3312855ebdc1d0228cb89e6abbf538"
[[package]]
name = "getrandom"
@@ -757,7 +757,7 @@ dependencies = [
[[package]]
name = "redox-rt"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#cb0acf3e579f755d63db89e0301b3666ae097c8d"
source = "git+https://gitlab.redox-os.org/Ibuki.O/relibc.git?branch=getpeername#274e8a11eb3312855ebdc1d0228cb89e6abbf538"
dependencies = [
"bitflags 2.10.0",
"generic-rt",
+1 -1
View File
@@ -8,7 +8,7 @@ libredox = { version = "0.1.8", features = ["call"]}
redox-daemon = "0.1.2"
redox_syscall = "0.5.17"
redox-scheme = "0.8.0"
redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc.git", default-features = false }
redox-rt = { git = "https://gitlab.redox-os.org/Ibuki.O/relibc.git", branch = "getpeername", default-features = false }
redox_event = "0.4.0"
anyhow = "1.0.97"
libc = "0.2"
+14 -9
View File
@@ -1,19 +1,24 @@
use std::{
fs::File,
io::{self, prelude::*},
os::unix::io::{AsRawFd, FromRawFd, RawFd}
os::unix::io::{AsRawFd, FromRawFd, RawFd},
};
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
}
fn nonblock(file: &File) -> io::Result<()> {
syscall::fcntl(file.as_raw_fd() as usize, syscall::F_SETFL, syscall::O_NONBLOCK)
.map(|_| ())
.map_err(from_syscall_error)
syscall::fcntl(
file.as_raw_fd() as usize,
syscall::F_SETFL,
syscall::O_NONBLOCK,
)
.map(|_| ())
.map_err(from_syscall_error)
}
fn dup(file: &File, buf: &str) -> io::Result<File> {
let stream = syscall::dup(file.as_raw_fd() as usize, buf.as_bytes()).map_err(from_syscall_error)?;
let stream =
syscall::dup(file.as_raw_fd() as usize, buf.as_bytes()).map_err(from_syscall_error)?;
Ok(unsafe { File::from_raw_fd(stream as RawFd) })
}
@@ -42,12 +47,12 @@ fn main() -> io::Result<()> {
event_file.write(&syscall::Event {
id: time_file.as_raw_fd() as usize,
flags: syscall::EVENT_READ,
data: TOKEN_TIMER
data: TOKEN_TIMER,
})?;
event_file.write(&syscall::Event {
id: server.as_raw_fd() as usize,
flags: syscall::EVENT_WRITE | syscall::EVENT_READ,
data: TOKEN_SERVER
data: TOKEN_SERVER,
})?;
let mut event = syscall::Event::default();
@@ -63,7 +68,7 @@ fn main() -> io::Result<()> {
event_file.write(&syscall::Event {
id: client.as_raw_fd() as usize,
flags: syscall::EVENT_WRITE | syscall::EVENT_READ,
data: TOKEN_CLIENT
data: TOKEN_CLIENT,
})?;
event_file.read(&mut event)?;
@@ -83,7 +88,7 @@ fn main() -> io::Result<()> {
event_file.write(&syscall::Event {
id: stream.as_raw_fd() as usize,
flags: syscall::EVENT_READ | syscall::EVENT_WRITE,
data: TOKEN_STREAM
data: TOKEN_STREAM,
})?;
event_file.read(&mut event)?;
+1 -4
View File
@@ -1,7 +1,4 @@
use std::{
fs::File,
io
};
use std::{fs::File, io};
fn main() -> io::Result<()> {
let mut client = File::open("chan:hello")?;
+3 -2
View File
@@ -1,7 +1,7 @@
use std::{
fs::File,
io::{self, prelude::*},
os::unix::io::{AsRawFd, FromRawFd, RawFd}
os::unix::io::{AsRawFd, FromRawFd, RawFd},
};
fn from_syscall_error(error: syscall::Error) -> io::Error {
@@ -12,7 +12,8 @@ fn main() -> io::Result<()> {
let server = File::create("chan:hello")?;
loop {
let stream = syscall::dup(server.as_raw_fd() as usize, b"listen").map_err(from_syscall_error)?;
let stream =
syscall::dup(server.as_raw_fd() as usize, b"listen").map_err(from_syscall_error)?;
let mut stream = unsafe { File::from_raw_fd(stream as RawFd) };
stream.write(b"Hello World!\n")?;
+26 -11
View File
@@ -3,7 +3,7 @@ use std::{
fs::File,
io::{self, prelude::*},
os::unix::io::{AsRawFd, FromRawFd, RawFd},
str
str,
};
fn from_syscall_error(error: syscall::Error) -> io::Error {
@@ -14,9 +14,13 @@ fn main() -> io::Result<()> {
let server = File::create("chan:log")?;
let mut event_file = File::open("event:")?;
syscall::fcntl(server.as_raw_fd() as usize, syscall::F_SETFL, syscall::O_NONBLOCK)
.map(|_| ())
.map_err(from_syscall_error)?;
syscall::fcntl(
server.as_raw_fd() as usize,
syscall::F_SETFL,
syscall::O_NONBLOCK,
)
.map(|_| ())
.map_err(from_syscall_error)?;
event_file.write(&syscall::Event {
id: server.as_raw_fd() as usize,
data: 0,
@@ -34,9 +38,11 @@ fn main() -> io::Result<()> {
println!("Listener recevied flags: {:?}", event.flags);
if event.flags & syscall::EVENT_WRITE == syscall::EVENT_WRITE {
loop {
let stream = match syscall::dup(server.as_raw_fd() as usize, b"listen").map_err(from_syscall_error) {
let stream = match syscall::dup(server.as_raw_fd() as usize, b"listen")
.map_err(from_syscall_error)
{
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
stream => stream?
stream => stream?,
};
let stream = unsafe { File::from_raw_fd(stream as RawFd) };
@@ -64,11 +70,15 @@ fn main() -> io::Result<()> {
println!("--> EOF");
clients.remove(&event.data);
continue 'outer;
},
}
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
len => len?
len => len?,
};
println!("--> Read {}/128 bytes: {:?}", len, str::from_utf8(&buf[..len]));
println!(
"--> Read {}/128 bytes: {:?}",
len,
str::from_utf8(&buf[..len])
);
}
}
if event.flags & syscall::EVENT_WRITE == syscall::EVENT_WRITE {
@@ -79,9 +89,14 @@ fn main() -> io::Result<()> {
let len = match client.write(BUF[written..].as_bytes()) {
Ok(0) => panic!("EOF should never happen here"),
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
len => len?
len => len?,
};
println!("--> Wrote {}/{} bytes: {:?}", len, BUF.len(), &BUF[written..]);
println!(
"--> Wrote {}/{} bytes: {:?}",
len,
BUF.len(),
&BUF[written..]
);
written += len;
}
}
+33 -11
View File
@@ -3,19 +3,24 @@ use std::{
io::{self, prelude::*},
os::unix::io::{AsRawFd, FromRawFd, RawFd},
thread,
time::Duration
time::Duration,
};
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
}
fn nonblock(file: &File) -> io::Result<()> {
syscall::fcntl(file.as_raw_fd() as usize, syscall::F_SETFL, syscall::O_NONBLOCK)
.map(|_| ())
.map_err(from_syscall_error)
syscall::fcntl(
file.as_raw_fd() as usize,
syscall::F_SETFL,
syscall::O_NONBLOCK,
)
.map(|_| ())
.map_err(from_syscall_error)
}
fn dup(file: &File, buf: &str) -> io::Result<File> {
let stream = syscall::dup(file.as_raw_fd() as usize, buf.as_bytes()).map_err(from_syscall_error)?;
let stream =
syscall::dup(file.as_raw_fd() as usize, buf.as_bytes()).map_err(from_syscall_error)?;
Ok(unsafe { File::from_raw_fd(stream as RawFd) })
}
@@ -28,7 +33,9 @@ fn main() -> io::Result<()> {
OpenOptions::new()
.write(true)
.create_new(true)
.open("chan:hello_world").unwrap_err().kind(),
.open("chan:hello_world")
.unwrap_err()
.kind(),
io::ErrorKind::AlreadyExists
);
@@ -55,7 +62,10 @@ fn main() -> io::Result<()> {
println!("Testing close...");
drop(client);
assert_eq!(stream.write(b"a").unwrap_err().kind(), io::ErrorKind::BrokenPipe);
assert_eq!(
stream.write(b"a").unwrap_err().kind(),
io::ErrorKind::BrokenPipe
);
assert_eq!(stream.read(&mut buf)?, 0);
}
println!("Testing alternative connect method...");
@@ -87,10 +97,16 @@ fn main() -> io::Result<()> {
nonblock(&client)?;
nonblock(&server)?;
assert_eq!(client.read(&mut buf).unwrap_err().kind(), io::ErrorKind::WouldBlock);
assert_eq!(
client.read(&mut buf).unwrap_err().kind(),
io::ErrorKind::WouldBlock
);
println!("-> Read would block");
assert_eq!(dup(&server, "listen").unwrap_err().kind(), io::ErrorKind::WouldBlock);
assert_eq!(
dup(&server, "listen").unwrap_err().kind(),
io::ErrorKind::WouldBlock
);
println!("-> Accept would block");
drop(client);
@@ -98,14 +114,20 @@ fn main() -> io::Result<()> {
let mut client = File::open("chan:hello_world")?;
nonblock(&client)?;
assert_eq!(client.write(b"a").unwrap_err().kind(), io::ErrorKind::WouldBlock);
assert_eq!(
client.write(b"a").unwrap_err().kind(),
io::ErrorKind::WouldBlock
);
println!("-> Write before accept would block");
}
let mut client = dup(&server, "connect")?;
nonblock(&client)?;
assert_eq!(client.write(b"a").unwrap_err().kind(), io::ErrorKind::WouldBlock);
assert_eq!(
client.write(b"a").unwrap_err().kind(),
io::ErrorKind::WouldBlock
);
println!("-> Write before accept would block (alternative connection method)");
println!("Everything tested!");
+23 -20
View File
@@ -1,9 +1,4 @@
use std::{
fs::File,
io,
os::unix::io::AsRawFd,
slice
};
use std::{fs::File, io, os::unix::io::AsRawFd, slice};
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
@@ -14,26 +9,34 @@ fn main() -> Result<(), io::Error> {
let one = unsafe {
slice::from_raw_parts_mut(
syscall::fmap(file1.as_raw_fd() as usize, &syscall::Map {
offset: 0,
size: 128,
flags: syscall::PROT_READ | syscall::PROT_WRITE | syscall::MAP_SHARED,
address: 0,
}).map_err(from_syscall_error)? as *mut u8,
128
syscall::fmap(
file1.as_raw_fd() as usize,
&syscall::Map {
offset: 0,
size: 128,
flags: syscall::PROT_READ | syscall::PROT_WRITE | syscall::MAP_SHARED,
address: 0,
},
)
.map_err(from_syscall_error)? as *mut u8,
128,
)
};
// FIXME: While the length can be unaligned, the offset cannot. This test is incorrectly
// written.
let two = unsafe {
slice::from_raw_parts_mut(
syscall::fmap(file2.as_raw_fd() as usize, &syscall::Map {
offset: 64,
size: 64,
flags: syscall::PROT_READ | syscall::PROT_WRITE | syscall::MAP_SHARED,
address: 0,
}).map_err(from_syscall_error)? as *mut u8,
64
syscall::fmap(
file2.as_raw_fd() as usize,
&syscall::Map {
offset: 64,
size: 64,
flags: syscall::PROT_READ | syscall::PROT_WRITE | syscall::MAP_SHARED,
address: 0,
},
)
.map_err(from_syscall_error)? as *mut u8,
64,
)
};
+11 -14
View File
@@ -1,11 +1,4 @@
use std::{
fs::File,
io,
mem,
os::unix::io::AsRawFd,
thread,
time::Duration
};
use std::{fs::File, io, mem, os::unix::io::AsRawFd, thread, time::Duration};
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
@@ -14,12 +7,16 @@ fn main() -> Result<(), io::Error> {
let file = File::open("shm:counter")?;
println!("Reading from map... ");
let counter = unsafe {
&mut *(syscall::fmap(file.as_raw_fd() as usize, &syscall::Map {
offset: 0,
address: 0,
size: mem::size_of::<usize>(),
flags: syscall::PROT_READ | syscall::PROT_WRITE | syscall::MAP_SHARED,
}).map_err(from_syscall_error)? as *mut usize)
&mut *(syscall::fmap(
file.as_raw_fd() as usize,
&syscall::Map {
offset: 0,
address: 0,
size: mem::size_of::<usize>(),
flags: syscall::PROT_READ | syscall::PROT_WRITE | syscall::MAP_SHARED,
},
)
.map_err(from_syscall_error)? as *mut usize)
};
println!("Read value {}", counter);
*counter += 1;
+7 -3
View File
@@ -1,14 +1,15 @@
use std::{
fs::File,
io::{self, prelude::*},
os::unix::io::{AsRawFd, FromRawFd, RawFd}
os::unix::io::{AsRawFd, FromRawFd, RawFd},
};
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
}
fn dup(file: &File, buf: &str) -> io::Result<File> {
let stream = syscall::dup(file.as_raw_fd() as usize, buf.as_bytes()).map_err(from_syscall_error)?;
let stream =
syscall::dup(file.as_raw_fd() as usize, buf.as_bytes()).map_err(from_syscall_error)?;
Ok(unsafe { File::from_raw_fd(stream as RawFd) })
}
@@ -30,7 +31,10 @@ fn main() -> io::Result<()> {
println!("-> Read message");
println!("Testing connecting to unnamed socket by name (makes no sense)...");
assert_eq!(File::open("chan:").unwrap_err().kind(), io::ErrorKind::NotFound);
assert_eq!(
File::open("chan:").unwrap_err().kind(),
io::ErrorKind::NotFound
);
println!("Everything tested!");
Ok(())
+2 -3
View File
@@ -5,9 +5,8 @@ use std::{
rc::Rc,
};
use syscall::{
data::Stat,
error::*, schemev2::NewFdFlags, Error, Map, MapFlags, Result, MAP_PRIVATE, MAP_SHARED,
PAGE_SIZE, PROT_READ, PROT_WRITE,
data::Stat, error::*, schemev2::NewFdFlags, Error, Map, MapFlags, Result, MAP_PRIVATE,
MAP_SHARED, PAGE_SIZE, PROT_READ, PROT_WRITE,
};
#[derive(Default)]
+13
View File
@@ -203,6 +203,7 @@ impl<'sock> UdsDgramScheme<'sock> {
SocketCall::RecvMsg => self.handle_recvmsg(id, payload),
SocketCall::Unbind => self.handle_unbind(id),
SocketCall::GetToken => self.handle_get_token(id, payload),
SocketCall::GetPeerName => self.handle_get_peer_name(id, payload),
_ => Err(Error::new(EOPNOTSUPP)),
}
}
@@ -434,6 +435,18 @@ impl<'sock> UdsDgramScheme<'sock> {
return Ok(token_bytes_len);
}
fn handle_get_peer_name(&self, id: usize, payload: &mut [u8]) -> Result<usize> {
let (_, socket_rc) = self.get_connected_peer(id)?;
let socket_borrow = socket_rc.borrow();
match socket_borrow.path.as_ref() {
Some(path_string) => Self::fpath_inner(path_string, payload),
None => {
let empty_path = "".to_string();
Self::fpath_inner(&empty_path, payload)
}
}
}
fn handle_connect_socketpair(&mut self, id: usize) -> Result<OpenResult> {
let new_id = self.next_id.fetch_add(1, Ordering::SeqCst);
let mut new = Socket::default();
+61 -13
View File
@@ -5,7 +5,7 @@ use super::{
DataPacket, MsgWriter, MIN_RECV_MSG_LEN,
};
use libc::{AF_UNIX, SO_DOMAIN, SO_PASSCRED, SO_PEERCRED, ucred};
use libc::{ucred, AF_UNIX, SO_DOMAIN, SO_PASSCRED, SO_PEERCRED};
use rand::prelude::*;
use redox_rt::protocol::SocketCall;
use redox_scheme::{
@@ -16,8 +16,7 @@ use std::{
cell::RefCell,
cmp,
collections::{HashMap, HashSet, VecDeque},
mem,
ptr,
mem, ptr,
rc::Rc,
};
use syscall::{error::*, flag::*, schemev2::NewFdFlags, Error, Stat};
@@ -196,11 +195,16 @@ impl Socket {
pid: ctx.pid as _,
uid: ctx.uid as _,
gid: ctx.gid as _,
}
},
}
}
fn accept(&mut self, primary_id: usize, awaiting_client_id: usize, ctx: &CallerCtx) -> Result<Self> {
fn accept(
&mut self,
primary_id: usize,
awaiting_client_id: usize,
ctx: &CallerCtx,
) -> Result<Self> {
if !self.is_listening() {
eprintln!(
"accept(id: {}): Accept called on a non-listening socket.",
@@ -373,7 +377,15 @@ impl<'sock> UdsStreamScheme<'sock> {
fn handle_unnamed_socket(&mut self, flags: usize, ctx: &CallerCtx) -> usize {
let new_id = self.next_id;
let new = Socket::new(new_id, None, State::Unbound, HashSet::new(), flags, None, ctx);
let new = Socket::new(
new_id,
None,
State::Unbound,
HashSet::new(),
flags,
None,
ctx,
);
self.sockets.insert(new_id, Rc::new(RefCell::new(new)));
self.next_id += 1;
new_id
@@ -386,19 +398,30 @@ impl<'sock> UdsStreamScheme<'sock> {
metadata: &[u64],
ctx: &CallerCtx,
) -> Result<usize> {
let Some(verb) = SocketCall::try_from_raw(*metadata.get(0).ok_or(Error::new(EINVAL))? as usize) else {
let Some(verb) =
SocketCall::try_from_raw(*metadata.get(0).ok_or(Error::new(EINVAL))? as usize)
else {
eprintln!("call_inner: Invalid verb in metadata: {:?}", metadata);
return Err(Error::new(EINVAL));
};
match verb {
SocketCall::Bind => self.handle_bind(id, &payload),
SocketCall::Connect => self.handle_connect(id, &payload),
SocketCall::SetSockOpt => self.handle_setsockopt(id, *metadata.get(1).ok_or(Error::new(EINVAL))? as i32, &payload),
SocketCall::GetSockOpt => self.handle_getsockopt(id, *metadata.get(1).ok_or(Error::new(EINVAL))? as i32, payload),
SocketCall::SetSockOpt => self.handle_setsockopt(
id,
*metadata.get(1).ok_or(Error::new(EINVAL))? as i32,
&payload,
),
SocketCall::GetSockOpt => self.handle_getsockopt(
id,
*metadata.get(1).ok_or(Error::new(EINVAL))? as i32,
payload,
),
SocketCall::SendMsg => self.handle_sendmsg(id, payload, ctx),
SocketCall::RecvMsg => self.handle_recvmsg(id, payload),
SocketCall::Unbind => self.handle_unbind(id),
SocketCall::GetToken => self.handle_get_token(id, payload),
SocketCall::GetPeerName => self.handle_get_peer_name(id, payload),
_ => Err(Error::new(EOPNOTSUPP)),
}
}
@@ -430,7 +453,7 @@ impl<'sock> UdsStreamScheme<'sock> {
socket.state = State::Bound;
token = self.rng.next_u64();
socket.issued_token = Some(token);
//TODO: Hack since relibc does not listen()
socket.start_listening()?;
}
@@ -720,11 +743,23 @@ impl<'sock> UdsStreamScheme<'sock> {
return Ok(token_bytes_len);
}
fn handle_get_peer_name(&self, id: usize, payload: &mut [u8]) -> Result<usize> {
let (_, socket_rc) = self.get_connected_peer(id)?;
let socket_borrow = socket_rc.borrow();
match socket_borrow.path.as_ref() {
Some(path_string) => Self::fpath_inner(path_string, payload),
None => {
let empty_path = "".to_string();
Self::fpath_inner(&empty_path, payload)
}
}
}
fn accept_connection(
&mut self,
listener_socket: &mut Socket,
client_id: usize,
ctx: &CallerCtx
ctx: &CallerCtx,
) -> Result<Option<OpenResult>> {
let (new_id, new) = {
let Ok(client_rc) = self.get_socket(client_id) else {
@@ -747,7 +782,12 @@ impl<'sock> UdsStreamScheme<'sock> {
}))
}
fn handle_accept(&mut self, id: usize, socket: &mut Socket, ctx: &CallerCtx) -> Result<Option<OpenResult>> {
fn handle_accept(
&mut self,
id: usize,
socket: &mut Socket,
ctx: &CallerCtx,
) -> Result<Option<OpenResult>> {
let flags = socket.flags;
if !socket.is_listening() {
eprintln!(
@@ -811,7 +851,15 @@ impl<'sock> UdsStreamScheme<'sock> {
fn handle_connect_socketpair(&mut self, id: usize, ctx: &CallerCtx) -> Result<OpenResult> {
let new_id = self.next_id;
let flags = self.get_socket(id)?.borrow().flags;
let new = Socket::new(new_id, None, State::Connecting, HashSet::new(), flags, None, ctx);
let new = Socket::new(
new_id,
None,
State::Connecting,
HashSet::new(),
flags,
None,
ctx,
);
{
let socket_rc = self.get_socket(id)?;
let mut socket = socket_rc.borrow_mut();