1 use crate::{defrag::*, *}; 2 use std::collections::HashMap; 3 use std::vec::Vec; 4 5 /// Pool of buffers to reconstruct multiple fragmented IP packets in 6 /// parallel (re-uses buffers to minimize allocations). 7 /// 8 /// It differentiates the packets based on their inner & outer vlan as well as 9 /// source and destination ip address and allows the user to add their own 10 /// custom "channel id" type to further differentiate different streams. 11 /// The custom channel id can be used to 12 /// 13 /// # This implementation is NOT safe against "Out of Memory" attacks 14 /// 15 /// If you use the [`IpDefragPool`] in an untrusted environment an attacker could 16 /// cause an "out of memory error" by opening up multiple parallel TP streams, 17 /// never ending them and filling them up with as much data as possible. 18 /// 19 /// Mitigations will hopefully be offered in future versions but if you have 20 /// take care right now you can still use [`IpDefragBuf`] directly and implement the 21 /// connection handling and mitigation yourself. 22 #[derive(Debug, Clone)] 23 pub struct IpDefragPool<Timestamp = (), CustomChannelId = ()> 24 where 25 Timestamp: Sized + core::fmt::Debug + Clone, 26 CustomChannelId: Sized + core::fmt::Debug + Clone + core::hash::Hash + Eq + PartialEq, 27 { 28 /// Currently reconstructing IP packets. 29 active: HashMap<IpFragId<CustomChannelId>, (IpDefragBuf, Timestamp)>, 30 31 /// Data buffers that have finished receiving data and can be re-used. 32 finished_data_bufs: Vec<Vec<u8>>, 33 34 /// Section buffers that have finished receiving data and can be re-used. 35 finished_section_bufs: Vec<Vec<IpFragRange>>, 36 } 37 38 impl<Timestamp, CustomChannelId> IpDefragPool<Timestamp, CustomChannelId> 39 where 40 Timestamp: Sized + core::fmt::Debug + Clone, 41 CustomChannelId: Sized + core::fmt::Debug + Clone + core::hash::Hash + Eq + PartialEq, 42 { new() -> IpDefragPool<Timestamp, CustomChannelId>43 pub fn new() -> IpDefragPool<Timestamp, CustomChannelId> { 44 IpDefragPool { 45 active: HashMap::new(), 46 finished_data_bufs: Vec::new(), 47 finished_section_bufs: Vec::new(), 48 } 49 } 50 51 /// Add data from a sliced packet. process_sliced_packet( &mut self, slice: &SlicedPacket, timestamp: Timestamp, channel_id: CustomChannelId, ) -> Result<Option<IpDefragPayloadVec>, IpDefragError>52 pub fn process_sliced_packet( 53 &mut self, 54 slice: &SlicedPacket, 55 timestamp: Timestamp, 56 channel_id: CustomChannelId, 57 ) -> Result<Option<IpDefragPayloadVec>, IpDefragError> { 58 // extract the fragment related data and skip non-fragmented packets 59 let (frag_id, offset, more_fragments, payload, is_ipv4) = match &slice.net { 60 Some(NetSlice::Ipv4(ipv4)) => { 61 let header = ipv4.header(); 62 if false == header.is_fragmenting_payload() { 63 // nothing to defragment here, skip packet 64 return Ok(None); 65 } 66 67 let (outer_vlan_id, inner_vlan_id) = match &slice.vlan { 68 Some(VlanSlice::SingleVlan(s)) => (Some(s.vlan_identifier()), None), 69 Some(VlanSlice::DoubleVlan(d)) => ( 70 Some(d.outer().vlan_identifier()), 71 Some(d.inner().vlan_identifier()), 72 ), 73 None => (None, None), 74 }; 75 76 ( 77 IpFragId { 78 outer_vlan_id, 79 inner_vlan_id, 80 ip: IpFragVersionSpecId::Ipv4 { 81 source: header.source(), 82 destination: header.destination(), 83 identification: header.identification(), 84 }, 85 payload_ip_number: ipv4.payload().ip_number, 86 channel_id, 87 }, 88 header.fragments_offset(), 89 header.more_fragments(), 90 ipv4.payload(), 91 true, 92 ) 93 } 94 Some(NetSlice::Ipv6(ipv6)) => { 95 // get fragmentation header 96 let frag = { 97 let mut f = None; 98 for ext in ipv6.extensions().clone().into_iter() { 99 use Ipv6ExtensionSlice::*; 100 if let Fragment(frag_it) = ext { 101 f = Some(frag_it); 102 break; 103 } 104 } 105 if let Some(f) = f { 106 if f.is_fragmenting_payload() { 107 f.to_header() 108 } else { 109 // nothing to defragment here, skip packet 110 return Ok(None); 111 } 112 } else { 113 // nothing to defragment here, skip packet 114 return Ok(None); 115 } 116 }; 117 118 let (outer_vlan_id, inner_vlan_id) = match &slice.vlan { 119 Some(VlanSlice::SingleVlan(s)) => (Some(s.vlan_identifier()), None), 120 Some(VlanSlice::DoubleVlan(d)) => ( 121 Some(d.outer().vlan_identifier()), 122 Some(d.inner().vlan_identifier()), 123 ), 124 None => (None, None), 125 }; 126 127 // calculate frag id 128 ( 129 IpFragId { 130 outer_vlan_id, 131 inner_vlan_id, 132 ip: IpFragVersionSpecId::Ipv6 { 133 source: ipv6.header().source(), 134 destination: ipv6.header().destination(), 135 identification: frag.identification, 136 }, 137 payload_ip_number: ipv6.payload().ip_number, 138 channel_id, 139 }, 140 frag.fragment_offset, 141 frag.more_fragments, 142 ipv6.payload(), 143 false, 144 ) 145 } 146 Some(NetSlice::Arp(_)) | None => { 147 // nothing to defragment here, skip packet 148 return Ok(None); 149 } 150 }; 151 152 // get the reconstruction buffer 153 use std::collections::hash_map::Entry; 154 match self.active.entry(frag_id) { 155 Entry::Occupied(mut entry) => { 156 let buf = entry.get_mut(); 157 buf.0.add(offset, more_fragments, payload.payload)?; 158 buf.1 = timestamp; 159 if buf.0.is_complete() { 160 let (defraged_payload, sections) = entry.remove().0.take_bufs(); 161 self.finished_section_bufs.push(sections); 162 Ok(Some(IpDefragPayloadVec { 163 ip_number: payload.ip_number, 164 len_source: if is_ipv4 { 165 LenSource::Ipv4HeaderTotalLen 166 } else { 167 LenSource::Ipv6HeaderPayloadLen 168 }, 169 payload: defraged_payload, 170 })) 171 } else { 172 Ok(None) 173 } 174 } 175 Entry::Vacant(entry) => { 176 let data_buf = if let Some(mut d) = self.finished_data_bufs.pop() { 177 d.clear(); 178 d 179 } else { 180 Vec::with_capacity(payload.payload.len() * 2) 181 }; 182 let sections = if let Some(mut s) = self.finished_section_bufs.pop() { 183 s.clear(); 184 s 185 } else { 186 Vec::with_capacity(4) 187 }; 188 189 let mut defrag_buf = IpDefragBuf::new(payload.ip_number, data_buf, sections); 190 match defrag_buf.add(offset, more_fragments, payload.payload) { 191 Ok(()) => { 192 // no need to check if the defrag is done as the 193 // packet can not be defragmented on initial add 194 // otherwise `is_fragmenting_payload` would have 195 // been false 196 entry.insert((defrag_buf, timestamp)); 197 Ok(None) 198 } 199 Err(err) => { 200 // return the buffers 201 let (data_buf, sections) = defrag_buf.take_bufs(); 202 self.finished_data_bufs.push(data_buf); 203 self.finished_section_bufs.push(sections); 204 Err(err) 205 } 206 } 207 } 208 } 209 } 210 211 /// Returns a buffer to the pool so it can be re-used. return_buf(&mut self, buf: IpDefragPayloadVec)212 pub fn return_buf(&mut self, buf: IpDefragPayloadVec) { 213 self.finished_data_bufs.push(buf.payload); 214 } 215 216 /// Retains only the elements specified by the predicate. retain<F>(&mut self, f: F) where F: Fn(&Timestamp) -> bool,217 pub fn retain<F>(&mut self, f: F) 218 where 219 F: Fn(&Timestamp) -> bool, 220 { 221 if self.active.iter().any(|(_, (_, t))| false == f(t)) { 222 self.active = self 223 .active 224 .drain() 225 .filter_map(|(k, v)| { 226 if f(&v.1) { 227 Some((k, v)) 228 } else { 229 let (data, sections) = v.0.take_bufs(); 230 self.finished_data_bufs.push(data); 231 self.finished_section_bufs.push(sections); 232 None 233 } 234 }) 235 .collect(); 236 } 237 } 238 } 239 240 impl<Timestamp, CustomChannelId> Default for IpDefragPool<Timestamp, CustomChannelId> 241 where 242 Timestamp: Sized + core::fmt::Debug + Clone, 243 CustomChannelId: Sized + core::fmt::Debug + Clone + core::hash::Hash + Eq + PartialEq, 244 { default() -> Self245 fn default() -> Self { 246 Self::new() 247 } 248 } 249 250 #[cfg(test)] 251 mod test { 252 use std::cmp::max; 253 254 use super::*; 255 256 #[test] new()257 fn new() { 258 { 259 let pool = IpDefragPool::<(), ()>::new(); 260 assert_eq!(pool.active.len(), 0); 261 assert_eq!(pool.finished_data_bufs.len(), 0); 262 assert_eq!(pool.finished_section_bufs.len(), 0); 263 } 264 { 265 let pool = IpDefragPool::<u32, (u32, u32)>::new(); 266 assert_eq!(pool.active.len(), 0); 267 assert_eq!(pool.finished_data_bufs.len(), 0); 268 assert_eq!(pool.finished_section_bufs.len(), 0); 269 } 270 } 271 272 #[test] default()273 fn default() { 274 { 275 let pool: IpDefragPool<(), ()> = Default::default(); 276 assert_eq!(pool.active.len(), 0); 277 assert_eq!(pool.finished_data_bufs.len(), 0); 278 assert_eq!(pool.finished_section_bufs.len(), 0); 279 } 280 { 281 let pool: IpDefragPool<u32, (u32, u32)> = Default::default(); 282 assert_eq!(pool.active.len(), 0); 283 assert_eq!(pool.finished_data_bufs.len(), 0); 284 assert_eq!(pool.finished_section_bufs.len(), 0); 285 } 286 } 287 build_packet<CustomChannelId: core::hash::Hash + Eq + PartialEq + Clone + Sized>( id: IpFragId<CustomChannelId>, offset: u16, more: bool, payload: &[u8], ) -> Vec<u8>288 fn build_packet<CustomChannelId: core::hash::Hash + Eq + PartialEq + Clone + Sized>( 289 id: IpFragId<CustomChannelId>, 290 offset: u16, 291 more: bool, 292 payload: &[u8], 293 ) -> Vec<u8> { 294 let mut buf = Vec::with_capacity( 295 Ethernet2Header::LEN 296 + SingleVlanHeader::LEN 297 + SingleVlanHeader::LEN 298 + max( 299 Ipv4Header::MIN_LEN, 300 Ipv6Header::LEN + Ipv6FragmentHeader::LEN, 301 ) 302 + payload.len(), 303 ); 304 305 let ip_ether_type = match id.ip { 306 IpFragVersionSpecId::Ipv4 { 307 source: _, 308 destination: _, 309 identification: _, 310 } => EtherType::IPV4, 311 IpFragVersionSpecId::Ipv6 { 312 source: _, 313 destination: _, 314 identification: _, 315 } => EtherType::IPV6, 316 }; 317 318 buf.extend_from_slice( 319 &Ethernet2Header { 320 source: [0; 6], 321 destination: [0; 6], 322 ether_type: if id.outer_vlan_id.is_some() || id.inner_vlan_id.is_some() { 323 EtherType::VLAN_TAGGED_FRAME 324 } else { 325 ip_ether_type 326 }, 327 } 328 .to_bytes(), 329 ); 330 331 if let Some(vlan_id) = id.outer_vlan_id { 332 buf.extend_from_slice( 333 &SingleVlanHeader { 334 pcp: VlanPcp::try_new(0).unwrap(), 335 drop_eligible_indicator: false, 336 vlan_id, 337 ether_type: if id.inner_vlan_id.is_some() { 338 EtherType::VLAN_TAGGED_FRAME 339 } else { 340 ip_ether_type 341 }, 342 } 343 .to_bytes(), 344 ); 345 } 346 347 if let Some(vlan_id) = id.inner_vlan_id { 348 buf.extend_from_slice( 349 &SingleVlanHeader { 350 pcp: VlanPcp::try_new(0).unwrap(), 351 drop_eligible_indicator: false, 352 vlan_id, 353 ether_type: ip_ether_type, 354 } 355 .to_bytes(), 356 ); 357 } 358 359 match id.ip { 360 IpFragVersionSpecId::Ipv4 { 361 source, 362 destination, 363 identification, 364 } => { 365 let mut header = Ipv4Header { 366 identification, 367 more_fragments: more, 368 fragment_offset: IpFragOffset::try_new(offset).unwrap(), 369 protocol: id.payload_ip_number, 370 source, 371 destination, 372 total_len: (Ipv4Header::MIN_LEN + payload.len()) as u16, 373 time_to_live: 2, 374 ..Default::default() 375 }; 376 header.header_checksum = header.calc_header_checksum(); 377 buf.extend_from_slice(&header.to_bytes()); 378 } 379 IpFragVersionSpecId::Ipv6 { 380 source, 381 destination, 382 identification, 383 } => { 384 buf.extend_from_slice( 385 &Ipv6Header { 386 traffic_class: 0, 387 flow_label: Default::default(), 388 payload_length: (payload.len() + Ipv6FragmentHeader::LEN + 8) as u16, 389 next_header: IpNumber::IPV6_FRAGMENTATION_HEADER, 390 hop_limit: 2, 391 source, 392 destination, 393 } 394 .to_bytes(), 395 ); 396 buf.extend_from_slice( 397 &Ipv6FragmentHeader { 398 next_header: IpNumber::IPV6_ROUTE_HEADER, 399 fragment_offset: IpFragOffset::try_new(offset).unwrap(), 400 more_fragments: more, 401 identification, 402 } 403 .to_bytes(), 404 ); 405 buf.extend_from_slice( 406 &{ 407 let mut h: Ipv6RawExtHeader = Default::default(); 408 h.next_header = id.payload_ip_number; 409 h 410 } 411 .to_bytes(), 412 ); 413 } 414 } 415 buf.extend_from_slice(payload); 416 buf 417 } 418 419 #[test] process_sliced_packet()420 fn process_sliced_packet() { 421 // non ip packet 422 { 423 let mut pool = IpDefragPool::<(), ()>::new(); 424 let pslice = SlicedPacket { 425 link: None, 426 vlan: None, 427 net: None, 428 transport: None, 429 }; 430 let v = pool.process_sliced_packet(&pslice, (), ()); 431 assert_eq!(Ok(None), v); 432 assert_eq!(pool.active.len(), 0); 433 assert_eq!(pool.finished_data_bufs.len(), 0); 434 assert_eq!(pool.finished_section_bufs.len(), 0); 435 } 436 437 // v4 non fragmented 438 { 439 let mut pool = IpDefragPool::<(), ()>::new(); 440 let pdata = build_packet( 441 IpFragId { 442 outer_vlan_id: None, 443 inner_vlan_id: None, 444 ip: IpFragVersionSpecId::Ipv4 { 445 source: [0; 4], 446 destination: [0; 4], 447 identification: 0, 448 }, 449 payload_ip_number: IpNumber::UDP, 450 channel_id: (), 451 }, 452 0, 453 false, 454 &UdpHeader { 455 source_port: 0, 456 destination_port: 0, 457 length: 0, 458 checksum: 0, 459 } 460 .to_bytes(), 461 ); 462 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 463 let v = pool.process_sliced_packet(&pslice, (), ()); 464 assert_eq!(Ok(None), v); 465 466 // check the effect had no effect 467 assert_eq!(pool.active.len(), 0); 468 assert_eq!(pool.finished_data_bufs.len(), 0); 469 assert_eq!(pool.finished_section_bufs.len(), 0); 470 } 471 472 // v6 non fragmented 473 { 474 let mut pool = IpDefragPool::<(), ()>::new(); 475 let pdata = build_packet( 476 IpFragId { 477 outer_vlan_id: None, 478 inner_vlan_id: None, 479 ip: IpFragVersionSpecId::Ipv6 { 480 source: [0; 16], 481 destination: [0; 16], 482 identification: 0, 483 }, 484 payload_ip_number: IpNumber::UDP, 485 channel_id: (), 486 }, 487 0, 488 false, 489 &UdpHeader { 490 source_port: 0, 491 destination_port: 0, 492 length: 0, 493 checksum: 0, 494 } 495 .to_bytes(), 496 ); 497 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 498 let v = pool.process_sliced_packet(&pslice, (), ()); 499 assert_eq!(Ok(None), v); 500 501 // check the effect had no effect 502 assert_eq!(pool.active.len(), 0); 503 assert_eq!(pool.finished_data_bufs.len(), 0); 504 assert_eq!(pool.finished_section_bufs.len(), 0); 505 } 506 507 // v4 & v6 basic test 508 { 509 let frag_ids = [ 510 // v4 (no vlan) 511 IpFragId { 512 outer_vlan_id: None, 513 inner_vlan_id: None, 514 ip: IpFragVersionSpecId::Ipv4 { 515 source: [1, 2, 3, 4], 516 destination: [5, 6, 7, 8], 517 identification: 9, 518 }, 519 payload_ip_number: IpNumber::UDP, 520 channel_id: (), 521 }, 522 // v4 (single vlan) 523 IpFragId { 524 outer_vlan_id: Some(VlanId::try_new(12).unwrap()), 525 inner_vlan_id: None, 526 ip: IpFragVersionSpecId::Ipv4 { 527 source: [1, 2, 3, 4], 528 destination: [5, 6, 7, 8], 529 identification: 9, 530 }, 531 payload_ip_number: IpNumber::UDP, 532 channel_id: (), 533 }, 534 // v4 (double vlan) 535 IpFragId { 536 outer_vlan_id: Some(VlanId::try_new(12).unwrap()), 537 inner_vlan_id: Some(VlanId::try_new(23).unwrap()), 538 ip: IpFragVersionSpecId::Ipv4 { 539 source: [1, 2, 3, 4], 540 destination: [5, 6, 7, 8], 541 identification: 9, 542 }, 543 payload_ip_number: IpNumber::UDP, 544 channel_id: (), 545 }, 546 // v6 (no vlan) 547 IpFragId { 548 outer_vlan_id: None, 549 inner_vlan_id: None, 550 ip: IpFragVersionSpecId::Ipv6 { 551 source: [0; 16], 552 destination: [0; 16], 553 identification: 0, 554 }, 555 payload_ip_number: IpNumber::UDP, 556 channel_id: (), 557 }, 558 // v6 (single vlan) 559 IpFragId { 560 outer_vlan_id: Some(VlanId::try_new(12).unwrap()), 561 inner_vlan_id: None, 562 ip: IpFragVersionSpecId::Ipv6 { 563 source: [0; 16], 564 destination: [0; 16], 565 identification: 0, 566 }, 567 payload_ip_number: IpNumber::UDP, 568 channel_id: (), 569 }, 570 // v6 (double vlan) 571 IpFragId { 572 outer_vlan_id: Some(VlanId::try_new(12).unwrap()), 573 inner_vlan_id: Some(VlanId::try_new(23).unwrap()), 574 ip: IpFragVersionSpecId::Ipv6 { 575 source: [0; 16], 576 destination: [0; 16], 577 identification: 0, 578 }, 579 payload_ip_number: IpNumber::UDP, 580 channel_id: (), 581 }, 582 ]; 583 584 let mut pool = IpDefragPool::<(), ()>::new(); 585 586 for frag_id in frag_ids { 587 { 588 let pdata = build_packet(frag_id.clone(), 0, true, &[1, 2, 3, 4, 5, 6, 7, 8]); 589 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 590 let v = pool.process_sliced_packet(&pslice, (), ()); 591 assert_eq!(Ok(None), v); 592 593 // check the frag id was correctly calculated 594 assert_eq!(1, pool.active.len()); 595 assert_eq!(pool.active.iter().next().unwrap().0, &frag_id); 596 } 597 598 { 599 let pdata = build_packet( 600 frag_id.clone(), 601 1, 602 true, 603 &[ 604 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 605 ], 606 ); 607 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 608 let v = pool.process_sliced_packet(&pslice, (), ()); 609 assert_eq!(Ok(None), v); 610 611 // check the frag id was correctly calculated 612 assert_eq!(1, pool.active.len()); 613 assert_eq!(pool.active.iter().next().unwrap().0, &frag_id); 614 } 615 616 { 617 let pdata = build_packet(frag_id.clone(), 3, false, &[25, 26]); 618 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 619 let v = pool 620 .process_sliced_packet(&pslice, (), ()) 621 .unwrap() 622 .unwrap(); 623 assert_eq!(v.ip_number, IpNumber::UDP); 624 assert_eq!( 625 v.len_source, 626 if matches!( 627 frag_id.ip, 628 IpFragVersionSpecId::Ipv4 { 629 source: _, 630 destination: _, 631 identification: _ 632 } 633 ) { 634 LenSource::Ipv4HeaderTotalLen 635 } else { 636 LenSource::Ipv6HeaderPayloadLen 637 } 638 ); 639 assert_eq!( 640 v.payload, 641 &[ 642 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 643 21, 22, 23, 24, 25, 26 644 ] 645 ); 646 647 // there should be nothing left 648 assert_eq!(pool.active.len(), 0); 649 assert_eq!(pool.finished_data_bufs.len(), 0); 650 assert_eq!(pool.finished_section_bufs.len(), 1); 651 652 // return buffer 653 pool.return_buf(v); 654 655 assert_eq!(pool.active.len(), 0); 656 assert_eq!(pool.finished_data_bufs.len(), 1); 657 assert_eq!(pool.finished_section_bufs.len(), 1); 658 } 659 } 660 } 661 662 // ipv6 no frag header 663 { 664 // build packet without ipv6 665 let pdata = { 666 let mut v = Vec::with_capacity(Ipv6Header::LEN + UdpHeader::LEN + 16); 667 v.extend_from_slice( 668 &Ipv6Header { 669 traffic_class: 0, 670 flow_label: Ipv6FlowLabel::try_new(0).unwrap(), 671 payload_length: UdpHeader::LEN_U16 + 16, 672 next_header: IpNumber::UDP, 673 hop_limit: 2, 674 source: [0; 16], 675 destination: [0; 16], 676 } 677 .to_bytes(), 678 ); 679 v.extend_from_slice( 680 &UdpHeader { 681 source_port: 1234, 682 destination_port: 2345, 683 length: UdpHeader::LEN_U16 + 10, 684 checksum: 0, 685 } 686 .to_bytes(), 687 ); 688 v.extend_from_slice(&[0; 16]); 689 v 690 }; 691 let slice = SlicedPacket::from_ip(&pdata).unwrap(); 692 693 let mut pool = IpDefragPool::<(), ()>::new(); 694 assert_eq!(Ok(None), pool.process_sliced_packet(&slice, (), ())); 695 assert_eq!(pool.active.len(), 0); 696 assert_eq!(pool.finished_data_bufs.len(), 0); 697 assert_eq!(pool.finished_section_bufs.len(), 0); 698 } 699 700 // error in initial packet 701 { 702 let frag_ids = [ 703 // v4 704 IpFragId { 705 outer_vlan_id: None, 706 inner_vlan_id: None, 707 ip: IpFragVersionSpecId::Ipv4 { 708 source: [1, 2, 3, 4], 709 destination: [5, 6, 7, 8], 710 identification: 9, 711 }, 712 payload_ip_number: IpNumber::UDP, 713 channel_id: (), 714 }, 715 // v6 716 IpFragId { 717 outer_vlan_id: None, 718 inner_vlan_id: None, 719 ip: IpFragVersionSpecId::Ipv6 { 720 source: [0; 16], 721 destination: [0; 16], 722 identification: 0, 723 }, 724 payload_ip_number: IpNumber::UDP, 725 channel_id: (), 726 }, 727 ]; 728 let mut pool = IpDefragPool::<(), ()>::new(); 729 730 for frag_id in frag_ids { 731 let pdata = build_packet(frag_id.clone(), 0, true, &[0; 7]); 732 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 733 let v = pool.process_sliced_packet(&pslice, (), ()); 734 assert_eq!( 735 Err(IpDefragError::UnalignedFragmentPayloadLen { 736 offset: IpFragOffset::try_new(0).unwrap(), 737 payload_len: 7 738 }), 739 v 740 ); 741 assert_eq!(0, pool.active.len()); 742 } 743 } 744 745 // error in followup packet 746 { 747 let frag_ids = [ 748 // v4 749 IpFragId { 750 outer_vlan_id: None, 751 inner_vlan_id: None, 752 ip: IpFragVersionSpecId::Ipv4 { 753 source: [1, 2, 3, 4], 754 destination: [5, 6, 7, 8], 755 identification: 9, 756 }, 757 payload_ip_number: IpNumber::UDP, 758 channel_id: (), 759 }, 760 // v6 761 IpFragId { 762 outer_vlan_id: None, 763 inner_vlan_id: None, 764 ip: IpFragVersionSpecId::Ipv6 { 765 source: [0; 16], 766 destination: [0; 16], 767 identification: 0, 768 }, 769 payload_ip_number: IpNumber::UDP, 770 channel_id: (), 771 }, 772 ]; 773 774 for frag_id in frag_ids { 775 let mut pool = IpDefragPool::<(), ()>::new(); 776 777 // initial packet 778 { 779 let pdata = build_packet(frag_id.clone(), 0, true, &[1, 2, 3, 4, 5, 6, 7, 8]); 780 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 781 let v = pool.process_sliced_packet(&pslice, (), ()); 782 assert_eq!(Ok(None), v); 783 784 // check the frag id was correctly calculated 785 assert_eq!(1, pool.active.len()); 786 assert_eq!(pool.active.iter().next().unwrap().0, &frag_id); 787 } 788 789 // follow up packet error 790 { 791 let pdata = build_packet( 792 frag_id.clone(), 793 1, 794 true, 795 &[9, 10, 11, 12, 13, 14, 15, 16, 17], 796 ); 797 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 798 let v = pool.process_sliced_packet(&pslice, (), ()); 799 assert_eq!( 800 Err(IpDefragError::UnalignedFragmentPayloadLen { 801 offset: IpFragOffset::try_new(1).unwrap(), 802 payload_len: 9 803 }), 804 v 805 ); 806 807 // check the frag id was correctly calculated 808 assert_eq!(1, pool.active.len()); 809 { 810 let p = pool.active.iter().next().unwrap(); 811 assert_eq!(p.0, &frag_id); 812 assert_eq!(p.1 .0.data(), &[1, 2, 3, 4, 5, 6, 7, 8]); 813 assert_eq!(p.1 .0.sections()[0].start, 0); 814 assert_eq!(p.1 .0.sections()[0].end, 8); 815 } 816 } 817 } 818 } 819 } 820 821 #[test] retain()822 fn retain() { 823 let frag_id_0 = IpFragId { 824 outer_vlan_id: None, 825 inner_vlan_id: None, 826 ip: IpFragVersionSpecId::Ipv4 { 827 source: [1, 2, 3, 4], 828 destination: [5, 6, 7, 8], 829 identification: 0, 830 }, 831 payload_ip_number: IpNumber::UDP, 832 channel_id: (), 833 }; 834 let frag_id_1 = IpFragId { 835 outer_vlan_id: None, 836 inner_vlan_id: None, 837 ip: IpFragVersionSpecId::Ipv4 { 838 source: [1, 2, 3, 4], 839 destination: [5, 6, 7, 8], 840 identification: 1, 841 }, 842 payload_ip_number: IpNumber::UDP, 843 channel_id: (), 844 }; 845 846 let mut pool = IpDefragPool::<u32, ()>::new(); 847 848 // packet timestamp 1 849 { 850 let pdata = build_packet(frag_id_0.clone(), 0, true, &[1, 2, 3, 4, 5, 6, 7, 8]); 851 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 852 let v = pool.process_sliced_packet(&pslice, 1, ()); 853 assert_eq!(Ok(None), v); 854 } 855 // packet timestamp 2 856 { 857 let pdata = build_packet(frag_id_1.clone(), 0, true, &[1, 2, 3, 4, 5, 6, 7, 8]); 858 let pslice = SlicedPacket::from_ethernet(&pdata).unwrap(); 859 let v = pool.process_sliced_packet(&pslice, 2, ()); 860 assert_eq!(Ok(None), v); 861 } 862 863 // check buffers are active 864 assert_eq!(pool.active.len(), 2); 865 assert_eq!(pool.finished_data_bufs.len(), 0); 866 assert_eq!(pool.finished_section_bufs.len(), 0); 867 868 // call retain without effect 869 pool.retain(|ts| *ts > 0); 870 assert_eq!(pool.active.len(), 2); 871 assert_eq!(pool.finished_data_bufs.len(), 0); 872 assert_eq!(pool.finished_section_bufs.len(), 0); 873 874 // call retain and delete timestamp 1 875 pool.retain(|ts| *ts > 1); 876 assert_eq!(pool.active.len(), 1); 877 assert_eq!(pool.finished_data_bufs.len(), 1); 878 assert_eq!(pool.finished_section_bufs.len(), 1); 879 assert_eq!(pool.active.iter().next().unwrap().0, &frag_id_1); 880 } 881 } 882