1use byteorder::{ByteOrder, NetworkEndian};
2use core::fmt;
3
4use super::{Error, Result};
5use crate::phy::ChecksumCapabilities;
6use crate::wire::ip::{checksum, pretty_print_ip_payload};
7
8pub use super::IpProtocol as Protocol;
9
10pub const MIN_MTU: usize = 576;
23
24pub const MULTICAST_ALL_SYSTEMS: Address = Address::new(224, 0, 0, 1);
26
27pub const MULTICAST_ALL_ROUTERS: Address = Address::new(224, 0, 0, 2);
29
30const MINIMUM_IHL_BYTES: u8 = 20;
33
34#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36pub struct Key {
37 id: u16,
38 src_addr: Address,
39 dst_addr: Address,
40 protocol: Protocol,
41}
42
43pub use core::net::Ipv4Addr as Address;
44
45pub(crate) trait AddressExt {
46 fn x_is_unicast(&self) -> bool;
50
51 fn prefix_len(&self) -> Option<u8>;
54}
55
56impl AddressExt for Address {
57 fn x_is_unicast(&self) -> bool {
59 !(self.is_broadcast() || self.is_multicast() || self.is_unspecified())
60 }
61
62 fn prefix_len(&self) -> Option<u8> {
63 let mut ones = true;
64 let mut prefix_len = 0;
65 for byte in self.octets() {
66 let mut mask = 0x80;
67 for _ in 0..8 {
68 let one = byte & mask != 0;
69 if ones {
70 if one {
72 prefix_len += 1;
73 } else {
74 ones = false;
75 }
76 } else if one {
77 return None;
79 }
80 mask >>= 1;
81 }
82 }
83 Some(prefix_len)
84 }
85}
86
87#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
90pub struct Cidr {
91 address: Address,
92 prefix_len: u8,
93}
94
95impl Cidr {
96 pub const fn new(address: Address, prefix_len: u8) -> Cidr {
101 assert!(prefix_len <= 32);
102 Cidr {
103 address,
104 prefix_len,
105 }
106 }
107
108 pub fn from_netmask(addr: Address, netmask: Address) -> Result<Cidr> {
110 let netmask = netmask.to_bits();
111 if netmask.leading_zeros() == 0 && netmask.trailing_zeros() == netmask.count_zeros() {
112 Ok(Cidr {
113 address: addr,
114 prefix_len: netmask.count_ones() as u8,
115 })
116 } else {
117 Err(Error)
118 }
119 }
120
121 pub const fn address(&self) -> Address {
123 self.address
124 }
125
126 pub const fn prefix_len(&self) -> u8 {
128 self.prefix_len
129 }
130
131 pub const fn netmask(&self) -> Address {
133 if self.prefix_len == 0 {
134 return Address::new(0, 0, 0, 0);
135 }
136
137 let number = 0xffffffffu32 << (32 - self.prefix_len);
138 Address::from_bits(number)
139 }
140
141 pub fn broadcast(&self) -> Option<Address> {
143 let network = self.network();
144
145 if network.prefix_len == 31 || network.prefix_len == 32 {
146 return None;
147 }
148
149 let network_number = network.address.to_bits();
150 let number = network_number | 0xffffffffu32 >> network.prefix_len;
151 Some(Address::from_bits(number))
152 }
153
154 pub const fn network(&self) -> Cidr {
156 Cidr {
157 address: Address::from_bits(self.address.to_bits() & self.netmask().to_bits()),
158 prefix_len: self.prefix_len,
159 }
160 }
161
162 pub fn contains_addr(&self, addr: &Address) -> bool {
165 self.address.to_bits() & self.netmask().to_bits()
166 == addr.to_bits() & self.netmask().to_bits()
167 }
168
169 pub fn contains_subnet(&self, subnet: &Cidr) -> bool {
172 self.prefix_len <= subnet.prefix_len && self.contains_addr(&subnet.address)
173 }
174}
175
176impl fmt::Display for Cidr {
177 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178 write!(f, "{}/{}", self.address, self.prefix_len)
179 }
180}
181
182#[cfg(feature = "defmt")]
183impl defmt::Format for Cidr {
184 fn format(&self, f: defmt::Formatter) {
185 defmt::write!(f, "{}/{=u8}", self.address, self.prefix_len);
186 }
187}
188
189#[derive(Debug, PartialEq, Eq, Clone)]
191#[cfg_attr(feature = "defmt", derive(defmt::Format))]
192pub struct Packet<T: AsRef<[u8]>> {
193 buffer: T,
194}
195
196mod field {
197 use crate::wire::field::*;
198
199 pub const VER_IHL: usize = 0;
200 pub const DSCP_ECN: usize = 1;
201 pub const LENGTH: Field = 2..4;
202 pub const IDENT: Field = 4..6;
203 pub const FLG_OFF: Field = 6..8;
204 pub const TTL: usize = 8;
205 pub const PROTOCOL: usize = 9;
206 pub const CHECKSUM: Field = 10..12;
207 pub const SRC_ADDR: Field = 12..16;
208 pub const DST_ADDR: Field = 16..20;
209}
210
211pub const HEADER_LEN: usize = field::DST_ADDR.end;
212
213impl<T: AsRef<[u8]>> Packet<T> {
214 pub const fn new_unchecked(buffer: T) -> Packet<T> {
216 Packet { buffer }
217 }
218
219 pub fn new_checked(buffer: T) -> Result<Packet<T>> {
224 let packet = Self::new_unchecked(buffer);
225 packet.check_len()?;
226 Ok(packet)
227 }
228
229 #[allow(clippy::if_same_then_else)]
241 pub fn check_len(&self) -> Result<()> {
242 let len = self.buffer.as_ref().len();
243 if len < field::DST_ADDR.end {
244 Err(Error)
245 } else if len < self.header_len() as usize {
246 Err(Error)
247 } else if self.header_len() as u16 > self.total_len() {
248 Err(Error)
249 } else if len < self.total_len() as usize {
250 Err(Error)
251 } else if self.header_len() < MINIMUM_IHL_BYTES {
252 Err(Error)
253 } else {
254 Ok(())
255 }
256 }
257
258 pub fn into_inner(self) -> T {
260 self.buffer
261 }
262
263 #[inline]
265 pub fn version(&self) -> u8 {
266 let data = self.buffer.as_ref();
267 data[field::VER_IHL] >> 4
268 }
269
270 #[inline]
272 pub fn header_len(&self) -> u8 {
273 let data = self.buffer.as_ref();
274 (data[field::VER_IHL] & 0x0f) * 4
275 }
276
277 pub fn dscp(&self) -> u8 {
279 let data = self.buffer.as_ref();
280 data[field::DSCP_ECN] >> 2
281 }
282
283 pub fn ecn(&self) -> u8 {
285 let data = self.buffer.as_ref();
286 data[field::DSCP_ECN] & 0x03
287 }
288
289 #[inline]
291 pub fn total_len(&self) -> u16 {
292 let data = self.buffer.as_ref();
293 NetworkEndian::read_u16(&data[field::LENGTH])
294 }
295
296 #[inline]
298 pub fn ident(&self) -> u16 {
299 let data = self.buffer.as_ref();
300 NetworkEndian::read_u16(&data[field::IDENT])
301 }
302
303 #[inline]
305 pub fn dont_frag(&self) -> bool {
306 let data = self.buffer.as_ref();
307 NetworkEndian::read_u16(&data[field::FLG_OFF]) & 0x4000 != 0
308 }
309
310 #[inline]
312 pub fn more_frags(&self) -> bool {
313 let data = self.buffer.as_ref();
314 NetworkEndian::read_u16(&data[field::FLG_OFF]) & 0x2000 != 0
315 }
316
317 #[inline]
319 pub fn frag_offset(&self) -> u16 {
320 let data = self.buffer.as_ref();
321 NetworkEndian::read_u16(&data[field::FLG_OFF]) << 3
322 }
323
324 #[inline]
326 pub fn hop_limit(&self) -> u8 {
327 let data = self.buffer.as_ref();
328 data[field::TTL]
329 }
330
331 #[inline]
333 pub fn next_header(&self) -> Protocol {
334 let data = self.buffer.as_ref();
335 Protocol::from(data[field::PROTOCOL])
336 }
337
338 #[inline]
340 pub fn checksum(&self) -> u16 {
341 let data = self.buffer.as_ref();
342 NetworkEndian::read_u16(&data[field::CHECKSUM])
343 }
344
345 #[inline]
347 pub fn src_addr(&self) -> Address {
348 let data = self.buffer.as_ref();
349 Address::from_octets(data[field::SRC_ADDR].try_into().unwrap())
350 }
351
352 #[inline]
354 pub fn dst_addr(&self) -> Address {
355 let data = self.buffer.as_ref();
356 Address::from_octets(data[field::DST_ADDR].try_into().unwrap())
357 }
358
359 pub fn verify_checksum(&self) -> bool {
364 if cfg!(fuzzing) {
365 return true;
366 }
367
368 let data = self.buffer.as_ref();
369 checksum::data(&data[..self.header_len() as usize]) == !0
370 }
371
372 pub fn get_key(&self) -> Key {
374 Key {
375 id: self.ident(),
376 src_addr: self.src_addr(),
377 dst_addr: self.dst_addr(),
378 protocol: self.next_header(),
379 }
380 }
381}
382
383impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
384 #[inline]
386 pub fn payload(&self) -> &'a [u8] {
387 let range = self.header_len() as usize..self.total_len() as usize;
388 let data = self.buffer.as_ref();
389 &data[range]
390 }
391}
392
393impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
394 #[inline]
396 pub fn set_version(&mut self, value: u8) {
397 let data = self.buffer.as_mut();
398 data[field::VER_IHL] = (data[field::VER_IHL] & !0xf0) | (value << 4);
399 }
400
401 #[inline]
403 pub fn set_header_len(&mut self, value: u8) {
404 let data = self.buffer.as_mut();
405 data[field::VER_IHL] = (data[field::VER_IHL] & !0x0f) | ((value / 4) & 0x0f);
406 }
407
408 pub fn set_dscp(&mut self, value: u8) {
410 let data = self.buffer.as_mut();
411 data[field::DSCP_ECN] = (data[field::DSCP_ECN] & !0xfc) | (value << 2)
412 }
413
414 pub fn set_ecn(&mut self, value: u8) {
416 let data = self.buffer.as_mut();
417 data[field::DSCP_ECN] = (data[field::DSCP_ECN] & !0x03) | (value & 0x03)
418 }
419
420 #[inline]
422 pub fn set_total_len(&mut self, value: u16) {
423 let data = self.buffer.as_mut();
424 NetworkEndian::write_u16(&mut data[field::LENGTH], value)
425 }
426
427 #[inline]
429 pub fn set_ident(&mut self, value: u16) {
430 let data = self.buffer.as_mut();
431 NetworkEndian::write_u16(&mut data[field::IDENT], value)
432 }
433
434 #[inline]
436 pub fn clear_flags(&mut self) {
437 let data = self.buffer.as_mut();
438 let raw = NetworkEndian::read_u16(&data[field::FLG_OFF]);
439 let raw = raw & !0xe000;
440 NetworkEndian::write_u16(&mut data[field::FLG_OFF], raw);
441 }
442
443 #[inline]
445 pub fn set_dont_frag(&mut self, value: bool) {
446 let data = self.buffer.as_mut();
447 let raw = NetworkEndian::read_u16(&data[field::FLG_OFF]);
448 let raw = if value { raw | 0x4000 } else { raw & !0x4000 };
449 NetworkEndian::write_u16(&mut data[field::FLG_OFF], raw);
450 }
451
452 #[inline]
454 pub fn set_more_frags(&mut self, value: bool) {
455 let data = self.buffer.as_mut();
456 let raw = NetworkEndian::read_u16(&data[field::FLG_OFF]);
457 let raw = if value { raw | 0x2000 } else { raw & !0x2000 };
458 NetworkEndian::write_u16(&mut data[field::FLG_OFF], raw);
459 }
460
461 #[inline]
463 pub fn set_frag_offset(&mut self, value: u16) {
464 let data = self.buffer.as_mut();
465 let raw = NetworkEndian::read_u16(&data[field::FLG_OFF]);
466 let raw = (raw & 0xe000) | (value >> 3);
467 NetworkEndian::write_u16(&mut data[field::FLG_OFF], raw);
468 }
469
470 #[inline]
472 pub fn set_hop_limit(&mut self, value: u8) {
473 let data = self.buffer.as_mut();
474 data[field::TTL] = value
475 }
476
477 #[inline]
479 pub fn set_next_header(&mut self, value: Protocol) {
480 let data = self.buffer.as_mut();
481 data[field::PROTOCOL] = value.into()
482 }
483
484 #[inline]
486 pub fn set_checksum(&mut self, value: u16) {
487 let data = self.buffer.as_mut();
488 NetworkEndian::write_u16(&mut data[field::CHECKSUM], value)
489 }
490
491 #[inline]
493 pub fn set_src_addr(&mut self, value: Address) {
494 let data = self.buffer.as_mut();
495 data[field::SRC_ADDR].copy_from_slice(&value.octets())
496 }
497
498 #[inline]
500 pub fn set_dst_addr(&mut self, value: Address) {
501 let data = self.buffer.as_mut();
502 data[field::DST_ADDR].copy_from_slice(&value.octets())
503 }
504
505 pub fn fill_checksum(&mut self) {
507 self.set_checksum(0);
508 let checksum = {
509 let data = self.buffer.as_ref();
510 !checksum::data(&data[..self.header_len() as usize])
511 };
512 self.set_checksum(checksum)
513 }
514
515 #[inline]
517 pub fn payload_mut(&mut self) -> &mut [u8] {
518 let range = self.header_len() as usize..self.total_len() as usize;
519 let data = self.buffer.as_mut();
520 &mut data[range]
521 }
522}
523
524impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
525 fn as_ref(&self) -> &[u8] {
526 self.buffer.as_ref()
527 }
528}
529
530#[derive(Debug, PartialEq, Eq, Clone, Copy)]
532#[cfg_attr(feature = "defmt", derive(defmt::Format))]
533pub struct Repr {
534 pub src_addr: Address,
535 pub dst_addr: Address,
536 pub next_header: Protocol,
537 pub payload_len: usize,
538 pub hop_limit: u8,
539}
540
541impl Repr {
542 pub fn parse<T: AsRef<[u8]> + ?Sized>(
544 packet: &Packet<&T>,
545 checksum_caps: &ChecksumCapabilities,
546 ) -> Result<Repr> {
547 packet.check_len()?;
548 if packet.version() != 4 {
550 return Err(Error);
551 }
552 if checksum_caps.ipv4.rx() && !packet.verify_checksum() {
554 return Err(Error);
555 }
556
557 #[cfg(not(feature = "proto-ipv4-fragmentation"))]
558 if packet.more_frags() || packet.frag_offset() != 0 {
560 return Err(Error);
561 }
562
563 let payload_len = packet.total_len() as usize - packet.header_len() as usize;
564
565 Ok(Repr {
569 src_addr: packet.src_addr(),
570 dst_addr: packet.dst_addr(),
571 next_header: packet.next_header(),
572 payload_len,
573 hop_limit: packet.hop_limit(),
574 })
575 }
576
577 pub const fn buffer_len(&self) -> usize {
579 field::DST_ADDR.end
581 }
582
583 pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(
585 &self,
586 packet: &mut Packet<T>,
587 checksum_caps: &ChecksumCapabilities,
588 ) {
589 packet.set_version(4);
590 packet.set_header_len(field::DST_ADDR.end as u8);
591 packet.set_dscp(0);
592 packet.set_ecn(0);
593 #[cfg(not(feature = "segmentation-offload"))]
594 let total_len = packet.header_len() as u16 + self.payload_len as u16;
595 #[cfg(feature = "segmentation-offload")]
596 let total_len = u16::try_from(self.payload_len)
600 .ok()
601 .and_then(|payload_len: u16| payload_len.checked_add(packet.header_len() as u16))
602 .unwrap_or(0);
603 packet.set_total_len(total_len);
604 packet.set_ident(0);
605 packet.clear_flags();
606 packet.set_more_frags(false);
607 packet.set_dont_frag(true);
608 packet.set_frag_offset(0);
609 packet.set_hop_limit(self.hop_limit);
610 packet.set_next_header(self.next_header);
611 packet.set_src_addr(self.src_addr);
612 packet.set_dst_addr(self.dst_addr);
613
614 if checksum_caps.ipv4.tx() {
615 packet.fill_checksum();
616 } else {
617 packet.set_checksum(0);
620 }
621 }
622}
623
624impl<T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&T> {
625 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
626 match Repr::parse(self, &ChecksumCapabilities::ignored()) {
627 Ok(repr) => write!(f, "{repr}"),
628 Err(err) => {
629 write!(f, "IPv4 ({err})")?;
630 write!(
631 f,
632 " src={} dst={} proto={} hop_limit={}",
633 self.src_addr(),
634 self.dst_addr(),
635 self.next_header(),
636 self.hop_limit()
637 )?;
638 if self.version() != 4 {
639 write!(f, " ver={}", self.version())?;
640 }
641 if self.header_len() != 20 {
642 write!(f, " hlen={}", self.header_len())?;
643 }
644 if self.dscp() != 0 {
645 write!(f, " dscp={}", self.dscp())?;
646 }
647 if self.ecn() != 0 {
648 write!(f, " ecn={}", self.ecn())?;
649 }
650 write!(f, " tlen={}", self.total_len())?;
651 if self.dont_frag() {
652 write!(f, " df")?;
653 }
654 if self.more_frags() {
655 write!(f, " mf")?;
656 }
657 if self.frag_offset() != 0 {
658 write!(f, " off={}", self.frag_offset())?;
659 }
660 if self.more_frags() || self.frag_offset() != 0 {
661 write!(f, " id={}", self.ident())?;
662 }
663 Ok(())
664 }
665 }
666 }
667}
668
669impl fmt::Display for Repr {
670 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
671 write!(
672 f,
673 "IPv4 src={} dst={} proto={}",
674 self.src_addr, self.dst_addr, self.next_header
675 )
676 }
677}
678
679use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
680
681impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
682 fn pretty_print(
683 buffer: &dyn AsRef<[u8]>,
684 f: &mut fmt::Formatter,
685 indent: &mut PrettyIndent,
686 ) -> fmt::Result {
687 use crate::wire::ip::checksum::format_checksum;
688
689 let checksum_caps = ChecksumCapabilities::ignored();
690
691 let (ip_repr, payload) = match Packet::new_checked(buffer) {
692 Err(err) => return write!(f, "{indent}({err})"),
693 Ok(ip_packet) => match Repr::parse(&ip_packet, &checksum_caps) {
694 Err(_) => return Ok(()),
695 Ok(ip_repr) => {
696 if ip_packet.more_frags() || ip_packet.frag_offset() != 0 {
697 write!(
698 f,
699 "{}IPv4 Fragment more_frags={} offset={}",
700 indent,
701 ip_packet.more_frags(),
702 ip_packet.frag_offset()
703 )?;
704 return Ok(());
705 } else {
706 write!(f, "{indent}{ip_repr}")?;
707 format_checksum(f, ip_packet.verify_checksum(), false)?;
708 (ip_repr, ip_packet.payload())
709 }
710 }
711 },
712 };
713
714 pretty_print_ip_payload(f, indent, ip_repr, payload)
715 }
716}
717
718#[cfg(test)]
719pub(crate) mod test {
720 use super::*;
721
722 #[allow(unused)]
723 pub(crate) const MOCK_IP_ADDR_1: Address = Address::new(192, 168, 1, 1);
724 #[allow(unused)]
725 pub(crate) const MOCK_IP_ADDR_2: Address = Address::new(192, 168, 1, 2);
726 #[allow(unused)]
727 pub(crate) const MOCK_IP_ADDR_3: Address = Address::new(192, 168, 1, 3);
728 #[allow(unused)]
729 pub(crate) const MOCK_IP_ADDR_4: Address = Address::new(192, 168, 1, 4);
730 #[allow(unused)]
731 pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED;
732
733 static PACKET_BYTES: [u8; 30] = [
734 0x45, 0x00, 0x00, 0x1e, 0x01, 0x02, 0x62, 0x03, 0x1a, 0x01, 0xd5, 0x6e, 0x11, 0x12, 0x13,
735 0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
736 ];
737
738 static PAYLOAD_BYTES: [u8; 10] = [0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff];
739
740 #[test]
741 fn test_deconstruct() {
742 let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
743 assert_eq!(packet.version(), 4);
744 assert_eq!(packet.header_len(), 20);
745 assert_eq!(packet.dscp(), 0);
746 assert_eq!(packet.ecn(), 0);
747 assert_eq!(packet.total_len(), 30);
748 assert_eq!(packet.ident(), 0x102);
749 assert!(packet.more_frags());
750 assert!(packet.dont_frag());
751 assert_eq!(packet.frag_offset(), 0x203 * 8);
752 assert_eq!(packet.hop_limit(), 0x1a);
753 assert_eq!(packet.next_header(), Protocol::Icmp);
754 assert_eq!(packet.checksum(), 0xd56e);
755 assert_eq!(packet.src_addr(), Address::new(0x11, 0x12, 0x13, 0x14));
756 assert_eq!(packet.dst_addr(), Address::new(0x21, 0x22, 0x23, 0x24));
757 assert!(packet.verify_checksum());
758 assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]);
759 }
760
761 #[test]
762 fn test_construct() {
763 let mut bytes = vec![0xa5; 30];
764 let mut packet = Packet::new_unchecked(&mut bytes);
765 packet.set_version(4);
766 packet.set_header_len(20);
767 packet.clear_flags();
768 packet.set_dscp(0);
769 packet.set_ecn(0);
770 packet.set_total_len(30);
771 packet.set_ident(0x102);
772 packet.set_more_frags(true);
773 packet.set_dont_frag(true);
774 packet.set_frag_offset(0x203 * 8);
775 packet.set_hop_limit(0x1a);
776 packet.set_next_header(Protocol::Icmp);
777 packet.set_src_addr(Address::new(0x11, 0x12, 0x13, 0x14));
778 packet.set_dst_addr(Address::new(0x21, 0x22, 0x23, 0x24));
779 packet.fill_checksum();
780 packet.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
781 assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]);
782 }
783
784 #[test]
785 fn test_overlong() {
786 let mut bytes = vec![];
787 bytes.extend(&PACKET_BYTES[..]);
788 bytes.push(0);
789
790 assert_eq!(
791 Packet::new_unchecked(&bytes).payload().len(),
792 PAYLOAD_BYTES.len()
793 );
794 assert_eq!(
795 Packet::new_unchecked(&mut bytes).payload_mut().len(),
796 PAYLOAD_BYTES.len()
797 );
798 }
799
800 #[test]
801 fn test_total_len_overflow() {
802 let mut bytes = vec![];
803 bytes.extend(&PACKET_BYTES[..]);
804 Packet::new_unchecked(&mut bytes).set_total_len(128);
805
806 assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error);
807 }
808
809 static REPR_PACKET_BYTES: [u8; 24] = [
810 0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0xd2, 0x79, 0x11, 0x12, 0x13,
811 0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0xff,
812 ];
813
814 static REPR_PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
815
816 const fn packet_repr() -> Repr {
817 Repr {
818 src_addr: Address::new(0x11, 0x12, 0x13, 0x14),
819 dst_addr: Address::new(0x21, 0x22, 0x23, 0x24),
820 next_header: Protocol::Icmp,
821 payload_len: 4,
822 hop_limit: 64,
823 }
824 }
825
826 #[test]
827 fn test_parse() {
828 let packet = Packet::new_unchecked(&REPR_PACKET_BYTES[..]);
829 let repr = Repr::parse(&packet, &ChecksumCapabilities::default()).unwrap();
830 assert_eq!(repr, packet_repr());
831 }
832
833 #[test]
834 fn test_parse_bad_version() {
835 let mut bytes = vec![0; 24];
836 bytes.copy_from_slice(&REPR_PACKET_BYTES[..]);
837 let mut packet = Packet::new_unchecked(&mut bytes);
838 packet.set_version(6);
839 packet.fill_checksum();
840 let packet = Packet::new_unchecked(&*packet.into_inner());
841 assert_eq!(
842 Repr::parse(&packet, &ChecksumCapabilities::default()),
843 Err(Error)
844 );
845 }
846
847 #[test]
848 fn test_parse_total_len_less_than_header_len() {
849 let mut bytes = vec![0; 40];
850 bytes[0] = 0x09;
851 assert_eq!(Packet::new_checked(&mut bytes), Err(Error));
852 }
853
854 #[test]
855 fn test_parse_small_ihl() {
856 let mut bytes = vec![0; 24];
857 bytes.copy_from_slice(&REPR_PACKET_BYTES[..]);
858 let mut packet = Packet::new_unchecked(&mut bytes);
859 packet.set_header_len(16);
860
861 assert_eq!(Packet::new_checked(&mut bytes), Err(Error));
862 }
863
864 #[test]
865 fn test_emit() {
866 let repr = packet_repr();
867 let mut bytes = vec![0xa5; repr.buffer_len() + REPR_PAYLOAD_BYTES.len()];
868 let mut packet = Packet::new_unchecked(&mut bytes);
869 repr.emit(&mut packet, &ChecksumCapabilities::default());
870 packet.payload_mut().copy_from_slice(&REPR_PAYLOAD_BYTES);
871 assert_eq!(&*packet.into_inner(), &REPR_PACKET_BYTES[..]);
872 }
873
874 #[test]
875 fn test_unspecified() {
876 assert!(Address::UNSPECIFIED.is_unspecified());
877 assert!(!Address::UNSPECIFIED.is_broadcast());
878 assert!(!Address::UNSPECIFIED.is_multicast());
879 assert!(!Address::UNSPECIFIED.is_link_local());
880 assert!(!Address::UNSPECIFIED.is_loopback());
881 }
882
883 #[test]
884 fn test_broadcast() {
885 assert!(!Address::BROADCAST.is_unspecified());
886 assert!(Address::BROADCAST.is_broadcast());
887 assert!(!Address::BROADCAST.is_multicast());
888 assert!(!Address::BROADCAST.is_link_local());
889 assert!(!Address::BROADCAST.is_loopback());
890 }
891
892 #[test]
893 fn test_cidr() {
894 let cidr = Cidr::new(Address::new(192, 168, 1, 10), 24);
895
896 let inside_subnet = [
897 [192, 168, 1, 0],
898 [192, 168, 1, 1],
899 [192, 168, 1, 2],
900 [192, 168, 1, 10],
901 [192, 168, 1, 127],
902 [192, 168, 1, 255],
903 ];
904
905 let outside_subnet = [
906 [192, 168, 0, 0],
907 [127, 0, 0, 1],
908 [192, 168, 2, 0],
909 [192, 168, 0, 255],
910 [0, 0, 0, 0],
911 [255, 255, 255, 255],
912 ];
913
914 let subnets = [
915 ([192, 168, 1, 0], 32),
916 ([192, 168, 1, 255], 24),
917 ([192, 168, 1, 10], 30),
918 ];
919
920 let not_subnets = [
921 ([192, 168, 1, 10], 23),
922 ([127, 0, 0, 1], 8),
923 ([192, 168, 1, 0], 0),
924 ([192, 168, 0, 255], 32),
925 ];
926
927 for addr in inside_subnet.iter().map(|a| Address::from_octets(*a)) {
928 assert!(cidr.contains_addr(&addr));
929 }
930
931 for addr in outside_subnet.iter().map(|a| Address::from_octets(*a)) {
932 assert!(!cidr.contains_addr(&addr));
933 }
934
935 for subnet in subnets
936 .iter()
937 .map(|&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p))
938 {
939 assert!(cidr.contains_subnet(&subnet));
940 }
941
942 for subnet in not_subnets
943 .iter()
944 .map(|&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p))
945 {
946 assert!(!cidr.contains_subnet(&subnet));
947 }
948
949 let cidr_without_prefix = Cidr::new(cidr.address(), 0);
950 assert!(cidr_without_prefix.contains_addr(&Address::new(127, 0, 0, 1)));
951 }
952
953 #[test]
954 fn test_cidr_from_netmask() {
955 assert!(Cidr::from_netmask(Address::new(0, 0, 0, 0), Address::new(1, 0, 2, 0)).is_err());
956 assert!(Cidr::from_netmask(Address::new(0, 0, 0, 0), Address::new(0, 0, 0, 0)).is_err());
957 assert_eq!(
958 Cidr::from_netmask(Address::new(0, 0, 0, 1), Address::new(255, 255, 255, 0)).unwrap(),
959 Cidr::new(Address::new(0, 0, 0, 1), 24)
960 );
961 assert_eq!(
962 Cidr::from_netmask(Address::new(192, 168, 0, 1), Address::new(255, 255, 0, 0)).unwrap(),
963 Cidr::new(Address::new(192, 168, 0, 1), 16)
964 );
965 assert_eq!(
966 Cidr::from_netmask(Address::new(172, 16, 0, 1), Address::new(255, 240, 0, 0)).unwrap(),
967 Cidr::new(Address::new(172, 16, 0, 1), 12)
968 );
969 assert_eq!(
970 Cidr::from_netmask(
971 Address::new(255, 255, 255, 1),
972 Address::new(255, 255, 255, 0)
973 )
974 .unwrap(),
975 Cidr::new(Address::new(255, 255, 255, 1), 24)
976 );
977 assert_eq!(
978 Cidr::from_netmask(
979 Address::new(255, 255, 255, 255),
980 Address::new(255, 255, 255, 255)
981 )
982 .unwrap(),
983 Cidr::new(Address::new(255, 255, 255, 255), 32)
984 );
985 }
986
987 #[test]
988 fn test_cidr_netmask() {
989 assert_eq!(
990 Cidr::new(Address::new(0, 0, 0, 0), 0).netmask(),
991 Address::new(0, 0, 0, 0)
992 );
993 assert_eq!(
994 Cidr::new(Address::new(0, 0, 0, 1), 24).netmask(),
995 Address::new(255, 255, 255, 0)
996 );
997 assert_eq!(
998 Cidr::new(Address::new(0, 0, 0, 0), 32).netmask(),
999 Address::new(255, 255, 255, 255)
1000 );
1001 assert_eq!(
1002 Cidr::new(Address::new(127, 0, 0, 0), 8).netmask(),
1003 Address::new(255, 0, 0, 0)
1004 );
1005 assert_eq!(
1006 Cidr::new(Address::new(192, 168, 0, 0), 16).netmask(),
1007 Address::new(255, 255, 0, 0)
1008 );
1009 assert_eq!(
1010 Cidr::new(Address::new(192, 168, 1, 1), 16).netmask(),
1011 Address::new(255, 255, 0, 0)
1012 );
1013 assert_eq!(
1014 Cidr::new(Address::new(192, 168, 1, 1), 17).netmask(),
1015 Address::new(255, 255, 128, 0)
1016 );
1017 assert_eq!(
1018 Cidr::new(Address::new(172, 16, 0, 0), 12).netmask(),
1019 Address::new(255, 240, 0, 0)
1020 );
1021 assert_eq!(
1022 Cidr::new(Address::new(255, 255, 255, 1), 24).netmask(),
1023 Address::new(255, 255, 255, 0)
1024 );
1025 assert_eq!(
1026 Cidr::new(Address::new(255, 255, 255, 255), 32).netmask(),
1027 Address::new(255, 255, 255, 255)
1028 );
1029 }
1030
1031 #[test]
1032 fn test_cidr_broadcast() {
1033 assert_eq!(
1034 Cidr::new(Address::new(0, 0, 0, 0), 0).broadcast().unwrap(),
1035 Address::new(255, 255, 255, 255)
1036 );
1037 assert_eq!(
1038 Cidr::new(Address::new(0, 0, 0, 1), 24).broadcast().unwrap(),
1039 Address::new(0, 0, 0, 255)
1040 );
1041 assert_eq!(Cidr::new(Address::new(0, 0, 0, 0), 32).broadcast(), None);
1042 assert_eq!(
1043 Cidr::new(Address::new(127, 0, 0, 0), 8)
1044 .broadcast()
1045 .unwrap(),
1046 Address::new(127, 255, 255, 255)
1047 );
1048 assert_eq!(
1049 Cidr::new(Address::new(192, 168, 0, 0), 16)
1050 .broadcast()
1051 .unwrap(),
1052 Address::new(192, 168, 255, 255)
1053 );
1054 assert_eq!(
1055 Cidr::new(Address::new(192, 168, 1, 1), 16)
1056 .broadcast()
1057 .unwrap(),
1058 Address::new(192, 168, 255, 255)
1059 );
1060 assert_eq!(
1061 Cidr::new(Address::new(192, 168, 1, 1), 17)
1062 .broadcast()
1063 .unwrap(),
1064 Address::new(192, 168, 127, 255)
1065 );
1066 assert_eq!(
1067 Cidr::new(Address::new(172, 16, 0, 1), 12)
1068 .broadcast()
1069 .unwrap(),
1070 Address::new(172, 31, 255, 255)
1071 );
1072 assert_eq!(
1073 Cidr::new(Address::new(255, 255, 255, 1), 24)
1074 .broadcast()
1075 .unwrap(),
1076 Address::new(255, 255, 255, 255)
1077 );
1078 assert_eq!(
1079 Cidr::new(Address::new(255, 255, 255, 254), 31).broadcast(),
1080 None
1081 );
1082 assert_eq!(
1083 Cidr::new(Address::new(255, 255, 255, 255), 32).broadcast(),
1084 None
1085 );
1086 }
1087
1088 #[test]
1089 fn test_cidr_network() {
1090 assert_eq!(
1091 Cidr::new(Address::new(0, 0, 0, 0), 0).network(),
1092 Cidr::new(Address::new(0, 0, 0, 0), 0)
1093 );
1094 assert_eq!(
1095 Cidr::new(Address::new(0, 0, 0, 1), 24).network(),
1096 Cidr::new(Address::new(0, 0, 0, 0), 24)
1097 );
1098 assert_eq!(
1099 Cidr::new(Address::new(0, 0, 0, 0), 32).network(),
1100 Cidr::new(Address::new(0, 0, 0, 0), 32)
1101 );
1102 assert_eq!(
1103 Cidr::new(Address::new(127, 0, 0, 0), 8).network(),
1104 Cidr::new(Address::new(127, 0, 0, 0), 8)
1105 );
1106 assert_eq!(
1107 Cidr::new(Address::new(192, 168, 0, 0), 16).network(),
1108 Cidr::new(Address::new(192, 168, 0, 0), 16)
1109 );
1110 assert_eq!(
1111 Cidr::new(Address::new(192, 168, 1, 1), 16).network(),
1112 Cidr::new(Address::new(192, 168, 0, 0), 16)
1113 );
1114 assert_eq!(
1115 Cidr::new(Address::new(192, 168, 1, 1), 17).network(),
1116 Cidr::new(Address::new(192, 168, 0, 0), 17)
1117 );
1118 assert_eq!(
1119 Cidr::new(Address::new(172, 16, 0, 1), 12).network(),
1120 Cidr::new(Address::new(172, 16, 0, 0), 12)
1121 );
1122 assert_eq!(
1123 Cidr::new(Address::new(255, 255, 255, 1), 24).network(),
1124 Cidr::new(Address::new(255, 255, 255, 0), 24)
1125 );
1126 assert_eq!(
1127 Cidr::new(Address::new(255, 255, 255, 255), 32).network(),
1128 Cidr::new(Address::new(255, 255, 255, 255), 32)
1129 );
1130 }
1131}