ipv6.rs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. #![deny(missing_docs)]
  2. use byteorder::{ByteOrder, NetworkEndian};
  3. use core::fmt;
  4. use crate::wire::ip::pretty_print_ip_payload;
  5. #[cfg(feature = "proto-ipv4")]
  6. use crate::wire::ipv4;
  7. use crate::{Error, Result};
  8. pub use super::IpProtocol as Protocol;
  9. /// Minimum MTU required of all links supporting IPv6. See [RFC 8200 § 5].
  10. ///
  11. /// [RFC 8200 § 5]: https://tools.ietf.org/html/rfc8200#section-5
  12. pub const MIN_MTU: usize = 1280;
  13. /// A sixteen-octet IPv6 address.
  14. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
  15. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  16. pub struct Address(pub [u8; 16]);
  17. impl Address {
  18. /// The [unspecified address].
  19. ///
  20. /// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
  21. pub const UNSPECIFIED: Address = Address([0x00; 16]);
  22. /// The link-local [all routers multicast address].
  23. ///
  24. /// [all routers multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1
  25. pub const LINK_LOCAL_ALL_NODES: Address = Address([
  26. 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  27. 0x01,
  28. ]);
  29. /// The link-local [all nodes multicast address].
  30. ///
  31. /// [all nodes multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1
  32. pub const LINK_LOCAL_ALL_ROUTERS: Address = Address([
  33. 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  34. 0x02,
  35. ]);
  36. /// The [loopback address].
  37. ///
  38. /// [loopback address]: https://tools.ietf.org/html/rfc4291#section-2.5.3
  39. pub const LOOPBACK: Address = Address([
  40. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  41. 0x01,
  42. ]);
  43. /// Construct an IPv6 address from parts.
  44. #[allow(clippy::too_many_arguments)]
  45. pub fn new(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16) -> Address {
  46. let mut addr = [0u8; 16];
  47. NetworkEndian::write_u16(&mut addr[0..2], a0);
  48. NetworkEndian::write_u16(&mut addr[2..4], a1);
  49. NetworkEndian::write_u16(&mut addr[4..6], a2);
  50. NetworkEndian::write_u16(&mut addr[6..8], a3);
  51. NetworkEndian::write_u16(&mut addr[8..10], a4);
  52. NetworkEndian::write_u16(&mut addr[10..12], a5);
  53. NetworkEndian::write_u16(&mut addr[12..14], a6);
  54. NetworkEndian::write_u16(&mut addr[14..16], a7);
  55. Address(addr)
  56. }
  57. /// Construct an IPv6 address from a sequence of octets, in big-endian.
  58. ///
  59. /// # Panics
  60. /// The function panics if `data` is not sixteen octets long.
  61. pub fn from_bytes(data: &[u8]) -> Address {
  62. let mut bytes = [0; 16];
  63. bytes.copy_from_slice(data);
  64. Address(bytes)
  65. }
  66. /// Construct an IPv6 address from a sequence of words, in big-endian.
  67. ///
  68. /// # Panics
  69. /// The function panics if `data` is not 8 words long.
  70. pub fn from_parts(data: &[u16]) -> Address {
  71. assert!(data.len() >= 8);
  72. let mut bytes = [0; 16];
  73. for (word_idx, chunk) in bytes.chunks_mut(2).enumerate() {
  74. NetworkEndian::write_u16(chunk, data[word_idx]);
  75. }
  76. Address(bytes)
  77. }
  78. /// Write a IPv6 address to the given slice.
  79. ///
  80. /// # Panics
  81. /// The function panics if `data` is not 8 words long.
  82. pub fn write_parts(&self, data: &mut [u16]) {
  83. assert!(data.len() >= 8);
  84. for (i, chunk) in self.0.chunks(2).enumerate() {
  85. data[i] = NetworkEndian::read_u16(chunk);
  86. }
  87. }
  88. /// Return an IPv6 address as a sequence of octets, in big-endian.
  89. pub fn as_bytes(&self) -> &[u8] {
  90. &self.0
  91. }
  92. /// Query whether the IPv6 address is an [unicast address].
  93. ///
  94. /// [unicast address]: https://tools.ietf.org/html/rfc4291#section-2.5
  95. pub fn is_unicast(&self) -> bool {
  96. !(self.is_multicast() || self.is_unspecified())
  97. }
  98. /// Query whether the IPv6 address is a [multicast address].
  99. ///
  100. /// [multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7
  101. pub fn is_multicast(&self) -> bool {
  102. self.0[0] == 0xff
  103. }
  104. /// Query whether the IPv6 address is the [unspecified address].
  105. ///
  106. /// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
  107. pub fn is_unspecified(&self) -> bool {
  108. self.0 == [0x00; 16]
  109. }
  110. /// Query whether the IPv6 address is in the [link-local] scope.
  111. ///
  112. /// [link-local]: https://tools.ietf.org/html/rfc4291#section-2.5.6
  113. pub fn is_link_local(&self) -> bool {
  114. self.0[0..8] == [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  115. }
  116. /// Query whether the IPv6 address is the [loopback address].
  117. ///
  118. /// [loopback address]: https://tools.ietf.org/html/rfc4291#section-2.5.3
  119. pub fn is_loopback(&self) -> bool {
  120. *self == Self::LOOPBACK
  121. }
  122. /// Query whether the IPv6 address is an [IPv4 mapped IPv6 address].
  123. ///
  124. /// [IPv4 mapped IPv6 address]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
  125. pub fn is_ipv4_mapped(&self) -> bool {
  126. self.0[0..12] == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff]
  127. }
  128. #[cfg(feature = "proto-ipv4")]
  129. /// Convert an IPv4 mapped IPv6 address to an IPv4 address.
  130. pub fn as_ipv4(&self) -> Option<ipv4::Address> {
  131. if self.is_ipv4_mapped() {
  132. Some(ipv4::Address::new(
  133. self.0[12], self.0[13], self.0[14], self.0[15],
  134. ))
  135. } else {
  136. None
  137. }
  138. }
  139. /// Helper function used to mask an addres given a prefix.
  140. ///
  141. /// # Panics
  142. /// This function panics if `mask` is greater than 128.
  143. pub(super) fn mask(&self, mask: u8) -> [u8; 16] {
  144. assert!(mask <= 128);
  145. let mut bytes = [0u8; 16];
  146. let idx = (mask as usize) / 8;
  147. let modulus = (mask as usize) % 8;
  148. let (first, second) = self.0.split_at(idx);
  149. bytes[0..idx].copy_from_slice(first);
  150. if idx < 16 {
  151. let part = second[0];
  152. bytes[idx] = part & (!(0xff >> modulus) as u8);
  153. }
  154. bytes
  155. }
  156. /// The solicited node for the given unicast address.
  157. ///
  158. /// # Panics
  159. /// This function panics if the given address is not
  160. /// unicast.
  161. pub fn solicited_node(&self) -> Address {
  162. assert!(self.is_unicast());
  163. Address([
  164. 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF,
  165. self.0[13], self.0[14], self.0[15],
  166. ])
  167. }
  168. /// Convert to an `IpAddress`.
  169. ///
  170. /// Same as `.into()`, but works in `const`.
  171. pub const fn into_address(self) -> super::IpAddress {
  172. super::IpAddress::Ipv6(self)
  173. }
  174. }
  175. #[cfg(feature = "std")]
  176. impl From<::std::net::Ipv6Addr> for Address {
  177. fn from(x: ::std::net::Ipv6Addr) -> Address {
  178. Address(x.octets())
  179. }
  180. }
  181. #[cfg(feature = "std")]
  182. impl From<Address> for ::std::net::Ipv6Addr {
  183. fn from(Address(x): Address) -> ::std::net::Ipv6Addr {
  184. x.into()
  185. }
  186. }
  187. impl fmt::Display for Address {
  188. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  189. if self.is_ipv4_mapped() {
  190. return write!(
  191. f,
  192. "::ffff:{}.{}.{}.{}",
  193. self.0[12], self.0[13], self.0[14], self.0[15]
  194. );
  195. }
  196. // The string representation of an IPv6 address should
  197. // collapse a series of 16 bit sections that evaluate
  198. // to 0 to "::"
  199. //
  200. // See https://tools.ietf.org/html/rfc4291#section-2.2
  201. // for details.
  202. enum State {
  203. Head,
  204. HeadBody,
  205. Tail,
  206. TailBody,
  207. }
  208. let mut words = [0u16; 8];
  209. self.write_parts(&mut words);
  210. let mut state = State::Head;
  211. for word in words.iter() {
  212. state = match (*word, &state) {
  213. // Once a u16 equal to zero write a double colon and
  214. // skip to the next non-zero u16.
  215. (0, &State::Head) | (0, &State::HeadBody) => {
  216. write!(f, "::")?;
  217. State::Tail
  218. }
  219. // Continue iterating without writing any characters until
  220. // we hit anothing non-zero value.
  221. (0, &State::Tail) => State::Tail,
  222. // When the state is Head or Tail write a u16 in hexadecimal
  223. // without the leading colon if the value is not 0.
  224. (_, &State::Head) => {
  225. write!(f, "{:x}", word)?;
  226. State::HeadBody
  227. }
  228. (_, &State::Tail) => {
  229. write!(f, "{:x}", word)?;
  230. State::TailBody
  231. }
  232. // Write the u16 with a leading colon when parsing a value
  233. // that isn't the first in a section
  234. (_, &State::HeadBody) | (_, &State::TailBody) => {
  235. write!(f, ":{:x}", word)?;
  236. state
  237. }
  238. }
  239. }
  240. Ok(())
  241. }
  242. }
  243. #[cfg(feature = "proto-ipv4")]
  244. /// Convert the given IPv4 address into a IPv4-mapped IPv6 address
  245. impl From<ipv4::Address> for Address {
  246. fn from(address: ipv4::Address) -> Self {
  247. let octets = address.0;
  248. Address([
  249. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, octets[0], octets[1], octets[2], octets[3],
  250. ])
  251. }
  252. }
  253. /// A specification of an IPv6 CIDR block, containing an address and a variable-length
  254. /// subnet masking prefix length.
  255. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
  256. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  257. pub struct Cidr {
  258. address: Address,
  259. prefix_len: u8,
  260. }
  261. impl Cidr {
  262. /// The [solicited node prefix].
  263. ///
  264. /// [solicited node prefix]: https://tools.ietf.org/html/rfc4291#section-2.7.1
  265. pub const SOLICITED_NODE_PREFIX: Cidr = Cidr {
  266. address: Address([
  267. 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00,
  268. 0x00, 0x00,
  269. ]),
  270. prefix_len: 104,
  271. };
  272. /// Create an IPv6 CIDR block from the given address and prefix length.
  273. ///
  274. /// # Panics
  275. /// This function panics if the prefix length is larger than 128.
  276. pub fn new(address: Address, prefix_len: u8) -> Cidr {
  277. assert!(prefix_len <= 128);
  278. Cidr {
  279. address,
  280. prefix_len,
  281. }
  282. }
  283. /// Return the address of this IPv6 CIDR block.
  284. pub fn address(&self) -> Address {
  285. self.address
  286. }
  287. /// Return the prefix length of this IPv6 CIDR block.
  288. pub fn prefix_len(&self) -> u8 {
  289. self.prefix_len
  290. }
  291. /// Query whether the subnetwork described by this IPv6 CIDR block contains
  292. /// the given address.
  293. pub fn contains_addr(&self, addr: &Address) -> bool {
  294. // right shift by 128 is not legal
  295. if self.prefix_len == 0 {
  296. return true;
  297. }
  298. self.address.mask(self.prefix_len) == addr.mask(self.prefix_len)
  299. }
  300. /// Query whether the subnetwork described by this IPV6 CIDR block contains
  301. /// the subnetwork described by the given IPv6 CIDR block.
  302. pub fn contains_subnet(&self, subnet: &Cidr) -> bool {
  303. self.prefix_len <= subnet.prefix_len && self.contains_addr(&subnet.address)
  304. }
  305. }
  306. impl fmt::Display for Cidr {
  307. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  308. // https://tools.ietf.org/html/rfc4291#section-2.3
  309. write!(f, "{}/{}", self.address, self.prefix_len)
  310. }
  311. }
  312. /// A read/write wrapper around an Internet Protocol version 6 packet buffer.
  313. #[derive(Debug, PartialEq, Clone)]
  314. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  315. pub struct Packet<T: AsRef<[u8]>> {
  316. buffer: T,
  317. }
  318. // Ranges and constants describing the IPv6 header
  319. //
  320. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  321. // |Version| Traffic Class | Flow Label |
  322. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  323. // | Payload Length | Next Header | Hop Limit |
  324. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  325. // | |
  326. // + +
  327. // | |
  328. // + Source Address +
  329. // | |
  330. // + +
  331. // | |
  332. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  333. // | |
  334. // + +
  335. // | |
  336. // + Destination Address +
  337. // | |
  338. // + +
  339. // | |
  340. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  341. //
  342. // See https://tools.ietf.org/html/rfc2460#section-3 for details.
  343. mod field {
  344. use crate::wire::field::*;
  345. // 4-bit version number, 8-bit traffic class, and the
  346. // 20-bit flow label.
  347. pub const VER_TC_FLOW: Field = 0..4;
  348. // 16-bit value representing the length of the payload.
  349. // Note: Options are included in this length.
  350. pub const LENGTH: Field = 4..6;
  351. // 8-bit value identifying the type of header following this
  352. // one. Note: The same numbers are used in IPv4.
  353. pub const NXT_HDR: usize = 6;
  354. // 8-bit value decremented by each node that forwards this
  355. // packet. The packet is discarded when the value is 0.
  356. pub const HOP_LIMIT: usize = 7;
  357. // IPv6 address of the source node.
  358. pub const SRC_ADDR: Field = 8..24;
  359. // IPv6 address of the destination node.
  360. pub const DST_ADDR: Field = 24..40;
  361. }
  362. /// Length of an IPv6 header.
  363. pub const HEADER_LEN: usize = field::DST_ADDR.end;
  364. impl<T: AsRef<[u8]>> Packet<T> {
  365. /// Create a raw octet buffer with an IPv6 packet structure.
  366. #[inline]
  367. pub fn new_unchecked(buffer: T) -> Packet<T> {
  368. Packet { buffer }
  369. }
  370. /// Shorthand for a combination of [new_unchecked] and [check_len].
  371. ///
  372. /// [new_unchecked]: #method.new_unchecked
  373. /// [check_len]: #method.check_len
  374. #[inline]
  375. pub fn new_checked(buffer: T) -> Result<Packet<T>> {
  376. let packet = Self::new_unchecked(buffer);
  377. packet.check_len()?;
  378. Ok(packet)
  379. }
  380. /// Ensure that no accessor method will panic if called.
  381. /// Returns `Err(Error::Truncated)` if the buffer is too short.
  382. ///
  383. /// The result of this check is invalidated by calling [set_payload_len].
  384. ///
  385. /// [set_payload_len]: #method.set_payload_len
  386. #[inline]
  387. pub fn check_len(&self) -> Result<()> {
  388. let len = self.buffer.as_ref().len();
  389. if len < field::DST_ADDR.end || len < self.total_len() {
  390. Err(Error::Truncated)
  391. } else {
  392. Ok(())
  393. }
  394. }
  395. /// Consume the packet, returning the underlying buffer.
  396. #[inline]
  397. pub fn into_inner(self) -> T {
  398. self.buffer
  399. }
  400. /// Return the header length.
  401. #[inline]
  402. pub fn header_len(&self) -> usize {
  403. // This is not a strictly necessary function, but it makes
  404. // code more readable.
  405. field::DST_ADDR.end
  406. }
  407. /// Return the version field.
  408. #[inline]
  409. pub fn version(&self) -> u8 {
  410. let data = self.buffer.as_ref();
  411. data[field::VER_TC_FLOW.start] >> 4
  412. }
  413. /// Return the traffic class.
  414. #[inline]
  415. pub fn traffic_class(&self) -> u8 {
  416. let data = self.buffer.as_ref();
  417. ((NetworkEndian::read_u16(&data[0..2]) & 0x0ff0) >> 4) as u8
  418. }
  419. /// Return the flow label field.
  420. #[inline]
  421. pub fn flow_label(&self) -> u32 {
  422. let data = self.buffer.as_ref();
  423. NetworkEndian::read_u24(&data[1..4]) & 0x000fffff
  424. }
  425. /// Return the payload length field.
  426. #[inline]
  427. pub fn payload_len(&self) -> u16 {
  428. let data = self.buffer.as_ref();
  429. NetworkEndian::read_u16(&data[field::LENGTH])
  430. }
  431. /// Return the payload length added to the known header length.
  432. #[inline]
  433. pub fn total_len(&self) -> usize {
  434. self.header_len() + self.payload_len() as usize
  435. }
  436. /// Return the next header field.
  437. #[inline]
  438. pub fn next_header(&self) -> Protocol {
  439. let data = self.buffer.as_ref();
  440. Protocol::from(data[field::NXT_HDR])
  441. }
  442. /// Return the hop limit field.
  443. #[inline]
  444. pub fn hop_limit(&self) -> u8 {
  445. let data = self.buffer.as_ref();
  446. data[field::HOP_LIMIT]
  447. }
  448. /// Return the source address field.
  449. #[inline]
  450. pub fn src_addr(&self) -> Address {
  451. let data = self.buffer.as_ref();
  452. Address::from_bytes(&data[field::SRC_ADDR])
  453. }
  454. /// Return the destination address field.
  455. #[inline]
  456. pub fn dst_addr(&self) -> Address {
  457. let data = self.buffer.as_ref();
  458. Address::from_bytes(&data[field::DST_ADDR])
  459. }
  460. }
  461. impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
  462. /// Return a pointer to the payload.
  463. #[inline]
  464. pub fn payload(&self) -> &'a [u8] {
  465. let data = self.buffer.as_ref();
  466. let range = self.header_len()..self.total_len();
  467. &data[range]
  468. }
  469. }
  470. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  471. /// Set the version field.
  472. #[inline]
  473. pub fn set_version(&mut self, value: u8) {
  474. let data = self.buffer.as_mut();
  475. // Make sure to retain the lower order bits which contain
  476. // the higher order bits of the traffic class
  477. data[0] = (data[0] & 0x0f) | ((value & 0x0f) << 4);
  478. }
  479. /// Set the traffic class field.
  480. #[inline]
  481. pub fn set_traffic_class(&mut self, value: u8) {
  482. let data = self.buffer.as_mut();
  483. // Put the higher order 4-bits of value in the lower order
  484. // 4-bits of the first byte
  485. data[0] = (data[0] & 0xf0) | ((value & 0xf0) >> 4);
  486. // Put the lower order 4-bits of value in the higher order
  487. // 4-bits of the second byte
  488. data[1] = (data[1] & 0x0f) | ((value & 0x0f) << 4);
  489. }
  490. /// Set the flow label field.
  491. #[inline]
  492. pub fn set_flow_label(&mut self, value: u32) {
  493. let data = self.buffer.as_mut();
  494. // Retain the lower order 4-bits of the traffic class
  495. let raw = (((data[1] & 0xf0) as u32) << 16) | (value & 0x0fffff);
  496. NetworkEndian::write_u24(&mut data[1..4], raw);
  497. }
  498. /// Set the payload length field.
  499. #[inline]
  500. pub fn set_payload_len(&mut self, value: u16) {
  501. let data = self.buffer.as_mut();
  502. NetworkEndian::write_u16(&mut data[field::LENGTH], value);
  503. }
  504. /// Set the next header field.
  505. #[inline]
  506. pub fn set_next_header(&mut self, value: Protocol) {
  507. let data = self.buffer.as_mut();
  508. data[field::NXT_HDR] = value.into();
  509. }
  510. /// Set the hop limit field.
  511. #[inline]
  512. pub fn set_hop_limit(&mut self, value: u8) {
  513. let data = self.buffer.as_mut();
  514. data[field::HOP_LIMIT] = value;
  515. }
  516. /// Set the source address field.
  517. #[inline]
  518. pub fn set_src_addr(&mut self, value: Address) {
  519. let data = self.buffer.as_mut();
  520. data[field::SRC_ADDR].copy_from_slice(value.as_bytes());
  521. }
  522. /// Set the destination address field.
  523. #[inline]
  524. pub fn set_dst_addr(&mut self, value: Address) {
  525. let data = self.buffer.as_mut();
  526. data[field::DST_ADDR].copy_from_slice(value.as_bytes());
  527. }
  528. /// Return a mutable pointer to the payload.
  529. #[inline]
  530. pub fn payload_mut(&mut self) -> &mut [u8] {
  531. let range = self.header_len()..self.total_len();
  532. let data = self.buffer.as_mut();
  533. &mut data[range]
  534. }
  535. }
  536. impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
  537. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  538. match Repr::parse(self) {
  539. Ok(repr) => write!(f, "{}", repr),
  540. Err(err) => {
  541. write!(f, "IPv6 ({})", err)?;
  542. Ok(())
  543. }
  544. }
  545. }
  546. }
  547. impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
  548. fn as_ref(&self) -> &[u8] {
  549. self.buffer.as_ref()
  550. }
  551. }
  552. /// A high-level representation of an Internet Protocol version 6 packet header.
  553. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  554. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  555. pub struct Repr {
  556. /// IPv6 address of the source node.
  557. pub src_addr: Address,
  558. /// IPv6 address of the destination node.
  559. pub dst_addr: Address,
  560. /// Protocol contained in the next header.
  561. pub next_header: Protocol,
  562. /// Length of the payload including the extension headers.
  563. pub payload_len: usize,
  564. /// The 8-bit hop limit field.
  565. pub hop_limit: u8,
  566. }
  567. impl Repr {
  568. /// Parse an Internet Protocol version 6 packet and return a high-level representation.
  569. pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&T>) -> Result<Repr> {
  570. // Ensure basic accessors will work
  571. packet.check_len()?;
  572. if packet.version() != 6 {
  573. return Err(Error::Malformed);
  574. }
  575. Ok(Repr {
  576. src_addr: packet.src_addr(),
  577. dst_addr: packet.dst_addr(),
  578. next_header: packet.next_header(),
  579. payload_len: packet.payload_len() as usize,
  580. hop_limit: packet.hop_limit(),
  581. })
  582. }
  583. /// Return the length of a header that will be emitted from this high-level representation.
  584. pub fn buffer_len(&self) -> usize {
  585. // This function is not strictly necessary, but it can make client code more readable.
  586. field::DST_ADDR.end
  587. }
  588. /// Emit a high-level representation into an Internet Protocol version 6 packet.
  589. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
  590. // Make no assumptions about the original state of the packet buffer.
  591. // Make sure to set every byte.
  592. packet.set_version(6);
  593. packet.set_traffic_class(0);
  594. packet.set_flow_label(0);
  595. packet.set_payload_len(self.payload_len as u16);
  596. packet.set_hop_limit(self.hop_limit);
  597. packet.set_next_header(self.next_header);
  598. packet.set_src_addr(self.src_addr);
  599. packet.set_dst_addr(self.dst_addr);
  600. }
  601. }
  602. impl fmt::Display for Repr {
  603. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  604. write!(
  605. f,
  606. "IPv6 src={} dst={} nxt_hdr={} hop_limit={}",
  607. self.src_addr, self.dst_addr, self.next_header, self.hop_limit
  608. )
  609. }
  610. }
  611. use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
  612. // TODO: This is very similar to the implementation for IPv4. Make
  613. // a way to have less copy and pasted code here.
  614. impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
  615. fn pretty_print(
  616. buffer: &dyn AsRef<[u8]>,
  617. f: &mut fmt::Formatter,
  618. indent: &mut PrettyIndent,
  619. ) -> fmt::Result {
  620. let (ip_repr, payload) = match Packet::new_checked(buffer) {
  621. Err(err) => return write!(f, "{}({})", indent, err),
  622. Ok(ip_packet) => match Repr::parse(&ip_packet) {
  623. Err(_) => return Ok(()),
  624. Ok(ip_repr) => {
  625. write!(f, "{}{}", indent, ip_repr)?;
  626. (ip_repr, ip_packet.payload())
  627. }
  628. },
  629. };
  630. pretty_print_ip_payload(f, indent, ip_repr, payload)
  631. }
  632. }
  633. #[cfg(test)]
  634. mod test {
  635. use super::{Address, Cidr};
  636. use super::{Packet, Protocol, Repr};
  637. use crate::wire::pretty_print::PrettyPrinter;
  638. use crate::Error;
  639. #[cfg(feature = "proto-ipv4")]
  640. use crate::wire::ipv4::Address as Ipv4Address;
  641. static LINK_LOCAL_ADDR: Address = Address([
  642. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  643. 0x01,
  644. ]);
  645. #[test]
  646. fn test_basic_multicast() {
  647. assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_unspecified());
  648. assert!(Address::LINK_LOCAL_ALL_ROUTERS.is_multicast());
  649. assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_link_local());
  650. assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_loopback());
  651. assert!(!Address::LINK_LOCAL_ALL_NODES.is_unspecified());
  652. assert!(Address::LINK_LOCAL_ALL_NODES.is_multicast());
  653. assert!(!Address::LINK_LOCAL_ALL_NODES.is_link_local());
  654. assert!(!Address::LINK_LOCAL_ALL_NODES.is_loopback());
  655. }
  656. #[test]
  657. fn test_basic_link_local() {
  658. assert!(!LINK_LOCAL_ADDR.is_unspecified());
  659. assert!(!LINK_LOCAL_ADDR.is_multicast());
  660. assert!(LINK_LOCAL_ADDR.is_link_local());
  661. assert!(!LINK_LOCAL_ADDR.is_loopback());
  662. }
  663. #[test]
  664. fn test_basic_loopback() {
  665. assert!(!Address::LOOPBACK.is_unspecified());
  666. assert!(!Address::LOOPBACK.is_multicast());
  667. assert!(!Address::LOOPBACK.is_link_local());
  668. assert!(Address::LOOPBACK.is_loopback());
  669. }
  670. #[test]
  671. fn test_address_format() {
  672. assert_eq!("ff02::1", format!("{}", Address::LINK_LOCAL_ALL_NODES));
  673. assert_eq!("fe80::1", format!("{}", LINK_LOCAL_ADDR));
  674. assert_eq!(
  675. "fe80::7f00:0:1",
  676. format!(
  677. "{}",
  678. Address::new(0xfe80, 0, 0, 0, 0, 0x7f00, 0x0000, 0x0001)
  679. )
  680. );
  681. assert_eq!("::", format!("{}", Address::UNSPECIFIED));
  682. assert_eq!("::1", format!("{}", Address::LOOPBACK));
  683. #[cfg(feature = "proto-ipv4")]
  684. assert_eq!(
  685. "::ffff:192.168.1.1",
  686. format!("{}", Address::from(Ipv4Address::new(192, 168, 1, 1)))
  687. );
  688. }
  689. #[test]
  690. fn test_new() {
  691. assert_eq!(
  692. Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
  693. Address::LINK_LOCAL_ALL_NODES
  694. );
  695. assert_eq!(
  696. Address::new(0xff02, 0, 0, 0, 0, 0, 0, 2),
  697. Address::LINK_LOCAL_ALL_ROUTERS
  698. );
  699. assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 1), Address::LOOPBACK);
  700. assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 0), Address::UNSPECIFIED);
  701. assert_eq!(Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), LINK_LOCAL_ADDR);
  702. }
  703. #[test]
  704. fn test_from_parts() {
  705. assert_eq!(
  706. Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 1]),
  707. Address::LINK_LOCAL_ALL_NODES
  708. );
  709. assert_eq!(
  710. Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 2]),
  711. Address::LINK_LOCAL_ALL_ROUTERS
  712. );
  713. assert_eq!(
  714. Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 1]),
  715. Address::LOOPBACK
  716. );
  717. assert_eq!(
  718. Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 0]),
  719. Address::UNSPECIFIED
  720. );
  721. assert_eq!(
  722. Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 1]),
  723. LINK_LOCAL_ADDR
  724. );
  725. }
  726. #[test]
  727. fn test_write_parts() {
  728. let mut bytes = [0u16; 8];
  729. {
  730. Address::LOOPBACK.write_parts(&mut bytes);
  731. assert_eq!(Address::LOOPBACK, Address::from_parts(&bytes));
  732. }
  733. {
  734. Address::LINK_LOCAL_ALL_ROUTERS.write_parts(&mut bytes);
  735. assert_eq!(Address::LINK_LOCAL_ALL_ROUTERS, Address::from_parts(&bytes));
  736. }
  737. {
  738. LINK_LOCAL_ADDR.write_parts(&mut bytes);
  739. assert_eq!(LINK_LOCAL_ADDR, Address::from_parts(&bytes));
  740. }
  741. }
  742. #[test]
  743. fn test_mask() {
  744. let addr = Address::new(0x0123, 0x4567, 0x89ab, 0, 0, 0, 0, 1);
  745. assert_eq!(
  746. addr.mask(11),
  747. [0x01, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  748. );
  749. assert_eq!(
  750. addr.mask(15),
  751. [0x01, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  752. );
  753. assert_eq!(
  754. addr.mask(26),
  755. [0x01, 0x23, 0x45, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  756. );
  757. assert_eq!(
  758. addr.mask(128),
  759. [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
  760. );
  761. assert_eq!(
  762. addr.mask(127),
  763. [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  764. );
  765. }
  766. #[cfg(feature = "proto-ipv4")]
  767. #[test]
  768. fn test_is_ipv4_mapped() {
  769. assert!(!Address::UNSPECIFIED.is_ipv4_mapped());
  770. assert!(Address::from(Ipv4Address::new(192, 168, 1, 1)).is_ipv4_mapped());
  771. }
  772. #[cfg(feature = "proto-ipv4")]
  773. #[test]
  774. fn test_as_ipv4() {
  775. assert_eq!(None, Address::UNSPECIFIED.as_ipv4());
  776. let ipv4 = Ipv4Address::new(192, 168, 1, 1);
  777. assert_eq!(Some(ipv4), Address::from(ipv4).as_ipv4());
  778. }
  779. #[cfg(feature = "proto-ipv4")]
  780. #[test]
  781. fn test_from_ipv4_address() {
  782. assert_eq!(
  783. Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1]),
  784. Address::from(Ipv4Address::new(192, 168, 1, 1))
  785. );
  786. assert_eq!(
  787. Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 222, 1, 41, 90]),
  788. Address::from(Ipv4Address::new(222, 1, 41, 90))
  789. );
  790. }
  791. #[test]
  792. fn test_cidr() {
  793. // fe80::1/56
  794. // 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  795. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  796. let cidr = Cidr::new(LINK_LOCAL_ADDR, 56);
  797. let inside_subnet = [
  798. // fe80::2
  799. [
  800. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  801. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  802. ],
  803. // fe80::1122:3344:5566:7788
  804. [
  805. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  806. 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
  807. ],
  808. // fe80::ff00:0:0:0
  809. [
  810. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  811. 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  812. ],
  813. // fe80::ff
  814. [
  815. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  816. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  817. ],
  818. ];
  819. let outside_subnet = [
  820. // fe80:0:0:101::1
  821. [
  822. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01,
  823. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  824. ],
  825. // ::1
  826. [
  827. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  828. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  829. ],
  830. // ff02::1
  831. [
  832. 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
  833. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  834. ],
  835. // ff02::2
  836. [
  837. 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
  838. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  839. ],
  840. ];
  841. let subnets = [
  842. // fe80::ffff:ffff:ffff:ffff/65
  843. (
  844. [
  845. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  846. 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  847. ],
  848. 65,
  849. ),
  850. // fe80::1/128
  851. (
  852. [
  853. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  854. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  855. ],
  856. 128,
  857. ),
  858. // fe80::1234:5678/96
  859. (
  860. [
  861. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  862. 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78,
  863. ],
  864. 96,
  865. ),
  866. ];
  867. let not_subnets = [
  868. // fe80::101:ffff:ffff:ffff:ffff/55
  869. (
  870. [
  871. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01,
  872. 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  873. ],
  874. 55,
  875. ),
  876. // fe80::101:ffff:ffff:ffff:ffff/56
  877. (
  878. [
  879. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01,
  880. 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  881. ],
  882. 56,
  883. ),
  884. // fe80::101:ffff:ffff:ffff:ffff/57
  885. (
  886. [
  887. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01,
  888. 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  889. ],
  890. 57,
  891. ),
  892. // ::1/128
  893. (
  894. [
  895. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  896. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  897. ],
  898. 128,
  899. ),
  900. ];
  901. for addr in inside_subnet.iter().map(|a| Address::from_bytes(a)) {
  902. assert!(cidr.contains_addr(&addr));
  903. }
  904. for addr in outside_subnet.iter().map(|a| Address::from_bytes(a)) {
  905. assert!(!cidr.contains_addr(&addr));
  906. }
  907. for subnet in subnets.iter().map(|&(a, p)| Cidr::new(Address(a), p)) {
  908. assert!(cidr.contains_subnet(&subnet));
  909. }
  910. for subnet in not_subnets.iter().map(|&(a, p)| Cidr::new(Address(a), p)) {
  911. assert!(!cidr.contains_subnet(&subnet));
  912. }
  913. let cidr_without_prefix = Cidr::new(LINK_LOCAL_ADDR, 0);
  914. assert!(cidr_without_prefix.contains_addr(&Address::LOOPBACK));
  915. }
  916. #[test]
  917. #[should_panic(expected = "length")]
  918. fn test_from_bytes_too_long() {
  919. let _ = Address::from_bytes(&[0u8; 15]);
  920. }
  921. #[test]
  922. #[should_panic(expected = "data.len() >= 8")]
  923. fn test_from_parts_too_long() {
  924. let _ = Address::from_parts(&[0u16; 7]);
  925. }
  926. static REPR_PACKET_BYTES: [u8; 52] = [
  927. 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  928. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
  929. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00,
  930. 0x0c, 0x02, 0x4e, 0xff, 0xff, 0xff, 0xff,
  931. ];
  932. static REPR_PAYLOAD_BYTES: [u8; 12] = [
  933. 0x00, 0x01, 0x00, 0x02, 0x00, 0x0c, 0x02, 0x4e, 0xff, 0xff, 0xff, 0xff,
  934. ];
  935. fn packet_repr() -> Repr {
  936. Repr {
  937. src_addr: Address([
  938. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  939. 0x00, 0x01,
  940. ]),
  941. dst_addr: Address::LINK_LOCAL_ALL_NODES,
  942. next_header: Protocol::Udp,
  943. payload_len: 12,
  944. hop_limit: 64,
  945. }
  946. }
  947. #[test]
  948. fn test_packet_deconstruction() {
  949. let packet = Packet::new_unchecked(&REPR_PACKET_BYTES[..]);
  950. assert_eq!(packet.check_len(), Ok(()));
  951. assert_eq!(packet.version(), 6);
  952. assert_eq!(packet.traffic_class(), 0);
  953. assert_eq!(packet.flow_label(), 0);
  954. assert_eq!(packet.total_len(), 0x34);
  955. assert_eq!(packet.payload_len() as usize, REPR_PAYLOAD_BYTES.len());
  956. assert_eq!(packet.next_header(), Protocol::Udp);
  957. assert_eq!(packet.hop_limit(), 0x40);
  958. assert_eq!(
  959. packet.src_addr(),
  960. Address([
  961. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  962. 0x00, 0x01
  963. ])
  964. );
  965. assert_eq!(packet.dst_addr(), Address::LINK_LOCAL_ALL_NODES);
  966. assert_eq!(packet.payload(), &REPR_PAYLOAD_BYTES[..]);
  967. }
  968. #[test]
  969. fn test_packet_construction() {
  970. let mut bytes = [0xff; 52];
  971. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  972. // Version, Traffic Class, and Flow Label are not
  973. // byte aligned. make sure the setters and getters
  974. // do not interfere with each other.
  975. packet.set_version(6);
  976. assert_eq!(packet.version(), 6);
  977. packet.set_traffic_class(0x99);
  978. assert_eq!(packet.version(), 6);
  979. assert_eq!(packet.traffic_class(), 0x99);
  980. packet.set_flow_label(0x54321);
  981. assert_eq!(packet.traffic_class(), 0x99);
  982. assert_eq!(packet.flow_label(), 0x54321);
  983. packet.set_payload_len(0xc);
  984. packet.set_next_header(Protocol::Udp);
  985. packet.set_hop_limit(0xfe);
  986. packet.set_src_addr(Address::LINK_LOCAL_ALL_ROUTERS);
  987. packet.set_dst_addr(Address::LINK_LOCAL_ALL_NODES);
  988. packet
  989. .payload_mut()
  990. .copy_from_slice(&REPR_PAYLOAD_BYTES[..]);
  991. let mut expected_bytes = [
  992. 0x69, 0x95, 0x43, 0x21, 0x00, 0x0c, 0x11, 0xfe, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
  993. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x02, 0x00, 0x00,
  994. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
  995. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  996. ];
  997. let start = expected_bytes.len() - REPR_PAYLOAD_BYTES.len();
  998. expected_bytes[start..].copy_from_slice(&REPR_PAYLOAD_BYTES[..]);
  999. assert_eq!(packet.check_len(), Ok(()));
  1000. assert_eq!(&packet.into_inner()[..], &expected_bytes[..]);
  1001. }
  1002. #[test]
  1003. fn test_overlong() {
  1004. let mut bytes = vec![];
  1005. bytes.extend(&REPR_PACKET_BYTES[..]);
  1006. bytes.push(0);
  1007. assert_eq!(
  1008. Packet::new_unchecked(&bytes).payload().len(),
  1009. REPR_PAYLOAD_BYTES.len()
  1010. );
  1011. assert_eq!(
  1012. Packet::new_unchecked(&mut bytes).payload_mut().len(),
  1013. REPR_PAYLOAD_BYTES.len()
  1014. );
  1015. }
  1016. #[test]
  1017. fn test_total_len_overflow() {
  1018. let mut bytes = vec![];
  1019. bytes.extend(&REPR_PACKET_BYTES[..]);
  1020. Packet::new_unchecked(&mut bytes).set_payload_len(0x80);
  1021. assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated);
  1022. }
  1023. #[test]
  1024. fn test_repr_parse_valid() {
  1025. let packet = Packet::new_unchecked(&REPR_PACKET_BYTES[..]);
  1026. let repr = Repr::parse(&packet).unwrap();
  1027. assert_eq!(repr, packet_repr());
  1028. }
  1029. #[test]
  1030. fn test_repr_parse_bad_version() {
  1031. let mut bytes = vec![0; 40];
  1032. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  1033. packet.set_version(4);
  1034. packet.set_payload_len(0);
  1035. let packet = Packet::new_unchecked(&*packet.into_inner());
  1036. assert_eq!(Repr::parse(&packet), Err(Error::Malformed));
  1037. }
  1038. #[test]
  1039. fn test_repr_parse_smaller_than_header() {
  1040. let mut bytes = vec![0; 40];
  1041. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  1042. packet.set_version(6);
  1043. packet.set_payload_len(39);
  1044. let packet = Packet::new_unchecked(&*packet.into_inner());
  1045. assert_eq!(Repr::parse(&packet), Err(Error::Truncated));
  1046. }
  1047. #[test]
  1048. fn test_repr_parse_smaller_than_payload() {
  1049. let mut bytes = vec![0; 40];
  1050. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  1051. packet.set_version(6);
  1052. packet.set_payload_len(1);
  1053. let packet = Packet::new_unchecked(&*packet.into_inner());
  1054. assert_eq!(Repr::parse(&packet), Err(Error::Truncated));
  1055. }
  1056. #[test]
  1057. fn test_basic_repr_emit() {
  1058. let repr = packet_repr();
  1059. let mut bytes = vec![0xff; repr.buffer_len() + REPR_PAYLOAD_BYTES.len()];
  1060. let mut packet = Packet::new_unchecked(&mut bytes);
  1061. repr.emit(&mut packet);
  1062. packet.payload_mut().copy_from_slice(&REPR_PAYLOAD_BYTES);
  1063. assert_eq!(&packet.into_inner()[..], &REPR_PACKET_BYTES[..]);
  1064. }
  1065. #[test]
  1066. fn test_pretty_print() {
  1067. assert_eq!(
  1068. format!(
  1069. "{}",
  1070. PrettyPrinter::<Packet<&'static [u8]>>::new("\n", &&REPR_PACKET_BYTES[..])
  1071. ),
  1072. "\nIPv6 src=fe80::1 dst=ff02::1 nxt_hdr=UDP hop_limit=64\n \\ UDP src=1 dst=2 len=4"
  1073. );
  1074. }
  1075. }