Implemented checker as described in internal-docs/notes4coding/checker_design.md
This commit is contained in:
188
docs/api.md
Normal file
188
docs/api.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# API Documentation
|
||||
|
||||
This document describes the input/output formats and the checker program API.
|
||||
|
||||
## CLI API
|
||||
|
||||
Command:
|
||||
|
||||
```bash
|
||||
checker --pcap <trace.pcapng> --meta <trace.meta.jsonl> --config <modbus.json> \
|
||||
--report <report.json> [--port 502] [--mode mvp|strict] [--fail-fast]
|
||||
```
|
||||
|
||||
Exit behavior:
|
||||
|
||||
- Returns a non-zero exit code only on process-level errors (I/O, parse failures).
|
||||
- Validation findings are written to the report file.
|
||||
|
||||
## JSONL Sidecar (`trace.meta.jsonl`)
|
||||
|
||||
Each line corresponds to one packet, in the same order as the PCAP.
|
||||
|
||||
```json
|
||||
{
|
||||
"trace_id": "c7f1...",
|
||||
"event_id": 42,
|
||||
"pcap_index": 42,
|
||||
"ts_ns": 1736451234567890123,
|
||||
"direction": "c2s",
|
||||
"flow": {
|
||||
"src_ip": "10.0.0.10",
|
||||
"src_port": 51012,
|
||||
"dst_ip": "10.0.0.20",
|
||||
"dst_port": 502
|
||||
},
|
||||
"expected": {
|
||||
"modbus": {
|
||||
"transaction_id": 513,
|
||||
"unit_id": 1,
|
||||
"function_code": 3
|
||||
},
|
||||
"fields": {
|
||||
"starting_address": 0,
|
||||
"quantity": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Example: `docs/examples/trace.meta.jsonl`
|
||||
|
||||
Fields:
|
||||
|
||||
- `trace_id` (string, optional): Trace identifier.
|
||||
- `event_id` (integer, optional): Event identifier from generator.
|
||||
- `pcap_index` (integer, optional): Packet index for reference.
|
||||
- `ts_ns` (integer, optional): Timestamp in nanoseconds.
|
||||
- `direction` (string, required): `c2s` (request) or `s2c` (response).
|
||||
- `flow` (object, required): Flow metadata used for request/response tracking.
|
||||
- `expected` (object, optional): Expected Modbus header and/or field values.
|
||||
|
||||
`expected.modbus`:
|
||||
|
||||
- `transaction_id` (u16, optional)
|
||||
- `unit_id` (u8, optional)
|
||||
- `function_code` (u8, optional)
|
||||
|
||||
`expected.fields`:
|
||||
|
||||
- Arbitrary JSON object whose keys match descriptor field names.
|
||||
- Values are compared against parsed output.
|
||||
|
||||
## Modbus Descriptor JSON (`modbus.json`)
|
||||
|
||||
Top-level:
|
||||
|
||||
```json
|
||||
{
|
||||
"functions": [
|
||||
{
|
||||
"function": 3,
|
||||
"name": "read_holding_registers",
|
||||
"request": [
|
||||
{"name":"starting_address","type":"u16"},
|
||||
{"name":"quantity","type":"u16"}
|
||||
],
|
||||
"response": [
|
||||
{"name":"byte_count","type":"u8"},
|
||||
{"name":"registers","type":"bytes","length_from":"byte_count"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Example: `docs/examples/modbus.json`
|
||||
|
||||
Function descriptor:
|
||||
|
||||
- `function` (u8, required): Function code.
|
||||
- `name` (string, optional): Human-readable function name.
|
||||
- `request` (array, optional): Field list for client-to-server PDUs.
|
||||
- `response` (array, optional): Field list for server-to-client PDUs.
|
||||
|
||||
Field descriptor:
|
||||
|
||||
- `name` (string, required): Field name used in output JSON.
|
||||
- `type` (string, required): `u8`, `u16`, `u32`, `i16`, `i32`, `bytes`.
|
||||
- `length` (integer, optional): Fixed length for `bytes`.
|
||||
- `length_from` (string, optional): Name of a previous numeric field.
|
||||
- `scale` (number, optional): Multiply numeric values by this scale.
|
||||
- `enum_map` (object, optional): Map numeric strings to JSON values.
|
||||
|
||||
Notes:
|
||||
|
||||
- `length_from` uses values parsed earlier in the same descriptor.
|
||||
- `bytes` output is an array of integers.
|
||||
|
||||
## Report JSON (`report.json`)
|
||||
|
||||
Structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"summary": {
|
||||
"total_packets": 1000,
|
||||
"total_findings": 8,
|
||||
"fatal": 1,
|
||||
"error": 4,
|
||||
"warn": 3,
|
||||
"info": 0
|
||||
},
|
||||
"findings": [
|
||||
{
|
||||
"pcap_index": 7,
|
||||
"event_id": 42,
|
||||
"severity": "error",
|
||||
"code": "mbap_protocol",
|
||||
"message": "Protocol id is 1, expected 0",
|
||||
"flow": {
|
||||
"src_ip": "10.0.0.10",
|
||||
"src_port": 51012,
|
||||
"dst_ip": "10.0.0.20",
|
||||
"dst_port": 502
|
||||
},
|
||||
"observed": {"payload_len": 42, "mbap_length": 10},
|
||||
"expected": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Example: `docs/examples/report.json`
|
||||
|
||||
Summary fields:
|
||||
|
||||
- `total_packets`: Total packets processed.
|
||||
- `total_findings`: Total findings emitted.
|
||||
- `fatal`, `error`, `warn`, `info`: Counts by severity.
|
||||
|
||||
Finding fields:
|
||||
|
||||
- `pcap_index` (u64): Index in PCAP stream.
|
||||
- `event_id` (u64, optional): Event identifier from metadata.
|
||||
- `severity` (string): `fatal`, `error`, `warn`, `info`.
|
||||
- `code` (string): Short machine-friendly code.
|
||||
- `message` (string): Human-readable description.
|
||||
- `flow` (object, optional): Source/destination addresses.
|
||||
- `observed` (JSON, optional): Observed values for comparison.
|
||||
- `expected` (JSON, optional): Expected values for comparison.
|
||||
|
||||
## Validation Modes
|
||||
|
||||
- `mvp`: Core checks only.
|
||||
- `strict`: Treat MBAP length mismatch as a stopping condition.
|
||||
|
||||
## Internal Module API (Rust)
|
||||
|
||||
Primary modules:
|
||||
|
||||
- `config`: Descriptor types and loader for JSON config.
|
||||
- `meta`: JSONL metadata structs.
|
||||
- `decode`: PCAP packet decode to TCP payload.
|
||||
- `mbap`: MBAP parsing utilities.
|
||||
- `modbus_desc`: Descriptor-based field parsing.
|
||||
- `state`: Outstanding request tracking.
|
||||
- `validate`: End-to-end validation pipeline.
|
||||
- `report`: Report data structures.
|
||||
Reference in New Issue
Block a user