bgpkit_parser/parser/iters/
raw.rs1use crate::parser::iters::{handle_record_parse_error, record_matches_filters};
15use crate::parser::mrt::mrt_record::raw_record_uses_zebra_compat;
16use crate::{chunk_mrt_record, BgpkitParser, Elementor, Filter, MrtRecord, RawMrtRecord};
17use std::io::Read;
18
19pub struct RawRecordIterator<R> {
20 parser: BgpkitParser<R>,
21 count: u64,
22}
23
24impl<R> RawRecordIterator<R> {
25 pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
26 RawRecordIterator { parser, count: 0 }
27 }
28}
29
30impl<R: Read> Iterator for RawRecordIterator<R> {
31 type Item = RawMrtRecord;
32
33 fn next(&mut self) -> Option<RawMrtRecord> {
34 if self.parser.text_dump_iter.is_some() {
36 return None;
37 }
38 self.count += 1;
39 loop {
40 match chunk_mrt_record(&mut self.parser.reader) {
41 Ok(raw_record) => return Some(raw_record),
42 Err(e) => {
43 if !handle_record_parse_error(&mut self.parser, e.error, e.bytes) {
44 return None;
45 }
46 }
47 }
48 }
49 }
50}
51
52pub struct FilteredRawRecordIterator<R> {
77 inner: RawRecordIterator<R>,
78 elementor: Elementor,
79 filters: Vec<Filter>,
80}
81
82impl<R> FilteredRawRecordIterator<R> {
83 pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
84 let filters = parser.filters.clone();
85 FilteredRawRecordIterator {
86 inner: RawRecordIterator::new(parser),
87 elementor: Elementor::new(),
88 filters,
89 }
90 }
91
92 fn warn_zebra_once(&mut self, raw: &RawMrtRecord) {
96 if raw_record_uses_zebra_compat(raw) {
97 self.inner.parser.warn_zebra_compat_once();
98 }
99 }
100}
101
102impl<R: Read> Iterator for FilteredRawRecordIterator<R> {
103 type Item = (RawMrtRecord, MrtRecord);
104
105 fn next(&mut self) -> Option<Self::Item> {
106 loop {
107 let raw = self.inner.next()?;
108 self.warn_zebra_once(&raw);
109 let record = match raw.clone().parse() {
113 Ok(record) => record,
114 Err(error) => {
115 if !handle_record_parse_error(
116 &mut self.inner.parser,
117 error,
118 Some(raw.raw_bytes().to_vec()),
119 ) {
120 return None;
121 }
122 continue;
123 }
124 };
125 if self.filters.is_empty()
126 || record_matches_filters(&record, &self.filters, &mut self.elementor)
127 {
128 return Some((raw, record));
129 }
130 }
131 }
132}
133
134#[cfg(test)]
135mod filtered_tests {
136 use super::*;
137 use crate::models::*;
138 use std::io::Cursor;
139
140 fn bgp4mp_record(timestamp: u32, bgp_message: BgpMessage) -> Vec<u8> {
141 let body_of = |update: &BgpUpdateMessage| update.encode(AsnLength::Bits32).unwrap();
142 let body = match &bgp_message {
143 BgpMessage::Update(update) => body_of(update),
144 BgpMessage::KeepAlive => Vec::new().into(),
145 _ => unreachable!("test builds updates and keepalives only"),
146 };
147 let mut bgp = vec![0xFF; 16];
148 bgp.extend_from_slice(&((19 + body.len()) as u16).to_be_bytes());
149 bgp.push(bgp_message.msg_type() as u8);
150 bgp.extend_from_slice(&body);
151
152 let mut mrt_body = Vec::new();
153 mrt_body.extend_from_slice(&64496u32.to_be_bytes());
154 mrt_body.extend_from_slice(&64497u32.to_be_bytes());
155 mrt_body.extend_from_slice(&0u16.to_be_bytes());
156 mrt_body.extend_from_slice(&1u16.to_be_bytes());
157 mrt_body.extend_from_slice(&[192, 0, 2, 1]);
158 mrt_body.extend_from_slice(&[192, 0, 2, 2]);
159 mrt_body.extend_from_slice(&bgp);
160
161 let mut wire = Vec::new();
162 wire.extend_from_slice(×tamp.to_be_bytes());
163 wire.extend_from_slice(&(EntryType::BGP4MP as u16).to_be_bytes());
164 wire.extend_from_slice(&(Bgp4MpType::MessageAs4 as u16).to_be_bytes());
165 wire.extend_from_slice(&(mrt_body.len() as u32).to_be_bytes());
166 wire.extend_from_slice(&mrt_body);
167 wire
168 }
169
170 fn keepalive(timestamp: u32) -> Vec<u8> {
171 bgp4mp_record(timestamp, BgpMessage::KeepAlive)
172 }
173
174 fn update(timestamp: u32) -> Vec<u8> {
175 let mut attributes = Attributes::default();
176 attributes.add_attr(AttributeValue::Origin(Origin::IGP).into());
177 attributes.add_attr(AttributeValue::AsPath(AsPath::from_sequence([65000])).into());
178 attributes.add_attr(AttributeValue::NextHop("192.0.2.254".parse().unwrap()).into());
179 bgp4mp_record(
180 timestamp,
181 BgpMessage::Update(BgpUpdateMessage {
182 withdrawn_prefixes: vec![],
183 attributes,
184 announced_prefixes: vec!["198.51.100.0/24".parse().unwrap()],
185 }),
186 )
187 }
188
189 #[test]
190 fn no_filters_yield_original_bytes_exactly() {
191 let mut input = keepalive(1);
192 let upd = update(2);
193 input.extend_from_slice(&upd);
194
195 let parser = BgpkitParser::from_reader(Cursor::new(input.clone()));
196 let yielded: Vec<Vec<u8>> = parser
197 .into_filtered_raw_record_iter()
198 .map(|(raw, _)| raw.raw_bytes().to_vec())
199 .collect();
200 assert_eq!(yielded.len(), 2);
201 assert_eq!(yielded[0], input[..input.len() - upd.len()].to_vec());
202 assert_eq!(yielded[1], upd);
203 }
204
205 #[test]
206 fn filters_drop_no_elem_records_and_preserve_bytes() {
207 let keep = keepalive(1);
208 let upd = update(2);
209 let mut input = keep.clone();
210 input.extend_from_slice(&upd);
211
212 let parser = BgpkitParser::from_reader(Cursor::new(input))
213 .add_filter("prefix", "198.51.100.0/24")
214 .unwrap();
215 let yielded: Vec<Vec<u8>> = parser
216 .into_filtered_raw_record_iter()
217 .map(|(raw, _)| raw.raw_bytes().to_vec())
218 .collect();
219
220 assert_eq!(yielded.len(), 1);
222 assert_eq!(yielded[0], upd);
223 }
224}