1 use byteorder::{ByteOrder, NetworkEndian};
2 use core::fmt;
3 
4 use super::{Error, Result};
5 use crate::phy::ChecksumCapabilities;
6 use crate::wire::ip::{checksum, pretty_print_ip_payload};
7 
8 pub use super::IpProtocol as Protocol;
9 
10 /// Minimum MTU required of all links supporting IPv4. See [RFC 791 § 3.1].
11 ///
12 /// [RFC 791 § 3.1]: https://tools.ietf.org/html/rfc791#section-3.1
13 // RFC 791 states the following:
14 //
15 // > Every internet module must be able to forward a datagram of 68
16 // > octets without further fragmentation... Every internet destination
17 // > must be able to receive a datagram of 576 octets either in one piece
18 // > or in fragments to be reassembled.
19 //
20 // As a result, we can assume that every host we send packets to can
21 // accept a packet of the following size.
22 pub const MIN_MTU: usize = 576;
23 
24 /// Size of IPv4 adderess in octets.
25 ///
26 /// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc791#section-3.2
27 pub const ADDR_SIZE: usize = 4;
28 
29 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
30 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
31 pub struct Key {
32     id: u16,
33     src_addr: Address,
34     dst_addr: Address,
35     protocol: Protocol,
36 }
37 
38 /// A four-octet IPv4 address.
39 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
40 pub struct Address(pub [u8; ADDR_SIZE]);
41 
42 impl Address {
43     /// An unspecified address.
44     pub const UNSPECIFIED: Address = Address([0x00; ADDR_SIZE]);
45 
46     /// The broadcast address.
47     pub const BROADCAST: Address = Address([0xff; ADDR_SIZE]);
48 
49     /// All multicast-capable nodes
50     pub const MULTICAST_ALL_SYSTEMS: Address = Address([224, 0, 0, 1]);
51 
52     /// All multicast-capable routers
53     pub const MULTICAST_ALL_ROUTERS: Address = Address([224, 0, 0, 2]);
54 
55     /// Construct an IPv4 address from parts.
new(a0: u8, a1: u8, a2: u8, a3: u8) -> Address56     pub const fn new(a0: u8, a1: u8, a2: u8, a3: u8) -> Address {
57         Address([a0, a1, a2, a3])
58     }
59 
60     /// Construct an IPv4 address from a sequence of octets, in big-endian.
61     ///
62     /// # Panics
63     /// The function panics if `data` is not four octets long.
from_bytes(data: &[u8]) -> Address64     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     /// Return an IPv4 address as a sequence of octets, in big-endian.
as_bytes(&self) -> &[u8]71     pub const fn as_bytes(&self) -> &[u8] {
72         &self.0
73     }
74 
75     /// Query whether the address is an unicast address.
is_unicast(&self) -> bool76     pub fn is_unicast(&self) -> bool {
77         !(self.is_broadcast() || self.is_multicast() || self.is_unspecified())
78     }
79 
80     /// Query whether the address is the broadcast address.
is_broadcast(&self) -> bool81     pub fn is_broadcast(&self) -> bool {
82         self.0[0..4] == [255; ADDR_SIZE]
83     }
84 
85     /// Query whether the address is a multicast address.
is_multicast(&self) -> bool86     pub const fn is_multicast(&self) -> bool {
87         self.0[0] & 0xf0 == 224
88     }
89 
90     /// Query whether the address falls into the "unspecified" range.
is_unspecified(&self) -> bool91     pub const fn is_unspecified(&self) -> bool {
92         self.0[0] == 0
93     }
94 
95     /// Query whether the address falls into the "link-local" range.
is_link_local(&self) -> bool96     pub fn is_link_local(&self) -> bool {
97         self.0[0..2] == [169, 254]
98     }
99 
100     /// Query whether the address falls into the "loopback" range.
is_loopback(&self) -> bool101     pub const fn is_loopback(&self) -> bool {
102         self.0[0] == 127
103     }
104 
105     /// Convert to an `IpAddress`.
106     ///
107     /// Same as `.into()`, but works in `const`.
into_address(self) -> super::IpAddress108     pub const fn into_address(self) -> super::IpAddress {
109         super::IpAddress::Ipv4(self)
110     }
111 }
112 
113 #[cfg(feature = "std")]
114 impl From<::std::net::Ipv4Addr> for Address {
from(x: ::std::net::Ipv4Addr) -> Address115     fn from(x: ::std::net::Ipv4Addr) -> Address {
116         Address(x.octets())
117     }
118 }
119 
120 #[cfg(feature = "std")]
121 impl From<Address> for ::std::net::Ipv4Addr {
from(Address(x): Address) -> ::std::net::Ipv4Addr122     fn from(Address(x): Address) -> ::std::net::Ipv4Addr {
123         x.into()
124     }
125 }
126 
127 impl fmt::Display for Address {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result128     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")]
135 impl defmt::Format for Address {
format(&self, f: defmt::Formatter)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 /// A specification of an IPv4 CIDR block, containing an address and a variable-length
149 /// subnet masking prefix length.
150 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
151 pub struct Cidr {
152     address: Address,
153     prefix_len: u8,
154 }
155 
156 impl Cidr {
157     /// Create an IPv4 CIDR block from the given address and prefix length.
158     ///
159     /// # Panics
160     /// This function panics if the prefix length is larger than 32.
161     #[allow(clippy::no_effect)]
new(address: Address, prefix_len: u8) -> Cidr162     pub const fn new(address: Address, prefix_len: u8) -> Cidr {
163         // Replace with const panic (or assert) when stabilized
164         // see: https://github.com/rust-lang/rust/issues/51999
165         ["Prefix length should be <= 32"][(prefix_len > 32) as usize];
166         Cidr {
167             address,
168             prefix_len,
169         }
170     }
171 
172     /// Create an IPv4 CIDR block from the given address and network mask.
from_netmask(addr: Address, netmask: Address) -> Result<Cidr>173     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     /// Return the address of this IPv4 CIDR block.
address(&self) -> Address186     pub const fn address(&self) -> Address {
187         self.address
188     }
189 
190     /// Return the prefix length of this IPv4 CIDR block.
prefix_len(&self) -> u8191     pub const fn prefix_len(&self) -> u8 {
192         self.prefix_len
193     }
194 
195     /// Return the network mask of this IPv4 CIDR.
netmask(&self) -> Address196     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     /// Return the broadcast address of this IPv4 CIDR.
broadcast(&self) -> Option<Address>213     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     /// Return the network block of this IPv4 CIDR.
network(&self) -> Cidr233     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     /// Query whether the subnetwork described by this IPv4 CIDR block contains
248     /// the given address.
contains_addr(&self, addr: &Address) -> bool249     pub fn contains_addr(&self, addr: &Address) -> bool {
250         // right shift by 32 is not legal
251         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     /// Query whether the subnetwork described by this IPv4 CIDR block contains
262     /// the subnetwork described by the given IPv4 CIDR block.
contains_subnet(&self, subnet: &Cidr) -> bool263     pub fn contains_subnet(&self, subnet: &Cidr) -> bool {
264         self.prefix_len <= subnet.prefix_len && self.contains_addr(&subnet.address)
265     }
266 }
267 
268 impl fmt::Display for Cidr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result269     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270         write!(f, "{}/{}", self.address, self.prefix_len)
271     }
272 }
273 
274 #[cfg(feature = "defmt")]
275 impl defmt::Format for Cidr {
format(&self, f: defmt::Formatter)276     fn format(&self, f: defmt::Formatter) {
277         defmt::write!(f, "{:?}/{=u8}", self.address, self.prefix_len);
278     }
279 }
280 
281 /// A read/write wrapper around an Internet Protocol version 4 packet buffer.
282 #[derive(Debug, PartialEq, Eq, Clone)]
283 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
284 pub struct Packet<T: AsRef<[u8]>> {
285     buffer: T,
286 }
287 
288 mod 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 
303 pub const HEADER_LEN: usize = field::DST_ADDR.end;
304 
305 impl<T: AsRef<[u8]>> Packet<T> {
306     /// Imbue a raw octet buffer with IPv4 packet structure.
new_unchecked(buffer: T) -> Packet<T>307     pub const fn new_unchecked(buffer: T) -> Packet<T> {
308         Packet { buffer }
309     }
310 
311     /// Shorthand for a combination of [new_unchecked] and [check_len].
312     ///
313     /// [new_unchecked]: #method.new_unchecked
314     /// [check_len]: #method.check_len
new_checked(buffer: T) -> Result<Packet<T>>315     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     /// Ensure that no accessor method will panic if called.
322     /// Returns `Err(Error)` if the buffer is too short.
323     /// Returns `Err(Error)` if the header length is greater
324     /// than total length.
325     ///
326     /// The result of this check is invalidated by calling [set_header_len]
327     /// and [set_total_len].
328     ///
329     /// [set_header_len]: #method.set_header_len
330     /// [set_total_len]: #method.set_total_len
331     #[allow(clippy::if_same_then_else)]
check_len(&self) -> Result<()>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     /// Consume the packet, returning the underlying buffer.
into_inner(self) -> T348     pub fn into_inner(self) -> T {
349         self.buffer
350     }
351 
352     /// Return the version field.
353     #[inline]
version(&self) -> u8354     pub fn version(&self) -> u8 {
355         let data = self.buffer.as_ref();
356         data[field::VER_IHL] >> 4
357     }
358 
359     /// Return the header length, in octets.
360     #[inline]
header_len(&self) -> u8361     pub fn header_len(&self) -> u8 {
362         let data = self.buffer.as_ref();
363         (data[field::VER_IHL] & 0x0f) * 4
364     }
365 
366     /// Return the Differential Services Code Point field.
dscp(&self) -> u8367     pub fn dscp(&self) -> u8 {
368         let data = self.buffer.as_ref();
369         data[field::DSCP_ECN] >> 2
370     }
371 
372     /// Return the Explicit Congestion Notification field.
ecn(&self) -> u8373     pub fn ecn(&self) -> u8 {
374         let data = self.buffer.as_ref();
375         data[field::DSCP_ECN] & 0x03
376     }
377 
378     /// Return the total length field.
379     #[inline]
total_len(&self) -> u16380     pub fn total_len(&self) -> u16 {
381         let data = self.buffer.as_ref();
382         NetworkEndian::read_u16(&data[field::LENGTH])
383     }
384 
385     /// Return the fragment identification field.
386     #[inline]
ident(&self) -> u16387     pub fn ident(&self) -> u16 {
388         let data = self.buffer.as_ref();
389         NetworkEndian::read_u16(&data[field::IDENT])
390     }
391 
392     /// Return the "don't fragment" flag.
393     #[inline]
dont_frag(&self) -> bool394     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     /// Return the "more fragments" flag.
400     #[inline]
more_frags(&self) -> bool401     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     /// Return the fragment offset, in octets.
407     #[inline]
frag_offset(&self) -> u16408     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     /// Return the time to live field.
414     #[inline]
hop_limit(&self) -> u8415     pub fn hop_limit(&self) -> u8 {
416         let data = self.buffer.as_ref();
417         data[field::TTL]
418     }
419 
420     /// Return the next_header (protocol) field.
421     #[inline]
next_header(&self) -> Protocol422     pub fn next_header(&self) -> Protocol {
423         let data = self.buffer.as_ref();
424         Protocol::from(data[field::PROTOCOL])
425     }
426 
427     /// Return the header checksum field.
428     #[inline]
checksum(&self) -> u16429     pub fn checksum(&self) -> u16 {
430         let data = self.buffer.as_ref();
431         NetworkEndian::read_u16(&data[field::CHECKSUM])
432     }
433 
434     /// Return the source address field.
435     #[inline]
src_addr(&self) -> Address436     pub fn src_addr(&self) -> Address {
437         let data = self.buffer.as_ref();
438         Address::from_bytes(&data[field::SRC_ADDR])
439     }
440 
441     /// Return the destination address field.
442     #[inline]
dst_addr(&self) -> Address443     pub fn dst_addr(&self) -> Address {
444         let data = self.buffer.as_ref();
445         Address::from_bytes(&data[field::DST_ADDR])
446     }
447 
448     /// Validate the header checksum.
449     ///
450     /// # Fuzzing
451     /// This function always returns `true` when fuzzing.
verify_checksum(&self) -> bool452     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     /// Returns the key for identifying the packet.
get_key(&self) -> Key462     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 
472 impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
473     /// Return a pointer to the payload.
474     #[inline]
payload(&self) -> &'a [u8]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 
482 impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
483     /// Set the version field.
484     #[inline]
set_version(&mut self, value: u8)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     /// Set the header length, in octets.
491     #[inline]
set_header_len(&mut self, value: u8)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     /// Set the Differential Services Code Point field.
set_dscp(&mut self, value: u8)498     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     /// Set the Explicit Congestion Notification field.
set_ecn(&mut self, value: u8)504     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     /// Set the total length field.
510     #[inline]
set_total_len(&mut self, value: u16)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     /// Set the fragment identification field.
517     #[inline]
set_ident(&mut self, value: u16)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     /// Clear the entire flags field.
524     #[inline]
clear_flags(&mut self)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     /// Set the "don't fragment" flag.
533     #[inline]
set_dont_frag(&mut self, value: bool)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     /// Set the "more fragments" flag.
542     #[inline]
set_more_frags(&mut self, value: bool)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     /// Set the fragment offset, in octets.
551     #[inline]
set_frag_offset(&mut self, value: u16)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     /// Set the time to live field.
560     #[inline]
set_hop_limit(&mut self, value: u8)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     /// Set the next header (protocol) field.
567     #[inline]
set_next_header(&mut self, value: Protocol)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     /// Set the header checksum field.
574     #[inline]
set_checksum(&mut self, value: u16)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     /// Set the source address field.
581     #[inline]
set_src_addr(&mut self, value: Address)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     /// Set the destination address field.
588     #[inline]
set_dst_addr(&mut self, value: Address)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     /// Compute and fill in the header checksum.
fill_checksum(&mut self)595     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     /// Return a mutable pointer to the payload.
605     #[inline]
payload_mut(&mut self) -> &mut [u8]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 
613 impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
as_ref(&self) -> &[u8]614     fn as_ref(&self) -> &[u8] {
615         self.buffer.as_ref()
616     }
617 }
618 
619 /// A high-level representation of an Internet Protocol version 4 packet header.
620 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
621 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
622 pub 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 
630 impl Repr {
631     /// Parse an Internet Protocol version 4 packet and return a high-level representation.
parse<T: AsRef<[u8]> + ?Sized>( packet: &Packet<&T>, checksum_caps: &ChecksumCapabilities, ) -> Result<Repr>632     pub fn parse<T: AsRef<[u8]> + ?Sized>(
633         packet: &Packet<&T>,
634         checksum_caps: &ChecksumCapabilities,
635     ) -> Result<Repr> {
636         // Version 4 is expected.
637         if packet.version() != 4 {
638             return Err(Error);
639         }
640         // Valid checksum is expected.
641         if checksum_caps.ipv4.rx() && !packet.verify_checksum() {
642             return Err(Error);
643         }
644 
645         #[cfg(not(feature = "proto-ipv4-fragmentation"))]
646         // We do not support fragmentation.
647         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         // All DSCP values are acceptable, since they are of no concern to receiving endpoint.
654         // All ECN values are acceptable, since ECN requires opt-in from both endpoints.
655         // All TTL values are acceptable, since we do not perform routing.
656         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     /// Return the length of a header that will be emitted from this high-level representation.
buffer_len(&self) -> usize666     pub const fn buffer_len(&self) -> usize {
667         // We never emit any options.
668         field::DST_ADDR.end
669     }
670 
671     /// Emit a high-level representation into an Internet Protocol version 4 packet.
emit<T: AsRef<[u8]> + AsMut<[u8]>>( &self, packet: &mut Packet<T>, checksum_caps: &ChecksumCapabilities, )672     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             // make sure we get a consistently zeroed checksum,
697             // since implementations might rely on it
698             packet.set_checksum(0);
699         }
700     }
701 }
702 
703 impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result704     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 
748 impl fmt::Display for Repr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result749     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 
758 use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
759 
760 impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
pretty_print( buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, indent: &mut PrettyIndent, ) -> fmt::Result761     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)]
798 mod 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]
test_deconstruct()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]
test_construct()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]
test_overlong()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]
test_total_len_overflow()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 
packet_repr() -> Repr884     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]
test_parse()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]
test_parse_bad_version()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]
test_parse_total_len_less_than_header_len()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]
test_emit()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]
test_unspecified()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]
test_broadcast()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]
test_cidr()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]
test_cidr_from_netmask()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]
test_cidr_netmask()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]
test_cidr_broadcast()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]
test_cidr_network()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 }
1179