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