mld.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. // Packet implementation for the Multicast Listener Discovery
  2. // protocol. See [RFC 3810] and [RFC 2710].
  3. //
  4. // [RFC 3810]: https://tools.ietf.org/html/rfc3810
  5. // [RFC 2710]: https://tools.ietf.org/html/rfc2710
  6. use byteorder::{ByteOrder, NetworkEndian};
  7. use super::{Error, Result};
  8. use crate::wire::icmpv6::{field, Message, Packet};
  9. use crate::wire::Ipv6Address;
  10. enum_with_unknown! {
  11. /// MLDv2 Multicast Listener Report Record Type. See [RFC 3810 § 5.2.12] for
  12. /// more details.
  13. ///
  14. /// [RFC 3810 § 5.2.12]: https://tools.ietf.org/html/rfc3010#section-5.2.12
  15. pub enum RecordType(u8) {
  16. /// Interface has a filter mode of INCLUDE for the specified multicast address.
  17. ModeIsInclude = 0x01,
  18. /// Interface has a filter mode of EXCLUDE for the specified multicast address.
  19. ModeIsExclude = 0x02,
  20. /// Interface has changed to a filter mode of INCLUDE for the specified
  21. /// multicast address.
  22. ChangeToInclude = 0x03,
  23. /// Interface has changed to a filter mode of EXCLUDE for the specified
  24. /// multicast address.
  25. ChangeToExclude = 0x04,
  26. /// Interface wishes to listen to the sources in the specified list.
  27. AllowNewSources = 0x05,
  28. /// Interface no longer wishes to listen to the sources in the specified list.
  29. BlockOldSources = 0x06
  30. }
  31. }
  32. /// Getters for the Multicast Listener Query message header.
  33. /// See [RFC 3810 § 5.1].
  34. ///
  35. /// [RFC 3810 § 5.1]: https://tools.ietf.org/html/rfc3010#section-5.1
  36. impl<T: AsRef<[u8]>> Packet<T> {
  37. /// Return the maximum response code field.
  38. #[inline]
  39. pub fn max_resp_code(&self) -> u16 {
  40. let data = self.buffer.as_ref();
  41. NetworkEndian::read_u16(&data[field::MAX_RESP_CODE])
  42. }
  43. /// Return the address being queried.
  44. #[inline]
  45. pub fn mcast_addr(&self) -> Ipv6Address {
  46. let data = self.buffer.as_ref();
  47. Ipv6Address::from_bytes(&data[field::QUERY_MCAST_ADDR])
  48. }
  49. /// Return the Suppress Router-Side Processing flag.
  50. #[inline]
  51. pub fn s_flag(&self) -> bool {
  52. let data = self.buffer.as_ref();
  53. (data[field::SQRV] & 0x08) != 0
  54. }
  55. /// Return the Querier's Robustness Variable.
  56. #[inline]
  57. pub fn qrv(&self) -> u8 {
  58. let data = self.buffer.as_ref();
  59. data[field::SQRV] & 0x7
  60. }
  61. /// Return the Querier's Query Interval Code.
  62. #[inline]
  63. pub fn qqic(&self) -> u8 {
  64. let data = self.buffer.as_ref();
  65. data[field::QQIC]
  66. }
  67. /// Return number of sources.
  68. #[inline]
  69. pub fn num_srcs(&self) -> u16 {
  70. let data = self.buffer.as_ref();
  71. NetworkEndian::read_u16(&data[field::QUERY_NUM_SRCS])
  72. }
  73. }
  74. /// Getters for the Multicast Listener Report message header.
  75. /// See [RFC 3810 § 5.2].
  76. ///
  77. /// [RFC 3810 § 5.2]: https://tools.ietf.org/html/rfc3010#section-5.2
  78. impl<T: AsRef<[u8]>> Packet<T> {
  79. /// Return the number of Multicast Address Records.
  80. #[inline]
  81. pub fn nr_mcast_addr_rcrds(&self) -> u16 {
  82. let data = self.buffer.as_ref();
  83. NetworkEndian::read_u16(&data[field::NR_MCAST_RCRDS])
  84. }
  85. }
  86. /// Setters for the Multicast Listener Query message header.
  87. /// See [RFC 3810 § 5.1].
  88. ///
  89. /// [RFC 3810 § 5.1]: https://tools.ietf.org/html/rfc3010#section-5.1
  90. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  91. /// Set the maximum response code field.
  92. #[inline]
  93. pub fn set_max_resp_code(&mut self, code: u16) {
  94. let data = self.buffer.as_mut();
  95. NetworkEndian::write_u16(&mut data[field::MAX_RESP_CODE], code);
  96. }
  97. /// Set the address being queried.
  98. #[inline]
  99. pub fn set_mcast_addr(&mut self, addr: Ipv6Address) {
  100. let data = self.buffer.as_mut();
  101. data[field::QUERY_MCAST_ADDR].copy_from_slice(addr.as_bytes());
  102. }
  103. /// Set the Suppress Router-Side Processing flag.
  104. #[inline]
  105. pub fn set_s_flag(&mut self) {
  106. let data = self.buffer.as_mut();
  107. let current = data[field::SQRV];
  108. data[field::SQRV] = 0x8 | (current & 0x7);
  109. }
  110. /// Clear the Suppress Router-Side Processing flag.
  111. #[inline]
  112. pub fn clear_s_flag(&mut self) {
  113. let data = self.buffer.as_mut();
  114. data[field::SQRV] &= 0x7;
  115. }
  116. /// Set the Querier's Robustness Variable.
  117. #[inline]
  118. pub fn set_qrv(&mut self, value: u8) {
  119. assert!(value < 8);
  120. let data = self.buffer.as_mut();
  121. data[field::SQRV] = (data[field::SQRV] & 0x8) | value & 0x7;
  122. }
  123. /// Set the Querier's Query Interval Code.
  124. #[inline]
  125. pub fn set_qqic(&mut self, value: u8) {
  126. let data = self.buffer.as_mut();
  127. data[field::QQIC] = value;
  128. }
  129. /// Set number of sources.
  130. #[inline]
  131. pub fn set_num_srcs(&mut self, value: u16) {
  132. let data = self.buffer.as_mut();
  133. NetworkEndian::write_u16(&mut data[field::QUERY_NUM_SRCS], value);
  134. }
  135. }
  136. /// Setters for the Multicast Listener Report message header.
  137. /// See [RFC 3810 § 5.2].
  138. ///
  139. /// [RFC 3810 § 5.2]: https://tools.ietf.org/html/rfc3010#section-5.2
  140. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  141. /// Set the number of Multicast Address Records.
  142. #[inline]
  143. pub fn set_nr_mcast_addr_rcrds(&mut self, value: u16) {
  144. let data = self.buffer.as_mut();
  145. NetworkEndian::write_u16(&mut data[field::NR_MCAST_RCRDS], value)
  146. }
  147. }
  148. /// A read/write wrapper around an MLDv2 Listener Report Message Address Record.
  149. #[derive(Debug, PartialEq, Eq, Clone)]
  150. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  151. pub struct AddressRecord<T: AsRef<[u8]>> {
  152. buffer: T,
  153. }
  154. impl<T: AsRef<[u8]>> AddressRecord<T> {
  155. /// Imbue a raw octet buffer with a Address Record structure.
  156. pub const fn new_unchecked(buffer: T) -> Self {
  157. Self { buffer }
  158. }
  159. /// Shorthand for a combination of [new_unchecked] and [check_len].
  160. ///
  161. /// [new_unchecked]: #method.new_unchecked
  162. /// [check_len]: #method.check_len
  163. pub fn new_checked(buffer: T) -> Result<Self> {
  164. let packet = Self::new_unchecked(buffer);
  165. packet.check_len()?;
  166. Ok(packet)
  167. }
  168. /// Ensure that no accessor method will panic if called.
  169. /// Returns `Err(Error::Truncated)` if the buffer is too short.
  170. pub fn check_len(&self) -> Result<()> {
  171. let len = self.buffer.as_ref().len();
  172. if len < field::RECORD_MCAST_ADDR.end {
  173. Err(Error)
  174. } else {
  175. Ok(())
  176. }
  177. }
  178. /// Consume the packet, returning the underlying buffer.
  179. pub fn into_inner(self) -> T {
  180. self.buffer
  181. }
  182. }
  183. /// Getters for a MLDv2 Listener Report Message Address Record.
  184. /// See [RFC 3810 § 5.2].
  185. ///
  186. /// [RFC 3810 § 5.2]: https://tools.ietf.org/html/rfc3010#section-5.2
  187. impl<T: AsRef<[u8]>> AddressRecord<T> {
  188. /// Return the record type for the given sources.
  189. #[inline]
  190. pub fn record_type(&self) -> RecordType {
  191. let data = self.buffer.as_ref();
  192. RecordType::from(data[field::RECORD_TYPE])
  193. }
  194. /// Return the length of the auxiliary data.
  195. #[inline]
  196. pub fn aux_data_len(&self) -> u8 {
  197. let data = self.buffer.as_ref();
  198. data[field::AUX_DATA_LEN]
  199. }
  200. /// Return the number of sources field.
  201. #[inline]
  202. pub fn num_srcs(&self) -> u16 {
  203. let data = self.buffer.as_ref();
  204. NetworkEndian::read_u16(&data[field::RECORD_NUM_SRCS])
  205. }
  206. /// Return the multicast address field.
  207. #[inline]
  208. pub fn mcast_addr(&self) -> Ipv6Address {
  209. let data = self.buffer.as_ref();
  210. Ipv6Address::from_bytes(&data[field::RECORD_MCAST_ADDR])
  211. }
  212. }
  213. impl<'a, T: AsRef<[u8]> + ?Sized> AddressRecord<&'a T> {
  214. /// Return a pointer to the address records.
  215. #[inline]
  216. pub fn payload(&self) -> &'a [u8] {
  217. let data = self.buffer.as_ref();
  218. &data[field::RECORD_MCAST_ADDR.end..]
  219. }
  220. }
  221. /// Setters for a MLDv2 Listener Report Message Address Record.
  222. /// See [RFC 3810 § 5.2].
  223. ///
  224. /// [RFC 3810 § 5.2]: https://tools.ietf.org/html/rfc3010#section-5.2
  225. impl<T: AsMut<[u8]> + AsRef<[u8]>> AddressRecord<T> {
  226. /// Return the record type for the given sources.
  227. #[inline]
  228. pub fn set_record_type(&mut self, rty: RecordType) {
  229. let data = self.buffer.as_mut();
  230. data[field::RECORD_TYPE] = rty.into();
  231. }
  232. /// Return the length of the auxiliary data.
  233. #[inline]
  234. pub fn set_aux_data_len(&mut self, len: u8) {
  235. let data = self.buffer.as_mut();
  236. data[field::AUX_DATA_LEN] = len;
  237. }
  238. /// Return the number of sources field.
  239. #[inline]
  240. pub fn set_num_srcs(&mut self, num_srcs: u16) {
  241. let data = self.buffer.as_mut();
  242. NetworkEndian::write_u16(&mut data[field::RECORD_NUM_SRCS], num_srcs);
  243. }
  244. /// Return the multicast address field.
  245. ///
  246. /// # Panics
  247. /// This function panics if the given address is not a multicast address.
  248. #[inline]
  249. pub fn set_mcast_addr(&mut self, addr: Ipv6Address) {
  250. assert!(addr.is_multicast());
  251. let data = self.buffer.as_mut();
  252. data[field::RECORD_MCAST_ADDR].copy_from_slice(addr.as_bytes());
  253. }
  254. }
  255. impl<T: AsRef<[u8]> + AsMut<[u8]>> AddressRecord<T> {
  256. /// Return a pointer to the address records.
  257. #[inline]
  258. pub fn payload_mut(&mut self) -> &mut [u8] {
  259. let data = self.buffer.as_mut();
  260. &mut data[field::RECORD_MCAST_ADDR.end..]
  261. }
  262. }
  263. /// A high level representation of an MLDv2 Listener Report Message Address Record.
  264. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  265. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  266. pub struct AddressRecordRepr<'a> {
  267. pub record_type: RecordType,
  268. pub aux_data_len: u8,
  269. pub num_srcs: u16,
  270. pub mcast_addr: Ipv6Address,
  271. pub payload: &'a [u8],
  272. }
  273. impl<'a> AddressRecordRepr<'a> {
  274. /// Create a new MLDv2 address record representation with an empty payload.
  275. pub const fn new(record_type: RecordType, mcast_addr: Ipv6Address) -> Self {
  276. Self {
  277. record_type,
  278. aux_data_len: 0,
  279. num_srcs: 0,
  280. mcast_addr,
  281. payload: &[],
  282. }
  283. }
  284. /// Parse an MLDv2 address record and return a high-level representation.
  285. pub fn parse<T>(record: &AddressRecord<&'a T>) -> Result<Self>
  286. where
  287. T: AsRef<[u8]> + ?Sized,
  288. {
  289. Ok(Self {
  290. num_srcs: record.num_srcs(),
  291. mcast_addr: record.mcast_addr(),
  292. record_type: record.record_type(),
  293. aux_data_len: record.aux_data_len(),
  294. payload: record.payload(),
  295. })
  296. }
  297. /// Return the length of a record that will be emitted from this high-level
  298. /// representation, not including any payload data.
  299. pub fn buffer_len(&self) -> usize {
  300. field::RECORD_MCAST_ADDR.end
  301. }
  302. /// Emit a high-level representation into an MLDv2 address record.
  303. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, record: &mut AddressRecord<T>) {
  304. record.set_record_type(self.record_type);
  305. record.set_aux_data_len(self.aux_data_len);
  306. record.set_num_srcs(self.num_srcs);
  307. record.set_mcast_addr(self.mcast_addr);
  308. }
  309. }
  310. /// A high-level representation of an MLDv2 packet header.
  311. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  312. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  313. pub enum Repr<'a> {
  314. Query {
  315. max_resp_code: u16,
  316. mcast_addr: Ipv6Address,
  317. s_flag: bool,
  318. qrv: u8,
  319. qqic: u8,
  320. num_srcs: u16,
  321. data: &'a [u8],
  322. },
  323. Report {
  324. nr_mcast_addr_rcrds: u16,
  325. data: &'a [u8],
  326. },
  327. ReportRecordReprs(&'a [AddressRecordRepr<'a>]),
  328. }
  329. impl<'a> Repr<'a> {
  330. /// Parse an MLDv2 packet and return a high-level representation.
  331. pub fn parse<T>(packet: &Packet<&'a T>) -> Result<Repr<'a>>
  332. where
  333. T: AsRef<[u8]> + ?Sized,
  334. {
  335. packet.check_len()?;
  336. match packet.msg_type() {
  337. Message::MldQuery => Ok(Repr::Query {
  338. max_resp_code: packet.max_resp_code(),
  339. mcast_addr: packet.mcast_addr(),
  340. s_flag: packet.s_flag(),
  341. qrv: packet.qrv(),
  342. qqic: packet.qqic(),
  343. num_srcs: packet.num_srcs(),
  344. data: packet.payload(),
  345. }),
  346. Message::MldReport => Ok(Repr::Report {
  347. nr_mcast_addr_rcrds: packet.nr_mcast_addr_rcrds(),
  348. data: packet.payload(),
  349. }),
  350. _ => Err(Error),
  351. }
  352. }
  353. /// Return the length of a packet that will be emitted from this high-level representation.
  354. pub const fn buffer_len(&self) -> usize {
  355. match self {
  356. Repr::Query { data, .. } => field::QUERY_NUM_SRCS.end + data.len(),
  357. Repr::Report { data, .. } => field::NR_MCAST_RCRDS.end + data.len(),
  358. Repr::ReportRecordReprs(_data) => field::NR_MCAST_RCRDS.end,
  359. }
  360. }
  361. /// Emit a high-level representation into an MLDv2 packet.
  362. pub fn emit<T>(&self, packet: &mut Packet<&mut T>)
  363. where
  364. T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
  365. {
  366. match self {
  367. Repr::Query {
  368. max_resp_code,
  369. mcast_addr,
  370. s_flag,
  371. qrv,
  372. qqic,
  373. num_srcs,
  374. data,
  375. } => {
  376. packet.set_msg_type(Message::MldQuery);
  377. packet.set_msg_code(0);
  378. packet.clear_reserved();
  379. packet.set_max_resp_code(*max_resp_code);
  380. packet.set_mcast_addr(*mcast_addr);
  381. if *s_flag {
  382. packet.set_s_flag();
  383. } else {
  384. packet.clear_s_flag();
  385. }
  386. packet.set_qrv(*qrv);
  387. packet.set_qqic(*qqic);
  388. packet.set_num_srcs(*num_srcs);
  389. packet.payload_mut().copy_from_slice(&data[..]);
  390. }
  391. Repr::Report {
  392. nr_mcast_addr_rcrds,
  393. data,
  394. } => {
  395. packet.set_msg_type(Message::MldReport);
  396. packet.set_msg_code(0);
  397. packet.clear_reserved();
  398. packet.set_nr_mcast_addr_rcrds(*nr_mcast_addr_rcrds);
  399. packet.payload_mut().copy_from_slice(&data[..]);
  400. }
  401. Repr::ReportRecordReprs(records) => {
  402. packet.set_msg_type(Message::MldReport);
  403. packet.set_msg_code(0);
  404. packet.clear_reserved();
  405. packet.set_nr_mcast_addr_rcrds(records.len() as u16);
  406. let mut payload = packet.payload_mut();
  407. for record in *records {
  408. record.emit(&mut AddressRecord::new_unchecked(&mut *payload));
  409. payload = &mut payload[record.buffer_len()..];
  410. }
  411. }
  412. }
  413. }
  414. }
  415. #[cfg(test)]
  416. mod test {
  417. use super::*;
  418. use crate::phy::ChecksumCapabilities;
  419. use crate::wire::icmpv6::Message;
  420. use crate::wire::Icmpv6Repr;
  421. static QUERY_PACKET_BYTES: [u8; 44] = [
  422. 0x82, 0x00, 0x73, 0x74, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
  423. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x12, 0x00, 0x01, 0xff, 0x02,
  424. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  425. ];
  426. static QUERY_PACKET_PAYLOAD: [u8; 16] = [
  427. 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  428. 0x02,
  429. ];
  430. static REPORT_PACKET_BYTES: [u8; 44] = [
  431. 0x8f, 0x00, 0x73, 0x85, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00,
  432. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02,
  433. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  434. ];
  435. static REPORT_PACKET_PAYLOAD: [u8; 36] = [
  436. 0x01, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  437. 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  438. 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  439. ];
  440. fn create_repr<'a>(ty: Message) -> Icmpv6Repr<'a> {
  441. match ty {
  442. Message::MldQuery => Icmpv6Repr::Mld(Repr::Query {
  443. max_resp_code: 0x400,
  444. mcast_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
  445. s_flag: true,
  446. qrv: 0x02,
  447. qqic: 0x12,
  448. num_srcs: 0x01,
  449. data: &QUERY_PACKET_PAYLOAD,
  450. }),
  451. Message::MldReport => Icmpv6Repr::Mld(Repr::Report {
  452. nr_mcast_addr_rcrds: 1,
  453. data: &REPORT_PACKET_PAYLOAD,
  454. }),
  455. _ => {
  456. panic!("Message type must be a MLDv2 message type");
  457. }
  458. }
  459. }
  460. #[test]
  461. fn test_query_deconstruct() {
  462. let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]);
  463. assert_eq!(packet.msg_type(), Message::MldQuery);
  464. assert_eq!(packet.msg_code(), 0);
  465. assert_eq!(packet.checksum(), 0x7374);
  466. assert_eq!(packet.max_resp_code(), 0x0400);
  467. assert_eq!(packet.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES);
  468. assert!(packet.s_flag());
  469. assert_eq!(packet.qrv(), 0x02);
  470. assert_eq!(packet.qqic(), 0x12);
  471. assert_eq!(packet.num_srcs(), 0x01);
  472. assert_eq!(
  473. Ipv6Address::from_bytes(packet.payload()),
  474. Ipv6Address::LINK_LOCAL_ALL_ROUTERS
  475. );
  476. }
  477. #[test]
  478. fn test_query_construct() {
  479. let mut bytes = vec![0xff; 44];
  480. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  481. packet.set_msg_type(Message::MldQuery);
  482. packet.set_msg_code(0);
  483. packet.set_max_resp_code(0x0400);
  484. packet.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES);
  485. packet.set_s_flag();
  486. packet.set_qrv(0x02);
  487. packet.set_qqic(0x12);
  488. packet.set_num_srcs(0x01);
  489. packet
  490. .payload_mut()
  491. .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
  492. packet.clear_reserved();
  493. packet.fill_checksum(
  494. &Ipv6Address::LINK_LOCAL_ALL_NODES,
  495. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
  496. );
  497. assert_eq!(&*packet.into_inner(), &QUERY_PACKET_BYTES[..]);
  498. }
  499. #[test]
  500. fn test_record_deconstruct() {
  501. let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]);
  502. assert_eq!(packet.msg_type(), Message::MldReport);
  503. assert_eq!(packet.msg_code(), 0);
  504. assert_eq!(packet.checksum(), 0x7385);
  505. assert_eq!(packet.nr_mcast_addr_rcrds(), 0x01);
  506. let addr_rcrd = AddressRecord::new_unchecked(packet.payload());
  507. assert_eq!(addr_rcrd.record_type(), RecordType::ModeIsInclude);
  508. assert_eq!(addr_rcrd.aux_data_len(), 0x00);
  509. assert_eq!(addr_rcrd.num_srcs(), 0x01);
  510. assert_eq!(addr_rcrd.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES);
  511. assert_eq!(
  512. Ipv6Address::from_bytes(addr_rcrd.payload()),
  513. Ipv6Address::LINK_LOCAL_ALL_ROUTERS
  514. );
  515. }
  516. #[test]
  517. fn test_record_construct() {
  518. let mut bytes = vec![0xff; 44];
  519. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  520. packet.set_msg_type(Message::MldReport);
  521. packet.set_msg_code(0);
  522. packet.clear_reserved();
  523. packet.set_nr_mcast_addr_rcrds(1);
  524. {
  525. let mut addr_rcrd = AddressRecord::new_unchecked(packet.payload_mut());
  526. addr_rcrd.set_record_type(RecordType::ModeIsInclude);
  527. addr_rcrd.set_aux_data_len(0);
  528. addr_rcrd.set_num_srcs(1);
  529. addr_rcrd.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES);
  530. addr_rcrd
  531. .payload_mut()
  532. .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
  533. }
  534. packet.fill_checksum(
  535. &Ipv6Address::LINK_LOCAL_ALL_NODES,
  536. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
  537. );
  538. assert_eq!(&*packet.into_inner(), &REPORT_PACKET_BYTES[..]);
  539. }
  540. #[test]
  541. fn test_query_repr_parse() {
  542. let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]);
  543. let repr = Icmpv6Repr::parse(
  544. &Ipv6Address::LINK_LOCAL_ALL_NODES,
  545. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
  546. &packet,
  547. &ChecksumCapabilities::default(),
  548. );
  549. assert_eq!(repr, Ok(create_repr(Message::MldQuery)));
  550. }
  551. #[test]
  552. fn test_report_repr_parse() {
  553. let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]);
  554. let repr = Icmpv6Repr::parse(
  555. &Ipv6Address::LINK_LOCAL_ALL_NODES,
  556. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
  557. &packet,
  558. &ChecksumCapabilities::default(),
  559. );
  560. assert_eq!(repr, Ok(create_repr(Message::MldReport)));
  561. }
  562. #[test]
  563. fn test_query_repr_emit() {
  564. let mut bytes = [0x2a; 44];
  565. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  566. let repr = create_repr(Message::MldQuery);
  567. repr.emit(
  568. &Ipv6Address::LINK_LOCAL_ALL_NODES,
  569. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
  570. &mut packet,
  571. &ChecksumCapabilities::default(),
  572. );
  573. assert_eq!(&*packet.into_inner(), &QUERY_PACKET_BYTES[..]);
  574. }
  575. #[test]
  576. fn test_report_repr_emit() {
  577. let mut bytes = [0x2a; 44];
  578. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  579. let repr = create_repr(Message::MldReport);
  580. repr.emit(
  581. &Ipv6Address::LINK_LOCAL_ALL_NODES,
  582. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
  583. &mut packet,
  584. &ChecksumCapabilities::default(),
  585. );
  586. assert_eq!(&*packet.into_inner(), &REPORT_PACKET_BYTES[..]);
  587. }
  588. }