From 2fd85ccda8d7938ba05c2492bd56b5c25bad77a1 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 24 Jan 2025 21:19:26 +0000 Subject: [PATCH] freebsd add basic ethernet frames support [reference](https://github.com/freebsd/freebsd-src/blob/stable/14/sys/net/ethernet.h) --- libc-test/build.rs | 1 + libc-test/semver/freebsd.txt | 13 ++++ src/unix/bsd/freebsdlike/freebsd/mod.rs | 87 +++++++++++++++++++++++++ 3 files changed, 101 insertions(+) diff --git a/libc-test/build.rs b/libc-test/build.rs index eb2a5dfe72c4..71651b40c498 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -2197,6 +2197,7 @@ fn test_freebsd(target: &str) { "memstat.h", "mqueue.h", "net/bpf.h", + "net/ethernet.h", "net/if.h", "net/if_arp.h", "net/if_dl.h", diff --git a/libc-test/semver/freebsd.txt b/libc-test/semver/freebsd.txt index b4f770c571dd..9367fd91fc4f 100644 --- a/libc-test/semver/freebsd.txt +++ b/libc-test/semver/freebsd.txt @@ -377,6 +377,17 @@ ERA_T_FMT EREMOTE ERPCMISMATCH ESOCKTNOSUPPORT +ETHER_ADDR_LEN +ETHER_CRC_LEN +ETHER_HDR_LEN +ETHER_IS_BROADCAST +ETHER_IS_IPV6_MULTICAST +ETHER_IS_MULTICAST +ETHER_IS_ZERO +ETHER_MIN_LEN +ETHER_MAX_LEN +ETHER_MAX_LEN_JUMBO +ETHER_TYPE_LEN ETOOMANYREFS EUSERS EVFILT_AIO @@ -1915,6 +1926,8 @@ endpwent endservent endutxent erand48 +ether_addr +ether_header eui64_aton eui64_hostton eui64_ntoa diff --git a/src/unix/bsd/freebsdlike/freebsd/mod.rs b/src/unix/bsd/freebsdlike/freebsd/mod.rs index 1e9ab1576625..c49b90470779 100644 --- a/src/unix/bsd/freebsdlike/freebsd/mod.rs +++ b/src/unix/bsd/freebsdlike/freebsd/mod.rs @@ -1661,6 +1661,18 @@ s_no_extra_traits! { pub uc_flags: c_int, __spare__: [c_int; 4], } + + #[repr(packed)] + pub struct ether_header { + pub ether_dhost: [crate::u_char; ETHER_ADDR_LEN as usize], + pub ether_shost: [crate::u_char; ETHER_ADDR_LEN as usize], + pub ether_type: crate::u_short, + } + + #[repr(packed)] + pub struct ether_addr { + pub octet: [crate::u_char; ETHER_ADDR_LEN as usize], + } } cfg_if! { @@ -2541,6 +2553,53 @@ cfg_if! { .finish() } } + + impl PartialEq for ether_header { + fn eq(&self, other: ðer_header) -> bool { + self.ether_dhost.iter().zip(other.ether_dhost.iter()).all(|(a, b)| a == b) + && self.ether_dhost.iter().zip(other.ether_shost.iter()).all(|(a, b)| a == b) + && self.ether_type == other.ether_type + } + } + + impl Eq for ether_header {} + impl fmt::Debug for ether_header { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ether_header") + .field("ether_dhost", &{ self.ether_dhost }) + .field("ether_shost", &{ self.ether_shost }) + .field("ether_type", &{ self.ether_type }) + .finish() + } + } + + impl hash::Hash for ether_header { + fn hash(&self, state: &mut H) { + { self.ether_dhost }.hash(state); + { self.ether_shost }.hash(state); + { self.ether_type }.hash(state); + } + } + + impl PartialEq for ether_addr { + fn eq(&self, other: ðer_addr) -> bool { + self.octet.iter().zip(other.octet.iter()).all(|(a, b)| a == b) + } + } + + impl Eq for ether_addr {} + impl fmt::Debug for ether_addr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ether_addr") + .field("octet", &{ self.octet }) + .finish() + } + } + impl hash::Hash for ether_header { + fn hash(&self, state: &mut H) { + { self.octet }.hash(state); + } + } } } @@ -4647,6 +4706,16 @@ pub const RTM_VERSION: c_int = 5; pub const RTAX_MAX: c_int = 8; +// net/ethernet.h + +pub const ETHER_ADDR_LEN: c_int = 6; +pub const ETHER_TYPE_LEN: c_int = 2; +pub const ETHER_CRC_LEN: c_int = 4; +pub const ETHER_HDR_LEN: c_int = ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN; +pub const ETHER_MIN_LEN: c_int = 64; +pub const ETHER_MAX_LEN: c_int = 1518; +pub const ETHER_MAX_LEN_JUMBO: c_int = 9018; + // sys/signal.h pub const SIGTHR: c_int = 32; pub const SIGLWP: c_int = SIGTHR; @@ -4957,6 +5026,24 @@ f! { pub fn PROT_MAX_EXTRACT(x: c_int) -> c_int { (x >> 16) & (crate::PROT_READ | crate::PROT_WRITE | crate::PROT_EXEC) } + + pub {const} fn ETHER_IS_MULTICAST(addr: *mut u_char) -> bool { + (*addr.wrapping_add(0)) & 0x01 != 0x00 + } + + pub {const} fn ETHER_IS_IPV6_MULTICAST(addr: *mut u_char) -> bool { + (*addr.wrapping_add(0)) == 0x33 && (*addr.wrapping_add(1)) == 0x33 + } + + pub {const} fn ETHER_IS_BROADCAST(addr: *mut u_char) -> bool { + (*addr.wrapping_add(0)) & (*addr.wrapping_add(1)) & (*addr.wrapping_add(2)) + & (*addr.wrapping_add(3)) & (*addr.wrapping_add(4)) & (*addr.wrapping_add(5)) == 0xff + } + + pub {const} fn ETHER_IS_ZERO(addr: *mut u_char) -> bool { + (*addr.wrapping_add(0)) | (*addr.wrapping_add(1)) | (*addr.wrapping_add(2)) + | (*addr.wrapping_add(3)) | (*addr.wrapping_add(4)) | (*addr.wrapping_add(5)) == 0x00 + } } safe_f! {