mod.rs 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774
  1. // Heads up! Before working on this file you should read the parts
  2. // of RFC 1122 that discuss Ethernet, ARP and IP for any IPv4 work
  3. // and RFCs 8200 and 4861 for any IPv6 and NDISC work.
  4. #[cfg(test)]
  5. mod tests;
  6. #[cfg(feature = "medium-ethernet")]
  7. mod ethernet;
  8. #[cfg(feature = "medium-ieee802154")]
  9. mod ieee802154;
  10. #[cfg(feature = "proto-ipv4")]
  11. mod ipv4;
  12. #[cfg(feature = "proto-ipv6")]
  13. mod ipv6;
  14. #[cfg(feature = "proto-sixlowpan")]
  15. mod sixlowpan;
  16. #[cfg(feature = "proto-igmp")]
  17. mod igmp;
  18. #[cfg(feature = "proto-igmp")]
  19. pub use igmp::MulticastError;
  20. use super::ip_packet::*;
  21. use core::result::Result;
  22. use heapless::{LinearMap, Vec};
  23. #[cfg(any(feature = "proto-ipv4", feature = "proto-sixlowpan"))]
  24. use super::fragmentation::PacketAssemblerSet;
  25. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  26. use super::neighbor::{Answer as NeighborAnswer, Cache as NeighborCache};
  27. use super::socket_set::SocketSet;
  28. use crate::config::{
  29. FRAGMENTATION_BUFFER_SIZE, IFACE_MAX_ADDR_COUNT, IFACE_MAX_MULTICAST_GROUP_COUNT,
  30. IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT,
  31. };
  32. use crate::iface::Routes;
  33. use crate::phy::PacketMeta;
  34. use crate::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
  35. use crate::rand::Rand;
  36. #[cfg(feature = "socket-dns")]
  37. use crate::socket::dns;
  38. use crate::socket::*;
  39. use crate::time::{Duration, Instant};
  40. #[cfg(feature = "proto-ipv4")]
  41. use crate::wire::Ipv4Packet as Ipv4PacketWire;
  42. #[cfg(feature = "proto-ipv6")]
  43. use crate::wire::Ipv6Packet as Ipv6PacketWire;
  44. use crate::wire::*;
  45. #[cfg(feature = "_proto-fragmentation")]
  46. #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
  47. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  48. pub(crate) enum FragKey {
  49. #[cfg(feature = "proto-ipv4-fragmentation")]
  50. Ipv4(Ipv4FragKey),
  51. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  52. Sixlowpan(SixlowpanFragKey),
  53. }
  54. pub(crate) struct FragmentsBuffer {
  55. #[cfg(feature = "proto-sixlowpan")]
  56. decompress_buf: [u8; sixlowpan::MAX_DECOMPRESSED_LEN],
  57. #[cfg(feature = "_proto-fragmentation")]
  58. pub(crate) assembler: PacketAssemblerSet<FragKey>,
  59. #[cfg(feature = "_proto-fragmentation")]
  60. reassembly_timeout: Duration,
  61. }
  62. #[cfg(not(feature = "_proto-fragmentation"))]
  63. pub(crate) struct Fragmenter {}
  64. #[cfg(not(feature = "_proto-fragmentation"))]
  65. impl Fragmenter {
  66. pub(crate) fn new() -> Self {
  67. Self {}
  68. }
  69. }
  70. #[cfg(feature = "_proto-fragmentation")]
  71. pub(crate) struct Fragmenter {
  72. /// The buffer that holds the unfragmented 6LoWPAN packet.
  73. buffer: [u8; FRAGMENTATION_BUFFER_SIZE],
  74. /// The size of the packet without the IEEE802.15.4 header and the fragmentation headers.
  75. packet_len: usize,
  76. /// The amount of bytes that already have been transmitted.
  77. sent_bytes: usize,
  78. #[cfg(feature = "proto-ipv4-fragmentation")]
  79. ipv4: Ipv4Fragmenter,
  80. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  81. sixlowpan: SixlowpanFragmenter,
  82. }
  83. #[cfg(feature = "proto-ipv4-fragmentation")]
  84. pub(crate) struct Ipv4Fragmenter {
  85. /// The IPv4 representation.
  86. repr: Ipv4Repr,
  87. /// The destination hardware address.
  88. #[cfg(feature = "medium-ethernet")]
  89. dst_hardware_addr: EthernetAddress,
  90. /// The offset of the next fragment.
  91. frag_offset: u16,
  92. /// The identifier of the stream.
  93. ident: u16,
  94. }
  95. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  96. pub(crate) struct SixlowpanFragmenter {
  97. /// The datagram size that is used for the fragmentation headers.
  98. datagram_size: u16,
  99. /// The datagram tag that is used for the fragmentation headers.
  100. datagram_tag: u16,
  101. datagram_offset: usize,
  102. /// The size of the FRAG_N packets.
  103. fragn_size: usize,
  104. /// The link layer IEEE802.15.4 source address.
  105. ll_dst_addr: Ieee802154Address,
  106. /// The link layer IEEE802.15.4 source address.
  107. ll_src_addr: Ieee802154Address,
  108. }
  109. #[cfg(feature = "_proto-fragmentation")]
  110. impl Fragmenter {
  111. pub(crate) fn new() -> Self {
  112. Self {
  113. buffer: [0u8; FRAGMENTATION_BUFFER_SIZE],
  114. packet_len: 0,
  115. sent_bytes: 0,
  116. #[cfg(feature = "proto-ipv4-fragmentation")]
  117. ipv4: Ipv4Fragmenter {
  118. repr: Ipv4Repr {
  119. src_addr: Ipv4Address::default(),
  120. dst_addr: Ipv4Address::default(),
  121. next_header: IpProtocol::Unknown(0),
  122. payload_len: 0,
  123. hop_limit: 0,
  124. },
  125. #[cfg(feature = "medium-ethernet")]
  126. dst_hardware_addr: EthernetAddress::default(),
  127. frag_offset: 0,
  128. ident: 0,
  129. },
  130. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  131. sixlowpan: SixlowpanFragmenter {
  132. datagram_size: 0,
  133. datagram_tag: 0,
  134. datagram_offset: 0,
  135. fragn_size: 0,
  136. ll_dst_addr: Ieee802154Address::Absent,
  137. ll_src_addr: Ieee802154Address::Absent,
  138. },
  139. }
  140. }
  141. /// Return `true` when everything is transmitted.
  142. #[inline]
  143. fn finished(&self) -> bool {
  144. self.packet_len == self.sent_bytes
  145. }
  146. /// Returns `true` when there is nothing to transmit.
  147. #[inline]
  148. fn is_empty(&self) -> bool {
  149. self.packet_len == 0
  150. }
  151. // Reset the buffer.
  152. fn reset(&mut self) {
  153. self.packet_len = 0;
  154. self.sent_bytes = 0;
  155. #[cfg(feature = "proto-ipv4-fragmentation")]
  156. {
  157. self.ipv4.repr = Ipv4Repr {
  158. src_addr: Ipv4Address::default(),
  159. dst_addr: Ipv4Address::default(),
  160. next_header: IpProtocol::Unknown(0),
  161. payload_len: 0,
  162. hop_limit: 0,
  163. };
  164. #[cfg(feature = "medium-ethernet")]
  165. {
  166. self.ipv4.dst_hardware_addr = EthernetAddress::default();
  167. }
  168. }
  169. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  170. {
  171. self.sixlowpan.datagram_size = 0;
  172. self.sixlowpan.datagram_tag = 0;
  173. self.sixlowpan.fragn_size = 0;
  174. self.sixlowpan.ll_dst_addr = Ieee802154Address::Absent;
  175. self.sixlowpan.ll_src_addr = Ieee802154Address::Absent;
  176. }
  177. }
  178. }
  179. macro_rules! check {
  180. ($e:expr) => {
  181. match $e {
  182. Ok(x) => x,
  183. Err(_) => {
  184. // concat!/stringify! doesn't work with defmt macros
  185. #[cfg(not(feature = "defmt"))]
  186. net_trace!(concat!("iface: malformed ", stringify!($e)));
  187. #[cfg(feature = "defmt")]
  188. net_trace!("iface: malformed");
  189. return Default::default();
  190. }
  191. }
  192. };
  193. }
  194. use check;
  195. /// A network interface.
  196. ///
  197. /// The network interface logically owns a number of other data structures; to avoid
  198. /// a dependency on heap allocation, it instead owns a `BorrowMut<[T]>`, which can be
  199. /// a `&mut [T]`, or `Vec<T>` if a heap is available.
  200. pub struct Interface {
  201. pub(crate) inner: InterfaceInner,
  202. fragments: FragmentsBuffer,
  203. fragmenter: Fragmenter,
  204. }
  205. /// The device independent part of an Ethernet network interface.
  206. ///
  207. /// Separating the device from the data required for processing and dispatching makes
  208. /// it possible to borrow them independently. For example, the tx and rx tokens borrow
  209. /// the `device` mutably until they're used, which makes it impossible to call other
  210. /// methods on the `Interface` in this time (since its `device` field is borrowed
  211. /// exclusively). However, it is still possible to call methods on its `inner` field.
  212. pub struct InterfaceInner {
  213. caps: DeviceCapabilities,
  214. now: Instant,
  215. rand: Rand,
  216. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  217. neighbor_cache: NeighborCache,
  218. hardware_addr: HardwareAddress,
  219. #[cfg(feature = "medium-ieee802154")]
  220. sequence_no: u8,
  221. #[cfg(feature = "medium-ieee802154")]
  222. pan_id: Option<Ieee802154Pan>,
  223. #[cfg(feature = "proto-ipv4-fragmentation")]
  224. ipv4_id: u16,
  225. #[cfg(feature = "proto-sixlowpan")]
  226. sixlowpan_address_context:
  227. Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT>,
  228. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  229. tag: u16,
  230. ip_addrs: Vec<IpCidr, IFACE_MAX_ADDR_COUNT>,
  231. #[cfg(feature = "proto-ipv4")]
  232. any_ip: bool,
  233. routes: Routes,
  234. #[cfg(feature = "proto-igmp")]
  235. ipv4_multicast_groups: LinearMap<Ipv4Address, (), IFACE_MAX_MULTICAST_GROUP_COUNT>,
  236. /// When to report for (all or) the next multicast group membership via IGMP
  237. #[cfg(feature = "proto-igmp")]
  238. igmp_report_state: IgmpReportState,
  239. }
  240. /// Configuration structure used for creating a network interface.
  241. #[non_exhaustive]
  242. pub struct Config {
  243. /// Random seed.
  244. ///
  245. /// It is strongly recommended that the random seed is different on each boot,
  246. /// to avoid problems with TCP port/sequence collisions.
  247. ///
  248. /// The seed doesn't have to be cryptographically secure.
  249. pub random_seed: u64,
  250. /// Set the Hardware address the interface will use.
  251. ///
  252. /// # Panics
  253. /// Creating the interface panics if the address is not unicast.
  254. pub hardware_addr: HardwareAddress,
  255. /// Set the IEEE802.15.4 PAN ID the interface will use.
  256. ///
  257. /// **NOTE**: we use the same PAN ID for destination and source.
  258. #[cfg(feature = "medium-ieee802154")]
  259. pub pan_id: Option<Ieee802154Pan>,
  260. }
  261. impl Config {
  262. pub fn new(hardware_addr: HardwareAddress) -> Self {
  263. Config {
  264. random_seed: 0,
  265. hardware_addr,
  266. #[cfg(feature = "medium-ieee802154")]
  267. pan_id: None,
  268. }
  269. }
  270. }
  271. impl Interface {
  272. /// Create a network interface using the previously provided configuration.
  273. ///
  274. /// # Panics
  275. /// This function panics if the [`Config::hardware_address`] does not match
  276. /// the medium of the device.
  277. pub fn new<D>(config: Config, device: &mut D, now: Instant) -> Self
  278. where
  279. D: Device + ?Sized,
  280. {
  281. let caps = device.capabilities();
  282. assert_eq!(
  283. config.hardware_addr.medium(),
  284. caps.medium,
  285. "The hardware address does not match the medium of the interface."
  286. );
  287. let mut rand = Rand::new(config.random_seed);
  288. #[cfg(feature = "medium-ieee802154")]
  289. let mut sequence_no;
  290. #[cfg(feature = "medium-ieee802154")]
  291. loop {
  292. sequence_no = (rand.rand_u32() & 0xff) as u8;
  293. if sequence_no != 0 {
  294. break;
  295. }
  296. }
  297. #[cfg(feature = "proto-sixlowpan")]
  298. let mut tag;
  299. #[cfg(feature = "proto-sixlowpan")]
  300. loop {
  301. tag = rand.rand_u16();
  302. if tag != 0 {
  303. break;
  304. }
  305. }
  306. #[cfg(feature = "proto-ipv4")]
  307. let mut ipv4_id;
  308. #[cfg(feature = "proto-ipv4")]
  309. loop {
  310. ipv4_id = rand.rand_u16();
  311. if ipv4_id != 0 {
  312. break;
  313. }
  314. }
  315. Interface {
  316. fragments: FragmentsBuffer {
  317. #[cfg(feature = "proto-sixlowpan")]
  318. decompress_buf: [0u8; sixlowpan::MAX_DECOMPRESSED_LEN],
  319. #[cfg(feature = "_proto-fragmentation")]
  320. assembler: PacketAssemblerSet::new(),
  321. #[cfg(feature = "_proto-fragmentation")]
  322. reassembly_timeout: Duration::from_secs(60),
  323. },
  324. fragmenter: Fragmenter::new(),
  325. inner: InterfaceInner {
  326. now,
  327. caps,
  328. hardware_addr: config.hardware_addr,
  329. ip_addrs: Vec::new(),
  330. #[cfg(feature = "proto-ipv4")]
  331. any_ip: false,
  332. routes: Routes::new(),
  333. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  334. neighbor_cache: NeighborCache::new(),
  335. #[cfg(feature = "proto-igmp")]
  336. ipv4_multicast_groups: LinearMap::new(),
  337. #[cfg(feature = "proto-igmp")]
  338. igmp_report_state: IgmpReportState::Inactive,
  339. #[cfg(feature = "medium-ieee802154")]
  340. sequence_no,
  341. #[cfg(feature = "medium-ieee802154")]
  342. pan_id: config.pan_id,
  343. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  344. tag,
  345. #[cfg(feature = "proto-ipv4-fragmentation")]
  346. ipv4_id,
  347. #[cfg(feature = "proto-sixlowpan")]
  348. sixlowpan_address_context: Vec::new(),
  349. rand,
  350. },
  351. }
  352. }
  353. /// Get the socket context.
  354. ///
  355. /// The context is needed for some socket methods.
  356. pub fn context(&mut self) -> &mut InterfaceInner {
  357. &mut self.inner
  358. }
  359. /// Get the HardwareAddress address of the interface.
  360. ///
  361. /// # Panics
  362. /// This function panics if the medium is not Ethernet or Ieee802154.
  363. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  364. pub fn hardware_addr(&self) -> HardwareAddress {
  365. #[cfg(all(feature = "medium-ethernet", not(feature = "medium-ieee802154")))]
  366. assert!(self.inner.caps.medium == Medium::Ethernet);
  367. #[cfg(all(feature = "medium-ieee802154", not(feature = "medium-ethernet")))]
  368. assert!(self.inner.caps.medium == Medium::Ieee802154);
  369. #[cfg(all(feature = "medium-ieee802154", feature = "medium-ethernet"))]
  370. assert!(
  371. self.inner.caps.medium == Medium::Ethernet
  372. || self.inner.caps.medium == Medium::Ieee802154
  373. );
  374. self.inner.hardware_addr
  375. }
  376. /// Set the HardwareAddress address of the interface.
  377. ///
  378. /// # Panics
  379. /// This function panics if the address is not unicast, and if the medium is not Ethernet or
  380. /// Ieee802154.
  381. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  382. pub fn set_hardware_addr(&mut self, addr: HardwareAddress) {
  383. #[cfg(all(feature = "medium-ethernet", not(feature = "medium-ieee802154")))]
  384. assert!(self.inner.caps.medium == Medium::Ethernet);
  385. #[cfg(all(feature = "medium-ieee802154", not(feature = "medium-ethernet")))]
  386. assert!(self.inner.caps.medium == Medium::Ieee802154);
  387. #[cfg(all(feature = "medium-ieee802154", feature = "medium-ethernet"))]
  388. assert!(
  389. self.inner.caps.medium == Medium::Ethernet
  390. || self.inner.caps.medium == Medium::Ieee802154
  391. );
  392. InterfaceInner::check_hardware_addr(&addr);
  393. self.inner.hardware_addr = addr;
  394. }
  395. /// Get the IP addresses of the interface.
  396. pub fn ip_addrs(&self) -> &[IpCidr] {
  397. self.inner.ip_addrs.as_ref()
  398. }
  399. /// Get the first IPv4 address if present.
  400. #[cfg(feature = "proto-ipv4")]
  401. pub fn ipv4_addr(&self) -> Option<Ipv4Address> {
  402. self.inner.ipv4_addr()
  403. }
  404. /// Get the first IPv6 address if present.
  405. #[cfg(feature = "proto-ipv6")]
  406. pub fn ipv6_addr(&self) -> Option<Ipv6Address> {
  407. self.inner.ipv6_addr()
  408. }
  409. /// Get an address from the interface that could be used as source address. For IPv4, this is
  410. /// the first IPv4 address from the list of addresses. For IPv6, the address is based on the
  411. /// destination address and uses RFC6724 for selecting the source address.
  412. pub fn get_source_address(&self, dst_addr: &IpAddress) -> Option<IpAddress> {
  413. self.inner.get_source_address(dst_addr)
  414. }
  415. /// Get an address from the interface that could be used as source address. This is the first
  416. /// IPv4 address from the list of addresses in the interface.
  417. #[cfg(feature = "proto-ipv4")]
  418. pub fn get_source_address_ipv4(&self, dst_addr: &Ipv4Address) -> Option<Ipv4Address> {
  419. self.inner.get_source_address_ipv4(dst_addr)
  420. }
  421. /// Get an address from the interface that could be used as source address. The selection is
  422. /// based on RFC6724.
  423. #[cfg(feature = "proto-ipv6")]
  424. pub fn get_source_address_ipv6(&self, dst_addr: &Ipv6Address) -> Option<Ipv6Address> {
  425. self.inner.get_source_address_ipv6(dst_addr)
  426. }
  427. /// Update the IP addresses of the interface.
  428. ///
  429. /// # Panics
  430. /// This function panics if any of the addresses are not unicast.
  431. pub fn update_ip_addrs<F: FnOnce(&mut Vec<IpCidr, IFACE_MAX_ADDR_COUNT>)>(&mut self, f: F) {
  432. f(&mut self.inner.ip_addrs);
  433. InterfaceInner::flush_cache(&mut self.inner);
  434. InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
  435. }
  436. /// Check whether the interface has the given IP address assigned.
  437. pub fn has_ip_addr<T: Into<IpAddress>>(&self, addr: T) -> bool {
  438. self.inner.has_ip_addr(addr)
  439. }
  440. pub fn routes(&self) -> &Routes {
  441. &self.inner.routes
  442. }
  443. pub fn routes_mut(&mut self) -> &mut Routes {
  444. &mut self.inner.routes
  445. }
  446. /// Enable or disable the AnyIP capability.
  447. ///
  448. /// AnyIP allowins packets to be received
  449. /// locally on IPv4 addresses other than the interface's configured [ip_addrs].
  450. /// When AnyIP is enabled and a route prefix in [`routes`](Self::routes) specifies one of
  451. /// the interface's [`ip_addrs`](Self::ip_addrs) as its gateway, the interface will accept
  452. /// packets addressed to that prefix.
  453. ///
  454. /// # IPv6
  455. ///
  456. /// This option is not available or required for IPv6 as packets sent to
  457. /// the interface are not filtered by IPv6 address.
  458. #[cfg(feature = "proto-ipv4")]
  459. pub fn set_any_ip(&mut self, any_ip: bool) {
  460. self.inner.any_ip = any_ip;
  461. }
  462. /// Get whether AnyIP is enabled.
  463. ///
  464. /// See [`set_any_ip`](Self::set_any_ip) for details on AnyIP
  465. #[cfg(feature = "proto-ipv4")]
  466. pub fn any_ip(&self) -> bool {
  467. self.inner.any_ip
  468. }
  469. /// Get the 6LoWPAN address contexts.
  470. #[cfg(feature = "proto-sixlowpan")]
  471. pub fn sixlowpan_address_context(
  472. &self,
  473. ) -> &Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
  474. &self.inner.sixlowpan_address_context
  475. }
  476. /// Get a mutable reference to the 6LoWPAN address contexts.
  477. #[cfg(feature = "proto-sixlowpan")]
  478. pub fn sixlowpan_address_context_mut(
  479. &mut self,
  480. ) -> &mut Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
  481. &mut self.inner.sixlowpan_address_context
  482. }
  483. /// Get the packet reassembly timeout.
  484. #[cfg(feature = "_proto-fragmentation")]
  485. pub fn reassembly_timeout(&self) -> Duration {
  486. self.fragments.reassembly_timeout
  487. }
  488. /// Set the packet reassembly timeout.
  489. #[cfg(feature = "_proto-fragmentation")]
  490. pub fn set_reassembly_timeout(&mut self, timeout: Duration) {
  491. if timeout > Duration::from_secs(60) {
  492. net_debug!("RFC 4944 specifies that the reassembly timeout MUST be set to a maximum of 60 seconds");
  493. }
  494. self.fragments.reassembly_timeout = timeout;
  495. }
  496. /// Transmit packets queued in the given sockets, and receive packets queued
  497. /// in the device.
  498. ///
  499. /// This function returns a boolean value indicating whether any packets were
  500. /// processed or emitted, and thus, whether the readiness of any socket might
  501. /// have changed.
  502. pub fn poll<D>(
  503. &mut self,
  504. timestamp: Instant,
  505. device: &mut D,
  506. sockets: &mut SocketSet<'_>,
  507. ) -> bool
  508. where
  509. D: Device + ?Sized,
  510. {
  511. self.inner.now = timestamp;
  512. #[cfg(feature = "_proto-fragmentation")]
  513. self.fragments.assembler.remove_expired(timestamp);
  514. match self.inner.caps.medium {
  515. #[cfg(feature = "medium-ieee802154")]
  516. Medium::Ieee802154 =>
  517. {
  518. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  519. if self.sixlowpan_egress(device) {
  520. return true;
  521. }
  522. }
  523. #[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
  524. _ =>
  525. {
  526. #[cfg(feature = "proto-ipv4-fragmentation")]
  527. if self.ipv4_egress(device) {
  528. return true;
  529. }
  530. }
  531. }
  532. let mut readiness_may_have_changed = false;
  533. loop {
  534. let mut did_something = false;
  535. did_something |= self.socket_ingress(device, sockets);
  536. did_something |= self.socket_egress(device, sockets);
  537. #[cfg(feature = "proto-igmp")]
  538. {
  539. did_something |= self.igmp_egress(device);
  540. }
  541. if did_something {
  542. readiness_may_have_changed = true;
  543. } else {
  544. break;
  545. }
  546. }
  547. readiness_may_have_changed
  548. }
  549. /// Return a _soft deadline_ for calling [poll] the next time.
  550. /// The [Instant] returned is the time at which you should call [poll] next.
  551. /// It is harmless (but wastes energy) to call it before the [Instant], and
  552. /// potentially harmful (impacting quality of service) to call it after the
  553. /// [Instant]
  554. ///
  555. /// [poll]: #method.poll
  556. /// [Instant]: struct.Instant.html
  557. pub fn poll_at(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Instant> {
  558. self.inner.now = timestamp;
  559. #[cfg(feature = "_proto-fragmentation")]
  560. if !self.fragmenter.is_empty() {
  561. return Some(Instant::from_millis(0));
  562. }
  563. let inner = &mut self.inner;
  564. sockets
  565. .items()
  566. .filter_map(move |item| {
  567. let socket_poll_at = item.socket.poll_at(inner);
  568. match item
  569. .meta
  570. .poll_at(socket_poll_at, |ip_addr| inner.has_neighbor(&ip_addr))
  571. {
  572. PollAt::Ingress => None,
  573. PollAt::Time(instant) => Some(instant),
  574. PollAt::Now => Some(Instant::from_millis(0)),
  575. }
  576. })
  577. .min()
  578. }
  579. /// Return an _advisory wait time_ for calling [poll] the next time.
  580. /// The [Duration] returned is the time left to wait before calling [poll] next.
  581. /// It is harmless (but wastes energy) to call it before the [Duration] has passed,
  582. /// and potentially harmful (impacting quality of service) to call it after the
  583. /// [Duration] has passed.
  584. ///
  585. /// [poll]: #method.poll
  586. /// [Duration]: struct.Duration.html
  587. pub fn poll_delay(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Duration> {
  588. match self.poll_at(timestamp, sockets) {
  589. Some(poll_at) if timestamp < poll_at => Some(poll_at - timestamp),
  590. Some(_) => Some(Duration::from_millis(0)),
  591. _ => None,
  592. }
  593. }
  594. fn socket_ingress<D>(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool
  595. where
  596. D: Device + ?Sized,
  597. {
  598. let mut processed_any = false;
  599. while let Some((rx_token, tx_token)) = device.receive(self.inner.now) {
  600. let rx_meta = rx_token.meta();
  601. rx_token.consume(|frame| {
  602. match self.inner.caps.medium {
  603. #[cfg(feature = "medium-ethernet")]
  604. Medium::Ethernet => {
  605. if let Some(packet) = self.inner.process_ethernet(
  606. sockets,
  607. rx_meta,
  608. frame,
  609. &mut self.fragments,
  610. ) {
  611. if let Err(err) =
  612. self.inner.dispatch(tx_token, packet, &mut self.fragmenter)
  613. {
  614. net_debug!("Failed to send response: {:?}", err);
  615. }
  616. }
  617. }
  618. #[cfg(feature = "medium-ip")]
  619. Medium::Ip => {
  620. if let Some(packet) =
  621. self.inner
  622. .process_ip(sockets, rx_meta, frame, &mut self.fragments)
  623. {
  624. if let Err(err) = self.inner.dispatch_ip(
  625. tx_token,
  626. PacketMeta::default(),
  627. packet,
  628. &mut self.fragmenter,
  629. ) {
  630. net_debug!("Failed to send response: {:?}", err);
  631. }
  632. }
  633. }
  634. #[cfg(feature = "medium-ieee802154")]
  635. Medium::Ieee802154 => {
  636. if let Some(packet) = self.inner.process_ieee802154(
  637. sockets,
  638. rx_meta,
  639. frame,
  640. &mut self.fragments,
  641. ) {
  642. if let Err(err) = self.inner.dispatch_ip(
  643. tx_token,
  644. PacketMeta::default(),
  645. packet,
  646. &mut self.fragmenter,
  647. ) {
  648. net_debug!("Failed to send response: {:?}", err);
  649. }
  650. }
  651. }
  652. }
  653. processed_any = true;
  654. });
  655. }
  656. processed_any
  657. }
  658. fn socket_egress<D>(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool
  659. where
  660. D: Device + ?Sized,
  661. {
  662. let _caps = device.capabilities();
  663. enum EgressError {
  664. Exhausted,
  665. Dispatch(DispatchError),
  666. }
  667. let mut emitted_any = false;
  668. for item in sockets.items_mut() {
  669. if !item
  670. .meta
  671. .egress_permitted(self.inner.now, |ip_addr| self.inner.has_neighbor(&ip_addr))
  672. {
  673. continue;
  674. }
  675. let mut neighbor_addr = None;
  676. let mut respond = |inner: &mut InterfaceInner, meta: PacketMeta, response: IpPacket| {
  677. neighbor_addr = Some(response.ip_repr().dst_addr());
  678. let t = device.transmit(inner.now).ok_or_else(|| {
  679. net_debug!("failed to transmit IP: device exhausted");
  680. EgressError::Exhausted
  681. })?;
  682. inner
  683. .dispatch_ip(t, meta, response, &mut self.fragmenter)
  684. .map_err(EgressError::Dispatch)?;
  685. emitted_any = true;
  686. Ok(())
  687. };
  688. let result = match &mut item.socket {
  689. #[cfg(feature = "socket-raw")]
  690. Socket::Raw(socket) => socket.dispatch(&mut self.inner, |inner, (ip, raw)| {
  691. respond(
  692. inner,
  693. PacketMeta::default(),
  694. IpPacket::new(ip, IpPayload::Raw(raw)),
  695. )
  696. }),
  697. #[cfg(feature = "socket-icmp")]
  698. Socket::Icmp(socket) => {
  699. socket.dispatch(&mut self.inner, |inner, response| match response {
  700. #[cfg(feature = "proto-ipv4")]
  701. (IpRepr::Ipv4(ipv4_repr), IcmpRepr::Ipv4(icmpv4_repr)) => respond(
  702. inner,
  703. PacketMeta::default(),
  704. IpPacket::new_ipv4(ipv4_repr, IpPayload::Icmpv4(icmpv4_repr)),
  705. ),
  706. #[cfg(feature = "proto-ipv6")]
  707. (IpRepr::Ipv6(ipv6_repr), IcmpRepr::Ipv6(icmpv6_repr)) => respond(
  708. inner,
  709. PacketMeta::default(),
  710. IpPacket::new_ipv6(ipv6_repr, IpPayload::Icmpv6(icmpv6_repr)),
  711. ),
  712. #[allow(unreachable_patterns)]
  713. _ => unreachable!(),
  714. })
  715. }
  716. #[cfg(feature = "socket-udp")]
  717. Socket::Udp(socket) => {
  718. socket.dispatch(&mut self.inner, |inner, meta, (ip, udp, payload)| {
  719. respond(inner, meta, IpPacket::new(ip, IpPayload::Udp(udp, payload)))
  720. })
  721. }
  722. #[cfg(feature = "socket-tcp")]
  723. Socket::Tcp(socket) => socket.dispatch(&mut self.inner, |inner, (ip, tcp)| {
  724. respond(
  725. inner,
  726. PacketMeta::default(),
  727. IpPacket::new(ip, IpPayload::Tcp(tcp)),
  728. )
  729. }),
  730. #[cfg(feature = "socket-dhcpv4")]
  731. Socket::Dhcpv4(socket) => {
  732. socket.dispatch(&mut self.inner, |inner, (ip, udp, dhcp)| {
  733. respond(
  734. inner,
  735. PacketMeta::default(),
  736. IpPacket::new_ipv4(ip, IpPayload::Dhcpv4(udp, dhcp)),
  737. )
  738. })
  739. }
  740. #[cfg(feature = "socket-dns")]
  741. Socket::Dns(socket) => socket.dispatch(&mut self.inner, |inner, (ip, udp, dns)| {
  742. respond(
  743. inner,
  744. PacketMeta::default(),
  745. IpPacket::new(ip, IpPayload::Udp(udp, dns)),
  746. )
  747. }),
  748. };
  749. match result {
  750. Err(EgressError::Exhausted) => break, // Device buffer full.
  751. Err(EgressError::Dispatch(_)) => {
  752. // `NeighborCache` already takes care of rate limiting the neighbor discovery
  753. // requests from the socket. However, without an additional rate limiting
  754. // mechanism, we would spin on every socket that has yet to discover its
  755. // neighbor.
  756. item.meta.neighbor_missing(
  757. self.inner.now,
  758. neighbor_addr.expect("non-IP response packet"),
  759. );
  760. }
  761. Ok(()) => {}
  762. }
  763. }
  764. emitted_any
  765. }
  766. /// Process fragments that still need to be sent for IPv4 packets.
  767. ///
  768. /// This function returns a boolean value indicating whether any packets were
  769. /// processed or emitted, and thus, whether the readiness of any socket might
  770. /// have changed.
  771. #[cfg(feature = "proto-ipv4-fragmentation")]
  772. fn ipv4_egress<D>(&mut self, device: &mut D) -> bool
  773. where
  774. D: Device + ?Sized,
  775. {
  776. // Reset the buffer when we transmitted everything.
  777. if self.fragmenter.finished() {
  778. self.fragmenter.reset();
  779. }
  780. if self.fragmenter.is_empty() {
  781. return false;
  782. }
  783. let pkt = &self.fragmenter;
  784. if pkt.packet_len > pkt.sent_bytes {
  785. if let Some(tx_token) = device.transmit(self.inner.now) {
  786. self.inner
  787. .dispatch_ipv4_frag(tx_token, &mut self.fragmenter);
  788. return true;
  789. }
  790. }
  791. false
  792. }
  793. /// Process fragments that still need to be sent for 6LoWPAN packets.
  794. ///
  795. /// This function returns a boolean value indicating whether any packets were
  796. /// processed or emitted, and thus, whether the readiness of any socket might
  797. /// have changed.
  798. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  799. fn sixlowpan_egress<D>(&mut self, device: &mut D) -> bool
  800. where
  801. D: Device + ?Sized,
  802. {
  803. // Reset the buffer when we transmitted everything.
  804. if self.fragmenter.finished() {
  805. self.fragmenter.reset();
  806. }
  807. if self.fragmenter.is_empty() {
  808. return false;
  809. }
  810. let pkt = &self.fragmenter;
  811. if pkt.packet_len > pkt.sent_bytes {
  812. if let Some(tx_token) = device.transmit(self.inner.now) {
  813. self.inner
  814. .dispatch_ieee802154_frag(tx_token, &mut self.fragmenter);
  815. return true;
  816. }
  817. }
  818. false
  819. }
  820. }
  821. impl InterfaceInner {
  822. #[allow(unused)] // unused depending on which sockets are enabled
  823. pub(crate) fn now(&self) -> Instant {
  824. self.now
  825. }
  826. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  827. #[allow(unused)] // unused depending on which sockets are enabled
  828. pub(crate) fn hardware_addr(&self) -> HardwareAddress {
  829. self.hardware_addr
  830. }
  831. #[allow(unused)] // unused depending on which sockets are enabled
  832. pub(crate) fn checksum_caps(&self) -> ChecksumCapabilities {
  833. self.caps.checksum.clone()
  834. }
  835. #[allow(unused)] // unused depending on which sockets are enabled
  836. pub(crate) fn ip_mtu(&self) -> usize {
  837. self.caps.ip_mtu()
  838. }
  839. #[allow(unused)] // unused depending on which sockets are enabled, and in tests
  840. pub(crate) fn rand(&mut self) -> &mut Rand {
  841. &mut self.rand
  842. }
  843. #[allow(unused)] // unused depending on which sockets are enabled
  844. pub(crate) fn get_source_address(&self, dst_addr: &IpAddress) -> Option<IpAddress> {
  845. match dst_addr {
  846. #[cfg(feature = "proto-ipv4")]
  847. IpAddress::Ipv4(addr) => self.get_source_address_ipv4(addr).map(|a| a.into()),
  848. #[cfg(feature = "proto-ipv6")]
  849. IpAddress::Ipv6(addr) => self.get_source_address_ipv6(addr).map(|a| a.into()),
  850. }
  851. }
  852. #[cfg(feature = "proto-ipv4")]
  853. #[allow(unused)]
  854. pub(crate) fn get_source_address_ipv4(&self, _dst_addr: &Ipv4Address) -> Option<Ipv4Address> {
  855. for cidr in self.ip_addrs.iter() {
  856. #[allow(irrefutable_let_patterns)] // if only ipv4 is enabled
  857. if let IpCidr::Ipv4(cidr) = cidr {
  858. return Some(cidr.address());
  859. }
  860. }
  861. None
  862. }
  863. #[cfg(feature = "proto-ipv6")]
  864. #[allow(unused)]
  865. pub(crate) fn get_source_address_ipv6(&self, dst_addr: &Ipv6Address) -> Option<Ipv6Address> {
  866. // RFC 6724 describes how to select the correct source address depending on the destination
  867. // address.
  868. // See RFC 6724 Section 4: Candidate source address
  869. fn is_candidate_source_address(dst_addr: &Ipv6Address, src_addr: &Ipv6Address) -> bool {
  870. // For all multicast and link-local destination addresses, the candidate address MUST
  871. // only be an address from the same link.
  872. if dst_addr.is_link_local() && !src_addr.is_link_local() {
  873. return false;
  874. }
  875. if dst_addr.is_multicast()
  876. && matches!(dst_addr.scope(), Ipv6AddressScope::LinkLocal)
  877. && src_addr.is_multicast()
  878. && !matches!(src_addr.scope(), Ipv6AddressScope::LinkLocal)
  879. {
  880. return false;
  881. }
  882. // Loopback addresses and multicast address can not be in the candidate source address
  883. // list. Except when the destination multicast address has a link-local scope, then the
  884. // source address can also be link-local multicast.
  885. if src_addr.is_loopback() || src_addr.is_multicast() {
  886. return false;
  887. }
  888. true
  889. }
  890. // See RFC 6724 Section 2.2: Common Prefix Length
  891. fn common_prefix_length(dst_addr: &Ipv6Cidr, src_addr: &Ipv6Address) -> usize {
  892. let addr = dst_addr.address();
  893. let mut bits = 0;
  894. for (l, r) in addr.as_bytes().iter().zip(src_addr.as_bytes().iter()) {
  895. if l == r {
  896. bits += 8;
  897. } else {
  898. bits += (l ^ r).leading_zeros();
  899. break;
  900. }
  901. }
  902. bits = bits.min(dst_addr.prefix_len() as u32);
  903. bits as usize
  904. }
  905. // Get the first address that is a candidate address.
  906. let mut candidate = self
  907. .ip_addrs
  908. .iter()
  909. .filter_map(|a| match a {
  910. #[cfg(feature = "proto-ipv4")]
  911. IpCidr::Ipv4(_) => None,
  912. #[cfg(feature = "proto-ipv6")]
  913. IpCidr::Ipv6(a) => Some(a),
  914. })
  915. .find(|a| is_candidate_source_address(dst_addr, &a.address()))
  916. .unwrap();
  917. for addr in self.ip_addrs.iter().filter_map(|a| match a {
  918. #[cfg(feature = "proto-ipv4")]
  919. IpCidr::Ipv4(_) => None,
  920. #[cfg(feature = "proto-ipv6")]
  921. IpCidr::Ipv6(a) => Some(a),
  922. }) {
  923. if !is_candidate_source_address(dst_addr, &addr.address()) {
  924. continue;
  925. }
  926. // Rule 1: prefer the address that is the same as the output destination address.
  927. if candidate.address() != *dst_addr && addr.address() == *dst_addr {
  928. candidate = addr;
  929. }
  930. // Rule 2: prefer appropriate scope.
  931. if (candidate.address().scope() as u8) < (addr.address().scope() as u8) {
  932. if (candidate.address().scope() as u8) < (dst_addr.scope() as u8) {
  933. candidate = addr;
  934. }
  935. } else if (addr.address().scope() as u8) > (dst_addr.scope() as u8) {
  936. candidate = addr;
  937. }
  938. // Rule 3: avoid deprecated addresses (TODO)
  939. // Rule 4: prefer home addresses (TODO)
  940. // Rule 5: prefer outgoing interfaces (TODO)
  941. // Rule 5.5: prefer addresses in a prefix advertises by the next-hop (TODO).
  942. // Rule 6: prefer matching label (TODO)
  943. // Rule 7: prefer temporary addresses (TODO)
  944. // Rule 8: use longest matching prefix
  945. if common_prefix_length(candidate, dst_addr) < common_prefix_length(addr, dst_addr) {
  946. candidate = addr;
  947. }
  948. }
  949. Some(candidate.address())
  950. }
  951. #[cfg(test)]
  952. #[allow(unused)] // unused depending on which sockets are enabled
  953. pub(crate) fn set_now(&mut self, now: Instant) {
  954. self.now = now
  955. }
  956. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  957. fn check_hardware_addr(addr: &HardwareAddress) {
  958. if !addr.is_unicast() {
  959. panic!("Hardware address {addr} is not unicast")
  960. }
  961. }
  962. fn check_ip_addrs(addrs: &[IpCidr]) {
  963. for cidr in addrs {
  964. if !cidr.address().is_unicast() && !cidr.address().is_unspecified() {
  965. panic!("IP address {} is not unicast", cidr.address())
  966. }
  967. }
  968. }
  969. #[cfg(feature = "medium-ieee802154")]
  970. fn get_sequence_number(&mut self) -> u8 {
  971. let no = self.sequence_no;
  972. self.sequence_no = self.sequence_no.wrapping_add(1);
  973. no
  974. }
  975. #[cfg(feature = "proto-ipv4-fragmentation")]
  976. fn get_ipv4_ident(&mut self) -> u16 {
  977. let ipv4_id = self.ipv4_id;
  978. self.ipv4_id = self.ipv4_id.wrapping_add(1);
  979. ipv4_id
  980. }
  981. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  982. fn get_sixlowpan_fragment_tag(&mut self) -> u16 {
  983. let tag = self.tag;
  984. self.tag = self.tag.wrapping_add(1);
  985. tag
  986. }
  987. /// Determine if the given `Ipv6Address` is the solicited node
  988. /// multicast address for a IPv6 addresses assigned to the interface.
  989. /// See [RFC 4291 § 2.7.1] for more details.
  990. ///
  991. /// [RFC 4291 § 2.7.1]: https://tools.ietf.org/html/rfc4291#section-2.7.1
  992. #[cfg(feature = "proto-ipv6")]
  993. pub fn has_solicited_node(&self, addr: Ipv6Address) -> bool {
  994. self.ip_addrs.iter().any(|cidr| {
  995. match *cidr {
  996. IpCidr::Ipv6(cidr) if cidr.address() != Ipv6Address::LOOPBACK => {
  997. // Take the lower order 24 bits of the IPv6 address and
  998. // append those bits to FF02:0:0:0:0:1:FF00::/104.
  999. addr.as_bytes()[14..] == cidr.address().as_bytes()[14..]
  1000. }
  1001. _ => false,
  1002. }
  1003. })
  1004. }
  1005. /// Check whether the interface has the given IP address assigned.
  1006. fn has_ip_addr<T: Into<IpAddress>>(&self, addr: T) -> bool {
  1007. let addr = addr.into();
  1008. self.ip_addrs.iter().any(|probe| probe.address() == addr)
  1009. }
  1010. /// Get the first IPv4 address of the interface.
  1011. #[cfg(feature = "proto-ipv4")]
  1012. pub fn ipv4_addr(&self) -> Option<Ipv4Address> {
  1013. self.ip_addrs.iter().find_map(|addr| match *addr {
  1014. IpCidr::Ipv4(cidr) => Some(cidr.address()),
  1015. #[allow(unreachable_patterns)]
  1016. _ => None,
  1017. })
  1018. }
  1019. /// Get the first IPv6 address if present.
  1020. #[cfg(feature = "proto-ipv6")]
  1021. pub fn ipv6_addr(&self) -> Option<Ipv6Address> {
  1022. self.ip_addrs.iter().find_map(|addr| match *addr {
  1023. IpCidr::Ipv6(cidr) => Some(cidr.address()),
  1024. #[allow(unreachable_patterns)]
  1025. _ => None,
  1026. })
  1027. }
  1028. #[cfg(not(feature = "proto-igmp"))]
  1029. fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
  1030. false
  1031. }
  1032. #[cfg(feature = "medium-ip")]
  1033. fn process_ip<'frame>(
  1034. &mut self,
  1035. sockets: &mut SocketSet,
  1036. meta: PacketMeta,
  1037. ip_payload: &'frame [u8],
  1038. frag: &'frame mut FragmentsBuffer,
  1039. ) -> Option<IpPacket<'frame>> {
  1040. match IpVersion::of_packet(ip_payload) {
  1041. #[cfg(feature = "proto-ipv4")]
  1042. Ok(IpVersion::Ipv4) => {
  1043. let ipv4_packet = check!(Ipv4PacketWire::new_checked(ip_payload));
  1044. self.process_ipv4(sockets, meta, &ipv4_packet, frag)
  1045. }
  1046. #[cfg(feature = "proto-ipv6")]
  1047. Ok(IpVersion::Ipv6) => {
  1048. let ipv6_packet = check!(Ipv6PacketWire::new_checked(ip_payload));
  1049. self.process_ipv6(sockets, meta, &ipv6_packet)
  1050. }
  1051. // Drop all other traffic.
  1052. _ => None,
  1053. }
  1054. }
  1055. #[cfg(feature = "socket-raw")]
  1056. fn raw_socket_filter(
  1057. &mut self,
  1058. sockets: &mut SocketSet,
  1059. ip_repr: &IpRepr,
  1060. ip_payload: &[u8],
  1061. ) -> bool {
  1062. let mut handled_by_raw_socket = false;
  1063. // Pass every IP packet to all raw sockets we have registered.
  1064. for raw_socket in sockets
  1065. .items_mut()
  1066. .filter_map(|i| raw::Socket::downcast_mut(&mut i.socket))
  1067. {
  1068. if raw_socket.accepts(ip_repr) {
  1069. raw_socket.process(self, ip_repr, ip_payload);
  1070. handled_by_raw_socket = true;
  1071. }
  1072. }
  1073. handled_by_raw_socket
  1074. }
  1075. /// Checks if an address is broadcast, taking into account ipv4 subnet-local
  1076. /// broadcast addresses.
  1077. pub(crate) fn is_broadcast(&self, address: &IpAddress) -> bool {
  1078. match address {
  1079. #[cfg(feature = "proto-ipv4")]
  1080. IpAddress::Ipv4(address) => self.is_broadcast_v4(*address),
  1081. #[cfg(feature = "proto-ipv6")]
  1082. IpAddress::Ipv6(_) => false,
  1083. }
  1084. }
  1085. /// Checks if an address is broadcast, taking into account ipv4 subnet-local
  1086. /// broadcast addresses.
  1087. #[cfg(feature = "proto-ipv4")]
  1088. pub(crate) fn is_broadcast_v4(&self, address: Ipv4Address) -> bool {
  1089. if address.is_broadcast() {
  1090. return true;
  1091. }
  1092. self.ip_addrs
  1093. .iter()
  1094. .filter_map(|own_cidr| match own_cidr {
  1095. IpCidr::Ipv4(own_ip) => Some(own_ip.broadcast()?),
  1096. #[cfg(feature = "proto-ipv6")]
  1097. IpCidr::Ipv6(_) => None,
  1098. })
  1099. .any(|broadcast_address| address == broadcast_address)
  1100. }
  1101. /// Checks if an ipv4 address is unicast, taking into account subnet broadcast addresses
  1102. #[cfg(feature = "proto-ipv4")]
  1103. fn is_unicast_v4(&self, address: Ipv4Address) -> bool {
  1104. address.is_unicast() && !self.is_broadcast_v4(address)
  1105. }
  1106. #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
  1107. #[allow(clippy::too_many_arguments)]
  1108. fn process_udp<'frame>(
  1109. &mut self,
  1110. sockets: &mut SocketSet,
  1111. meta: PacketMeta,
  1112. ip_repr: IpRepr,
  1113. udp_repr: UdpRepr,
  1114. handled_by_raw_socket: bool,
  1115. udp_payload: &'frame [u8],
  1116. ip_payload: &'frame [u8],
  1117. ) -> Option<IpPacket<'frame>> {
  1118. #[cfg(feature = "socket-udp")]
  1119. for udp_socket in sockets
  1120. .items_mut()
  1121. .filter_map(|i| udp::Socket::downcast_mut(&mut i.socket))
  1122. {
  1123. if udp_socket.accepts(self, &ip_repr, &udp_repr) {
  1124. udp_socket.process(self, meta, &ip_repr, &udp_repr, udp_payload);
  1125. return None;
  1126. }
  1127. }
  1128. #[cfg(feature = "socket-dns")]
  1129. for dns_socket in sockets
  1130. .items_mut()
  1131. .filter_map(|i| dns::Socket::downcast_mut(&mut i.socket))
  1132. {
  1133. if dns_socket.accepts(&ip_repr, &udp_repr) {
  1134. dns_socket.process(self, &ip_repr, &udp_repr, udp_payload);
  1135. return None;
  1136. }
  1137. }
  1138. // The packet wasn't handled by a socket, send an ICMP port unreachable packet.
  1139. match ip_repr {
  1140. #[cfg(feature = "proto-ipv4")]
  1141. IpRepr::Ipv4(_) if handled_by_raw_socket => None,
  1142. #[cfg(feature = "proto-ipv6")]
  1143. IpRepr::Ipv6(_) if handled_by_raw_socket => None,
  1144. #[cfg(feature = "proto-ipv4")]
  1145. IpRepr::Ipv4(ipv4_repr) => {
  1146. let payload_len =
  1147. icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU, ipv4_repr.buffer_len());
  1148. let icmpv4_reply_repr = Icmpv4Repr::DstUnreachable {
  1149. reason: Icmpv4DstUnreachable::PortUnreachable,
  1150. header: ipv4_repr,
  1151. data: &ip_payload[0..payload_len],
  1152. };
  1153. self.icmpv4_reply(ipv4_repr, icmpv4_reply_repr)
  1154. }
  1155. #[cfg(feature = "proto-ipv6")]
  1156. IpRepr::Ipv6(ipv6_repr) => {
  1157. let payload_len =
  1158. icmp_reply_payload_len(ip_payload.len(), IPV6_MIN_MTU, ipv6_repr.buffer_len());
  1159. let icmpv6_reply_repr = Icmpv6Repr::DstUnreachable {
  1160. reason: Icmpv6DstUnreachable::PortUnreachable,
  1161. header: ipv6_repr,
  1162. data: &ip_payload[0..payload_len],
  1163. };
  1164. self.icmpv6_reply(ipv6_repr, icmpv6_reply_repr)
  1165. }
  1166. }
  1167. }
  1168. #[cfg(feature = "socket-tcp")]
  1169. pub(crate) fn process_tcp<'frame>(
  1170. &mut self,
  1171. sockets: &mut SocketSet,
  1172. ip_repr: IpRepr,
  1173. ip_payload: &'frame [u8],
  1174. ) -> Option<IpPacket<'frame>> {
  1175. let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
  1176. let tcp_packet = check!(TcpPacket::new_checked(ip_payload));
  1177. let tcp_repr = check!(TcpRepr::parse(
  1178. &tcp_packet,
  1179. &src_addr,
  1180. &dst_addr,
  1181. &self.caps.checksum
  1182. ));
  1183. for tcp_socket in sockets
  1184. .items_mut()
  1185. .filter_map(|i| tcp::Socket::downcast_mut(&mut i.socket))
  1186. {
  1187. if tcp_socket.accepts(self, &ip_repr, &tcp_repr) {
  1188. return tcp_socket
  1189. .process(self, &ip_repr, &tcp_repr)
  1190. .map(|(ip, tcp)| IpPacket::new(ip, IpPayload::Tcp(tcp)));
  1191. }
  1192. }
  1193. if tcp_repr.control == TcpControl::Rst {
  1194. // Never reply to a TCP RST packet with another TCP RST packet.
  1195. None
  1196. } else {
  1197. // The packet wasn't handled by a socket, send a TCP RST packet.
  1198. let (ip, tcp) = tcp::Socket::rst_reply(&ip_repr, &tcp_repr);
  1199. Some(IpPacket::new(ip, IpPayload::Tcp(tcp)))
  1200. }
  1201. }
  1202. #[cfg(feature = "medium-ethernet")]
  1203. fn dispatch<Tx>(
  1204. &mut self,
  1205. tx_token: Tx,
  1206. packet: EthernetPacket,
  1207. frag: &mut Fragmenter,
  1208. ) -> Result<(), DispatchError>
  1209. where
  1210. Tx: TxToken,
  1211. {
  1212. match packet {
  1213. #[cfg(feature = "proto-ipv4")]
  1214. EthernetPacket::Arp(arp_repr) => {
  1215. let dst_hardware_addr = match arp_repr {
  1216. ArpRepr::EthernetIpv4 {
  1217. target_hardware_addr,
  1218. ..
  1219. } => target_hardware_addr,
  1220. };
  1221. self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
  1222. frame.set_dst_addr(dst_hardware_addr);
  1223. frame.set_ethertype(EthernetProtocol::Arp);
  1224. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  1225. arp_repr.emit(&mut packet);
  1226. })
  1227. }
  1228. EthernetPacket::Ip(packet) => {
  1229. self.dispatch_ip(tx_token, PacketMeta::default(), packet, frag)
  1230. }
  1231. }
  1232. }
  1233. fn in_same_network(&self, addr: &IpAddress) -> bool {
  1234. self.ip_addrs.iter().any(|cidr| cidr.contains_addr(addr))
  1235. }
  1236. fn route(&self, addr: &IpAddress, timestamp: Instant) -> Option<IpAddress> {
  1237. // Send directly.
  1238. // note: no need to use `self.is_broadcast()` to check for subnet-local broadcast addrs
  1239. // here because `in_same_network` will already return true.
  1240. if self.in_same_network(addr) || addr.is_broadcast() {
  1241. return Some(*addr);
  1242. }
  1243. // Route via a router.
  1244. self.routes.lookup(addr, timestamp)
  1245. }
  1246. fn has_neighbor(&self, addr: &IpAddress) -> bool {
  1247. match self.route(addr, self.now) {
  1248. Some(_routed_addr) => match self.caps.medium {
  1249. #[cfg(feature = "medium-ethernet")]
  1250. Medium::Ethernet => self.neighbor_cache.lookup(&_routed_addr, self.now).found(),
  1251. #[cfg(feature = "medium-ieee802154")]
  1252. Medium::Ieee802154 => self.neighbor_cache.lookup(&_routed_addr, self.now).found(),
  1253. #[cfg(feature = "medium-ip")]
  1254. Medium::Ip => true,
  1255. },
  1256. None => false,
  1257. }
  1258. }
  1259. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  1260. fn lookup_hardware_addr<Tx>(
  1261. &mut self,
  1262. tx_token: Tx,
  1263. src_addr: &IpAddress,
  1264. dst_addr: &IpAddress,
  1265. fragmenter: &mut Fragmenter,
  1266. ) -> Result<(HardwareAddress, Tx), DispatchError>
  1267. where
  1268. Tx: TxToken,
  1269. {
  1270. if self.is_broadcast(dst_addr) {
  1271. let hardware_addr = match self.caps.medium {
  1272. #[cfg(feature = "medium-ethernet")]
  1273. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::BROADCAST),
  1274. #[cfg(feature = "medium-ieee802154")]
  1275. Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::BROADCAST),
  1276. #[cfg(feature = "medium-ip")]
  1277. Medium::Ip => unreachable!(),
  1278. };
  1279. return Ok((hardware_addr, tx_token));
  1280. }
  1281. if dst_addr.is_multicast() {
  1282. let b = dst_addr.as_bytes();
  1283. let hardware_addr = match *dst_addr {
  1284. #[cfg(feature = "proto-ipv4")]
  1285. IpAddress::Ipv4(_addr) => match self.caps.medium {
  1286. #[cfg(feature = "medium-ethernet")]
  1287. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  1288. 0x01,
  1289. 0x00,
  1290. 0x5e,
  1291. b[1] & 0x7F,
  1292. b[2],
  1293. b[3],
  1294. ])),
  1295. #[cfg(feature = "medium-ieee802154")]
  1296. Medium::Ieee802154 => unreachable!(),
  1297. #[cfg(feature = "medium-ip")]
  1298. Medium::Ip => unreachable!(),
  1299. },
  1300. #[cfg(feature = "proto-ipv6")]
  1301. IpAddress::Ipv6(_addr) => match self.caps.medium {
  1302. #[cfg(feature = "medium-ethernet")]
  1303. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  1304. 0x33, 0x33, b[12], b[13], b[14], b[15],
  1305. ])),
  1306. #[cfg(feature = "medium-ieee802154")]
  1307. Medium::Ieee802154 => {
  1308. // Not sure if this is correct
  1309. HardwareAddress::Ieee802154(Ieee802154Address::BROADCAST)
  1310. }
  1311. #[cfg(feature = "medium-ip")]
  1312. Medium::Ip => unreachable!(),
  1313. },
  1314. };
  1315. return Ok((hardware_addr, tx_token));
  1316. }
  1317. let dst_addr = self
  1318. .route(dst_addr, self.now)
  1319. .ok_or(DispatchError::NoRoute)?;
  1320. match self.neighbor_cache.lookup(&dst_addr, self.now) {
  1321. NeighborAnswer::Found(hardware_addr) => return Ok((hardware_addr, tx_token)),
  1322. NeighborAnswer::RateLimited => return Err(DispatchError::NeighborPending),
  1323. _ => (), // XXX
  1324. }
  1325. match (src_addr, dst_addr) {
  1326. #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
  1327. (&IpAddress::Ipv4(src_addr), IpAddress::Ipv4(dst_addr))
  1328. if matches!(self.caps.medium, Medium::Ethernet) =>
  1329. {
  1330. net_debug!(
  1331. "address {} not in neighbor cache, sending ARP request",
  1332. dst_addr
  1333. );
  1334. let src_hardware_addr = self.hardware_addr.ethernet_or_panic();
  1335. let arp_repr = ArpRepr::EthernetIpv4 {
  1336. operation: ArpOperation::Request,
  1337. source_hardware_addr: src_hardware_addr,
  1338. source_protocol_addr: src_addr,
  1339. target_hardware_addr: EthernetAddress::BROADCAST,
  1340. target_protocol_addr: dst_addr,
  1341. };
  1342. if let Err(e) =
  1343. self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
  1344. frame.set_dst_addr(EthernetAddress::BROADCAST);
  1345. frame.set_ethertype(EthernetProtocol::Arp);
  1346. arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
  1347. })
  1348. {
  1349. net_debug!("Failed to dispatch ARP request: {:?}", e);
  1350. return Err(DispatchError::NeighborPending);
  1351. }
  1352. }
  1353. #[cfg(feature = "proto-ipv6")]
  1354. (&IpAddress::Ipv6(src_addr), IpAddress::Ipv6(dst_addr)) => {
  1355. net_debug!(
  1356. "address {} not in neighbor cache, sending Neighbor Solicitation",
  1357. dst_addr
  1358. );
  1359. let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit {
  1360. target_addr: dst_addr,
  1361. lladdr: Some(self.hardware_addr.into()),
  1362. });
  1363. let packet = IpPacket::new_ipv6(
  1364. Ipv6Repr {
  1365. src_addr,
  1366. dst_addr: dst_addr.solicited_node(),
  1367. next_header: IpProtocol::Icmpv6,
  1368. payload_len: solicit.buffer_len(),
  1369. hop_limit: 0xff,
  1370. },
  1371. IpPayload::Icmpv6(solicit),
  1372. );
  1373. if let Err(e) =
  1374. self.dispatch_ip(tx_token, PacketMeta::default(), packet, fragmenter)
  1375. {
  1376. net_debug!("Failed to dispatch NDISC solicit: {:?}", e);
  1377. return Err(DispatchError::NeighborPending);
  1378. }
  1379. }
  1380. #[allow(unreachable_patterns)]
  1381. _ => (),
  1382. }
  1383. // The request got dispatched, limit the rate on the cache.
  1384. self.neighbor_cache.limit_rate(self.now);
  1385. Err(DispatchError::NeighborPending)
  1386. }
  1387. fn flush_cache(&mut self) {
  1388. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  1389. self.neighbor_cache.flush()
  1390. }
  1391. fn dispatch_ip<Tx: TxToken>(
  1392. &mut self,
  1393. // NOTE(unused_mut): tx_token isn't always mutated, depending on
  1394. // the feature set that is used.
  1395. #[allow(unused_mut)] mut tx_token: Tx,
  1396. meta: PacketMeta,
  1397. packet: IpPacket,
  1398. frag: &mut Fragmenter,
  1399. ) -> Result<(), DispatchError> {
  1400. let mut ip_repr = packet.ip_repr();
  1401. assert!(!ip_repr.dst_addr().is_unspecified());
  1402. // Dispatch IEEE802.15.4:
  1403. #[cfg(feature = "medium-ieee802154")]
  1404. if matches!(self.caps.medium, Medium::Ieee802154) {
  1405. let (addr, tx_token) = self.lookup_hardware_addr(
  1406. tx_token,
  1407. &ip_repr.src_addr(),
  1408. &ip_repr.dst_addr(),
  1409. frag,
  1410. )?;
  1411. let addr = addr.ieee802154_or_panic();
  1412. self.dispatch_ieee802154(addr, tx_token, meta, packet, frag);
  1413. return Ok(());
  1414. }
  1415. // Dispatch IP/Ethernet:
  1416. let caps = self.caps.clone();
  1417. #[cfg(feature = "proto-ipv4-fragmentation")]
  1418. let ipv4_id = self.get_ipv4_ident();
  1419. // First we calculate the total length that we will have to emit.
  1420. let mut total_len = ip_repr.buffer_len();
  1421. // Add the size of the Ethernet header if the medium is Ethernet.
  1422. #[cfg(feature = "medium-ethernet")]
  1423. if matches!(self.caps.medium, Medium::Ethernet) {
  1424. total_len = EthernetFrame::<&[u8]>::buffer_len(total_len);
  1425. }
  1426. // If the medium is Ethernet, then we need to retrieve the destination hardware address.
  1427. #[cfg(feature = "medium-ethernet")]
  1428. let (dst_hardware_addr, mut tx_token) = match self.caps.medium {
  1429. Medium::Ethernet => {
  1430. match self.lookup_hardware_addr(
  1431. tx_token,
  1432. &ip_repr.src_addr(),
  1433. &ip_repr.dst_addr(),
  1434. frag,
  1435. )? {
  1436. (HardwareAddress::Ethernet(addr), tx_token) => (addr, tx_token),
  1437. (_, _) => unreachable!(),
  1438. }
  1439. }
  1440. _ => (EthernetAddress([0; 6]), tx_token),
  1441. };
  1442. // Emit function for the Ethernet header.
  1443. #[cfg(feature = "medium-ethernet")]
  1444. let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| {
  1445. let mut frame = EthernetFrame::new_unchecked(tx_buffer);
  1446. let src_addr = self.hardware_addr.ethernet_or_panic();
  1447. frame.set_src_addr(src_addr);
  1448. frame.set_dst_addr(dst_hardware_addr);
  1449. match repr.version() {
  1450. #[cfg(feature = "proto-ipv4")]
  1451. IpVersion::Ipv4 => frame.set_ethertype(EthernetProtocol::Ipv4),
  1452. #[cfg(feature = "proto-ipv6")]
  1453. IpVersion::Ipv6 => frame.set_ethertype(EthernetProtocol::Ipv6),
  1454. }
  1455. Ok(())
  1456. };
  1457. // Emit function for the IP header and payload.
  1458. let emit_ip = |repr: &IpRepr, mut tx_buffer: &mut [u8]| {
  1459. repr.emit(&mut tx_buffer, &self.caps.checksum);
  1460. let payload = &mut tx_buffer[repr.header_len()..];
  1461. packet.emit_payload(repr, payload, &caps)
  1462. };
  1463. let total_ip_len = ip_repr.buffer_len();
  1464. match &mut ip_repr {
  1465. #[cfg(feature = "proto-ipv4")]
  1466. IpRepr::Ipv4(repr) => {
  1467. // If we have an IPv4 packet, then we need to check if we need to fragment it.
  1468. if total_ip_len > self.caps.max_transmission_unit {
  1469. #[cfg(feature = "proto-ipv4-fragmentation")]
  1470. {
  1471. net_debug!("start fragmentation");
  1472. // Calculate how much we will send now (including the Ethernet header).
  1473. let tx_len = self.caps.max_transmission_unit;
  1474. let ip_header_len = repr.buffer_len();
  1475. let first_frag_ip_len = self.caps.ip_mtu();
  1476. if frag.buffer.len() < total_ip_len {
  1477. net_debug!(
  1478. "Fragmentation buffer is too small, at least {} needed. Dropping",
  1479. total_ip_len
  1480. );
  1481. return Ok(());
  1482. }
  1483. #[cfg(feature = "medium-ethernet")]
  1484. {
  1485. frag.ipv4.dst_hardware_addr = dst_hardware_addr;
  1486. }
  1487. // Save the total packet len (without the Ethernet header, but with the first
  1488. // IP header).
  1489. frag.packet_len = total_ip_len;
  1490. // Save the IP header for other fragments.
  1491. frag.ipv4.repr = *repr;
  1492. // Save how much bytes we will send now.
  1493. frag.sent_bytes = first_frag_ip_len;
  1494. // Modify the IP header
  1495. repr.payload_len = first_frag_ip_len - repr.buffer_len();
  1496. // Emit the IP header to the buffer.
  1497. emit_ip(&ip_repr, &mut frag.buffer);
  1498. let mut ipv4_packet = Ipv4PacketWire::new_unchecked(&mut frag.buffer[..]);
  1499. frag.ipv4.ident = ipv4_id;
  1500. ipv4_packet.set_ident(ipv4_id);
  1501. ipv4_packet.set_more_frags(true);
  1502. ipv4_packet.set_dont_frag(false);
  1503. ipv4_packet.set_frag_offset(0);
  1504. if caps.checksum.ipv4.tx() {
  1505. ipv4_packet.fill_checksum();
  1506. }
  1507. // Transmit the first packet.
  1508. tx_token.consume(tx_len, |mut tx_buffer| {
  1509. #[cfg(feature = "medium-ethernet")]
  1510. if matches!(self.caps.medium, Medium::Ethernet) {
  1511. emit_ethernet(&ip_repr, tx_buffer)?;
  1512. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1513. }
  1514. // Change the offset for the next packet.
  1515. frag.ipv4.frag_offset = (first_frag_ip_len - ip_header_len) as u16;
  1516. // Copy the IP header and the payload.
  1517. tx_buffer[..first_frag_ip_len]
  1518. .copy_from_slice(&frag.buffer[..first_frag_ip_len]);
  1519. Ok(())
  1520. })
  1521. }
  1522. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  1523. {
  1524. net_debug!("Enable the `proto-ipv4-fragmentation` feature for fragmentation support.");
  1525. Ok(())
  1526. }
  1527. } else {
  1528. tx_token.set_meta(meta);
  1529. // No fragmentation is required.
  1530. tx_token.consume(total_len, |mut tx_buffer| {
  1531. #[cfg(feature = "medium-ethernet")]
  1532. if matches!(self.caps.medium, Medium::Ethernet) {
  1533. emit_ethernet(&ip_repr, tx_buffer)?;
  1534. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1535. }
  1536. emit_ip(&ip_repr, tx_buffer);
  1537. Ok(())
  1538. })
  1539. }
  1540. }
  1541. // We don't support IPv6 fragmentation yet.
  1542. #[cfg(feature = "proto-ipv6")]
  1543. IpRepr::Ipv6(_) => tx_token.consume(total_len, |mut tx_buffer| {
  1544. #[cfg(feature = "medium-ethernet")]
  1545. if matches!(self.caps.medium, Medium::Ethernet) {
  1546. emit_ethernet(&ip_repr, tx_buffer)?;
  1547. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1548. }
  1549. emit_ip(&ip_repr, tx_buffer);
  1550. Ok(())
  1551. }),
  1552. }
  1553. }
  1554. }
  1555. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  1556. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  1557. enum DispatchError {
  1558. /// No route to dispatch this packet. Retrying won't help unless
  1559. /// configuration is changed.
  1560. NoRoute,
  1561. /// We do have a route to dispatch this packet, but we haven't discovered
  1562. /// the neighbor for it yet. Discovery has been initiated, dispatch
  1563. /// should be retried later.
  1564. NeighborPending,
  1565. }