ipv4.rs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. use super::*;
  2. #[rstest]
  3. #[case(Medium::Ip)]
  4. #[cfg(feature = "medium-ip")]
  5. #[case(Medium::Ethernet)]
  6. #[cfg(feature = "medium-ethernet")]
  7. fn test_no_icmp_no_unicast(#[case] medium: Medium) {
  8. let (mut iface, mut sockets, _) = setup(medium);
  9. // Unknown Ipv4 Protocol
  10. //
  11. // Because the destination is the broadcast address
  12. // this should not trigger and Destination Unreachable
  13. // response. See RFC 1122 § 3.2.2.
  14. let repr = IpRepr::Ipv4(Ipv4Repr {
  15. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  16. dst_addr: Ipv4Address::BROADCAST,
  17. next_header: IpProtocol::Unknown(0x0c),
  18. payload_len: 0,
  19. hop_limit: 0x40,
  20. });
  21. let mut bytes = vec![0u8; 54];
  22. repr.emit(&mut bytes, &ChecksumCapabilities::default());
  23. let frame = Ipv4Packet::new_unchecked(&bytes);
  24. // Ensure that the unknown protocol frame does not trigger an
  25. // ICMP error response when the destination address is a
  26. // broadcast address
  27. assert_eq!(
  28. iface.inner.process_ipv4(
  29. &mut sockets,
  30. PacketMeta::default(),
  31. &frame,
  32. &mut iface.fragments
  33. ),
  34. None
  35. );
  36. }
  37. #[rstest]
  38. #[case(Medium::Ip)]
  39. #[cfg(feature = "medium-ip")]
  40. #[case(Medium::Ethernet)]
  41. #[cfg(feature = "medium-ethernet")]
  42. fn test_icmp_error_no_payload(#[case] medium: Medium) {
  43. static NO_BYTES: [u8; 0] = [];
  44. let (mut iface, mut sockets, _device) = setup(medium);
  45. // Unknown Ipv4 Protocol with no payload
  46. let repr = IpRepr::Ipv4(Ipv4Repr {
  47. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  48. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  49. next_header: IpProtocol::Unknown(0x0c),
  50. payload_len: 0,
  51. hop_limit: 0x40,
  52. });
  53. let mut bytes = vec![0u8; 34];
  54. repr.emit(&mut bytes, &ChecksumCapabilities::default());
  55. let frame = Ipv4Packet::new_unchecked(&bytes);
  56. // The expected Destination Unreachable response due to the
  57. // unknown protocol
  58. let icmp_repr = Icmpv4Repr::DstUnreachable {
  59. reason: Icmpv4DstUnreachable::ProtoUnreachable,
  60. header: Ipv4Repr {
  61. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  62. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  63. next_header: IpProtocol::Unknown(12),
  64. payload_len: 0,
  65. hop_limit: 64,
  66. },
  67. data: &NO_BYTES,
  68. };
  69. let expected_repr = IpPacket::Icmpv4((
  70. Ipv4Repr {
  71. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  72. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  73. next_header: IpProtocol::Icmp,
  74. payload_len: icmp_repr.buffer_len(),
  75. hop_limit: 64,
  76. },
  77. icmp_repr,
  78. ));
  79. // Ensure that the unknown protocol triggers an error response.
  80. // And we correctly handle no payload.
  81. assert_eq!(
  82. iface.inner.process_ipv4(
  83. &mut sockets,
  84. PacketMeta::default(),
  85. &frame,
  86. &mut iface.fragments
  87. ),
  88. Some(expected_repr)
  89. );
  90. }
  91. #[rstest]
  92. #[case(Medium::Ip)]
  93. #[cfg(feature = "medium-ip")]
  94. #[case(Medium::Ethernet)]
  95. #[cfg(feature = "medium-ethernet")]
  96. fn test_local_subnet_broadcasts(#[case] medium: Medium) {
  97. let (mut iface, _, _device) = setup(medium);
  98. iface.update_ip_addrs(|addrs| {
  99. addrs.iter_mut().next().map(|addr| {
  100. *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 23]), 24));
  101. });
  102. });
  103. assert!(iface
  104. .inner
  105. .is_broadcast_v4(Ipv4Address([255, 255, 255, 255])));
  106. assert!(!iface
  107. .inner
  108. .is_broadcast_v4(Ipv4Address([255, 255, 255, 254])));
  109. assert!(iface.inner.is_broadcast_v4(Ipv4Address([192, 168, 1, 255])));
  110. assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 168, 1, 254])));
  111. iface.update_ip_addrs(|addrs| {
  112. addrs.iter_mut().next().map(|addr| {
  113. *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 16));
  114. });
  115. });
  116. assert!(iface
  117. .inner
  118. .is_broadcast_v4(Ipv4Address([255, 255, 255, 255])));
  119. assert!(!iface
  120. .inner
  121. .is_broadcast_v4(Ipv4Address([255, 255, 255, 254])));
  122. assert!(!iface
  123. .inner
  124. .is_broadcast_v4(Ipv4Address([192, 168, 23, 255])));
  125. assert!(!iface
  126. .inner
  127. .is_broadcast_v4(Ipv4Address([192, 168, 23, 254])));
  128. assert!(!iface
  129. .inner
  130. .is_broadcast_v4(Ipv4Address([192, 168, 255, 254])));
  131. assert!(iface
  132. .inner
  133. .is_broadcast_v4(Ipv4Address([192, 168, 255, 255])));
  134. iface.update_ip_addrs(|addrs| {
  135. addrs.iter_mut().next().map(|addr| {
  136. *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 8));
  137. });
  138. });
  139. assert!(iface
  140. .inner
  141. .is_broadcast_v4(Ipv4Address([255, 255, 255, 255])));
  142. assert!(!iface
  143. .inner
  144. .is_broadcast_v4(Ipv4Address([255, 255, 255, 254])));
  145. assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 23, 1, 255])));
  146. assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 23, 1, 254])));
  147. assert!(!iface
  148. .inner
  149. .is_broadcast_v4(Ipv4Address([192, 255, 255, 254])));
  150. assert!(iface
  151. .inner
  152. .is_broadcast_v4(Ipv4Address([192, 255, 255, 255])));
  153. }
  154. #[rstest]
  155. #[case(Medium::Ip)]
  156. #[cfg(all(feature = "medium-ip", feature = "socket-udp"))]
  157. #[case(Medium::Ethernet)]
  158. #[cfg(all(feature = "medium-ethernet", feature = "socket-udp"))]
  159. fn test_icmp_error_port_unreachable(#[case] medium: Medium) {
  160. static UDP_PAYLOAD: [u8; 12] = [
  161. 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x6c, 0x64, 0x21,
  162. ];
  163. let (mut iface, mut sockets, _device) = setup(medium);
  164. let mut udp_bytes_unicast = vec![0u8; 20];
  165. let mut udp_bytes_broadcast = vec![0u8; 20];
  166. let mut packet_unicast = UdpPacket::new_unchecked(&mut udp_bytes_unicast);
  167. let mut packet_broadcast = UdpPacket::new_unchecked(&mut udp_bytes_broadcast);
  168. let udp_repr = UdpRepr {
  169. src_port: 67,
  170. dst_port: 68,
  171. };
  172. let ip_repr = IpRepr::Ipv4(Ipv4Repr {
  173. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  174. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  175. next_header: IpProtocol::Udp,
  176. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  177. hop_limit: 64,
  178. });
  179. // Emit the representations to a packet
  180. udp_repr.emit(
  181. &mut packet_unicast,
  182. &ip_repr.src_addr(),
  183. &ip_repr.dst_addr(),
  184. UDP_PAYLOAD.len(),
  185. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  186. &ChecksumCapabilities::default(),
  187. );
  188. let data = packet_unicast.into_inner();
  189. // The expected Destination Unreachable ICMPv4 error response due
  190. // to no sockets listening on the destination port.
  191. let icmp_repr = Icmpv4Repr::DstUnreachable {
  192. reason: Icmpv4DstUnreachable::PortUnreachable,
  193. header: Ipv4Repr {
  194. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  195. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  196. next_header: IpProtocol::Udp,
  197. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  198. hop_limit: 64,
  199. },
  200. data,
  201. };
  202. let expected_repr = IpPacket::Icmpv4((
  203. Ipv4Repr {
  204. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  205. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  206. next_header: IpProtocol::Icmp,
  207. payload_len: icmp_repr.buffer_len(),
  208. hop_limit: 64,
  209. },
  210. icmp_repr,
  211. ));
  212. // Ensure that the unknown protocol triggers an error response.
  213. // And we correctly handle no payload.
  214. assert_eq!(
  215. iface.inner.process_udp(
  216. &mut sockets,
  217. PacketMeta::default(),
  218. ip_repr,
  219. udp_repr,
  220. false,
  221. &UDP_PAYLOAD,
  222. data
  223. ),
  224. Some(expected_repr)
  225. );
  226. let ip_repr = IpRepr::Ipv4(Ipv4Repr {
  227. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  228. dst_addr: Ipv4Address::BROADCAST,
  229. next_header: IpProtocol::Udp,
  230. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  231. hop_limit: 64,
  232. });
  233. // Emit the representations to a packet
  234. udp_repr.emit(
  235. &mut packet_broadcast,
  236. &ip_repr.src_addr(),
  237. &IpAddress::Ipv4(Ipv4Address::BROADCAST),
  238. UDP_PAYLOAD.len(),
  239. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  240. &ChecksumCapabilities::default(),
  241. );
  242. // Ensure that the port unreachable error does not trigger an
  243. // ICMP error response when the destination address is a
  244. // broadcast address and no socket is bound to the port.
  245. assert_eq!(
  246. iface.inner.process_udp(
  247. &mut sockets,
  248. PacketMeta::default(),
  249. ip_repr,
  250. udp_repr,
  251. false,
  252. &UDP_PAYLOAD,
  253. packet_broadcast.into_inner(),
  254. ),
  255. None
  256. );
  257. }
  258. #[rstest]
  259. #[case(Medium::Ip)]
  260. #[cfg(feature = "medium-ip")]
  261. #[case(Medium::Ethernet)]
  262. #[cfg(feature = "medium-ethernet")]
  263. fn test_handle_ipv4_broadcast(#[case] medium: Medium) {
  264. use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Packet};
  265. let (mut iface, mut sockets, _device) = setup(medium);
  266. let our_ipv4_addr = iface.ipv4_addr().unwrap();
  267. let src_ipv4_addr = Ipv4Address([127, 0, 0, 2]);
  268. // ICMPv4 echo request
  269. let icmpv4_data: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
  270. let icmpv4_repr = Icmpv4Repr::EchoRequest {
  271. ident: 0x1234,
  272. seq_no: 0xabcd,
  273. data: &icmpv4_data,
  274. };
  275. // Send to IPv4 broadcast address
  276. let ipv4_repr = Ipv4Repr {
  277. src_addr: src_ipv4_addr,
  278. dst_addr: Ipv4Address::BROADCAST,
  279. next_header: IpProtocol::Icmp,
  280. hop_limit: 64,
  281. payload_len: icmpv4_repr.buffer_len(),
  282. };
  283. // Emit to ip frame
  284. let mut bytes = vec![0u8; ipv4_repr.buffer_len() + icmpv4_repr.buffer_len()];
  285. let frame = {
  286. ipv4_repr.emit(
  287. &mut Ipv4Packet::new_unchecked(&mut bytes),
  288. &ChecksumCapabilities::default(),
  289. );
  290. icmpv4_repr.emit(
  291. &mut Icmpv4Packet::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
  292. &ChecksumCapabilities::default(),
  293. );
  294. Ipv4Packet::new_unchecked(&bytes)
  295. };
  296. // Expected ICMPv4 echo reply
  297. let expected_icmpv4_repr = Icmpv4Repr::EchoReply {
  298. ident: 0x1234,
  299. seq_no: 0xabcd,
  300. data: &icmpv4_data,
  301. };
  302. let expected_ipv4_repr = Ipv4Repr {
  303. src_addr: our_ipv4_addr,
  304. dst_addr: src_ipv4_addr,
  305. next_header: IpProtocol::Icmp,
  306. hop_limit: 64,
  307. payload_len: expected_icmpv4_repr.buffer_len(),
  308. };
  309. let expected_packet = IpPacket::Icmpv4((expected_ipv4_repr, expected_icmpv4_repr));
  310. assert_eq!(
  311. iface.inner.process_ipv4(
  312. &mut sockets,
  313. PacketMeta::default(),
  314. &frame,
  315. &mut iface.fragments
  316. ),
  317. Some(expected_packet)
  318. );
  319. }
  320. #[rstest]
  321. #[case(Medium::Ethernet)]
  322. #[cfg(feature = "medium-ethernet")]
  323. fn test_handle_valid_arp_request(#[case] medium: Medium) {
  324. let (mut iface, mut sockets, _device) = setup(medium);
  325. let mut eth_bytes = vec![0u8; 42];
  326. let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
  327. let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
  328. let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  329. let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
  330. let repr = ArpRepr::EthernetIpv4 {
  331. operation: ArpOperation::Request,
  332. source_hardware_addr: remote_hw_addr,
  333. source_protocol_addr: remote_ip_addr,
  334. target_hardware_addr: EthernetAddress::default(),
  335. target_protocol_addr: local_ip_addr,
  336. };
  337. let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
  338. frame.set_dst_addr(EthernetAddress::BROADCAST);
  339. frame.set_src_addr(remote_hw_addr);
  340. frame.set_ethertype(EthernetProtocol::Arp);
  341. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  342. repr.emit(&mut packet);
  343. // Ensure an ARP Request for us triggers an ARP Reply
  344. assert_eq!(
  345. iface.inner.process_ethernet(
  346. &mut sockets,
  347. PacketMeta::default(),
  348. frame.into_inner(),
  349. &mut iface.fragments
  350. ),
  351. Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 {
  352. operation: ArpOperation::Reply,
  353. source_hardware_addr: local_hw_addr,
  354. source_protocol_addr: local_ip_addr,
  355. target_hardware_addr: remote_hw_addr,
  356. target_protocol_addr: remote_ip_addr
  357. }))
  358. );
  359. // Ensure the address of the requestor was entered in the cache
  360. assert_eq!(
  361. iface.inner.lookup_hardware_addr(
  362. MockTxToken,
  363. &IpAddress::Ipv4(local_ip_addr),
  364. &IpAddress::Ipv4(remote_ip_addr),
  365. &mut iface.fragmenter,
  366. ),
  367. Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
  368. );
  369. }
  370. #[rstest]
  371. #[case(Medium::Ethernet)]
  372. #[cfg(feature = "medium-ethernet")]
  373. fn test_handle_other_arp_request(#[case] medium: Medium) {
  374. let (mut iface, mut sockets, _device) = setup(medium);
  375. let mut eth_bytes = vec![0u8; 42];
  376. let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
  377. let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
  378. let repr = ArpRepr::EthernetIpv4 {
  379. operation: ArpOperation::Request,
  380. source_hardware_addr: remote_hw_addr,
  381. source_protocol_addr: remote_ip_addr,
  382. target_hardware_addr: EthernetAddress::default(),
  383. target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x03]),
  384. };
  385. let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
  386. frame.set_dst_addr(EthernetAddress::BROADCAST);
  387. frame.set_src_addr(remote_hw_addr);
  388. frame.set_ethertype(EthernetProtocol::Arp);
  389. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  390. repr.emit(&mut packet);
  391. // Ensure an ARP Request for someone else does not trigger an ARP Reply
  392. assert_eq!(
  393. iface.inner.process_ethernet(
  394. &mut sockets,
  395. PacketMeta::default(),
  396. frame.into_inner(),
  397. &mut iface.fragments
  398. ),
  399. None
  400. );
  401. // Ensure the address of the requestor was NOT entered in the cache
  402. assert_eq!(
  403. iface.inner.lookup_hardware_addr(
  404. MockTxToken,
  405. &IpAddress::Ipv4(Ipv4Address([0x7f, 0x00, 0x00, 0x01])),
  406. &IpAddress::Ipv4(remote_ip_addr),
  407. &mut iface.fragmenter,
  408. ),
  409. Err(DispatchError::NeighborPending)
  410. );
  411. }
  412. #[rstest]
  413. #[case(Medium::Ethernet)]
  414. #[cfg(feature = "medium-ethernet")]
  415. fn test_arp_flush_after_update_ip(#[case] medium: Medium) {
  416. let (mut iface, mut sockets, _device) = setup(medium);
  417. let mut eth_bytes = vec![0u8; 42];
  418. let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
  419. let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
  420. let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  421. let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
  422. let repr = ArpRepr::EthernetIpv4 {
  423. operation: ArpOperation::Request,
  424. source_hardware_addr: remote_hw_addr,
  425. source_protocol_addr: remote_ip_addr,
  426. target_hardware_addr: EthernetAddress::default(),
  427. target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  428. };
  429. let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
  430. frame.set_dst_addr(EthernetAddress::BROADCAST);
  431. frame.set_src_addr(remote_hw_addr);
  432. frame.set_ethertype(EthernetProtocol::Arp);
  433. {
  434. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  435. repr.emit(&mut packet);
  436. }
  437. // Ensure an ARP Request for us triggers an ARP Reply
  438. assert_eq!(
  439. iface.inner.process_ethernet(
  440. &mut sockets,
  441. PacketMeta::default(),
  442. frame.into_inner(),
  443. &mut iface.fragments
  444. ),
  445. Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 {
  446. operation: ArpOperation::Reply,
  447. source_hardware_addr: local_hw_addr,
  448. source_protocol_addr: local_ip_addr,
  449. target_hardware_addr: remote_hw_addr,
  450. target_protocol_addr: remote_ip_addr
  451. }))
  452. );
  453. // Ensure the address of the requestor was entered in the cache
  454. assert_eq!(
  455. iface.inner.lookup_hardware_addr(
  456. MockTxToken,
  457. &IpAddress::Ipv4(local_ip_addr),
  458. &IpAddress::Ipv4(remote_ip_addr),
  459. &mut iface.fragmenter,
  460. ),
  461. Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
  462. );
  463. // Update IP addrs to trigger ARP cache flush
  464. let local_ip_addr_new = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
  465. iface.update_ip_addrs(|addrs| {
  466. addrs.iter_mut().next().map(|addr| {
  467. *addr = IpCidr::Ipv4(Ipv4Cidr::new(local_ip_addr_new, 24));
  468. });
  469. });
  470. // ARP cache flush after address change
  471. assert!(!iface.inner.has_neighbor(&IpAddress::Ipv4(remote_ip_addr)));
  472. }
  473. #[rstest]
  474. #[case(Medium::Ip)]
  475. #[cfg(all(feature = "socket-icmp", feature = "medium-ip"))]
  476. #[case(Medium::Ethernet)]
  477. #[cfg(all(feature = "socket-icmp", feature = "medium-ethernet"))]
  478. fn test_icmpv4_socket(#[case] medium: Medium) {
  479. use crate::wire::Icmpv4Packet;
  480. let (mut iface, mut sockets, _device) = setup(medium);
  481. let rx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 24]);
  482. let tx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 24]);
  483. let icmpv4_socket = icmp::Socket::new(rx_buffer, tx_buffer);
  484. let socket_handle = sockets.add(icmpv4_socket);
  485. let ident = 0x1234;
  486. let seq_no = 0x5432;
  487. let echo_data = &[0xff; 16];
  488. let socket = sockets.get_mut::<icmp::Socket>(socket_handle);
  489. // Bind to the ID 0x1234
  490. assert_eq!(socket.bind(icmp::Endpoint::Ident(ident)), Ok(()));
  491. // Ensure the ident we bound to and the ident of the packet are the same.
  492. let mut bytes = [0xff; 24];
  493. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
  494. let echo_repr = Icmpv4Repr::EchoRequest {
  495. ident,
  496. seq_no,
  497. data: echo_data,
  498. };
  499. echo_repr.emit(&mut packet, &ChecksumCapabilities::default());
  500. let icmp_data = &*packet.into_inner();
  501. let ipv4_repr = Ipv4Repr {
  502. src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02),
  503. dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01),
  504. next_header: IpProtocol::Icmp,
  505. payload_len: 24,
  506. hop_limit: 64,
  507. };
  508. let ip_repr = IpRepr::Ipv4(ipv4_repr);
  509. // Open a socket and ensure the packet is handled due to the listening
  510. // socket.
  511. assert!(!sockets.get_mut::<icmp::Socket>(socket_handle).can_recv());
  512. // Confirm we still get EchoReply from `smoltcp` even with the ICMP socket listening
  513. let echo_reply = Icmpv4Repr::EchoReply {
  514. ident,
  515. seq_no,
  516. data: echo_data,
  517. };
  518. let ipv4_reply = Ipv4Repr {
  519. src_addr: ipv4_repr.dst_addr,
  520. dst_addr: ipv4_repr.src_addr,
  521. ..ipv4_repr
  522. };
  523. assert_eq!(
  524. iface.inner.process_icmpv4(&mut sockets, ip_repr, icmp_data),
  525. Some(IpPacket::Icmpv4((ipv4_reply, echo_reply)))
  526. );
  527. let socket = sockets.get_mut::<icmp::Socket>(socket_handle);
  528. assert!(socket.can_recv());
  529. assert_eq!(
  530. socket.recv(),
  531. Ok((
  532. icmp_data,
  533. IpAddress::Ipv4(Ipv4Address::new(0x7f, 0x00, 0x00, 0x02))
  534. ))
  535. );
  536. }
  537. #[rstest]
  538. #[case(Medium::Ip)]
  539. #[cfg(all(feature = "proto-igmp", feature = "medium-ip"))]
  540. #[case(Medium::Ethernet)]
  541. #[cfg(all(feature = "proto-igmp", feature = "medium-ethernet"))]
  542. fn test_handle_igmp(#[case] medium: Medium) {
  543. fn recv_igmp(device: &mut Loopback, timestamp: Instant) -> Vec<(Ipv4Repr, IgmpRepr)> {
  544. let caps = device.capabilities();
  545. let checksum_caps = &caps.checksum;
  546. recv_all(device, timestamp)
  547. .iter()
  548. .filter_map(|frame| {
  549. let ipv4_packet = match caps.medium {
  550. #[cfg(feature = "medium-ethernet")]
  551. Medium::Ethernet => {
  552. let eth_frame = EthernetFrame::new_checked(frame).ok()?;
  553. Ipv4Packet::new_checked(eth_frame.payload()).ok()?
  554. }
  555. #[cfg(feature = "medium-ip")]
  556. Medium::Ip => Ipv4Packet::new_checked(&frame[..]).ok()?,
  557. #[cfg(feature = "medium-ieee802154")]
  558. Medium::Ieee802154 => todo!(),
  559. };
  560. let ipv4_repr = Ipv4Repr::parse(&ipv4_packet, checksum_caps).ok()?;
  561. let ip_payload = ipv4_packet.payload();
  562. let igmp_packet = IgmpPacket::new_checked(ip_payload).ok()?;
  563. let igmp_repr = IgmpRepr::parse(&igmp_packet).ok()?;
  564. Some((ipv4_repr, igmp_repr))
  565. })
  566. .collect::<Vec<_>>()
  567. }
  568. let groups = [
  569. Ipv4Address::new(224, 0, 0, 22),
  570. Ipv4Address::new(224, 0, 0, 56),
  571. ];
  572. let (mut iface, mut sockets, mut device) = setup(medium);
  573. // Join multicast groups
  574. let timestamp = Instant::now();
  575. for group in &groups {
  576. iface
  577. .join_multicast_group(&mut device, *group, timestamp)
  578. .unwrap();
  579. }
  580. let reports = recv_igmp(&mut device, timestamp);
  581. assert_eq!(reports.len(), 2);
  582. for (i, group_addr) in groups.iter().enumerate() {
  583. assert_eq!(reports[i].0.next_header, IpProtocol::Igmp);
  584. assert_eq!(reports[i].0.dst_addr, *group_addr);
  585. assert_eq!(
  586. reports[i].1,
  587. IgmpRepr::MembershipReport {
  588. group_addr: *group_addr,
  589. version: IgmpVersion::Version2,
  590. }
  591. );
  592. }
  593. // General query
  594. let timestamp = Instant::now();
  595. const GENERAL_QUERY_BYTES: &[u8] = &[
  596. 0x46, 0xc0, 0x00, 0x24, 0xed, 0xb4, 0x00, 0x00, 0x01, 0x02, 0x47, 0x43, 0xac, 0x16, 0x63,
  597. 0x04, 0xe0, 0x00, 0x00, 0x01, 0x94, 0x04, 0x00, 0x00, 0x11, 0x64, 0xec, 0x8f, 0x00, 0x00,
  598. 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  599. 0x00,
  600. ];
  601. {
  602. // Transmit GENERAL_QUERY_BYTES into loopback
  603. let tx_token = device.transmit(timestamp).unwrap();
  604. tx_token.consume(GENERAL_QUERY_BYTES.len(), |buffer| {
  605. buffer.copy_from_slice(GENERAL_QUERY_BYTES);
  606. });
  607. }
  608. // Trigger processing until all packets received through the
  609. // loopback have been processed, including responses to
  610. // GENERAL_QUERY_BYTES. Therefore `recv_all()` would return 0
  611. // pkts that could be checked.
  612. iface.socket_ingress(&mut device, &mut sockets);
  613. // Leave multicast groups
  614. let timestamp = Instant::now();
  615. for group in &groups {
  616. iface
  617. .leave_multicast_group(&mut device, *group, timestamp)
  618. .unwrap();
  619. }
  620. let leaves = recv_igmp(&mut device, timestamp);
  621. assert_eq!(leaves.len(), 2);
  622. for (i, group_addr) in groups.iter().cloned().enumerate() {
  623. assert_eq!(leaves[i].0.next_header, IpProtocol::Igmp);
  624. assert_eq!(leaves[i].0.dst_addr, Ipv4Address::MULTICAST_ALL_ROUTERS);
  625. assert_eq!(leaves[i].1, IgmpRepr::LeaveGroup { group_addr });
  626. }
  627. }
  628. #[rstest]
  629. #[case(Medium::Ip)]
  630. #[cfg(all(feature = "socket-raw", feature = "medium-ip"))]
  631. #[case(Medium::Ethernet)]
  632. #[cfg(all(feature = "socket-raw", feature = "medium-ethernet"))]
  633. fn test_raw_socket_no_reply(#[case] medium: Medium) {
  634. use crate::wire::{IpVersion, Ipv4Packet, UdpPacket, UdpRepr};
  635. let (mut iface, mut sockets, _) = setup(medium);
  636. let packets = 1;
  637. let rx_buffer =
  638. raw::PacketBuffer::new(vec![raw::PacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
  639. let tx_buffer = raw::PacketBuffer::new(
  640. vec![raw::PacketMetadata::EMPTY; packets],
  641. vec![0; 48 * packets],
  642. );
  643. let raw_socket = raw::Socket::new(IpVersion::Ipv4, IpProtocol::Udp, rx_buffer, tx_buffer);
  644. sockets.add(raw_socket);
  645. let src_addr = Ipv4Address([127, 0, 0, 2]);
  646. let dst_addr = Ipv4Address([127, 0, 0, 1]);
  647. const PAYLOAD_LEN: usize = 10;
  648. let udp_repr = UdpRepr {
  649. src_port: 67,
  650. dst_port: 68,
  651. };
  652. let mut bytes = vec![0xff; udp_repr.header_len() + PAYLOAD_LEN];
  653. let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
  654. udp_repr.emit(
  655. &mut packet,
  656. &src_addr.into(),
  657. &dst_addr.into(),
  658. PAYLOAD_LEN,
  659. |buf| fill_slice(buf, 0x2a),
  660. &ChecksumCapabilities::default(),
  661. );
  662. let ipv4_repr = Ipv4Repr {
  663. src_addr,
  664. dst_addr,
  665. next_header: IpProtocol::Udp,
  666. hop_limit: 64,
  667. payload_len: udp_repr.header_len() + PAYLOAD_LEN,
  668. };
  669. // Emit to frame
  670. let mut bytes = vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + PAYLOAD_LEN];
  671. let frame = {
  672. ipv4_repr.emit(
  673. &mut Ipv4Packet::new_unchecked(&mut bytes),
  674. &ChecksumCapabilities::default(),
  675. );
  676. udp_repr.emit(
  677. &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
  678. &src_addr.into(),
  679. &dst_addr.into(),
  680. PAYLOAD_LEN,
  681. |buf| fill_slice(buf, 0x2a),
  682. &ChecksumCapabilities::default(),
  683. );
  684. Ipv4Packet::new_unchecked(&bytes)
  685. };
  686. assert_eq!(
  687. iface.inner.process_ipv4(
  688. &mut sockets,
  689. PacketMeta::default(),
  690. &frame,
  691. &mut iface.fragments
  692. ),
  693. None
  694. );
  695. }
  696. #[rstest]
  697. #[case(Medium::Ip)]
  698. #[cfg(all(feature = "socket-raw", feature = "socket-udp", feature = "medium-ip"))]
  699. #[case(Medium::Ethernet)]
  700. #[cfg(all(
  701. feature = "socket-raw",
  702. feature = "socket-udp",
  703. feature = "medium-ethernet"
  704. ))]
  705. fn test_raw_socket_with_udp_socket(#[case] medium: Medium) {
  706. use crate::wire::{IpEndpoint, IpVersion, Ipv4Packet, UdpPacket, UdpRepr};
  707. static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];
  708. let (mut iface, mut sockets, _) = setup(medium);
  709. let udp_rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
  710. let udp_tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
  711. let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
  712. let udp_socket_handle = sockets.add(udp_socket);
  713. // Bind the socket to port 68
  714. let socket = sockets.get_mut::<udp::Socket>(udp_socket_handle);
  715. assert_eq!(socket.bind(68), Ok(()));
  716. assert!(!socket.can_recv());
  717. assert!(socket.can_send());
  718. let packets = 1;
  719. let raw_rx_buffer =
  720. raw::PacketBuffer::new(vec![raw::PacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
  721. let raw_tx_buffer = raw::PacketBuffer::new(
  722. vec![raw::PacketMetadata::EMPTY; packets],
  723. vec![0; 48 * packets],
  724. );
  725. let raw_socket = raw::Socket::new(
  726. IpVersion::Ipv4,
  727. IpProtocol::Udp,
  728. raw_rx_buffer,
  729. raw_tx_buffer,
  730. );
  731. sockets.add(raw_socket);
  732. let src_addr = Ipv4Address([127, 0, 0, 2]);
  733. let dst_addr = Ipv4Address([127, 0, 0, 1]);
  734. let udp_repr = UdpRepr {
  735. src_port: 67,
  736. dst_port: 68,
  737. };
  738. let mut bytes = vec![0xff; udp_repr.header_len() + UDP_PAYLOAD.len()];
  739. let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
  740. udp_repr.emit(
  741. &mut packet,
  742. &src_addr.into(),
  743. &dst_addr.into(),
  744. UDP_PAYLOAD.len(),
  745. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  746. &ChecksumCapabilities::default(),
  747. );
  748. let ipv4_repr = Ipv4Repr {
  749. src_addr,
  750. dst_addr,
  751. next_header: IpProtocol::Udp,
  752. hop_limit: 64,
  753. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  754. };
  755. // Emit to frame
  756. let mut bytes = vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + UDP_PAYLOAD.len()];
  757. let frame = {
  758. ipv4_repr.emit(
  759. &mut Ipv4Packet::new_unchecked(&mut bytes),
  760. &ChecksumCapabilities::default(),
  761. );
  762. udp_repr.emit(
  763. &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
  764. &src_addr.into(),
  765. &dst_addr.into(),
  766. UDP_PAYLOAD.len(),
  767. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  768. &ChecksumCapabilities::default(),
  769. );
  770. Ipv4Packet::new_unchecked(&bytes)
  771. };
  772. assert_eq!(
  773. iface.inner.process_ipv4(
  774. &mut sockets,
  775. PacketMeta::default(),
  776. &frame,
  777. &mut iface.fragments
  778. ),
  779. None
  780. );
  781. // Make sure the UDP socket can still receive in presence of a Raw socket that handles UDP
  782. let socket = sockets.get_mut::<udp::Socket>(udp_socket_handle);
  783. assert!(socket.can_recv());
  784. assert_eq!(
  785. socket.recv(),
  786. Ok((
  787. &UDP_PAYLOAD[..],
  788. IpEndpoint::new(src_addr.into(), 67).into()
  789. ))
  790. );
  791. }
  792. #[rstest]
  793. #[case(Medium::Ip)]
  794. #[cfg(all(feature = "socket-udp", feature = "medium-ip"))]
  795. #[case(Medium::Ethernet)]
  796. #[cfg(all(feature = "socket-udp", feature = "medium-ethernet"))]
  797. fn test_icmp_reply_size(#[case] medium: Medium) {
  798. use crate::wire::IPV4_MIN_MTU as MIN_MTU;
  799. const MAX_PAYLOAD_LEN: usize = 528;
  800. let (mut iface, mut sockets, _device) = setup(medium);
  801. let src_addr = Ipv4Address([192, 168, 1, 1]);
  802. let dst_addr = Ipv4Address([192, 168, 1, 2]);
  803. // UDP packet that if not tructated will cause a icmp port unreachable reply
  804. // to exeed the minimum mtu bytes in length.
  805. let udp_repr = UdpRepr {
  806. src_port: 67,
  807. dst_port: 68,
  808. };
  809. let mut bytes = vec![0xff; udp_repr.header_len() + MAX_PAYLOAD_LEN];
  810. let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
  811. udp_repr.emit(
  812. &mut packet,
  813. &src_addr.into(),
  814. &dst_addr.into(),
  815. MAX_PAYLOAD_LEN,
  816. |buf| fill_slice(buf, 0x2a),
  817. &ChecksumCapabilities::default(),
  818. );
  819. let ip_repr = Ipv4Repr {
  820. src_addr,
  821. dst_addr,
  822. next_header: IpProtocol::Udp,
  823. hop_limit: 64,
  824. payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN,
  825. };
  826. let payload = packet.into_inner();
  827. let expected_icmp_repr = Icmpv4Repr::DstUnreachable {
  828. reason: Icmpv4DstUnreachable::PortUnreachable,
  829. header: ip_repr,
  830. data: &payload[..MAX_PAYLOAD_LEN],
  831. };
  832. let expected_ip_repr = Ipv4Repr {
  833. src_addr: dst_addr,
  834. dst_addr: src_addr,
  835. next_header: IpProtocol::Icmp,
  836. hop_limit: 64,
  837. payload_len: expected_icmp_repr.buffer_len(),
  838. };
  839. assert_eq!(
  840. expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(),
  841. MIN_MTU
  842. );
  843. assert_eq!(
  844. iface.inner.process_udp(
  845. &mut sockets,
  846. PacketMeta::default(),
  847. ip_repr.into(),
  848. udp_repr,
  849. false,
  850. &vec![0x2a; MAX_PAYLOAD_LEN],
  851. payload,
  852. ),
  853. Some(IpPacket::Icmpv4((expected_ip_repr, expected_icmp_repr)))
  854. );
  855. }