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