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