imsnif/bandwhich · critical

{err_msg}

Error message

{err_msg}

What it means

After filtering available interfaces, bandwhich tries to open a packet frame receiver on each. If every attempt fails, it aggregates the underlying errors into `err_msg` (distinguishing EPERM/permission errors from other errors) and bails with this message.

Solutions

  1. Run with elevated privileges: `sudo bandwhich` (raw capture needs CAP_NET_RAW)
  2. Grant the binary capabilities instead of sudo: `sudo setcap cap_net_raw,cap_net_admin=eip $(which bandwhich)`
  3. Check container security options (`--cap-add=NET_RAW --cap-add=NET_ADMIN`)
  4. Ensure no other sniffer exclusively holds the interface; read the aggregated err_msg to see the per-interface cause

Example fix

// before
bandwhich  # EPERM on all interfaces
// after
sudo setcap cap_net_raw,cap_net_admin=eip $(which bandwhich)
bandwhich
Defensive patterns

Strategy: validation

Validate before calling

// shell: confirm capture privileges before running
if [ "$(id -u)" -ne 0 ] && ! getcap "$(which bandwhich)" | grep -q cap_net_raw; then
  echo "Run with sudo or setcap cap_net_raw,cap_net_admin=eip"
  exit 1
fi

Try / catch

sudo bandwhich 2>errs.log || { cat errs.log; echo "check per-interface errors above (EPERM => privileges)"; }

Prevention

When it happens

Trigger: All calls to create a frame receiver (via `pnet`/datalink channel creation) fail for every interface — e.g. EPERM because the process lacks root/cap_net_raw, or bind failures — leaving `interfaces_with_frames` empty.

Common situations: Running bandwithout sudo, missing CAP_NET_RAW capability in containers, SELinux/AppArmor denials, or all interfaces bound by another capture process.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of imsnif/bandwhich@1899870cea (2026-09-08). Data as JSON: /api/errors/c573890a933ce3ea. Report an issue: GitHub.

Appendix: source

Thrown at src/os/shared.rs:199

            },
        );

        let err_msg = match (permission_err_interfaces.is_empty(), other_errs.is_empty()) {
            (false, false) => format!(
                "\n\n{}: {}\nAdditional errors:\n{}",
                permission_err_interfaces.join(", "),
                eperm_message(),
                other_errs.join("\n")
            ),
            (false, true) => format!(
                "\n\n{}: {}",
                permission_err_interfaces.join(", "),
                eperm_message()
            ),
            (true, false) => format!("\n\n{}", other_errs.join("\n")),
            (true, true) => unreachable!("Found no errors in error handling code path."),
        };
        bail!(err_msg);
    }

    // filter out interfaces for which we failed to acquire a frame receiver
    let interfaces_with_frames = interfaces_with_frames_res
        .into_iter()
        .filter_map(|(interface, res)| res.ok().map(|frames| (interface, frames)))
        .collect();

    let dns_client = if resolve {
        let runtime = Runtime::new()?;
        let resolver = runtime
            .block_on(dns::Resolver::new(dns_server))
            .map_err(|err| {
                eyre!("Could not initialize the DNS resolver. Are you offline?\n\nReason: {err}")
            })?;
        let dns_client = dns::Client::new(resolver, runtime)?;
        Some(dns_client)
    } else {

View on GitHub (pinned to 1899870cea)