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