ipv6.rs 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  1. use super::*;
  2. fn parse_ipv6(data: &[u8]) -> crate::wire::Result<Packet<'_>> {
  3. let ipv6_header = Ipv6Packet::new_checked(data)?;
  4. let ipv6 = Ipv6Repr::parse(&ipv6_header)?;
  5. match ipv6.next_header {
  6. IpProtocol::HopByHop => todo!(),
  7. IpProtocol::Icmp => todo!(),
  8. IpProtocol::Igmp => todo!(),
  9. IpProtocol::Tcp => todo!(),
  10. IpProtocol::Udp => todo!(),
  11. IpProtocol::Ipv6Route => todo!(),
  12. IpProtocol::Ipv6Frag => todo!(),
  13. IpProtocol::IpSecEsp => todo!(),
  14. IpProtocol::IpSecAh => todo!(),
  15. IpProtocol::Icmpv6 => {
  16. let icmp = Icmpv6Repr::parse(
  17. &ipv6.src_addr,
  18. &ipv6.dst_addr,
  19. &Icmpv6Packet::new_checked(ipv6_header.payload())?,
  20. &Default::default(),
  21. )?;
  22. Ok(Packet::new_ipv6(ipv6, IpPayload::Icmpv6(icmp)))
  23. }
  24. IpProtocol::Ipv6NoNxt => todo!(),
  25. IpProtocol::Ipv6Opts => todo!(),
  26. IpProtocol::Unknown(_) => todo!(),
  27. }
  28. }
  29. #[rstest]
  30. #[case::ip(Medium::Ip)]
  31. #[cfg(feature = "medium-ip")]
  32. #[case::ethernet(Medium::Ethernet)]
  33. #[cfg(feature = "medium-ethernet")]
  34. #[case::ieee802154(Medium::Ieee802154)]
  35. #[cfg(feature = "medium-ieee802154")]
  36. fn multicast_source_address(#[case] medium: Medium) {
  37. let data = [
  38. 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x40, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  39. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  40. 0x0, 0x0, 0x0, 0x0, 0x1,
  41. ];
  42. let response = None;
  43. let (mut iface, mut sockets, _device) = setup(medium);
  44. assert_eq!(
  45. iface.inner.process_ipv6(
  46. &mut sockets,
  47. PacketMeta::default(),
  48. &Ipv6Packet::new_checked(&data[..]).unwrap()
  49. ),
  50. response
  51. );
  52. }
  53. #[rstest]
  54. #[case::ip(Medium::Ip)]
  55. #[cfg(feature = "medium-ip")]
  56. #[case::ethernet(Medium::Ethernet)]
  57. #[cfg(feature = "medium-ethernet")]
  58. #[case::ieee802154(Medium::Ieee802154)]
  59. #[cfg(feature = "medium-ieee802154")]
  60. fn hop_by_hop_skip_with_icmp(#[case] medium: Medium) {
  61. // The following contains:
  62. // - IPv6 header
  63. // - Hop-by-hop, with options:
  64. // - PADN (skipped)
  65. // - Unknown option (skipped)
  66. // - ICMP echo request
  67. let data = [
  68. 0x60, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x0, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  69. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  70. 0x0, 0x0, 0x0, 0x0, 0x1, 0x3a, 0x0, 0x1, 0x0, 0xf, 0x0, 0x1, 0x0, 0x80, 0x0, 0x2c, 0x88,
  71. 0x0, 0x2a, 0x1, 0xa4, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d,
  72. ];
  73. let response = Some(Packet::new_ipv6(
  74. Ipv6Repr {
  75. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  76. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  77. hop_limit: 64,
  78. next_header: IpProtocol::Icmpv6,
  79. payload_len: 19,
  80. },
  81. IpPayload::Icmpv6(Icmpv6Repr::EchoReply {
  82. ident: 42,
  83. seq_no: 420,
  84. data: b"Lorem Ipsum",
  85. }),
  86. ));
  87. let (mut iface, mut sockets, _device) = setup(medium);
  88. assert_eq!(
  89. iface.inner.process_ipv6(
  90. &mut sockets,
  91. PacketMeta::default(),
  92. &Ipv6Packet::new_checked(&data[..]).unwrap()
  93. ),
  94. response
  95. );
  96. }
  97. #[rstest]
  98. #[case::ip(Medium::Ip)]
  99. #[cfg(feature = "medium-ip")]
  100. #[case::ethernet(Medium::Ethernet)]
  101. #[cfg(feature = "medium-ethernet")]
  102. #[case::ieee802154(Medium::Ieee802154)]
  103. #[cfg(feature = "medium-ieee802154")]
  104. fn hop_by_hop_discard_with_icmp(#[case] medium: Medium) {
  105. // The following contains:
  106. // - IPv6 header
  107. // - Hop-by-hop, with options:
  108. // - PADN (skipped)
  109. // - Unknown option (discard)
  110. // - ICMP echo request
  111. let data = [
  112. 0x60, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x0, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  113. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  114. 0x0, 0x0, 0x0, 0x0, 0x1, 0x3a, 0x0, 0x1, 0x0, 0x40, 0x0, 0x1, 0x0, 0x80, 0x0, 0x2c, 0x88,
  115. 0x0, 0x2a, 0x1, 0xa4, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d,
  116. ];
  117. let response = None;
  118. let (mut iface, mut sockets, _device) = setup(medium);
  119. assert_eq!(
  120. iface.inner.process_ipv6(
  121. &mut sockets,
  122. PacketMeta::default(),
  123. &Ipv6Packet::new_checked(&data[..]).unwrap()
  124. ),
  125. response
  126. );
  127. }
  128. #[rstest]
  129. #[case::ip(Medium::Ip)]
  130. #[cfg(feature = "medium-ip")]
  131. fn hop_by_hop_discard_param_problem(#[case] medium: Medium) {
  132. // The following contains:
  133. // - IPv6 header
  134. // - Hop-by-hop, with options:
  135. // - PADN (skipped)
  136. // - Unknown option (discard + ParamProblem)
  137. // - ICMP echo request
  138. let data = [
  139. 0x60, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x0, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  140. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  141. 0x0, 0x0, 0x0, 0x0, 0x1, 0x3a, 0x0, 0xC0, 0x0, 0x40, 0x0, 0x1, 0x0, 0x80, 0x0, 0x2c, 0x88,
  142. 0x0, 0x2a, 0x1, 0xa4, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d,
  143. ];
  144. let response = Some(Packet::new_ipv6(
  145. Ipv6Repr {
  146. src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 1),
  147. dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 2),
  148. next_header: IpProtocol::Icmpv6,
  149. payload_len: 75,
  150. hop_limit: 64,
  151. },
  152. IpPayload::Icmpv6(Icmpv6Repr::ParamProblem {
  153. reason: Icmpv6ParamProblem::UnrecognizedOption,
  154. pointer: 40,
  155. header: Ipv6Repr {
  156. src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 2),
  157. dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 1),
  158. next_header: IpProtocol::HopByHop,
  159. payload_len: 27,
  160. hop_limit: 64,
  161. },
  162. data: &[
  163. 0x3a, 0x0, 0xC0, 0x0, 0x40, 0x0, 0x1, 0x0, 0x80, 0x0, 0x2c, 0x88, 0x0, 0x2a, 0x1,
  164. 0xa4, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d,
  165. ],
  166. }),
  167. ));
  168. let (mut iface, mut sockets, _device) = setup(medium);
  169. assert_eq!(
  170. iface.inner.process_ipv6(
  171. &mut sockets,
  172. PacketMeta::default(),
  173. &Ipv6Packet::new_checked(&data[..]).unwrap()
  174. ),
  175. response
  176. );
  177. }
  178. #[rstest]
  179. #[case::ip(Medium::Ip)]
  180. #[cfg(feature = "medium-ip")]
  181. fn hop_by_hop_discard_with_multicast(#[case] medium: Medium) {
  182. // The following contains:
  183. // - IPv6 header
  184. // - Hop-by-hop, with options:
  185. // - PADN (skipped)
  186. // - Unknown option (discard (0b11) + ParamProblem)
  187. // - ICMP echo request
  188. //
  189. // In this case, even if the destination address is a multicast address, an ICMPv6 ParamProblem
  190. // should be transmitted.
  191. let data = [
  192. 0x60, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x0, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  193. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  194. 0x0, 0x0, 0x0, 0x0, 0x1, 0x3a, 0x0, 0x80, 0x0, 0x40, 0x0, 0x1, 0x0, 0x80, 0x0, 0x2c, 0x88,
  195. 0x0, 0x2a, 0x1, 0xa4, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d,
  196. ];
  197. let response = Some(Packet::new_ipv6(
  198. Ipv6Repr {
  199. src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 1),
  200. dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 2),
  201. next_header: IpProtocol::Icmpv6,
  202. payload_len: 75,
  203. hop_limit: 64,
  204. },
  205. IpPayload::Icmpv6(Icmpv6Repr::ParamProblem {
  206. reason: Icmpv6ParamProblem::UnrecognizedOption,
  207. pointer: 40,
  208. header: Ipv6Repr {
  209. src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 2),
  210. dst_addr: Ipv6Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
  211. next_header: IpProtocol::HopByHop,
  212. payload_len: 27,
  213. hop_limit: 64,
  214. },
  215. data: &[
  216. 0x3a, 0x0, 0x80, 0x0, 0x40, 0x0, 0x1, 0x0, 0x80, 0x0, 0x2c, 0x88, 0x0, 0x2a, 0x1,
  217. 0xa4, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d,
  218. ],
  219. }),
  220. ));
  221. let (mut iface, mut sockets, _device) = setup(medium);
  222. assert_eq!(
  223. iface.inner.process_ipv6(
  224. &mut sockets,
  225. PacketMeta::default(),
  226. &Ipv6Packet::new_checked(&data[..]).unwrap()
  227. ),
  228. response
  229. );
  230. }
  231. #[rstest]
  232. #[case::ip(Medium::Ip)]
  233. #[cfg(feature = "medium-ip")]
  234. #[case::ethernet(Medium::Ethernet)]
  235. #[cfg(feature = "medium-ethernet")]
  236. #[case::ieee802154(Medium::Ieee802154)]
  237. #[cfg(feature = "medium-ieee802154")]
  238. fn imcp_empty_echo_request(#[case] medium: Medium) {
  239. let data = [
  240. 0x60, 0x0, 0x0, 0x0, 0x0, 0x8, 0x3a, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  241. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  242. 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x84, 0x3c, 0x0, 0x0, 0x0, 0x0,
  243. ];
  244. assert_eq!(
  245. parse_ipv6(&data),
  246. Ok(Packet::new_ipv6(
  247. Ipv6Repr {
  248. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  249. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  250. hop_limit: 64,
  251. next_header: IpProtocol::Icmpv6,
  252. payload_len: 8,
  253. },
  254. IpPayload::Icmpv6(Icmpv6Repr::EchoRequest {
  255. ident: 0,
  256. seq_no: 0,
  257. data: b"",
  258. })
  259. ))
  260. );
  261. let response = Some(Packet::new_ipv6(
  262. Ipv6Repr {
  263. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  264. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  265. hop_limit: 64,
  266. next_header: IpProtocol::Icmpv6,
  267. payload_len: 8,
  268. },
  269. IpPayload::Icmpv6(Icmpv6Repr::EchoReply {
  270. ident: 0,
  271. seq_no: 0,
  272. data: b"",
  273. }),
  274. ));
  275. let (mut iface, mut sockets, _device) = setup(medium);
  276. assert_eq!(
  277. iface.inner.process_ipv6(
  278. &mut sockets,
  279. PacketMeta::default(),
  280. &Ipv6Packet::new_checked(&data[..]).unwrap()
  281. ),
  282. response
  283. );
  284. }
  285. #[rstest]
  286. #[case::ip(Medium::Ip)]
  287. #[cfg(feature = "medium-ip")]
  288. #[case::ethernet(Medium::Ethernet)]
  289. #[cfg(feature = "medium-ethernet")]
  290. #[case::ieee802154(Medium::Ieee802154)]
  291. #[cfg(feature = "medium-ieee802154")]
  292. fn icmp_echo_request(#[case] medium: Medium) {
  293. let data = [
  294. 0x60, 0x0, 0x0, 0x0, 0x0, 0x13, 0x3a, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  295. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  296. 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x2c, 0x88, 0x0, 0x2a, 0x1, 0xa4, 0x4c, 0x6f, 0x72,
  297. 0x65, 0x6d, 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d,
  298. ];
  299. assert_eq!(
  300. parse_ipv6(&data),
  301. Ok(Packet::new_ipv6(
  302. Ipv6Repr {
  303. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  304. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  305. hop_limit: 64,
  306. next_header: IpProtocol::Icmpv6,
  307. payload_len: 19,
  308. },
  309. IpPayload::Icmpv6(Icmpv6Repr::EchoRequest {
  310. ident: 42,
  311. seq_no: 420,
  312. data: b"Lorem Ipsum",
  313. })
  314. ))
  315. );
  316. let response = Some(Packet::new_ipv6(
  317. Ipv6Repr {
  318. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  319. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  320. hop_limit: 64,
  321. next_header: IpProtocol::Icmpv6,
  322. payload_len: 19,
  323. },
  324. IpPayload::Icmpv6(Icmpv6Repr::EchoReply {
  325. ident: 42,
  326. seq_no: 420,
  327. data: b"Lorem Ipsum",
  328. }),
  329. ));
  330. let (mut iface, mut sockets, _device) = setup(medium);
  331. assert_eq!(
  332. iface.inner.process_ipv6(
  333. &mut sockets,
  334. PacketMeta::default(),
  335. &Ipv6Packet::new_checked(&data[..]).unwrap()
  336. ),
  337. response
  338. );
  339. }
  340. #[rstest]
  341. #[case::ip(Medium::Ip)]
  342. #[cfg(feature = "medium-ip")]
  343. #[case::ethernet(Medium::Ethernet)]
  344. #[cfg(feature = "medium-ethernet")]
  345. #[case::ieee802154(Medium::Ieee802154)]
  346. #[cfg(feature = "medium-ieee802154")]
  347. fn icmp_echo_reply_as_input(#[case] medium: Medium) {
  348. let data = [
  349. 0x60, 0x0, 0x0, 0x0, 0x0, 0x13, 0x3a, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  350. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  351. 0x0, 0x0, 0x0, 0x0, 0x1, 0x81, 0x0, 0x2d, 0x56, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x6f, 0x72, 0x65,
  352. 0x6d, 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d,
  353. ];
  354. assert_eq!(
  355. parse_ipv6(&data),
  356. Ok(Packet::new_ipv6(
  357. Ipv6Repr {
  358. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  359. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  360. hop_limit: 64,
  361. next_header: IpProtocol::Icmpv6,
  362. payload_len: 19,
  363. },
  364. IpPayload::Icmpv6(Icmpv6Repr::EchoReply {
  365. ident: 0,
  366. seq_no: 0,
  367. data: b"Lorem Ipsum",
  368. })
  369. ))
  370. );
  371. let response = None;
  372. let (mut iface, mut sockets, _device) = setup(medium);
  373. assert_eq!(
  374. iface.inner.process_ipv6(
  375. &mut sockets,
  376. PacketMeta::default(),
  377. &Ipv6Packet::new_checked(&data[..]).unwrap()
  378. ),
  379. response
  380. );
  381. }
  382. #[rstest]
  383. #[case::ip(Medium::Ip)]
  384. #[cfg(feature = "medium-ip")]
  385. #[case::ethernet(Medium::Ethernet)]
  386. #[cfg(feature = "medium-ethernet")]
  387. #[case::ieee802154(Medium::Ieee802154)]
  388. #[cfg(feature = "medium-ieee802154")]
  389. fn unknown_proto_with_multicast_dst_address(#[case] medium: Medium) {
  390. let data = [
  391. 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  392. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  393. 0x0, 0x0, 0x0, 0x0, 0x1,
  394. ];
  395. let response = Some(Packet::new_ipv6(
  396. Ipv6Repr {
  397. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  398. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  399. hop_limit: 64,
  400. next_header: IpProtocol::Icmpv6,
  401. payload_len: 48,
  402. },
  403. IpPayload::Icmpv6(Icmpv6Repr::ParamProblem {
  404. reason: Icmpv6ParamProblem::UnrecognizedNxtHdr,
  405. pointer: 40,
  406. header: Ipv6Repr {
  407. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  408. dst_addr: Ipv6Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 0x0001]),
  409. hop_limit: 64,
  410. next_header: IpProtocol::Unknown(0x0c),
  411. payload_len: 0,
  412. },
  413. data: &[],
  414. }),
  415. ));
  416. let (mut iface, mut sockets, _device) = setup(medium);
  417. assert_eq!(
  418. iface.inner.process_ipv6(
  419. &mut sockets,
  420. PacketMeta::default(),
  421. &Ipv6Packet::new_checked(&data[..]).unwrap()
  422. ),
  423. response
  424. );
  425. }
  426. #[rstest]
  427. #[case::ip(Medium::Ip)]
  428. #[cfg(feature = "medium-ip")]
  429. #[case::ethernet(Medium::Ethernet)]
  430. #[cfg(feature = "medium-ethernet")]
  431. #[case::ieee802154(Medium::Ieee802154)]
  432. #[cfg(feature = "medium-ieee802154")]
  433. fn unknown_proto(#[case] medium: Medium) {
  434. // Since the destination address is multicast, we should answer with an ICMPv6 message.
  435. let data = [
  436. 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x40, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  437. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  438. 0x0, 0x0, 0x0, 0x0, 0x1,
  439. ];
  440. let response = Some(Packet::new_ipv6(
  441. Ipv6Repr {
  442. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  443. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  444. hop_limit: 64,
  445. next_header: IpProtocol::Icmpv6,
  446. payload_len: 48,
  447. },
  448. IpPayload::Icmpv6(Icmpv6Repr::ParamProblem {
  449. reason: Icmpv6ParamProblem::UnrecognizedNxtHdr,
  450. pointer: 40,
  451. header: Ipv6Repr {
  452. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  453. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  454. hop_limit: 64,
  455. next_header: IpProtocol::Unknown(0x0c),
  456. payload_len: 0,
  457. },
  458. data: &[],
  459. }),
  460. ));
  461. let (mut iface, mut sockets, _device) = setup(medium);
  462. assert_eq!(
  463. iface.inner.process_ipv6(
  464. &mut sockets,
  465. PacketMeta::default(),
  466. &Ipv6Packet::new_checked(&data[..]).unwrap()
  467. ),
  468. response
  469. );
  470. }
  471. #[rstest]
  472. #[case::ethernet(Medium::Ethernet)]
  473. #[cfg(feature = "medium-ethernet")]
  474. fn ndsic_neighbor_advertisement_ethernet(#[case] medium: Medium) {
  475. let data = [
  476. 0x60, 0x0, 0x0, 0x0, 0x0, 0x20, 0x3a, 0xff, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  477. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  478. 0x0, 0x0, 0x0, 0x0, 0x1, 0x88, 0x0, 0x3b, 0x9f, 0x40, 0x0, 0x0, 0x0, 0xfe, 0x80, 0x0, 0x0,
  479. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0,
  480. 0x0, 0x1,
  481. ];
  482. assert_eq!(
  483. parse_ipv6(&data),
  484. Ok(Packet::new_ipv6(
  485. Ipv6Repr {
  486. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  487. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  488. hop_limit: 255,
  489. next_header: IpProtocol::Icmpv6,
  490. payload_len: 32,
  491. },
  492. IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
  493. flags: NdiscNeighborFlags::SOLICITED,
  494. target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]),
  495. lladdr: Some(RawHardwareAddress::from_bytes(&[0, 0, 0, 0, 0, 1])),
  496. }))
  497. ))
  498. );
  499. let response = None;
  500. let (mut iface, mut sockets, _device) = setup(medium);
  501. assert_eq!(
  502. iface.inner.process_ipv6(
  503. &mut sockets,
  504. PacketMeta::default(),
  505. &Ipv6Packet::new_checked(&data[..]).unwrap()
  506. ),
  507. response
  508. );
  509. assert_eq!(
  510. iface.inner.neighbor_cache.lookup(
  511. &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])),
  512. iface.inner.now,
  513. ),
  514. NeighborAnswer::Found(HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  515. 0, 0, 0, 0, 0, 1
  516. ]))),
  517. );
  518. }
  519. #[rstest]
  520. #[case::ethernet(Medium::Ethernet)]
  521. #[cfg(feature = "medium-ethernet")]
  522. fn ndsic_neighbor_advertisement_ethernet_multicast_addr(#[case] medium: Medium) {
  523. let data = [
  524. 0x60, 0x0, 0x0, 0x0, 0x0, 0x20, 0x3a, 0xff, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  525. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  526. 0x0, 0x0, 0x0, 0x0, 0x1, 0x88, 0x0, 0x3b, 0xa0, 0x40, 0x0, 0x0, 0x0, 0xfe, 0x80, 0x0, 0x0,
  527. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x2, 0x1, 0xff, 0xff, 0xff,
  528. 0xff, 0xff, 0xff,
  529. ];
  530. assert_eq!(
  531. parse_ipv6(&data),
  532. Ok(Packet::new_ipv6(
  533. Ipv6Repr {
  534. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  535. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  536. hop_limit: 255,
  537. next_header: IpProtocol::Icmpv6,
  538. payload_len: 32,
  539. },
  540. IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
  541. flags: NdiscNeighborFlags::SOLICITED,
  542. target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]),
  543. lladdr: Some(RawHardwareAddress::from_bytes(&[
  544. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  545. ])),
  546. }))
  547. ))
  548. );
  549. let response = None;
  550. let (mut iface, mut sockets, _device) = setup(medium);
  551. assert_eq!(
  552. iface.inner.process_ipv6(
  553. &mut sockets,
  554. PacketMeta::default(),
  555. &Ipv6Packet::new_checked(&data[..]).unwrap()
  556. ),
  557. response
  558. );
  559. assert_eq!(
  560. iface.inner.neighbor_cache.lookup(
  561. &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])),
  562. iface.inner.now,
  563. ),
  564. NeighborAnswer::NotFound,
  565. );
  566. }
  567. #[rstest]
  568. #[case::ieee802154(Medium::Ieee802154)]
  569. #[cfg(feature = "medium-ieee802154")]
  570. fn ndsic_neighbor_advertisement_ieee802154(#[case] medium: Medium) {
  571. let data = [
  572. 0x60, 0x0, 0x0, 0x0, 0x0, 0x28, 0x3a, 0xff, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  573. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  574. 0x0, 0x0, 0x0, 0x0, 0x1, 0x88, 0x0, 0x3b, 0x96, 0x40, 0x0, 0x0, 0x0, 0xfe, 0x80, 0x0, 0x0,
  575. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0,
  576. 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  577. ];
  578. assert_eq!(
  579. parse_ipv6(&data),
  580. Ok(Packet::new_ipv6(
  581. Ipv6Repr {
  582. src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
  583. dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
  584. hop_limit: 255,
  585. next_header: IpProtocol::Icmpv6,
  586. payload_len: 40,
  587. },
  588. IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
  589. flags: NdiscNeighborFlags::SOLICITED,
  590. target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]),
  591. lladdr: Some(RawHardwareAddress::from_bytes(&[0, 0, 0, 0, 0, 0, 0, 1])),
  592. }))
  593. ))
  594. );
  595. let response = None;
  596. let (mut iface, mut sockets, _device) = setup(medium);
  597. assert_eq!(
  598. iface.inner.process_ipv6(
  599. &mut sockets,
  600. PacketMeta::default(),
  601. &Ipv6Packet::new_checked(&data[..]).unwrap()
  602. ),
  603. response
  604. );
  605. assert_eq!(
  606. iface.inner.neighbor_cache.lookup(
  607. &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])),
  608. iface.inner.now,
  609. ),
  610. NeighborAnswer::Found(HardwareAddress::Ieee802154(Ieee802154Address::from_bytes(
  611. &[0, 0, 0, 0, 0, 0, 0, 1]
  612. ))),
  613. );
  614. }
  615. #[rstest]
  616. #[case(Medium::Ethernet)]
  617. #[cfg(feature = "medium-ethernet")]
  618. fn test_handle_valid_ndisc_request(#[case] medium: Medium) {
  619. let (mut iface, mut sockets, _device) = setup(medium);
  620. let mut eth_bytes = vec![0u8; 86];
  621. let local_ip_addr = Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 1);
  622. let remote_ip_addr = Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 2);
  623. let local_hw_addr = EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]);
  624. let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
  625. let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit {
  626. target_addr: local_ip_addr,
  627. lladdr: Some(remote_hw_addr.into()),
  628. });
  629. let ip_repr = IpRepr::Ipv6(Ipv6Repr {
  630. src_addr: remote_ip_addr,
  631. dst_addr: local_ip_addr.solicited_node(),
  632. next_header: IpProtocol::Icmpv6,
  633. hop_limit: 0xff,
  634. payload_len: solicit.buffer_len(),
  635. });
  636. let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
  637. frame.set_dst_addr(EthernetAddress([0x33, 0x33, 0x00, 0x00, 0x00, 0x00]));
  638. frame.set_src_addr(remote_hw_addr);
  639. frame.set_ethertype(EthernetProtocol::Ipv6);
  640. ip_repr.emit(frame.payload_mut(), &ChecksumCapabilities::default());
  641. solicit.emit(
  642. &remote_ip_addr,
  643. &local_ip_addr.solicited_node(),
  644. &mut Icmpv6Packet::new_unchecked(&mut frame.payload_mut()[ip_repr.header_len()..]),
  645. &ChecksumCapabilities::default(),
  646. );
  647. let icmpv6_expected = Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
  648. flags: NdiscNeighborFlags::SOLICITED,
  649. target_addr: local_ip_addr,
  650. lladdr: Some(local_hw_addr.into()),
  651. });
  652. let ipv6_expected = Ipv6Repr {
  653. src_addr: local_ip_addr,
  654. dst_addr: remote_ip_addr,
  655. next_header: IpProtocol::Icmpv6,
  656. hop_limit: 0xff,
  657. payload_len: icmpv6_expected.buffer_len(),
  658. };
  659. // Ensure an Neighbor Solicitation triggers a Neighbor Advertisement
  660. assert_eq!(
  661. iface.inner.process_ethernet(
  662. &mut sockets,
  663. PacketMeta::default(),
  664. frame.into_inner(),
  665. &mut iface.fragments
  666. ),
  667. Some(EthernetPacket::Ip(Packet::new_ipv6(
  668. ipv6_expected,
  669. IpPayload::Icmpv6(icmpv6_expected)
  670. )))
  671. );
  672. // Ensure the address of the requester was entered in the cache
  673. assert_eq!(
  674. iface.inner.lookup_hardware_addr(
  675. MockTxToken,
  676. &IpAddress::Ipv6(local_ip_addr),
  677. &IpAddress::Ipv6(remote_ip_addr),
  678. &mut iface.fragmenter,
  679. ),
  680. Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
  681. );
  682. }
  683. #[rstest]
  684. #[case(Medium::Ip)]
  685. #[cfg(feature = "medium-ip")]
  686. #[case(Medium::Ethernet)]
  687. #[cfg(feature = "medium-ethernet")]
  688. #[case(Medium::Ieee802154)]
  689. #[cfg(feature = "medium-ieee802154")]
  690. fn test_solicited_node_addrs(#[case] medium: Medium) {
  691. let (mut iface, _, _) = setup(medium);
  692. let mut new_addrs = heapless::Vec::<IpCidr, IFACE_MAX_ADDR_COUNT>::new();
  693. new_addrs
  694. .push(IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 1, 2, 0, 2), 64))
  695. .unwrap();
  696. new_addrs
  697. .push(IpCidr::new(
  698. IpAddress::v6(0xfe80, 0, 0, 0, 3, 4, 0, 0xffff),
  699. 64,
  700. ))
  701. .unwrap();
  702. iface.update_ip_addrs(|addrs| {
  703. new_addrs.extend(addrs.to_vec());
  704. *addrs = new_addrs;
  705. });
  706. assert!(iface
  707. .inner
  708. .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0002)));
  709. assert!(iface
  710. .inner
  711. .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0xffff)));
  712. assert!(!iface
  713. .inner
  714. .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0003)));
  715. }
  716. #[rstest]
  717. #[case(Medium::Ip)]
  718. #[cfg(all(feature = "socket-udp", feature = "medium-ip"))]
  719. #[case(Medium::Ethernet)]
  720. #[cfg(all(feature = "socket-udp", feature = "medium-ethernet"))]
  721. #[case(Medium::Ieee802154)]
  722. #[cfg(all(feature = "socket-udp", feature = "medium-ieee802154"))]
  723. fn test_icmp_reply_size(#[case] medium: Medium) {
  724. use crate::wire::Icmpv6DstUnreachable;
  725. use crate::wire::IPV6_MIN_MTU as MIN_MTU;
  726. const MAX_PAYLOAD_LEN: usize = 1192;
  727. let (mut iface, mut sockets, _device) = setup(medium);
  728. let src_addr = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
  729. let dst_addr = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
  730. // UDP packet that if not tructated will cause a icmp port unreachable reply
  731. // to exceed the minimum mtu bytes in length.
  732. let udp_repr = UdpRepr {
  733. src_port: 67,
  734. dst_port: 68,
  735. };
  736. let mut bytes = vec![0xff; udp_repr.header_len() + MAX_PAYLOAD_LEN];
  737. let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
  738. udp_repr.emit(
  739. &mut packet,
  740. &src_addr.into(),
  741. &dst_addr.into(),
  742. MAX_PAYLOAD_LEN,
  743. |buf| fill_slice(buf, 0x2a),
  744. &ChecksumCapabilities::default(),
  745. );
  746. let ip_repr = Ipv6Repr {
  747. src_addr,
  748. dst_addr,
  749. next_header: IpProtocol::Udp,
  750. hop_limit: 64,
  751. payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN,
  752. };
  753. let payload = packet.into_inner();
  754. let expected_icmp_repr = Icmpv6Repr::DstUnreachable {
  755. reason: Icmpv6DstUnreachable::PortUnreachable,
  756. header: ip_repr,
  757. data: &payload[..MAX_PAYLOAD_LEN],
  758. };
  759. let expected_ip_repr = Ipv6Repr {
  760. src_addr: dst_addr,
  761. dst_addr: src_addr,
  762. next_header: IpProtocol::Icmpv6,
  763. hop_limit: 64,
  764. payload_len: expected_icmp_repr.buffer_len(),
  765. };
  766. assert_eq!(
  767. expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(),
  768. MIN_MTU
  769. );
  770. assert_eq!(
  771. iface.inner.process_udp(
  772. &mut sockets,
  773. PacketMeta::default(),
  774. false,
  775. ip_repr.into(),
  776. payload,
  777. ),
  778. Some(Packet::new_ipv6(
  779. expected_ip_repr,
  780. IpPayload::Icmpv6(expected_icmp_repr)
  781. ))
  782. );
  783. }
  784. #[cfg(feature = "medium-ip")]
  785. #[test]
  786. fn get_source_address() {
  787. let (mut iface, _, _) = setup(Medium::Ip);
  788. const OWN_LINK_LOCAL_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
  789. const OWN_UNIQUE_LOCAL_ADDR1: Ipv6Address = Ipv6Address::new(0xfd00, 0, 0, 201, 1, 1, 1, 2);
  790. const OWN_UNIQUE_LOCAL_ADDR2: Ipv6Address = Ipv6Address::new(0xfd01, 0, 0, 201, 1, 1, 1, 2);
  791. const OWN_GLOBAL_UNICAST_ADDR1: Ipv6Address =
  792. Ipv6Address::new(0x2001, 0x0db8, 0x0003, 0, 0, 0, 0, 1);
  793. // List of addresses of the interface:
  794. // fe80::1/64
  795. // fd00::201:1:1:1:2/64
  796. // fd01::201:1:1:1:2/64
  797. // 2001:db8:3::1/64
  798. iface.update_ip_addrs(|addrs| {
  799. addrs.clear();
  800. addrs
  801. .push(IpCidr::Ipv6(Ipv6Cidr::new(OWN_LINK_LOCAL_ADDR, 64)))
  802. .unwrap();
  803. addrs
  804. .push(IpCidr::Ipv6(Ipv6Cidr::new(OWN_UNIQUE_LOCAL_ADDR1, 64)))
  805. .unwrap();
  806. addrs
  807. .push(IpCidr::Ipv6(Ipv6Cidr::new(OWN_UNIQUE_LOCAL_ADDR2, 64)))
  808. .unwrap();
  809. addrs
  810. .push(IpCidr::Ipv6(Ipv6Cidr::new(OWN_GLOBAL_UNICAST_ADDR1, 64)))
  811. .unwrap();
  812. });
  813. // List of addresses we test:
  814. // ::1 -> ::1
  815. // fe80::42 -> fe80::1
  816. // fd00::201:1:1:1:1 -> fd00::201:1:1:1:2
  817. // fd01::201:1:1:1:1 -> fd01::201:1:1:1:2
  818. // fd02::201:1:1:1:1 -> fd00::201:1:1:1:2 (because first added in the list)
  819. // ff02::1 -> fe80::1 (same scope)
  820. // 2001:db8:3::2 -> 2001:db8:3::1
  821. // 2001:db9:3::2 -> 2001:db8:3::1
  822. const LINK_LOCAL_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 42);
  823. const UNIQUE_LOCAL_ADDR1: Ipv6Address = Ipv6Address::new(0xfd00, 0, 0, 201, 1, 1, 1, 1);
  824. const UNIQUE_LOCAL_ADDR2: Ipv6Address = Ipv6Address::new(0xfd01, 0, 0, 201, 1, 1, 1, 1);
  825. const UNIQUE_LOCAL_ADDR3: Ipv6Address = Ipv6Address::new(0xfd02, 0, 0, 201, 1, 1, 1, 1);
  826. const GLOBAL_UNICAST_ADDR1: Ipv6Address =
  827. Ipv6Address::new(0x2001, 0x0db8, 0x0003, 0, 0, 0, 0, 2);
  828. const GLOBAL_UNICAST_ADDR2: Ipv6Address =
  829. Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2);
  830. assert_eq!(
  831. iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK),
  832. Ipv6Address::LOOPBACK
  833. );
  834. assert_eq!(
  835. iface.inner.get_source_address_ipv6(&LINK_LOCAL_ADDR),
  836. OWN_LINK_LOCAL_ADDR
  837. );
  838. assert_eq!(
  839. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1),
  840. OWN_UNIQUE_LOCAL_ADDR1
  841. );
  842. assert_eq!(
  843. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2),
  844. OWN_UNIQUE_LOCAL_ADDR2
  845. );
  846. assert_eq!(
  847. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3),
  848. OWN_UNIQUE_LOCAL_ADDR1
  849. );
  850. assert_eq!(
  851. iface
  852. .inner
  853. .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
  854. OWN_LINK_LOCAL_ADDR
  855. );
  856. assert_eq!(
  857. iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1),
  858. OWN_GLOBAL_UNICAST_ADDR1
  859. );
  860. assert_eq!(
  861. iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2),
  862. OWN_GLOBAL_UNICAST_ADDR1
  863. );
  864. assert_eq!(
  865. iface.get_source_address_ipv6(&LINK_LOCAL_ADDR),
  866. OWN_LINK_LOCAL_ADDR
  867. );
  868. assert_eq!(
  869. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1),
  870. OWN_UNIQUE_LOCAL_ADDR1
  871. );
  872. assert_eq!(
  873. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2),
  874. OWN_UNIQUE_LOCAL_ADDR2
  875. );
  876. assert_eq!(
  877. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3),
  878. OWN_UNIQUE_LOCAL_ADDR1
  879. );
  880. assert_eq!(
  881. iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
  882. OWN_LINK_LOCAL_ADDR
  883. );
  884. assert_eq!(
  885. iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1),
  886. OWN_GLOBAL_UNICAST_ADDR1
  887. );
  888. assert_eq!(
  889. iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2),
  890. OWN_GLOBAL_UNICAST_ADDR1
  891. );
  892. }
  893. #[cfg(feature = "medium-ip")]
  894. #[test]
  895. fn get_source_address_only_link_local() {
  896. let (mut iface, _, _) = setup(Medium::Ip);
  897. // List of addresses in the interface:
  898. // fe80::1/64
  899. const OWN_LINK_LOCAL_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
  900. iface.update_ip_addrs(|ips| {
  901. ips.clear();
  902. ips.push(IpCidr::Ipv6(Ipv6Cidr::new(OWN_LINK_LOCAL_ADDR, 64)))
  903. .unwrap();
  904. });
  905. // List of addresses we test:
  906. // ::1 -> ::1
  907. // fe80::42 -> fe80::1
  908. // fd00::201:1:1:1:1 -> fe80::1
  909. // fd01::201:1:1:1:1 -> fe80::1
  910. // fd02::201:1:1:1:1 -> fe80::1
  911. // ff02::1 -> fe80::1
  912. // 2001:db8:3::2 -> fe80::1
  913. // 2001:db9:3::2 -> fe80::1
  914. const LINK_LOCAL_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 42);
  915. const UNIQUE_LOCAL_ADDR1: Ipv6Address = Ipv6Address::new(0xfd00, 0, 0, 201, 1, 1, 1, 1);
  916. const UNIQUE_LOCAL_ADDR2: Ipv6Address = Ipv6Address::new(0xfd01, 0, 0, 201, 1, 1, 1, 1);
  917. const UNIQUE_LOCAL_ADDR3: Ipv6Address = Ipv6Address::new(0xfd02, 0, 0, 201, 1, 1, 1, 1);
  918. const GLOBAL_UNICAST_ADDR1: Ipv6Address =
  919. Ipv6Address::new(0x2001, 0x0db8, 0x0003, 0, 0, 0, 0, 2);
  920. const GLOBAL_UNICAST_ADDR2: Ipv6Address =
  921. Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2);
  922. assert_eq!(
  923. iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK),
  924. Ipv6Address::LOOPBACK
  925. );
  926. assert_eq!(
  927. iface.inner.get_source_address_ipv6(&LINK_LOCAL_ADDR),
  928. OWN_LINK_LOCAL_ADDR
  929. );
  930. assert_eq!(
  931. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1),
  932. OWN_LINK_LOCAL_ADDR
  933. );
  934. assert_eq!(
  935. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2),
  936. OWN_LINK_LOCAL_ADDR
  937. );
  938. assert_eq!(
  939. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3),
  940. OWN_LINK_LOCAL_ADDR
  941. );
  942. assert_eq!(
  943. iface
  944. .inner
  945. .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
  946. OWN_LINK_LOCAL_ADDR
  947. );
  948. assert_eq!(
  949. iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1),
  950. OWN_LINK_LOCAL_ADDR
  951. );
  952. assert_eq!(
  953. iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2),
  954. OWN_LINK_LOCAL_ADDR
  955. );
  956. assert_eq!(
  957. iface.get_source_address_ipv6(&LINK_LOCAL_ADDR),
  958. OWN_LINK_LOCAL_ADDR
  959. );
  960. assert_eq!(
  961. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1),
  962. OWN_LINK_LOCAL_ADDR
  963. );
  964. assert_eq!(
  965. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2),
  966. OWN_LINK_LOCAL_ADDR
  967. );
  968. assert_eq!(
  969. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3),
  970. OWN_LINK_LOCAL_ADDR
  971. );
  972. assert_eq!(
  973. iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
  974. OWN_LINK_LOCAL_ADDR
  975. );
  976. assert_eq!(
  977. iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1),
  978. OWN_LINK_LOCAL_ADDR
  979. );
  980. assert_eq!(
  981. iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2),
  982. OWN_LINK_LOCAL_ADDR
  983. );
  984. }
  985. #[cfg(feature = "medium-ip")]
  986. #[test]
  987. fn get_source_address_empty_interface() {
  988. let (mut iface, _, _) = setup(Medium::Ip);
  989. iface.update_ip_addrs(|ips| ips.clear());
  990. // List of addresses we test:
  991. // ::1 -> ::1
  992. // fe80::42 -> ::1
  993. // fd00::201:1:1:1:1 -> ::1
  994. // fd01::201:1:1:1:1 -> ::1
  995. // fd02::201:1:1:1:1 -> ::1
  996. // ff02::1 -> ::1
  997. // 2001:db8:3::2 -> ::1
  998. // 2001:db9:3::2 -> ::1
  999. const LINK_LOCAL_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 42);
  1000. const UNIQUE_LOCAL_ADDR1: Ipv6Address = Ipv6Address::new(0xfd00, 0, 0, 201, 1, 1, 1, 1);
  1001. const UNIQUE_LOCAL_ADDR2: Ipv6Address = Ipv6Address::new(0xfd01, 0, 0, 201, 1, 1, 1, 1);
  1002. const UNIQUE_LOCAL_ADDR3: Ipv6Address = Ipv6Address::new(0xfd02, 0, 0, 201, 1, 1, 1, 1);
  1003. const GLOBAL_UNICAST_ADDR1: Ipv6Address =
  1004. Ipv6Address::new(0x2001, 0x0db8, 0x0003, 0, 0, 0, 0, 2);
  1005. const GLOBAL_UNICAST_ADDR2: Ipv6Address =
  1006. Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2);
  1007. assert_eq!(
  1008. iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK),
  1009. Ipv6Address::LOOPBACK
  1010. );
  1011. assert_eq!(
  1012. iface.inner.get_source_address_ipv6(&LINK_LOCAL_ADDR),
  1013. Ipv6Address::LOOPBACK
  1014. );
  1015. assert_eq!(
  1016. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1),
  1017. Ipv6Address::LOOPBACK
  1018. );
  1019. assert_eq!(
  1020. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2),
  1021. Ipv6Address::LOOPBACK
  1022. );
  1023. assert_eq!(
  1024. iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3),
  1025. Ipv6Address::LOOPBACK
  1026. );
  1027. assert_eq!(
  1028. iface
  1029. .inner
  1030. .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
  1031. Ipv6Address::LOOPBACK
  1032. );
  1033. assert_eq!(
  1034. iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1),
  1035. Ipv6Address::LOOPBACK
  1036. );
  1037. assert_eq!(
  1038. iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2),
  1039. Ipv6Address::LOOPBACK
  1040. );
  1041. assert_eq!(
  1042. iface.get_source_address_ipv6(&LINK_LOCAL_ADDR),
  1043. Ipv6Address::LOOPBACK
  1044. );
  1045. assert_eq!(
  1046. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1),
  1047. Ipv6Address::LOOPBACK
  1048. );
  1049. assert_eq!(
  1050. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2),
  1051. Ipv6Address::LOOPBACK
  1052. );
  1053. assert_eq!(
  1054. iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3),
  1055. Ipv6Address::LOOPBACK
  1056. );
  1057. assert_eq!(
  1058. iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
  1059. Ipv6Address::LOOPBACK
  1060. );
  1061. assert_eq!(
  1062. iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1),
  1063. Ipv6Address::LOOPBACK
  1064. );
  1065. assert_eq!(
  1066. iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2),
  1067. Ipv6Address::LOOPBACK
  1068. );
  1069. }
  1070. #[rstest]
  1071. #[case(Medium::Ip)]
  1072. #[cfg(feature = "medium-ip")]
  1073. #[case(Medium::Ethernet)]
  1074. #[cfg(feature = "medium-ethernet")]
  1075. fn test_join_ipv6_multicast_group(#[case] medium: Medium) {
  1076. fn recv_icmpv6(
  1077. device: &mut crate::tests::TestingDevice,
  1078. timestamp: Instant,
  1079. ) -> std::vec::Vec<Ipv6Packet<std::vec::Vec<u8>>> {
  1080. let caps = device.capabilities();
  1081. recv_all(device, timestamp)
  1082. .iter()
  1083. .filter_map(|frame| {
  1084. let ipv6_packet = match caps.medium {
  1085. #[cfg(feature = "medium-ethernet")]
  1086. Medium::Ethernet => {
  1087. let eth_frame = EthernetFrame::new_checked(frame).ok()?;
  1088. Ipv6Packet::new_checked(eth_frame.payload()).ok()?
  1089. }
  1090. #[cfg(feature = "medium-ip")]
  1091. Medium::Ip => Ipv6Packet::new_checked(&frame[..]).ok()?,
  1092. #[cfg(feature = "medium-ieee802154")]
  1093. Medium::Ieee802154 => todo!(),
  1094. };
  1095. let buf = ipv6_packet.into_inner().to_vec();
  1096. Some(Ipv6Packet::new_unchecked(buf))
  1097. })
  1098. .collect::<std::vec::Vec<_>>()
  1099. }
  1100. let (mut iface, _sockets, mut device) = setup(medium);
  1101. let groups = [
  1102. Ipv6Address::from_parts(&[0xff05, 0, 0, 0, 0, 0, 0, 0x00fb]),
  1103. Ipv6Address::from_parts(&[0xff0e, 0, 0, 0, 0, 0, 0, 0x0017]),
  1104. ];
  1105. let timestamp = Instant::from_millis(0);
  1106. for &group in &groups {
  1107. iface
  1108. .join_multicast_group(&mut device, group, timestamp)
  1109. .unwrap();
  1110. assert!(iface.has_multicast_group(group));
  1111. }
  1112. assert!(iface.has_multicast_group(Ipv6Address::LINK_LOCAL_ALL_NODES));
  1113. let reports = recv_icmpv6(&mut device, timestamp);
  1114. assert_eq!(reports.len(), 2);
  1115. let caps = device.capabilities();
  1116. let checksum_caps = &caps.checksum;
  1117. for (&group_addr, ipv6_packet) in groups.iter().zip(reports) {
  1118. let buf = ipv6_packet.into_inner();
  1119. let ipv6_packet = Ipv6Packet::new_unchecked(buf.as_slice());
  1120. let _ipv6_repr = Ipv6Repr::parse(&ipv6_packet).unwrap();
  1121. let ip_payload = ipv6_packet.payload();
  1122. // The first 2 octets of this payload hold the next-header indicator and the
  1123. // Hop-by-Hop header length (in 8-octet words, minus 1). The remaining 6 octets
  1124. // hold the Hop-by-Hop PadN and Router Alert options.
  1125. let hbh_header = Ipv6HopByHopHeader::new_checked(&ip_payload[..8]).unwrap();
  1126. let hbh_repr = Ipv6HopByHopRepr::parse(&hbh_header).unwrap();
  1127. assert_eq!(hbh_repr.options.len(), 3);
  1128. assert_eq!(
  1129. hbh_repr.options[0],
  1130. Ipv6OptionRepr::Unknown {
  1131. type_: Ipv6OptionType::Unknown(IpProtocol::Icmpv6.into()),
  1132. length: 0,
  1133. data: &[],
  1134. }
  1135. );
  1136. assert_eq!(
  1137. hbh_repr.options[1],
  1138. Ipv6OptionRepr::RouterAlert(Ipv6OptionRouterAlert::MulticastListenerDiscovery)
  1139. );
  1140. assert_eq!(hbh_repr.options[2], Ipv6OptionRepr::PadN(0));
  1141. let icmpv6_packet =
  1142. Icmpv6Packet::new_checked(&ip_payload[hbh_repr.buffer_len()..]).unwrap();
  1143. let icmpv6_repr = Icmpv6Repr::parse(
  1144. &ipv6_packet.src_addr(),
  1145. &ipv6_packet.dst_addr(),
  1146. &icmpv6_packet,
  1147. checksum_caps,
  1148. )
  1149. .unwrap();
  1150. let record_data = match icmpv6_repr {
  1151. Icmpv6Repr::Mld(MldRepr::Report {
  1152. nr_mcast_addr_rcrds,
  1153. data,
  1154. }) => {
  1155. assert_eq!(nr_mcast_addr_rcrds, 1);
  1156. data
  1157. }
  1158. other => panic!("unexpected icmpv6_repr: {:?}", other),
  1159. };
  1160. let record = MldAddressRecord::new_checked(record_data).unwrap();
  1161. let record_repr = MldAddressRecordRepr::parse(&record).unwrap();
  1162. assert_eq!(
  1163. record_repr,
  1164. MldAddressRecordRepr {
  1165. num_srcs: 0,
  1166. mcast_addr: group_addr,
  1167. record_type: MldRecordType::ChangeToInclude,
  1168. aux_data_len: 0,
  1169. payload: &[],
  1170. }
  1171. );
  1172. iface
  1173. .leave_multicast_group(&mut device, group_addr, timestamp)
  1174. .unwrap();
  1175. assert!(!iface.has_multicast_group(group_addr));
  1176. }
  1177. }