mod.rs 64 KB

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