mod.rs 59 KB

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