ipv6routing.rs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. use crate::{Error, Result};
  2. use core::fmt;
  3. use crate::wire::IpProtocol as Protocol;
  4. use crate::wire::Ipv6Address as Address;
  5. enum_with_unknown! {
  6. /// IPv6 Extension Routing Header Routing Type
  7. pub enum Type(u8) {
  8. /// Source Route (DEPRECATED)
  9. ///
  10. /// See https://tools.ietf.org/html/rfc5095 for details.
  11. Type0 = 0,
  12. /// Nimrod (DEPRECATED 2009-05-06)
  13. Nimrod = 1,
  14. /// Type 2 Routing Header for Mobile IPv6
  15. ///
  16. /// See https://tools.ietf.org/html/rfc6275#section-6.4 for details.
  17. Type2 = 2,
  18. /// RPL Source Routing Header
  19. ///
  20. /// See https://tools.ietf.org/html/rfc6554 for details.
  21. Rpl = 3,
  22. /// RFC3692-style Experiment 1
  23. ///
  24. /// See https://tools.ietf.org/html/rfc4727 for details.
  25. Experiment1 = 253,
  26. /// RFC3692-style Experiment 2
  27. ///
  28. /// See https://tools.ietf.org/html/rfc4727 for details.
  29. Experiment2 = 254,
  30. /// Reserved for future use
  31. Reserved = 252
  32. }
  33. }
  34. impl fmt::Display for Type {
  35. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  36. match *self {
  37. Type::Type0 => write!(f, "Type0"),
  38. Type::Nimrod => write!(f, "Nimrod"),
  39. Type::Type2 => write!(f, "Type2"),
  40. Type::Rpl => write!(f, "Rpl"),
  41. Type::Experiment1 => write!(f, "Experiment1"),
  42. Type::Experiment2 => write!(f, "Experiment2"),
  43. Type::Reserved => write!(f, "Reserved"),
  44. Type::Unknown(id) => write!(f, "{}", id),
  45. }
  46. }
  47. }
  48. /// A read/write wrapper around an IPv6 Routing Header buffer.
  49. #[derive(Debug, PartialEq)]
  50. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  51. pub struct Header<T: AsRef<[u8]>> {
  52. buffer: T,
  53. }
  54. // Format of the Routing Header
  55. //
  56. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  57. // | Next Header | Hdr Ext Len | Routing Type | Segments Left |
  58. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  59. // | |
  60. // . .
  61. // . type-specific data .
  62. // . .
  63. // | |
  64. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  65. //
  66. //
  67. // See https://tools.ietf.org/html/rfc8200#section-4.4 for details.
  68. mod field {
  69. #![allow(non_snake_case)]
  70. use crate::wire::field::*;
  71. // Minimum size of the header.
  72. pub const MIN_HEADER_SIZE: usize = 4;
  73. // 8-bit identifier of the header immediately following this header.
  74. pub const NXT_HDR: usize = 0;
  75. // 8-bit unsigned integer. Length of the DATA field in 8-octet units,
  76. // not including the first 8 octets.
  77. pub const LENGTH: usize = 1;
  78. // 8-bit identifier of a particular Routing header variant.
  79. pub const TYPE: usize = 2;
  80. // 8-bit unsigned integer. The number of route segments remaining.
  81. pub const SEG_LEFT: usize = 3;
  82. // Variable-length field. Routing-Type-specific data.
  83. //
  84. // Length of the header is in 8-octet units, not including the first 8 octets. The first four
  85. // octets are the next header type, the header length, routing type and segments left.
  86. pub fn DATA(length_field: u8) -> Field {
  87. let bytes = length_field * 8 + 8;
  88. 4..bytes as usize
  89. }
  90. // The Type 2 Routing Header has the following format:
  91. //
  92. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  93. // | Next Header | Hdr Ext Len=2 | Routing Type=2|Segments Left=1|
  94. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  95. // | Reserved |
  96. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  97. // | |
  98. // + +
  99. // | |
  100. // + Home Address +
  101. // | |
  102. // + +
  103. // | |
  104. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  105. // 16-byte field containing the home address of the destination mobile node.
  106. pub const HOME_ADDRESS: Field = 8..24;
  107. // The RPL Source Routing Header has the following format:
  108. //
  109. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  110. // | Next Header | Hdr Ext Len | Routing Type | Segments Left |
  111. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  112. // | CmprI | CmprE | Pad | Reserved |
  113. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  114. // | |
  115. // . .
  116. // . Addresses[1..n] .
  117. // . .
  118. // | |
  119. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  120. // 8-bit field containing the CmprI and CmprE values.
  121. pub const CMPR: usize = 4;
  122. // 8-bit field containing the Pad value.
  123. pub const PAD: usize = 5;
  124. // Variable length field containing addresses
  125. pub fn ADDRESSES(length_field: u8) -> Field {
  126. let data = DATA(length_field);
  127. 8..data.end
  128. }
  129. }
  130. /// Core getter methods relevant to any routing type.
  131. impl<T: AsRef<[u8]>> Header<T> {
  132. /// Create a raw octet buffer with an IPv6 Routing Header structure.
  133. pub fn new(buffer: T) -> Header<T> {
  134. Header { buffer }
  135. }
  136. /// Shorthand for a combination of [new_unchecked] and [check_len].
  137. ///
  138. /// [new_unchecked]: #method.new_unchecked
  139. /// [check_len]: #method.check_len
  140. pub fn new_checked(buffer: T) -> Result<Header<T>> {
  141. let header = Self::new(buffer);
  142. header.check_len()?;
  143. Ok(header)
  144. }
  145. /// Ensure that no accessor method will panic if called.
  146. /// Returns `Err(Error::Truncated)` if the buffer is too short.
  147. ///
  148. /// The result of this check is invalidated by calling [set_header_len].
  149. ///
  150. /// [set_header_len]: #method.set_header_len
  151. pub fn check_len(&self) -> Result<()> {
  152. let len = self.buffer.as_ref().len();
  153. if len < field::MIN_HEADER_SIZE {
  154. return Err(Error::Truncated);
  155. }
  156. if len < field::DATA(self.header_len()).end as usize {
  157. return Err(Error::Truncated);
  158. }
  159. Ok(())
  160. }
  161. /// Consume the header, returning the underlying buffer.
  162. pub fn into_inner(self) -> T {
  163. self.buffer
  164. }
  165. /// Return the next header field.
  166. #[inline]
  167. pub fn next_header(&self) -> Protocol {
  168. let data = self.buffer.as_ref();
  169. Protocol::from(data[field::NXT_HDR])
  170. }
  171. /// Return the header length field. Length of the Routing header in 8-octet units,
  172. /// not including the first 8 octets.
  173. #[inline]
  174. pub fn header_len(&self) -> u8 {
  175. let data = self.buffer.as_ref();
  176. data[field::LENGTH]
  177. }
  178. /// Return the routing type field.
  179. #[inline]
  180. pub fn routing_type(&self) -> Type {
  181. let data = self.buffer.as_ref();
  182. Type::from(data[field::TYPE])
  183. }
  184. /// Return the segments left field.
  185. #[inline]
  186. pub fn segments_left(&self) -> u8 {
  187. let data = self.buffer.as_ref();
  188. data[field::SEG_LEFT]
  189. }
  190. }
  191. /// Getter methods for the Type 2 Routing Header routing type.
  192. impl<T: AsRef<[u8]>> Header<T> {
  193. /// Return the IPv6 Home Address
  194. ///
  195. /// # Panics
  196. /// This function may panic if this header is not the Type2 Routing Header routing type.
  197. pub fn home_address(&self) -> Address {
  198. let data = self.buffer.as_ref();
  199. Address::from_bytes(&data[field::HOME_ADDRESS])
  200. }
  201. }
  202. /// Getter methods for the RPL Source Routing Header routing type.
  203. impl<T: AsRef<[u8]>> Header<T> {
  204. /// Return the number of prefix octets elided from addresses[1..n-1].
  205. ///
  206. /// # Panics
  207. /// This function may panic if this header is not the RPL Source Routing Header routing type.
  208. pub fn cmpr_i(&self) -> u8 {
  209. let data = self.buffer.as_ref();
  210. data[field::CMPR] >> 4
  211. }
  212. /// Return the number of prefix octets elided from the last address (`addresses[n]`).
  213. ///
  214. /// # Panics
  215. /// This function may panic if this header is not the RPL Source Routing Header routing type.
  216. pub fn cmpr_e(&self) -> u8 {
  217. let data = self.buffer.as_ref();
  218. data[field::CMPR] & 0xf
  219. }
  220. /// Return the number of octets used for padding after `addresses[n]`.
  221. ///
  222. /// # Panics
  223. /// This function may panic if this header is not the RPL Source Routing Header routing type.
  224. pub fn pad(&self) -> u8 {
  225. let data = self.buffer.as_ref();
  226. data[field::PAD] >> 4
  227. }
  228. /// Return the address vector in bytes
  229. ///
  230. /// # Panics
  231. /// This function may panic if this header is not the RPL Source Routing Header routing type.
  232. pub fn addresses(&self) -> &[u8] {
  233. let data = self.buffer.as_ref();
  234. &data[field::ADDRESSES(data[field::LENGTH])]
  235. }
  236. }
  237. /// Core setter methods relevant to any routing type.
  238. impl<T: AsRef<[u8]> + AsMut<[u8]>> Header<T> {
  239. /// Set the next header field.
  240. #[inline]
  241. pub fn set_next_header(&mut self, value: Protocol) {
  242. let data = self.buffer.as_mut();
  243. data[field::NXT_HDR] = value.into();
  244. }
  245. /// Set the option data length. Length of the Routing header in 8-octet units.
  246. #[inline]
  247. pub fn set_header_len(&mut self, value: u8) {
  248. let data = self.buffer.as_mut();
  249. data[field::LENGTH] = value;
  250. }
  251. /// Set the routing type.
  252. #[inline]
  253. pub fn set_routing_type(&mut self, value: Type) {
  254. let data = self.buffer.as_mut();
  255. data[field::TYPE] = value.into();
  256. }
  257. /// Set the segments left field.
  258. #[inline]
  259. pub fn set_segments_left(&mut self, value: u8) {
  260. let data = self.buffer.as_mut();
  261. data[field::SEG_LEFT] = value;
  262. }
  263. /// Initialize reserved fields to 0.
  264. ///
  265. /// # Panics
  266. /// This function may panic if the routing type is not set.
  267. #[inline]
  268. pub fn clear_reserved(&mut self) {
  269. let routing_type = self.routing_type();
  270. let data = self.buffer.as_mut();
  271. match routing_type {
  272. Type::Type2 => {
  273. data[4] = 0;
  274. data[5] = 0;
  275. data[6] = 0;
  276. data[7] = 0;
  277. }
  278. Type::Rpl => {
  279. // Retain the higher order 4 bits of the padding field
  280. data[field::PAD] &= 0xF0;
  281. data[6] = 0;
  282. data[7] = 0;
  283. }
  284. _ => panic!("Unrecognized routing type when clearing reserved fields."),
  285. }
  286. }
  287. }
  288. /// Setter methods for the RPL Source Routing Header routing type.
  289. impl<T: AsRef<[u8]> + AsMut<[u8]>> Header<T> {
  290. /// Set the Ipv6 Home Address
  291. ///
  292. /// # Panics
  293. /// This function may panic if this header is not the Type 2 Routing Header routing type.
  294. pub fn set_home_address(&mut self, value: Address) {
  295. let data = self.buffer.as_mut();
  296. data[field::HOME_ADDRESS].copy_from_slice(value.as_bytes());
  297. }
  298. }
  299. /// Setter methods for the RPL Source Routing Header routing type.
  300. impl<T: AsRef<[u8]> + AsMut<[u8]>> Header<T> {
  301. /// Set the number of prefix octets elided from addresses[1..n-1].
  302. ///
  303. /// # Panics
  304. /// This function may panic if this header is not the RPL Source Routing Header routing type.
  305. pub fn set_cmpr_i(&mut self, value: u8) {
  306. let data = self.buffer.as_mut();
  307. let raw = (value << 4) | (data[field::CMPR] & 0xF);
  308. data[field::CMPR] = raw;
  309. }
  310. /// Set the number of prefix octets elided from the last address (`addresses[n]`).
  311. ///
  312. /// # Panics
  313. /// This function may panic if this header is not the RPL Source Routing Header routing type.
  314. pub fn set_cmpr_e(&mut self, value: u8) {
  315. let data = self.buffer.as_mut();
  316. let raw = (value & 0xF) | (data[field::CMPR] & 0xF0);
  317. data[field::CMPR] = raw;
  318. }
  319. /// Set the number of octets used for padding after `addresses[n]`.
  320. ///
  321. /// # Panics
  322. /// This function may panic if this header is not the RPL Source Routing Header routing type.
  323. pub fn set_pad(&mut self, value: u8) {
  324. let data = self.buffer.as_mut();
  325. data[field::PAD] = value << 4;
  326. }
  327. /// Set address data
  328. ///
  329. /// # Panics
  330. /// This function may panic if this header is not the RPL Source Routing Header routing type.
  331. pub fn set_addresses(&mut self, value: &[u8]) {
  332. let data = self.buffer.as_mut();
  333. let len = data[field::LENGTH];
  334. let addresses = &mut data[field::ADDRESSES(len)];
  335. addresses.copy_from_slice(value);
  336. }
  337. }
  338. impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Header<&'a T> {
  339. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  340. match Repr::parse(self) {
  341. Ok(repr) => write!(f, "{}", repr),
  342. Err(err) => {
  343. write!(f, "IPv6 Routing ({})", err)?;
  344. Ok(())
  345. }
  346. }
  347. }
  348. }
  349. /// A high-level representation of an IPv6 Routing Header.
  350. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  351. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  352. #[non_exhaustive]
  353. pub enum Repr<'a> {
  354. Type2 {
  355. /// The type of header immediately following the Routing header.
  356. next_header: Protocol,
  357. /// Length of the Routing header in 8-octet units, not including the first 8 octets.
  358. length: u8,
  359. /// Number of route segments remaining.
  360. segments_left: u8,
  361. /// The home address of the destination mobile node.
  362. home_address: Address,
  363. },
  364. Rpl {
  365. /// The type of header immediately following the Routing header.
  366. next_header: Protocol,
  367. /// Length of the Routing header in 8-octet units, not including the first 8 octets.
  368. length: u8,
  369. /// Number of route segments remaining.
  370. segments_left: u8,
  371. /// Number of prefix octets from each segment, except the last segment, that are elided.
  372. cmpr_i: u8,
  373. /// Number of prefix octets from the last segment that are elided.
  374. cmpr_e: u8,
  375. /// Number of octets that are used for padding after `address[n]` at the end of the
  376. /// RPL Source Route Header.
  377. pad: u8,
  378. /// Vector of addresses, numbered 1 to `n`.
  379. addresses: &'a [u8],
  380. },
  381. }
  382. impl<'a> Repr<'a> {
  383. /// Parse an IPv6 Routing Header and return a high-level representation.
  384. pub fn parse<T>(header: &'a Header<&'a T>) -> Result<Repr<'a>>
  385. where
  386. T: AsRef<[u8]> + ?Sized,
  387. {
  388. match header.routing_type() {
  389. Type::Type2 => Ok(Repr::Type2 {
  390. next_header: header.next_header(),
  391. length: header.header_len(),
  392. segments_left: header.segments_left(),
  393. home_address: header.home_address(),
  394. }),
  395. Type::Rpl => Ok(Repr::Rpl {
  396. next_header: header.next_header(),
  397. length: header.header_len(),
  398. segments_left: header.segments_left(),
  399. cmpr_i: header.cmpr_i(),
  400. cmpr_e: header.cmpr_e(),
  401. pad: header.pad(),
  402. addresses: header.addresses(),
  403. }),
  404. _ => Err(Error::Unrecognized),
  405. }
  406. }
  407. /// Return the length, in bytes, of a header that will be emitted from this high-level
  408. /// representation.
  409. pub fn buffer_len(&self) -> usize {
  410. match self {
  411. &Repr::Rpl { length, .. } | &Repr::Type2 { length, .. } => field::DATA(length).end,
  412. }
  413. }
  414. /// Emit a high-level representation into an IPv6 Routing Header.
  415. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, header: &mut Header<&mut T>) {
  416. match *self {
  417. Repr::Type2 {
  418. next_header,
  419. length,
  420. segments_left,
  421. home_address,
  422. } => {
  423. header.set_next_header(next_header);
  424. header.set_header_len(length);
  425. header.set_routing_type(Type::Type2);
  426. header.set_segments_left(segments_left);
  427. header.clear_reserved();
  428. header.set_home_address(home_address);
  429. }
  430. Repr::Rpl {
  431. next_header,
  432. length,
  433. segments_left,
  434. cmpr_i,
  435. cmpr_e,
  436. pad,
  437. addresses,
  438. } => {
  439. header.set_next_header(next_header);
  440. header.set_header_len(length);
  441. header.set_routing_type(Type::Rpl);
  442. header.set_segments_left(segments_left);
  443. header.set_cmpr_i(cmpr_i);
  444. header.set_cmpr_e(cmpr_e);
  445. header.set_pad(pad);
  446. header.clear_reserved();
  447. header.set_addresses(addresses);
  448. }
  449. }
  450. }
  451. }
  452. impl<'a> fmt::Display for Repr<'a> {
  453. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  454. match *self {
  455. Repr::Type2 {
  456. next_header,
  457. length,
  458. segments_left,
  459. home_address,
  460. } => {
  461. write!(
  462. f,
  463. "IPv6 Routing next_hdr={} length={} type={} seg_left={} home_address={}",
  464. next_header,
  465. length,
  466. Type::Type2,
  467. segments_left,
  468. home_address
  469. )
  470. }
  471. Repr::Rpl {
  472. next_header,
  473. length,
  474. segments_left,
  475. cmpr_i,
  476. cmpr_e,
  477. pad,
  478. ..
  479. } => {
  480. write!(f, "IPv6 Routing next_hdr={} length={} type={} seg_left={} cmpr_i={} cmpr_e={} pad={}",
  481. next_header, length, Type::Rpl, segments_left, cmpr_i, cmpr_e, pad)
  482. }
  483. }
  484. }
  485. }
  486. #[cfg(test)]
  487. mod test {
  488. use super::*;
  489. // A Type 2 Routing Header
  490. static BYTES_TYPE2: [u8; 24] = [
  491. 0x6, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  492. 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
  493. ];
  494. // A representation of a Type 2 Routing header
  495. static REPR_TYPE2: Repr = Repr::Type2 {
  496. next_header: Protocol::Tcp,
  497. length: 2,
  498. segments_left: 1,
  499. home_address: Address::LOOPBACK,
  500. };
  501. // A Source Routing Header with full IPv6 addresses in bytes
  502. static BYTES_SRH_FULL: [u8; 40] = [
  503. 0x6, 0x4, 0x3, 0x2, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  504. 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  505. 0x0, 0x0, 0x3, 0x1,
  506. ];
  507. // A representation of a Source Routing Header with full IPv6 addresses
  508. static REPR_SRH_FULL: Repr = Repr::Rpl {
  509. next_header: Protocol::Tcp,
  510. length: 4,
  511. segments_left: 2,
  512. cmpr_i: 0,
  513. cmpr_e: 0,
  514. pad: 0,
  515. addresses: &[
  516. 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd,
  517. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x1,
  518. ],
  519. };
  520. // A Source Routing Header with elided IPv6 addresses in bytes
  521. static BYTES_SRH_ELIDED: [u8; 16] = [
  522. 0x6, 0x1, 0x3, 0x2, 0xfe, 0x50, 0x0, 0x0, 0x2, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
  523. ];
  524. // A representation of a Source Routing Header with elided IPv6 addresses
  525. static REPR_SRH_ELIDED: Repr = Repr::Rpl {
  526. next_header: Protocol::Tcp,
  527. length: 1,
  528. segments_left: 2,
  529. cmpr_i: 15,
  530. cmpr_e: 14,
  531. pad: 5,
  532. addresses: &[0x2, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0],
  533. };
  534. #[test]
  535. fn test_check_len() {
  536. // less than min header size
  537. assert_eq!(
  538. Err(Error::Truncated),
  539. Header::new(&BYTES_TYPE2[..3]).check_len()
  540. );
  541. assert_eq!(
  542. Err(Error::Truncated),
  543. Header::new(&BYTES_SRH_FULL[..3]).check_len()
  544. );
  545. assert_eq!(
  546. Err(Error::Truncated),
  547. Header::new(&BYTES_SRH_ELIDED[..3]).check_len()
  548. );
  549. // less than specified length field
  550. assert_eq!(
  551. Err(Error::Truncated),
  552. Header::new(&BYTES_TYPE2[..23]).check_len()
  553. );
  554. assert_eq!(
  555. Err(Error::Truncated),
  556. Header::new(&BYTES_SRH_FULL[..39]).check_len()
  557. );
  558. assert_eq!(
  559. Err(Error::Truncated),
  560. Header::new(&BYTES_SRH_ELIDED[..11]).check_len()
  561. );
  562. // valid
  563. assert_eq!(Ok(()), Header::new(&BYTES_TYPE2[..]).check_len());
  564. assert_eq!(Ok(()), Header::new(&BYTES_SRH_FULL[..]).check_len());
  565. assert_eq!(Ok(()), Header::new(&BYTES_SRH_ELIDED[..]).check_len());
  566. }
  567. #[test]
  568. fn test_header_deconstruct() {
  569. let header = Header::new(&BYTES_TYPE2[..]);
  570. assert_eq!(header.next_header(), Protocol::Tcp);
  571. assert_eq!(header.header_len(), 2);
  572. assert_eq!(header.routing_type(), Type::Type2);
  573. assert_eq!(header.segments_left(), 1);
  574. assert_eq!(header.home_address(), Address::LOOPBACK);
  575. let header = Header::new(&BYTES_SRH_FULL[..]);
  576. assert_eq!(header.next_header(), Protocol::Tcp);
  577. assert_eq!(header.header_len(), 4);
  578. assert_eq!(header.routing_type(), Type::Rpl);
  579. assert_eq!(header.segments_left(), 2);
  580. assert_eq!(header.addresses(), &BYTES_SRH_FULL[8..]);
  581. let header = Header::new(&BYTES_SRH_ELIDED[..]);
  582. assert_eq!(header.next_header(), Protocol::Tcp);
  583. assert_eq!(header.header_len(), 1);
  584. assert_eq!(header.routing_type(), Type::Rpl);
  585. assert_eq!(header.segments_left(), 2);
  586. assert_eq!(header.addresses(), &BYTES_SRH_ELIDED[8..]);
  587. }
  588. #[test]
  589. fn test_repr_parse_valid() {
  590. let header = Header::new_checked(&BYTES_TYPE2[..]).unwrap();
  591. let repr = Repr::parse(&header).unwrap();
  592. assert_eq!(repr, REPR_TYPE2);
  593. let header = Header::new_checked(&BYTES_SRH_FULL[..]).unwrap();
  594. let repr = Repr::parse(&header).unwrap();
  595. assert_eq!(repr, REPR_SRH_FULL);
  596. let header = Header::new_checked(&BYTES_SRH_ELIDED[..]).unwrap();
  597. let repr = Repr::parse(&header).unwrap();
  598. assert_eq!(repr, REPR_SRH_ELIDED);
  599. }
  600. #[test]
  601. fn test_repr_emit() {
  602. let mut bytes = [0u8; 24];
  603. let mut header = Header::new(&mut bytes[..]);
  604. REPR_TYPE2.emit(&mut header);
  605. assert_eq!(header.into_inner(), &BYTES_TYPE2[..]);
  606. let mut bytes = [0u8; 40];
  607. let mut header = Header::new(&mut bytes[..]);
  608. REPR_SRH_FULL.emit(&mut header);
  609. assert_eq!(header.into_inner(), &BYTES_SRH_FULL[..]);
  610. let mut bytes = [0u8; 16];
  611. let mut header = Header::new(&mut bytes[..]);
  612. REPR_SRH_ELIDED.emit(&mut header);
  613. assert_eq!(header.into_inner(), &BYTES_SRH_ELIDED[..]);
  614. }
  615. #[test]
  616. fn test_buffer_len() {
  617. assert_eq!(REPR_TYPE2.buffer_len(), 24);
  618. assert_eq!(REPR_SRH_FULL.buffer_len(), 40);
  619. assert_eq!(REPR_SRH_ELIDED.buffer_len(), 16);
  620. }
  621. }