From 11f16c40bc0b528ad5e88db228362c6c320705e4 Mon Sep 17 00:00:00 2001 From: Nathaniel Bennett Date: Mon, 30 Sep 2024 23:27:50 -0400 Subject: [PATCH] Add additional Linux AF_PACKET options (#3540) --- libc-test/build.rs | 19 ++- libc-test/semver/linux.txt | 62 ++++++++ src/unix/linux_like/linux/align.rs | 18 +++ src/unix/linux_like/linux/mod.rs | 206 ++++++++++++++++++++++++++ src/unix/linux_like/linux/no_align.rs | 18 +++ 5 files changed, 322 insertions(+), 1 deletion(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index b6472b4ea56a8..ca1301320b211 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -3451,7 +3451,6 @@ fn test_linux(target: &str) { "netinet/ip.h", "netinet/tcp.h", "netinet/udp.h", - "netpacket/packet.h", "poll.h", "pthread.h", "pty.h", @@ -3554,6 +3553,7 @@ fn test_linux(target: &str) { "linux/if_addr.h", "linux/if_alg.h", "linux/if_ether.h", + "linux/if_packet.h", "linux/if_tun.h", "linux/if_xdp.h", "linux/input.h", @@ -3730,6 +3730,23 @@ fn test_linux(target: &str) { if (gnu && sparc64) && (ty == "ip_mreqn" || ty == "hwtstamp_config") { return true; } + // FIXME(https://github.com/rust-lang/rust/issues/43894): pass by value for structs that are not an even 32/64 bits on + // big-endian systems corrupts the value for unknown reasons. + if (sparc64 || ppc || ppc64 || s390x) + && (ty == "sockaddr_pkt" + || ty == "tpacket_auxdata" + || ty == "tpacket_hdr_variant1" + || ty == "tpacket_req3" + || ty == "tpacket_stats_v3" + || ty == "tpacket_req_u") + { + return true; + } + // FIXME: musl doesn't compile with `struct fanout_args` for unknown reasons. + if musl && ty == "fanout_args" { + return true; + } + match ty { // These cannot be tested when "resolv.h" is included and are tested // in the `linux_elf.rs` file. diff --git a/libc-test/semver/linux.txt b/libc-test/semver/linux.txt index 0bee4e68c16ae..ebbe04d1b7262 100644 --- a/libc-test/semver/linux.txt +++ b/libc-test/semver/linux.txt @@ -1805,11 +1805,38 @@ O_RSYNC O_SYNC O_TMPFILE PACKET_ADD_MEMBERSHIP +PACKET_AUXDATA +PACKET_BROADCAST PACKET_DROP_MEMBERSHIP +PACKET_FANOUT +PACKET_FANOUT_CBPF +PACKET_FANOUT_CPU +PACKET_FANOUT_FLAG_DEFRAG +PACKET_FANOUT_FLAG_ROLLOVER +PACKET_FANOUT_FLAG_UNIQUEID +PACKET_FANOUT_HASH +PACKET_FANOUT_LB +PACKET_FANOUT_QM +PACKET_FANOUT_RND +PACKET_FANOUT_ROLLOVER +PACKET_HOST +PACKET_KERNEL +PACKET_LOOPBACK +PACKET_LOSS PACKET_MR_ALLMULTI PACKET_MR_MULTICAST PACKET_MR_PROMISC PACKET_MR_UNICAST +PACKET_MULTICAST +PACKET_OTHERHOST +PACKET_OUTGOING +PACKET_QDISC_BYPASS +PACKET_RESERVE +PACKET_RX_RING +PACKET_STATISTICS +PACKET_TIMESTAMP +PACKET_USER +PACKET_VERSION PENDIN PF_ALG PF_APPLETALK @@ -3195,6 +3222,23 @@ TLS_GET_RECORD_TYPE TLS_RX TLS_SET_RECORD_TYPE TLS_TX +TP_FT_REQ_FILL_RXHASH +TP_STATUS_AVAILABLE +TP_STATUS_BLK_TMO +TP_STATUS_COPY +TP_STATUS_CSUMNOTREADY +TP_STATUS_CSUM_VALID +TP_STATUS_KERNEL +TP_STATUS_LOSING +TP_STATUS_SENDING +TP_STATUS_SEND_REQUEST +TP_STATUS_TS_RAW_HARDWARE +TP_STATUS_TS_SOFTWARE +TP_STATUS_TS_SYS_HARDWARE +TP_STATUS_USER +TP_STATUS_VLAN_TPID_VALID +TP_STATUS_VLAN_VALID +TP_STATUS_WRONG_FORMAT TUN_READQ_SIZE TUN_TAP_DEV TUN_TUN_DEV @@ -3457,6 +3501,7 @@ fanotify_event_metadata fanotify_init fanotify_mark fanotify_response +fanout_args fchdir fdatasync fdopendir @@ -3825,6 +3870,7 @@ sockaddr_alg sockaddr_can sockaddr_ll sockaddr_nl +sockaddr_pkt sockaddr_vm splice spwd @@ -3862,6 +3908,22 @@ timer_getoverrun timer_gettime timer_settime tmpfile64 +tpacket2_hdr +tpacket3_hdr +tpacket_auxdata +tpacket_bd_header_u +tpacket_bd_ts +tpacket_block_desc +tpacket_hdr +tpacket_hdr_v1 +tpacket_hdr_variant1 +tpacket_req +tpacket_req3 +tpacket_req_u +tpacket_rollover_stats +tpacket_stats +tpacket_stats_v3 +tpacket_versions truncate truncate64 ttyname_r diff --git a/src/unix/linux_like/linux/align.rs b/src/unix/linux_like/linux/align.rs index 1036e23dc8f09..bd16e449bb22c 100644 --- a/src/unix/linux_like/linux/align.rs +++ b/src/unix/linux_like/linux/align.rs @@ -63,6 +63,24 @@ macro_rules! expand_align { pub fd: ::c_int, pub pid: ::c_int, } + + #[repr(align(8))] + pub struct tpacket_rollover_stats { + pub tp_all: ::__u64, + pub tp_huge: ::__u64, + pub tp_failed: ::__u64, + } + + #[repr(align(8))] + pub struct tpacket_hdr_v1 { + pub block_status: ::__u32, + pub num_pkts: ::__u32, + pub offset_to_first_pkt: ::__u32, + pub blk_len: ::__u32, + pub seq_num: ::__u64, + pub ts_first_pkt: ::tpacket_bd_ts, + pub ts_last_pkt: ::tpacket_bd_ts, + } } s_no_extra_traits! { diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs index 1973b3f574efa..a7815ddfc3c14 100644 --- a/src/unix/linux_like/linux/mod.rs +++ b/src/unix/linux_like/linux/mod.rs @@ -58,6 +58,15 @@ missing! { pub enum fpos64_t {} // FIXME: fill this out with a struct } +e! { + #[repr(u32)] + pub enum tpacket_versions { + TPACKET_V1, + TPACKET_V2, + TPACKET_V3, + } +} + s! { pub struct glob_t { pub gl_pathc: ::size_t, @@ -140,6 +149,15 @@ s! { __val: [::c_int; 2], } + pub struct fanout_args { + #[cfg(target_endian = "little")] + pub id: ::__u16, + pub type_flags: ::__u16, + #[cfg(target_endian = "big")] + pub id: ::__u16, + pub max_num_members: ::__u32, + } + pub struct packet_mreq { pub mr_ifindex: ::c_int, pub mr_type: ::c_ushort, @@ -147,6 +165,98 @@ s! { pub mr_address: [::c_uchar; 8], } + pub struct sockaddr_pkt { + pub spkt_family: ::c_ushort, + pub spkt_device: [::c_uchar; 14], + pub spkt_protocol: ::c_ushort, + } + + pub struct tpacket_auxdata { + pub tp_status: ::__u32, + pub tp_len: ::__u32, + pub tp_snaplen: ::__u32, + pub tp_mac: ::__u16, + pub tp_net: ::__u16, + pub tp_vlan_tci: ::__u16, + pub tp_vlan_tpid: ::__u16, + } + + pub struct tpacket_hdr { + pub tp_status: ::c_ulong, + pub tp_len: ::c_uint, + pub tp_snaplen: ::c_uint, + pub tp_mac: ::c_ushort, + pub tp_net: ::c_ushort, + pub tp_sec: ::c_uint, + pub tp_usec: ::c_uint, + } + + pub struct tpacket_hdr_variant1 { + pub tp_rxhash: ::__u32, + pub tp_vlan_tci: ::__u32, + pub tp_vlan_tpid: ::__u16, + pub tp_padding: ::__u16, + } + + pub struct tpacket2_hdr { + pub tp_status: ::__u32, + pub tp_len: ::__u32, + pub tp_snaplen: ::__u32, + pub tp_mac: ::__u16, + pub tp_net: ::__u16, + pub tp_sec: ::__u32, + pub tp_nsec: ::__u32, + pub tp_vlan_tci: ::__u16, + pub tp_vlan_tpid: ::__u16, + pub tp_padding: [::__u8; 4], + } + + pub struct tpacket_req { + pub tp_block_size: ::c_uint, + pub tp_block_nr: ::c_uint, + pub tp_frame_size: ::c_uint, + pub tp_frame_nr: ::c_uint, + } + + pub struct tpacket_req3 { + pub tp_block_size: ::c_uint, + pub tp_block_nr: ::c_uint, + pub tp_frame_size: ::c_uint, + pub tp_frame_nr: ::c_uint, + pub tp_retire_blk_tov: ::c_uint, + pub tp_sizeof_priv: ::c_uint, + pub tp_feature_req_word: ::c_uint, + } + + pub struct tpacket_stats { + pub tp_packets: ::c_uint, + pub tp_drops: ::c_uint, + } + + pub struct tpacket_stats_v3 { + pub tp_packets: ::c_uint, + pub tp_drops: ::c_uint, + pub tp_freeze_q_cnt: ::c_uint, + } + + pub struct tpacket3_hdr { + pub tp_next_offset: ::__u32, + pub tp_sec: ::__u32, + pub tp_nsec: ::__u32, + pub tp_snaplen: ::__u32, + pub tp_len: ::__u32, + pub tp_status: ::__u32, + pub tp_mac: ::__u16, + pub tp_net: ::__u16, + pub hv1: ::tpacket_hdr_variant1, + pub tp_padding: [::__u8; 8], + } + + pub struct tpacket_bd_ts { + pub ts_sec: ::c_uint, + pub ts_usec: ::c_uint, + } + pub struct cpu_set_t { #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] @@ -890,6 +1000,27 @@ s_no_extra_traits! { pub sched_deadline: ::__u64, pub sched_period: ::__u64, } + + #[cfg(libc_union)] + #[allow(missing_debug_implementations)] + pub union tpacket_req_u { + pub req: ::tpacket_req, + pub req3: ::tpacket_req3, + } + + #[cfg(libc_union)] + #[allow(missing_debug_implementations)] + pub union tpacket_bd_header_u { + pub bh1: ::tpacket_hdr_v1, + } + + #[cfg(libc_union)] + #[allow(missing_debug_implementations)] + pub struct tpacket_block_desc { + pub version: ::__u32, + pub offset_to_priv: ::__u32, + pub hdr: ::tpacket_bd_header_u, + } } s_no_extra_traits! { @@ -2825,13 +2956,84 @@ pub const CTRL_ATTR_MCAST_GRP_NAME: ::c_int = 1; pub const CTRL_ATTR_MCAST_GRP_ID: ::c_int = 2; // linux/if_packet.h +pub const PACKET_HOST: ::c_uchar = 0; +pub const PACKET_BROADCAST: ::c_uchar = 1; +pub const PACKET_MULTICAST: ::c_uchar = 2; +pub const PACKET_OTHERHOST: ::c_uchar = 3; +pub const PACKET_OUTGOING: ::c_uchar = 4; +pub const PACKET_LOOPBACK: ::c_uchar = 5; +pub const PACKET_USER: ::c_uchar = 6; +pub const PACKET_KERNEL: ::c_uchar = 7; + pub const PACKET_ADD_MEMBERSHIP: ::c_int = 1; pub const PACKET_DROP_MEMBERSHIP: ::c_int = 2; +pub const PACKET_RX_RING: ::c_int = 5; +pub const PACKET_STATISTICS: ::c_int = 6; +pub const PACKET_AUXDATA: ::c_int = 8; +pub const PACKET_VERSION: ::c_int = 10; +pub const PACKET_RESERVE: ::c_int = 12; +pub const PACKET_TX_RING: ::c_int = 13; +pub const PACKET_LOSS: ::c_int = 14; +pub const PACKET_TIMESTAMP: ::c_int = 17; +pub const PACKET_FANOUT: ::c_int = 18; +pub const PACKET_QDISC_BYPASS: ::c_int = 20; + +pub const PACKET_FANOUT_HASH: ::c_uint = 0; +pub const PACKET_FANOUT_LB: ::c_uint = 1; +pub const PACKET_FANOUT_CPU: ::c_uint = 2; +pub const PACKET_FANOUT_ROLLOVER: ::c_uint = 3; +pub const PACKET_FANOUT_RND: ::c_uint = 4; +pub const PACKET_FANOUT_QM: ::c_uint = 5; +pub const PACKET_FANOUT_CBPF: ::c_uint = 6; +pub const PACKET_FANOUT_EBPF: ::c_uint = 7; +pub const PACKET_FANOUT_FLAG_ROLLOVER: ::c_uint = 0x1000; +pub const PACKET_FANOUT_FLAG_UNIQUEID: ::c_uint = 0x2000; +pub const PACKET_FANOUT_FLAG_DEFRAG: ::c_uint = 0x8000; pub const PACKET_MR_MULTICAST: ::c_int = 0; pub const PACKET_MR_PROMISC: ::c_int = 1; pub const PACKET_MR_ALLMULTI: ::c_int = 2; +pub const TP_STATUS_KERNEL: ::__u32 = 0; +pub const TP_STATUS_USER: ::__u32 = 1 << 0; +pub const TP_STATUS_COPY: ::__u32 = 1 << 1; +pub const TP_STATUS_LOSING: ::__u32 = 1 << 2; +pub const TP_STATUS_CSUMNOTREADY: ::__u32 = 1 << 3; +pub const TP_STATUS_VLAN_VALID: ::__u32 = 1 << 4; +pub const TP_STATUS_BLK_TMO: ::__u32 = 1 << 5; +pub const TP_STATUS_VLAN_TPID_VALID: ::__u32 = 1 << 6; +pub const TP_STATUS_CSUM_VALID: ::__u32 = 1 << 7; + +pub const TP_STATUS_AVAILABLE: ::__u32 = 0; +pub const TP_STATUS_SEND_REQUEST: ::__u32 = 1 << 0; +pub const TP_STATUS_SENDING: ::__u32 = 1 << 1; +pub const TP_STATUS_WRONG_FORMAT: ::__u32 = 1 << 2; + +pub const TP_STATUS_TS_SOFTWARE: ::__u32 = 1 << 29; +pub const TP_STATUS_TS_SYS_HARDWARE: ::__u32 = 1 << 30; +pub const TP_STATUS_TS_RAW_HARDWARE: ::__u32 = 1 << 31; + +pub const TP_FT_REQ_FILL_RXHASH: ::__u32 = 1; + +pub const TPACKET_ALIGNMENT: usize = 16; + +cfg_if! { + if #[cfg(libc_const_size_of)] { + pub const TPACKET_HDRLEN: usize = ( + (::mem::size_of::<::tpacket_hdr>() + TPACKET_ALIGNMENT - 1) + & !(TPACKET_ALIGNMENT - 1) + ) + ::mem::size_of::<::sockaddr_ll>(); + pub const TPACKET2_HDRLEN: usize = ( + (::mem::size_of::<::tpacket2_hdr>() + TPACKET_ALIGNMENT - 1) + & !(TPACKET_ALIGNMENT - 1) + ) + ::mem::size_of::<::sockaddr_ll>(); + pub const TPACKET3_HDRLEN: usize = ( + (::mem::size_of::<::tpacket3_hdr>() + TPACKET_ALIGNMENT - 1) + & !(TPACKET_ALIGNMENT - 1) + ) + ::mem::size_of::<::sockaddr_ll>(); + } +} + // linux/netfilter.h pub const NF_DROP: ::c_int = 0; pub const NF_ACCEPT: ::c_int = 1; @@ -4805,6 +5007,10 @@ f! { ee.offset(1) as *mut ::sockaddr } + pub fn TPACKET_ALIGN(x: usize) -> usize { + (x + TPACKET_ALIGNMENT - 1) & !(TPACKET_ALIGNMENT - 1) + } + pub fn BPF_RVAL(code: ::__u32) -> ::__u32 { code & 0x18 } diff --git a/src/unix/linux_like/linux/no_align.rs b/src/unix/linux_like/linux/no_align.rs index 328a5cc484231..f81d046ccefb1 100644 --- a/src/unix/linux_like/linux/no_align.rs +++ b/src/unix/linux_like/linux/no_align.rs @@ -57,6 +57,24 @@ macro_rules! expand_align { pub fd: ::c_int, pub pid: ::c_int, } + + pub struct tpacket_rollover_stats { + __align: [::c_long; 0], + pub tp_all: ::__u64, + pub tp_huge: ::__u64, + pub tp_failed: ::__u64, + } + + pub struct tpacket_hdr_v1 { + __align: [::c_long; 0], + pub block_status: ::__u32, + pub num_pkts: ::__u32, + pub offset_to_first_pkt: ::__u32, + pub blk_len: ::__u32, + pub seq_num: ::__u64, + pub ts_first_pkt: ::tpacket_bd_ts, + pub ts_last_pkt: ::tpacket_bd_ts, + } } s_no_extra_traits! {