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 let total_len = packet.header_len() as u16 + self.payload_len as u16;
594 packet.set_total_len(total_len);
595 packet.set_ident(0);
596 packet.clear_flags();
597 packet.set_more_frags(false);
598 packet.set_dont_frag(true);
599 packet.set_frag_offset(0);
600 packet.set_hop_limit(self.hop_limit);
601 packet.set_next_header(self.next_header);
602 packet.set_src_addr(self.src_addr);
603 packet.set_dst_addr(self.dst_addr);
604
605 if checksum_caps.ipv4.tx() {
606 packet.fill_checksum();
607 } else {
608 packet.set_checksum(0);
611 }
612 }
613}
614
615impl<T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&T> {
616 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
617 match Repr::parse(self, &ChecksumCapabilities::ignored()) {
618 Ok(repr) => write!(f, "{repr}"),
619 Err(err) => {
620 write!(f, "IPv4 ({err})")?;
621 write!(
622 f,
623 " src={} dst={} proto={} hop_limit={}",
624 self.src_addr(),
625 self.dst_addr(),
626 self.next_header(),
627 self.hop_limit()
628 )?;
629 if self.version() != 4 {
630 write!(f, " ver={}", self.version())?;
631 }
632 if self.header_len() != 20 {
633 write!(f, " hlen={}", self.header_len())?;
634 }
635 if self.dscp() != 0 {
636 write!(f, " dscp={}", self.dscp())?;
637 }
638 if self.ecn() != 0 {
639 write!(f, " ecn={}", self.ecn())?;
640 }
641 write!(f, " tlen={}", self.total_len())?;
642 if self.dont_frag() {
643 write!(f, " df")?;
644 }
645 if self.more_frags() {
646 write!(f, " mf")?;
647 }
648 if self.frag_offset() != 0 {
649 write!(f, " off={}", self.frag_offset())?;
650 }
651 if self.more_frags() || self.frag_offset() != 0 {
652 write!(f, " id={}", self.ident())?;
653 }
654 Ok(())
655 }
656 }
657 }
658}
659
660impl fmt::Display for Repr {
661 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
662 write!(
663 f,
664 "IPv4 src={} dst={} proto={}",
665 self.src_addr, self.dst_addr, self.next_header
666 )
667 }
668}
669
670use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
671
672impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
673 fn pretty_print(
674 buffer: &dyn AsRef<[u8]>,
675 f: &mut fmt::Formatter,
676 indent: &mut PrettyIndent,
677 ) -> fmt::Result {
678 use crate::wire::ip::checksum::format_checksum;
679
680 let checksum_caps = ChecksumCapabilities::ignored();
681
682 let (ip_repr, payload) = match Packet::new_checked(buffer) {
683 Err(err) => return write!(f, "{indent}({err})"),
684 Ok(ip_packet) => match Repr::parse(&ip_packet, &checksum_caps) {
685 Err(_) => return Ok(()),
686 Ok(ip_repr) => {
687 if ip_packet.more_frags() || ip_packet.frag_offset() != 0 {
688 write!(
689 f,
690 "{}IPv4 Fragment more_frags={} offset={}",
691 indent,
692 ip_packet.more_frags(),
693 ip_packet.frag_offset()
694 )?;
695 return Ok(());
696 } else {
697 write!(f, "{indent}{ip_repr}")?;
698 format_checksum(f, ip_packet.verify_checksum(), false)?;
699 (ip_repr, ip_packet.payload())
700 }
701 }
702 },
703 };
704
705 pretty_print_ip_payload(f, indent, ip_repr, payload)
706 }
707}
708
709#[cfg(test)]
710pub(crate) mod test {
711 use super::*;
712
713 #[allow(unused)]
714 pub(crate) const MOCK_IP_ADDR_1: Address = Address::new(192, 168, 1, 1);
715 #[allow(unused)]
716 pub(crate) const MOCK_IP_ADDR_2: Address = Address::new(192, 168, 1, 2);
717 #[allow(unused)]
718 pub(crate) const MOCK_IP_ADDR_3: Address = Address::new(192, 168, 1, 3);
719 #[allow(unused)]
720 pub(crate) const MOCK_IP_ADDR_4: Address = Address::new(192, 168, 1, 4);
721 #[allow(unused)]
722 pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED;
723
724 static PACKET_BYTES: [u8; 30] = [
725 0x45, 0x00, 0x00, 0x1e, 0x01, 0x02, 0x62, 0x03, 0x1a, 0x01, 0xd5, 0x6e, 0x11, 0x12, 0x13,
726 0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
727 ];
728
729 static PAYLOAD_BYTES: [u8; 10] = [0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff];
730
731 #[test]
732 fn test_deconstruct() {
733 let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
734 assert_eq!(packet.version(), 4);
735 assert_eq!(packet.header_len(), 20);
736 assert_eq!(packet.dscp(), 0);
737 assert_eq!(packet.ecn(), 0);
738 assert_eq!(packet.total_len(), 30);
739 assert_eq!(packet.ident(), 0x102);
740 assert!(packet.more_frags());
741 assert!(packet.dont_frag());
742 assert_eq!(packet.frag_offset(), 0x203 * 8);
743 assert_eq!(packet.hop_limit(), 0x1a);
744 assert_eq!(packet.next_header(), Protocol::Icmp);
745 assert_eq!(packet.checksum(), 0xd56e);
746 assert_eq!(packet.src_addr(), Address::new(0x11, 0x12, 0x13, 0x14));
747 assert_eq!(packet.dst_addr(), Address::new(0x21, 0x22, 0x23, 0x24));
748 assert!(packet.verify_checksum());
749 assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]);
750 }
751
752 #[test]
753 fn test_construct() {
754 let mut bytes = vec![0xa5; 30];
755 let mut packet = Packet::new_unchecked(&mut bytes);
756 packet.set_version(4);
757 packet.set_header_len(20);
758 packet.clear_flags();
759 packet.set_dscp(0);
760 packet.set_ecn(0);
761 packet.set_total_len(30);
762 packet.set_ident(0x102);
763 packet.set_more_frags(true);
764 packet.set_dont_frag(true);
765 packet.set_frag_offset(0x203 * 8);
766 packet.set_hop_limit(0x1a);
767 packet.set_next_header(Protocol::Icmp);
768 packet.set_src_addr(Address::new(0x11, 0x12, 0x13, 0x14));
769 packet.set_dst_addr(Address::new(0x21, 0x22, 0x23, 0x24));
770 packet.fill_checksum();
771 packet.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
772 assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]);
773 }
774
775 #[test]
776 fn test_overlong() {
777 let mut bytes = vec![];
778 bytes.extend(&PACKET_BYTES[..]);
779 bytes.push(0);
780
781 assert_eq!(
782 Packet::new_unchecked(&bytes).payload().len(),
783 PAYLOAD_BYTES.len()
784 );
785 assert_eq!(
786 Packet::new_unchecked(&mut bytes).payload_mut().len(),
787 PAYLOAD_BYTES.len()
788 );
789 }
790
791 #[test]
792 fn test_total_len_overflow() {
793 let mut bytes = vec![];
794 bytes.extend(&PACKET_BYTES[..]);
795 Packet::new_unchecked(&mut bytes).set_total_len(128);
796
797 assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error);
798 }
799
800 static REPR_PACKET_BYTES: [u8; 24] = [
801 0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0xd2, 0x79, 0x11, 0x12, 0x13,
802 0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0xff,
803 ];
804
805 static REPR_PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
806
807 const fn packet_repr() -> Repr {
808 Repr {
809 src_addr: Address::new(0x11, 0x12, 0x13, 0x14),
810 dst_addr: Address::new(0x21, 0x22, 0x23, 0x24),
811 next_header: Protocol::Icmp,
812 payload_len: 4,
813 hop_limit: 64,
814 }
815 }
816
817 #[test]
818 fn test_parse() {
819 let packet = Packet::new_unchecked(&REPR_PACKET_BYTES[..]);
820 let repr = Repr::parse(&packet, &ChecksumCapabilities::default()).unwrap();
821 assert_eq!(repr, packet_repr());
822 }
823
824 #[test]
825 fn test_parse_bad_version() {
826 let mut bytes = vec![0; 24];
827 bytes.copy_from_slice(&REPR_PACKET_BYTES[..]);
828 let mut packet = Packet::new_unchecked(&mut bytes);
829 packet.set_version(6);
830 packet.fill_checksum();
831 let packet = Packet::new_unchecked(&*packet.into_inner());
832 assert_eq!(
833 Repr::parse(&packet, &ChecksumCapabilities::default()),
834 Err(Error)
835 );
836 }
837
838 #[test]
839 fn test_parse_total_len_less_than_header_len() {
840 let mut bytes = vec![0; 40];
841 bytes[0] = 0x09;
842 assert_eq!(Packet::new_checked(&mut bytes), Err(Error));
843 }
844
845 #[test]
846 fn test_parse_small_ihl() {
847 let mut bytes = vec![0; 24];
848 bytes.copy_from_slice(&REPR_PACKET_BYTES[..]);
849 let mut packet = Packet::new_unchecked(&mut bytes);
850 packet.set_header_len(16);
851
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_octets(*a)) {
919 assert!(cidr.contains_addr(&addr));
920 }
921
922 for addr in outside_subnet.iter().map(|a| Address::from_octets(*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}