r-extcap

Crates.ior-extcap
lib.rsr-extcap
version
sourcesrc
created_at2023-03-04 09:33:17.6005
updated_at2024-12-08 22:40:47.057877
descriptionWrite Wireshark extcap programs in Rust
homepage
repositoryhttps://github.com/mauricelam/r-extcap/
max_upload_size
id800508
Cargo.toml error:TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include`
size0
Maurice Lam (mauricelam)

documentation

https://docs.rs/r-extcap

README

r-extcap

Build status Crates.io Docs.rs

Write extcap programs in Rust.

The extcap interface is a versatile plugin interface used by Wireshark to allow external binaries to act as capture interfaces. The extcap interface itself is generic and can be used by applications other than Wireshark, like Wireshark's command line sibling tshark. For the sake of brevity, in the documentation we will refer to the host application simply as Wireshark.

Extcap overview

  1. --extcap-interfaces: In this step, Wireshark asks the extcap for its list of supported interfaces, version metadata, and the list of toolbar controls.
  2. --extcap-dlts: Invoked once for each interface, Wireshark asks the extcap program for the data link type associated with the interface.
  3. --extcap-config: Invoked for each interface upon user request, Wireshark asks the extcap program for a list of configurations to populate a config dialog in the UI.
  4. --capture: The main part of the extcap program – invoked once when the user selects an interface for capture, to tell the extcap to start capturing packets. Captured packets should be written to the --fifo in the PCAP format.

Getting started

To create an extcap using this library, these are the high level steps:

  1. Create a struct with #[derive(clap::Parser)], and add ExtcapArgs as one of the fields with the #[command(flatten)] attribute.

    #[derive(Debug, clap::Parser)]
    struct AppArgs {
        #[command(flatten)]
        extcap: r_extcap::ExtcapArgs,
    
        // Other args for extcap (see the `configs` module)
    }
    
  2. In a lazy_static, define the necessary interfaces, toolbar controls, and configs. If you are unsure, you can simply start with the Interfaces you want to capture and add the others later as needed.

  3. In the main function, parse the arguments and call ExtcapArgs::run. Use the returned ExtcapStep to perform the requested operation. There are 5 steps:

    1. InterfacesStep: List the interfaces that can be captured by this program, as well as the metadata and toolbar controls associated.
    2. DltsStep: Prints the DLTs for a given interface.
    3. ConfigStep: Optional, provide a list of UI configuration options that the user can change.
    4. ReloadConfigStep: Optional, if SelectorConfig::reload is configured in one of the configs, invoked to reload the list of options the user can choose from.
    5. CaptureStep: described below.
  4. In the CaptureStep, start capturing packets from the external interface, and write the packets to CaptureStep::fifo using the pcap_file crate.

Example

use clap::Parser;
use r_extcap::{cargo_metadata, ExtcapArgs, ExtcapStep, interface::*, controls::*, config::*};

#[derive(Debug, Parser)]
struct AppArgs {
    #[command(flatten)]
    extcap: ExtcapArgs,
}

lazy_static! {
    // static ref CONFIG_FOO: SelectorConfig = ...;
    // static ref CONFIG_BAR: StringConfig = ...;

    // static ref CONTROL_A: BooleanControl = ...;

    // static ref INTERFACE_1: Interface = ...;
}

fn main() -> anyhow::Result<()> {
    match AppArgs::parse().extcap.run()? {
        ExtcapStep::Interfaces(interfaces_step) => {
            interfaces_step.list_interfaces(
                &cargo_metadata!(),
                &[
                    // &*INTERFACE_1,
                ],
                &[
                    // &*CONTROL_A,
                    // &*CONTROL_B,
                ],
            );
        }
        ExtcapStep::Dlts(dlts_step) => {
            dlts_step.print_from_interfaces(&[
                // &*INTERFACE_1,
            ])?;
        }
        ExtcapStep::Config(config_step) => config_step.list_configs(&[
            // &*CONFIG_FOO,
            // &*CONFIG_BAR,
        ]),
        ExtcapStep::ReloadConfig(reload_config_step) => {
            reload_config_step.reload_from_configs(&[
                // &*CONFIG_FOO,
                // &*CONFIG_BAR,
            ])?;
        }
        ExtcapStep::Capture(capture_step) => {
            // Run capture
        }
    }
    Ok(())
}

References:

Contributions

Contributions of any form are appreciated. New features, bug fixes, documentation improvements, additional tests, or PRs with failing test cases are welcome.

Commit count: 64

cargo fmt