diff --git a/libc-test/Cargo.toml b/libc-test/Cargo.toml index 8d2d9033308b7fb0ff42b0fec5b81e92877f0791..0b6866d49c0bba21acb3c97a097612e77574a51f 100644 --- a/libc-test/Cargo.toml +++ b/libc-test/Cargo.toml @@ -52,3 +52,8 @@ harness = false name = "cmsg" path = "test/cmsg.rs" harness = true + +[[test]] +name = "errqueue" +path = "test/errqueue.rs" +harness = true diff --git a/libc-test/build.rs b/libc-test/build.rs index 9001000b26389cf065ae328e9fc59af7684c48a0..8ab5d89592d56835c43a00704631f9307e41fd5e 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -10,6 +10,9 @@ fn do_cc() { if cfg!(unix) && !target.contains("wasi") { cc::Build::new().file("src/cmsg.c").compile("cmsg"); } + if target.contains("android") || target.contains("linux") { + cc::Build::new().file("src/errqueue.c").compile("errqueue"); + } } fn do_ctest() { @@ -1239,7 +1242,6 @@ fn test_android(target: &str) { headers! { cfg: "arpa/inet.h", - "asm/mman.h", "ctype.h", "dirent.h", "dlfcn.h", @@ -1248,27 +1250,6 @@ fn test_android(target: &str) { "grp.h", "ifaddrs.h", "limits.h", - "linux/dccp.h", - "linux/futex.h", - "linux/fs.h", - "linux/genetlink.h", - "linux/if_alg.h", - "linux/if_ether.h", - "linux/if_tun.h", - "linux/magic.h", - "linux/memfd.h", - "linux/module.h", - "linux/net_tstamp.h", - "linux/netfilter/nfnetlink.h", - "linux/netfilter/nfnetlink_log.h", - "linux/netfilter/nf_tables.h", - "linux/netfilter_ipv4.h", - "linux/netfilter_ipv6.h", - "linux/netlink.h", - "linux/quota.h", - "linux/reboot.h", - "linux/seccomp.h", - "linux/sockios.h", "locale.h", "malloc.h", "net/ethernet.h", @@ -1339,6 +1320,34 @@ fn test_android(target: &str) { [x86]: "sys/reg.h", } + // Include linux headers at the end: + headers! { cfg: + "asm/mman.h", + "linux/dccp.h", + "linux/errqueue.h", + "linux/futex.h", + "linux/fs.h", + "linux/genetlink.h", + "linux/if_alg.h", + "linux/if_ether.h", + "linux/if_tun.h", + "linux/magic.h", + "linux/memfd.h", + "linux/module.h", + "linux/net_tstamp.h", + "linux/netfilter/nfnetlink.h", + "linux/netfilter/nfnetlink_log.h", + "linux/netfilter/nf_tables.h", + "linux/netfilter_ipv4.h", + "linux/netfilter_ipv6.h", + "linux/netlink.h", + "linux/quota.h", + "linux/reboot.h", + "linux/seccomp.h", + "linux/sockios.h", + + } + cfg.type_name(move |ty, is_struct, is_union| { match ty { // Just pass all these through, no need for a "struct" prefix @@ -2188,6 +2197,7 @@ fn test_linux(target: &str) { cfg: "asm/mman.h", "linux/dccp.h", + "linux/errqueue.h", "linux/falloc.h", "linux/fs.h", "linux/futex.h", diff --git a/libc-test/src/errqueue.c b/libc-test/src/errqueue.c new file mode 100644 index 0000000000000000000000000000000000000000..931ca91bbf8c834e666ca482d609ee59c4064d1f --- /dev/null +++ b/libc-test/src/errqueue.c @@ -0,0 +1,10 @@ +#include <time.h> +#include <linux/errqueue.h> + +// SO_EE_OFFENDER is defined as a macro in linux/errqueue.h. This file wraps +// that macro in a function so we can test the reimplementation in this package +// is equivalent. + +struct sockaddr *so_ee_offender(struct sock_extended_err *ee) { + return SO_EE_OFFENDER(ee); +} diff --git a/libc-test/test/errqueue.rs b/libc-test/test/errqueue.rs new file mode 100644 index 0000000000000000000000000000000000000000..8d0c7bb7416761604f8abe30fb087b62c6d5b5fb --- /dev/null +++ b/libc-test/test/errqueue.rs @@ -0,0 +1,22 @@ +//! Compare libc's SO_EE_OFFENDER function against the actual C macro + +extern crate libc; + +#[cfg(any(target_os = "linux", target_os = "android"))] +mod t { + use libc::{self, sock_extended_err, sockaddr}; + + extern "C" { + pub fn so_ee_offender(ee: *const sock_extended_err) -> *mut sockaddr; + } + + #[test] + fn test_cmsg_data() { + for l in 0..128 { + let ee = l as *const sock_extended_err; + unsafe { + assert_eq!(libc::SO_EE_OFFENDER(ee), so_ee_offender(ee)); + } + } + } +} diff --git a/src/unix/linux_like/mod.rs b/src/unix/linux_like/mod.rs index 792548f981b69073fde5832e05705b96d08297bd..5b2fb11c33258538323bc0e6f0fedb87e1af4236 100644 --- a/src/unix/linux_like/mod.rs +++ b/src/unix/linux_like/mod.rs @@ -199,6 +199,16 @@ s! { pub msg_hdr: ::msghdr, pub msg_len: ::c_uint, } + + pub struct sock_extended_err { + pub ee_errno: u32, + pub ee_origin: u8, + pub ee_type: u8, + pub ee_code: u8, + pub ee_pad: u8, + pub ee_info: u32, + pub ee_data: u32 + } } s_no_extra_traits! { @@ -1189,6 +1199,13 @@ pub const ARPHRD_IEEE802154: u16 = 804; pub const ARPHRD_VOID: u16 = 0xFFFF; pub const ARPHRD_NONE: u16 = 0xFFFE; +pub const SO_EE_ORIGIN_NONE: u8 = 0; +pub const SO_EE_ORIGIN_LOCAL: u8 = 1; +pub const SO_EE_ORIGIN_ICMP: u8 = 2; +pub const SO_EE_ORIGIN_ICMP6: u8 = 3; +pub const SO_EE_ORIGIN_TXSTATUS: u8 = 4; +pub const SO_EE_ORIGIN_TIMESTAMPING: u8 = SO_EE_ORIGIN_TXSTATUS; + const_fn! { {const} fn CMSG_ALIGN(len: usize) -> usize { len + ::mem::size_of::<usize>() - 1 & !(::mem::size_of::<usize>() - 1) @@ -1294,6 +1311,10 @@ f! { pub fn IPTOS_ECN(x: u8) -> u8 { x & ::IPTOS_ECN_MASK } + + pub fn SO_EE_OFFENDER(ee: *const ::sock_extended_err) -> *mut ::sockaddr { + ee.offset(1) as *mut ::sockaddr + } } extern "C" {