From 1fa20624ffa5d34d1d133ef5960296671323407b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 12 Jan 2025 11:35:14 +0000 Subject: [PATCH] adding ethhdr type for linux/android for proper packet filtering. [ref](https://docs.huihoo.com/doxygen/linux/kernel/3.7/structethhdr.html) --- libc-test/build.rs | 8 ++++++ libc-test/semver/android.txt | 1 + libc-test/semver/linux-gnu.txt | 1 + src/unix/linux_like/android/mod.rs | 37 ++++++++++++++++++++++++++++ src/unix/linux_like/linux/gnu/mod.rs | 37 ++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+) diff --git a/libc-test/build.rs b/libc-test/build.rs index 5ed1ec2e0aeb2..8a591e18468dd 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -2301,6 +2301,8 @@ fn test_android(target: &str) { (struct_ == "sigaction" && field == "sa_sigaction") || // signalfd had SIGSYS fields added in Android 4.19, but CI does not have that version yet. (struct_ == "signalfd_siginfo" && field == "ssi_call_addr") || + // FIXME: `h_proto` is of type __be16 big endian version of __u16 + (struct_ == "ethhdr" && field == "h_proto") || // FIXME(android): Seems the type has been changed on NDK r26b (struct_ == "flock64" && (field == "l_start" || field == "l_len")) }); @@ -3918,6 +3920,10 @@ fn test_linux(target: &str) { if sparc64 && (ty == "Elf32_Rela" || ty == "Elf64_Rela") { return true; } + // FIXME: alignment issue with this arch + if loongarch64 && ty == "ethhdr" { + return true; + } match ty { // FIXME(sighandler): `sighandler_t` type is incorrect, see: // https://github.com/rust-lang/libc/issues/1359 @@ -4676,6 +4682,8 @@ fn test_linux(target: &str) { (struct_ == "ptp_perout_request" && field == "anonymous_1") || // `anonymous_2` is an anonymous union (struct_ == "ptp_perout_request" && field == "anonymous_2") || + // FIXME: `h_proto` is of type __be16 big endian version of __u16 + (struct_ == "ethhdr" && field == "h_proto") || // FIXME(linux): `adjust_phase` requires >= 5.7 kernel headers // FIXME(linux): `max_phase_adj` requires >= 5.19 kernel headers // the rsv field shrunk when those fields got added, so is omitted too diff --git a/libc-test/semver/android.txt b/libc-test/semver/android.txt index a15912611a0aa..ba78c58eb3180 100644 --- a/libc-test/semver/android.txt +++ b/libc-test/semver/android.txt @@ -3277,6 +3277,7 @@ epoll_create1 epoll_ctl epoll_event epoll_wait +ethhdr eventfd eventfd_read eventfd_write diff --git a/libc-test/semver/linux-gnu.txt b/libc-test/semver/linux-gnu.txt index 7f04169042c14..96b06921c4a16 100644 --- a/libc-test/semver/linux-gnu.txt +++ b/libc-test/semver/linux-gnu.txt @@ -590,6 +590,7 @@ dlmopen eaccess endutxent epoll_pwait2 +ethhdr euidaccess execveat explicit_bzero diff --git a/src/unix/linux_like/android/mod.rs b/src/unix/linux_like/android/mod.rs index 13d882be0075b..e0d093b0d2fb9 100644 --- a/src/unix/linux_like/android/mod.rs +++ b/src/unix/linux_like/android/mod.rs @@ -34,6 +34,7 @@ pub type __u16 = c_ushort; pub type __s16 = c_short; pub type __u32 = c_uint; pub type __s32 = c_int; +pub type __be16 = __u16; // linux/elf.h @@ -643,6 +644,15 @@ s_no_extra_traits! { pub ifc_len: c_int, pub ifc_ifcu: __c_anonymous_ifc_ifcu, } + + // linux/if_ether.h + + #[repr(C, packed)] + pub struct ethhdr { + pub h_dest: [c_uchar; crate::ETH_ALEN as usize], + pub h_source: [c_uchar; crate::ETH_ALEN as usize], + pub h_proto: crate::__be16, + } } cfg_if! { @@ -1025,6 +1035,33 @@ cfg_if! { .finish() } } + + impl Eq for ethhdr {} + + impl PartialEq for ethhdr { + fn eq(&self, other: ðhdr) -> bool { + self.h_dest + .iter() + .zip(other.h_dest.iter()) + .all(|(a, b)| a == b) + && self + .h_source + .iter() + .zip(other.h_source.iter()) + .all(|(a, b)| a == b) + && self.h_proto == other.h_proto + } + } + + impl fmt::Debug for ethhdr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ethhdr") + .field("h_dest", &self.h_dest) + .field("h_source", &self.h_source) + .field("h_proto", &{ self.h_proto }) + .finish() + } + } } } diff --git a/src/unix/linux_like/linux/gnu/mod.rs b/src/unix/linux_like/linux/gnu/mod.rs index 3a90a70d710eb..e906b6a701812 100644 --- a/src/unix/linux_like/linux/gnu/mod.rs +++ b/src/unix/linux_like/linux/gnu/mod.rs @@ -7,6 +7,7 @@ pub type __rlimit_resource_t = c_uint; pub type Lmid_t = c_long; pub type regoff_t = c_int; pub type __kernel_rwf_t = c_int; +pub type __be16 = crate::__u16; cfg_if! { if #[cfg(doc)] { @@ -466,6 +467,15 @@ s_no_extra_traits! { __pad: [c_char; 4], __glibc_reserved: [c_char; 32], } + + // linux/if_ether.h + + #[repr(C, packed)] + pub struct ethhdr { + pub h_dest: [c_uchar; crate::ETH_ALEN as usize], + pub h_source: [c_uchar; crate::ETH_ALEN as usize], + pub h_proto: crate::__be16, + } } // Internal, for casts to access union fields @@ -675,6 +685,33 @@ cfg_if! { } } } + + impl Eq for ethhdr {} + + impl PartialEq for ethhdr { + fn eq(&self, other: ðhdr) -> bool { + self.h_dest + .iter() + .zip(other.h_dest.iter()) + .all(|(a, b)| a == b) + && self + .h_source + .iter() + .zip(other.h_source.iter()) + .all(|(a, b)| a == b) + && self.h_proto == other.h_proto + } + } + + impl fmt::Debug for ethhdr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ethhdr") + .field("h_dest", &self.h_dest) + .field("h_source", &self.h_source) + .field("h_proto", &{ self.h_proto }) + .finish() + } + } } }