1pub mod ext;
102
103use std::fmt::{self, Formatter};
104use std::net::Ipv6Addr;
105use std::ops::Deref;
106
107use zerocopy::byteorder::{BigEndian, U16};
108use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
109
110use crate::packet::ipv6::ext::Ipv6ExtensionHeadersIter;
111use crate::packet::protocol::IpProto;
112use crate::packet::{HeaderParser, PacketHeader};
113
114#[repr(C, packed)]
119#[derive(FromBytes, IntoBytes, Immutable, Unaligned, KnownLayout, Debug, Clone, Copy)]
120pub struct Ipv6Header {
121 ver_tc_flow: [u8; 4],
123 payload_length: U16<BigEndian>,
125 next_header: IpProto,
127 hop_limit: u8,
129 src_ip: [u8; 16],
131 dst_ip: [u8; 16],
133}
134
135pub const IPV6_NEXT_HOPBYHOP: IpProto = IpProto::IPV6_HOPOPT;
138pub const IPV6_NEXT_TCP: IpProto = IpProto::TCP;
139pub const IPV6_NEXT_UDP: IpProto = IpProto::UDP;
140pub const IPV6_NEXT_IPV6: IpProto = IpProto::IPV6;
141pub const IPV6_NEXT_ROUTING: IpProto = IpProto::IPV6_ROUTE;
142pub const IPV6_NEXT_FRAGMENT: IpProto = IpProto::IPV6_FRAG;
143pub const IPV6_NEXT_ICMPV6: IpProto = IpProto::IPV6_ICMP;
144pub const IPV6_NEXT_NONE: IpProto = IpProto::IPV6_NONXT;
145pub const IPV6_NEXT_DSTOPTS: IpProto = IpProto::IPV6_OPTS;
146pub const IPV6_NEXT_MOBILITY: IpProto = IpProto::IPV6_MOBILITY;
147
148impl Ipv6Header {
149 #[inline]
151 pub fn version(&self) -> u8 {
152 self.ver_tc_flow[0] >> 4
153 }
154
155 #[inline]
158 pub fn traffic_class(&self) -> u8 {
159 ((self.ver_tc_flow[0] & 0x0F) << 4) | (self.ver_tc_flow[1] >> 4)
160 }
161
162 #[inline]
164 pub fn dscp(&self) -> u8 {
165 self.traffic_class() >> 2
166 }
167
168 #[inline]
170 pub fn ecn(&self) -> u8 {
171 self.traffic_class() & 0x03
172 }
173
174 #[inline]
177 pub fn flow_label(&self) -> u32 {
178 let b1 = (self.ver_tc_flow[1] & 0x0F) as u32;
179 let b2 = self.ver_tc_flow[2] as u32;
180 let b3 = self.ver_tc_flow[3] as u32;
181 (b1 << 16) | (b2 << 8) | b3
182 }
183
184 #[inline]
187 pub fn payload_length(&self) -> usize {
188 self.payload_length.get() as usize
189 }
190
191 #[inline]
193 pub fn total_length(&self) -> usize {
194 Self::FIXED_LEN + self.payload_length()
195 }
196
197 #[inline]
200 pub fn next_header(&self) -> IpProto {
201 self.next_header
202 }
203
204 #[inline]
207 pub fn hop_limit(&self) -> u8 {
208 self.hop_limit
209 }
210
211 #[inline]
213 pub fn src_ip(&self) -> Ipv6Addr {
214 Ipv6Addr::from(self.src_ip)
215 }
216
217 #[inline]
219 pub fn dst_ip(&self) -> Ipv6Addr {
220 Ipv6Addr::from(self.dst_ip)
221 }
222
223 #[inline]
225 pub fn src_ip_raw(&self) -> [u8; 16] {
226 self.src_ip
227 }
228
229 #[inline]
231 pub fn dst_ip_raw(&self) -> [u8; 16] {
232 self.dst_ip
233 }
234
235 #[inline]
237 pub fn has_extension_headers(&self) -> bool {
238 matches!(
239 self.next_header,
240 IPV6_NEXT_HOPBYHOP | IPV6_NEXT_ROUTING | IPV6_NEXT_FRAGMENT | IPV6_NEXT_DSTOPTS
241 )
242 }
243
244 #[inline]
246 pub fn is_transport_protocol(&self) -> bool {
247 matches!(self.next_header, IPV6_NEXT_TCP | IPV6_NEXT_UDP)
248 }
249
250 fn parse_extension_headers(
254 buf: &[u8],
255 bytes_available: usize,
256 initial_next_header: IpProto,
257 allow_fragment: bool,
258 ) -> Option<(usize, IpProto, bool)> {
259 if bytes_available < Self::FIXED_LEN {
260 return None;
261 }
262
263 let mut len = Self::FIXED_LEN;
264 let mut next_hdr = initial_next_header;
265 let mut is_fragmented = false;
266
267 while matches!(
269 next_hdr,
270 IPV6_NEXT_HOPBYHOP
271 | IPV6_NEXT_ROUTING
272 | IPV6_NEXT_DSTOPTS
273 | IPV6_NEXT_MOBILITY
274 | IPV6_NEXT_FRAGMENT
275 ) {
276 if next_hdr == IPV6_NEXT_FRAGMENT {
277 if !allow_fragment {
278 return None;
279 }
280 is_fragmented = true;
281 if len >= bytes_available {
284 return None;
285 }
286 next_hdr = IpProto::from(buf[len]);
287 len += 8;
288 } else {
289 if len + 2 > bytes_available {
292 return None;
293 }
294
295 next_hdr = IpProto::from(buf[len]);
299 let ext_len = buf[len + 1];
300
301 let delta = (1 + ext_len as usize) * 8;
304
305 if delta == 0 {
307 return None;
308 }
309
310 len += delta;
311
312 if len > bytes_available {
314 return None;
315 }
316 }
317 }
318
319 Some((len, next_hdr, is_fragmented))
320 }
321
322 pub fn total_header_len(&self, buf: &[u8], bytes_available: usize) -> usize {
330 Self::parse_extension_headers(buf, bytes_available, self.next_header, false)
332 .map(|(len, _, _)| len)
333 .unwrap_or(0)
334 }
335
336 pub fn upper_layer_protocol(
339 &self,
340 buf: &[u8],
341 bytes_available: usize,
342 ) -> Option<(IpProto, bool)> {
343 Self::parse_extension_headers(buf, bytes_available, self.next_header, true)
345 .map(|(_, protocol, is_fragmented)| (protocol, is_fragmented))
346 }
347
348 #[inline]
350 pub fn should_parse_extensions(&self) -> bool {
351 self.has_extension_headers()
352 }
353}
354
355#[derive(Debug, Clone)]
357pub struct Ipv6HeaderExt<'a> {
358 pub header: &'a Ipv6Header,
359 pub raw_extensions: &'a [u8],
360}
361
362impl<'a> Ipv6HeaderExt<'a> {
363 pub fn extensions(&'a self) -> Ipv6ExtensionHeadersIter<'a> {
365 Ipv6ExtensionHeadersIter::new(self.header.next_header, self.raw_extensions)
366 }
367
368 pub fn ext_headers_len(&self) -> usize {
370 Ipv6Header::FIXED_LEN + self.raw_extensions.len()
371 }
372}
373
374impl Deref for Ipv6HeaderExt<'_> {
375 type Target = Ipv6Header;
376
377 #[inline]
378 fn deref(&self) -> &Self::Target {
379 self.header
380 }
381}
382
383impl PacketHeader for Ipv6Header {
384 const NAME: &'static str = "IPv6Header";
385 type InnerType = IpProto;
386
387 #[inline]
388 fn inner_type(&self) -> Self::InnerType {
389 self.next_header
390 }
391
392 #[inline]
395 fn total_len(&self, buf: &[u8]) -> usize {
396 Self::parse_extension_headers(buf, buf.len(), self.next_header, true)
399 .map(|(len, _, _)| len)
400 .unwrap_or(Self::FIXED_LEN) }
402
403 #[inline]
405 fn is_valid(&self) -> bool {
406 self.version() == 6
408 }
409}
410
411impl HeaderParser for Ipv6Header {
412 type Output<'a> = Ipv6HeaderExt<'a>;
413
414 #[inline]
415 fn into_view<'a>(header: &'a Self, raw_extensions: &'a [u8]) -> Self::Output<'a> {
416 Ipv6HeaderExt {
417 header,
418 raw_extensions,
419 }
420 }
421}
422
423impl fmt::Display for Ipv6Header {
424 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
425 write!(
426 f,
427 "IPv6 {} -> {} proto={} hop={} len={}",
428 self.src_ip(),
429 self.dst_ip(),
430 self.next_header(),
431 self.hop_limit(),
432 self.total_length()
433 )?;
434
435 if self.flow_label() != 0 {
436 write!(f, " flow=0x{:05x}", self.flow_label())?;
437 }
438
439 if self.has_extension_headers() {
440 write!(f, " +exts")?;
441 }
442
443 Ok(())
444 }
445}
446
447impl fmt::Display for Ipv6HeaderExt<'_> {
448 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
449 write!(f, "{}", self.header)?;
450
451 if !self.raw_extensions.is_empty() {
452 write!(f, " exts=[")?;
453 let mut first = true;
454 for ext in self.extensions().flatten() {
455 if !first {
456 write!(f, ",")?;
457 }
458 first = false;
459 write!(f, "{}", ext)?;
460 }
461 write!(f, "]")?;
462 }
463
464 Ok(())
465 }
466}
467
468#[cfg(test)]
469mod tests {
470 use super::*;
471 use std::mem;
472
473 #[test]
474 fn test_ipv6_header_size() {
475 assert_eq!(mem::size_of::<Ipv6Header>(), 40);
476 assert_eq!(Ipv6Header::FIXED_LEN, 40);
477 }
478
479 #[test]
480 fn test_ipv6_version() {
481 let header = create_test_header();
482 assert_eq!(header.version(), 6);
483 assert!(header.is_valid());
484 }
485
486 #[test]
487 fn test_ipv6_traffic_class() {
488 let mut header = create_test_header();
489
490 header.ver_tc_flow[0] = 0x6A;
494 header.ver_tc_flow[1] = 0xB0;
495
496 assert_eq!(header.traffic_class(), 0xAB);
497 assert_eq!(header.dscp(), 0xAB >> 2);
498 assert_eq!(header.ecn(), 0xAB & 0x03);
499 }
500
501 #[test]
502 fn test_ipv6_flow_label() {
503 let mut header = create_test_header();
504
505 header.ver_tc_flow[1] = (header.ver_tc_flow[1] & 0xF0) | 0x01;
508 header.ver_tc_flow[2] = 0x23;
509 header.ver_tc_flow[3] = 0x45;
510
511 assert_eq!(header.flow_label(), 0x12345);
512 }
513
514 #[test]
515 fn test_ipv6_addresses() {
516 let header = create_test_header();
517
518 let expected_src = Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1);
520 assert_eq!(header.src_ip(), expected_src);
521
522 let expected_dst = Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 2);
524 assert_eq!(header.dst_ip(), expected_dst);
525 }
526
527 #[test]
528 fn test_ipv6_payload_length() {
529 let mut header = create_test_header();
530 header.payload_length = U16::new(1024);
531
532 assert_eq!(header.payload_length(), 1024);
533 assert_eq!(header.total_length(), 40 + 1024);
534 }
535
536 #[test]
537 fn test_ipv6_next_header() {
538 let mut header = create_test_header();
539
540 header.next_header = IPV6_NEXT_TCP;
541 assert_eq!(header.next_header(), IpProto::TCP);
542 assert!(header.is_transport_protocol());
543 assert!(!header.has_extension_headers());
544
545 header.next_header = IPV6_NEXT_FRAGMENT;
546 assert!(header.has_extension_headers());
547 assert!(!header.is_transport_protocol());
548 }
549
550 #[test]
551 fn test_ipv6_parsing() {
552 let packet = create_test_packet();
553
554 let result = Ipv6Header::from_bytes(&packet);
555 assert!(result.is_ok());
556
557 let (header_ext, payload) = result.unwrap();
558 assert_eq!(header_ext.version(), 6);
559 assert_eq!(header_ext.next_header(), IPV6_NEXT_TCP);
560 assert_eq!(header_ext.hop_limit(), 64);
561 assert_eq!(header_ext.raw_extensions.len(), 0);
562 assert_eq!(payload.len(), 0);
563 }
564
565 #[test]
566 fn test_ipv6_parsing_invalid_version() {
567 let mut packet = create_test_packet();
568 packet[0] = 0x40; let result = Ipv6Header::from_bytes(&packet);
571 assert!(result.is_err());
572 }
573
574 #[test]
575 fn test_ipv6_parsing_too_small() {
576 let packet = vec![0u8; 39]; let result = Ipv6Header::from_bytes(&packet);
579 assert!(result.is_err());
580 }
581
582 #[test]
583 fn test_ipv6_total_header_len_no_extensions() {
584 let packet = create_test_packet();
585 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
586
587 assert_eq!(header.total_header_len(&packet, packet.len()), 40);
589 }
590
591 #[test]
592 fn test_ipv6_total_header_len_with_extensions() {
593 let mut packet = create_test_packet();
594
595 packet[6] = IPV6_NEXT_HOPBYHOP.into();
597
598 packet.push(IPV6_NEXT_TCP.into());
601 packet.push(0);
603 packet.extend_from_slice(&[0, 0, 0, 0, 0, 0]);
605
606 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
607
608 assert_eq!(header.total_header_len(&packet, packet.len()), 48);
610 }
611
612 #[test]
613 fn test_ipv6_upper_layer_protocol() {
614 let packet = create_test_packet();
615 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
616
617 let result = header.upper_layer_protocol(&packet, packet.len());
619 assert_eq!(result, Some((IpProto::TCP, false)));
620 }
621
622 #[test]
623 fn test_ipv6_upper_layer_protocol_with_extensions() {
624 let mut packet = create_test_packet();
625
626 packet[6] = IPV6_NEXT_HOPBYHOP.into();
628
629 packet.push(IPV6_NEXT_TCP.into()); packet.push(0); packet.extend_from_slice(&[0, 0, 0, 0, 0, 0]); let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
635
636 let result = header.upper_layer_protocol(&packet, packet.len());
637 assert_eq!(result, Some((IpProto::TCP, false)));
638 }
639
640 #[test]
641 fn test_ipv6_from_bytes_with_routing_extension() {
642 let mut packet = create_test_packet();
643
644 packet[6] = IPV6_NEXT_ROUTING.into();
646
647 packet.push(IPV6_NEXT_TCP.into()); packet.push(2); packet.push(0); packet.push(1); packet.extend_from_slice(&[0, 0, 0, 0]); packet.extend_from_slice(&[
656 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x03,
658 ]);
659
660 let payload_data = b"Test payload after routing header";
662 packet.extend_from_slice(payload_data);
663
664 let total_payload = 24 + payload_data.len();
666 packet[4] = ((total_payload >> 8) & 0xFF) as u8;
667 packet[5] = (total_payload & 0xFF) as u8;
668
669 let result = Ipv6Header::from_bytes(&packet);
671 assert!(result.is_ok());
672
673 let (header, payload) = result.unwrap();
674
675 assert_eq!(payload.len(), payload_data.len());
678 assert_eq!(payload, payload_data);
679
680 assert_eq!(header.next_header(), IpProto::IPV6_ROUTE);
682 assert!(header.has_extension_headers());
683
684 assert_eq!(header.total_length(), 40 + 24 + payload_data.len());
688 assert_eq!(header.payload_length(), 24 + payload_data.len());
689
690 let total_header_len = header.total_header_len(&packet, packet.len());
692 assert!(header.total_length() >= total_header_len);
693 }
694
695 #[test]
696 fn test_ipv6_from_bytes_with_hopbyhop_extension() {
697 let mut packet = create_test_packet();
698
699 packet[6] = IPV6_NEXT_HOPBYHOP.into();
701
702 packet.push(IPV6_NEXT_UDP.into()); packet.push(0); packet.push(1); packet.push(4); packet.extend_from_slice(&[0, 0, 0, 0]); let payload_data = b"UDP payload";
711 packet.extend_from_slice(payload_data);
712
713 let total_payload = 8 + payload_data.len();
715 packet[4] = ((total_payload >> 8) & 0xFF) as u8;
716 packet[5] = (total_payload & 0xFF) as u8;
717
718 let result = Ipv6Header::from_bytes(&packet);
720 assert!(result.is_ok());
721
722 let (header, payload) = result.unwrap();
723
724 assert_eq!(payload.len(), payload_data.len());
727 assert_eq!(payload, payload_data);
728
729 assert_eq!(header.next_header(), IpProto::IPV6_HOPOPT);
731 assert!(header.has_extension_headers());
732
733 assert_eq!(header.total_length(), 40 + 8 + payload_data.len());
735 assert_eq!(header.payload_length(), 8 + payload_data.len());
736
737 let total_header_len = header.total_header_len(&packet, packet.len());
739 assert!(header.total_length() >= total_header_len);
740 }
741
742 #[test]
743 fn test_ipv6_multiple_chained_extension_headers() {
744 let mut packet = create_test_packet();
745
746 packet[6] = IPV6_NEXT_HOPBYHOP.into();
748
749 packet.push(IPV6_NEXT_ROUTING.into()); packet.push(0); packet.push(1); packet.push(4); packet.extend_from_slice(&[0, 0, 0, 0]); packet.push(IPV6_NEXT_DSTOPTS.into()); packet.push(2); packet.push(0); packet.push(1); packet.extend_from_slice(&[0, 0, 0, 0]); packet.extend_from_slice(&[
764 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765 0x00, 0x03,
766 ]);
767
768 packet.push(IPV6_NEXT_TCP.into()); packet.push(0); packet.push(1); packet.push(4); packet.extend_from_slice(&[0, 0, 0, 0]); let payload_data = b"TCP payload after multiple extension headers";
777 packet.extend_from_slice(payload_data);
778
779 let total_payload = 8 + 24 + 8 + payload_data.len();
781 packet[4] = ((total_payload >> 8) & 0xFF) as u8;
782 packet[5] = (total_payload & 0xFF) as u8;
783
784 let result = Ipv6Header::from_bytes(&packet);
786 assert!(result.is_ok());
787
788 let (header, payload) = result.unwrap();
789
790 assert_eq!(payload.len(), payload_data.len());
793 assert_eq!(payload, payload_data);
794
795 assert_eq!(header.next_header(), IpProto::IPV6_HOPOPT);
797 assert!(header.has_extension_headers());
798
799 assert_eq!(header.total_header_len(&packet, packet.len()), 80);
801
802 let result = header.upper_layer_protocol(&packet, packet.len());
804 assert_eq!(result, Some((IpProto::TCP, false)));
805
806 assert_eq!(header.total_length(), 40 + 8 + 24 + 8 + payload_data.len());
809 assert_eq!(header.payload_length(), 8 + 24 + 8 + payload_data.len());
810
811 let total_header_len = header.total_header_len(&packet, packet.len());
813 assert!(header.total_length() >= total_header_len);
814 assert_eq!(header.total_length(), total_header_len + payload_data.len());
815 }
816
817 #[test]
818 fn test_ipv6_routing_extension_header() {
819 let mut packet = create_test_packet();
820
821 packet[6] = IPV6_NEXT_ROUTING.into();
823
824 packet.push(IPV6_NEXT_TCP.into()); packet.push(2); packet.push(0); packet.push(1); packet.extend_from_slice(&[0, 0, 0, 0]); packet.extend_from_slice(&[
834 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835 0x00, 0x03,
836 ]);
837
838 packet[4] = 0;
840 packet[5] = 24;
841
842 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
843
844 assert!(header.has_extension_headers());
846 assert!(!header.is_transport_protocol());
847
848 assert_eq!(header.total_header_len(&packet, packet.len()), 64);
850
851 let result = header.upper_layer_protocol(&packet, packet.len());
853 assert_eq!(result, Some((IpProto::TCP, false)));
854
855 let total_header_len = header.total_header_len(&packet, packet.len());
857 assert!(header.total_length() >= total_header_len);
858 assert_eq!(header.total_length(), 40 + 24); assert_eq!(header.payload_length(), 24);
860 }
861
862 #[test]
863 fn test_ipv6_hopbyhop_extension_header() {
864 let mut packet = create_test_packet();
865
866 packet[6] = IPV6_NEXT_HOPBYHOP.into();
868
869 packet.push(IPV6_NEXT_UDP.into()); packet.push(0); packet.push(1); packet.push(4); packet.extend_from_slice(&[0, 0, 0, 0]); packet[4] = 0;
880 packet[5] = 8;
881
882 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
883
884 assert!(header.has_extension_headers());
886 assert!(!header.is_transport_protocol());
887
888 assert_eq!(header.total_header_len(&packet, packet.len()), 48);
890
891 let result = header.upper_layer_protocol(&packet, packet.len());
893 assert_eq!(result, Some((IpProto::UDP, false)));
894
895 let total_header_len = header.total_header_len(&packet, packet.len());
897 assert!(header.total_length() >= total_header_len);
898 assert_eq!(header.total_length(), 40 + 8); assert_eq!(header.payload_length(), 8);
900 }
901
902 #[test]
903 fn test_ipv6_total_len_includes_extension_headers() {
904 let mut packet = create_test_packet();
906
907 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
909 assert_eq!(header.total_len(&packet), 40);
910
911 packet = create_test_packet();
913 packet[6] = IPV6_NEXT_HOPBYHOP.into();
914 packet.push(IPV6_NEXT_TCP.into());
915 packet.push(0);
916 packet.extend_from_slice(&[1, 4, 0, 0, 0, 0]);
917 packet[4] = 0;
918 packet[5] = 8;
919
920 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
921 assert_eq!(header.total_len(&packet), 48); packet = create_test_packet();
925 packet[6] = IPV6_NEXT_ROUTING.into();
926 packet.push(IPV6_NEXT_TCP.into());
927 packet.push(2);
928 packet.push(0);
929 packet.push(1);
930 packet.extend_from_slice(&[0, 0, 0, 0]);
931 packet.extend_from_slice(&[
932 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
933 0x00, 0x03,
934 ]);
935 packet[4] = 0;
936 packet[5] = 24;
937
938 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
939 assert_eq!(header.total_len(&packet), 64); packet = create_test_packet();
943 packet[6] = IPV6_NEXT_HOPBYHOP.into();
944 packet.push(IPV6_NEXT_ROUTING.into());
946 packet.push(0);
947 packet.extend_from_slice(&[1, 4, 0, 0, 0, 0]);
948 packet.push(IPV6_NEXT_TCP.into());
950 packet.push(2);
951 packet.push(0);
952 packet.push(1);
953 packet.extend_from_slice(&[0, 0, 0, 0]);
954 packet.extend_from_slice(&[
955 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
956 0x00, 0x03,
957 ]);
958 packet[4] = 0;
959 packet[5] = 32;
960
961 let (header, _) = Ipv6Header::from_bytes(&packet).unwrap();
962 assert_eq!(header.total_len(&packet), 72); }
964
965 fn create_test_header() -> Ipv6Header {
967 Ipv6Header {
968 ver_tc_flow: [0x60, 0x00, 0x00, 0x00], payload_length: U16::new(0),
970 next_header: IpProto::TCP,
971 hop_limit: 64,
972 src_ip: [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
973 dst_ip: [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
974 }
975 }
976
977 fn create_test_packet() -> Vec<u8> {
979 let mut packet = Vec::new();
980
981 packet.extend_from_slice(&[0x60, 0x00, 0x00, 0x00]);
983
984 packet.extend_from_slice(&[0x00, 0x00]);
986
987 packet.push(IpProto::TCP.into());
989
990 packet.push(64);
992
993 packet.extend_from_slice(&[
995 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 0x00, 0x01,
997 ]);
998
999 packet.extend_from_slice(&[
1001 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1002 0x00, 0x02,
1003 ]);
1004
1005 packet
1006 }
1007
1008 #[test]
1009 fn test_ipv6_header_ext_no_extensions() {
1010 let packet = create_test_packet();
1011 let (header_ext, _) = Ipv6Header::from_bytes(&packet).unwrap();
1012
1013 assert_eq!(header_ext.raw_extensions.len(), 0);
1014 assert!(!header_ext.should_parse_extensions());
1015 assert_eq!(header_ext.ext_headers_len(), 40); assert_eq!(header_ext.version(), 6);
1019 assert_eq!(header_ext.next_header(), IPV6_NEXT_TCP);
1020 assert_eq!(header_ext.hop_limit(), 64);
1021 }
1022
1023 #[test]
1024 fn test_ipv6_header_ext_with_fragment() {
1025 let mut packet = create_test_packet();
1026
1027 packet[6] = IPV6_NEXT_FRAGMENT.into();
1029
1030 packet[4] = 0;
1032 packet[5] = 8;
1033
1034 packet.extend_from_slice(&[
1036 IpProto::TCP.into(), 0, 0x00,
1039 0x01, 0x00,
1041 0x00,
1042 0x00,
1043 0x01, ]);
1045
1046 let (header_ext, _) = Ipv6Header::from_bytes(&packet).unwrap();
1047
1048 assert_eq!(header_ext.raw_extensions.len(), 8);
1049 assert!(header_ext.should_parse_extensions());
1050 assert_eq!(header_ext.ext_headers_len(), 48); let exts: Vec<_> = header_ext
1054 .extensions()
1055 .collect::<Result<Vec<_>, _>>()
1056 .unwrap();
1057 assert_eq!(exts.len(), 1);
1058
1059 use crate::packet::ipv6::ext::Ipv6ExtensionHeader;
1060 match &exts[0] {
1061 Ipv6ExtensionHeader::Fragment {
1062 next_header,
1063 fragment_offset,
1064 more_fragments,
1065 identification,
1066 } => {
1067 assert_eq!(*next_header, IpProto::TCP);
1068 assert_eq!(*fragment_offset, 0);
1069 assert!(*more_fragments);
1070 assert_eq!(*identification, 1);
1071 }
1072 _ => panic!("Expected Fragment header"),
1073 }
1074 }
1075
1076 #[test]
1077 fn test_ipv6_header_ext_with_hop_by_hop() {
1078 let mut packet = create_test_packet();
1079
1080 packet[6] = IPV6_NEXT_HOPBYHOP.into();
1082
1083 packet[4] = 0;
1085 packet[5] = 8;
1086
1087 packet.extend_from_slice(&[
1089 IpProto::TCP.into(), 0, 1,
1092 4,
1093 0,
1094 0,
1095 0,
1096 0, ]);
1098
1099 let (header_ext, _) = Ipv6Header::from_bytes(&packet).unwrap();
1100
1101 assert_eq!(header_ext.raw_extensions.len(), 8);
1102 assert_eq!(header_ext.ext_headers_len(), 48);
1103
1104 let exts: Vec<_> = header_ext
1106 .extensions()
1107 .collect::<Result<Vec<_>, _>>()
1108 .unwrap();
1109 assert_eq!(exts.len(), 1);
1110
1111 use crate::packet::ipv6::ext::Ipv6ExtensionHeader;
1112 match &exts[0] {
1113 Ipv6ExtensionHeader::HopByHop {
1114 next_header,
1115 options,
1116 } => {
1117 assert_eq!(*next_header, IpProto::TCP);
1118 assert_eq!(options.len(), 6);
1119 }
1120 _ => panic!("Expected HopByHop header"),
1121 }
1122 }
1123
1124 #[test]
1125 fn test_ipv6_header_ext_multiple_extensions() {
1126 let mut packet = create_test_packet();
1127
1128 packet[6] = IPV6_NEXT_HOPBYHOP.into();
1130
1131 packet[4] = 0;
1133 packet[5] = 16;
1134
1135 packet.extend_from_slice(&[
1137 IPV6_NEXT_FRAGMENT.into(), 0, 1,
1140 4,
1141 0,
1142 0,
1143 0,
1144 0, ]);
1146
1147 packet.extend_from_slice(&[
1149 IpProto::TCP.into(), 0, 0x00,
1152 0x00, 0x00,
1154 0x00,
1155 0x00,
1156 0x42, ]);
1158
1159 let (header_ext, _) = Ipv6Header::from_bytes(&packet).unwrap();
1160
1161 assert_eq!(header_ext.raw_extensions.len(), 16);
1162 assert_eq!(header_ext.ext_headers_len(), 56); let exts: Vec<_> = header_ext
1166 .extensions()
1167 .collect::<Result<Vec<_>, _>>()
1168 .unwrap();
1169 assert_eq!(exts.len(), 2);
1170
1171 use crate::packet::ipv6::ext::Ipv6ExtensionHeader;
1172 assert!(matches!(&exts[0], Ipv6ExtensionHeader::HopByHop { .. }));
1173 assert!(matches!(&exts[1], Ipv6ExtensionHeader::Fragment { .. }));
1174
1175 assert_eq!(exts[0].next_header(), IPV6_NEXT_FRAGMENT);
1177 assert_eq!(exts[1].next_header(), IpProto::TCP);
1178 }
1179
1180 #[test]
1181 fn test_ipv6_header_ext_deref() {
1182 let packet = create_test_packet();
1183 let (header_ext, _) = Ipv6Header::from_bytes(&packet).unwrap();
1184
1185 assert_eq!(header_ext.version(), 6);
1187 assert_eq!(header_ext.traffic_class(), 0);
1188 assert_eq!(header_ext.flow_label(), 0);
1189 assert_eq!(header_ext.payload_length(), 0);
1190 assert_eq!(header_ext.next_header(), IPV6_NEXT_TCP);
1191 assert_eq!(header_ext.hop_limit(), 64);
1192
1193 let src = header_ext.src_ip();
1194 assert_eq!(src.to_string(), "2001:db8::1");
1195
1196 let dst = header_ext.dst_ip();
1197 assert_eq!(dst.to_string(), "2001:db8::2");
1198 }
1199
1200 #[test]
1201 fn test_ipv6_header_ext_with_routing() {
1202 let mut packet = create_test_packet();
1203
1204 packet[6] = IPV6_NEXT_ROUTING.into();
1206
1207 packet[4] = 0;
1209 packet[5] = 8;
1210
1211 packet.extend_from_slice(&[
1213 IpProto::TCP.into(), 0, 0, 0, 0,
1218 0,
1219 0,
1220 0, ]);
1222
1223 let (header_ext, _) = Ipv6Header::from_bytes(&packet).unwrap();
1224
1225 assert_eq!(header_ext.raw_extensions.len(), 8);
1226
1227 let exts: Vec<_> = header_ext
1229 .extensions()
1230 .collect::<Result<Vec<_>, _>>()
1231 .unwrap();
1232 assert_eq!(exts.len(), 1);
1233
1234 use crate::packet::ipv6::ext::Ipv6ExtensionHeader;
1235 match &exts[0] {
1236 Ipv6ExtensionHeader::Routing {
1237 next_header,
1238 routing_type,
1239 segments_left,
1240 data,
1241 } => {
1242 assert_eq!(*next_header, IpProto::TCP);
1243 assert_eq!(*routing_type, 0);
1244 assert_eq!(*segments_left, 0);
1245 assert_eq!(data.len(), 4);
1246 }
1247 _ => panic!("Expected Routing header"),
1248 }
1249 }
1250}