mod.rs 67 KB

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