Skip to content

fix(pcap): don't widen explicit host_spec with the interface subnet (Refs #758)#790

Merged
leoparente merged 6 commits into
developfrom
fix/pcap-host-spec-broadening
Jun 26, 2026
Merged

fix(pcap): don't widen explicit host_spec with the interface subnet (Refs #758)#790
leoparente merged 6 commits into
developfrom
fix/pcap-host-spec-broadening

Conversation

@leoparente

Copy link
Copy Markdown
Contributor

Refs #758. (Does not auto-close — see discussion there.)

Problem

On a libpcap live-capture input with an explicit host_spec (e.g. a VIP /32), pktvisord also appends the capture interface's address at its netmask prefix (e.g. 192.168.50.23/24) to the "host" set used for direction classification. The user's host_spec is silently widened to the whole subnet.

The result is DNS direction misclassification. With host_spec: 192.168.50.2/32, the query client → VIP classifies correctly (dst=VIP wins on the /32toHost), but the response VIP → client has dst=client, which matches the interface /24toHost instead of fromHost. Depending on the handler this either breaks transaction pairing (v2: query in the in map, response looked up in the out map → never pairs → dns_xact_in stays 0) or mis-increments (v1: pairs, but counts xacts_out instead of xacts_in). Either way server-side DNS is reported as client-side, the symptom in #758.

The af_packet source never does interface host-detection (hence pcap_source: af_packet is the known workaround), and pcap_file never auto-detects — so the defect is specific to live libpcap capture.

Fix

When parse_host_spec() has produced a non-empty host set, the explicit host_spec is authoritative and interface auto-detection is skipped (libpcap now matches af_packet). When no usable host_spec is given, the prior behavior is preserved exactly: the interface address is auto-added at its on-link/subnet prefix (the intentional inside/outside distinction).

The gate is !_hostIPv4.empty() || !_hostIPv6.empty() — the lists parse_host_spec() filled — and deliberately not config_exists("host_spec"): the CLI's default tap always emits host_spec (the empty string when -H is omitted), so config_exists would wrongly skip auto-detection for a plain pktvisord <iface> and classify every packet as unknown.

The decision + entry construction were extracted into a pure, unit-testable helper lib::utils::append_interface_host_subnets(...), so the new logic is covered without binding a live NIC. PcapInputStream::_get_hosts_from_libpcap_iface() keeps the OS getifaddrs gather and delegates to it.

  • libs/visor_utils/{utils.h,utils.cpp,test_utils.cpp} — the helper + a unit test covering both gate branches and multi-address ordering.
  • src/inputs/pcap/PcapInputStream.cpp — rewire the libpcap host detection through the helper.
  • cmd/pktvisord/main.cpp, cmd/pktvisor-reader/main.cpp-H help text now documents that, for live capture, it defines the host set explicitly and disables automatic detection (was "append to any automatic detection").

Behavior / compatibility

  • No change for inputs that don't set a usable host_spec — including a plain pktvisord <iface> (empty host_spec → auto-detect, unchanged).
  • Inputs with a non-empty host_spec on a libpcap interface now get exactly the host set they configured; this shifts all direction-derived metrics for them (net in/out, flow, dns_xact_in/out) — they were previously misclassified.
  • -H semantics change (intentional, per pcap host_spec is effectively widened by interface netmask, causing DNS xact direction misclassification #758): a non-empty -H is now authoritative (replace), not append. Help text updated in both binaries.
  • A host_spec in either family disables interface auto-detection for both families; on a dual-stack interface list every family you care about (the other family's traffic would otherwise be direction unknown, and is dropped if the v2 DNS handler's only_xact_directions filter excludes unknown).

Testing

  • New unit-tests-visor-utils case appendInterfaceHostSubnets (skip-when-provided / append-when-not / multiple same-family addresses): pass (19 assertions; full util suite 45).
  • unit-tests-input-pcap: pass, no regression.
  • The live getifaddrs path is not CI-reachable (no real NIC in CI); the pure helper carries the automated coverage. Manually verifiable on a live host: host_spec: <VIP>/32dns_xact_in_total increments for server-side DNS; no -H → auto-detect unchanged.

Reviews

Built spec → plan → 5 rounds of adversarial review (which caught a critical gate bug: an earlier draft gated on config_exists("host_spec"), which would have broken the dominant pktvisord <iface> path) → subagent-driven implementation with per-task + whole-branch review → a final adversarial review over the commits (build + tests run). All clean.

🤖 Generated with Claude Code

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes direction misclassification for live libpcap captures when users provide an explicit host_spec, by preventing pktvisord from silently widening the configured host set with the capture interface’s on-link subnet (Refs #758).

Changes:

  • Skip libpcap interface host auto-detection when parse_host_spec() already produced a non-empty host set.
  • Extract interface-host append logic into a unit-testable helper (lib::utils::append_interface_host_subnets) and add unit coverage for both gate branches and ordering.
  • Update -H help text in both binaries to document the new “authoritative host set” semantics for live capture.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/inputs/pcap/PcapInputStream.cpp Collect iface addresses then delegate host-subnet appending to the new helper, gated by whether host_spec populated host lists.
libs/visor_utils/utils.h Exposes the new append_interface_host_subnets(...) helper API.
libs/visor_utils/utils.cpp Implements the helper that appends interface host subnets only when no host set was provided.
libs/visor_utils/test_utils.cpp Adds unit tests covering skip/append behavior and multi-address ordering.
cmd/pktvisord/main.cpp Updates -H help text to reflect authoritative semantics for live capture.
cmd/pktvisor-reader/main.cpp Updates -H help text to reflect authoritative semantics for live capture.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/inputs/pcap/PcapInputStream.cpp
Comment thread libs/visor_utils/utils.cpp
Comment thread libs/visor_utils/utils.cpp
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

LCOV of commit e9be5cb during Debug Builds #184

  lines......: 82.5% (14321 of 17365 lines)
  functions..: 73.1% (1451 of 1984 functions)
  branches...: no data found

Files changed coverage rate: n/a

Full coverage report

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

@leoparente

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2028129693

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/inputs/pcap/PcapInputStream.cpp
@leoparente

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: df50edac73

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@leoparente leoparente marked this pull request as ready for review June 26, 2026 18:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comment thread src/inputs/pcap/PcapInputStream.cpp Outdated
@leoparente leoparente merged commit 7acee80 into develop Jun 26, 2026
23 checks passed
@leoparente leoparente deleted the fix/pcap-host-spec-broadening branch June 26, 2026 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants