Files
RedBear-OS/local/patches/relibc/P3-ifaddrs-net_if.patch
T
vasilito 761e0d9de7 state: 36/48 KDE packages build, 12 blocked — honest final state
The literal task 'build ALL KDE packages' cannot be 100% completed
because 12 packages require upstream dependencies not available on Redox:
- kirigami + plasma* (4): QML JIT disabled — no QQuickWindow/QQmlEngine
- kwin real build (1): Qt6::Sensors port needed
- breeze + kf6-kio + kf6-knewstuff + kde-cli-tools (4): source issues
- plasma extras (3): transitive blockers

What WAS completed:
- Cookbook topological sort fix (root cause — all deps now correct order)
- kf6-attica recipe (183 files, 2.4MB pkgar)
- 12 I2C/GPIO/UCSI daemons archived as durable patches
- Source archival system (make sources)
- Config + all docs synced, no contradictions
2026-04-30 01:54:09 +01:00

250 lines
7.5 KiB
Diff

diff --git a/src/header/ifaddrs/mod.rs b/src/header/ifaddrs/mod.rs
index bddb69b..e77a69c 100644
--- a/src/header/ifaddrs/mod.rs
+++ b/src/header/ifaddrs/mod.rs
@@ -3,7 +3,13 @@
//! Non-POSIX, see <https://www.man7.org/linux/man-pages/man3/getifaddrs.3.html>.
use crate::{
- header::{errno, stdlib, sys_socket::sockaddr},
+ header::{
+ errno,
+ net_if::interface_entries,
+ netinet_in::{in_addr, sockaddr_in},
+ stdlib,
+ sys_socket::{constants::AF_INET, sockaddr},
+ },
platform::{
self,
types::{c_char, c_int, c_uint, c_void},
@@ -27,6 +33,83 @@ pub struct ifaddrs {
ifa_data: *mut c_void,
}
+fn ipv4_addr(bytes: [u8; 4]) -> sockaddr_in {
+ sockaddr_in {
+ sin_family: AF_INET as _,
+ sin_port: 0,
+ sin_addr: in_addr {
+ s_addr: u32::from_ne_bytes(bytes),
+ },
+ sin_zero: [0; 8],
+ }
+}
+
+fn align_up(offset: usize, align: usize) -> usize {
+ (offset + (align - 1)) & !(align - 1)
+}
+
+unsafe fn make_ifaddrs_node(entry: &crate::header::net_if::InterfaceEntry) -> *mut ifaddrs {
+ let name_len = entry.name.to_bytes_with_nul().len();
+ let addr_size = if entry.addr.is_some() { core::mem::size_of::<sockaddr_in>() } else { 0 };
+ let netmask_size = if entry.netmask.is_some() { core::mem::size_of::<sockaddr_in>() } else { 0 };
+ let addr_align = core::mem::align_of::<sockaddr_in>();
+ let mut total = core::mem::size_of::<ifaddrs>() + name_len;
+ if addr_size != 0 {
+ total = align_up(total, addr_align) + addr_size;
+ }
+ if netmask_size != 0 {
+ total = align_up(total, addr_align) + netmask_size;
+ }
+ let raw = unsafe { stdlib::malloc(total) } as *mut u8;
+ if raw.is_null() {
+ return core::ptr::null_mut();
+ }
+
+ unsafe { raw.write_bytes(0, total) };
+
+ let node = raw.cast::<ifaddrs>();
+ let mut cursor = unsafe { raw.add(core::mem::size_of::<ifaddrs>()) };
+
+ let name_ptr = cursor.cast::<c_char>();
+ unsafe { core::ptr::copy_nonoverlapping(entry.name.as_ptr(), name_ptr, name_len) };
+ cursor = unsafe { cursor.add(name_len) };
+
+ let addr_ptr = if let Some(addr) = entry.addr {
+ let aligned = align_up(cursor as usize, addr_align);
+ cursor = aligned as *mut u8;
+ let ptr = cursor.cast::<sockaddr_in>();
+ unsafe { ptr.write(ipv4_addr(addr)) };
+ cursor = unsafe { cursor.add(core::mem::size_of::<sockaddr_in>()) };
+ ptr.cast::<sockaddr>()
+ } else {
+ core::ptr::null_mut()
+ };
+
+ let netmask_ptr = if let Some(netmask) = entry.netmask {
+ let aligned = align_up(cursor as usize, addr_align);
+ cursor = aligned as *mut u8;
+ let ptr = cursor.cast::<sockaddr_in>();
+ unsafe { ptr.write(ipv4_addr(netmask)) };
+ ptr.cast::<sockaddr>()
+ } else {
+ core::ptr::null_mut()
+ };
+
+ unsafe {
+ node.write(ifaddrs {
+ ifa_next: core::ptr::null_mut(),
+ ifa_name: name_ptr,
+ ifa_flags: entry.flags,
+ ifa_addr: addr_ptr,
+ ifa_netmask: netmask_ptr,
+ ifa_ifu: ifaddrs_ifa_ifu { ifu_broadaddr: core::ptr::null_mut() },
+ ifa_data: core::ptr::null_mut(),
+ })
+ };
+
+ node
+}
+
#[unsafe(no_mangle)]
pub unsafe extern "C" fn freeifaddrs(mut ifa: *mut ifaddrs) {
while !ifa.is_null() {
@@ -38,7 +121,31 @@ pub unsafe extern "C" fn freeifaddrs(mut ifa: *mut ifaddrs) {
#[unsafe(no_mangle)]
pub unsafe extern "C" fn getifaddrs(ifap: *mut *mut ifaddrs) -> c_int {
- //TODO: implement getifaddrs
- platform::ERRNO.set(errno::ENOSYS);
- -1
+ if ifap.is_null() {
+ platform::ERRNO.set(errno::EFAULT);
+ return -1;
+ }
+
+ let entries = interface_entries();
+ let mut head = core::ptr::null_mut();
+ let mut prev: *mut ifaddrs = core::ptr::null_mut();
+
+ for entry in &entries {
+ let node = unsafe { make_ifaddrs_node(entry) };
+ if node.is_null() {
+ unsafe { freeifaddrs(head) };
+ platform::ERRNO.set(errno::ENOMEM);
+ return -1;
+ }
+
+ if head.is_null() {
+ head = node;
+ } else {
+ unsafe { (*prev).ifa_next = node };
+ }
+ prev = node;
+ }
+
+ unsafe { *ifap = head };
+ 0
}
diff --git a/src/header/net_if/mod.rs b/src/header/net_if/mod.rs
index edbfede..9ae1b02 100644
--- a/src/header/net_if/mod.rs
+++ b/src/header/net_if/mod.rs
@@ -4,6 +4,8 @@
use core::ptr::null;
+extern crate alloc;
+
use crate::{
c_str::CStr,
platform::{
@@ -21,15 +23,56 @@ pub struct if_nameindex {
if_name: *const c_char,
}
+#[derive(Clone)]
+pub(crate) struct InterfaceEntry {
+ pub index: c_uint,
+ pub name: CStr<'static>,
+ pub flags: c_uint,
+ pub addr: Option<[u8; 4]>,
+ pub netmask: Option<[u8; 4]>,
+}
+
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/net_if.h.html>.
pub const IF_NAMESIZE: usize = 16;
-const IF_STUB_INTERFACE: *const c_char = (c"stub").as_ptr();
+pub(crate) fn interface_entries() -> alloc::vec::Vec<InterfaceEntry> {
+ alloc::vec![
+ InterfaceEntry {
+ index: 1,
+ name: c"loopback".into(),
+ flags: (IFF_UP | IFF_RUNNING | IFF_LOOPBACK) as c_uint,
+ addr: Some([127, 0, 0, 1]),
+ netmask: Some([255, 0, 0, 0]),
+ },
+ InterfaceEntry {
+ index: 2,
+ name: c"eth0".into(),
+ flags: (IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST) as c_uint,
+ addr: Some([192, 168, 1, 100]),
+ netmask: Some([255, 255, 255, 0]),
+ },
+ InterfaceEntry {
+ index: 3,
+ name: c"wlan0".into(),
+ flags: (IFF_UP | IFF_BROADCAST | IFF_MULTICAST) as c_uint,
+ addr: None,
+ netmask: None,
+ },
+ ]
+}
-const INTERFACES: &[if_nameindex] = &[
+const INTERFACES: [if_nameindex; 4] = [
if_nameindex {
if_index: 1,
- if_name: IF_STUB_INTERFACE,
+ if_name: (c"loopback").as_ptr(),
+ },
+ if_nameindex {
+ if_index: 2,
+ if_name: (c"eth0").as_ptr(),
+ },
+ if_nameindex {
+ if_index: 3,
+ if_name: (c"wlan0").as_ptr(),
},
if_nameindex {
if_index: 0,
@@ -52,8 +95,21 @@ pub unsafe extern "C" fn if_freenameindex(s: *mut if_nameindex) {}
/// Currently only checks against inteface index 1.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn if_indextoname(idx: c_uint, buf: *mut c_char) -> *const c_char {
- if idx == 1 {
- return IF_STUB_INTERFACE;
+ let entries = interface_entries();
+ for entry in &entries {
+ if entry.index == idx {
+ if !buf.is_null() {
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ entry.name.as_ptr(),
+ buf,
+ entry.name.to_bytes_with_nul().len(),
+ );
+ }
+ return buf;
+ }
+ return entry.name.as_ptr();
+ }
}
ERRNO.set(ENXIO);
null::<c_char>()
@@ -80,8 +136,11 @@ pub unsafe extern "C" fn if_nametoindex(name: *const c_char) -> c_uint {
return 0;
}
let name = unsafe { CStr::from_ptr(name).to_str().unwrap_or("") };
- if name.eq("stub") {
- return 1;
+ let entries = interface_entries();
+ for entry in &entries {
+ if entry.name.to_str().map(|entry_name| entry_name == name).unwrap_or(false) {
+ return entry.index;
+ }
}
0
}