bgpkit_parser/models/bgp/flowspec/
mod.rs1use crate::models::*;
2
3pub mod nlri;
4pub mod operators;
5
6#[cfg(test)]
7mod tests;
8
9pub use nlri::*;
10pub use operators::*;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct FlowSpecNlri {
16 pub components: Vec<FlowSpecComponent>,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub enum FlowSpecComponent {
23 DestinationPrefix(NetworkPrefix),
25 SourcePrefix(NetworkPrefix),
27 IpProtocol(Vec<NumericOperator>),
29 Port(Vec<NumericOperator>),
31 DestinationPort(Vec<NumericOperator>),
33 SourcePort(Vec<NumericOperator>),
35 IcmpType(Vec<NumericOperator>),
37 IcmpCode(Vec<NumericOperator>),
39 TcpFlags(Vec<BitmaskOperator>),
41 PacketLength(Vec<NumericOperator>),
43 Dscp(Vec<NumericOperator>),
45 Fragment(Vec<BitmaskOperator>),
47 FlowLabel(Vec<NumericOperator>),
49 DestinationIpv6Prefix { offset: u8, prefix: NetworkPrefix },
51 SourceIpv6Prefix { offset: u8, prefix: NetworkPrefix },
53}
54
55impl FlowSpecComponent {
56 pub const fn component_type(&self) -> u8 {
58 match self {
59 FlowSpecComponent::DestinationPrefix(_)
60 | FlowSpecComponent::DestinationIpv6Prefix { .. } => 1,
61 FlowSpecComponent::SourcePrefix(_) | FlowSpecComponent::SourceIpv6Prefix { .. } => 2,
62 FlowSpecComponent::IpProtocol(_) => 3,
63 FlowSpecComponent::Port(_) => 4,
64 FlowSpecComponent::DestinationPort(_) => 5,
65 FlowSpecComponent::SourcePort(_) => 6,
66 FlowSpecComponent::IcmpType(_) => 7,
67 FlowSpecComponent::IcmpCode(_) => 8,
68 FlowSpecComponent::TcpFlags(_) => 9,
69 FlowSpecComponent::PacketLength(_) => 10,
70 FlowSpecComponent::Dscp(_) => 11,
71 FlowSpecComponent::Fragment(_) => 12,
72 FlowSpecComponent::FlowLabel(_) => 13,
73 }
74 }
75
76 pub const fn uses_numeric_operators(&self) -> bool {
78 matches!(
79 self,
80 FlowSpecComponent::IpProtocol(_)
81 | FlowSpecComponent::Port(_)
82 | FlowSpecComponent::DestinationPort(_)
83 | FlowSpecComponent::SourcePort(_)
84 | FlowSpecComponent::IcmpType(_)
85 | FlowSpecComponent::IcmpCode(_)
86 | FlowSpecComponent::PacketLength(_)
87 | FlowSpecComponent::Dscp(_)
88 | FlowSpecComponent::FlowLabel(_)
89 )
90 }
91
92 pub const fn uses_bitmask_operators(&self) -> bool {
94 matches!(
95 self,
96 FlowSpecComponent::TcpFlags(_) | FlowSpecComponent::Fragment(_)
97 )
98 }
99}
100
101impl FlowSpecNlri {
102 pub fn new(components: Vec<FlowSpecComponent>) -> Self {
104 FlowSpecNlri { components }
105 }
106
107 pub fn components(&self) -> &[FlowSpecComponent] {
109 &self.components
110 }
111
112 pub fn is_ipv4(&self) -> bool {
114 self.components.iter().any(|c| {
115 matches!(c,
116 FlowSpecComponent::DestinationPrefix(prefix) |
117 FlowSpecComponent::SourcePrefix(prefix)
118 if matches!(prefix.prefix, ipnet::IpNet::V4(_))
119 )
120 })
121 }
122
123 pub fn is_ipv6(&self) -> bool {
125 self.components.iter().any(|c| {
126 matches!(c,
127 FlowSpecComponent::DestinationPrefix(prefix) |
128 FlowSpecComponent::SourcePrefix(prefix)
129 if matches!(prefix.prefix, ipnet::IpNet::V6(_))
130 )
131 }) || self.components.iter().any(|c| {
132 matches!(
133 c,
134 FlowSpecComponent::DestinationIpv6Prefix { .. }
135 | FlowSpecComponent::SourceIpv6Prefix { .. }
136 | FlowSpecComponent::FlowLabel(_)
137 )
138 })
139 }
140}
141
142#[derive(Debug, Clone, PartialEq, Eq)]
144#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
145pub enum FlowSpecError {
146 InvalidComponentOrder {
148 expected_greater_than: u8,
149 found: u8,
150 },
151 InvalidOperator(u8),
153 InvalidComponentType(u8),
155 InsufficientData,
157 InvalidPrefix,
159 InvalidValueLength(u8),
161}
162
163impl std::fmt::Display for FlowSpecError {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 match self {
166 FlowSpecError::InvalidComponentOrder {
167 expected_greater_than,
168 found,
169 } => {
170 write!(
171 f,
172 "Invalid component order: expected type > {}, but found {}",
173 expected_greater_than, found
174 )
175 }
176 FlowSpecError::InvalidOperator(op) => {
177 write!(f, "Invalid operator: 0x{:02X}", op)
178 }
179 FlowSpecError::InvalidComponentType(t) => {
180 write!(f, "Invalid component type: {}", t)
181 }
182 FlowSpecError::InsufficientData => {
183 write!(f, "Insufficient data for parsing")
184 }
185 FlowSpecError::InvalidPrefix => {
186 write!(f, "Invalid prefix encoding")
187 }
188 FlowSpecError::InvalidValueLength(len) => {
189 write!(f, "Invalid value length: {}", len)
190 }
191 }
192 }
193}
194
195impl std::error::Error for FlowSpecError {}