net_gen: replace net_gen with libc

The libc crate provides all functionality provided by the net_gen crate.
Removing the net_gen crate reduces the maintenance burden.

The switch to libc required some fixes, most notably the switch from a
`Vec<u8>` to a `CString` for the `net_util::Tap.if_name` field.

On-behalf-of: SAP julian.schindel@sap.com
Signed-off-by: Julian Schindel <julian.schindel@cyberus-technology.de>
This commit is contained in:
Julian Schindel
2026-03-13 15:11:14 +01:00
committed by Rob Bradford
parent 3a56f20ee1
commit 2b28c5b15a
17 changed files with 140 additions and 2215 deletions

9
Cargo.lock generated
View File

@@ -1384,13 +1384,6 @@ dependencies = [
"vmm-sys-util",
]
[[package]]
name = "net_gen"
version = "0.1.0"
dependencies = [
"vmm-sys-util",
]
[[package]]
name = "net_util"
version = "0.1.0"
@@ -1399,7 +1392,6 @@ dependencies = [
"getrandom 0.4.2",
"libc",
"log",
"net_gen",
"pnet",
"pnet_datalink",
"rate_limiter",
@@ -2214,7 +2206,6 @@ dependencies = [
"anyhow",
"libc",
"log",
"net_gen",
"thiserror",
"vmm-sys-util",
]

View File

@@ -22,7 +22,6 @@ members = [
"devices",
"event_monitor",
"hypervisor",
"net_gen",
"net_util",
"option_parser",
"pci",

9
fuzz/Cargo.lock generated
View File

@@ -801,13 +801,6 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "net_gen"
version = "0.1.0"
dependencies = [
"vmm-sys-util",
]
[[package]]
name = "net_util"
version = "0.1.0"
@@ -816,7 +809,6 @@ dependencies = [
"getrandom 0.4.2",
"libc",
"log",
"net_gen",
"rate_limiter",
"serde",
"thiserror",
@@ -1235,7 +1227,6 @@ dependencies = [
"anyhow",
"libc",
"log",
"net_gen",
"thiserror",
"vmm-sys-util",
]

View File

@@ -64,7 +64,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
}
let (dummy_tap_frontend, dummy_tap_backend) = create_socketpair().unwrap();
let if_name = "fuzzer_tap_name".as_bytes().to_vec();
let if_name = "fuzzer_tap_name";
let tap = net_util::Tap::new_for_fuzzing(dummy_tap_frontend, if_name);
let mut net = virtio_devices::Net::new_with_tap(

View File

@@ -1,13 +0,0 @@
[package]
authors = ["The Chromium OS Authors"]
edition = "2021"
#edition.workspace = true
name = "net_gen"
rust-version.workspace = true
version = "0.1.0"
[dependencies]
vmm-sys-util = { workspace = true }
[lints]
workspace = true

View File

@@ -1,327 +0,0 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
// bindgen /usr/include/linux/if_tun.h --no-layout-tests
/* automatically generated by rust-bindgen 0.58.1 */
#[repr(C)]
#[derive(Default)]
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
#[allow(clippy::missing_safety_doc)]
impl<T> __IncompleteArrayField<T> {
#[inline]
pub const fn new() -> Self {
__IncompleteArrayField(::std::marker::PhantomData, [])
}
#[inline]
pub fn as_ptr(&self) -> *const T {
self as *const _ as *const T
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self as *mut _ as *mut T
}
#[inline]
pub unsafe fn as_slice(&self, len: usize) -> &[T] {
::std::slice::from_raw_parts(self.as_ptr(), len)
}
#[inline]
pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
}
}
impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_str("__IncompleteArrayField")
}
}
pub const __BITS_PER_LONG: u32 = 64;
pub const __FD_SETSIZE: u32 = 1024;
pub const ETH_ALEN: u32 = 6;
pub const ETH_TLEN: u32 = 2;
pub const ETH_HLEN: u32 = 14;
pub const ETH_ZLEN: u32 = 60;
pub const ETH_DATA_LEN: u32 = 1500;
pub const ETH_FRAME_LEN: u32 = 1514;
pub const ETH_FCS_LEN: u32 = 4;
pub const ETH_MIN_MTU: u32 = 68;
pub const ETH_MAX_MTU: u32 = 65535;
pub const ETH_P_LOOP: u32 = 96;
pub const ETH_P_PUP: u32 = 512;
pub const ETH_P_PUPAT: u32 = 513;
pub const ETH_P_TSN: u32 = 8944;
pub const ETH_P_ERSPAN2: u32 = 8939;
pub const ETH_P_IP: u32 = 2048;
pub const ETH_P_X25: u32 = 2053;
pub const ETH_P_ARP: u32 = 2054;
pub const ETH_P_BPQ: u32 = 2303;
pub const ETH_P_IEEEPUP: u32 = 2560;
pub const ETH_P_IEEEPUPAT: u32 = 2561;
pub const ETH_P_BATMAN: u32 = 17157;
pub const ETH_P_DEC: u32 = 24576;
pub const ETH_P_DNA_DL: u32 = 24577;
pub const ETH_P_DNA_RC: u32 = 24578;
pub const ETH_P_DNA_RT: u32 = 24579;
pub const ETH_P_LAT: u32 = 24580;
pub const ETH_P_DIAG: u32 = 24581;
pub const ETH_P_CUST: u32 = 24582;
pub const ETH_P_SCA: u32 = 24583;
pub const ETH_P_TEB: u32 = 25944;
pub const ETH_P_RARP: u32 = 32821;
pub const ETH_P_ATALK: u32 = 32923;
pub const ETH_P_AARP: u32 = 33011;
pub const ETH_P_8021Q: u32 = 33024;
pub const ETH_P_ERSPAN: u32 = 35006;
pub const ETH_P_IPX: u32 = 33079;
pub const ETH_P_IPV6: u32 = 34525;
pub const ETH_P_PAUSE: u32 = 34824;
pub const ETH_P_SLOW: u32 = 34825;
pub const ETH_P_WCCP: u32 = 34878;
pub const ETH_P_MPLS_UC: u32 = 34887;
pub const ETH_P_MPLS_MC: u32 = 34888;
pub const ETH_P_ATMMPOA: u32 = 34892;
pub const ETH_P_PPP_DISC: u32 = 34915;
pub const ETH_P_PPP_SES: u32 = 34916;
pub const ETH_P_LINK_CTL: u32 = 34924;
pub const ETH_P_ATMFATE: u32 = 34948;
pub const ETH_P_PAE: u32 = 34958;
pub const ETH_P_AOE: u32 = 34978;
pub const ETH_P_8021AD: u32 = 34984;
pub const ETH_P_802_EX1: u32 = 34997;
pub const ETH_P_PREAUTH: u32 = 35015;
pub const ETH_P_TIPC: u32 = 35018;
pub const ETH_P_LLDP: u32 = 35020;
pub const ETH_P_MRP: u32 = 35043;
pub const ETH_P_MACSEC: u32 = 35045;
pub const ETH_P_8021AH: u32 = 35047;
pub const ETH_P_MVRP: u32 = 35061;
pub const ETH_P_1588: u32 = 35063;
pub const ETH_P_NCSI: u32 = 35064;
pub const ETH_P_PRP: u32 = 35067;
pub const ETH_P_FCOE: u32 = 35078;
pub const ETH_P_IBOE: u32 = 35093;
pub const ETH_P_TDLS: u32 = 35085;
pub const ETH_P_FIP: u32 = 35092;
pub const ETH_P_80221: u32 = 35095;
pub const ETH_P_HSR: u32 = 35119;
pub const ETH_P_NSH: u32 = 35151;
pub const ETH_P_LOOPBACK: u32 = 36864;
pub const ETH_P_QINQ1: u32 = 37120;
pub const ETH_P_QINQ2: u32 = 37376;
pub const ETH_P_QINQ3: u32 = 37632;
pub const ETH_P_EDSA: u32 = 56026;
pub const ETH_P_DSA_8021Q: u32 = 56027;
pub const ETH_P_IFE: u32 = 60734;
pub const ETH_P_AF_IUCV: u32 = 64507;
pub const ETH_P_802_3_MIN: u32 = 1536;
pub const ETH_P_802_3: u32 = 1;
pub const ETH_P_AX25: u32 = 2;
pub const ETH_P_ALL: u32 = 3;
pub const ETH_P_802_2: u32 = 4;
pub const ETH_P_SNAP: u32 = 5;
pub const ETH_P_DDCMP: u32 = 6;
pub const ETH_P_WAN_PPP: u32 = 7;
pub const ETH_P_PPP_MP: u32 = 8;
pub const ETH_P_LOCALTALK: u32 = 9;
pub const ETH_P_CAN: u32 = 12;
pub const ETH_P_CANFD: u32 = 13;
pub const ETH_P_PPPTALK: u32 = 16;
pub const ETH_P_TR_802_2: u32 = 17;
pub const ETH_P_MOBITEX: u32 = 21;
pub const ETH_P_CONTROL: u32 = 22;
pub const ETH_P_IRDA: u32 = 23;
pub const ETH_P_ECONET: u32 = 24;
pub const ETH_P_HDLC: u32 = 25;
pub const ETH_P_ARCNET: u32 = 26;
pub const ETH_P_DSA: u32 = 27;
pub const ETH_P_TRAILER: u32 = 28;
pub const ETH_P_PHONET: u32 = 245;
pub const ETH_P_IEEE802154: u32 = 246;
pub const ETH_P_CAIF: u32 = 247;
pub const ETH_P_XDSA: u32 = 248;
pub const ETH_P_MAP: u32 = 249;
pub const __UAPI_DEF_ETHHDR: u32 = 1;
pub const BPF_LD: u32 = 0;
pub const BPF_LDX: u32 = 1;
pub const BPF_ST: u32 = 2;
pub const BPF_STX: u32 = 3;
pub const BPF_ALU: u32 = 4;
pub const BPF_JMP: u32 = 5;
pub const BPF_RET: u32 = 6;
pub const BPF_MISC: u32 = 7;
pub const BPF_W: u32 = 0;
pub const BPF_H: u32 = 8;
pub const BPF_B: u32 = 16;
pub const BPF_IMM: u32 = 0;
pub const BPF_ABS: u32 = 32;
pub const BPF_IND: u32 = 64;
pub const BPF_MEM: u32 = 96;
pub const BPF_LEN: u32 = 128;
pub const BPF_MSH: u32 = 160;
pub const BPF_ADD: u32 = 0;
pub const BPF_SUB: u32 = 16;
pub const BPF_MUL: u32 = 32;
pub const BPF_DIV: u32 = 48;
pub const BPF_OR: u32 = 64;
pub const BPF_AND: u32 = 80;
pub const BPF_LSH: u32 = 96;
pub const BPF_RSH: u32 = 112;
pub const BPF_NEG: u32 = 128;
pub const BPF_MOD: u32 = 144;
pub const BPF_XOR: u32 = 160;
pub const BPF_JA: u32 = 0;
pub const BPF_JEQ: u32 = 16;
pub const BPF_JGT: u32 = 32;
pub const BPF_JGE: u32 = 48;
pub const BPF_JSET: u32 = 64;
pub const BPF_K: u32 = 0;
pub const BPF_X: u32 = 8;
pub const BPF_MAXINSNS: u32 = 4096;
pub const BPF_MAJOR_VERSION: u32 = 1;
pub const BPF_MINOR_VERSION: u32 = 1;
pub const BPF_A: u32 = 16;
pub const BPF_TAX: u32 = 0;
pub const BPF_TXA: u32 = 128;
pub const BPF_MEMWORDS: u32 = 16;
pub const SKF_AD_OFF: i32 = -4096;
pub const SKF_AD_PROTOCOL: u32 = 0;
pub const SKF_AD_PKTTYPE: u32 = 4;
pub const SKF_AD_IFINDEX: u32 = 8;
pub const SKF_AD_NLATTR: u32 = 12;
pub const SKF_AD_NLATTR_NEST: u32 = 16;
pub const SKF_AD_MARK: u32 = 20;
pub const SKF_AD_QUEUE: u32 = 24;
pub const SKF_AD_HATYPE: u32 = 28;
pub const SKF_AD_RXHASH: u32 = 32;
pub const SKF_AD_CPU: u32 = 36;
pub const SKF_AD_ALU_XOR_X: u32 = 40;
pub const SKF_AD_VLAN_TAG: u32 = 44;
pub const SKF_AD_VLAN_TAG_PRESENT: u32 = 48;
pub const SKF_AD_PAY_OFFSET: u32 = 52;
pub const SKF_AD_RANDOM: u32 = 56;
pub const SKF_AD_VLAN_TPID: u32 = 60;
pub const SKF_AD_MAX: u32 = 64;
pub const SKF_NET_OFF: i32 = -1048576;
pub const SKF_LL_OFF: i32 = -2097152;
pub const BPF_NET_OFF: i32 = -1048576;
pub const BPF_LL_OFF: i32 = -2097152;
pub const TUN_READQ_SIZE: u32 = 500;
pub const TUN_TYPE_MASK: u32 = 15;
pub const IFF_TUN: u32 = 1;
pub const IFF_TAP: u32 = 2;
pub const IFF_NAPI: u32 = 16;
pub const IFF_NAPI_FRAGS: u32 = 32;
pub const IFF_NO_PI: u32 = 4096;
pub const IFF_ONE_QUEUE: u32 = 8192;
pub const IFF_VNET_HDR: u32 = 16384;
pub const IFF_TUN_EXCL: u32 = 32768;
pub const IFF_MULTI_QUEUE: u32 = 256;
pub const IFF_ATTACH_QUEUE: u32 = 512;
pub const IFF_DETACH_QUEUE: u32 = 1024;
pub const IFF_PERSIST: u32 = 2048;
pub const IFF_NOFILTER: u32 = 4096;
pub const TUN_TX_TIMESTAMP: u32 = 1;
pub const TUN_F_CSUM: u32 = 1;
pub const TUN_F_TSO4: u32 = 2;
pub const TUN_F_TSO6: u32 = 4;
pub const TUN_F_TSO_ECN: u32 = 8;
pub const TUN_F_UFO: u32 = 16;
pub const TUN_PKT_STRIP: u32 = 1;
pub const TUN_FLT_ALLMULTI: u32 = 1;
pub type __s8 = ::std::os::raw::c_schar;
pub type __u8 = ::std::os::raw::c_uchar;
pub type __s16 = ::std::os::raw::c_short;
pub type __u16 = ::std::os::raw::c_ushort;
pub type __s32 = ::std::os::raw::c_int;
pub type __u32 = ::std::os::raw::c_uint;
pub type __s64 = ::std::os::raw::c_longlong;
pub type __u64 = ::std::os::raw::c_ulonglong;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __kernel_fd_set {
pub fds_bits: [::std::os::raw::c_ulong; 16usize],
}
pub type __kernel_sighandler_t =
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
pub type __kernel_key_t = ::std::os::raw::c_int;
pub type __kernel_mqd_t = ::std::os::raw::c_int;
pub type __kernel_old_uid_t = ::std::os::raw::c_ushort;
pub type __kernel_old_gid_t = ::std::os::raw::c_ushort;
pub type __kernel_old_dev_t = ::std::os::raw::c_ulong;
pub type __kernel_long_t = ::std::os::raw::c_long;
pub type __kernel_ulong_t = ::std::os::raw::c_ulong;
pub type __kernel_ino_t = __kernel_ulong_t;
pub type __kernel_mode_t = ::std::os::raw::c_uint;
pub type __kernel_pid_t = ::std::os::raw::c_int;
pub type __kernel_ipc_pid_t = ::std::os::raw::c_int;
pub type __kernel_uid_t = ::std::os::raw::c_uint;
pub type __kernel_gid_t = ::std::os::raw::c_uint;
pub type __kernel_suseconds_t = __kernel_long_t;
pub type __kernel_daddr_t = ::std::os::raw::c_int;
pub type __kernel_uid32_t = ::std::os::raw::c_uint;
pub type __kernel_gid32_t = ::std::os::raw::c_uint;
pub type __kernel_size_t = __kernel_ulong_t;
pub type __kernel_ssize_t = __kernel_long_t;
pub type __kernel_ptrdiff_t = __kernel_long_t;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __kernel_fsid_t {
pub val: [::std::os::raw::c_int; 2usize],
}
pub type __kernel_off_t = __kernel_long_t;
pub type __kernel_loff_t = ::std::os::raw::c_longlong;
pub type __kernel_old_time_t = __kernel_long_t;
pub type __kernel_time_t = __kernel_long_t;
pub type __kernel_time64_t = ::std::os::raw::c_longlong;
pub type __kernel_clock_t = __kernel_long_t;
pub type __kernel_timer_t = ::std::os::raw::c_int;
pub type __kernel_clockid_t = ::std::os::raw::c_int;
pub type __kernel_caddr_t = *mut ::std::os::raw::c_char;
pub type __kernel_uid16_t = ::std::os::raw::c_ushort;
pub type __kernel_gid16_t = ::std::os::raw::c_ushort;
pub type __le16 = __u16;
pub type __be16 = __u16;
pub type __le32 = __u32;
pub type __be32 = __u32;
pub type __le64 = __u64;
pub type __be64 = __u64;
pub type __sum16 = __u16;
pub type __wsum = __u32;
pub type __poll_t = ::std::os::raw::c_uint;
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
pub struct ethhdr {
pub h_dest: [::std::os::raw::c_uchar; 6usize],
pub h_source: [::std::os::raw::c_uchar; 6usize],
pub h_proto: __be16,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct sock_filter {
pub code: __u16,
pub jt: __u8,
pub jf: __u8,
pub k: __u32,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct sock_fprog {
pub len: ::std::os::raw::c_ushort,
pub filter: *mut sock_filter,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct tun_pi {
pub flags: __u16,
pub proto: __be16,
}
#[repr(C)]
#[derive(Debug)]
pub struct tun_filter {
pub flags: __u16,
pub count: __u16,
pub addr: __IncompleteArrayField<[__u8; 6usize]>,
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,294 +0,0 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
// bindgen /usr/include/linux/in.h --no-layout-tests
/* automatically generated by rust-bindgen 0.58.1 */
pub const __BITS_PER_LONG: u32 = 64;
pub const __FD_SETSIZE: u32 = 1024;
pub const __UAPI_DEF_IF_IFCONF: u32 = 1;
pub const __UAPI_DEF_IF_IFMAP: u32 = 1;
pub const __UAPI_DEF_IF_IFNAMSIZ: u32 = 1;
pub const __UAPI_DEF_IF_IFREQ: u32 = 1;
pub const __UAPI_DEF_IF_NET_DEVICE_FLAGS: u32 = 1;
pub const __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO: u32 = 1;
pub const __UAPI_DEF_IN_ADDR: u32 = 1;
pub const __UAPI_DEF_IN_IPPROTO: u32 = 1;
pub const __UAPI_DEF_IN_PKTINFO: u32 = 1;
pub const __UAPI_DEF_IP_MREQ: u32 = 1;
pub const __UAPI_DEF_SOCKADDR_IN: u32 = 1;
pub const __UAPI_DEF_IN_CLASS: u32 = 1;
pub const __UAPI_DEF_IN6_ADDR: u32 = 1;
pub const __UAPI_DEF_IN6_ADDR_ALT: u32 = 1;
pub const __UAPI_DEF_SOCKADDR_IN6: u32 = 1;
pub const __UAPI_DEF_IPV6_MREQ: u32 = 1;
pub const __UAPI_DEF_IPPROTO_V6: u32 = 1;
pub const __UAPI_DEF_IPV6_OPTIONS: u32 = 1;
pub const __UAPI_DEF_IN6_PKTINFO: u32 = 1;
pub const __UAPI_DEF_IP6_MTUINFO: u32 = 1;
pub const __UAPI_DEF_SOCKADDR_IPX: u32 = 1;
pub const __UAPI_DEF_IPX_ROUTE_DEFINITION: u32 = 1;
pub const __UAPI_DEF_IPX_INTERFACE_DEFINITION: u32 = 1;
pub const __UAPI_DEF_IPX_CONFIG_DATA: u32 = 1;
pub const __UAPI_DEF_IPX_ROUTE_DEF: u32 = 1;
pub const __UAPI_DEF_XATTR: u32 = 1;
pub const _K_SS_MAXSIZE: u32 = 128;
pub const IP_TOS: u32 = 1;
pub const IP_TTL: u32 = 2;
pub const IP_HDRINCL: u32 = 3;
pub const IP_OPTIONS: u32 = 4;
pub const IP_ROUTER_ALERT: u32 = 5;
pub const IP_RECVOPTS: u32 = 6;
pub const IP_RETOPTS: u32 = 7;
pub const IP_PKTINFO: u32 = 8;
pub const IP_PKTOPTIONS: u32 = 9;
pub const IP_MTU_DISCOVER: u32 = 10;
pub const IP_RECVERR: u32 = 11;
pub const IP_RECVTTL: u32 = 12;
pub const IP_RECVTOS: u32 = 13;
pub const IP_MTU: u32 = 14;
pub const IP_FREEBIND: u32 = 15;
pub const IP_IPSEC_POLICY: u32 = 16;
pub const IP_XFRM_POLICY: u32 = 17;
pub const IP_PASSSEC: u32 = 18;
pub const IP_TRANSPARENT: u32 = 19;
pub const IP_RECVRETOPTS: u32 = 7;
pub const IP_ORIGDSTADDR: u32 = 20;
pub const IP_RECVORIGDSTADDR: u32 = 20;
pub const IP_MINTTL: u32 = 21;
pub const IP_NODEFRAG: u32 = 22;
pub const IP_CHECKSUM: u32 = 23;
pub const IP_BIND_ADDRESS_NO_PORT: u32 = 24;
pub const IP_RECVFRAGSIZE: u32 = 25;
pub const IP_PMTUDISC_DONT: u32 = 0;
pub const IP_PMTUDISC_WANT: u32 = 1;
pub const IP_PMTUDISC_DO: u32 = 2;
pub const IP_PMTUDISC_PROBE: u32 = 3;
pub const IP_PMTUDISC_INTERFACE: u32 = 4;
pub const IP_PMTUDISC_OMIT: u32 = 5;
pub const IP_MULTICAST_IF: u32 = 32;
pub const IP_MULTICAST_TTL: u32 = 33;
pub const IP_MULTICAST_LOOP: u32 = 34;
pub const IP_ADD_MEMBERSHIP: u32 = 35;
pub const IP_DROP_MEMBERSHIP: u32 = 36;
pub const IP_UNBLOCK_SOURCE: u32 = 37;
pub const IP_BLOCK_SOURCE: u32 = 38;
pub const IP_ADD_SOURCE_MEMBERSHIP: u32 = 39;
pub const IP_DROP_SOURCE_MEMBERSHIP: u32 = 40;
pub const IP_MSFILTER: u32 = 41;
pub const MCAST_JOIN_GROUP: u32 = 42;
pub const MCAST_BLOCK_SOURCE: u32 = 43;
pub const MCAST_UNBLOCK_SOURCE: u32 = 44;
pub const MCAST_LEAVE_GROUP: u32 = 45;
pub const MCAST_JOIN_SOURCE_GROUP: u32 = 46;
pub const MCAST_LEAVE_SOURCE_GROUP: u32 = 47;
pub const MCAST_MSFILTER: u32 = 48;
pub const IP_MULTICAST_ALL: u32 = 49;
pub const IP_UNICAST_IF: u32 = 50;
pub const MCAST_EXCLUDE: u32 = 0;
pub const MCAST_INCLUDE: u32 = 1;
pub const IP_DEFAULT_MULTICAST_TTL: u32 = 1;
pub const IP_DEFAULT_MULTICAST_LOOP: u32 = 1;
pub const __SOCK_SIZE__: u32 = 16;
pub const IN_CLASSA_NET: u32 = 4278190080;
pub const IN_CLASSA_NSHIFT: u32 = 24;
pub const IN_CLASSA_HOST: u32 = 16777215;
pub const IN_CLASSA_MAX: u32 = 128;
pub const IN_CLASSB_NET: u32 = 4294901760;
pub const IN_CLASSB_NSHIFT: u32 = 16;
pub const IN_CLASSB_HOST: u32 = 65535;
pub const IN_CLASSB_MAX: u32 = 65536;
pub const IN_CLASSC_NET: u32 = 4294967040;
pub const IN_CLASSC_NSHIFT: u32 = 8;
pub const IN_CLASSC_HOST: u32 = 255;
pub const IN_MULTICAST_NET: u32 = 3758096384;
pub const IN_CLASSE_NET: u32 = 4294967295;
pub const IN_CLASSE_NSHIFT: u32 = 0;
pub const IN_LOOPBACKNET: u32 = 127;
pub const INADDR_LOOPBACK: u32 = 2130706433;
pub const INADDR_UNSPEC_GROUP: u32 = 3758096384;
pub const INADDR_ALLHOSTS_GROUP: u32 = 3758096385;
pub const INADDR_ALLRTRS_GROUP: u32 = 3758096386;
pub const INADDR_ALLSNOOPERS_GROUP: u32 = 3758096490;
pub const INADDR_MAX_LOCAL_GROUP: u32 = 3758096639;
pub const __LITTLE_ENDIAN: u32 = 1234;
pub type __s8 = ::std::os::raw::c_schar;
pub type __u8 = ::std::os::raw::c_uchar;
pub type __s16 = ::std::os::raw::c_short;
pub type __u16 = ::std::os::raw::c_ushort;
pub type __s32 = ::std::os::raw::c_int;
pub type __u32 = ::std::os::raw::c_uint;
pub type __s64 = ::std::os::raw::c_longlong;
pub type __u64 = ::std::os::raw::c_ulonglong;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __kernel_fd_set {
pub fds_bits: [::std::os::raw::c_ulong; 16usize],
}
pub type __kernel_sighandler_t =
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
pub type __kernel_key_t = ::std::os::raw::c_int;
pub type __kernel_mqd_t = ::std::os::raw::c_int;
pub type __kernel_old_uid_t = ::std::os::raw::c_ushort;
pub type __kernel_old_gid_t = ::std::os::raw::c_ushort;
pub type __kernel_old_dev_t = ::std::os::raw::c_ulong;
pub type __kernel_long_t = ::std::os::raw::c_long;
pub type __kernel_ulong_t = ::std::os::raw::c_ulong;
pub type __kernel_ino_t = __kernel_ulong_t;
pub type __kernel_mode_t = ::std::os::raw::c_uint;
pub type __kernel_pid_t = ::std::os::raw::c_int;
pub type __kernel_ipc_pid_t = ::std::os::raw::c_int;
pub type __kernel_uid_t = ::std::os::raw::c_uint;
pub type __kernel_gid_t = ::std::os::raw::c_uint;
pub type __kernel_suseconds_t = __kernel_long_t;
pub type __kernel_daddr_t = ::std::os::raw::c_int;
pub type __kernel_uid32_t = ::std::os::raw::c_uint;
pub type __kernel_gid32_t = ::std::os::raw::c_uint;
pub type __kernel_size_t = __kernel_ulong_t;
pub type __kernel_ssize_t = __kernel_long_t;
pub type __kernel_ptrdiff_t = __kernel_long_t;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __kernel_fsid_t {
pub val: [::std::os::raw::c_int; 2usize],
}
pub type __kernel_off_t = __kernel_long_t;
pub type __kernel_loff_t = ::std::os::raw::c_longlong;
pub type __kernel_old_time_t = __kernel_long_t;
pub type __kernel_time_t = __kernel_long_t;
pub type __kernel_time64_t = ::std::os::raw::c_longlong;
pub type __kernel_clock_t = __kernel_long_t;
pub type __kernel_timer_t = ::std::os::raw::c_int;
pub type __kernel_clockid_t = ::std::os::raw::c_int;
pub type __kernel_caddr_t = *mut ::std::os::raw::c_char;
pub type __kernel_uid16_t = ::std::os::raw::c_ushort;
pub type __kernel_gid16_t = ::std::os::raw::c_ushort;
pub type __le16 = __u16;
pub type __be16 = __u16;
pub type __le32 = __u32;
pub type __be32 = __u32;
pub type __le64 = __u64;
pub type __be64 = __u64;
pub type __sum16 = __u16;
pub type __wsum = __u32;
pub type __poll_t = ::std::os::raw::c_uint;
pub type __kernel_sa_family_t = ::std::os::raw::c_ushort;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct __kernel_sockaddr_storage {
pub __bindgen_anon_1: __kernel_sockaddr_storage__bindgen_ty_1,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union __kernel_sockaddr_storage__bindgen_ty_1 {
pub __bindgen_anon_1: __kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1,
pub __align: *mut ::std::os::raw::c_void,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct __kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 {
pub ss_family: __kernel_sa_family_t,
pub __data: [::std::os::raw::c_char; 126usize],
}
pub const IPPROTO_IP: ::std::os::raw::c_uint = 0;
pub const IPPROTO_ICMP: ::std::os::raw::c_uint = 1;
pub const IPPROTO_IGMP: ::std::os::raw::c_uint = 2;
pub const IPPROTO_IPIP: ::std::os::raw::c_uint = 4;
pub const IPPROTO_TCP: ::std::os::raw::c_uint = 6;
pub const IPPROTO_EGP: ::std::os::raw::c_uint = 8;
pub const IPPROTO_PUP: ::std::os::raw::c_uint = 12;
pub const IPPROTO_UDP: ::std::os::raw::c_uint = 17;
pub const IPPROTO_IDP: ::std::os::raw::c_uint = 22;
pub const IPPROTO_TP: ::std::os::raw::c_uint = 29;
pub const IPPROTO_DCCP: ::std::os::raw::c_uint = 33;
pub const IPPROTO_IPV6: ::std::os::raw::c_uint = 41;
pub const IPPROTO_RSVP: ::std::os::raw::c_uint = 46;
pub const IPPROTO_GRE: ::std::os::raw::c_uint = 47;
pub const IPPROTO_ESP: ::std::os::raw::c_uint = 50;
pub const IPPROTO_AH: ::std::os::raw::c_uint = 51;
pub const IPPROTO_MTP: ::std::os::raw::c_uint = 92;
pub const IPPROTO_BEETPH: ::std::os::raw::c_uint = 94;
pub const IPPROTO_ENCAP: ::std::os::raw::c_uint = 98;
pub const IPPROTO_PIM: ::std::os::raw::c_uint = 103;
pub const IPPROTO_COMP: ::std::os::raw::c_uint = 108;
pub const IPPROTO_SCTP: ::std::os::raw::c_uint = 132;
pub const IPPROTO_UDPLITE: ::std::os::raw::c_uint = 136;
pub const IPPROTO_MPLS: ::std::os::raw::c_uint = 137;
pub const IPPROTO_ETHERNET: ::std::os::raw::c_uint = 143;
pub const IPPROTO_RAW: ::std::os::raw::c_uint = 255;
pub const IPPROTO_MPTCP: ::std::os::raw::c_uint = 262;
pub const IPPROTO_MAX: ::std::os::raw::c_uint = 263;
pub type _bindgen_ty_1 = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct in_addr {
pub s_addr: __be32,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ip_mreqn {
pub imr_multiaddr: in_addr,
pub imr_address: in_addr,
pub imr_ifindex: ::std::os::raw::c_int,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ip_mreq_source {
pub imr_multiaddr: __be32,
pub imr_interface: __be32,
pub imr_sourceaddr: __be32,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ip_msfilter {
pub imsf_multiaddr: __be32,
pub imsf_interface: __be32,
pub imsf_fmode: __u32,
pub imsf_numsrc: __u32,
pub imsf_slist: [__be32; 1usize],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct group_req {
pub gr_interface: __u32,
pub gr_group: __kernel_sockaddr_storage,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct group_source_req {
pub gsr_interface: __u32,
pub gsr_group: __kernel_sockaddr_storage,
pub gsr_source: __kernel_sockaddr_storage,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct group_filter {
pub gf_interface: __u32,
pub gf_group: __kernel_sockaddr_storage,
pub gf_fmode: __u32,
pub gf_numsrc: __u32,
pub gf_slist: [__kernel_sockaddr_storage; 1usize],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct in_pktinfo {
pub ipi_ifindex: ::std::os::raw::c_int,
pub ipi_spec_dst: in_addr,
pub ipi_addr: in_addr,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct sockaddr_in {
pub sin_family: __kernel_sa_family_t,
pub sin_port: __be16,
pub sin_addr: in_addr,
pub __pad: [::std::os::raw::c_uchar; 8usize],
}

View File

@@ -1,41 +0,0 @@
// Copyright © 2025 Cloud Hypervisor Authors
//
// SPDX-License-Identifier: Apache-2.0
// bindgen /usr/include/linux/ipv6.h --no-layout-tests --constified-enum '*' --allowlist-type 'sockaddr_in6|in6_ifreq'
/* automatically generated by rust-bindgen 0.71.1 */
pub type __u8 = ::std::os::raw::c_uchar;
pub type __u16 = ::std::os::raw::c_ushort;
pub type __u32 = ::std::os::raw::c_uint;
pub type __be16 = __u16;
pub type __be32 = __u32;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct in6_addr {
pub in6_u: in6_addr__bindgen_ty_1,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union in6_addr__bindgen_ty_1 {
pub u6_addr8: [__u8; 16usize],
pub u6_addr16: [__be16; 8usize],
pub u6_addr32: [__be32; 4usize],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
pub sin6_family: ::std::os::raw::c_ushort,
pub sin6_port: __be16,
pub sin6_flowinfo: __be32,
pub sin6_addr: in6_addr,
pub sin6_scope_id: __u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct in6_ifreq {
pub ifr6_addr: in6_addr,
pub ifr6_prefixlen: __u32,
pub ifr6_ifindex: ::std::os::raw::c_int,
}

View File

@@ -1,66 +0,0 @@
// Copyright TUNTAP, 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
// generated with bindgen /usr/include/linux/if.h --no-unstable-rust
// --constified-enum '*' --with-derive-default -- -D __UAPI_DEF_IF_IFNAMSIZ -D
// __UAPI_DEF_IF_NET_DEVICE_FLAGS -D __UAPI_DEF_IF_IFREQ -D __UAPI_DEF_IF_IFMAP
// Name is "iff" to avoid conflicting with "if" keyword.
// Generated against Linux 4.11 to include fix "uapi: fix linux/if.h userspace
// compilation errors".
// Manual fixup of ifrn_name to be of type c_uchar instead of c_char.
pub mod iff;
// generated with bindgen /usr/include/linux/if_tun.h --no-unstable-rust
// --constified-enum '*' --with-derive-default
pub mod if_tun;
// generated with bindgen /usr/include/linux/in.h --no-unstable-rust
// --constified-enum '*' --with-derive-default
// Name is "inn" to avoid conflicting with "in" keyword.
pub mod inn;
// generated with bindgen /usr/include/linux/ipv6.h --no-layout-tests --constified-enum '*'
// --allowlist-type 'sockaddr_in6|in6_ifreq'
pub mod ipv6;
// generated with bindgen /usr/include/linux/sockios.h --no-unstable-rust
// --constified-enum '*' --with-derive-default
pub mod sockios;
pub use if_tun::{
sock_fprog, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_TAP, IFF_VNET_HDR, TUN_F_CSUM, TUN_F_TSO4,
TUN_F_TSO6, TUN_F_TSO_ECN, TUN_F_UFO,
};
pub use iff::{ifreq, net_device_flags_IFF_UP, setsockopt, sockaddr, AF_INET};
pub use inn::sockaddr_in;
pub use ipv6::{in6_ifreq, sockaddr_in6};
use vmm_sys_util::{ioctl_ior_nr, ioctl_iow_nr};
pub const TUNTAP: ::std::os::raw::c_uint = 84;
ioctl_iow_nr!(TUNSETNOCSUM, TUNTAP, 200, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETDEBUG, TUNTAP, 201, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETIFF, TUNTAP, 202, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETPERSIST, TUNTAP, 203, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETOWNER, TUNTAP, 204, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETLINK, TUNTAP, 205, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETGROUP, TUNTAP, 206, ::std::os::raw::c_int);
ioctl_ior_nr!(TUNGETFEATURES, TUNTAP, 207, ::std::os::raw::c_uint);
ioctl_iow_nr!(TUNSETOFFLOAD, TUNTAP, 208, ::std::os::raw::c_uint);
ioctl_iow_nr!(TUNSETTXFILTER, TUNTAP, 209, ::std::os::raw::c_uint);
ioctl_ior_nr!(TUNGETIFF, TUNTAP, 210, ::std::os::raw::c_uint);
ioctl_ior_nr!(TUNGETSNDBUF, TUNTAP, 211, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETSNDBUF, TUNTAP, 212, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNATTACHFILTER, TUNTAP, 213, sock_fprog);
ioctl_iow_nr!(TUNDETACHFILTER, TUNTAP, 214, sock_fprog);
ioctl_ior_nr!(TUNGETVNETHDRSZ, TUNTAP, 215, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETVNETHDRSZ, TUNTAP, 216, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETQUEUE, TUNTAP, 217, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETIFINDEX, TUNTAP, 218, ::std::os::raw::c_uint);
ioctl_ior_nr!(TUNGETFILTER, TUNTAP, 219, sock_fprog);
ioctl_iow_nr!(TUNSETVNETLE, TUNTAP, 220, ::std::os::raw::c_int);
ioctl_ior_nr!(TUNGETVNETLE, TUNTAP, 221, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETVNETBE, TUNTAP, 222, ::std::os::raw::c_int);
ioctl_ior_nr!(TUNGETVNETBE, TUNTAP, 223, ::std::os::raw::c_int);

View File

@@ -1,95 +0,0 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
// bindgen /usr/include/linux/sockios.h --no-layout-tests
/* automatically generated by rust-bindgen 0.58.1 */
pub const __BITS_PER_LONG: u32 = 64;
pub const FIOSETOWN: u32 = 35073;
pub const SIOCSPGRP: u32 = 35074;
pub const FIOGETOWN: u32 = 35075;
pub const SIOCGPGRP: u32 = 35076;
pub const SIOCATMARK: u32 = 35077;
pub const SIOCGSTAMP_OLD: u32 = 35078;
pub const SIOCGSTAMPNS_OLD: u32 = 35079;
pub const SOCK_IOC_TYPE: u32 = 137;
pub const SIOCGSTAMP: u32 = 35078;
pub const SIOCGSTAMPNS: u32 = 35079;
pub const SIOCADDRT: u32 = 35083;
pub const SIOCDELRT: u32 = 35084;
pub const SIOCRTMSG: u32 = 35085;
pub const SIOCGIFNAME: u32 = 35088;
pub const SIOCSIFLINK: u32 = 35089;
pub const SIOCGIFCONF: u32 = 35090;
pub const SIOCGIFFLAGS: u32 = 35091;
pub const SIOCSIFFLAGS: u32 = 35092;
pub const SIOCGIFADDR: u32 = 35093;
pub const SIOCSIFADDR: u32 = 35094;
pub const SIOCGIFDSTADDR: u32 = 35095;
pub const SIOCSIFDSTADDR: u32 = 35096;
pub const SIOCGIFBRDADDR: u32 = 35097;
pub const SIOCSIFBRDADDR: u32 = 35098;
pub const SIOCGIFNETMASK: u32 = 35099;
pub const SIOCSIFNETMASK: u32 = 35100;
pub const SIOCGIFMETRIC: u32 = 35101;
pub const SIOCSIFMETRIC: u32 = 35102;
pub const SIOCGIFMEM: u32 = 35103;
pub const SIOCSIFMEM: u32 = 35104;
pub const SIOCGIFMTU: u32 = 35105;
pub const SIOCSIFMTU: u32 = 35106;
pub const SIOCSIFNAME: u32 = 35107;
pub const SIOCSIFHWADDR: u32 = 35108;
pub const SIOCGIFENCAP: u32 = 35109;
pub const SIOCSIFENCAP: u32 = 35110;
pub const SIOCGIFHWADDR: u32 = 35111;
pub const SIOCGIFSLAVE: u32 = 35113;
pub const SIOCSIFSLAVE: u32 = 35120;
pub const SIOCADDMULTI: u32 = 35121;
pub const SIOCDELMULTI: u32 = 35122;
pub const SIOCGIFINDEX: u32 = 35123;
pub const SIOGIFINDEX: u32 = 35123;
pub const SIOCSIFPFLAGS: u32 = 35124;
pub const SIOCGIFPFLAGS: u32 = 35125;
pub const SIOCDIFADDR: u32 = 35126;
pub const SIOCSIFHWBROADCAST: u32 = 35127;
pub const SIOCGIFCOUNT: u32 = 35128;
pub const SIOCGIFBR: u32 = 35136;
pub const SIOCSIFBR: u32 = 35137;
pub const SIOCGIFTXQLEN: u32 = 35138;
pub const SIOCSIFTXQLEN: u32 = 35139;
pub const SIOCETHTOOL: u32 = 35142;
pub const SIOCGMIIPHY: u32 = 35143;
pub const SIOCGMIIREG: u32 = 35144;
pub const SIOCSMIIREG: u32 = 35145;
pub const SIOCWANDEV: u32 = 35146;
pub const SIOCOUTQNSD: u32 = 35147;
pub const SIOCGSKNS: u32 = 35148;
pub const SIOCDARP: u32 = 35155;
pub const SIOCGARP: u32 = 35156;
pub const SIOCSARP: u32 = 35157;
pub const SIOCDRARP: u32 = 35168;
pub const SIOCGRARP: u32 = 35169;
pub const SIOCSRARP: u32 = 35170;
pub const SIOCGIFMAP: u32 = 35184;
pub const SIOCSIFMAP: u32 = 35185;
pub const SIOCADDDLCI: u32 = 35200;
pub const SIOCDELDLCI: u32 = 35201;
pub const SIOCGIFVLAN: u32 = 35202;
pub const SIOCSIFVLAN: u32 = 35203;
pub const SIOCBONDENSLAVE: u32 = 35216;
pub const SIOCBONDRELEASE: u32 = 35217;
pub const SIOCBONDSETHWADDR: u32 = 35218;
pub const SIOCBONDSLAVEINFOQUERY: u32 = 35219;
pub const SIOCBONDINFOQUERY: u32 = 35220;
pub const SIOCBONDCHANGEACTIVE: u32 = 35221;
pub const SIOCBRADDBR: u32 = 35232;
pub const SIOCBRDELBR: u32 = 35233;
pub const SIOCBRADDIF: u32 = 35234;
pub const SIOCBRDELIF: u32 = 35235;
pub const SIOCSHWTSTAMP: u32 = 35248;
pub const SIOCGHWTSTAMP: u32 = 35249;
pub const SIOCDEVPRIVATE: u32 = 35312;
pub const SIOCPROTOPRIVATE: u32 = 35296;

View File

@@ -10,7 +10,6 @@ epoll = { workspace = true }
getrandom = "0.4.2"
libc = { workspace = true }
log = { workspace = true }
net_gen = { path = "../net_gen" }
rate_limiter = { path = "../rate_limiter" }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }

View File

@@ -59,15 +59,15 @@ unsafe impl ByteValued for VirtioNetConfig {}
/// Create a sockaddr_in from an IPv4 address, and expose it as
/// an opaque sockaddr suitable for usage by socket ioctls.
fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr {
// IPv4 addresses big-endian (network order), but Ipv4Addr will give us
// a view of those bytes directly so we can avoid any endian trickiness.
let addr_in = net_gen::sockaddr_in {
sin_family: net_gen::AF_INET as u16,
fn create_sockaddr(ip_addr: net::Ipv4Addr) -> libc::sockaddr {
let addr_in = libc::sockaddr_in {
sin_family: libc::AF_INET as u16,
sin_port: 0,
// SAFETY: ip_addr can be safely transmute to in_addr
sin_addr: unsafe { mem::transmute::<[u8; 4], net_gen::inn::in_addr>(ip_addr.octets()) },
__pad: [0; 8usize],
sin_addr: libc::in_addr {
// Use network byte order (big endian).
s_addr: ip_addr.to_bits().to_be(),
},
sin_zero: [0; 8],
};
// SAFETY: addr_in can be safely transmute to sockaddr
@@ -167,19 +167,19 @@ pub fn build_net_config_space_with_mq(
pub fn virtio_features_to_tap_offload(features: u64) -> c_uint {
let mut tap_offloads: c_uint = 0;
if features & (1 << VIRTIO_NET_F_GUEST_CSUM) != 0 {
tap_offloads |= net_gen::TUN_F_CSUM;
tap_offloads |= libc::TUN_F_CSUM;
}
if features & (1 << VIRTIO_NET_F_GUEST_TSO4) != 0 {
tap_offloads |= net_gen::TUN_F_TSO4;
tap_offloads |= libc::TUN_F_TSO4;
}
if features & (1 << VIRTIO_NET_F_GUEST_TSO6) != 0 {
tap_offloads |= net_gen::TUN_F_TSO6;
tap_offloads |= libc::TUN_F_TSO6;
}
if features & (1 << VIRTIO_NET_F_GUEST_ECN) != 0 {
tap_offloads |= net_gen::TUN_F_TSO_ECN;
tap_offloads |= libc::TUN_F_TSO_ECN;
}
if features & (1 << VIRTIO_NET_F_GUEST_UFO) != 0 {
tap_offloads |= net_gen::TUN_F_UFO;
tap_offloads |= libc::TUN_F_UFO;
}
tap_offloads
@@ -194,7 +194,7 @@ mod unit_tests {
let addr: net::Ipv4Addr = "10.0.0.1".parse().unwrap();
let sockaddr = create_sockaddr(addr);
assert_eq!(sockaddr.sa_family, net_gen::AF_INET as u16);
assert_eq!(sockaddr.sa_family, libc::AF_INET as u16);
let data = &sockaddr.sa_data[..];

View File

@@ -48,11 +48,11 @@ fn check_mq_support(if_name: &Option<&str>, queue_pairs: usize) -> Result<()> {
return Ok(());
}
let tun_flags_str = fs::read_to_string(path).map_err(Error::ReadSysfsTunFlags)?;
let tun_flags = u32::from_str_radix(tun_flags_str.trim().trim_start_matches("0x"), 16)
let tun_flags = i32::from_str_radix(tun_flags_str.trim().trim_start_matches("0x"), 16)
.map_err(Error::ConvertHexStringToInt)?;
if (tun_flags & net_gen::IFF_MULTI_QUEUE != 0) && !mq {
if (tun_flags & libc::IFF_MULTI_QUEUE != 0) && !mq {
return Err(Error::MultiQueueNoDeviceSupport);
} else if (tun_flags & net_gen::IFF_MULTI_QUEUE == 0) && mq {
} else if (tun_flags & libc::IFF_MULTI_QUEUE == 0) && mq {
return Err(Error::MultiQueueNoTapSupport);
}
}

View File

@@ -5,12 +5,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.
use std::ffi::{CStr, CString};
use std::fs::File;
use std::io::{Error as IoError, Read, Result as IoResult, Write};
use std::net::{IpAddr, Ipv6Addr};
use std::os::raw::*;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use libc::{__c_anonymous_ifr_ifru, ifreq};
use thiserror::Error;
use vmm_sys_util::ioctl::{ioctl_with_mut_ref, ioctl_with_ref, ioctl_with_val};
@@ -43,6 +45,8 @@ pub enum Error {
NetUtil(#[source] NetUtilError),
#[error("Interface name too long (max length is {MAX_INTERFACE_NAME_LEN}): {0}")]
IfnameTooLong(String),
#[error("Interface name contains interior NUL byte: {0:?}")]
IfnameContainsNUL(String),
#[error("Invalid interface name (does it exist?): {0}")]
InvalidIfname(String),
#[error("Error parsing MAC data")]
@@ -62,7 +66,8 @@ pub type Result<T> = ::std::result::Result<T, Error>;
#[derive(Debug)]
pub struct Tap {
tap_file: File,
if_name: Vec<u8>,
/// The name does not exceed [`MAX_INTERFACE_NAME_LEN`] bytes excluding the NUL byte.
if_name: CString,
}
impl PartialEq for Tap {
@@ -80,23 +85,6 @@ impl std::clone::Clone for Tap {
}
}
// Returns a byte vector representing the contents of a null terminated C string which
// contains if_name.
fn build_terminated_if_name(if_name: &str) -> Result<Vec<u8>> {
// Convert the string slice to bytes, and shadow the variable,
// since we no longer need the &str version.
let bytes = if_name.as_bytes();
if bytes.len() > MAX_INTERFACE_NAME_LEN {
return Err(Error::IfnameTooLong(if_name.to_string()));
}
let mut terminated_if_name = vec![b'\0'; bytes.len() + 1];
terminated_if_name[..bytes.len()].copy_from_slice(bytes);
Ok(terminated_if_name)
}
fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8> {
let mask = mask.segments();
let mut iter = mask.iter();
@@ -169,7 +157,12 @@ impl Tap {
}
pub fn open_named(if_name: &str, num_queue_pairs: usize, flags: Option<i32>) -> Result<Tap> {
let terminated_if_name = build_terminated_if_name(if_name)?;
if if_name.len() > MAX_INTERFACE_NAME_LEN {
return Err(Error::IfnameTooLong(if_name.to_string()));
}
let terminated_if_name =
CString::new(if_name).map_err(|_| Error::IfnameContainsNUL(if_name.to_string()))?;
// SAFETY: FFI call
let fd = unsafe {
@@ -192,42 +185,48 @@ impl Tap {
// value.
let mut features = 0;
// SAFETY: IOCTL with correct arguments
let ret = unsafe { ioctl_with_mut_ref(&tuntap, net_gen::TUNGETFEATURES(), &mut features) };
let ret =
unsafe { ioctl_with_mut_ref(&tuntap, libc::TUNGETFEATURES as c_ulong, &mut features) };
if ret < 0 {
return Err(Error::GetFeatures(IoError::last_os_error()));
}
// Check if the user parameters match the kernel support for MQ
if (features & net_gen::IFF_MULTI_QUEUE == 0) && num_queue_pairs > 1 {
if (features & libc::IFF_MULTI_QUEUE == 0) && num_queue_pairs > 1 {
return Err(Error::MultiQueueKernelSupport);
}
// This is pretty messy because of the unions used by ifreq. Since we
// don't call as_mut on the same union field more than once, this block
// is safe.
let mut ifreq: net_gen::ifreq = Default::default();
// SAFETY: see the comment above.
unsafe {
let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
let name_slice = &mut ifrn_name[..terminated_if_name.len()];
name_slice.copy_from_slice(terminated_if_name.as_slice());
ifreq.ifr_ifru.ifru_flags =
(net_gen::IFF_TAP | net_gen::IFF_NO_PI | net_gen::IFF_VNET_HDR) as c_short;
if num_queue_pairs > 1 {
ifreq.ifr_ifru.ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
}
let mut ifru_flags = (libc::IFF_TAP | libc::IFF_NO_PI | libc::IFF_VNET_HDR) as c_short;
if num_queue_pairs > 1 {
ifru_flags |= libc::IFF_MULTI_QUEUE as c_short;
}
let mut ifreq = libc::ifreq {
ifr_name: [0; libc::IFNAMSIZ],
ifr_ifru: __c_anonymous_ifr_ifru { ifru_flags },
};
// Convert and copy bytes to `ifr_name` buffer.
// `terminated_if_name` will fit into `ifr_name` since we enforce the length limit
// above.
ifreq
.ifr_name
.iter_mut()
.zip(terminated_if_name.as_bytes_with_nul())
.for_each(|(ifr_name_char, terminated_if_name_byte)| {
*ifr_name_char = *terminated_if_name_byte as c_char;
});
// SAFETY: ioctl is safe since we call it with a valid tap fd and check the return
// value.
let ret = unsafe { ioctl_with_mut_ref(&tuntap, net_gen::TUNSETIFF(), &mut ifreq) };
let ret = unsafe { ioctl_with_mut_ref(&tuntap, libc::TUNSETIFF as c_ulong, &mut ifreq) };
if ret < 0 {
return Err(Error::ConfigureTap(IoError::last_os_error()));
}
// SAFETY: only the name is accessed, and it's cloned out.
let mut if_name = unsafe { ifreq.ifr_ifrn.ifrn_name }.to_vec();
if_name.truncate(terminated_if_name.len() - 1);
// SAFETY: `ifreq.ifr_name` is set by the `ioctl_with_mut_ref` call and we checked the
// return code, so the name must be a valid `CStr`.
let if_name = unsafe { CStr::from_ptr(ifreq.ifr_name.as_ptr()) }.to_owned();
Ok(Tap {
tap_file: tuntap,
if_name,
@@ -254,27 +253,36 @@ impl Tap {
// SAFETY: fd is a tap fd
let tap_file = unsafe { File::from_raw_fd(fd) };
let mut ifreq: net_gen::ifreq = Default::default();
let mut ifreq: libc::ifreq = ifreq {
ifr_name: [0; libc::IFNAMSIZ],
ifr_ifru: __c_anonymous_ifr_ifru { ifru_flags: 0 },
};
// Get current config including name
// SAFETY: IOCTL with correct arguments
unsafe { Self::ioctl_with_mut_ref(&tap_file, net_gen::TUNGETIFF(), &mut ifreq)? };
unsafe { Self::ioctl_with_mut_ref(&tap_file, libc::TUNGETIFF as c_ulong, &mut ifreq)? };
// SAFETY: We only access one field of the ifru union
let if_name = unsafe { ifreq.ifr_ifrn.ifrn_name }.to_vec();
let if_name = {
let ifr_ptr = ifreq.ifr_name.as_ptr();
// SAFETY: The `ifr_name` field of the union is a valid, nul-terminated C string since it
// was just set by the ioctl call, and we checked for errors.
// We immediately convert the `CStr` to the owned `CString, so the memory of the union field
// is not accessed or mutated during the lifetime of the `Cstr`.
unsafe { CStr::from_ptr(ifr_ptr).to_owned() }
};
// Try and update flags. Depending on how the tap was created (macvtap
// or via open_named()) this might return -EEXIST so we just ignore that.
// SAFETY: access union fields
unsafe {
ifreq.ifr_ifru.ifru_flags =
(net_gen::IFF_TAP | net_gen::IFF_NO_PI | net_gen::IFF_VNET_HDR) as c_short;
(libc::IFF_TAP | libc::IFF_NO_PI | libc::IFF_VNET_HDR) as c_short;
if num_queue_pairs > 1 {
ifreq.ifr_ifru.ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
ifreq.ifr_ifru.ifru_flags |= libc::IFF_MULTI_QUEUE as c_short;
}
}
// SAFETY: IOCTL with correct arguments
let ret = unsafe { ioctl_with_mut_ref(&tap_file, net_gen::TUNSETIFF(), &mut ifreq) };
let ret = unsafe { ioctl_with_mut_ref(&tap_file, libc::TUNSETIFF as c_ulong, &mut ifreq) };
if ret < 0 && IoError::last_os_error().raw_os_error().unwrap() != libc::EEXIST {
return Err(Error::ConfigureTap(IoError::last_os_error()));
}
@@ -300,7 +308,7 @@ impl Tap {
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe {
Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFADDR as c_ulong, &ifreq)?;
Self::ioctl_with_ref(&sock, libc::SIOCSIFADDR as c_ulong, &ifreq)?;
}
if let Some(IpAddr::V4(mask)) = netmask {
@@ -308,11 +316,7 @@ impl Tap {
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe {
Self::ioctl_with_ref(
&sock,
net_gen::sockios::SIOCSIFNETMASK as c_ulong,
&ifreq,
)?;
Self::ioctl_with_ref(&sock, libc::SIOCSIFNETMASK as c_ulong, &ifreq)?;
}
}
@@ -322,18 +326,14 @@ impl Tap {
let ifindex = {
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe {
Self::ioctl_with_ref(
&sock,
net_gen::sockios::SIOCGIFINDEX as c_ulong,
&ifreq,
)?;
Self::ioctl_with_ref(&sock, libc::SIOCGIFINDEX as c_ulong, &ifreq)?;
}
// SAFETY: ifru_ivalue contains the ifindex and is set by the previous ioctl
unsafe {
match ifreq.ifr_ifru.ifru_ivalue {
match ifreq.ifr_ifru.ifru_ifindex {
0 => {
let name = String::from_utf8_lossy(&self.if_name).to_string();
let name = self.if_name.to_string_lossy().to_string();
return Err(Error::InvalidIfname(name));
}
i => i,
@@ -347,19 +347,17 @@ impl Tap {
None => 0,
};
let ifreq = net_gen::in6_ifreq {
let ifreq = libc::in6_ifreq {
// SAFETY: addr can be safely transmuted to in6_addr
ifr6_addr: unsafe {
std::mem::transmute::<[u8; 16], net_gen::ipv6::in6_addr>(addr.octets())
std::mem::transmute::<[u8; 16], libc::in6_addr>(addr.octets())
},
ifr6_prefixlen: prefixlen as u32,
ifr6_ifindex: ifindex,
};
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe {
Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFADDR as c_ulong, &ifreq)
}
unsafe { Self::ioctl_with_ref(&sock, libc::SIOCSIFADDR as c_ulong, &ifreq) }
}
}
}
@@ -380,18 +378,18 @@ impl Tap {
let mut ifreq = self.get_ifreq();
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe { Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFHWADDR as c_ulong, &ifreq)? };
unsafe { Self::ioctl_with_ref(&sock, libc::SIOCGIFHWADDR as c_ulong, &ifreq)? };
// SAFETY: We only access one field of the ifru union
unsafe {
let ifru_hwaddr = &mut ifreq.ifr_ifru.ifru_hwaddr;
for (i, v) in addr.get_bytes().iter().enumerate() {
ifru_hwaddr.sa_data[i] = *v as c_uchar;
ifru_hwaddr.sa_data[i] = *v as c_char;
}
}
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe { Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFHWADDR as c_ulong, &ifreq) }
unsafe { Self::ioctl_with_ref(&sock, libc::SIOCSIFHWADDR as c_ulong, &ifreq) }
}
/// Get mac addr for tap interface.
@@ -401,12 +399,21 @@ impl Tap {
let ifreq = self.get_ifreq();
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe { Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFHWADDR as c_ulong, &ifreq)? };
unsafe { Self::ioctl_with_ref(&sock, libc::SIOCGIFHWADDR as c_ulong, &ifreq)? };
// SAFETY: We only access one field of the ifru union
let addr = unsafe {
MacAddr::from_bytes(&ifreq.ifr_ifru.ifru_hwaddr.sa_data[0..MAC_ADDR_LEN])
.map_err(Error::MacParsing)?
let addr = {
let bytes: Vec<u8> =
// SAFETY: The `ioctl_with_ref` ensures accessing `ifru_hwaddr` is valid.
unsafe { ifreq.ifr_ifru.ifru_hwaddr.sa_data[0..MAC_ADDR_LEN].iter() }
.map(|byte| {
// On some architectures, `c_char` is already a `u8`.
#[allow(clippy::unnecessary_cast)]
{
*byte as u8
}
})
.collect();
MacAddr::from_bytes(&bytes).map_err(Error::MacParsing)?
};
Ok(addr)
}
@@ -418,7 +425,7 @@ impl Tap {
let ifreq = self.get_ifreq();
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe { Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFMTU as c_ulong, &ifreq)? };
unsafe { Self::ioctl_with_ref(&sock, libc::SIOCGIFMTU as c_ulong, &ifreq)? };
// SAFETY: access a union field
let mtu = unsafe { ifreq.ifr_ifru.ifru_mtu };
@@ -439,13 +446,19 @@ impl Tap {
ifreq.ifr_ifru.ifru_mtu = mtu;
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe { Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFMTU as c_ulong, &ifreq) }
unsafe { Self::ioctl_with_ref(&sock, libc::SIOCSIFMTU as c_ulong, &ifreq) }
}
/// Set the offload flags for the tap interface.
pub fn set_offload(&self, flags: c_uint) -> Result<()> {
// SAFETY: ioctl is safe. Called with a valid tap fd, and we check the return.
unsafe { Self::ioctl_with_val(&self.tap_file, net_gen::TUNSETOFFLOAD(), flags as c_ulong) }
unsafe {
Self::ioctl_with_val(
&self.tap_file,
libc::TUNSETOFFLOAD as c_ulong,
flags as c_ulong,
)
}
}
/// Enable the tap interface.
@@ -455,50 +468,46 @@ impl Tap {
let mut ifreq = self.get_ifreq();
// SAFETY: IOCTL with correct arguments
unsafe { Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFFLAGS as c_ulong, &ifreq)? };
unsafe { Self::ioctl_with_ref(&sock, libc::SIOCGIFFLAGS as c_ulong, &ifreq)? };
// If TAP device is already up don't try and enable it
// SAFETY: access a union field
let ifru_flags = unsafe { ifreq.ifr_ifru.ifru_flags };
if ifru_flags & net_gen::net_device_flags_IFF_UP as i16
== net_gen::net_device_flags_IFF_UP as i16
{
if ifru_flags & libc::IFF_UP as i16 == libc::IFF_UP as i16 {
return Ok(());
}
ifreq.ifr_ifru.ifru_flags = net_gen::net_device_flags_IFF_UP as i16;
ifreq.ifr_ifru.ifru_flags = libc::IFF_UP as i16;
// SAFETY: ioctl is safe. Called with a valid sock fd, and we check the return.
unsafe { Self::ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFFLAGS as c_ulong, &ifreq) }
unsafe { Self::ioctl_with_ref(&sock, libc::SIOCSIFFLAGS as c_ulong, &ifreq) }
}
/// Set the size of the vnet hdr.
pub fn set_vnet_hdr_size(&self, size: c_int) -> Result<()> {
// SAFETY: ioctl is safe. Called with a valid tap fd, and we check the return.
unsafe { Self::ioctl_with_ref(&self.tap_file, net_gen::TUNSETVNETHDRSZ(), &size) }
unsafe { Self::ioctl_with_ref(&self.tap_file, libc::TUNSETVNETHDRSZ as c_ulong, &size) }
}
fn get_ifreq(&self) -> net_gen::ifreq {
let mut ifreq: net_gen::ifreq = Default::default();
fn get_ifreq(&self) -> libc::ifreq {
let mut ifreq: libc::ifreq = libc::ifreq {
ifr_name: [0; libc::IFNAMSIZ],
ifr_ifru: __c_anonymous_ifr_ifru { ifru_flags: 0 },
};
// This sets the name of the interface, which is the only entry
// in a single-field union.
// SAFETY: access union fields and we're sure the copy is okay.
unsafe {
let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
let name_slice = &mut ifrn_name[..self.if_name.len()];
name_slice.copy_from_slice(&self.if_name);
}
// Convert and copy bytes to `ifr_name` buffer.
// `self.if_name` will fit into `ifr_name` since we enforce the length when setting it.
ifreq
.ifr_name
.iter_mut()
.zip(self.if_name.as_bytes_with_nul())
.for_each(|(ifr_name_char, terminated_if_name_byte)| {
*ifr_name_char = *terminated_if_name_byte as c_char;
});
ifreq
}
/// Returns the raw bytes of the interface name, which may or may not be
/// valid UTF-8.
pub fn if_name_as_bytes(&self) -> &[u8] {
&self.if_name
}
/// Returns the interface name as a string, truncated at the first NUL byte
/// if present.
///
@@ -509,19 +518,20 @@ impl Tap {
/// thus valid UTF-8. Also, self-generated interface names form CHV are
/// also always created from Rust strings, thus valid UTF-8.
pub fn if_name_as_str(&self) -> &str {
// All bytes until first NUL.
let nul_terminated = self
.if_name_as_bytes()
.split(|&b| b == 0)
.next()
.unwrap_or(&[]);
// Panicking here is fine, see function documentation.
std::str::from_utf8(nul_terminated).expect("Tap interface name should be valid UTF-8")
std::str::from_utf8(self.if_name.as_bytes())
.expect("Tap interface name should be valid UTF-8")
}
#[cfg(fuzzing)]
pub fn new_for_fuzzing(tap_file: File, if_name: Vec<u8>) -> Self {
pub fn new_for_fuzzing(tap_file: File, if_name: &str) -> Self {
if if_name.len() > MAX_INTERFACE_NAME_LEN {
panic!("provided name longer than `MAX_INTERFACE_NAME_LEN`")
}
let if_name = CString::new(if_name)
.map_err(|_| Error::IfnameContainsNUL(if_name.to_string()))
.unwrap();
Tap { tap_file, if_name }
}
}

View File

@@ -10,7 +10,6 @@ version = "0.1.0"
anyhow = { workspace = true }
libc = { workspace = true }
log = { workspace = true }
net_gen = { path = "../net_gen" }
thiserror = { workspace = true }
vmm-sys-util = { workspace = true }

View File

@@ -150,16 +150,16 @@ impl Emulator {
// SAFETY: FFI calls and return value of the unsafe call is checked
unsafe {
let tv = net_gen::iff::timeval {
let tv = libc::timeval {
tv_sec: 0,
tv_usec: 100000, // Set recv timeout to 100ms
};
let ret = net_gen::setsockopt(
let ret = libc::setsockopt(
fds[0],
net_gen::iff::SOL_SOCKET as i32,
net_gen::iff::SO_RCVTIMEO as i32,
libc::SOL_SOCKET,
libc::SO_RCVTIMEO,
&tv as *const _ as *const libc::c_void,
std::mem::size_of::<net_gen::iff::timeval>() as u32,
std::mem::size_of::<libc::timeval>() as u32,
);
if ret == -1 {
return Err(Error::PrepareDataFd(anyhow!(