fix(pcap): don't widen explicit host_spec with the interface subnet (Refs #758)#790
Conversation
There was a problem hiding this comment.
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
-Hhelp 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.
LCOV of commit
|
|
@codex review |
There was a problem hiding this comment.
💡 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".
…hosts on restart (Refs #758)
|
@codex review |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
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'shost_specis silently widened to the whole subnet.The result is DNS direction misclassification. With
host_spec: 192.168.50.2/32, the queryclient → VIPclassifies correctly (dst=VIPwins on the/32→toHost), but the responseVIP → clienthasdst=client, which matches the interface/24→toHostinstead offromHost. Depending on the handler this either breaks transaction pairing (v2: query in theinmap, response looked up in theoutmap → never pairs →dns_xact_instays 0) or mis-increments (v1: pairs, but countsxacts_outinstead ofxacts_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_packetis 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 explicithost_specis authoritative and interface auto-detection is skipped (libpcap now matches af_packet). When no usablehost_specis 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 listsparse_host_spec()filled — and deliberately notconfig_exists("host_spec"): the CLI's default tap always emitshost_spec(the empty string when-His omitted), soconfig_existswould wrongly skip auto-detection for a plainpktvisord <iface>and classify every packet asunknown.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 OSgetifaddrsgather 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—-Hhelp 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
host_spec— including a plainpktvisord <iface>(emptyhost_spec→ auto-detect, unchanged).host_specon a libpcap interface now get exactly the host set they configured; this shifts all direction-derived metrics for them (netin/out, flow,dns_xact_in/out) — they were previously misclassified.-Hsemantics change (intentional, per pcap host_spec is effectively widened by interface netmask, causing DNS xact direction misclassification #758): a non-empty-His now authoritative (replace), not append. Help text updated in both binaries.host_specin 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 directionunknown, and is dropped if the v2 DNS handler'sonly_xact_directionsfilter excludesunknown).Testing
unit-tests-visor-utilscaseappendInterfaceHostSubnets(skip-when-provided / append-when-not / multiple same-family addresses): pass (19 assertions; full util suite 45).unit-tests-input-pcap: pass, no regression.getifaddrspath 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>/32→dns_xact_in_totalincrements 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 dominantpktvisord <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