You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
MSRV raised to Rust 1.88 (#338): rust-version in Cargo.toml is now 1.88.0. The idna_adapter dev-dependency pin is removed as it is no longer needed.
Announcement::next_hop is now the verbatim RIS Live string (#339) (String, was IpAddr): the field can carry a comma-joined RFC 2545 global + link-local pair (see Fixed below), so like prefixes it now keeps the wire value — parse it with NextHopAddress's new FromStr. Related edges: NextHopAddress's Display renders a pair comma-joined (round-tripping with FromStr), and BgpModelsError gains a NextHopParsingError variant.
BgpModelsError and ParserRisliveError are now #[non_exhaustive] (#340): both enums gain a variant in this cycle (NextHopParsingError, UnparsedMessageBody), and future additions will no longer break exhaustive matches downstream.
parse_ris_live_message now errors on a body it could not deserialize (#340): a frame that declares a message type this crate decodes but whose body fails to parse returns ParserRisliveError::UnparsedMessageBody with the underlying reason, where it previously returned Ok(vec![]). The flattened RisMessage::msgOption hid such failures, which is how the comma-joined next-hop bug (see Fixed below) dropped a frame's routes without a trace. Frames whose message type this crate does not decode still return no elems.
Dependencies
Updated oneio dependency from 0.25 to 0.26 (#338): clears the suppaftp advisory (RUSTSEC-2026-0271) that cargo audit reported via oneio 0.25's lockfile entry.
Layered text output format (#333) (render::text::format_record, --format text): one human-readable, indented block per MRT record — session context (TIME/TYPE/FROM/TO), UPDATE: sections with withdrawn/announced prefixes (including those carried in MP_REACH/MP_UNREACH) and every path attribute, OPEN: capabilities, session states, RIB entries, the peer table, and full legacy type-5 records. RFC 7606 validation findings render under WARNINGS: when present. The format is designed around this crate's own models and Display vocabulary — inspired by bgpdump's human-readable output, not byte-compatible with it. Rendering is a pure function of the record. In the CLI, --format text always uses record-level output (implies --level records); the other formats follow --level and default to elems.
--hex flag (#334): include each record's original wire bytes as hex in record-level output — a HEX: line at the end of --format text blocks, a hex field in --format json/json-pretty records. Designed as the pipe from filtered CLI output into byte-level tools (e.g. wirescope's hex paste input): bgpkit-parser -p 8.8.8.0/24 --format text --hex updates.mrt.gz yields blocks whose HEX: line can be pasted straight into a dissector. Bytes come from a new library iterator, BgpkitParser::into_filtered_raw_record_iter() — raw MRT records with the same record-level filter semantics as into_record_iter, yielding the untouched original bytes (no re-encoding, so attribute-ordering quirks such as BGP-LS hash-map iteration can never alter the output). The flag implies --level records, requires text/json/json-pretty formats, is mutually exclusive with --recover, and is ignored by count-only runs (-e/-r), which keep the normal counting pipelines and their per-elem filter semantics.
Record-level filter semantics are now explicit (#334): records that produce no elems (KEEPALIVE, OPEN, NOTIFICATION, state changes) never match elem-oriented filters and are dropped from record iteration while filters are active — a debug! line notes each drop.
NextHopAddress text form and scope-aware accessors (#339): FromStr parses a single address or a comma-joined RFC 2545 pair (stored positionally as Ipv6LinkLocal); global_addr() resolves a pair by scope rather than position, and link_local_addr() returns the link-local half, if any.
Fixed
RIS Live link-local next hops no longer drop UPDATEs (#339): an RFC 2545 global + link-local pair arrives as one comma-joined string ("next_hop": "2001:db8::1,fe80::1"), which failed IpAddr deserialisation; because RisMessage::msg is a flattened Option, the error surfaced as msg: None and the frame's announcements and withdrawals were silently discarded — ~20% of UPDATE frames (15,706 of 77,075 in a 20-second full-feed capture on 2026-09-10). next_hop is now kept verbatim; parse_ris_live_message resolves pairs by scope and returns ElemIncorrectIp for unparseable values instead of silently returning no elems. Regression fixtures with captured frames live in tests/fixtures/rislive/; tests/rislive_frames.rs also cross-checks the JSON and raw-bytes parsers against each other.
Two-address next hops resolve by scope in elem conversion (#339): the MRT/raw path took the first address of an Ipv6LinkLocal/VpnIpv6LinkLocal next hop positionally, so a pair with the link-local address first yielded fe80::. The MRT/raw path, the RIS Live JSON path, and Nlri::next_hop_addr() now share NextHopAddress::global_addr().
BGP-LS next hops resolve RFC 2545 pairs by scope (#340): parse_link_state_nlri took the first address of an Ipv6LinkLocal/VpnIpv6LinkLocal next hop positionally, so a reversed pair put the link-local address in the BGP-LS NLRI; it now uses NextHopAddress::global_addr(), matching the other elem conversion paths.
RIS Live peer-state message type (#338): the live stream sends peer-state messages with "type": "STATE", not "type": "RIS_PEER_STATE" as documented in the RIPE RIS Live documentation and schema. RisMessageEnum::RIS_PEER_STATE now deserializes from both STATE and RIS_PEER_STATE and serializes as STATE, matching the live stream. To be re-validated against RIPE's documentation and schema on/after January 2027.
Contributors
@ties — RIS Live peer-state message type (#338), comma-joined IPv6 next hops and scope-resolved next-hop conversion (#339)