summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2024-08-28 09:32:55 +0200
committerMarkus Pettersson <markus.pettersson@mullvad.net>2024-08-28 09:32:55 +0200
commit7ead1cce4a7e12e8f42ed65c32323af5ff0d57f9 (patch)
treeb70bf3516c999c86a1ea59426ecd6e3efd68cad8
parente1af89b893444b2c58312a8199693dca13e9707a (diff)
parent43b276e1cbb8e9bacdd7886ad6e83153f6a4332b (diff)
downloadmullvadvpn-7ead1cce4a7e12e8f42ed65c32323af5ff0d57f9.tar.xz
mullvadvpn-7ead1cce4a7e12e8f42ed65c32323af5ff0d57f9.zip
Merge branch 'cleanup-libpcap-bindings-for-macos-des-1188'
-rw-r--r--Cargo.lock4
-rw-r--r--talpid-core/Cargo.toml2
-rw-r--r--talpid-core/src/split_tunnel/macos/bindings.rs324
-rw-r--r--talpid-core/src/split_tunnel/macos/bpf.rs8
-rwxr-xr-xtalpid-core/src/split_tunnel/macos/generate-bindings.sh4
-rw-r--r--talpid-core/src/split_tunnel/macos/tun.rs42
6 files changed, 64 insertions, 320 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9e5b30d1af..ec64baf113 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2740,9 +2740,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pcap"
-version = "2.0.0"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45f1686828a29fd8002fbf9c01506b4b2dd575c2305e1b884da3731abae8b9e0"
+checksum = "fe4d339439e5e7f8ce32d58c2b58d5e304790e66f3aa0bd391dd6a9dc676e054"
dependencies = [
"bitflags 1.3.2",
"errno 0.2.8",
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml
index be8d6ca39b..a5a25aad59 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -53,7 +53,7 @@ system-configuration = "0.5.1"
hickory-proto = "0.24.1"
hickory-server = { version = "0.24.1", features = ["resolver"] }
talpid-platform-metadata = { path = "../talpid-platform-metadata" }
-pcap = { version = "2.0", features = ["capture-stream"] }
+pcap = { version = "2.1", features = ["capture-stream"] }
pnet_packet = "0.34"
tun = { version = "0.5.5", features = ["async"] }
nix = { version = "0.28", features = ["socket"] }
diff --git a/talpid-core/src/split_tunnel/macos/bindings.rs b/talpid-core/src/split_tunnel/macos/bindings.rs
index 931ac84d2e..425527d5c0 100644
--- a/talpid-core/src/split_tunnel/macos/bindings.rs
+++ b/talpid-core/src/split_tunnel/macos/bindings.rs
@@ -1,7 +1,6 @@
-// automatically generated by rust-bindgen 0.69.2
+/* automatically generated by rust-bindgen 0.70.1 */
pub const PTH_FLAG_DIR_OUT: u32 = 2;
-pub const PCAP_ERRBUF_SIZE: u32 = 256;
pub type __int32_t = ::std::os::raw::c_int;
pub type __darwin_pid_t = __int32_t;
pub type __darwin_uuid_t = [::std::os::raw::c_uchar; 16usize];
@@ -12,41 +11,13 @@ pub struct timeval32 {
pub tv_sec: __int32_t,
pub tv_usec: __int32_t,
}
-#[test]
-fn bindgen_test_layout_timeval32() {
- const UNINIT: ::std::mem::MaybeUninit<timeval32> = ::std::mem::MaybeUninit::uninit();
- let ptr = UNINIT.as_ptr();
- assert_eq!(
- ::std::mem::size_of::<timeval32>(),
- 8usize,
- concat!("Size of: ", stringify!(timeval32))
- );
- assert_eq!(
- ::std::mem::align_of::<timeval32>(),
- 4usize,
- concat!("Alignment of ", stringify!(timeval32))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize },
- 0usize,
- concat!(
- "Offset of field: ",
- stringify!(timeval32),
- "::",
- stringify!(tv_sec)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).tv_usec) as usize - ptr as usize },
- 4usize,
- concat!(
- "Offset of field: ",
- stringify!(timeval32),
- "::",
- stringify!(tv_usec)
- )
- );
-}
+#[allow(clippy::unnecessary_operation, clippy::identity_op)]
+const _: () = {
+ ["Size of timeval32"][::std::mem::size_of::<timeval32>() - 8usize];
+ ["Alignment of timeval32"][::std::mem::align_of::<timeval32>() - 4usize];
+ ["Offset of field: timeval32::tv_sec"][::std::mem::offset_of!(timeval32, tv_sec) - 0usize];
+ ["Offset of field: timeval32::tv_usec"][::std::mem::offset_of!(timeval32, tv_usec) - 4usize];
+};
pub type uuid_t = __darwin_uuid_t;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
@@ -72,237 +43,48 @@ pub struct pktap_header {
pub pth_uuid: uuid_t,
pub pth_euuid: uuid_t,
}
-#[test]
-fn bindgen_test_layout_pktap_header() {
- const UNINIT: ::std::mem::MaybeUninit<pktap_header> = ::std::mem::MaybeUninit::uninit();
- let ptr = UNINIT.as_ptr();
- assert_eq!(
- ::std::mem::size_of::<pktap_header>(),
- 156usize,
- concat!("Size of: ", stringify!(pktap_header))
- );
- assert_eq!(
- ::std::mem::align_of::<pktap_header>(),
- 4usize,
- concat!("Alignment of ", stringify!(pktap_header))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_length) as usize - ptr as usize },
- 0usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_length)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_type_next) as usize - ptr as usize },
- 4usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_type_next)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_dlt) as usize - ptr as usize },
- 8usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_dlt)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_ifname) as usize - ptr as usize },
- 12usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_ifname)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_flags) as usize - ptr as usize },
- 36usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_flags)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_protocol_family) as usize - ptr as usize },
- 40usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_protocol_family)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_frame_pre_length) as usize - ptr as usize },
- 44usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_frame_pre_length)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_frame_post_length) as usize - ptr as usize },
- 48usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_frame_post_length)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_pid) as usize - ptr as usize },
- 52usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_pid)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_comm) as usize - ptr as usize },
- 56usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_comm)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_svc) as usize - ptr as usize },
- 76usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_svc)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_iftype) as usize - ptr as usize },
- 80usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_iftype)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_ifunit) as usize - ptr as usize },
- 82usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_ifunit)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_epid) as usize - ptr as usize },
- 84usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_epid)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_ecomm) as usize - ptr as usize },
- 88usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_ecomm)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_flowid) as usize - ptr as usize },
- 108usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_flowid)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_ipproto) as usize - ptr as usize },
- 112usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_ipproto)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_tstamp) as usize - ptr as usize },
- 116usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_tstamp)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_uuid) as usize - ptr as usize },
- 124usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_uuid)
- )
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).pth_euuid) as usize - ptr as usize },
- 140usize,
- concat!(
- "Offset of field: ",
- stringify!(pktap_header),
- "::",
- stringify!(pth_euuid)
- )
- );
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct pcap {
- _unused: [u8; 0],
-}
-pub type pcap_t = pcap;
-extern "C" {
- pub fn pcap_create(
- arg1: *const ::std::os::raw::c_char,
- arg2: *mut ::std::os::raw::c_char,
- ) -> *mut pcap_t;
-}
-extern "C" {
- pub fn pcap_set_want_pktap(
- arg1: *mut pcap_t,
- arg2: ::std::os::raw::c_int,
- ) -> ::std::os::raw::c_int;
-}
-pub const BIOCSWANTPKTAP: u64 = 3221504639;
+#[allow(clippy::unnecessary_operation, clippy::identity_op)]
+const _: () = {
+ ["Size of pktap_header"][::std::mem::size_of::<pktap_header>() - 156usize];
+ ["Alignment of pktap_header"][::std::mem::align_of::<pktap_header>() - 4usize];
+ ["Offset of field: pktap_header::pth_length"]
+ [::std::mem::offset_of!(pktap_header, pth_length) - 0usize];
+ ["Offset of field: pktap_header::pth_type_next"]
+ [::std::mem::offset_of!(pktap_header, pth_type_next) - 4usize];
+ ["Offset of field: pktap_header::pth_dlt"]
+ [::std::mem::offset_of!(pktap_header, pth_dlt) - 8usize];
+ ["Offset of field: pktap_header::pth_ifname"]
+ [::std::mem::offset_of!(pktap_header, pth_ifname) - 12usize];
+ ["Offset of field: pktap_header::pth_flags"]
+ [::std::mem::offset_of!(pktap_header, pth_flags) - 36usize];
+ ["Offset of field: pktap_header::pth_protocol_family"]
+ [::std::mem::offset_of!(pktap_header, pth_protocol_family) - 40usize];
+ ["Offset of field: pktap_header::pth_frame_pre_length"]
+ [::std::mem::offset_of!(pktap_header, pth_frame_pre_length) - 44usize];
+ ["Offset of field: pktap_header::pth_frame_post_length"]
+ [::std::mem::offset_of!(pktap_header, pth_frame_post_length) - 48usize];
+ ["Offset of field: pktap_header::pth_pid"]
+ [::std::mem::offset_of!(pktap_header, pth_pid) - 52usize];
+ ["Offset of field: pktap_header::pth_comm"]
+ [::std::mem::offset_of!(pktap_header, pth_comm) - 56usize];
+ ["Offset of field: pktap_header::pth_svc"]
+ [::std::mem::offset_of!(pktap_header, pth_svc) - 76usize];
+ ["Offset of field: pktap_header::pth_iftype"]
+ [::std::mem::offset_of!(pktap_header, pth_iftype) - 80usize];
+ ["Offset of field: pktap_header::pth_ifunit"]
+ [::std::mem::offset_of!(pktap_header, pth_ifunit) - 82usize];
+ ["Offset of field: pktap_header::pth_epid"]
+ [::std::mem::offset_of!(pktap_header, pth_epid) - 84usize];
+ ["Offset of field: pktap_header::pth_ecomm"]
+ [::std::mem::offset_of!(pktap_header, pth_ecomm) - 88usize];
+ ["Offset of field: pktap_header::pth_flowid"]
+ [::std::mem::offset_of!(pktap_header, pth_flowid) - 108usize];
+ ["Offset of field: pktap_header::pth_ipproto"]
+ [::std::mem::offset_of!(pktap_header, pth_ipproto) - 112usize];
+ ["Offset of field: pktap_header::pth_tstamp"]
+ [::std::mem::offset_of!(pktap_header, pth_tstamp) - 116usize];
+ ["Offset of field: pktap_header::pth_uuid"]
+ [::std::mem::offset_of!(pktap_header, pth_uuid) - 124usize];
+ ["Offset of field: pktap_header::pth_euuid"]
+ [::std::mem::offset_of!(pktap_header, pth_euuid) - 140usize];
+};
diff --git a/talpid-core/src/split_tunnel/macos/bpf.rs b/talpid-core/src/split_tunnel/macos/bpf.rs
index ec3f8fc62d..566cc1f56b 100644
--- a/talpid-core/src/split_tunnel/macos/bpf.rs
+++ b/talpid-core/src/split_tunnel/macos/bpf.rs
@@ -22,8 +22,6 @@ use std::{
};
use tokio::io::{unix::AsyncFd, AsyncRead, Interest, ReadBuf};
-use super::bindings::BIOCSWANTPKTAP;
-
#[derive(thiserror::Error, Debug)]
pub enum Error {
/// Failed to open BPF device
@@ -167,12 +165,6 @@ impl Bpf {
unsafe { ioctl!(self.file.as_raw_fd(), BIOCSHDRCMPLT, &enable) }
}
- pub fn set_want_pktap(&self, enable: bool) -> Result<(), Error> {
- let enable: c_int = if enable { 1 } else { 0 };
- // SAFETY: The fd is valid for the lifetime of `self`
- unsafe { ioctl!(self.file.as_raw_fd(), BIOCSWANTPKTAP, &enable) }
- }
-
pub fn set_buffer_size(&self, mut buffer_size: c_uint) -> Result<usize, Error> {
// SAFETY: The fd is valid for the lifetime of `self`
unsafe {
diff --git a/talpid-core/src/split_tunnel/macos/generate-bindings.sh b/talpid-core/src/split_tunnel/macos/generate-bindings.sh
index 9cfa5c1b62..a52c09fd86 100755
--- a/talpid-core/src/split_tunnel/macos/generate-bindings.sh
+++ b/talpid-core/src/split_tunnel/macos/generate-bindings.sh
@@ -13,9 +13,5 @@ curl https://opensource.apple.com/source/libpcap/libpcap-67/libpcap/pcap/pcap.h
curl https://opensource.apple.com/source/xnu/xnu-3789.41.3/bsd/net/bpf.h -o include/bpf.h
bindgen "include/bindings.h" -o ./bindings.rs \
- --allowlist-item "^pcap_create" \
- --allowlist-item "^pcap_set_want_pktap" \
--allowlist-item "^pktap_header" \
- --allowlist-item "PCAP_ERRBUF_SIZE" \
- --allowlist-item "^BIOCSWANTPKTAP" \
--allowlist-item "^PTH_FLAG_DIR_OUT"
diff --git a/talpid-core/src/split_tunnel/macos/tun.rs b/talpid-core/src/split_tunnel/macos/tun.rs
index f5cc588786..0e260a1517 100644
--- a/talpid-core/src/split_tunnel/macos/tun.rs
+++ b/talpid-core/src/split_tunnel/macos/tun.rs
@@ -2,9 +2,7 @@
//! either the default interface or a VPN tunnel interface.
use super::{
- bindings::{
- pcap_create, pcap_set_want_pktap, pktap_header, PCAP_ERRBUF_SIZE, PTH_FLAG_DIR_OUT,
- },
+ bindings::{pktap_header, PTH_FLAG_DIR_OUT},
bpf,
default::DefaultInterface,
};
@@ -25,7 +23,6 @@ use std::{
ffi::{c_uint, CStr},
io::{self, IoSlice, Write},
net::{Ipv4Addr, Ipv6Addr},
- ptr::NonNull,
};
use talpid_routing::RouteManagerHandle;
use tokio::{
@@ -57,7 +54,7 @@ pub enum Error {
EnableNonblock(#[source] pcap::Error),
/// pcap_create failed
#[error("pcap_create failed: {}", _0)]
- CreatePcap(String),
+ CreatePcap(#[source] pcap::Error),
/// Failed to create packet stream
#[error("Failed to create packet stream")]
CreateStream(#[source] pcap::Error),
@@ -806,8 +803,13 @@ fn fix_ipv6_checksums(
fn capture_outbound_packets(
utun_iface: &str,
) -> Result<impl Stream<Item = Result<PktapPacket, Error>> + Send, Error> {
- let cap = pktap_capture()?
+ // We want to create a pktap "pseudo-device" and capture data on it using a bpf device.
+ // This provides packet data plus a pktap header including process information.
+ // libpcap will do the heavy lifting for us if we simply request a "pktap" device.
+ let cap = pcap::Capture::from_device("pktap")
+ .map_err(Error::CreatePcap)?
.immediate_mode(true)
+ .want_pktap(true)
.open()
.map_err(Error::CaptureSplitTunnelDevice)?;
@@ -894,31 +896,3 @@ impl PacketCodec for PktapCodec {
})
}
}
-
-/// Create a pktap interface using `libpcap`
-fn pktap_capture() -> Result<pcap::Capture<pcap::Inactive>, Error> {
- // We want to create a pktap "pseudo-device" and capture data on it using a bpf device.
- // This provides packet data plus a pktap header including process information.
- // libpcap will do the heavy lifting for us if we simply request a "pktap" device.
-
- let mut errbuf = [0u8; PCAP_ERRBUF_SIZE as usize];
-
- let pcap = unsafe { pcap_create(c"pktap".as_ptr(), errbuf.as_mut_ptr() as _) };
- if pcap.is_null() {
- let errstr = CStr::from_bytes_until_nul(&errbuf)
- .unwrap()
- .to_string_lossy()
- .into_owned();
- return Err(Error::CreatePcap(errstr));
- }
- unsafe { pcap_set_want_pktap(pcap, 1) };
-
- // TODO: Upstream setting "want pktap" directly on Capture
- // If we had that, we could have simply used pcap::Capture::from_device("pktap")
- // TODO: Also upstream exposure of a raw handle to pcap_t on Capture<Inactive>
-
- // just casting a pointer to a private type using _. that's fine, apparently
- Ok(pcap::Capture::from(unsafe {
- NonNull::new_unchecked(pcap as *mut _)
- }))
-}