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