---
module: agent.packet-capture
title: Packet Capture — on-demand network capture for ATM diagnostics
tab: Claude
order: 40
audience: dev
---

> **Internal · agent reference.** Terse. Confirmed against `hiveops-module-packet-capture` source 2026-07-01.

## Identity
- Module name (`AgentModule.getName()`): **`packet-capture`**
- Maven artifact: **`hiveops-module-packet-capture`** (own version `1.0.0`; parent `hiveops-agent-parent` currently `4.4.3`)
- Entry class: `com.hiveops.packetcapture.PacketCaptureModule` (SPI file: `META-INF/services/com.hiveops.core.module.AgentModule`)
- Other classes: `PacketCaptureHandler` (task execution), `PacketCaptureTool` (OS-specific capture runner)
- Log package (`getLogPackage()`): `com.hiveops.packetcapture` → `logs/modules/packet-capture.log`
- Fleet task kind it implements: **`PACKET_CAPTURE`** (exact string, passed to `queryCurrentAtmPendingTask(country, atm, "PACKET_CAPTURE")`; the matching `FleetTaskKind` enum lives in `hiveops-fleet` — *(unverified, cross-repo)*)

## Config properties
- **No dedicated `packet-capture.*` keys exist in code.** Reuses whichever is set:
  - `agent.endpoint` (preferred) or `incident.endpoint` (fallback) — HTTP base URL
  - `agent.auth.token` / `agent.institution.key` — auth (shared across modules)
  - `modules.disabled` — comma list; include `packet-capture` to disable
- `isEnabled()` = true whenever `agent.endpoint` OR `incident.endpoint` is non-blank (on by default).
- Hardcoded (not configurable): `POLL_INTERVAL_SECONDS = 30`, `MAX_DURATION = 300` (seconds, hard cap), `SEGMENT_SIZE = 100_000` (upload chunk bytes).

## Fleet task `configPatch` keys (set by the operator in Fleet UI)
| Key | Default if absent | Notes |
|---|---|---|
| `duration` | `60` | seconds; clamped **agent-side** to ≤300 (`Math.min(parsed, MAX_DURATION)`) |
| `interface` | `"auto"` | blank or `"auto"` → OS default interface |
| `filter` | `""` | BPF filter string, e.g. `tcp port 443`; **ignored** by `pktmon`/`netsh` Windows fallbacks |

## Event / status strings emitted
- **No `EventType` / `IAT_*` / journal-incident events.** This module never calls `IncidentEventClient`.
- Only emits **fleet task status** via `FileUploadClient.statusReport(tid, aid, status, message)`: `"RUNNING"`, `"COMPLETED"`, `"FAILED"` (plus free-text progress messages while running).

## HTTP endpoints used (agent → agent-proxy)
| Call | Path |
|---|---|
| Poll (kind-filtered) | `GET {endpoint}/api/agent/{country}/{atm}/task?kind=PACKET_CAPTURE` |
| Status report | `POST {endpoint}/api/agent/tasks/{tid}/status` |
| Upload chunk | `POST {endpoint}/api/agent/tasks/{tid}/upload?o=<base36offset>&f=<filename>` |

Base URL = `agent.endpoint` (preferred) or `incident.endpoint` (fallback), from `HttpClientHelper.loadSettingsFromProperties(props, prefix)`. In current topology `agent.endpoint` points at `agent-proxy`, which forwards to incident's internal fleet API — *(agent-proxy controller/internal path unverified, cross-repo)*. Same transport as every other fleet-task module.

## Capture tool selection (in order tried)
- **Linux:** `tcpdump` only — no fallback; module throws if `tcpdump` isn't installed. Output: `.pcap`.
- **Windows:** `tshark` → `.pcap` (supports `-f <BPF filter>`) → else `pktmon` → `.etl` (no filter support) → else `netsh trace` → `.etl` (no filter support, `stop` can take up to 90s).
- Output file extension is decided by `PacketCaptureTool.detectFormat()` **before** the real capture file is created, so it matches the tool that will actually run.

## Concurrency / lifecycle
- `AtomicBoolean captureInProgress` (static in `PacketCaptureModule`, shared with `PacketCaptureHandler`) allows only **one capture per ATM at a time**. A second concurrent `PACKET_CAPTURE` task fails immediately: "Another capture is already in progress on this ATM".
- Capture file is **always deleted** locally after upload (success or failure) — never left on ATM disk.
- `stop()` (agent shutdown) calls `PacketCaptureHandler.abort()` → `PacketCaptureTool.abort()`, force-killing the running process (and best-effort `pktmon stop`/`netsh trace stop` on Windows).

## Deployment
- Ships in the **`atm`** module set of `deployment/build-dist.sh` (default), NOT the `srv` (server-monitor) set.
- Delivered as drop-in JAR `modules/hiveops-module-packet-capture.jar` — not bundled in the fat JAR.
- Retrofit to an ATM missing it: `INSTALL_MODULE` fleet task, or a full standard-set agent update.

## Gotchas
- **Legacy `command-processor` explicitly ignores `PACKET_CAPTURE`:** when its own unfiltered poll sees a `PACKET_CAPTURE` task, it reports it back to `PENDING` ("Released to packet-capture module") and sleeps 35s — it never executes the capture itself. If tasks never leave PENDING, check that the `packet-capture` module (not just `command-processor`) is actually running, not that command-processor is "stuck."
- Requesting `duration` > 300 does **not** error — it silently clamps to 300 with no warning back to Fleet.
- Windows without `tshark` installed silently degrades to `.etl` capture with **no BPF filter applied** — a requested `filter` is quietly ignored, not rejected.
- No `PlatformService`/`SystemCommands` usage here — OS branching is done locally via `os.name` + raw `ProcessBuilder`, unlike most other modules.
- This module has zero config-property surface of its own; don't go looking for `packet-capture.*` in `hiveops.properties` — there isn't any.

## Do NOT
- Do NOT treat this as a continuous/passive network monitor — it only runs when a `PACKET_CAPTURE` fleet task is queued.
- Do NOT expect journal/incident events (`IAT_*` or any `EventType`) from this module — it reports fleet task status only.
- Do NOT assume a BPF `filter` works on Windows unless `tshark` is confirmed installed — `pktmon`/`netsh` ignore it silently.
- Do NOT invent a `packet-capture.*` properties namespace — none exists; config comes from `agent.endpoint`/`incident.endpoint`/`agent.auth.token`/`modules.disabled` only.
- Do NOT expect the captured file to persist on the ATM after task completion — it's deleted immediately after upload, success or failure.
- Do NOT add this module to the `srv` (server-monitor) build set without checking with the team — it's ATM-set only today.
