ndisc.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. use byteorder::{ByteOrder, NetworkEndian};
  2. use {Error, Result};
  3. use super::icmpv6::{field, Message, Packet};
  4. use wire::{EthernetAddress, Ipv6Repr, Ipv6Packet};
  5. use wire::{NdiscOption, NdiscOptionRepr, NdiscOptionType, NdiscPrefixInformation, NdiscRedirectedHeader};
  6. use time::Duration;
  7. use super::Ipv6Address;
  8. bitflags! {
  9. pub struct RouterFlags: u8 {
  10. const MANAGED = 0b10000000;
  11. const OTHER = 0b01000000;
  12. }
  13. }
  14. bitflags! {
  15. pub struct NeighborFlags: u8 {
  16. const ROUTER = 0b10000000;
  17. const SOLICITED = 0b01000000;
  18. const OVERRIDE = 0b00100000;
  19. }
  20. }
  21. /// Getters for the Router Advertisement message header.
  22. /// See [RFC 4861 § 4.2].
  23. ///
  24. /// [RFC 4861 § 4.2]: https://tools.ietf.org/html/rfc4861#section-4.2
  25. impl<T: AsRef<[u8]>> Packet<T> {
  26. /// Return the current hop limit field.
  27. #[inline]
  28. pub fn current_hop_limit(&self) -> u8 {
  29. let data = self.buffer.as_ref();
  30. data[field::CUR_HOP_LIMIT]
  31. }
  32. /// Return the Router Advertisement flags.
  33. #[inline]
  34. pub fn router_flags(&self) -> RouterFlags {
  35. let data = self.buffer.as_ref();
  36. RouterFlags::from_bits_truncate(data[field::ROUTER_FLAGS])
  37. }
  38. /// Return the router lifetime field.
  39. #[inline]
  40. pub fn router_lifetime(&self) -> Duration {
  41. let data = self.buffer.as_ref();
  42. Duration::from_secs(NetworkEndian::read_u16(&data[field::ROUTER_LT]) as u64)
  43. }
  44. /// Return the reachable time field.
  45. #[inline]
  46. pub fn reachable_time(&self) -> Duration {
  47. let data = self.buffer.as_ref();
  48. Duration::from_millis(NetworkEndian::read_u32(&data[field::REACHABLE_TM]) as u64)
  49. }
  50. /// Return the retransmit time field.
  51. #[inline]
  52. pub fn retrans_time(&self) -> Duration {
  53. let data = self.buffer.as_ref();
  54. Duration::from_millis(NetworkEndian::read_u32(&data[field::RETRANS_TM]) as u64)
  55. }
  56. }
  57. /// Common getters for the [Neighbor Solicitation], [Neighbor Advertisement], and
  58. /// [Redirect] message types.
  59. ///
  60. /// [Neighbor Solicitation]: https://tools.ietf.org/html/rfc4861#section-4.3
  61. /// [Neighbor Advertisement]: https://tools.ietf.org/html/rfc4861#section-4.4
  62. /// [Redirect]: https://tools.ietf.org/html/rfc4861#section-4.5
  63. impl<T: AsRef<[u8]>> Packet<T> {
  64. /// Return the target address field.
  65. #[inline]
  66. pub fn target_addr(&self) -> Ipv6Address {
  67. let data = self.buffer.as_ref();
  68. Ipv6Address::from_bytes(&data[field::TARGET_ADDR])
  69. }
  70. }
  71. /// Getters for the Neighbor Solicitation message header.
  72. /// See [RFC 4861 § 4.3].
  73. ///
  74. /// [RFC 4861 § 4.3]: https://tools.ietf.org/html/rfc4861#section-4.3
  75. impl<T: AsRef<[u8]>> Packet<T> {
  76. /// Return the Neighbor Solicitation flags.
  77. #[inline]
  78. pub fn neighbor_flags(&self) -> NeighborFlags {
  79. let data = self.buffer.as_ref();
  80. NeighborFlags::from_bits_truncate(data[field::NEIGH_FLAGS])
  81. }
  82. }
  83. /// Getters for the Redirect message header.
  84. /// See [RFC 4861 § 4.5].
  85. ///
  86. /// [RFC 4861 § 4.5]: https://tools.ietf.org/html/rfc4861#section-4.5
  87. impl<T: AsRef<[u8]>> Packet<T> {
  88. /// Return the destination address field.
  89. #[inline]
  90. pub fn dest_addr(&self) -> Ipv6Address {
  91. let data = self.buffer.as_ref();
  92. Ipv6Address::from_bytes(&data[field::DEST_ADDR])
  93. }
  94. }
  95. /// Setters for the Router Solicitation message header.
  96. /// See [RFC 4861 § 4.1].
  97. ///
  98. /// [RFC 4861 § 4.1]: https://tools.ietf.org/html/rfc4861#section-4.1
  99. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  100. /// Clear the reserved field.
  101. #[inline]
  102. pub fn clear_reserved(&mut self) {
  103. let data = self.buffer.as_mut();
  104. NetworkEndian::write_u32(&mut data[field::UNUSED], 0);
  105. }
  106. }
  107. /// Setters for the Router Advertisement message header.
  108. /// See [RFC 4861 § 4.2].
  109. ///
  110. /// [RFC 4861 § 4.2]: https://tools.ietf.org/html/rfc4861#section-4.2
  111. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  112. /// Set the current hop limit field.
  113. #[inline]
  114. pub fn set_current_hop_limit(&mut self, value: u8) {
  115. let data = self.buffer.as_mut();
  116. data[field::CUR_HOP_LIMIT] = value;
  117. }
  118. /// Set the Router Advertisement flags.
  119. #[inline]
  120. pub fn set_router_flags(&mut self, flags: RouterFlags) {
  121. self.buffer.as_mut()[field::ROUTER_FLAGS] = flags.bits();
  122. }
  123. /// Set the router lifetime field.
  124. #[inline]
  125. pub fn set_router_lifetime(&mut self, value: Duration) {
  126. let data = self.buffer.as_mut();
  127. NetworkEndian::write_u16(&mut data[field::ROUTER_LT], value.secs() as u16);
  128. }
  129. /// Set the reachable time field.
  130. #[inline]
  131. pub fn set_reachable_time(&mut self, value: Duration) {
  132. let data = self.buffer.as_mut();
  133. NetworkEndian::write_u32(&mut data[field::REACHABLE_TM], value.total_millis() as u32);
  134. }
  135. /// Set the retransmit time field.
  136. #[inline]
  137. pub fn set_retrans_time(&mut self, value: Duration) {
  138. let data = self.buffer.as_mut();
  139. NetworkEndian::write_u32(&mut data[field::RETRANS_TM], value.total_millis() as u32);
  140. }
  141. }
  142. /// Common setters for the [Neighbor Solicitation], [Neighbor Advertisement], and
  143. /// [Redirect] message types.
  144. ///
  145. /// [Neighbor Solicitation]: https://tools.ietf.org/html/rfc4861#section-4.3
  146. /// [Neighbor Advertisement]: https://tools.ietf.org/html/rfc4861#section-4.4
  147. /// [Redirect]: https://tools.ietf.org/html/rfc4861#section-4.5
  148. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  149. /// Set the target address field.
  150. #[inline]
  151. pub fn set_target_addr(&mut self, value: Ipv6Address) {
  152. let data = self.buffer.as_mut();
  153. data[field::TARGET_ADDR].copy_from_slice(value.as_bytes());
  154. }
  155. }
  156. /// Setters for the Neighbor Solicitation message header.
  157. /// See [RFC 4861 § 4.3].
  158. ///
  159. /// [RFC 4861 § 4.3]: https://tools.ietf.org/html/rfc4861#section-4.3
  160. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  161. /// Set the Neighbor Solicitation flags.
  162. #[inline]
  163. pub fn set_neighbor_flags(&mut self, flags: NeighborFlags) {
  164. self.buffer.as_mut()[field::NEIGH_FLAGS] = flags.bits();
  165. }
  166. }
  167. /// Setters for the Redirect message header.
  168. /// See [RFC 4861 § 4.5].
  169. ///
  170. /// [RFC 4861 § 4.5]: https://tools.ietf.org/html/rfc4861#section-4.5
  171. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  172. /// Set the destination address field.
  173. #[inline]
  174. pub fn set_dest_addr(&mut self, value: Ipv6Address) {
  175. let data = self.buffer.as_mut();
  176. data[field::DEST_ADDR].copy_from_slice(value.as_bytes());
  177. }
  178. }
  179. /// A high-level representation of an Neighbor Discovery packet header.
  180. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  181. pub enum Repr<'a> {
  182. RouterSolicit {
  183. lladdr: Option<EthernetAddress>
  184. },
  185. RouterAdvert {
  186. hop_limit: u8,
  187. flags: RouterFlags,
  188. router_lifetime: Duration,
  189. reachable_time: Duration,
  190. retrans_time: Duration,
  191. lladdr: Option<EthernetAddress>,
  192. mtu: Option<u32>,
  193. prefix_info: Option<NdiscPrefixInformation>
  194. },
  195. NeighborSolicit {
  196. target_addr: Ipv6Address,
  197. lladdr: Option<EthernetAddress>
  198. },
  199. NeighborAdvert {
  200. flags: NeighborFlags,
  201. target_addr: Ipv6Address,
  202. lladdr: Option<EthernetAddress>
  203. },
  204. Redirect {
  205. target_addr: Ipv6Address,
  206. dest_addr: Ipv6Address,
  207. lladdr: Option<EthernetAddress>,
  208. redirected_hdr: Option<NdiscRedirectedHeader<'a>>
  209. }
  210. }
  211. impl<'a> Repr<'a> {
  212. /// Parse an NDISC packet and return a high-level representation of the
  213. /// packet.
  214. pub fn parse<T>(packet: &Packet<&'a T>)
  215. -> Result<Repr<'a>>
  216. where T: AsRef<[u8]> + ?Sized {
  217. match packet.msg_type() {
  218. Message::RouterSolicit => {
  219. let lladdr = if packet.payload().len() > 0 {
  220. let opt = NdiscOption::new_checked(packet.payload())?;
  221. match opt.option_type() {
  222. NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()),
  223. _ => { return Err(Error::Unrecognized); }
  224. }
  225. } else {
  226. None
  227. };
  228. Ok(Repr::RouterSolicit { lladdr })
  229. },
  230. Message::RouterAdvert => {
  231. let mut offset = 0;
  232. let (mut lladdr, mut mtu, mut prefix_info) = (None, None, None);
  233. while packet.payload().len() - offset > 0 {
  234. let pkt = NdiscOption::new_checked(&packet.payload()[offset..])?;
  235. let opt = NdiscOptionRepr::parse(&pkt)?;
  236. match opt {
  237. NdiscOptionRepr::SourceLinkLayerAddr(addr) => lladdr = Some(addr),
  238. NdiscOptionRepr::Mtu(val) => mtu = Some(val),
  239. NdiscOptionRepr::PrefixInformation(info) => prefix_info = Some(info),
  240. _ => { return Err(Error::Unrecognized); }
  241. }
  242. offset += opt.buffer_len();
  243. }
  244. Ok(Repr::RouterAdvert {
  245. hop_limit: packet.current_hop_limit(),
  246. flags: packet.router_flags(),
  247. router_lifetime: packet.router_lifetime(),
  248. reachable_time: packet.reachable_time(),
  249. retrans_time: packet.retrans_time(),
  250. lladdr, mtu, prefix_info
  251. })
  252. },
  253. Message::NeighborSolicit => {
  254. let lladdr = if packet.payload().len() > 0 {
  255. let opt = NdiscOption::new_checked(packet.payload())?;
  256. match opt.option_type() {
  257. NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()),
  258. _ => { return Err(Error::Unrecognized); }
  259. }
  260. } else {
  261. None
  262. };
  263. Ok(Repr::NeighborSolicit {
  264. target_addr: packet.target_addr(), lladdr
  265. })
  266. },
  267. Message::NeighborAdvert => {
  268. let lladdr = if packet.payload().len() > 0 {
  269. let opt = NdiscOption::new_checked(packet.payload())?;
  270. match opt.option_type() {
  271. NdiscOptionType::TargetLinkLayerAddr => Some(opt.link_layer_addr()),
  272. _ => { return Err(Error::Unrecognized); }
  273. }
  274. } else {
  275. None
  276. };
  277. Ok(Repr::NeighborAdvert {
  278. flags: packet.neighbor_flags(),
  279. target_addr: packet.target_addr(),
  280. lladdr
  281. })
  282. },
  283. Message::Redirect => {
  284. let mut offset = 0;
  285. let (mut lladdr, mut redirected_hdr) = (None, None);
  286. while packet.payload().len() - offset > 0 {
  287. let opt = NdiscOption::new_checked(&packet.payload()[offset..])?;
  288. match opt.option_type() {
  289. NdiscOptionType::SourceLinkLayerAddr => {
  290. lladdr = Some(opt.link_layer_addr());
  291. offset += 8;
  292. },
  293. NdiscOptionType::RedirectedHeader => {
  294. if opt.data_len() < 6 {
  295. return Err(Error::Truncated)
  296. } else {
  297. let ip_packet = Ipv6Packet::new(&opt.data()[offset + 8..]);
  298. let ip_repr = Ipv6Repr::parse(&ip_packet)?;
  299. let data = &opt.data()[offset + 8 + ip_repr.buffer_len()..];
  300. redirected_hdr = Some(NdiscRedirectedHeader {
  301. header: ip_repr, data
  302. });
  303. offset += 8 + ip_repr.buffer_len() + data.len();
  304. }
  305. }
  306. _ => { return Err(Error::Unrecognized); }
  307. }
  308. }
  309. Ok(Repr::Redirect {
  310. target_addr: packet.target_addr(),
  311. dest_addr: packet.dest_addr(),
  312. lladdr, redirected_hdr
  313. })
  314. },
  315. _ => Err(Error::Unrecognized)
  316. }
  317. }
  318. pub fn buffer_len(&self) -> usize {
  319. match self {
  320. &Repr::RouterSolicit { lladdr } => {
  321. match lladdr {
  322. Some(_) => field::UNUSED.end + 8,
  323. None => field::UNUSED.end,
  324. }
  325. },
  326. &Repr::RouterAdvert { lladdr, mtu, prefix_info, .. } => {
  327. let mut offset = 0;
  328. if lladdr.is_some() {
  329. offset += 8;
  330. }
  331. if mtu.is_some() {
  332. offset += 8;
  333. }
  334. if prefix_info.is_some() {
  335. offset += 32;
  336. }
  337. field::RETRANS_TM.end + offset
  338. },
  339. &Repr::NeighborSolicit { lladdr, .. } | &Repr::NeighborAdvert { lladdr, .. } => {
  340. match lladdr {
  341. Some(_) => field::TARGET_ADDR.end + 8,
  342. None => field::TARGET_ADDR.end,
  343. }
  344. },
  345. &Repr::Redirect { lladdr, redirected_hdr, .. } => {
  346. let mut offset = 0;
  347. if lladdr.is_some() {
  348. offset += 8;
  349. }
  350. if let Some(NdiscRedirectedHeader { header, data }) = redirected_hdr {
  351. offset += 8 + header.buffer_len() + data.len();
  352. }
  353. field::DEST_ADDR.end + offset
  354. }
  355. }
  356. }
  357. pub fn emit<T>(&self, packet: &mut Packet<&mut T>)
  358. where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
  359. match self {
  360. &Repr::RouterSolicit { lladdr } => {
  361. packet.set_msg_type(Message::RouterSolicit);
  362. packet.set_msg_code(0);
  363. packet.clear_reserved();
  364. if let Some(lladdr) = lladdr {
  365. let mut opt_pkt = NdiscOption::new(packet.payload_mut());
  366. NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt);
  367. }
  368. },
  369. &Repr::RouterAdvert { hop_limit, flags, router_lifetime, reachable_time,
  370. retrans_time, lladdr, mtu, prefix_info } => {
  371. packet.set_msg_type(Message::RouterAdvert);
  372. packet.set_msg_code(0);
  373. packet.set_current_hop_limit(hop_limit);
  374. packet.set_router_flags(flags);
  375. packet.set_router_lifetime(router_lifetime);
  376. packet.set_reachable_time(reachable_time);
  377. packet.set_retrans_time(retrans_time);
  378. let mut offset = 0;
  379. if let Some(lladdr) = lladdr {
  380. let mut opt_pkt = NdiscOption::new(packet.payload_mut());
  381. NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt);
  382. offset += 8;
  383. }
  384. if let Some(mtu) = mtu {
  385. let mut opt_pkt = NdiscOption::new(&mut packet.payload_mut()[offset..]);
  386. NdiscOptionRepr::Mtu(mtu).emit(&mut opt_pkt);
  387. offset += 8;
  388. }
  389. if let Some(prefix_info) = prefix_info {
  390. let mut opt_pkt = NdiscOption::new(&mut packet.payload_mut()[offset..]);
  391. NdiscOptionRepr::PrefixInformation(prefix_info).emit(&mut opt_pkt)
  392. }
  393. },
  394. &Repr::NeighborSolicit { target_addr, lladdr } => {
  395. packet.set_msg_type(Message::NeighborSolicit);
  396. packet.set_msg_code(0);
  397. packet.clear_reserved();
  398. packet.set_target_addr(target_addr);
  399. if let Some(lladdr) = lladdr {
  400. let mut opt_pkt = NdiscOption::new(packet.payload_mut());
  401. NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt);
  402. }
  403. },
  404. &Repr::NeighborAdvert { flags, target_addr, lladdr } => {
  405. packet.set_msg_type(Message::NeighborAdvert);
  406. packet.set_msg_code(0);
  407. packet.clear_reserved();
  408. packet.set_neighbor_flags(flags);
  409. packet.set_target_addr(target_addr);
  410. if let Some(lladdr) = lladdr {
  411. let mut opt_pkt = NdiscOption::new(packet.payload_mut());
  412. NdiscOptionRepr::TargetLinkLayerAddr(lladdr).emit(&mut opt_pkt);
  413. }
  414. },
  415. &Repr::Redirect { target_addr, dest_addr, lladdr, redirected_hdr } => {
  416. packet.set_msg_type(Message::Redirect);
  417. packet.set_msg_code(0);
  418. packet.clear_reserved();
  419. packet.set_target_addr(target_addr);
  420. packet.set_dest_addr(dest_addr);
  421. let offset = match lladdr {
  422. Some(lladdr) => {
  423. let mut opt_pkt = NdiscOption::new(packet.payload_mut());
  424. NdiscOptionRepr::TargetLinkLayerAddr(lladdr).emit(&mut opt_pkt);
  425. 8
  426. },
  427. None => 0,
  428. };
  429. if let Some(redirected_hdr) = redirected_hdr {
  430. let mut opt_pkt = NdiscOption::new(&mut packet.payload_mut()[offset..]);
  431. NdiscOptionRepr::RedirectedHeader(redirected_hdr).emit(&mut opt_pkt);
  432. }
  433. },
  434. }
  435. }
  436. }
  437. #[cfg(test)]
  438. mod test {
  439. use phy::ChecksumCapabilities;
  440. use super::*;
  441. use wire::Icmpv6Repr;
  442. use wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2};
  443. static ROUTER_ADVERT_BYTES: [u8; 24] =
  444. [0x86, 0x00, 0xa9, 0xde,
  445. 0x40, 0x80, 0x03, 0x84,
  446. 0x00, 0x00, 0x03, 0x84,
  447. 0x00, 0x00, 0x03, 0x84,
  448. 0x01, 0x01, 0x52, 0x54,
  449. 0x00, 0x12, 0x34, 0x56];
  450. static SOURCE_LINK_LAYER_OPT: [u8; 8] =
  451. [0x01, 0x01, 0x52, 0x54,
  452. 0x00, 0x12, 0x34, 0x56];
  453. fn create_repr<'a>() -> Icmpv6Repr<'a> {
  454. Icmpv6Repr::Ndisc(Repr::RouterAdvert {
  455. hop_limit: 64,
  456. flags: RouterFlags::MANAGED,
  457. router_lifetime: Duration::from_secs(900),
  458. reachable_time: Duration::from_millis(900),
  459. retrans_time: Duration::from_millis(900),
  460. lladdr: Some(EthernetAddress([0x52, 0x54, 0x00, 0x12, 0x34, 0x56])),
  461. mtu: None,
  462. prefix_info: None
  463. })
  464. }
  465. #[test]
  466. fn test_router_advert_deconstruct() {
  467. let packet = Packet::new(&ROUTER_ADVERT_BYTES[..]);
  468. assert_eq!(packet.msg_type(), Message::RouterAdvert);
  469. assert_eq!(packet.msg_code(), 0);
  470. assert_eq!(packet.current_hop_limit(), 64);
  471. assert_eq!(packet.router_flags(), RouterFlags::MANAGED);
  472. assert_eq!(packet.router_lifetime(), Duration::from_secs(900));
  473. assert_eq!(packet.reachable_time(), Duration::from_millis(900));
  474. assert_eq!(packet.retrans_time(), Duration::from_millis(900));
  475. assert_eq!(packet.payload(), &SOURCE_LINK_LAYER_OPT[..]);
  476. }
  477. #[test]
  478. fn test_router_advert_construct() {
  479. let mut bytes = vec![0x0; 24];
  480. let mut packet = Packet::new(&mut bytes);
  481. packet.set_msg_type(Message::RouterAdvert);
  482. packet.set_msg_code(0);
  483. packet.set_current_hop_limit(64);
  484. packet.set_router_flags(RouterFlags::MANAGED);
  485. packet.set_router_lifetime(Duration::from_secs(900));
  486. packet.set_reachable_time(Duration::from_millis(900));
  487. packet.set_retrans_time(Duration::from_millis(900));
  488. packet.payload_mut().copy_from_slice(&SOURCE_LINK_LAYER_OPT[..]);
  489. packet.fill_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2);
  490. assert_eq!(&packet.into_inner()[..], &ROUTER_ADVERT_BYTES[..]);
  491. }
  492. #[test]
  493. fn test_router_advert_repr_parse() {
  494. let packet = Packet::new(&ROUTER_ADVERT_BYTES[..]);
  495. assert_eq!(Icmpv6Repr::parse(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2,
  496. &packet, &ChecksumCapabilities::default()).unwrap(),
  497. create_repr());
  498. }
  499. #[test]
  500. fn test_router_advert_repr_emit() {
  501. let mut bytes = vec![0x2a; 24];
  502. let mut packet = Packet::new(&mut bytes[..]);
  503. create_repr().emit(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2,
  504. &mut packet, &ChecksumCapabilities::default());
  505. assert_eq!(&packet.into_inner()[..], &ROUTER_ADVERT_BYTES[..]);
  506. }
  507. }