diff --git a/src/header/mod.rs b/src/header/mod.rs index 42b8d270f4fcfbae25c94d9753a4d6c95f4a76a1..12d20f96c4779ba35e72343ab432f8dc125ec910 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -22,6 +22,7 @@ pub mod inttypes; pub mod libgen; pub mod limits; pub mod locale; +pub mod net_if; pub mod netdb; pub mod netinet_in; pub mod netinet_ip; diff --git a/src/header/net_if/cbindgen.toml b/src/header/net_if/cbindgen.toml new file mode 100644 index 0000000000000000000000000000000000000000..af56fa8a4edcdbdb6467fa8a6dd2c2fffc479783 --- /dev/null +++ b/src/header/net_if/cbindgen.toml @@ -0,0 +1,9 @@ +sys_includes = [] +include_guard = "_NET_IF_H" +language = "C" +style = "Tag" +no_includes = true +cpp_compat = true + +[enum] +prefix_with_name = true diff --git a/src/header/net_if/mod.rs b/src/header/net_if/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..2b4daf8c0c56434453d0914827e648557a9bd206 --- /dev/null +++ b/src/header/net_if/mod.rs @@ -0,0 +1,72 @@ +use core::ptr::null; + +use alloc::ffi::CString; + +use crate::{ + c_str::CStr, + platform::{types::*, ERRNO}, +}; + +use super::errno::ENXIO; + +#[repr(C)] +pub struct if_nameindex { + if_index: c_uint, + if_name: *const c_char, +} + +pub const IF_NAMESIZE: usize = 16; + +const IF_STUB_INTERFACE: *const c_char = (c"stub").as_ptr(); + +const INTERFACES: &[if_nameindex] = &[ + if_nameindex { + if_index: 1, + if_name: IF_STUB_INTERFACE, + }, + if_nameindex { + if_index: 0, + if_name: null::<c_char>(), + }, +]; + +/// # Safety +/// Returns a constant pointer to a pre defined const stub list +/// The end of the list is determined by an if_nameindex struct having if_index 0 and if_name NULL +#[no_mangle] +pub unsafe extern "C" fn if_nameindex() -> *const if_nameindex { + &INTERFACES[0] as *const if_nameindex +} + +/// # Safety +/// this is a no-op: the list returned by if_nameindex() is a ref to a constant +#[no_mangle] +pub unsafe extern "C" fn if_freenameindex(s: *mut if_nameindex) {} + +/// # Safety +/// Compares the name to a constant string and only returns an int as a result. +/// An invalid name string will return an index of 0 +#[no_mangle] +pub unsafe extern "C" fn if_nametoindex(name: *const c_char) -> c_uint { + if name == null::<c_char>() { + return 0; + } + let name = CStr::from_ptr(name).to_str().unwrap_or(""); + if name.eq("stub") { + return 1; + } + 0 +} + +/// # Safety +/// Returns only static lifetime references to const names, does not reuse the buf pointer. +/// Returns NULL in case of not found + ERRNO being set to ENXIO. +/// Currently only checks against inteface index 1. +#[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; + } + ERRNO.set(ENXIO); + null::<c_char>() +} diff --git a/tests/Makefile b/tests/Makefile index 73bb54dc20cd46b48e48957e34f274b166875a8a..91d251ac71ff504e6cab9a6c9d450b72b7d0f43e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -158,6 +158,7 @@ DYNAMIC_ONLY_NAMES=\ NAMES=\ $(EXPECT_NAMES) \ dirent/main \ + net/if \ pty/forkpty \ psignal \ pwd \ diff --git a/tests/net/if.c b/tests/net/if.c new file mode 100644 index 0000000000000000000000000000000000000000..5cce1465f4f9d8ec830219be855139d9ec0bbf68 --- /dev/null +++ b/tests/net/if.c @@ -0,0 +1,43 @@ +#include <net/if.h> +#include <string.h> + +#include "../test_helpers.h" + +#define assert_eq(value, expected) \ + { \ + if (value != expected) { \ + fprintf(stderr, "%s:%d: failed\n", __FILE__, __LINE__); \ + exit(EXIT_FAILURE); \ + } \ + } + +int main(void) { + const struct if_nameindex *list = if_nameindex(); + + // Currently always returning a stub + const struct if_nameindex *first = &(list[0]); + assert_eq(first->if_index, 1); + assert_eq(strcmp(first->if_name, "stub"), 0); + + // Last item with 0 values determines the end of the list + const struct if_nameindex *second = &(list[1]); + assert_eq(second->if_index, 0); + assert_eq(second->if_name, 0); + + unsigned idx; + idx = if_nametoindex(0); + assert_eq(idx, 0); + idx = if_nametoindex("any"); + assert_eq(idx, 0); + idx = if_nametoindex("stub"); + assert_eq(idx, 1); + + const char *name; + name = if_indextoname(0, 0); + assert_eq(name, 0); + + name = if_indextoname(1, 0); + assert_eq(strcmp(name, "stub"), 0); + + printf("OK\n"); +}