diff --git a/dc/wireshark/build.rs b/dc/wireshark/build.rs index 6189b63d51..33b5e93ab4 100644 --- a/dc/wireshark/build.rs +++ b/dc/wireshark/build.rs @@ -2,8 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 fn main() { - let plugin_name = option_env("PLUGIN_NAME").unwrap_or_else(|| "dcQUIC".to_string()); - println!("cargo:rustc-env=PLUGIN_NAME={plugin_name}"); + let plugin_name = fwd("PLUGIN_NAME", "dcQUIC"); + let _ = fwd("PLUGIN_MAJOR_VERSION", "4"); + let _ = fwd("PLUGIN_MINOR_VERSION", "2"); println!( "cargo:rustc-env=PLUGIN_NAME_LOWER={}", plugin_name.to_lowercase() @@ -18,6 +19,13 @@ fn main() { } } +fn fwd, D: AsRef>(name: N, default: D) -> String { + let name = name.as_ref(); + let value = option_env(name).unwrap_or_else(|| default.as_ref().to_string()); + println!("cargo:rustc-env={name}={value}"); + value +} + fn env>(name: N) -> String { let name = name.as_ref(); option_env(name).unwrap_or_else(|| panic!("missing env {name}")) diff --git a/dc/wireshark/src/plugin.rs b/dc/wireshark/src/plugin.rs index ab1b5675f6..78b14c7dd7 100644 --- a/dc/wireshark/src/plugin.rs +++ b/dc/wireshark/src/plugin.rs @@ -8,15 +8,29 @@ use std::{ffi::CStr, sync::OnceLock}; #[used] static plugin_version: [std::ffi::c_char; 4] = [b'0' as _, b'.' as _, b'1' as _, b'\0' as _]; +macro_rules! env_version { + ($name:literal) => {{ + let v = env!($name); + if v.len() != 1 { + panic!("unexpected version"); + } + let v = v.as_bytes()[0] as char; + match v.to_digit(10) { + Some(v) => v as _, + None => panic!("unexpected version"), + } + }}; +} + // When bumping, make sure that the bindgen bindings are updated to the new version. #[no_mangle] #[used] -static plugin_want_major: std::ffi::c_int = 4; +static plugin_want_major: std::ffi::c_int = env_version!("PLUGIN_MAJOR_VERSION"); // When bumping, make sure that the bindgen bindings are updated to the new version. #[no_mangle] #[used] -static plugin_want_minor: std::ffi::c_int = 2; +static plugin_want_minor: std::ffi::c_int = env_version!("PLUGIN_MINOR_VERSION"); #[no_mangle] pub extern "C" fn plugin_register() { @@ -80,12 +94,12 @@ pub fn copy_to_rust(tvb: *mut wireshark_sys::tvbuff_t) -> Vec { buffer } -unsafe extern "C" fn dissect_heur_udp( +unsafe extern "C" fn dissect_heur_udp>( tvb: *mut wireshark_sys::tvbuff_t, mut pinfo: *mut wireshark_sys::_packet_info, proto: *mut wireshark_sys::_proto_node, _: *mut std::ffi::c_void, -) -> i32 { +) -> Ret { let fields = field::get(); let packet = copy_to_rust(tvb); @@ -116,7 +130,7 @@ unsafe extern "C" fn dissect_heur_udp( // Didn't look like a dcQUIC packet. if accepted_offset == 0 { - return 0; + return false.into(); } if !info.is_empty() { @@ -128,15 +142,15 @@ unsafe extern "C" fn dissect_heur_udp( set_protocol(pinfo, c"dcQUIC"); - accepted_offset as _ + (accepted_offset != 0).into() } -unsafe extern "C" fn dissect_heur_tcp( +unsafe extern "C" fn dissect_heur_tcp>( tvb: *mut wireshark_sys::tvbuff_t, mut pinfo: *mut wireshark_sys::_packet_info, proto: *mut wireshark_sys::_proto_node, _: *mut std::ffi::c_void, -) -> i32 { +) -> Ret { let fields = field::get(); let packet = copy_to_rust(tvb); @@ -179,7 +193,7 @@ unsafe extern "C" fn dissect_heur_tcp( // Didn't look like a dcQUIC segment. if accepted_offset == 0 { - return 0; + return false.into(); } if !info.is_empty() { @@ -191,7 +205,7 @@ unsafe extern "C" fn dissect_heur_tcp( set_protocol(pinfo, c"TCP/dcQUIC"); - accepted_offset as _ + (accepted_offset != 0).into() } unsafe fn register_root_node( diff --git a/dc/wireshark/src/wireshark.rs b/dc/wireshark/src/wireshark.rs index 30a473c8f7..32e2eabd03 100644 --- a/dc/wireshark/src/wireshark.rs +++ b/dc/wireshark/src/wireshark.rs @@ -168,7 +168,7 @@ mod wireshark_sys_impl { buffer.tvb, parsed.offset as _, parsed.len as _, - parsed.value as u32, + parsed.value as _, ) } } @@ -186,7 +186,7 @@ mod wireshark_sys_impl { buffer.tvb, parsed.offset as _, parsed.len as _, - parsed.value.into() as u32, + parsed.value.into() as _, ) } } @@ -237,8 +237,8 @@ mod wireshark_sys_impl { parsed: Parsed, ) -> Self::AddedItem { let time = wireshark_sys::nstime_t { - secs: parsed.value.as_secs() as i64, - nsecs: parsed.value.subsec_nanos() as i32, + secs: parsed.value.as_secs() as _, + nsecs: parsed.value.subsec_nanos() as _, }; unsafe { wireshark_sys::proto_tree_add_time( diff --git a/dc/wireshark/xtask/src/main.rs b/dc/wireshark/xtask/src/main.rs index 83899e3c97..d9a6153054 100644 --- a/dc/wireshark/xtask/src/main.rs +++ b/dc/wireshark/xtask/src/main.rs @@ -45,10 +45,14 @@ struct Build { profile: Option, #[arg(long)] target: Option, + #[command(flatten)] + wireshark_version: WiresharkVersion, } impl Build { - fn run(self, sh: &Shell) -> Result { + fn run(mut self, sh: &Shell) -> Result { + self.wireshark_version.load(sh); + let target = if let Some(target) = self.target.as_ref() { let _ = cmd!(sh, "rustup target add {target}").run(); vec!["--target", target] @@ -56,18 +60,31 @@ impl Build { vec![] }; let profile = self.profile.as_deref().unwrap_or("release"); + + let _env = sh.push_env( + "PLUGIN_MAJOR_VERSION", + self.wireshark_version.major_version(), + ); + let _env = sh.push_env( + "PLUGIN_MINOR_VERSION", + self.wireshark_version.minor_version(), + ); + cmd!(sh, "cargo build --profile {profile} {target...}").run()?; Ok(()) } } #[derive(Debug, Parser)] -struct Test {} +struct Test { + #[command(flatten)] + wireshark_version: WiresharkVersion, +} impl Test { - fn run(self, sh: &Shell) -> Result { + fn run(mut self, sh: &Shell) -> Result { cmd!(sh, "cargo test").run()?; - let plugin_dir = plugin_dir(); + let plugin_dir = self.wireshark_version.plugin_dir(sh); sh.create_dir(format!("target/wireshark/{plugin_dir}"))?; sh.create_dir("target/pcaps")?; @@ -76,6 +93,14 @@ impl Test { let plugin_name = "dcQUIC__DEV"; let plugin_name_lower = &plugin_name.to_lowercase(); let _env = sh.push_env("PLUGIN_NAME", plugin_name); + let _env = sh.push_env( + "PLUGIN_MAJOR_VERSION", + self.wireshark_version.major_version(), + ); + let _env = sh.push_env( + "PLUGIN_MINOR_VERSION", + self.wireshark_version.minor_version(), + ); let profile = "release-test"; @@ -176,26 +201,27 @@ fn so() -> &'static str { } } -fn plugin_dir() -> &'static str { - if cfg!(target_os = "macos") { - "plugins/4-2/epan" - } else { - "plugins/4.2/epan" - } -} - #[derive(Debug, Parser)] -struct Install {} +struct Install { + #[command(flatten)] + wireshark_version: WiresharkVersion, +} impl Install { - fn run(self, sh: &Shell) -> Result { - Build::default().run(sh)?; + fn run(mut self, sh: &Shell) -> Result { + let plugin_dir = self.wireshark_version.plugin_dir(sh); + + Build { + wireshark_version: self.wireshark_version.clone(), + ..Default::default() + } + .run(sh)?; let dir = if cfg!(unix) { homedir::get_my_home()? .expect("missing home dir") .join(".local/lib/wireshark") - .join(plugin_dir()) + .join(plugin_dir) } else { todo!("OS is currently unsupported") }; @@ -212,6 +238,62 @@ impl Install { } } +#[derive(Clone, Debug, Default, Parser)] +struct WiresharkVersion { + #[arg(long, default_value = "DYNAMIC")] + wireshark_version: String, +} + +impl WiresharkVersion { + fn plugin_dir(&mut self, sh: &Shell) -> String { + self.load(sh); + + let value = &self.wireshark_version; + if cfg!(target_os = "macos") { + format!("plugins/{}/epan", value.replace('.', "-")) + } else { + format!("plugins/{value}/epan") + } + } + + fn load(&mut self, sh: &Shell) { + if !(self.wireshark_version.is_empty() || self.wireshark_version == "DYNAMIC") { + return; + } + + let tshark = tshark(sh).unwrap(); + let output = cmd!(sh, "{tshark} --version").read().unwrap(); + let version = output.lines().next().unwrap(); + let version = version.trim_start_matches(|v: char| !v.is_digit(10)); + let (version, _) = version + .split_once(char::is_whitespace) + .unwrap_or((version, "")); + + let version = version.trim_end_matches('.'); + + match version.split('.').count() { + 2 => { + self.wireshark_version = version.to_string(); + } + 3 => { + let (version, _) = version.rsplit_once('.').unwrap(); + self.wireshark_version = version.to_string(); + } + _ => panic!("invalid tshark version: {version}"), + } + } + + fn major_version(&self) -> &str { + let (version, _) = self.wireshark_version.split_once('.').unwrap(); + version + } + + fn minor_version(&self) -> &str { + let (_, version) = self.wireshark_version.split_once('.').unwrap(); + version + } +} + fn main() { Args::parse().run(); }