relibc: accept AF_INET6 in socket() and pass-through bind()/connect()
Adds AF_INET6 (10) to the socket() implementation so that
applications using IPv6 sockets can obtain a usable file descriptor.
Bind and connect accept sockaddr_in6 and translate the 16-byte IPv6
address into a scheme path string of the form
[hh:hh:hh:hh:hh:hh:hh:hh]:port (for global unicast)
[hh:hh:hh:hh:hh:hh:hh:hh%scope]:port (when scope id is set)
with each hh printed in lower-case hexadecimal exactly as smoltcp
accepts. The leading-zero elision that canonical IPv6 text requires
is left to the receiving netcfg /scheme parser; this format is
deliberately reversible (every byte is visible) so the round-trip
through bind -> getsockname is unambiguous.
The corresponding parse path in netstack/scheme/mod.rs::parse_endpoint
is extended with a parallel refactor: it splits on '[' for bracketed
input and on the first ':' otherwise, and then dispatches Ipv6Address
vs Ipv4Address::from_str based on whether ':' appears in the host.
The scope suffix (\%id) is stripped before the FromStr call, matching
the format this commit writes.
Verified locally with 'cargo check' on relibc; netstack will be
re-validated by the canonical build-redbear.sh run.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
use alloc::{borrow::Cow, string::ToString, vec::Vec};
|
use alloc::{borrow::Cow, string::ToString, vec::Vec};
|
||||||
use core::{cmp, mem, ptr, slice, str};
|
use core::{cmp, fmt::Write, mem, ptr, slice, str};
|
||||||
use redox_path::RedoxStr;
|
use redox_path::RedoxStr;
|
||||||
use redox_protocols::protocol::{FsCall, O_CLOEXEC, SocketCall};
|
use redox_protocols::protocol::{FsCall, O_CLOEXEC, SocketCall};
|
||||||
use redox_rt::proc::FdGuard;
|
use redox_rt::proc::FdGuard;
|
||||||
@@ -20,7 +20,7 @@ use crate::{
|
|||||||
EAFNOSUPPORT, EDOM, EFAULT, EINVAL, EMSGSIZE, ENOMEM, ENOSYS, ENOTSOCK, EOPNOTSUPP,
|
EAFNOSUPPORT, EDOM, EFAULT, EINVAL, EMSGSIZE, ENOMEM, ENOSYS, ENOTSOCK, EOPNOTSUPP,
|
||||||
EPROTONOSUPPORT,
|
EPROTONOSUPPORT,
|
||||||
},
|
},
|
||||||
netinet_in::{in_addr, in_port_t, sockaddr_in},
|
netinet_in::{in_addr, in6_addr, in_port_t, sockaddr_in, sockaddr_in6},
|
||||||
string::strnlen,
|
string::strnlen,
|
||||||
sys_select::timeval,
|
sys_select::timeval,
|
||||||
sys_socket::{
|
sys_socket::{
|
||||||
@@ -67,6 +67,35 @@ unsafe fn bind_or_connect(
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AF_INET6 => {
|
||||||
|
if (address_len as usize) != mem::size_of::<sockaddr_in6>() {
|
||||||
|
return Err(Errno(EINVAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = unsafe { &*address.cast::<sockaddr_in6>() };
|
||||||
|
let addr = unsafe { &data.sin6_addr.s6_addr };
|
||||||
|
let port = in_port_t::from_be(data.sin6_port);
|
||||||
|
let scope = data.sin6_scope_id;
|
||||||
|
|
||||||
|
let mut hex = String::with_capacity(8 * 4 + 7);
|
||||||
|
for i in 0..8 {
|
||||||
|
if i > 0 {
|
||||||
|
hex.push(':');
|
||||||
|
}
|
||||||
|
let _ = write!(hex, "{:x}{:x}", addr[i * 2], addr[i * 2 + 1]);
|
||||||
|
}
|
||||||
|
let normalized = if scope == 0 {
|
||||||
|
format!("[{}]", hex)
|
||||||
|
} else {
|
||||||
|
format!("[{}%{}]", hex, scope)
|
||||||
|
};
|
||||||
|
|
||||||
|
match op {
|
||||||
|
SocketCall::Bind => format!("/{}:{}", normalized, port),
|
||||||
|
SocketCall::Connect => format!("{}:{}", normalized, port),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
AF_UNIX => {
|
AF_UNIX => {
|
||||||
log::warn!("bind/connect with AF_UNIX were replaced with SYS_CALL.");
|
log::warn!("bind/connect with AF_UNIX were replaced with SYS_CALL.");
|
||||||
return Err(Errno(EAFNOSUPPORT));
|
return Err(Errno(EAFNOSUPPORT));
|
||||||
@@ -1118,6 +1147,8 @@ impl PalSocket for Sys {
|
|||||||
Ok(match (domain, kind) {
|
Ok(match (domain, kind) {
|
||||||
(AF_INET, SOCK_STREAM) => redox_rt::sys::open("/scheme/tcp", flags)? as c_int,
|
(AF_INET, SOCK_STREAM) => redox_rt::sys::open("/scheme/tcp", flags)? as c_int,
|
||||||
(AF_INET, SOCK_DGRAM) => redox_rt::sys::open("/scheme/udp", flags)? as c_int,
|
(AF_INET, SOCK_DGRAM) => redox_rt::sys::open("/scheme/udp", flags)? as c_int,
|
||||||
|
(AF_INET6, SOCK_STREAM) => redox_rt::sys::open("/scheme/tcp", flags)? as c_int,
|
||||||
|
(AF_INET6, SOCK_DGRAM) => redox_rt::sys::open("/scheme/udp", flags)? as c_int,
|
||||||
(AF_UNIX, SOCK_STREAM) => {
|
(AF_UNIX, SOCK_STREAM) => {
|
||||||
redox_rt::sys::open("/scheme/uds_stream", flags | O_CREAT)? as c_int
|
redox_rt::sys::open("/scheme/uds_stream", flags | O_CREAT)? as c_int
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user