mld.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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 packet header.
  264. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  265. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  266. pub enum Repr<'a> {
  267. Query {
  268. max_resp_code: u16,
  269. mcast_addr: Ipv6Address,
  270. s_flag: bool,
  271. qrv: u8,
  272. qqic: u8,
  273. num_srcs: u16,
  274. data: &'a [u8],
  275. },
  276. Report {
  277. nr_mcast_addr_rcrds: u16,
  278. data: &'a [u8],
  279. },
  280. }
  281. impl<'a> Repr<'a> {
  282. /// Parse an MLDv2 packet and return a high-level representation.
  283. pub fn parse<T>(packet: &Packet<&'a T>) -> Result<Repr<'a>>
  284. where
  285. T: AsRef<[u8]> + ?Sized,
  286. {
  287. match packet.msg_type() {
  288. Message::MldQuery => Ok(Repr::Query {
  289. max_resp_code: packet.max_resp_code(),
  290. mcast_addr: packet.mcast_addr(),
  291. s_flag: packet.s_flag(),
  292. qrv: packet.qrv(),
  293. qqic: packet.qqic(),
  294. num_srcs: packet.num_srcs(),
  295. data: packet.payload(),
  296. }),
  297. Message::MldReport => Ok(Repr::Report {
  298. nr_mcast_addr_rcrds: packet.nr_mcast_addr_rcrds(),
  299. data: packet.payload(),
  300. }),
  301. _ => Err(Error),
  302. }
  303. }
  304. /// Return the length of a packet that will be emitted from this high-level representation.
  305. pub const fn buffer_len(&self) -> usize {
  306. match self {
  307. Repr::Query { data, .. } => field::QUERY_NUM_SRCS.end + data.len(),
  308. Repr::Report { data, .. } => field::NR_MCAST_RCRDS.end + data.len(),
  309. }
  310. }
  311. /// Emit a high-level representation into an MLDv2 packet.
  312. pub fn emit<T>(&self, packet: &mut Packet<&mut T>)
  313. where
  314. T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
  315. {
  316. match self {
  317. Repr::Query {
  318. max_resp_code,
  319. mcast_addr,
  320. s_flag,
  321. qrv,
  322. qqic,
  323. num_srcs,
  324. data,
  325. } => {
  326. packet.set_msg_type(Message::MldQuery);
  327. packet.set_msg_code(0);
  328. packet.clear_reserved();
  329. packet.set_max_resp_code(*max_resp_code);
  330. packet.set_mcast_addr(*mcast_addr);
  331. if *s_flag {
  332. packet.set_s_flag();
  333. } else {
  334. packet.clear_s_flag();
  335. }
  336. packet.set_qrv(*qrv);
  337. packet.set_qqic(*qqic);
  338. packet.set_num_srcs(*num_srcs);
  339. packet.payload_mut().copy_from_slice(&data[..]);
  340. }
  341. Repr::Report {
  342. nr_mcast_addr_rcrds,
  343. data,
  344. } => {
  345. packet.set_msg_type(Message::MldReport);
  346. packet.set_msg_code(0);
  347. packet.clear_reserved();
  348. packet.set_nr_mcast_addr_rcrds(*nr_mcast_addr_rcrds);
  349. packet.payload_mut().copy_from_slice(&data[..]);
  350. }
  351. }
  352. }
  353. }
  354. #[cfg(test)]
  355. mod test {
  356. use super::*;
  357. use crate::phy::ChecksumCapabilities;
  358. use crate::wire::icmpv6::Message;
  359. use crate::wire::Icmpv6Repr;
  360. static QUERY_PACKET_BYTES: [u8; 44] = [
  361. 0x82, 0x00, 0x73, 0x74, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
  362. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x12, 0x00, 0x01, 0xff, 0x02,
  363. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  364. ];
  365. static QUERY_PACKET_PAYLOAD: [u8; 16] = [
  366. 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  367. 0x02,
  368. ];
  369. static REPORT_PACKET_BYTES: [u8; 44] = [
  370. 0x8f, 0x00, 0x73, 0x85, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00,
  371. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02,
  372. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  373. ];
  374. static REPORT_PACKET_PAYLOAD: [u8; 36] = [
  375. 0x01, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  376. 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  377. 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  378. ];
  379. fn create_repr<'a>(ty: Message) -> Icmpv6Repr<'a> {
  380. match ty {
  381. Message::MldQuery => Icmpv6Repr::Mld(Repr::Query {
  382. max_resp_code: 0x400,
  383. mcast_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
  384. s_flag: true,
  385. qrv: 0x02,
  386. qqic: 0x12,
  387. num_srcs: 0x01,
  388. data: &QUERY_PACKET_PAYLOAD,
  389. }),
  390. Message::MldReport => Icmpv6Repr::Mld(Repr::Report {
  391. nr_mcast_addr_rcrds: 1,
  392. data: &REPORT_PACKET_PAYLOAD,
  393. }),
  394. _ => {
  395. panic!("Message type must be a MLDv2 message type");
  396. }
  397. }
  398. }
  399. #[test]
  400. fn test_query_deconstruct() {
  401. let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]);
  402. assert_eq!(packet.msg_type(), Message::MldQuery);
  403. assert_eq!(packet.msg_code(), 0);
  404. assert_eq!(packet.checksum(), 0x7374);
  405. assert_eq!(packet.max_resp_code(), 0x0400);
  406. assert_eq!(packet.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES);
  407. assert!(packet.s_flag());
  408. assert_eq!(packet.qrv(), 0x02);
  409. assert_eq!(packet.qqic(), 0x12);
  410. assert_eq!(packet.num_srcs(), 0x01);
  411. assert_eq!(
  412. Ipv6Address::from_bytes(packet.payload()),
  413. Ipv6Address::LINK_LOCAL_ALL_ROUTERS
  414. );
  415. }
  416. #[test]
  417. fn test_query_construct() {
  418. let mut bytes = vec![0xff; 44];
  419. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  420. packet.set_msg_type(Message::MldQuery);
  421. packet.set_msg_code(0);
  422. packet.set_max_resp_code(0x0400);
  423. packet.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES);
  424. packet.set_s_flag();
  425. packet.set_qrv(0x02);
  426. packet.set_qqic(0x12);
  427. packet.set_num_srcs(0x01);
  428. packet
  429. .payload_mut()
  430. .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
  431. packet.clear_reserved();
  432. packet.fill_checksum(
  433. &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
  434. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
  435. );
  436. assert_eq!(&*packet.into_inner(), &QUERY_PACKET_BYTES[..]);
  437. }
  438. #[test]
  439. fn test_record_deconstruct() {
  440. let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]);
  441. assert_eq!(packet.msg_type(), Message::MldReport);
  442. assert_eq!(packet.msg_code(), 0);
  443. assert_eq!(packet.checksum(), 0x7385);
  444. assert_eq!(packet.nr_mcast_addr_rcrds(), 0x01);
  445. let addr_rcrd = AddressRecord::new_unchecked(packet.payload());
  446. assert_eq!(addr_rcrd.record_type(), RecordType::ModeIsInclude);
  447. assert_eq!(addr_rcrd.aux_data_len(), 0x00);
  448. assert_eq!(addr_rcrd.num_srcs(), 0x01);
  449. assert_eq!(addr_rcrd.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES);
  450. assert_eq!(
  451. Ipv6Address::from_bytes(addr_rcrd.payload()),
  452. Ipv6Address::LINK_LOCAL_ALL_ROUTERS
  453. );
  454. }
  455. #[test]
  456. fn test_record_construct() {
  457. let mut bytes = vec![0xff; 44];
  458. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  459. packet.set_msg_type(Message::MldReport);
  460. packet.set_msg_code(0);
  461. packet.clear_reserved();
  462. packet.set_nr_mcast_addr_rcrds(1);
  463. {
  464. let mut addr_rcrd = AddressRecord::new_unchecked(packet.payload_mut());
  465. addr_rcrd.set_record_type(RecordType::ModeIsInclude);
  466. addr_rcrd.set_aux_data_len(0);
  467. addr_rcrd.set_num_srcs(1);
  468. addr_rcrd.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES);
  469. addr_rcrd
  470. .payload_mut()
  471. .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
  472. }
  473. packet.fill_checksum(
  474. &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
  475. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
  476. );
  477. assert_eq!(&*packet.into_inner(), &REPORT_PACKET_BYTES[..]);
  478. }
  479. #[test]
  480. fn test_query_repr_parse() {
  481. let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]);
  482. let repr = Icmpv6Repr::parse(
  483. &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
  484. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
  485. &packet,
  486. &ChecksumCapabilities::default(),
  487. );
  488. assert_eq!(repr, Ok(create_repr(Message::MldQuery)));
  489. }
  490. #[test]
  491. fn test_report_repr_parse() {
  492. let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]);
  493. let repr = Icmpv6Repr::parse(
  494. &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
  495. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
  496. &packet,
  497. &ChecksumCapabilities::default(),
  498. );
  499. assert_eq!(repr, Ok(create_repr(Message::MldReport)));
  500. }
  501. #[test]
  502. fn test_query_repr_emit() {
  503. let mut bytes = [0x2a; 44];
  504. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  505. let repr = create_repr(Message::MldQuery);
  506. repr.emit(
  507. &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
  508. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
  509. &mut packet,
  510. &ChecksumCapabilities::default(),
  511. );
  512. assert_eq!(&*packet.into_inner(), &QUERY_PACKET_BYTES[..]);
  513. }
  514. #[test]
  515. fn test_report_repr_emit() {
  516. let mut bytes = [0x2a; 44];
  517. let mut packet = Packet::new_unchecked(&mut bytes[..]);
  518. let repr = create_repr(Message::MldReport);
  519. repr.emit(
  520. &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
  521. &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
  522. &mut packet,
  523. &ChecksumCapabilities::default(),
  524. );
  525. assert_eq!(&*packet.into_inner(), &REPORT_PACKET_BYTES[..]);
  526. }
  527. }