bgpkit_parser/parser/bgp/attributes/
mod.rs1mod attr_01_origin;
2mod attr_02_17_as_path;
3mod attr_03_next_hop;
4mod attr_04_med;
5mod attr_05_local_pref;
6mod attr_07_18_aggregator;
7mod attr_08_communities;
8mod attr_09_originator;
9mod attr_10_13_cluster;
10mod attr_14_15_nlri;
11mod attr_16_25_extended_communities;
12mod attr_32_large_communities;
13mod attr_35_otc;
14
15use bytes::{Buf, BufMut, Bytes, BytesMut};
16use log::{debug, warn};
17use std::net::IpAddr;
18
19use crate::models::*;
20
21use crate::error::ParserError;
22use crate::parser::bgp::attributes::attr_01_origin::{encode_origin, parse_origin};
23use crate::parser::bgp::attributes::attr_02_17_as_path::{encode_as_path, parse_as_path};
24use crate::parser::bgp::attributes::attr_03_next_hop::{encode_next_hop, parse_next_hop};
25use crate::parser::bgp::attributes::attr_04_med::{encode_med, parse_med};
26use crate::parser::bgp::attributes::attr_05_local_pref::{encode_local_pref, parse_local_pref};
27use crate::parser::bgp::attributes::attr_07_18_aggregator::{encode_aggregator, parse_aggregator};
28use crate::parser::bgp::attributes::attr_08_communities::{
29 encode_regular_communities, parse_regular_communities,
30};
31use crate::parser::bgp::attributes::attr_09_originator::{
32 encode_originator_id, parse_originator_id,
33};
34use crate::parser::bgp::attributes::attr_10_13_cluster::{encode_clusters, parse_clusters};
35use crate::parser::bgp::attributes::attr_14_15_nlri::{encode_nlri, parse_nlri};
36use crate::parser::bgp::attributes::attr_16_25_extended_communities::{
37 encode_extended_communities, encode_ipv6_extended_communities, parse_extended_community,
38 parse_ipv6_extended_community,
39};
40use crate::parser::bgp::attributes::attr_32_large_communities::{
41 encode_large_communities, parse_large_communities,
42};
43use crate::parser::bgp::attributes::attr_35_otc::{
44 encode_only_to_customer, parse_only_to_customer,
45};
46use crate::parser::ReadUtils;
47
48pub fn parse_attributes(
53 mut data: Bytes,
54 asn_len: &AsnLength,
55 add_path: bool,
56 afi: Option<Afi>,
57 safi: Option<Safi>,
58 prefixes: Option<&[NetworkPrefix]>,
59) -> Result<Attributes, ParserError> {
60 let mut attributes: Vec<Attribute> = Vec::with_capacity(20);
61
62 while data.remaining() >= 3 {
63 let flag = AttrFlags::from_bits_retain(data.get_u8());
68 let attr_type = data.get_u8();
69 let attr_length = match flag.contains(AttrFlags::EXTENDED) {
70 false => data.get_u8() as usize,
71 true => data.get_u16() as usize,
72 };
73
74 let mut partial = false;
75 if flag.contains(AttrFlags::PARTIAL) {
76 partial = true;
87 }
88
89 debug!(
90 "reading attribute: type -- {:?}, length -- {}",
91 &attr_type, attr_length
92 );
93 let attr_type = match AttrType::from(attr_type) {
94 attr_type @ AttrType::Unknown(unknown_type) => {
95 let bytes = data.read_n_bytes(attr_length)?;
97 let attr_value = match get_deprecated_attr_type(unknown_type) {
98 Some(t) => {
99 debug!("deprecated attribute type: {} - {}", unknown_type, t);
100 AttributeValue::Deprecated(AttrRaw { attr_type, bytes })
101 }
102 None => {
103 debug!("unknown attribute type: {}", unknown_type);
104 AttributeValue::Unknown(AttrRaw { attr_type, bytes })
105 }
106 };
107
108 assert_eq!(attr_type, attr_value.attr_type());
109 attributes.push(Attribute {
110 value: attr_value,
111 flag,
112 });
113 continue;
114 }
115 t => t,
116 };
117
118 let bytes_left = data.remaining();
119
120 if data.remaining() < attr_length {
121 warn!(
122 "not enough bytes: input bytes left - {}, want to read - {}; skipping",
123 bytes_left, attr_length
124 );
125 break;
127 }
128
129 data.has_n_remaining(attr_length)?;
131 let mut attr_data = data.split_to(attr_length);
132
133 let attr = match attr_type {
134 AttrType::ORIGIN => parse_origin(attr_data),
135 AttrType::AS_PATH => {
136 parse_as_path(attr_data, asn_len).map(|path| AttributeValue::AsPath {
137 path,
138 is_as4: false,
139 })
140 }
141 AttrType::NEXT_HOP => parse_next_hop(attr_data, &afi),
142 AttrType::MULTI_EXIT_DISCRIMINATOR => parse_med(attr_data),
143 AttrType::LOCAL_PREFERENCE => parse_local_pref(attr_data),
144 AttrType::ATOMIC_AGGREGATE => Ok(AttributeValue::AtomicAggregate),
145 AttrType::AGGREGATOR => {
146 parse_aggregator(attr_data, asn_len).map(|(asn, id)| AttributeValue::Aggregator {
147 asn,
148 id,
149 is_as4: false,
150 })
151 }
152 AttrType::ORIGINATOR_ID => parse_originator_id(attr_data),
153 AttrType::CLUSTER_LIST => parse_clusters(attr_data),
154 AttrType::MP_REACHABLE_NLRI => {
155 parse_nlri(attr_data, &afi, &safi, &prefixes, true, add_path)
156 }
157 AttrType::MP_UNREACHABLE_NLRI => {
158 parse_nlri(attr_data, &afi, &safi, &prefixes, false, add_path)
159 }
160 AttrType::AS4_PATH => parse_as_path(attr_data, &AsnLength::Bits32)
161 .map(|path| AttributeValue::AsPath { path, is_as4: true }),
162 AttrType::AS4_AGGREGATOR => {
163 parse_aggregator(attr_data, &AsnLength::Bits32).map(|(asn, id)| {
164 AttributeValue::Aggregator {
165 asn,
166 id,
167 is_as4: true,
168 }
169 })
170 }
171
172 AttrType::COMMUNITIES => parse_regular_communities(attr_data),
174 AttrType::LARGE_COMMUNITIES => parse_large_communities(attr_data),
175 AttrType::EXTENDED_COMMUNITIES => parse_extended_community(attr_data),
176 AttrType::IPV6_ADDRESS_SPECIFIC_EXTENDED_COMMUNITIES => {
177 parse_ipv6_extended_community(attr_data)
178 }
179 AttrType::DEVELOPMENT => {
180 let mut value = vec![];
181 for _i in 0..attr_length {
182 value.push(attr_data.get_u8());
183 }
184 Ok(AttributeValue::Development(value))
185 }
186 AttrType::ONLY_TO_CUSTOMER => parse_only_to_customer(attr_data),
187 _ => Err(ParserError::Unsupported(format!(
188 "unsupported attribute type: {:?}",
189 attr_type
190 ))),
191 };
192
193 match attr {
194 Ok(value) => {
195 assert_eq!(attr_type, value.attr_type());
196 attributes.push(Attribute { value, flag });
197 }
198 Err(e) => {
199 if partial {
200 debug!("PARTIAL: {}", e);
202 } else {
203 debug!("{}", e);
204 }
205 continue;
206 }
207 };
208 }
209
210 Ok(Attributes::from(attributes))
211}
212
213impl Attribute {
214 pub fn encode(&self, add_path: bool, asn_len: AsnLength) -> Bytes {
215 let mut bytes = BytesMut::new();
216
217 let flag = self.flag.bits();
218 let type_code = self.value.attr_type().into();
219
220 bytes.put_u8(flag);
221 bytes.put_u8(type_code);
222
223 let value_bytes = match &self.value {
224 AttributeValue::Origin(v) => encode_origin(v),
225 AttributeValue::AsPath { path, is_as4 } => {
226 let four_byte = match is_as4 {
227 true => AsnLength::Bits32,
228 false => match asn_len.is_four_byte() {
229 true => AsnLength::Bits32,
230 false => AsnLength::Bits16,
231 },
232 };
233 encode_as_path(path, four_byte)
234 }
235 AttributeValue::NextHop(v) => encode_next_hop(v),
236 AttributeValue::MultiExitDiscriminator(v) => encode_med(*v),
237 AttributeValue::LocalPreference(v) => encode_local_pref(*v),
238 AttributeValue::OnlyToCustomer(v) => encode_only_to_customer(v.into()),
239 AttributeValue::AtomicAggregate => Bytes::default(),
240 AttributeValue::Aggregator { asn, id, is_as4: _ } => {
241 encode_aggregator(asn, &IpAddr::from(*id))
242 }
243 AttributeValue::Communities(v) => encode_regular_communities(v),
244 AttributeValue::ExtendedCommunities(v) => encode_extended_communities(v),
245 AttributeValue::LargeCommunities(v) => encode_large_communities(v),
246 AttributeValue::Ipv6AddressSpecificExtendedCommunities(v) => {
247 encode_ipv6_extended_communities(v)
248 }
249 AttributeValue::OriginatorId(v) => encode_originator_id(&IpAddr::from(*v)),
250 AttributeValue::Clusters(v) => encode_clusters(v),
251 AttributeValue::MpReachNlri(v) => encode_nlri(v, true, add_path),
252 AttributeValue::MpUnreachNlri(v) => encode_nlri(v, false, add_path),
253 AttributeValue::Development(v) => Bytes::from(v.to_owned()),
254 AttributeValue::Deprecated(v) => Bytes::from(v.bytes.to_owned()),
255 AttributeValue::Unknown(v) => Bytes::from(v.bytes.to_owned()),
256 };
257
258 match self.is_extended() {
259 false => {
260 bytes.put_u8(value_bytes.len() as u8);
261 }
262 true => {
263 bytes.put_u16(value_bytes.len() as u16);
264 }
265 }
266 bytes.extend(value_bytes);
267 bytes.freeze()
268 }
269}
270
271impl Attributes {
272 pub fn encode(&self, add_path: bool, asn_len: AsnLength) -> Bytes {
273 let mut bytes = BytesMut::new();
274 for attr in &self.inner {
275 bytes.extend(attr.encode(add_path, asn_len));
276 }
277 bytes.freeze()
278 }
279}
280
281#[cfg(test)]
282mod tests {
283 use super::*;
284
285 #[test]
286 fn test_unknwon_attribute_type() {
287 let data = Bytes::from(vec![0x40, 0xFE, 0x00]);
288 let asn_len = AsnLength::Bits16;
289 let add_path = false;
290 let afi = None;
291 let safi = None;
292 let prefixes = None;
293 let attributes = parse_attributes(data, &asn_len, add_path, afi, safi, prefixes);
294 assert!(attributes.is_ok());
295 let attributes = attributes.unwrap();
296 assert_eq!(attributes.inner.len(), 1);
297 assert_eq!(
298 attributes.inner[0].value.attr_type(),
299 AttrType::Unknown(254)
300 );
301 }
302}