mod.rs 82 KB

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