Skip to main content

rustbgpd_wire/
lib.rs

1//! rustbgpd-wire — BGP message codec
2//!
3//! Pure codec library for BGP message encoding and decoding.
4//! Zero internal dependencies. This crate is independently publishable.
5//!
6//! # Message Types
7//!
8//! - [`OpenMessage`] — BGP OPEN with capability negotiation
9//! - [`NotificationMessage`] — BGP NOTIFICATION with error codes
10//! - [`UpdateMessage`] — BGP UPDATE (wire-level framing, raw bytes in M0)
11//! - `Keepalive` — represented as [`Message::Keepalive`] unit variant
12//!
13//! # Entry Points
14//!
15//! - [`decode_message`] — decode a complete BGP message from bytes
16//! - [`encode_message`] — encode a BGP message to bytes
17//! - [`peek_message_length`] — check if a
18//!   complete message is available (for transport framing)
19//!
20//! # Invariants
21//!
22//! - Maximum message size: 4096 bytes (RFC 4271 §4.1)
23//! - No panics on malformed input — all paths return `Result`
24//! - No `unsafe` code
25
26#![deny(unsafe_code)]
27#![deny(clippy::all)]
28#![warn(clippy::pedantic)]
29
30/// Path attribute types and codec (`ORIGIN`, `AS_PATH`, `NEXT_HOP`, etc.).
31pub mod attribute;
32/// BGP capability negotiation types and codec (RFC 5492).
33pub mod capability;
34/// Wire-format constants: markers, lengths, type codes.
35pub mod constants;
36/// Decode and encode error types.
37pub mod error;
38/// FlowSpec NLRI types and codec (RFC 8955 / RFC 8956).
39pub mod flowspec;
40/// BGP message header codec (RFC 4271 §4.1).
41pub mod header;
42/// KEEPALIVE message encoding and validation.
43pub mod keepalive;
44/// Top-level BGP message enum and codec dispatch.
45pub mod message;
46/// NLRI prefix types and codec (IPv4, IPv6, Add-Path).
47pub mod nlri;
48/// NOTIFICATION error codes, subcodes, and shutdown communication.
49pub mod notification;
50/// NOTIFICATION message struct and codec.
51pub mod notification_msg;
52/// OPEN message struct and codec.
53pub mod open;
54/// ROUTE-REFRESH message struct and codec (RFC 2918 / RFC 7313).
55pub mod route_refresh;
56/// UPDATE message struct, codec, and builder.
57pub mod update;
58/// UPDATE attribute semantic validation (RFC 4271 §6.3).
59pub mod validate;
60
61// Re-export primary public API
62pub use capability::{
63    AddPathFamily, AddPathMode, Afi, Capability, ExtendedNextHopFamily, GracefulRestartFamily,
64    LlgrFamily, Safi,
65};
66pub use constants::{EXTENDED_MAX_MESSAGE_LEN, MAX_MESSAGE_LEN};
67pub use error::{DecodeError, EncodeError};
68pub use header::{BgpHeader, MessageType, peek_message_length};
69pub use message::{Message, decode_message, encode_message, encode_message_with_limit};
70pub use notification::NotificationCode;
71pub use notification_msg::NotificationMessage;
72pub use open::OpenMessage;
73pub use route_refresh::{RouteRefreshMessage, RouteRefreshSubtype};
74pub use update::{Ipv4UnicastMode, UpdateMessage};
75
76// ── Routing-domain result enums ──────────────────────────────────────
77//
78// `RpkiValidation` and `AspaValidation` are routing-domain concepts, not
79// wire-format types. They live here because the wire crate is the current
80// lowest common dependency shared by rib, policy, and transport — avoiding
81// a rib → rpki dependency edge. If more shared non-wire types accumulate,
82// extract them into a dedicated domain-types crate.
83
84/// RPKI origin validation state per RFC 6811.
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
86pub enum RpkiValidation {
87    /// A VRP covers the prefix and the origin AS matches.
88    Valid,
89    /// A VRP covers the prefix but the origin AS does not match.
90    Invalid,
91    /// No VRP covers the prefix.
92    #[default]
93    NotFound,
94}
95
96impl std::fmt::Display for RpkiValidation {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        match self {
99            Self::Valid => write!(f, "valid"),
100            Self::Invalid => write!(f, "invalid"),
101            Self::NotFound => write!(f, "not_found"),
102        }
103    }
104}
105
106impl std::str::FromStr for RpkiValidation {
107    type Err = String;
108
109    fn from_str(s: &str) -> Result<Self, Self::Err> {
110        match s {
111            "valid" => Ok(Self::Valid),
112            "invalid" => Ok(Self::Invalid),
113            "not_found" => Ok(Self::NotFound),
114            other => Err(format!(
115                "unknown RPKI validation state {other:?}, expected \"valid\", \"invalid\", or \"not_found\""
116            )),
117        }
118    }
119}
120
121/// ASPA path verification state per draft-ietf-sidrops-aspa-verification.
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
123pub enum AspaValidation {
124    /// All hops in the `AS_PATH` have authorized provider relationships.
125    Valid,
126    /// At least one hop has a proven unauthorized provider relationship.
127    Invalid,
128    /// Verification could not complete due to missing ASPA records.
129    #[default]
130    Unknown,
131}
132
133impl std::fmt::Display for AspaValidation {
134    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135        match self {
136            Self::Valid => write!(f, "valid"),
137            Self::Invalid => write!(f, "invalid"),
138            Self::Unknown => write!(f, "unknown"),
139        }
140    }
141}
142
143impl std::str::FromStr for AspaValidation {
144    type Err = String;
145
146    fn from_str(s: &str) -> Result<Self, Self::Err> {
147        match s {
148            "valid" => Ok(Self::Valid),
149            "invalid" => Ok(Self::Invalid),
150            "unknown" => Ok(Self::Unknown),
151            other => Err(format!(
152                "unknown ASPA validation state {other:?}, expected \"valid\", \"invalid\", or \"unknown\""
153            )),
154        }
155    }
156}
157
158// Re-export attribute types
159pub use attribute::{
160    AsPath, AsPathSegment, ExtendedCommunity, LargeCommunity, MpReachNlri, MpUnreachNlri, Origin,
161    PathAttribute, RawAttribute, is_private_asn,
162};
163pub use nlri::{Ipv4NlriEntry, Ipv4Prefix, Ipv6Prefix, NlriEntry, Prefix};
164pub use update::ParsedUpdate;
165pub use validate::{UpdateError, is_valid_ipv6_nexthop};
166
167// Re-export FlowSpec types
168pub use flowspec::{
169    BitmaskMatch, FlowSpecAction, FlowSpecComponent, FlowSpecPrefix, FlowSpecRule,
170    Ipv6PrefixOffset, NumericMatch,
171};
172
173// Well-known communities (RFC 1997 + RFC 9494)
174/// `LLGR_STALE` community (RFC 9494 §4.6): marks a route as long-lived stale.
175pub const COMMUNITY_LLGR_STALE: u32 = 0xFFFF_0006;
176/// `NO_LLGR` community (RFC 9494 §4.7): this route must not enter LLGR stale phase.
177pub const COMMUNITY_NO_LLGR: u32 = 0xFFFF_0007;
178
179// Re-export RPKI types
180// (RpkiValidation is defined above in this file)