The work of the speaker-cleanup branch as one commit; the branch keeps the step-by-step history. Sessions - The state machine is a pure function from events to actions, driven by one task per connection. Idle, Connect and Active belong to a dialer that keeps configured peers up with backoff. - Capabilities are negotiated: address families, four-octet AS numbers with AS_TRANS and AS4_PATH, route refresh, ADD-PATH per family and direction. - Collision detection per RFC 4271 section 6.8, by address and identifier. - Connections are taken only from configured peers, a few per address. - A panic in a session is contained and answered with a Cease; a core task that stops shuts the server down with a Cease to every peer. - Writes that make no progress are given up (RFC 9687). Codec - Malformed UPDATEs are handled as RFC 7606 says: treat-as-withdraw, attribute discard, or session reset, with the NOTIFICATION to send. - Address families are open types; any can be named and ignored. - Prefixes are fixed-size values, normalised, with path identifiers. - Lengths are filled in after writing; one definition of each type code. - Property tests and fuzz targets for every decoder. Routing table - Adj-RIBs-In and Loc-RIB in one sharded table that sessions write to directly. Routes are sixteen bytes; attribute sets are interned in wire form. Best-path selection per RFC 4271 section 9.1.2.2 with deterministic MED. - A journal per shard lets followers read changes at their own pace; one that falls behind is resynchronised. - On a RIPE RIS dump of 148 peers and 39.3M routes: loaded in 2.0 s on 12 cores, about 52 bytes a route. Announcing - Originated routes come from the configuration. Each session has its own exporter with an Adj-RIB-Out, so a slow peer delays only itself. - Routes to a peer in our own AS have an empty path and a LOCAL_PREF. Operations - HTTP status page, JSON API, event stream and Prometheus metrics. - Benchmarks on synthetic and real tables. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
48 lines
1.8 KiB
Markdown
48 lines
1.8 KiB
Markdown
# Fuzz targets
|
|
|
|
Coverage-guided fuzzing of everything that reads input we do not control.
|
|
The property tests (`cargo test`, e.g. `crates/packet/tests/properties.rs`)
|
|
check the same things on generated input and run on every build; these
|
|
targets go further by letting libFuzzer follow code coverage for as long as
|
|
you leave them running.
|
|
|
|
| Target | Input |
|
|
|----------------|------------------------------------------------------------------|
|
|
| `message` | Raw bytes as they come off a TCP connection |
|
|
| `message_body` | A message body behind a correct header (reaches the body parsers) |
|
|
| `prefix_text` | A prefix as text |
|
|
| `config` | The configuration file |
|
|
|
|
For the two message targets a finding is either a panic, or a message the
|
|
decoder accepted that cannot be written and read back as itself.
|
|
|
|
## Running
|
|
|
|
libFuzzer needs a nightly toolchain and `cargo-fuzz`:
|
|
|
|
```bash
|
|
rustup toolchain install nightly
|
|
cargo install cargo-fuzz
|
|
```
|
|
|
|
Then, from this directory:
|
|
|
|
```bash
|
|
cargo +nightly fuzz run message_body corpus/message_body seeds/message_body -- -max_total_time=300
|
|
```
|
|
|
|
The first directory is the working corpus, which the fuzzer adds to and
|
|
which is not checked in. `seeds/` holds a few valid inputs to start from.
|
|
Leave out `-max_total_time` to run until interrupted.
|
|
|
|
## When it finds something
|
|
|
|
The input is saved under `artifacts/<target>/`. Reproduce it with
|
|
|
|
```bash
|
|
cargo +nightly fuzz run message_body artifacts/message_body/crash-...
|
|
```
|
|
|
|
Fix the bug, and add a unit test with the input next to the code it broke,
|
|
so that `cargo test` keeps it fixed without anyone having to run the fuzzer.
|