1pub mod extension_structure {
2 use crate::buffer::Buffer;
3 use crate::error::{Error, Result};
4 use crate::icmp_extension::extension_object::ExtensionObjectPacket;
5
6 pub struct ExtensionsPacket<'a> {
12 buf: Buffer<'a>,
13 }
14
15 impl<'a> ExtensionsPacket<'a> {
16 pub fn new(packet: &'a mut [u8]) -> Result<Self> {
17 if packet.len() >= Self::minimum_packet_size() {
18 Ok(Self {
19 buf: Buffer::Mutable(packet),
20 })
21 } else {
22 Err(Error::InsufficientPacketBuffer(
23 String::from("ExtensionsPacket"),
24 Self::minimum_packet_size(),
25 packet.len(),
26 ))
27 }
28 }
29
30 pub fn new_view(packet: &'a [u8]) -> Result<Self> {
31 if packet.len() >= Self::minimum_packet_size() {
32 Ok(Self {
33 buf: Buffer::Immutable(packet),
34 })
35 } else {
36 Err(Error::InsufficientPacketBuffer(
37 String::from("ExtensionsPacket"),
38 Self::minimum_packet_size(),
39 packet.len(),
40 ))
41 }
42 }
43
44 #[must_use]
45 pub const fn minimum_packet_size() -> usize {
46 4
47 }
48
49 #[must_use]
50 pub fn packet(&self) -> &[u8] {
51 self.buf.as_slice()
52 }
53
54 #[must_use]
55 pub fn header(&self) -> &[u8] {
56 &self.buf.as_slice()[..Self::minimum_packet_size()]
57 }
58
59 #[must_use]
61 pub const fn objects(&self) -> ExtensionObjectIter<'_> {
62 ExtensionObjectIter::new(&self.buf)
63 }
64 }
65
66 pub struct ExtensionObjectIter<'a> {
67 buf: &'a Buffer<'a>,
68 offset: usize,
69 }
70
71 impl<'a> ExtensionObjectIter<'a> {
72 #[must_use]
73 pub const fn new(buf: &'a Buffer<'_>) -> Self {
74 Self {
75 buf,
76 offset: ExtensionsPacket::minimum_packet_size(),
77 }
78 }
79 }
80
81 impl<'a> Iterator for ExtensionObjectIter<'a> {
82 type Item = &'a [u8];
83
84 fn next(&mut self) -> Option<Self::Item> {
85 let buf_slice = self.buf.as_slice();
86 if self.offset > buf_slice.len() {
87 None
88 } else {
89 let object_bytes = &buf_slice[self.offset..];
90 if let Ok(object) = ExtensionObjectPacket::new_view(object_bytes) {
91 let length = usize::from(object.get_length());
92 if length < ExtensionObjectPacket::minimum_packet_size()
95 || length > object_bytes.len()
96 {
97 return None;
98 }
99 self.offset += length;
100 Some(object_bytes)
101 } else {
102 None
103 }
104 }
105 }
106 }
107
108 #[cfg(test)]
109 mod tests {
110 use super::*;
111 use crate::icmp_extension::extension_header::ExtensionHeaderPacket;
112 use crate::icmp_extension::extension_object::{
113 ClassNum, ClassSubType, ExtensionObjectPacket,
114 };
115
116 #[test]
117 fn test_header() {
118 let buf = [
119 0x20, 0x00, 0x99, 0x3a, 0x00, 0x08, 0x01, 0x01, 0x04, 0xbb, 0x41, 0x01,
120 ];
121 let extensions = ExtensionsPacket::new_view(&buf).unwrap();
122 let header = ExtensionHeaderPacket::new_view(extensions.header()).unwrap();
123 assert_eq!(2, header.get_version());
124 assert_eq!(0x993A, header.get_checksum());
125 }
126
127 #[test]
128 fn test_object_iterator() {
129 let buf = [
130 0x20, 0x00, 0x99, 0x3a, 0x00, 0x08, 0x01, 0x01, 0x04, 0xbb, 0x41, 0x01,
131 ];
132 let extensions = ExtensionsPacket::new_view(&buf).unwrap();
133 let mut object_iter = extensions.objects();
134 let object_bytes = object_iter.next().unwrap();
135 let object = ExtensionObjectPacket::new_view(object_bytes).unwrap();
136 assert_eq!(8, object.get_length());
137 assert_eq!(
138 ClassNum::MultiProtocolLabelSwitchingLabelStack,
139 object.get_class_num()
140 );
141 assert_eq!(ClassSubType(1), object.get_class_subtype());
142 assert_eq!([0x04, 0xbb, 0x41, 0x01], object.payload());
143 assert!(object_iter.next().is_none());
144 }
145
146 #[test]
147 fn test_object_iterator_zero_length() {
148 let buf = [
149 0x20, 0x00, 0x99, 0x3a, 0x00, 0x00, 0x01, 0x01, 0x04, 0xbb, 0x41, 0x01,
150 ];
151 let extensions = ExtensionsPacket::new_view(&buf).unwrap();
152 let mut object_iter = extensions.objects();
153 assert!(object_iter.next().is_none());
154 }
155
156 #[test]
157 fn test_object_iterator_minimum_length() {
158 let buf = [
159 0x20, 0x00, 0x99, 0x3a, 0x00, 0x04, 0x01, 0x01, 0x04, 0xbb, 0x41, 0x01,
160 ];
161 let extensions = ExtensionsPacket::new_view(&buf).unwrap();
162 let mut object_iter = extensions.objects();
163 let object_bytes = object_iter.next().unwrap();
164 let object = ExtensionObjectPacket::new_view(object_bytes).unwrap();
165 assert_eq!(4, object.get_length());
166 assert_eq!(0, object.payload().len());
167 }
168
169 #[test]
170 fn test_object_iterator_length_to_short() {
171 let buf = [
172 0x20, 0x00, 0x99, 0x3a, 0x00, 0x03, 0x01, 0x01, 0x04, 0xbb, 0x41, 0x01,
173 ];
174 let extensions = ExtensionsPacket::new_view(&buf).unwrap();
175 let mut object_iter = extensions.objects();
176 assert!(object_iter.next().is_none());
177 }
178
179 #[test]
180 fn test_object_iterator_length_to_long() {
181 let buf = [
182 0x20, 0x00, 0x99, 0x3a, 0xa7, 0xdd, 0x01, 0x01, 0x04, 0xbb, 0x41, 0x01,
183 ];
184 let extensions = ExtensionsPacket::new_view(&buf).unwrap();
185 let mut object_iter = extensions.objects();
186 assert!(object_iter.next().is_none());
187 }
188 }
189}
190
191pub mod extension_header {
192 use crate::buffer::Buffer;
193 use crate::error::{Error, Result};
194 use std::fmt::{Debug, Formatter};
195
196 const VERSION_OFFSET: usize = 0;
197 const CHECKSUM_OFFSET: usize = 2;
198
199 pub struct ExtensionHeaderPacket<'a> {
205 buf: Buffer<'a>,
206 }
207
208 impl<'a> ExtensionHeaderPacket<'a> {
209 pub fn new(packet: &'a mut [u8]) -> Result<Self> {
210 if packet.len() >= Self::minimum_packet_size() {
211 Ok(Self {
212 buf: Buffer::Mutable(packet),
213 })
214 } else {
215 Err(Error::InsufficientPacketBuffer(
216 String::from("ExtensionHeaderPacket"),
217 Self::minimum_packet_size(),
218 packet.len(),
219 ))
220 }
221 }
222
223 pub fn new_view(packet: &'a [u8]) -> Result<Self> {
224 if packet.len() >= Self::minimum_packet_size() {
225 Ok(Self {
226 buf: Buffer::Immutable(packet),
227 })
228 } else {
229 Err(Error::InsufficientPacketBuffer(
230 String::from("ExtensionHeaderPacket"),
231 Self::minimum_packet_size(),
232 packet.len(),
233 ))
234 }
235 }
236
237 #[must_use]
238 pub const fn minimum_packet_size() -> usize {
239 4
240 }
241
242 #[must_use]
243 pub fn get_version(&self) -> u8 {
244 (self.buf.read(VERSION_OFFSET) & 0xf0) >> 4
245 }
246
247 #[must_use]
248 pub fn get_checksum(&self) -> u16 {
249 u16::from_be_bytes(self.buf.get_bytes(CHECKSUM_OFFSET))
250 }
251
252 pub fn set_version(&mut self, val: u8) {
253 *self.buf.write(VERSION_OFFSET) =
254 (self.buf.read(VERSION_OFFSET) & 0xf) | ((val & 0xf) << 4);
255 }
256
257 pub fn set_checksum(&mut self, val: u16) {
258 self.buf.set_bytes(CHECKSUM_OFFSET, val.to_be_bytes());
259 }
260
261 #[must_use]
262 pub fn packet(&self) -> &[u8] {
263 self.buf.as_slice()
264 }
265 }
266
267 impl Debug for ExtensionHeaderPacket<'_> {
268 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
269 f.debug_struct("ExtensionHeader")
270 .field("version", &self.get_version())
271 .field("checksum", &self.get_checksum())
272 .finish()
273 }
274 }
275
276 #[cfg(test)]
277 mod tests {
278 use super::*;
279
280 #[test]
281 fn test_version() {
282 let mut buf = [0_u8; ExtensionHeaderPacket::minimum_packet_size()];
283 let mut extension = ExtensionHeaderPacket::new(&mut buf).unwrap();
284 extension.set_version(0);
285 assert_eq!(0, extension.get_version());
286 assert_eq!([0x00], extension.packet()[0..1]);
287 extension.set_version(2);
288 assert_eq!(2, extension.get_version());
289 assert_eq!([0x20], extension.packet()[0..1]);
290 extension.set_version(15);
291 assert_eq!(15, extension.get_version());
292 assert_eq!([0xF0], extension.packet()[0..1]);
293 }
294
295 #[test]
296 fn test_checksum() {
297 let mut buf = [0_u8; ExtensionHeaderPacket::minimum_packet_size()];
298 let mut extension = ExtensionHeaderPacket::new(&mut buf).unwrap();
299 extension.set_checksum(0);
300 assert_eq!(0, extension.get_checksum());
301 assert_eq!([0x00, 0x00], extension.packet()[2..=3]);
302 extension.set_checksum(1999);
303 assert_eq!(1999, extension.get_checksum());
304 assert_eq!([0x07, 0xCF], extension.packet()[2..=3]);
305 extension.set_checksum(39226);
306 assert_eq!(39226, extension.get_checksum());
307 assert_eq!([0x99, 0x3A], extension.packet()[2..=3]);
308 extension.set_checksum(u16::MAX);
309 assert_eq!(u16::MAX, extension.get_checksum());
310 assert_eq!([0xFF, 0xFF], extension.packet()[2..=3]);
311 }
312
313 #[test]
314 fn test_extension_header_view() {
315 let buf = [
316 0x20, 0x00, 0x99, 0x3a, 0x00, 0x08, 0x01, 0x01, 0x04, 0xbb, 0x41, 0x01,
317 ];
318 let extension = ExtensionHeaderPacket::new_view(&buf).unwrap();
319 assert_eq!(2, extension.get_version());
320 assert_eq!(0x993A, extension.get_checksum());
321 }
322 }
323}
324
325pub mod extension_object {
326 use crate::buffer::Buffer;
327 use crate::error::{Error, Result};
328 use crate::fmt_payload;
329 use std::fmt::{Debug, Formatter};
330
331 #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
333 pub enum ClassNum {
334 MultiProtocolLabelSwitchingLabelStack,
335 InterfaceInformationObject,
336 InterfaceIdentificationObject,
337 ExtendedInformation,
338 Other(u8),
339 }
340
341 impl ClassNum {
342 #[must_use]
343 pub const fn id(&self) -> u8 {
344 match self {
345 Self::MultiProtocolLabelSwitchingLabelStack => 1,
346 Self::InterfaceInformationObject => 2,
347 Self::InterfaceIdentificationObject => 3,
348 Self::ExtendedInformation => 4,
349 Self::Other(id) => *id,
350 }
351 }
352 }
353
354 impl From<u8> for ClassNum {
355 fn from(val: u8) -> Self {
356 match val {
357 1 => Self::MultiProtocolLabelSwitchingLabelStack,
358 2 => Self::InterfaceInformationObject,
359 3 => Self::InterfaceIdentificationObject,
360 4 => Self::ExtendedInformation,
361 id => Self::Other(id),
362 }
363 }
364 }
365
366 #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
368 pub struct ClassSubType(pub u8);
369
370 impl From<u8> for ClassSubType {
371 fn from(val: u8) -> Self {
372 Self(val)
373 }
374 }
375
376 const LENGTH_OFFSET: usize = 0;
377 const CLASS_NUM_OFFSET: usize = 2;
378 const CLASS_SUBTYPE_OFFSET: usize = 3;
379
380 pub struct ExtensionObjectPacket<'a> {
386 buf: Buffer<'a>,
387 }
388
389 impl<'a> ExtensionObjectPacket<'a> {
390 pub fn new(packet: &'a mut [u8]) -> Result<Self> {
391 if packet.len() >= Self::minimum_packet_size() {
392 Ok(Self {
393 buf: Buffer::Mutable(packet),
394 })
395 } else {
396 Err(Error::InsufficientPacketBuffer(
397 String::from("ExtensionObjectPacket"),
398 Self::minimum_packet_size(),
399 packet.len(),
400 ))
401 }
402 }
403
404 pub fn new_view(packet: &'a [u8]) -> Result<Self> {
405 if packet.len() >= Self::minimum_packet_size() {
406 Ok(Self {
407 buf: Buffer::Immutable(packet),
408 })
409 } else {
410 Err(Error::InsufficientPacketBuffer(
411 String::from("ExtensionObjectPacket"),
412 Self::minimum_packet_size(),
413 packet.len(),
414 ))
415 }
416 }
417
418 #[must_use]
419 pub const fn minimum_packet_size() -> usize {
420 4
421 }
422
423 pub fn set_length(&mut self, val: u16) {
424 self.buf.set_bytes(LENGTH_OFFSET, val.to_be_bytes());
425 }
426
427 pub fn set_class_num(&mut self, val: ClassNum) {
428 *self.buf.write(CLASS_NUM_OFFSET) = val.id();
429 }
430
431 pub fn set_class_subtype(&mut self, val: ClassSubType) {
432 *self.buf.write(CLASS_SUBTYPE_OFFSET) = val.0;
433 }
434
435 pub fn set_payload(&mut self, vals: &[u8]) {
436 let current_offset = Self::minimum_packet_size();
437 self.buf.as_slice_mut()[current_offset..current_offset + vals.len()]
438 .copy_from_slice(vals);
439 }
440
441 #[must_use]
442 pub fn get_length(&self) -> u16 {
443 u16::from_be_bytes(self.buf.get_bytes(LENGTH_OFFSET))
444 }
445
446 #[must_use]
447 pub fn get_class_num(&self) -> ClassNum {
448 ClassNum::from(self.buf.read(CLASS_NUM_OFFSET))
449 }
450
451 #[must_use]
452 pub fn get_class_subtype(&self) -> ClassSubType {
453 ClassSubType::from(self.buf.read(CLASS_SUBTYPE_OFFSET))
454 }
455
456 #[must_use]
457 pub fn packet(&self) -> &[u8] {
458 self.buf.as_slice()
459 }
460
461 #[must_use]
462 pub fn payload(&self) -> &[u8] {
463 &self.buf.as_slice()[Self::minimum_packet_size()..usize::from(self.get_length())]
464 }
465 }
466
467 impl Debug for ExtensionObjectPacket<'_> {
468 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
469 f.debug_struct("ExtensionObject")
470 .field("length", &self.get_length())
471 .field("class_num", &self.get_class_num())
472 .field("class_subtype", &self.get_class_subtype())
473 .field("payload", &fmt_payload(self.payload()))
474 .finish()
475 }
476 }
477
478 #[cfg(test)]
479 mod tests {
480 use super::*;
481
482 #[test]
483 fn test_length() {
484 let mut buf = [0_u8; ExtensionObjectPacket::minimum_packet_size()];
485 let mut extension = ExtensionObjectPacket::new(&mut buf).unwrap();
486 extension.set_length(0);
487 assert_eq!(0, extension.get_length());
488 assert_eq!([0x00, 0x00], extension.packet()[0..=1]);
489 extension.set_length(8);
490 assert_eq!(8, extension.get_length());
491 assert_eq!([0x00, 0x08], extension.packet()[0..=1]);
492 extension.set_length(u16::MAX);
493 assert_eq!(u16::MAX, extension.get_length());
494 assert_eq!([0xFF, 0xFF], extension.packet()[0..=1]);
495 }
496
497 #[test]
498 fn test_class_num() {
499 let mut buf = [0_u8; ExtensionObjectPacket::minimum_packet_size()];
500 let mut extension = ExtensionObjectPacket::new(&mut buf).unwrap();
501 extension.set_class_num(ClassNum::MultiProtocolLabelSwitchingLabelStack);
502 assert_eq!(
503 ClassNum::MultiProtocolLabelSwitchingLabelStack,
504 extension.get_class_num()
505 );
506 assert_eq!([0x01], extension.packet()[2..3]);
507 extension.set_class_num(ClassNum::InterfaceInformationObject);
508 assert_eq!(
509 ClassNum::InterfaceInformationObject,
510 extension.get_class_num()
511 );
512 assert_eq!([0x02], extension.packet()[2..3]);
513 extension.set_class_num(ClassNum::InterfaceIdentificationObject);
514 assert_eq!(
515 ClassNum::InterfaceIdentificationObject,
516 extension.get_class_num()
517 );
518 assert_eq!([0x03], extension.packet()[2..3]);
519 extension.set_class_num(ClassNum::ExtendedInformation);
520 assert_eq!(ClassNum::ExtendedInformation, extension.get_class_num());
521 assert_eq!([0x04], extension.packet()[2..3]);
522 extension.set_class_num(ClassNum::Other(255));
523 assert_eq!(ClassNum::Other(255), extension.get_class_num());
524 assert_eq!([0xFF], extension.packet()[2..3]);
525 }
526
527 #[test]
528 fn test_class_subtype() {
529 let mut buf = [0_u8; ExtensionObjectPacket::minimum_packet_size()];
530 let mut extension = ExtensionObjectPacket::new(&mut buf).unwrap();
531 extension.set_class_subtype(ClassSubType(0));
532 assert_eq!(ClassSubType(0), extension.get_class_subtype());
533 assert_eq!([0x00], extension.packet()[3..4]);
534 extension.set_class_subtype(ClassSubType(1));
535 assert_eq!(ClassSubType(1), extension.get_class_subtype());
536 assert_eq!([0x01], extension.packet()[3..4]);
537 extension.set_class_subtype(ClassSubType(255));
538 assert_eq!(ClassSubType(255), extension.get_class_subtype());
539 assert_eq!([0xff], extension.packet()[3..4]);
540 }
541
542 #[test]
543 fn test_extension_header_view() {
544 let buf = [0x00, 0x08, 0x01, 0x01, 0x04, 0xbb, 0x41, 0x01];
545 let object = ExtensionObjectPacket::new_view(&buf).unwrap();
546 assert_eq!(8, object.get_length());
547 assert_eq!(
548 ClassNum::MultiProtocolLabelSwitchingLabelStack,
549 object.get_class_num()
550 );
551 assert_eq!(ClassSubType(1), object.get_class_subtype());
552 assert_eq!([0x04, 0xbb, 0x41, 0x01], object.payload());
553 }
554 }
555}
556
557pub mod mpls_label_stack {
558 use crate::buffer::Buffer;
559 use crate::error::{Error, Result};
560 use crate::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket;
561
562 pub struct MplsLabelStackPacket<'a> {
568 buf: Buffer<'a>,
569 }
570
571 impl<'a> MplsLabelStackPacket<'a> {
572 pub fn new(packet: &'a mut [u8]) -> Result<Self> {
573 if packet.len() >= Self::minimum_packet_size() {
574 Ok(Self {
575 buf: Buffer::Mutable(packet),
576 })
577 } else {
578 Err(Error::InsufficientPacketBuffer(
579 String::from("MplsLabelStackPacket"),
580 Self::minimum_packet_size(),
581 packet.len(),
582 ))
583 }
584 }
585
586 pub fn new_view(packet: &'a [u8]) -> Result<Self> {
587 if packet.len() >= Self::minimum_packet_size() {
588 Ok(Self {
589 buf: Buffer::Immutable(packet),
590 })
591 } else {
592 Err(Error::InsufficientPacketBuffer(
593 String::from("MplsLabelStackPacket"),
594 Self::minimum_packet_size(),
595 packet.len(),
596 ))
597 }
598 }
599
600 #[must_use]
601 pub const fn minimum_packet_size() -> usize {
602 4
603 }
604
605 #[must_use]
606 pub fn packet(&self) -> &[u8] {
607 self.buf.as_slice()
608 }
609
610 #[must_use]
611 pub const fn members(&self) -> MplsLabelStackIter<'_> {
612 MplsLabelStackIter::new(&self.buf)
613 }
614 }
615
616 pub struct MplsLabelStackIter<'a> {
617 buf: &'a Buffer<'a>,
618 offset: usize,
619 bos: u8,
620 }
621
622 impl<'a> MplsLabelStackIter<'a> {
623 #[must_use]
624 pub const fn new(buf: &'a Buffer<'_>) -> Self {
625 Self {
626 buf,
627 offset: 0,
628 bos: 0,
629 }
630 }
631 }
632
633 impl<'a> Iterator for MplsLabelStackIter<'a> {
634 type Item = &'a [u8];
635
636 fn next(&mut self) -> Option<Self::Item> {
637 if self.bos > 0 || self.offset >= self.buf.as_slice().len() {
638 None
639 } else {
640 let member_bytes = &self.buf.as_slice()[self.offset..];
641 if let Ok(member) = MplsLabelStackMemberPacket::new_view(member_bytes) {
642 self.bos = member.get_bos();
643 self.offset += MplsLabelStackMemberPacket::minimum_packet_size();
644 Some(member_bytes)
645 } else {
646 None
647 }
648 }
649 }
650 }
651
652 #[cfg(test)]
653 mod tests {
654 use super::*;
655
656 #[test]
657 fn test_stack_member_iterator() {
658 let buf = [0x04, 0xbb, 0x41, 0x01];
659 let stack = MplsLabelStackPacket::new_view(&buf).unwrap();
660 let mut member_iter = stack.members();
661 let member_bytes = member_iter.next().unwrap();
662 let member = MplsLabelStackMemberPacket::new_view(member_bytes).unwrap();
663 assert_eq!(19380, member.get_label());
664 assert_eq!(0, member.get_exp());
665 assert_eq!(1, member.get_bos());
666 assert_eq!(1, member.get_ttl());
667 assert!(member_iter.next().is_none());
668 }
669 }
670}
671
672pub mod mpls_label_stack_member {
673 use crate::buffer::Buffer;
674 use crate::error::{Error, Result};
675 use std::fmt::{Debug, Formatter};
676
677 const LABEL_OFFSET: usize = 0;
678 const EXP_OFFSET: usize = 2;
679 const BOS_OFFSET: usize = 2;
680 const TTL_OFFSET: usize = 3;
681
682 pub struct MplsLabelStackMemberPacket<'a> {
688 buf: Buffer<'a>,
689 }
690
691 impl<'a> MplsLabelStackMemberPacket<'a> {
692 pub fn new(packet: &'a mut [u8]) -> Result<Self> {
693 if packet.len() >= Self::minimum_packet_size() {
694 Ok(Self {
695 buf: Buffer::Mutable(packet),
696 })
697 } else {
698 Err(Error::InsufficientPacketBuffer(
699 String::from("MplsLabelStackMemberPacket"),
700 Self::minimum_packet_size(),
701 packet.len(),
702 ))
703 }
704 }
705
706 pub fn new_view(packet: &'a [u8]) -> Result<Self> {
707 if packet.len() >= Self::minimum_packet_size() {
708 Ok(Self {
709 buf: Buffer::Immutable(packet),
710 })
711 } else {
712 Err(Error::InsufficientPacketBuffer(
713 String::from("MplsLabelStackMemberPacket"),
714 Self::minimum_packet_size(),
715 packet.len(),
716 ))
717 }
718 }
719
720 #[must_use]
721 pub const fn minimum_packet_size() -> usize {
722 4
723 }
724
725 #[must_use]
726 pub fn get_label(&self) -> u32 {
727 u32::from_be_bytes([
728 0x0,
729 self.buf.read(LABEL_OFFSET),
730 self.buf.read(LABEL_OFFSET + 1),
731 self.buf.read(LABEL_OFFSET + 2),
732 ]) >> 4
733 }
734
735 #[must_use]
736 pub fn get_exp(&self) -> u8 {
737 (self.buf.read(EXP_OFFSET) & 0x0e) >> 1
738 }
739
740 #[must_use]
741 pub fn get_bos(&self) -> u8 {
742 self.buf.read(BOS_OFFSET) & 0x01
743 }
744
745 #[must_use]
746 pub fn get_ttl(&self) -> u8 {
747 self.buf.read(TTL_OFFSET)
748 }
749
750 pub fn set_label(&mut self, val: u32) {
751 let bytes = (val << 4).to_be_bytes();
752 *self.buf.write(LABEL_OFFSET) = bytes[1];
753 *self.buf.write(LABEL_OFFSET + 1) = bytes[2];
754 *self.buf.write(LABEL_OFFSET + 2) =
755 (self.buf.read(LABEL_OFFSET + 2) & 0x0f) | (bytes[3] & 0xf0);
756 }
757
758 pub fn set_exp(&mut self, exp: u8) {
759 *self.buf.write(EXP_OFFSET) = (self.buf.read(EXP_OFFSET) & 0xf1) | ((exp << 1) & 0x0e);
760 }
761
762 pub fn set_bos(&mut self, bos: u8) {
763 *self.buf.write(BOS_OFFSET) = (self.buf.read(BOS_OFFSET) & 0xfe) | (bos & 0x01);
764 }
765
766 pub fn set_ttl(&mut self, ttl: u8) {
767 *self.buf.write(TTL_OFFSET) = ttl;
768 }
769
770 #[must_use]
771 pub fn packet(&self) -> &[u8] {
772 self.buf.as_slice()
773 }
774 }
775
776 impl Debug for MplsLabelStackMemberPacket<'_> {
777 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
778 f.debug_struct("MplsLabelStackMember")
779 .field("label", &self.get_label())
780 .field("exp", &self.get_exp())
781 .field("bos", &self.get_bos())
782 .field("ttl", &self.get_ttl())
783 .finish()
784 }
785 }
786
787 #[cfg(test)]
788 mod tests {
789 use super::*;
790
791 #[test]
792 fn test_label() {
793 let mut buf = [0_u8; MplsLabelStackMemberPacket::minimum_packet_size()];
794 let mut mpls_extension = MplsLabelStackMemberPacket::new(&mut buf).unwrap();
795 mpls_extension.set_label(0);
796 assert_eq!(0, mpls_extension.get_label());
797 assert_eq!([0x00, 0x00, 0x00], mpls_extension.packet()[0..3]);
798 mpls_extension.set_label(19380);
799 assert_eq!(19380, mpls_extension.get_label());
800 assert_eq!([0x04, 0xbb, 0x40], mpls_extension.packet()[0..3]);
801 mpls_extension.set_label(1_048_575);
802 assert_eq!(1_048_575, mpls_extension.get_label());
803 assert_eq!([0xff, 0xff, 0xf0], mpls_extension.packet()[0..3]);
804 }
805
806 #[test]
807 fn test_exp() {
808 let mut buf = [0_u8; MplsLabelStackMemberPacket::minimum_packet_size()];
809 let mut mpls_extension = MplsLabelStackMemberPacket::new(&mut buf).unwrap();
810 mpls_extension.set_exp(0);
811 assert_eq!(0, mpls_extension.get_exp());
812 assert_eq!([0x00], mpls_extension.packet()[2..3]);
813 mpls_extension.set_exp(7);
814 assert_eq!(7, mpls_extension.get_exp());
815 assert_eq!([0x0e], mpls_extension.packet()[2..3]);
816 }
817
818 #[test]
819 fn test_bos() {
820 let mut buf = [0_u8; MplsLabelStackMemberPacket::minimum_packet_size()];
821 let mut mpls_extension = MplsLabelStackMemberPacket::new(&mut buf).unwrap();
822 mpls_extension.set_bos(0);
823 assert_eq!(0, mpls_extension.get_bos());
824 assert_eq!([0x00], mpls_extension.packet()[2..3]);
825 mpls_extension.set_bos(1);
826 assert_eq!(1, mpls_extension.get_bos());
827 assert_eq!([0x01], mpls_extension.packet()[2..3]);
828 }
829
830 #[test]
831 fn test_ttl() {
832 let mut buf = [0_u8; MplsLabelStackMemberPacket::minimum_packet_size()];
833 let mut mpls_extension = MplsLabelStackMemberPacket::new(&mut buf).unwrap();
834 mpls_extension.set_ttl(0);
835 assert_eq!(0, mpls_extension.get_ttl());
836 assert_eq!([0x00], mpls_extension.packet()[3..4]);
837 mpls_extension.set_ttl(1);
838 assert_eq!(1, mpls_extension.get_ttl());
839 assert_eq!([0x01], mpls_extension.packet()[3..4]);
840 mpls_extension.set_ttl(255);
841 assert_eq!(255, mpls_extension.get_ttl());
842 assert_eq!([0xff], mpls_extension.packet()[3..4]);
843 }
844
845 #[test]
846 fn test_combined() {
847 let mut buf = [0_u8; MplsLabelStackMemberPacket::minimum_packet_size()];
848 let mut mpls_extension = MplsLabelStackMemberPacket::new(&mut buf).unwrap();
849 mpls_extension.set_label(19380);
850 mpls_extension.set_exp(0);
851 mpls_extension.set_bos(1);
852 mpls_extension.set_ttl(1);
853 assert_eq!(19380, mpls_extension.get_label());
854 assert_eq!(0, mpls_extension.get_exp());
855 assert_eq!(1, mpls_extension.get_bos());
856 assert_eq!(1, mpls_extension.get_ttl());
857 assert_eq!([0x04, 0xbb, 0x41, 0x01], mpls_extension.packet()[0..4]);
858 mpls_extension.set_label(1_048_575);
859 mpls_extension.set_exp(7);
860 mpls_extension.set_bos(1);
861 mpls_extension.set_ttl(255);
862 assert_eq!(1_048_575, mpls_extension.get_label());
863 assert_eq!(7, mpls_extension.get_exp());
864 assert_eq!(1, mpls_extension.get_bos());
865 assert_eq!(255, mpls_extension.get_ttl());
866 assert_eq!([0xff, 0xff, 0xff, 0xff], mpls_extension.packet()[0..4]);
867 }
868
869 #[test]
870 fn test_view() {
871 let buf = [0x04, 0xbb, 0x41, 0x01];
872 let object = MplsLabelStackMemberPacket::new_view(&buf).unwrap();
873 assert_eq!(19380, object.get_label());
874 assert_eq!(0, object.get_exp());
875 assert_eq!(1, object.get_bos());
876 assert_eq!(1, object.get_ttl());
877 }
878 }
879}
880
881pub mod extension_splitter {
882 use crate::icmp_extension::extension_header::ExtensionHeaderPacket;
883 const MIN_HEADER: usize = ExtensionHeaderPacket::minimum_packet_size();
884
885 const ICMP_ORIG_DATAGRAM_MIN_LENGTH: usize = 128;
891
892 #[must_use]
896 pub fn split(length: usize, icmp_payload: &[u8]) -> (&[u8], Option<&[u8]>) {
897 if length > icmp_payload.len() {
900 return (icmp_payload, None);
901 }
902 if icmp_payload.len() > ICMP_ORIG_DATAGRAM_MIN_LENGTH {
903 if length > ICMP_ORIG_DATAGRAM_MIN_LENGTH {
904 match icmp_payload.split_at(length) {
906 (payload, extension) if extension.len() >= MIN_HEADER => {
907 (payload, Some(extension))
908 }
909 _ => (icmp_payload, None),
910 }
911 } else if length > 0 {
912 match icmp_payload.split_at(ICMP_ORIG_DATAGRAM_MIN_LENGTH) {
915 (payload, extension) if extension.len() >= MIN_HEADER => {
916 (&payload[..length], Some(extension))
917 }
918 _ => (icmp_payload, None),
919 }
920 } else {
921 match icmp_payload.split_at(ICMP_ORIG_DATAGRAM_MIN_LENGTH) {
923 (payload, extension) if extension.len() >= MIN_HEADER => {
924 (payload, Some(extension))
925 }
926 _ => (icmp_payload, None),
927 }
928 }
929 } else {
930 (icmp_payload, None)
932 }
933 }
934
935 #[cfg(test)]
936 mod tests {
937 use super::*;
938 use crate::icmp_extension::extension_header::ExtensionHeaderPacket;
939 use crate::icmp_extension::extension_object::{
940 ClassNum, ClassSubType, ExtensionObjectPacket,
941 };
942 use crate::icmp_extension::extension_structure::ExtensionsPacket;
943 use crate::icmp_extension::mpls_label_stack::MplsLabelStackPacket;
944 use crate::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket;
945
946 #[test]
947 fn test_split_empty_payload() {
948 let icmp_payload: [u8; 0] = [];
949 let (payload, extension) = split(0, &icmp_payload);
950 assert!(payload.is_empty() && extension.is_none());
951 }
952
953 #[test]
956 fn test_split_payload_with_compliant_empty_extension() {
957 let icmp_payload: [u8; 12] = [0; 12];
958 let (payload, extension) = split(3 * 4, &icmp_payload);
959 assert_eq!(payload, &[0; 12]);
960 assert_eq!(extension, None);
961 }
962
963 #[test]
965 fn test_split_payload_with_compliant_minimal_extension() {
966 let icmp_payload: [u8; 132] = [0; 132];
967 let (payload, extension) = split(32 * 4, &icmp_payload);
968 assert_eq!(payload, &[0; 128]);
969 assert_eq!(extension, Some([0; 4].as_slice()));
970 }
971
972 #[test]
977 fn test_split_payload_with_invalid_rfc4884_length() {
978 let icmp_payload: [u8; 128] = [0; 128];
979 let (payload, extension) = split(33 * 4, &icmp_payload);
980 assert_eq!(payload, &[0; 128]);
981 assert!(extension.is_none());
982 }
983
984 #[test]
990 fn test_split_payload_with_compliant_invalid_extension() {
991 let icmp_payload: [u8; 129] = [0; 129];
992 let (payload, extension) = split(32 * 4, &icmp_payload);
993 assert_eq!(payload, &[0; 129]);
994 assert!(extension.is_none());
995 }
996
997 mod ipv4 {
998 use super::*;
999 use crate::icmpv4::echo_request::EchoRequestPacket;
1000 use crate::icmpv4::time_exceeded::TimeExceededPacket;
1001 use crate::icmpv4::{IcmpCode, IcmpType};
1002 use crate::ipv4::Ipv4Packet;
1003 use std::net::Ipv4Addr;
1004
1005 #[test]
1009 #[allow(clippy::cognitive_complexity)]
1010 fn test_split_extension_ipv4_time_exceeded_non_compliant_mpls() {
1011 let buf = hex_literal::hex!(
1012 "
1013 0b 00 f4 ff 00 00 00 00 45 00 00 54 cc 1c 40 00
1014 01 01 b5 f4 c0 a8 01 15 5d b8 d8 22 08 00 0f e3
1015 65 da 82 42 00 00 00 00 00 00 00 00 00 00 00 00
1016 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1017 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1018 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1019 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1021 00 00 00 00 00 00 00 00 20 00 99 3a 00 08 01 01
1022 04 bb 41 01
1023 "
1024 );
1025 let time_exceeded_packet = TimeExceededPacket::new_view(&buf).unwrap();
1026 assert_eq!(IcmpType::TimeExceeded, time_exceeded_packet.get_icmp_type());
1027 assert_eq!(IcmpCode(0), time_exceeded_packet.get_icmp_code());
1028 assert_eq!(62719, time_exceeded_packet.get_checksum());
1029 assert_eq!(0, time_exceeded_packet.get_length());
1030 assert_eq!(&buf[8..136], time_exceeded_packet.payload());
1031 assert_eq!(Some(&buf[136..]), time_exceeded_packet.extension());
1032
1033 let nested_ipv4 = Ipv4Packet::new_view(time_exceeded_packet.payload()).unwrap();
1034 assert_eq!(Ipv4Addr::from([192, 168, 1, 21]), nested_ipv4.get_source());
1035 assert_eq!(
1036 Ipv4Addr::from([93, 184, 216, 34]),
1037 nested_ipv4.get_destination()
1038 );
1039 assert_eq!(&buf[28..136], nested_ipv4.payload());
1040
1041 let nested_echo = EchoRequestPacket::new_view(nested_ipv4.payload()).unwrap();
1042 assert_eq!(IcmpCode(0), nested_echo.get_icmp_code());
1043 assert_eq!(IcmpType::EchoRequest, nested_echo.get_icmp_type());
1044 assert_eq!(0x0FE3, nested_echo.get_checksum());
1045 assert_eq!(26074, nested_echo.get_identifier());
1046 assert_eq!(33346, nested_echo.get_sequence());
1047 assert_eq!(&buf[36..136], nested_echo.payload());
1048
1049 let extensions =
1050 ExtensionsPacket::new_view(time_exceeded_packet.extension().unwrap()).unwrap();
1051
1052 let extension_header =
1053 ExtensionHeaderPacket::new_view(extensions.header()).unwrap();
1054 assert_eq!(2, extension_header.get_version());
1055 assert_eq!(0x993A, extension_header.get_checksum());
1056
1057 let object_bytes = extensions.objects().next().unwrap();
1058 let extension_object = ExtensionObjectPacket::new_view(object_bytes).unwrap();
1059
1060 assert_eq!(8, extension_object.get_length());
1061 assert_eq!(
1062 ClassNum::MultiProtocolLabelSwitchingLabelStack,
1063 extension_object.get_class_num()
1064 );
1065 assert_eq!(ClassSubType(1), extension_object.get_class_subtype());
1066 assert_eq!([0x04, 0xbb, 0x41, 0x01], extension_object.payload());
1067
1068 let mpls_stack =
1069 MplsLabelStackPacket::new_view(extension_object.payload()).unwrap();
1070 let mpls_stack_member_bytes = mpls_stack.members().next().unwrap();
1071 let mpls_stack_member =
1072 MplsLabelStackMemberPacket::new_view(mpls_stack_member_bytes).unwrap();
1073 assert_eq!(19380, mpls_stack_member.get_label());
1074 assert_eq!(0, mpls_stack_member.get_exp());
1075 assert_eq!(1, mpls_stack_member.get_bos());
1076 assert_eq!(1, mpls_stack_member.get_ttl());
1077 }
1078
1079 #[test]
1082 fn test_split_extension_ipv4_time_exceeded_compliant_no_extension() {
1083 let buf = hex_literal::hex!(
1084 "
1085 0b 00 f4 ee 00 11 00 00 45 00 00 54 a2 ee 40 00
1086 01 01 df 22 c0 a8 01 15 5d b8 d8 22 08 00 0f e1
1087 65 da 82 44 00 00 00 00 00 00 00 00 00 00 00 00
1088 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1089 00 00 00 00 00 00 00 00 00 00 00 00
1090 "
1091 );
1092 let time_exceeded_packet = TimeExceededPacket::new_view(&buf).unwrap();
1093 assert_eq!(IcmpType::TimeExceeded, time_exceeded_packet.get_icmp_type());
1094 assert_eq!(IcmpCode(0), time_exceeded_packet.get_icmp_code());
1095 assert_eq!(62702, time_exceeded_packet.get_checksum());
1096 assert_eq!(17, time_exceeded_packet.get_length());
1097 assert_eq!(&buf[8..76], time_exceeded_packet.payload());
1098 assert_eq!(None, time_exceeded_packet.extension());
1099
1100 let nested_ipv4 = Ipv4Packet::new_view(&buf[8..76]).unwrap();
1101 assert_eq!(Ipv4Addr::from([192, 168, 1, 21]), nested_ipv4.get_source());
1102 assert_eq!(
1103 Ipv4Addr::from([93, 184, 216, 34]),
1104 nested_ipv4.get_destination()
1105 );
1106 assert_eq!(&buf[28..76], nested_ipv4.payload());
1107
1108 let nested_echo = EchoRequestPacket::new_view(nested_ipv4.payload()).unwrap();
1109 assert_eq!(IcmpCode(0), nested_echo.get_icmp_code());
1110 assert_eq!(IcmpType::EchoRequest, nested_echo.get_icmp_type());
1111 assert_eq!(0x0FE1, nested_echo.get_checksum());
1112 assert_eq!(26074, nested_echo.get_identifier());
1113 assert_eq!(33348, nested_echo.get_sequence());
1114 assert_eq!(&buf[36..76], nested_echo.payload());
1115 }
1116
1117 #[test]
1126 fn test_split_extension_ipv4_time_exceeded_compliant_extension() {
1127 let buf = hex_literal::hex!(
1128 "
1129 0b 00 f4 ee 00 11 00 00 45 00 00 54 20 c3 40 00
1130 02 01 b5 7e 64 63 08 2a 5d b8 d8 22 08 00 11 8d
1131 65 83 80 ef 00 00 00 00 00 00 00 00 00 00 00 00
1132 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1133 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1134 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1135 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1136 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1137 00 00 00 00 00 00 00 00 20 00 78 56 00 08 01 01
1138 65 9f 01 01
1139 "
1140 );
1141 let time_exceeded_packet = TimeExceededPacket::new_view(&buf).unwrap();
1142 assert_eq!(68, time_exceeded_packet.payload().len());
1143 assert_eq!(12, time_exceeded_packet.extension().unwrap().len());
1144 let extensions =
1145 ExtensionsPacket::new_view(time_exceeded_packet.extension().unwrap()).unwrap();
1146
1147 let extension_header =
1148 ExtensionHeaderPacket::new_view(extensions.header()).unwrap();
1149 assert_eq!(2, extension_header.get_version());
1150 assert_eq!(0x7856, extension_header.get_checksum());
1151
1152 let object_bytes = extensions.objects().next().unwrap();
1153 let extension_object = ExtensionObjectPacket::new_view(object_bytes).unwrap();
1154
1155 assert_eq!(8, extension_object.get_length());
1156 assert_eq!(
1157 ClassNum::MultiProtocolLabelSwitchingLabelStack,
1158 extension_object.get_class_num()
1159 );
1160 assert_eq!(ClassSubType(1), extension_object.get_class_subtype());
1161 assert_eq!([0x65, 0x9f, 0x01, 0x01], extension_object.payload());
1162
1163 let mpls_stack =
1164 MplsLabelStackPacket::new_view(extension_object.payload()).unwrap();
1165 let mpls_stack_member_bytes = mpls_stack.members().next().unwrap();
1166 let mpls_stack_member =
1167 MplsLabelStackMemberPacket::new_view(mpls_stack_member_bytes).unwrap();
1168 assert_eq!(416_240, mpls_stack_member.get_label());
1169 assert_eq!(0, mpls_stack_member.get_exp());
1170 assert_eq!(1, mpls_stack_member.get_bos());
1171 assert_eq!(1, mpls_stack_member.get_ttl());
1172 }
1173 }
1174
1175 mod ipv6 {
1176 use crate::icmp_extension::extension_header::ExtensionHeaderPacket;
1177 use crate::icmp_extension::extension_object::{
1178 ClassNum, ClassSubType, ExtensionObjectPacket,
1179 };
1180 use crate::icmp_extension::extension_structure::ExtensionsPacket;
1181 use crate::icmp_extension::mpls_label_stack::MplsLabelStackPacket;
1182 use crate::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket;
1183 use crate::icmpv6::echo_request::EchoRequestPacket;
1184 use crate::icmpv6::time_exceeded::TimeExceededPacket;
1185 use crate::icmpv6::{IcmpCode, IcmpType};
1186 use crate::ipv6::Ipv6Packet;
1187
1188 #[test]
1194 #[allow(clippy::cognitive_complexity)]
1195 fn test_ipv6() {
1196 let buf = hex_literal::hex!(
1197 "
1198 03 00 be a8 0a 00 00 00 68 04 83 fe 00 2c 3a 01
1199 24 00 61 80 00 00 00 d0 00 00 00 00 12 65 b0 01
1200 24 04 68 00 40 03 0c 1c 00 00 00 00 00 00 00 8a
1201 80 00 b2 e1 2a 60 80 f2 00 00 00 00 00 00 00 00
1202 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1203 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1204 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1205 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1206 00 00 00 00 00 00 00 00 20 00 96 53 00 0c 01 01
1207 06 9f 18 01 00 00 29 ff
1208 "
1209 );
1210 let time_exceeded_packet = TimeExceededPacket::new_view(&buf).unwrap();
1211 assert_eq!(IcmpType::TimeExceeded, time_exceeded_packet.get_icmp_type());
1212 assert_eq!(IcmpCode(0), time_exceeded_packet.get_icmp_code());
1213 assert_eq!(48808, time_exceeded_packet.get_checksum());
1214 assert_eq!(10, time_exceeded_packet.get_length());
1215 assert_eq!(&buf[8..88], time_exceeded_packet.payload());
1216 assert_eq!(Some(&buf[136..]), time_exceeded_packet.extension());
1217 assert_eq!(80, time_exceeded_packet.payload().len());
1218 assert_eq!(16, time_exceeded_packet.extension().unwrap().len());
1219
1220 let nested_ipv6 = Ipv6Packet::new_view(time_exceeded_packet.payload()).unwrap();
1221 let nested_echo = EchoRequestPacket::new_view(nested_ipv6.payload()).unwrap();
1222 assert_eq!(IcmpCode(0), nested_echo.get_icmp_code());
1223 assert_eq!(IcmpType::EchoRequest, nested_echo.get_icmp_type());
1224 assert_eq!(0xB2E1, nested_echo.get_checksum());
1225 assert_eq!(10848, nested_echo.get_identifier());
1226 assert_eq!(33010, nested_echo.get_sequence());
1227
1228 let extensions =
1229 ExtensionsPacket::new_view(time_exceeded_packet.extension().unwrap()).unwrap();
1230
1231 let extension_header =
1232 ExtensionHeaderPacket::new_view(extensions.header()).unwrap();
1233 assert_eq!(2, extension_header.get_version());
1234 assert_eq!(0x9653, extension_header.get_checksum());
1235
1236 let object_bytes = extensions.objects().next().unwrap();
1237 let extension_object = ExtensionObjectPacket::new_view(object_bytes).unwrap();
1238 assert_eq!(12, extension_object.get_length());
1239 assert_eq!(
1240 ClassNum::MultiProtocolLabelSwitchingLabelStack,
1241 extension_object.get_class_num()
1242 );
1243 assert_eq!(ClassSubType(1), extension_object.get_class_subtype());
1244 assert_eq!(
1245 [0x06, 0x9f, 0x18, 0x01, 0x00, 0x00, 0x29, 0xff],
1246 extension_object.payload()
1247 );
1248
1249 let mpls_stack =
1250 MplsLabelStackPacket::new_view(extension_object.payload()).unwrap();
1251 let mut mpls_stack_member_iter = mpls_stack.members();
1252
1253 let mpls_stack_member_bytes = mpls_stack_member_iter.next().unwrap();
1255 let mpls_stack_member =
1256 MplsLabelStackMemberPacket::new_view(mpls_stack_member_bytes).unwrap();
1257 assert_eq!(27121, mpls_stack_member.get_label());
1258 assert_eq!(4, mpls_stack_member.get_exp());
1259 assert_eq!(0, mpls_stack_member.get_bos());
1260 assert_eq!(1, mpls_stack_member.get_ttl());
1261
1262 let mpls_stack_member_bytes = mpls_stack_member_iter.next().unwrap();
1264 let mpls_stack_member =
1265 MplsLabelStackMemberPacket::new_view(mpls_stack_member_bytes).unwrap();
1266 assert_eq!(2, mpls_stack_member.get_label());
1267 assert_eq!(4, mpls_stack_member.get_exp());
1268 assert_eq!(1, mpls_stack_member.get_bos());
1269 assert_eq!(255, mpls_stack_member.get_ttl());
1270 assert!(mpls_stack_member_iter.next().is_none());
1271 }
1272
1273 #[test]
1279 fn test_ipv6_2() {
1280 let buf = hex_literal::hex!(
1281 "
1282 03 00 5a b4 10 00 00 00 68 0e 0d 91 00 2c 3a 01
1283 24 00 61 80 00 00 00 d0 00 00 00 00 12 65 b0 01
1284 24 04 68 00 40 03 0c 05 00 00 00 00 00 00 00 71
1285 80 00 a8 e7 34 88 80 f4 00 00 00 00 00 00 00 00
1286 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1287 00 00 00 00 00 00 00 00 00 00 00 00
1288 "
1289 );
1290 let time_exceeded_packet = TimeExceededPacket::new_view(&buf).unwrap();
1291 assert_eq!(84, time_exceeded_packet.payload().len());
1292 assert_eq!(None, time_exceeded_packet.extension());
1293
1294 let nested_ipv6 = Ipv6Packet::new_view(time_exceeded_packet.payload()).unwrap();
1295 let nested_echo = EchoRequestPacket::new_view(nested_ipv6.payload()).unwrap();
1296 assert_eq!(IcmpCode(0), nested_echo.get_icmp_code());
1297 assert_eq!(IcmpType::EchoRequest, nested_echo.get_icmp_type());
1298 assert_eq!(0xA8E7, nested_echo.get_checksum());
1299 assert_eq!(13448, nested_echo.get_identifier());
1300 assert_eq!(33012, nested_echo.get_sequence());
1301 }
1302 }
1303 }
1304}