Property tests (run by `cargo test`): - crates/packet/tests/properties.rs: every kind of message, generated, must be written, be as long as wire_len says, and read back equal; and noise, noise behind a valid header, and valid messages with bytes damaged must never do more than return an error. Anything the decoder accepts must be showable and survive being written and read again. - IpPrefix: text round trip, noise as text, `contains` against a bitwise model. - The session's framing: a stream of messages yields the same messages however it is cut into reads. Fuzz targets (fuzz/, cargo-fuzz on nightly, a minute each in CI): raw messages, message bodies behind a valid header, prefix text, the configuration file. Bugs found, each with a named regression test: - A prefix longer than its address family (e.g. an IPv4 NLRI of length 99) was accepted, and showing it panicked. The session logs every route, so one UPDATE from a peer ended the session task. Such a prefix is now malformed, and showing a prefix cannot fail. - Bits past a prefix's length were kept, so the same prefix sent with stray bits was a different key in the RIB. Prefixes now have one form. - An opaque extended community was read as seven octets instead of eight, putting every community after it out of step. - AGGREGATOR could be neither read from nor written to a peer with two-octet AS numbers. - The Outbound Route Filter and Long-Lived Graceful Restart capabilities were written differently from how they are read. - A capability value or unknown attribute too long for its length field was written with the length wrapped around; it is now an error, or for the attribute the two-octet length. Also: ROUTE-REFRESH carries its AFI and SAFI instead of being modelled as an empty message, and one with a body of the wrong length is refused. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
39 lines
1.2 KiB
Plaintext
39 lines
1.2 KiB
Plaintext
# A worked example; the fields are documented in
|
|
# crates/server/proto/config.proto.
|
|
router_id: "10.0.0.1"
|
|
local_asn: 65000
|
|
|
|
# Where to accept BGP connections. Port 179 needs privileges; pick another
|
|
# port to run unprivileged against a peer that dials a custom port.
|
|
listen_endpoints { address: "127.0.0.1" port: 179 }
|
|
listen_endpoints { address: "::1" port: 179 }
|
|
|
|
# A peer we connect to (and accept connections from).
|
|
peers {
|
|
name: "r1"
|
|
endpoint { address: "127.0.0.1" port: 1791 }
|
|
remote_asn: 65001
|
|
hold_time_seconds: 30
|
|
# Offer only these families to the peer. Left out, all are offered.
|
|
address_families: IPV4_UNICAST
|
|
address_families: IPV6_UNICAST
|
|
}
|
|
connect_retry_seconds: 5
|
|
|
|
# Let a restarted peer replace a stale Established session immediately
|
|
# (RFC 4271 CollisionDetectEstablishedState). Default false.
|
|
collision_detect_established_state: false
|
|
|
|
# Routes this router originates, announced to every peer.
|
|
originate { prefix: "10.100.0.0/16" }
|
|
originate {
|
|
prefix: "2001:db8:100::/48"
|
|
med: 50
|
|
communities: "65000:100"
|
|
large_communities: "65000:1:2"
|
|
}
|
|
|
|
# Read-only status page, JSON API and metrics. It has no authentication:
|
|
# keep it on loopback or behind a reverse proxy.
|
|
http_endpoint { address: "127.0.0.1" port: 8080 }
|