interface.rs 190 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105
  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. use core::cmp;
  5. use managed::{ManagedMap, ManagedSlice};
  6. #[cfg(any(feature = "proto-ipv4", feature = "proto-sixlowpan"))]
  7. use super::fragmentation::PacketAssemblerSet;
  8. use super::socket_set::SocketSet;
  9. use crate::iface::Routes;
  10. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  11. use crate::iface::{NeighborAnswer, NeighborCache};
  12. use crate::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
  13. use crate::rand::Rand;
  14. #[cfg(feature = "socket-dhcpv4")]
  15. use crate::socket::dhcpv4;
  16. #[cfg(feature = "socket-dns")]
  17. use crate::socket::dns;
  18. use crate::socket::*;
  19. use crate::time::{Duration, Instant};
  20. use crate::wire::*;
  21. use crate::{Error, Result};
  22. pub(crate) struct FragmentsBuffer<'a> {
  23. #[cfg(feature = "proto-ipv4-fragmentation")]
  24. ipv4_fragments: PacketAssemblerSet<'a, Ipv4FragKey>,
  25. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  26. sixlowpan_fragments: PacketAssemblerSet<'a, SixlowpanFragKey>,
  27. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  28. sixlowpan_fragments_cache_timeout: Duration,
  29. #[cfg(not(any(
  30. feature = "proto-ipv4-fragmentation",
  31. feature = "proto-sixlowpan-fragmentation"
  32. )))]
  33. _lifetime: core::marker::PhantomData<&'a ()>,
  34. }
  35. pub(crate) struct OutPackets<'a> {
  36. #[cfg(feature = "proto-ipv4-fragmentation")]
  37. ipv4_out_packet: Ipv4OutPacket<'a>,
  38. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  39. sixlowpan_out_packet: SixlowpanOutPacket<'a>,
  40. #[cfg(not(feature = "proto-sixlowpan-fragmentation"))]
  41. _lifetime: core::marker::PhantomData<&'a ()>,
  42. }
  43. impl<'a> OutPackets<'a> {
  44. #[cfg(any(
  45. feature = "proto-ipv4-fragmentation",
  46. feature = "proto-sixlowpan-fragmentation"
  47. ))]
  48. /// Returns `true` when all the data of the outgoing buffers are transmitted.
  49. fn all_transmitted(&self) -> bool {
  50. #[cfg(feature = "proto-ipv4-fragmentation")]
  51. if !self.ipv4_out_packet.is_empty() {
  52. return false;
  53. }
  54. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  55. if !self.sixlowpan_out_packet.is_empty() {
  56. return false;
  57. }
  58. true
  59. }
  60. }
  61. #[allow(unused)]
  62. #[cfg(feature = "proto-ipv4")]
  63. pub(crate) struct Ipv4OutPacket<'a> {
  64. /// The buffer that holds the unfragmented 6LoWPAN packet.
  65. buffer: ManagedSlice<'a, u8>,
  66. /// The size of the packet without the IEEE802.15.4 header and the fragmentation headers.
  67. packet_len: usize,
  68. /// The amount of bytes that already have been transmitted.
  69. sent_bytes: usize,
  70. /// The IPv4 representation.
  71. repr: Ipv4Repr,
  72. /// The destination hardware address.
  73. dst_hardware_addr: EthernetAddress,
  74. /// The offset of the next fragment.
  75. frag_offset: u16,
  76. /// The identifier of the stream.
  77. ident: u16,
  78. }
  79. #[cfg(feature = "proto-ipv4-fragmentation")]
  80. impl<'a> Ipv4OutPacket<'a> {
  81. pub(crate) fn new(buffer: ManagedSlice<'a, u8>) -> Self {
  82. Self {
  83. buffer,
  84. packet_len: 0,
  85. sent_bytes: 0,
  86. repr: Ipv4Repr {
  87. src_addr: Ipv4Address::default(),
  88. dst_addr: Ipv4Address::default(),
  89. next_header: IpProtocol::Unknown(0),
  90. payload_len: 0,
  91. hop_limit: 0,
  92. },
  93. dst_hardware_addr: EthernetAddress::default(),
  94. frag_offset: 0,
  95. ident: 0,
  96. }
  97. }
  98. /// Return `true` when everything is transmitted.
  99. #[inline]
  100. fn finished(&self) -> bool {
  101. self.packet_len == self.sent_bytes
  102. }
  103. /// Returns `true` when there is nothing to transmit.
  104. #[inline]
  105. fn is_empty(&self) -> bool {
  106. self.packet_len == 0
  107. }
  108. // Reset the buffer.
  109. fn reset(&mut self) {
  110. self.packet_len = 0;
  111. self.sent_bytes = 0;
  112. self.repr = Ipv4Repr {
  113. src_addr: Ipv4Address::default(),
  114. dst_addr: Ipv4Address::default(),
  115. next_header: IpProtocol::Unknown(0),
  116. payload_len: 0,
  117. hop_limit: 0,
  118. };
  119. self.dst_hardware_addr = EthernetAddress::default();
  120. }
  121. }
  122. #[allow(unused)]
  123. #[cfg(feature = "proto-sixlowpan")]
  124. pub(crate) struct SixlowpanOutPacket<'a> {
  125. /// The buffer that holds the unfragmented 6LoWPAN packet.
  126. buffer: ManagedSlice<'a, u8>,
  127. /// The size of the packet without the IEEE802.15.4 header and the fragmentation headers.
  128. packet_len: usize,
  129. /// The amount of bytes that already have been transmitted.
  130. sent_bytes: usize,
  131. /// The datagram size that is used for the fragmentation headers.
  132. datagram_size: u16,
  133. /// The datagram tag that is used for the fragmentation headers.
  134. datagram_tag: u16,
  135. datagram_offset: usize,
  136. /// The size of the FRAG_N packets.
  137. fragn_size: usize,
  138. /// The link layer IEEE802.15.4 source address.
  139. ll_dst_addr: Ieee802154Address,
  140. /// The link layer IEEE802.15.4 source address.
  141. ll_src_addr: Ieee802154Address,
  142. }
  143. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  144. impl<'a> SixlowpanOutPacket<'a> {
  145. pub(crate) fn new(buffer: ManagedSlice<'a, u8>) -> Self {
  146. Self {
  147. buffer,
  148. packet_len: 0,
  149. datagram_size: 0,
  150. datagram_tag: 0,
  151. datagram_offset: 0,
  152. sent_bytes: 0,
  153. fragn_size: 0,
  154. ll_dst_addr: Ieee802154Address::Absent,
  155. ll_src_addr: Ieee802154Address::Absent,
  156. }
  157. }
  158. /// Return `true` when everything is transmitted.
  159. #[inline]
  160. fn finished(&self) -> bool {
  161. self.packet_len == self.sent_bytes
  162. }
  163. /// Returns `true` when there is nothing to transmit.
  164. #[inline]
  165. fn is_empty(&self) -> bool {
  166. self.packet_len == 0
  167. }
  168. // Reset the buffer.
  169. fn reset(&mut self) {
  170. self.packet_len = 0;
  171. self.datagram_size = 0;
  172. self.datagram_tag = 0;
  173. self.sent_bytes = 0;
  174. self.fragn_size = 0;
  175. self.ll_dst_addr = Ieee802154Address::Absent;
  176. self.ll_src_addr = Ieee802154Address::Absent;
  177. }
  178. }
  179. macro_rules! check {
  180. ($e:expr) => {
  181. match $e {
  182. Ok(x) => x,
  183. Err(_) => {
  184. // concat!/stringify! doesn't work with defmt macros
  185. #[cfg(not(feature = "defmt"))]
  186. net_trace!(concat!("iface: malformed ", stringify!($e)));
  187. #[cfg(feature = "defmt")]
  188. net_trace!("iface: malformed");
  189. return Default::default();
  190. }
  191. }
  192. };
  193. }
  194. /// A network interface.
  195. ///
  196. /// The network interface logically owns a number of other data structures; to avoid
  197. /// a dependency on heap allocation, it instead owns a `BorrowMut<[T]>`, which can be
  198. /// a `&mut [T]`, or `Vec<T>` if a heap is available.
  199. pub struct Interface<'a> {
  200. inner: InterfaceInner<'a>,
  201. fragments: FragmentsBuffer<'a>,
  202. out_packets: OutPackets<'a>,
  203. }
  204. /// The device independent part of an Ethernet network interface.
  205. ///
  206. /// Separating the device from the data required for processing and dispatching makes
  207. /// it possible to borrow them independently. For example, the tx and rx tokens borrow
  208. /// the `device` mutably until they're used, which makes it impossible to call other
  209. /// methods on the `Interface` in this time (since its `device` field is borrowed
  210. /// exclusively). However, it is still possible to call methods on its `inner` field.
  211. pub struct InterfaceInner<'a> {
  212. caps: DeviceCapabilities,
  213. now: Instant,
  214. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  215. neighbor_cache: Option<NeighborCache<'a>>,
  216. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  217. hardware_addr: Option<HardwareAddress>,
  218. #[cfg(feature = "medium-ieee802154")]
  219. sequence_no: u8,
  220. #[cfg(feature = "medium-ieee802154")]
  221. pan_id: Option<Ieee802154Pan>,
  222. #[cfg(feature = "proto-ipv4-fragmentation")]
  223. ipv4_id: u16,
  224. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  225. tag: u16,
  226. ip_addrs: ManagedSlice<'a, IpCidr>,
  227. #[cfg(feature = "proto-ipv4")]
  228. any_ip: bool,
  229. routes: Routes<'a>,
  230. #[cfg(feature = "proto-igmp")]
  231. ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>,
  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. rand: Rand,
  236. }
  237. /// A builder structure used for creating a network interface.
  238. pub struct InterfaceBuilder<'a> {
  239. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  240. hardware_addr: Option<HardwareAddress>,
  241. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  242. neighbor_cache: Option<NeighborCache<'a>>,
  243. #[cfg(feature = "medium-ieee802154")]
  244. pan_id: Option<Ieee802154Pan>,
  245. ip_addrs: ManagedSlice<'a, IpCidr>,
  246. #[cfg(feature = "proto-ipv4")]
  247. any_ip: bool,
  248. routes: Routes<'a>,
  249. /// Does not share storage with `ipv6_multicast_groups` to avoid IPv6 size overhead.
  250. #[cfg(feature = "proto-igmp")]
  251. ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>,
  252. random_seed: u64,
  253. #[cfg(feature = "proto-ipv4-fragmentation")]
  254. ipv4_fragments: PacketAssemblerSet<'a, Ipv4FragKey>,
  255. #[cfg(feature = "proto-ipv4-fragmentation")]
  256. ipv4_out_buffer: ManagedSlice<'a, u8>,
  257. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  258. sixlowpan_fragments: PacketAssemblerSet<'a, SixlowpanFragKey>,
  259. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  260. sixlowpan_reassembly_buffer_timeout: Duration,
  261. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  262. sixlowpan_out_buffer: ManagedSlice<'a, u8>,
  263. }
  264. impl<'a> InterfaceBuilder<'a> {
  265. /// Create a builder used for creating a network interface using the
  266. /// given device and address.
  267. #[cfg_attr(
  268. all(feature = "medium-ethernet", not(feature = "proto-sixlowpan")),
  269. doc = r##"
  270. # Examples
  271. ```
  272. # use std::collections::BTreeMap;
  273. #[cfg(feature = "proto-ipv4-fragmentation")]
  274. use smoltcp::iface::FragmentsCache;
  275. use smoltcp::iface::{InterfaceBuilder, NeighborCache};
  276. # use smoltcp::phy::{Loopback, Medium};
  277. use smoltcp::wire::{EthernetAddress, IpCidr, IpAddress};
  278. let mut device = // ...
  279. # Loopback::new(Medium::Ethernet);
  280. let hw_addr = // ...
  281. # EthernetAddress::default();
  282. let neighbor_cache = // ...
  283. # NeighborCache::new(BTreeMap::new());
  284. # #[cfg(feature = "proto-ipv4-fragmentation")]
  285. # let ipv4_frag_cache = // ...
  286. # FragmentsCache::new(vec![], BTreeMap::new());
  287. let ip_addrs = // ...
  288. # [];
  289. let builder = InterfaceBuilder::new()
  290. .hardware_addr(hw_addr.into())
  291. .neighbor_cache(neighbor_cache)
  292. .ip_addrs(ip_addrs);
  293. # #[cfg(feature = "proto-ipv4-fragmentation")]
  294. let builder = builder
  295. .ipv4_reassembly_buffer(ipv4_frag_cache)
  296. .ipv4_fragmentation_buffer(vec![]);
  297. let iface = builder.finalize(&mut device);
  298. ```
  299. "##
  300. )]
  301. #[allow(clippy::new_without_default)]
  302. pub fn new() -> Self {
  303. InterfaceBuilder {
  304. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  305. hardware_addr: None,
  306. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  307. neighbor_cache: None,
  308. #[cfg(feature = "medium-ieee802154")]
  309. pan_id: None,
  310. ip_addrs: ManagedSlice::Borrowed(&mut []),
  311. #[cfg(feature = "proto-ipv4")]
  312. any_ip: false,
  313. routes: Routes::new(ManagedMap::Borrowed(&mut [])),
  314. #[cfg(feature = "proto-igmp")]
  315. ipv4_multicast_groups: ManagedMap::Borrowed(&mut []),
  316. random_seed: 0,
  317. #[cfg(feature = "proto-ipv4-fragmentation")]
  318. ipv4_fragments: PacketAssemblerSet::new(&mut [][..], &mut [][..]),
  319. #[cfg(feature = "proto-ipv4-fragmentation")]
  320. ipv4_out_buffer: ManagedSlice::Borrowed(&mut [][..]),
  321. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  322. sixlowpan_fragments: PacketAssemblerSet::new(&mut [][..], &mut [][..]),
  323. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  324. sixlowpan_reassembly_buffer_timeout: Duration::from_secs(60),
  325. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  326. sixlowpan_out_buffer: ManagedSlice::Borrowed(&mut [][..]),
  327. }
  328. }
  329. /// Set the random seed for this interface.
  330. ///
  331. /// It is strongly recommended that the random seed is different on each boot,
  332. /// to avoid problems with TCP port/sequence collisions.
  333. ///
  334. /// The seed doesn't have to be cryptographically secure.
  335. pub fn random_seed(mut self, random_seed: u64) -> Self {
  336. self.random_seed = random_seed;
  337. self
  338. }
  339. /// Set the Hardware address the interface will use. See also
  340. /// [hardware_addr].
  341. ///
  342. /// # Panics
  343. /// This function panics if the address is not unicast.
  344. ///
  345. /// [hardware_addr]: struct.Interface.html#method.hardware_addr
  346. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  347. pub fn hardware_addr(mut self, addr: HardwareAddress) -> Self {
  348. InterfaceInner::check_hardware_addr(&addr);
  349. self.hardware_addr = Some(addr);
  350. self
  351. }
  352. /// Set the IEEE802.15.4 PAN ID the interface will use.
  353. ///
  354. /// **NOTE**: we use the same PAN ID for destination and source.
  355. #[cfg(feature = "medium-ieee802154")]
  356. pub fn pan_id(mut self, pan_id: Ieee802154Pan) -> Self {
  357. self.pan_id = Some(pan_id);
  358. self
  359. }
  360. /// Set the IP addresses the interface will use. See also
  361. /// [ip_addrs].
  362. ///
  363. /// # Panics
  364. /// This function panics if any of the addresses are not unicast.
  365. ///
  366. /// [ip_addrs]: struct.Interface.html#method.ip_addrs
  367. pub fn ip_addrs<T>(mut self, ip_addrs: T) -> Self
  368. where
  369. T: Into<ManagedSlice<'a, IpCidr>>,
  370. {
  371. let ip_addrs = ip_addrs.into();
  372. InterfaceInner::check_ip_addrs(&ip_addrs);
  373. self.ip_addrs = ip_addrs;
  374. self
  375. }
  376. /// Enable or disable the AnyIP capability, allowing packets to be received
  377. /// locally on IPv4 addresses other than the interface's configured [ip_addrs].
  378. /// When AnyIP is enabled and a route prefix in [routes] specifies one of
  379. /// the interface's [ip_addrs] as its gateway, the interface will accept
  380. /// packets addressed to that prefix.
  381. ///
  382. /// # IPv6
  383. ///
  384. /// This option is not available or required for IPv6 as packets sent to
  385. /// the interface are not filtered by IPv6 address.
  386. ///
  387. /// [routes]: struct.Interface.html#method.routes
  388. /// [ip_addrs]: struct.Interface.html#method.ip_addrs
  389. #[cfg(feature = "proto-ipv4")]
  390. pub fn any_ip(mut self, enabled: bool) -> Self {
  391. self.any_ip = enabled;
  392. self
  393. }
  394. /// Set the IP routes the interface will use. See also
  395. /// [routes].
  396. ///
  397. /// [routes]: struct.Interface.html#method.routes
  398. pub fn routes<T>(mut self, routes: T) -> InterfaceBuilder<'a>
  399. where
  400. T: Into<Routes<'a>>,
  401. {
  402. self.routes = routes.into();
  403. self
  404. }
  405. /// Provide storage for multicast groups.
  406. ///
  407. /// Join multicast groups by calling [`join_multicast_group()`] on an `Interface`.
  408. /// Using [`join_multicast_group()`] will send initial membership reports.
  409. ///
  410. /// A previously destroyed interface can be recreated by reusing the multicast group
  411. /// storage, i.e. providing a non-empty storage to `ipv4_multicast_groups()`.
  412. /// Note that this way initial membership reports are **not** sent.
  413. ///
  414. /// [`join_multicast_group()`]: struct.Interface.html#method.join_multicast_group
  415. #[cfg(feature = "proto-igmp")]
  416. pub fn ipv4_multicast_groups<T>(mut self, ipv4_multicast_groups: T) -> Self
  417. where
  418. T: Into<ManagedMap<'a, Ipv4Address, ()>>,
  419. {
  420. self.ipv4_multicast_groups = ipv4_multicast_groups.into();
  421. self
  422. }
  423. /// Set the Neighbor Cache the interface will use.
  424. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  425. pub fn neighbor_cache(mut self, neighbor_cache: NeighborCache<'a>) -> Self {
  426. self.neighbor_cache = Some(neighbor_cache);
  427. self
  428. }
  429. #[cfg(feature = "proto-ipv4-fragmentation")]
  430. pub fn ipv4_reassembly_buffer(mut self, storage: PacketAssemblerSet<'a, Ipv4FragKey>) -> Self {
  431. self.ipv4_fragments = storage;
  432. self
  433. }
  434. #[cfg(feature = "proto-ipv4-fragmentation")]
  435. pub fn ipv4_fragmentation_buffer<T>(mut self, storage: T) -> Self
  436. where
  437. T: Into<ManagedSlice<'a, u8>>,
  438. {
  439. self.ipv4_out_buffer = storage.into();
  440. self
  441. }
  442. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  443. pub fn sixlowpan_reassembly_buffer(
  444. mut self,
  445. storage: PacketAssemblerSet<'a, SixlowpanFragKey>,
  446. ) -> Self {
  447. self.sixlowpan_fragments = storage;
  448. self
  449. }
  450. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  451. pub fn sixlowpan_reassembly_buffer_timeout(mut self, timeout: Duration) -> Self {
  452. if timeout > Duration::from_secs(60) {
  453. net_debug!("RFC 4944 specifies that the reassembly timeout MUST be set to a maximum of 60 seconds");
  454. }
  455. self.sixlowpan_reassembly_buffer_timeout = timeout;
  456. self
  457. }
  458. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  459. pub fn sixlowpan_fragmentation_buffer<T>(mut self, storage: T) -> Self
  460. where
  461. T: Into<ManagedSlice<'a, u8>>,
  462. {
  463. self.sixlowpan_out_buffer = storage.into();
  464. self
  465. }
  466. /// Create a network interface using the previously provided configuration.
  467. ///
  468. /// # Panics
  469. /// If a required option is not provided, this function will panic. Required
  470. /// options are:
  471. ///
  472. /// - [ethernet_addr]
  473. /// - [neighbor_cache]
  474. ///
  475. /// [ethernet_addr]: #method.ethernet_addr
  476. /// [neighbor_cache]: #method.neighbor_cache
  477. pub fn finalize<D>(self, device: &mut D) -> Interface<'a>
  478. where
  479. D: for<'d> Device<'d> + ?Sized,
  480. {
  481. let caps = device.capabilities();
  482. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  483. let (hardware_addr, neighbor_cache) = match caps.medium {
  484. #[cfg(feature = "medium-ethernet")]
  485. Medium::Ethernet => (
  486. Some(
  487. self.hardware_addr
  488. .expect("hardware_addr required option was not set"),
  489. ),
  490. Some(
  491. self.neighbor_cache
  492. .expect("neighbor_cache required option was not set"),
  493. ),
  494. ),
  495. #[cfg(feature = "medium-ip")]
  496. Medium::Ip => {
  497. assert!(
  498. self.hardware_addr.is_none(),
  499. "hardware_addr is set, but device medium is IP"
  500. );
  501. assert!(
  502. self.neighbor_cache.is_none(),
  503. "neighbor_cache is set, but device medium is IP"
  504. );
  505. (None, None)
  506. }
  507. #[cfg(feature = "medium-ieee802154")]
  508. Medium::Ieee802154 => (
  509. Some(
  510. self.hardware_addr
  511. .expect("hardware_addr required option was not set"),
  512. ),
  513. Some(
  514. self.neighbor_cache
  515. .expect("neighbor_cache required option was not set"),
  516. ),
  517. ),
  518. };
  519. let mut rand = Rand::new(self.random_seed);
  520. #[cfg(feature = "medium-ieee802154")]
  521. let mut sequence_no;
  522. #[cfg(feature = "medium-ieee802154")]
  523. loop {
  524. sequence_no = (rand.rand_u32() & 0xff) as u8;
  525. if sequence_no != 0 {
  526. break;
  527. }
  528. }
  529. #[cfg(feature = "proto-sixlowpan")]
  530. let mut tag;
  531. #[cfg(feature = "proto-sixlowpan")]
  532. loop {
  533. tag = rand.rand_u16();
  534. if tag != 0 {
  535. break;
  536. }
  537. }
  538. #[cfg(feature = "proto-ipv4")]
  539. let mut ipv4_id;
  540. #[cfg(feature = "proto-ipv4")]
  541. loop {
  542. ipv4_id = rand.rand_u16();
  543. if ipv4_id != 0 {
  544. break;
  545. }
  546. }
  547. Interface {
  548. fragments: FragmentsBuffer {
  549. #[cfg(feature = "proto-ipv4-fragmentation")]
  550. ipv4_fragments: self.ipv4_fragments,
  551. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  552. sixlowpan_fragments: self.sixlowpan_fragments,
  553. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  554. sixlowpan_fragments_cache_timeout: self.sixlowpan_reassembly_buffer_timeout,
  555. #[cfg(not(any(
  556. feature = "proto-ipv4-fragmentation",
  557. feature = "proto-sixlowpan-fragmentation"
  558. )))]
  559. _lifetime: core::marker::PhantomData,
  560. },
  561. out_packets: OutPackets {
  562. #[cfg(feature = "proto-ipv4-fragmentation")]
  563. ipv4_out_packet: Ipv4OutPacket::new(self.ipv4_out_buffer),
  564. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  565. sixlowpan_out_packet: SixlowpanOutPacket::new(self.sixlowpan_out_buffer),
  566. #[cfg(not(feature = "proto-sixlowpan-fragmentation"))]
  567. _lifetime: core::marker::PhantomData,
  568. },
  569. inner: InterfaceInner {
  570. now: Instant::from_secs(0),
  571. caps,
  572. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  573. hardware_addr,
  574. ip_addrs: self.ip_addrs,
  575. #[cfg(feature = "proto-ipv4")]
  576. any_ip: self.any_ip,
  577. routes: self.routes,
  578. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  579. neighbor_cache,
  580. #[cfg(feature = "proto-igmp")]
  581. ipv4_multicast_groups: self.ipv4_multicast_groups,
  582. #[cfg(feature = "proto-igmp")]
  583. igmp_report_state: IgmpReportState::Inactive,
  584. #[cfg(feature = "medium-ieee802154")]
  585. sequence_no,
  586. #[cfg(feature = "medium-ieee802154")]
  587. pan_id: self.pan_id,
  588. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  589. tag,
  590. #[cfg(feature = "proto-ipv4-fragmentation")]
  591. ipv4_id,
  592. rand,
  593. },
  594. }
  595. }
  596. }
  597. #[derive(Debug, PartialEq)]
  598. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  599. #[cfg(feature = "medium-ethernet")]
  600. enum EthernetPacket<'a> {
  601. #[cfg(feature = "proto-ipv4")]
  602. Arp(ArpRepr),
  603. Ip(IpPacket<'a>),
  604. }
  605. #[derive(Debug, PartialEq)]
  606. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  607. pub(crate) enum IpPacket<'a> {
  608. #[cfg(feature = "proto-ipv4")]
  609. Icmpv4((Ipv4Repr, Icmpv4Repr<'a>)),
  610. #[cfg(feature = "proto-igmp")]
  611. Igmp((Ipv4Repr, IgmpRepr)),
  612. #[cfg(feature = "proto-ipv6")]
  613. Icmpv6((Ipv6Repr, Icmpv6Repr<'a>)),
  614. #[cfg(feature = "socket-raw")]
  615. Raw((IpRepr, &'a [u8])),
  616. #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
  617. Udp((IpRepr, UdpRepr, &'a [u8])),
  618. #[cfg(feature = "socket-tcp")]
  619. Tcp((IpRepr, TcpRepr<'a>)),
  620. #[cfg(feature = "socket-dhcpv4")]
  621. Dhcpv4((Ipv4Repr, UdpRepr, DhcpRepr<'a>)),
  622. }
  623. impl<'a> IpPacket<'a> {
  624. pub(crate) fn ip_repr(&self) -> IpRepr {
  625. match self {
  626. #[cfg(feature = "proto-ipv4")]
  627. IpPacket::Icmpv4((ipv4_repr, _)) => IpRepr::Ipv4(*ipv4_repr),
  628. #[cfg(feature = "proto-igmp")]
  629. IpPacket::Igmp((ipv4_repr, _)) => IpRepr::Ipv4(*ipv4_repr),
  630. #[cfg(feature = "proto-ipv6")]
  631. IpPacket::Icmpv6((ipv6_repr, _)) => IpRepr::Ipv6(*ipv6_repr),
  632. #[cfg(feature = "socket-raw")]
  633. IpPacket::Raw((ip_repr, _)) => ip_repr.clone(),
  634. #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
  635. IpPacket::Udp((ip_repr, _, _)) => ip_repr.clone(),
  636. #[cfg(feature = "socket-tcp")]
  637. IpPacket::Tcp((ip_repr, _)) => ip_repr.clone(),
  638. #[cfg(feature = "socket-dhcpv4")]
  639. IpPacket::Dhcpv4((ipv4_repr, _, _)) => IpRepr::Ipv4(*ipv4_repr),
  640. }
  641. }
  642. pub(crate) fn emit_payload(
  643. &self,
  644. _ip_repr: &IpRepr,
  645. payload: &mut [u8],
  646. caps: &DeviceCapabilities,
  647. ) {
  648. match self {
  649. #[cfg(feature = "proto-ipv4")]
  650. IpPacket::Icmpv4((_, icmpv4_repr)) => {
  651. icmpv4_repr.emit(&mut Icmpv4Packet::new_unchecked(payload), &caps.checksum)
  652. }
  653. #[cfg(feature = "proto-igmp")]
  654. IpPacket::Igmp((_, igmp_repr)) => {
  655. igmp_repr.emit(&mut IgmpPacket::new_unchecked(payload))
  656. }
  657. #[cfg(feature = "proto-ipv6")]
  658. IpPacket::Icmpv6((_, icmpv6_repr)) => icmpv6_repr.emit(
  659. &_ip_repr.src_addr(),
  660. &_ip_repr.dst_addr(),
  661. &mut Icmpv6Packet::new_unchecked(payload),
  662. &caps.checksum,
  663. ),
  664. #[cfg(feature = "socket-raw")]
  665. IpPacket::Raw((_, raw_packet)) => payload.copy_from_slice(raw_packet),
  666. #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
  667. IpPacket::Udp((_, udp_repr, inner_payload)) => udp_repr.emit(
  668. &mut UdpPacket::new_unchecked(payload),
  669. &_ip_repr.src_addr(),
  670. &_ip_repr.dst_addr(),
  671. inner_payload.len(),
  672. |buf| buf.copy_from_slice(inner_payload),
  673. &caps.checksum,
  674. ),
  675. #[cfg(feature = "socket-tcp")]
  676. IpPacket::Tcp((_, mut tcp_repr)) => {
  677. // This is a terrible hack to make TCP performance more acceptable on systems
  678. // where the TCP buffers are significantly larger than network buffers,
  679. // e.g. a 64 kB TCP receive buffer (and so, when empty, a 64k window)
  680. // together with four 1500 B Ethernet receive buffers. If left untreated,
  681. // this would result in our peer pushing our window and sever packet loss.
  682. //
  683. // I'm really not happy about this "solution" but I don't know what else to do.
  684. if let Some(max_burst_size) = caps.max_burst_size {
  685. let mut max_segment_size = caps.max_transmission_unit;
  686. max_segment_size -= _ip_repr.header_len();
  687. max_segment_size -= tcp_repr.header_len();
  688. let max_window_size = max_burst_size * max_segment_size;
  689. if tcp_repr.window_len as usize > max_window_size {
  690. tcp_repr.window_len = max_window_size as u16;
  691. }
  692. }
  693. tcp_repr.emit(
  694. &mut TcpPacket::new_unchecked(payload),
  695. &_ip_repr.src_addr(),
  696. &_ip_repr.dst_addr(),
  697. &caps.checksum,
  698. );
  699. }
  700. #[cfg(feature = "socket-dhcpv4")]
  701. IpPacket::Dhcpv4((_, udp_repr, dhcp_repr)) => udp_repr.emit(
  702. &mut UdpPacket::new_unchecked(payload),
  703. &_ip_repr.src_addr(),
  704. &_ip_repr.dst_addr(),
  705. dhcp_repr.buffer_len(),
  706. |buf| dhcp_repr.emit(&mut DhcpPacket::new_unchecked(buf)).unwrap(),
  707. &caps.checksum,
  708. ),
  709. }
  710. }
  711. }
  712. #[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
  713. fn icmp_reply_payload_len(len: usize, mtu: usize, header_len: usize) -> usize {
  714. // Send back as much of the original payload as will fit within
  715. // the minimum MTU required by IPv4. See RFC 1812 § 4.3.2.3 for
  716. // more details.
  717. //
  718. // Since the entire network layer packet must fit within the minimum
  719. // MTU supported, the payload must not exceed the following:
  720. //
  721. // <min mtu> - IP Header Size * 2 - ICMPv4 DstUnreachable hdr size
  722. cmp::min(len, mtu - header_len * 2 - 8)
  723. }
  724. #[cfg(feature = "proto-igmp")]
  725. enum IgmpReportState {
  726. Inactive,
  727. ToGeneralQuery {
  728. version: IgmpVersion,
  729. timeout: Instant,
  730. interval: Duration,
  731. next_index: usize,
  732. },
  733. ToSpecificQuery {
  734. version: IgmpVersion,
  735. timeout: Instant,
  736. group: Ipv4Address,
  737. },
  738. }
  739. impl<'a> Interface<'a> {
  740. /// Get the socket context.
  741. ///
  742. /// The context is needed for some socket methods.
  743. pub fn context(&mut self) -> &mut InterfaceInner<'a> {
  744. &mut self.inner
  745. }
  746. /// Get the HardwareAddress address of the interface.
  747. ///
  748. /// # Panics
  749. /// This function panics if the medium is not Ethernet or Ieee802154.
  750. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  751. pub fn hardware_addr(&self) -> HardwareAddress {
  752. #[cfg(all(feature = "medium-ethernet", not(feature = "medium-ieee802154")))]
  753. assert!(self.inner.caps.medium == Medium::Ethernet);
  754. #[cfg(all(feature = "medium-ieee802154", not(feature = "medium-ethernet")))]
  755. assert!(self.inner.caps.medium == Medium::Ieee802154);
  756. #[cfg(all(feature = "medium-ieee802154", feature = "medium-ethernet"))]
  757. assert!(
  758. self.inner.caps.medium == Medium::Ethernet
  759. || self.inner.caps.medium == Medium::Ieee802154
  760. );
  761. self.inner.hardware_addr.unwrap()
  762. }
  763. /// Set the HardwareAddress address of the interface.
  764. ///
  765. /// # Panics
  766. /// This function panics if the address is not unicast, and if the medium is not Ethernet or
  767. /// Ieee802154.
  768. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  769. pub fn set_hardware_addr(&mut self, addr: HardwareAddress) {
  770. #[cfg(all(feature = "medium-ethernet", not(feature = "medium-ieee802154")))]
  771. assert!(self.inner.caps.medium == Medium::Ethernet);
  772. #[cfg(all(feature = "medium-ieee802154", not(feature = "medium-ethernet")))]
  773. assert!(self.inner.caps.medium == Medium::Ieee802154);
  774. #[cfg(all(feature = "medium-ieee802154", feature = "medium-ethernet"))]
  775. assert!(
  776. self.inner.caps.medium == Medium::Ethernet
  777. || self.inner.caps.medium == Medium::Ieee802154
  778. );
  779. InterfaceInner::check_hardware_addr(&addr);
  780. self.inner.hardware_addr = Some(addr);
  781. }
  782. /// Add an address to a list of subscribed multicast IP addresses.
  783. ///
  784. /// Returns `Ok(announce_sent)` if the address was added successfully, where `annouce_sent`
  785. /// indicates whether an initial immediate announcement has been sent.
  786. pub fn join_multicast_group<D, T: Into<IpAddress>>(
  787. &mut self,
  788. device: &mut D,
  789. addr: T,
  790. timestamp: Instant,
  791. ) -> Result<bool>
  792. where
  793. D: for<'d> Device<'d> + ?Sized,
  794. {
  795. self.inner.now = timestamp;
  796. match addr.into() {
  797. #[cfg(feature = "proto-igmp")]
  798. IpAddress::Ipv4(addr) => {
  799. let is_not_new = self
  800. .inner
  801. .ipv4_multicast_groups
  802. .insert(addr, ())
  803. .map_err(|_| Error::Exhausted)?
  804. .is_some();
  805. if is_not_new {
  806. Ok(false)
  807. } else if let Some(pkt) = self.inner.igmp_report_packet(IgmpVersion::Version2, addr)
  808. {
  809. // Send initial membership report
  810. let tx_token = device.transmit().ok_or(Error::Exhausted)?;
  811. self.inner.dispatch_ip(tx_token, pkt, None)?;
  812. Ok(true)
  813. } else {
  814. Ok(false)
  815. }
  816. }
  817. // Multicast is not yet implemented for other address families
  818. #[allow(unreachable_patterns)]
  819. _ => Err(Error::Unaddressable),
  820. }
  821. }
  822. /// Remove an address from the subscribed multicast IP addresses.
  823. ///
  824. /// Returns `Ok(leave_sent)` if the address was removed successfully, where `leave_sent`
  825. /// indicates whether an immediate leave packet has been sent.
  826. pub fn leave_multicast_group<D, T: Into<IpAddress>>(
  827. &mut self,
  828. device: &mut D,
  829. addr: T,
  830. timestamp: Instant,
  831. ) -> Result<bool>
  832. where
  833. D: for<'d> Device<'d> + ?Sized,
  834. {
  835. self.inner.now = timestamp;
  836. match addr.into() {
  837. #[cfg(feature = "proto-igmp")]
  838. IpAddress::Ipv4(addr) => {
  839. let was_not_present = self.inner.ipv4_multicast_groups.remove(&addr).is_none();
  840. if was_not_present {
  841. Ok(false)
  842. } else if let Some(pkt) = self.inner.igmp_leave_packet(addr) {
  843. // Send group leave packet
  844. let tx_token = device.transmit().ok_or(Error::Exhausted)?;
  845. self.inner.dispatch_ip(tx_token, pkt, None)?;
  846. Ok(true)
  847. } else {
  848. Ok(false)
  849. }
  850. }
  851. // Multicast is not yet implemented for other address families
  852. #[allow(unreachable_patterns)]
  853. _ => Err(Error::Unaddressable),
  854. }
  855. }
  856. /// Check whether the interface listens to given destination multicast IP address.
  857. pub fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
  858. self.inner.has_multicast_group(addr)
  859. }
  860. /// Get the IP addresses of the interface.
  861. pub fn ip_addrs(&self) -> &[IpCidr] {
  862. self.inner.ip_addrs.as_ref()
  863. }
  864. /// Get the first IPv4 address if present.
  865. #[cfg(feature = "proto-ipv4")]
  866. pub fn ipv4_addr(&self) -> Option<Ipv4Address> {
  867. self.ip_addrs()
  868. .iter()
  869. .find_map(|cidr| match cidr.address() {
  870. IpAddress::Ipv4(addr) => Some(addr),
  871. #[allow(unreachable_patterns)]
  872. _ => None,
  873. })
  874. }
  875. /// Update the IP addresses of the interface.
  876. ///
  877. /// # Panics
  878. /// This function panics if any of the addresses are not unicast.
  879. pub fn update_ip_addrs<F: FnOnce(&mut ManagedSlice<'a, IpCidr>)>(&mut self, f: F) {
  880. f(&mut self.inner.ip_addrs);
  881. InterfaceInner::flush_cache(&mut self.inner);
  882. InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
  883. }
  884. /// Check whether the interface has the given IP address assigned.
  885. pub fn has_ip_addr<T: Into<IpAddress>>(&self, addr: T) -> bool {
  886. self.inner.has_ip_addr(addr)
  887. }
  888. /// Get the first IPv4 address of the interface.
  889. #[cfg(feature = "proto-ipv4")]
  890. pub fn ipv4_address(&self) -> Option<Ipv4Address> {
  891. self.inner.ipv4_address()
  892. }
  893. pub fn routes(&self) -> &Routes<'a> {
  894. &self.inner.routes
  895. }
  896. pub fn routes_mut(&mut self) -> &mut Routes<'a> {
  897. &mut self.inner.routes
  898. }
  899. /// Transmit packets queued in the given sockets, and receive packets queued
  900. /// in the device.
  901. ///
  902. /// This function returns a boolean value indicating whether any packets were
  903. /// processed or emitted, and thus, whether the readiness of any socket might
  904. /// have changed.
  905. ///
  906. /// # Errors
  907. /// This method will routinely return errors in response to normal network
  908. /// activity as well as certain boundary conditions such as buffer exhaustion.
  909. /// These errors are provided as an aid for troubleshooting, and are meant
  910. /// to be logged and ignored.
  911. ///
  912. /// As a special case, `Err(Error::Unrecognized)` is returned in response to
  913. /// packets containing any unsupported protocol, option, or form, which is
  914. /// a very common occurrence and on a production system it should not even
  915. /// be logged.
  916. pub fn poll<D>(
  917. &mut self,
  918. timestamp: Instant,
  919. device: &mut D,
  920. sockets: &mut SocketSet<'_>,
  921. ) -> Result<bool>
  922. where
  923. D: for<'d> Device<'d> + ?Sized,
  924. {
  925. self.inner.now = timestamp;
  926. #[cfg(feature = "proto-ipv4-fragmentation")]
  927. self.fragments
  928. .ipv4_fragments
  929. .remove_when(|frag| Ok(timestamp >= frag.expires_at()?))?;
  930. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  931. self.fragments
  932. .sixlowpan_fragments
  933. .remove_when(|frag| Ok(timestamp >= frag.expires_at()?))?;
  934. #[cfg(feature = "proto-ipv4-fragmentation")]
  935. match self.ipv4_egress(device) {
  936. Ok(true) => return Ok(true),
  937. Err(e) => {
  938. net_debug!("failed to transmit: {}", e);
  939. return Err(e);
  940. }
  941. _ => (),
  942. }
  943. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  944. match self.sixlowpan_egress(device) {
  945. Ok(true) => return Ok(true),
  946. Err(e) => {
  947. net_debug!("failed to transmit: {}", e);
  948. return Err(e);
  949. }
  950. _ => (),
  951. }
  952. let mut readiness_may_have_changed = false;
  953. loop {
  954. let processed_any = self.socket_ingress(device, sockets);
  955. let emitted_any = self.socket_egress(device, sockets);
  956. #[cfg(feature = "proto-igmp")]
  957. self.igmp_egress(device)?;
  958. if processed_any || emitted_any {
  959. readiness_may_have_changed = true;
  960. } else {
  961. break;
  962. }
  963. }
  964. Ok(readiness_may_have_changed)
  965. }
  966. /// Return a _soft deadline_ for calling [poll] the next time.
  967. /// The [Instant] returned is the time at which you should call [poll] next.
  968. /// It is harmless (but wastes energy) to call it before the [Instant], and
  969. /// potentially harmful (impacting quality of service) to call it after the
  970. /// [Instant]
  971. ///
  972. /// [poll]: #method.poll
  973. /// [Instant]: struct.Instant.html
  974. pub fn poll_at(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Instant> {
  975. self.inner.now = timestamp;
  976. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  977. if !self.out_packets.all_transmitted() {
  978. return Some(Instant::from_millis(0));
  979. }
  980. let inner = &mut self.inner;
  981. sockets
  982. .items()
  983. .filter_map(move |item| {
  984. let socket_poll_at = item.socket.poll_at(inner);
  985. match item
  986. .meta
  987. .poll_at(socket_poll_at, |ip_addr| inner.has_neighbor(&ip_addr))
  988. {
  989. PollAt::Ingress => None,
  990. PollAt::Time(instant) => Some(instant),
  991. PollAt::Now => Some(Instant::from_millis(0)),
  992. }
  993. })
  994. .min()
  995. }
  996. /// Return an _advisory wait time_ for calling [poll] the next time.
  997. /// The [Duration] returned is the time left to wait before calling [poll] next.
  998. /// It is harmless (but wastes energy) to call it before the [Duration] has passed,
  999. /// and potentially harmful (impacting quality of service) to call it after the
  1000. /// [Duration] has passed.
  1001. ///
  1002. /// [poll]: #method.poll
  1003. /// [Duration]: struct.Duration.html
  1004. pub fn poll_delay(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Duration> {
  1005. match self.poll_at(timestamp, sockets) {
  1006. Some(poll_at) if timestamp < poll_at => Some(poll_at - timestamp),
  1007. Some(_) => Some(Duration::from_millis(0)),
  1008. _ => None,
  1009. }
  1010. }
  1011. fn socket_ingress<D>(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool
  1012. where
  1013. D: for<'d> Device<'d> + ?Sized,
  1014. {
  1015. let mut processed_any = false;
  1016. let Self {
  1017. inner,
  1018. fragments: ref mut _fragments,
  1019. out_packets: _out_packets,
  1020. } = self;
  1021. while let Some((rx_token, tx_token)) = device.receive() {
  1022. let res = rx_token.consume(inner.now, |frame| {
  1023. match inner.caps.medium {
  1024. #[cfg(feature = "medium-ethernet")]
  1025. Medium::Ethernet => {
  1026. if let Some(packet) = inner.process_ethernet(sockets, &frame, _fragments) {
  1027. if let Err(err) = inner.dispatch(tx_token, packet, Some(_out_packets)) {
  1028. net_debug!("Failed to send response: {}", err);
  1029. }
  1030. }
  1031. }
  1032. #[cfg(feature = "medium-ip")]
  1033. Medium::Ip => {
  1034. if let Some(packet) = inner.process_ip(sockets, &frame, _fragments) {
  1035. if let Err(err) =
  1036. inner.dispatch_ip(tx_token, packet, Some(_out_packets))
  1037. {
  1038. net_debug!("Failed to send response: {}", err);
  1039. }
  1040. }
  1041. }
  1042. #[cfg(feature = "medium-ieee802154")]
  1043. Medium::Ieee802154 => {
  1044. if let Some(packet) = inner.process_ieee802154(sockets, &frame, _fragments)
  1045. {
  1046. if let Err(err) =
  1047. inner.dispatch_ip(tx_token, packet, Some(_out_packets))
  1048. {
  1049. net_debug!("Failed to send response: {}", err);
  1050. }
  1051. }
  1052. }
  1053. }
  1054. processed_any = true;
  1055. Ok(())
  1056. });
  1057. if let Err(err) = res {
  1058. net_debug!("Failed to consume RX token: {}", err);
  1059. }
  1060. }
  1061. processed_any
  1062. }
  1063. fn socket_egress<D>(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool
  1064. where
  1065. D: for<'d> Device<'d> + ?Sized,
  1066. {
  1067. let Self {
  1068. inner,
  1069. out_packets: _out_packets,
  1070. ..
  1071. } = self;
  1072. let _caps = device.capabilities();
  1073. let mut emitted_any = false;
  1074. for item in sockets.items_mut() {
  1075. if !item
  1076. .meta
  1077. .egress_permitted(inner.now, |ip_addr| inner.has_neighbor(&ip_addr))
  1078. {
  1079. continue;
  1080. }
  1081. let mut neighbor_addr = None;
  1082. let mut respond = |inner: &mut InterfaceInner, response: IpPacket| {
  1083. neighbor_addr = Some(response.ip_repr().dst_addr());
  1084. let t = device.transmit().ok_or_else(|| {
  1085. net_debug!("failed to transmit IP: {}", Error::Exhausted);
  1086. Error::Exhausted
  1087. })?;
  1088. #[cfg(any(
  1089. feature = "proto-ipv4-fragmentation",
  1090. feature = "proto-sixlowpan-fragmentation"
  1091. ))]
  1092. inner.dispatch_ip(t, response, Some(_out_packets))?;
  1093. #[cfg(not(any(
  1094. feature = "proto-ipv4-fragmentation",
  1095. feature = "proto-sixlowpan-fragmentation"
  1096. )))]
  1097. inner.dispatch_ip(t, response, None)?;
  1098. emitted_any = true;
  1099. Ok(())
  1100. };
  1101. let result = match &mut item.socket {
  1102. #[cfg(feature = "socket-raw")]
  1103. Socket::Raw(socket) => socket.dispatch(inner, |inner, response| {
  1104. respond(inner, IpPacket::Raw(response))
  1105. }),
  1106. #[cfg(feature = "socket-icmp")]
  1107. Socket::Icmp(socket) => socket.dispatch(inner, |inner, response| match response {
  1108. #[cfg(feature = "proto-ipv4")]
  1109. (IpRepr::Ipv4(ipv4_repr), IcmpRepr::Ipv4(icmpv4_repr)) => {
  1110. respond(inner, IpPacket::Icmpv4((ipv4_repr, icmpv4_repr)))
  1111. }
  1112. #[cfg(feature = "proto-ipv6")]
  1113. (IpRepr::Ipv6(ipv6_repr), IcmpRepr::Ipv6(icmpv6_repr)) => {
  1114. respond(inner, IpPacket::Icmpv6((ipv6_repr, icmpv6_repr)))
  1115. }
  1116. #[allow(unreachable_patterns)]
  1117. _ => unreachable!(),
  1118. }),
  1119. #[cfg(feature = "socket-udp")]
  1120. Socket::Udp(socket) => socket.dispatch(inner, |inner, response| {
  1121. respond(inner, IpPacket::Udp(response))
  1122. }),
  1123. #[cfg(feature = "socket-tcp")]
  1124. Socket::Tcp(socket) => socket.dispatch(inner, |inner, response| {
  1125. respond(inner, IpPacket::Tcp(response))
  1126. }),
  1127. #[cfg(feature = "socket-dhcpv4")]
  1128. Socket::Dhcpv4(socket) => socket.dispatch(inner, |inner, response| {
  1129. respond(inner, IpPacket::Dhcpv4(response))
  1130. }),
  1131. #[cfg(feature = "socket-dns")]
  1132. Socket::Dns(ref mut socket) => socket.dispatch(inner, |inner, response| {
  1133. respond(inner, IpPacket::Udp(response))
  1134. }),
  1135. };
  1136. match result {
  1137. Err(Error::Exhausted) => break, // Device buffer full.
  1138. Err(Error::Unaddressable) => {
  1139. // `NeighborCache` already takes care of rate limiting the neighbor discovery
  1140. // requests from the socket. However, without an additional rate limiting
  1141. // mechanism, we would spin on every socket that has yet to discover its
  1142. // neighbor.
  1143. item.meta.neighbor_missing(
  1144. inner.now,
  1145. neighbor_addr.expect("non-IP response packet"),
  1146. );
  1147. break;
  1148. }
  1149. Err(err) => {
  1150. net_debug!(
  1151. "{}: cannot dispatch egress packet: {}",
  1152. item.meta.handle,
  1153. err
  1154. );
  1155. }
  1156. Ok(()) => {}
  1157. }
  1158. }
  1159. emitted_any
  1160. }
  1161. /// Depending on `igmp_report_state` and the therein contained
  1162. /// timeouts, send IGMP membership reports.
  1163. #[cfg(feature = "proto-igmp")]
  1164. fn igmp_egress<D>(&mut self, device: &mut D) -> Result<bool>
  1165. where
  1166. D: for<'d> Device<'d> + ?Sized,
  1167. {
  1168. match self.inner.igmp_report_state {
  1169. IgmpReportState::ToSpecificQuery {
  1170. version,
  1171. timeout,
  1172. group,
  1173. } if self.inner.now >= timeout => {
  1174. if let Some(pkt) = self.inner.igmp_report_packet(version, group) {
  1175. // Send initial membership report
  1176. let tx_token = device.transmit().ok_or(Error::Exhausted)?;
  1177. self.inner.dispatch_ip(tx_token, pkt, None)?;
  1178. }
  1179. self.inner.igmp_report_state = IgmpReportState::Inactive;
  1180. Ok(true)
  1181. }
  1182. IgmpReportState::ToGeneralQuery {
  1183. version,
  1184. timeout,
  1185. interval,
  1186. next_index,
  1187. } if self.inner.now >= timeout => {
  1188. let addr = self
  1189. .inner
  1190. .ipv4_multicast_groups
  1191. .iter()
  1192. .nth(next_index)
  1193. .map(|(addr, ())| *addr);
  1194. match addr {
  1195. Some(addr) => {
  1196. if let Some(pkt) = self.inner.igmp_report_packet(version, addr) {
  1197. // Send initial membership report
  1198. let tx_token = device.transmit().ok_or(Error::Exhausted)?;
  1199. self.inner.dispatch_ip(tx_token, pkt, None)?;
  1200. }
  1201. let next_timeout = (timeout + interval).max(self.inner.now);
  1202. self.inner.igmp_report_state = IgmpReportState::ToGeneralQuery {
  1203. version,
  1204. timeout: next_timeout,
  1205. interval,
  1206. next_index: next_index + 1,
  1207. };
  1208. Ok(true)
  1209. }
  1210. None => {
  1211. self.inner.igmp_report_state = IgmpReportState::Inactive;
  1212. Ok(false)
  1213. }
  1214. }
  1215. }
  1216. _ => Ok(false),
  1217. }
  1218. }
  1219. /// Process fragments that still need to be sent for IPv4 packets.
  1220. ///
  1221. /// This function returns a boolean value indicating whether any packets were
  1222. /// processed or emitted, and thus, whether the readiness of any socket might
  1223. /// have changed.
  1224. #[cfg(feature = "proto-ipv4-fragmentation")]
  1225. fn ipv4_egress<D>(&mut self, device: &mut D) -> Result<bool>
  1226. where
  1227. D: for<'d> Device<'d> + ?Sized,
  1228. {
  1229. // Reset the buffer when we transmitted everything.
  1230. if self.out_packets.ipv4_out_packet.finished() {
  1231. self.out_packets.ipv4_out_packet.reset();
  1232. }
  1233. if self.out_packets.ipv4_out_packet.is_empty() {
  1234. return Ok(false);
  1235. }
  1236. let Ipv4OutPacket {
  1237. packet_len,
  1238. sent_bytes,
  1239. ..
  1240. } = &self.out_packets.ipv4_out_packet;
  1241. if *packet_len > *sent_bytes {
  1242. match device.transmit() {
  1243. Some(tx_token) => self
  1244. .inner
  1245. .dispatch_ipv4_out_packet(tx_token, &mut self.out_packets.ipv4_out_packet),
  1246. None => Err(Error::Exhausted),
  1247. }
  1248. .map(|_| true)
  1249. } else {
  1250. Ok(false)
  1251. }
  1252. }
  1253. /// Process fragments that still need to be sent for 6LoWPAN packets.
  1254. ///
  1255. /// This function returns a boolean value indicating whether any packets were
  1256. /// processed or emitted, and thus, whether the readiness of any socket might
  1257. /// have changed.
  1258. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  1259. fn sixlowpan_egress<D>(&mut self, device: &mut D) -> Result<bool>
  1260. where
  1261. D: for<'d> Device<'d> + ?Sized,
  1262. {
  1263. // Reset the buffer when we transmitted everything.
  1264. if self.out_packets.sixlowpan_out_packet.finished() {
  1265. self.out_packets.sixlowpan_out_packet.reset();
  1266. }
  1267. if self.out_packets.sixlowpan_out_packet.is_empty() {
  1268. return Ok(false);
  1269. }
  1270. let SixlowpanOutPacket {
  1271. packet_len,
  1272. sent_bytes,
  1273. ..
  1274. } = &self.out_packets.sixlowpan_out_packet;
  1275. if *packet_len > *sent_bytes {
  1276. match device.transmit() {
  1277. Some(tx_token) => self.inner.dispatch_ieee802154_out_packet(
  1278. tx_token,
  1279. &mut self.out_packets.sixlowpan_out_packet,
  1280. ),
  1281. None => Err(Error::Exhausted),
  1282. }
  1283. .map(|_| true)
  1284. } else {
  1285. Ok(false)
  1286. }
  1287. }
  1288. }
  1289. impl<'a> InterfaceInner<'a> {
  1290. #[allow(unused)] // unused depending on which sockets are enabled
  1291. pub(crate) fn now(&self) -> Instant {
  1292. self.now
  1293. }
  1294. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  1295. #[allow(unused)] // unused depending on which sockets are enabled
  1296. pub(crate) fn hardware_addr(&self) -> Option<HardwareAddress> {
  1297. self.hardware_addr
  1298. }
  1299. #[allow(unused)] // unused depending on which sockets are enabled
  1300. pub(crate) fn checksum_caps(&self) -> ChecksumCapabilities {
  1301. self.caps.checksum.clone()
  1302. }
  1303. #[allow(unused)] // unused depending on which sockets are enabled
  1304. pub(crate) fn ip_mtu(&self) -> usize {
  1305. self.caps.ip_mtu()
  1306. }
  1307. #[allow(unused)] // unused depending on which sockets are enabled, and in tests
  1308. pub(crate) fn rand(&mut self) -> &mut Rand {
  1309. &mut self.rand
  1310. }
  1311. #[allow(unused)] // unused depending on which sockets are enabled
  1312. pub(crate) fn get_source_address(&mut self, dst_addr: IpAddress) -> Option<IpAddress> {
  1313. let v = dst_addr.version();
  1314. for cidr in self.ip_addrs.iter() {
  1315. let addr = cidr.address();
  1316. if addr.version() == v {
  1317. return Some(addr);
  1318. }
  1319. }
  1320. None
  1321. }
  1322. #[cfg(feature = "proto-ipv4")]
  1323. #[allow(unused)]
  1324. pub(crate) fn get_source_address_ipv4(
  1325. &mut self,
  1326. _dst_addr: Ipv4Address,
  1327. ) -> Option<Ipv4Address> {
  1328. for cidr in self.ip_addrs.iter() {
  1329. #[allow(irrefutable_let_patterns)] // if only ipv4 is enabled
  1330. if let IpCidr::Ipv4(cidr) = cidr {
  1331. return Some(cidr.address());
  1332. }
  1333. }
  1334. None
  1335. }
  1336. #[cfg(feature = "proto-ipv6")]
  1337. #[allow(unused)]
  1338. pub(crate) fn get_source_address_ipv6(
  1339. &mut self,
  1340. _dst_addr: Ipv6Address,
  1341. ) -> Option<Ipv6Address> {
  1342. for cidr in self.ip_addrs.iter() {
  1343. #[allow(irrefutable_let_patterns)] // if only ipv6 is enabled
  1344. if let IpCidr::Ipv6(cidr) = cidr {
  1345. return Some(cidr.address());
  1346. }
  1347. }
  1348. None
  1349. }
  1350. #[cfg(test)]
  1351. pub(crate) fn mock() -> Self {
  1352. Self {
  1353. caps: DeviceCapabilities {
  1354. #[cfg(feature = "medium-ethernet")]
  1355. medium: crate::phy::Medium::Ethernet,
  1356. #[cfg(not(feature = "medium-ethernet"))]
  1357. medium: crate::phy::Medium::Ip,
  1358. checksum: crate::phy::ChecksumCapabilities {
  1359. #[cfg(feature = "proto-ipv4")]
  1360. icmpv4: crate::phy::Checksum::Both,
  1361. #[cfg(feature = "proto-ipv6")]
  1362. icmpv6: crate::phy::Checksum::Both,
  1363. ipv4: crate::phy::Checksum::Both,
  1364. tcp: crate::phy::Checksum::Both,
  1365. udp: crate::phy::Checksum::Both,
  1366. },
  1367. max_burst_size: None,
  1368. #[cfg(feature = "medium-ethernet")]
  1369. max_transmission_unit: 1514,
  1370. #[cfg(not(feature = "medium-ethernet"))]
  1371. max_transmission_unit: 1500,
  1372. },
  1373. now: Instant::from_millis_const(0),
  1374. ip_addrs: ManagedSlice::Owned(vec![
  1375. #[cfg(feature = "proto-ipv4")]
  1376. IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 1), 24)),
  1377. #[cfg(feature = "proto-ipv6")]
  1378. IpCidr::Ipv6(Ipv6Cidr::new(
  1379. Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
  1380. 64,
  1381. )),
  1382. ]),
  1383. rand: Rand::new(1234),
  1384. routes: Routes::new(&mut [][..]),
  1385. #[cfg(feature = "proto-ipv4")]
  1386. any_ip: false,
  1387. #[cfg(feature = "medium-ieee802154")]
  1388. pan_id: Some(crate::wire::Ieee802154Pan(0xabcd)),
  1389. #[cfg(feature = "medium-ieee802154")]
  1390. sequence_no: 1,
  1391. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  1392. tag: 1,
  1393. #[cfg(feature = "proto-ipv4-fragmentation")]
  1394. ipv4_id: 1,
  1395. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  1396. hardware_addr: Some(crate::wire::HardwareAddress::Ethernet(
  1397. crate::wire::EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]),
  1398. )),
  1399. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  1400. neighbor_cache: None,
  1401. #[cfg(feature = "proto-igmp")]
  1402. igmp_report_state: IgmpReportState::Inactive,
  1403. #[cfg(feature = "proto-igmp")]
  1404. ipv4_multicast_groups: ManagedMap::Borrowed(&mut []),
  1405. }
  1406. }
  1407. #[cfg(test)]
  1408. #[allow(unused)] // unused depending on which sockets are enabled
  1409. pub(crate) fn set_now(&mut self, now: Instant) {
  1410. self.now = now
  1411. }
  1412. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  1413. fn check_hardware_addr(addr: &HardwareAddress) {
  1414. if !addr.is_unicast() {
  1415. panic!("Ethernet address {} is not unicast", addr)
  1416. }
  1417. }
  1418. fn check_ip_addrs(addrs: &[IpCidr]) {
  1419. for cidr in addrs {
  1420. if !cidr.address().is_unicast() && !cidr.address().is_unspecified() {
  1421. panic!("IP address {} is not unicast", cidr.address())
  1422. }
  1423. }
  1424. }
  1425. #[cfg(feature = "medium-ieee802154")]
  1426. fn get_sequence_number(&mut self) -> u8 {
  1427. let no = self.sequence_no;
  1428. self.sequence_no = self.sequence_no.wrapping_add(1);
  1429. no
  1430. }
  1431. #[cfg(feature = "proto-ipv4-fragmentation")]
  1432. fn get_ipv4_ident(&mut self) -> u16 {
  1433. let ipv4_id = self.ipv4_id;
  1434. self.ipv4_id = self.ipv4_id.wrapping_add(1);
  1435. ipv4_id
  1436. }
  1437. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  1438. fn get_sixlowpan_fragment_tag(&mut self) -> u16 {
  1439. let tag = self.tag;
  1440. self.tag = self.tag.wrapping_add(1);
  1441. tag
  1442. }
  1443. /// Determine if the given `Ipv6Address` is the solicited node
  1444. /// multicast address for a IPv6 addresses assigned to the interface.
  1445. /// See [RFC 4291 § 2.7.1] for more details.
  1446. ///
  1447. /// [RFC 4291 § 2.7.1]: https://tools.ietf.org/html/rfc4291#section-2.7.1
  1448. #[cfg(feature = "proto-ipv6")]
  1449. pub fn has_solicited_node(&self, addr: Ipv6Address) -> bool {
  1450. self.ip_addrs.iter().any(|cidr| {
  1451. match *cidr {
  1452. IpCidr::Ipv6(cidr) if cidr.address() != Ipv6Address::LOOPBACK => {
  1453. // Take the lower order 24 bits of the IPv6 address and
  1454. // append those bits to FF02:0:0:0:0:1:FF00::/104.
  1455. addr.as_bytes()[14..] == cidr.address().as_bytes()[14..]
  1456. }
  1457. _ => false,
  1458. }
  1459. })
  1460. }
  1461. /// Check whether the interface has the given IP address assigned.
  1462. fn has_ip_addr<T: Into<IpAddress>>(&self, addr: T) -> bool {
  1463. let addr = addr.into();
  1464. self.ip_addrs.iter().any(|probe| probe.address() == addr)
  1465. }
  1466. /// Get the first IPv4 address of the interface.
  1467. #[cfg(feature = "proto-ipv4")]
  1468. pub fn ipv4_address(&self) -> Option<Ipv4Address> {
  1469. self.ip_addrs.iter().find_map(|addr| match *addr {
  1470. IpCidr::Ipv4(cidr) => Some(cidr.address()),
  1471. #[cfg(feature = "proto-ipv6")]
  1472. IpCidr::Ipv6(_) => None,
  1473. })
  1474. }
  1475. /// Check whether the interface listens to given destination multicast IP address.
  1476. ///
  1477. /// If built without feature `proto-igmp` this function will
  1478. /// always return `false`.
  1479. pub fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
  1480. match addr.into() {
  1481. #[cfg(feature = "proto-igmp")]
  1482. IpAddress::Ipv4(key) => {
  1483. key == Ipv4Address::MULTICAST_ALL_SYSTEMS
  1484. || self.ipv4_multicast_groups.get(&key).is_some()
  1485. }
  1486. #[allow(unreachable_patterns)]
  1487. _ => false,
  1488. }
  1489. }
  1490. #[cfg(feature = "medium-ethernet")]
  1491. fn process_ethernet<'frame, T: AsRef<[u8]>>(
  1492. &mut self,
  1493. sockets: &mut SocketSet,
  1494. frame: &'frame T,
  1495. _fragments: &'frame mut FragmentsBuffer<'a>,
  1496. ) -> Option<EthernetPacket<'frame>> {
  1497. let eth_frame = check!(EthernetFrame::new_checked(frame));
  1498. // Ignore any packets not directed to our hardware address or any of the multicast groups.
  1499. if !eth_frame.dst_addr().is_broadcast()
  1500. && !eth_frame.dst_addr().is_multicast()
  1501. && HardwareAddress::Ethernet(eth_frame.dst_addr()) != self.hardware_addr.unwrap()
  1502. {
  1503. return None;
  1504. }
  1505. match eth_frame.ethertype() {
  1506. #[cfg(feature = "proto-ipv4")]
  1507. EthernetProtocol::Arp => self.process_arp(self.now, &eth_frame),
  1508. #[cfg(feature = "proto-ipv4")]
  1509. EthernetProtocol::Ipv4 => {
  1510. let ipv4_packet = check!(Ipv4Packet::new_checked(eth_frame.payload()));
  1511. cfg_if::cfg_if! {
  1512. if #[cfg(feature = "proto-ipv4-fragmentation")] {
  1513. self.process_ipv4(sockets, &ipv4_packet, Some(&mut _fragments.ipv4_fragments))
  1514. .map(EthernetPacket::Ip) } else {
  1515. self.process_ipv4(sockets, &ipv4_packet, None).map(EthernetPacket::Ip)
  1516. }
  1517. }
  1518. }
  1519. #[cfg(feature = "proto-ipv6")]
  1520. EthernetProtocol::Ipv6 => {
  1521. let ipv6_packet = check!(Ipv6Packet::new_checked(eth_frame.payload()));
  1522. self.process_ipv6(sockets, &ipv6_packet)
  1523. .map(EthernetPacket::Ip)
  1524. }
  1525. // Drop all other traffic.
  1526. _ => None,
  1527. }
  1528. }
  1529. #[cfg(feature = "medium-ip")]
  1530. fn process_ip<'frame, T: AsRef<[u8]>>(
  1531. &mut self,
  1532. sockets: &mut SocketSet,
  1533. ip_payload: &'frame T,
  1534. _fragments: &'frame mut FragmentsBuffer<'a>,
  1535. ) -> Option<IpPacket<'frame>> {
  1536. match IpVersion::of_packet(ip_payload.as_ref()) {
  1537. #[cfg(feature = "proto-ipv4")]
  1538. Ok(IpVersion::Ipv4) => {
  1539. let ipv4_packet = check!(Ipv4Packet::new_checked(ip_payload));
  1540. cfg_if::cfg_if! {
  1541. if #[cfg(feature = "proto-ipv4-fragmentation")] {
  1542. self.process_ipv4(sockets, &ipv4_packet, Some(&mut _fragments.ipv4_fragments))
  1543. } else {
  1544. self.process_ipv4(sockets, &ipv4_packet, None)
  1545. }
  1546. }
  1547. }
  1548. #[cfg(feature = "proto-ipv6")]
  1549. Ok(IpVersion::Ipv6) => {
  1550. let ipv6_packet = check!(Ipv6Packet::new_checked(ip_payload));
  1551. self.process_ipv6(sockets, &ipv6_packet)
  1552. }
  1553. // Drop all other traffic.
  1554. _ => None,
  1555. }
  1556. }
  1557. #[cfg(feature = "medium-ieee802154")]
  1558. fn process_ieee802154<'output, 'payload: 'output, T: AsRef<[u8]> + ?Sized>(
  1559. &mut self,
  1560. sockets: &mut SocketSet,
  1561. sixlowpan_payload: &'payload T,
  1562. _fragments: &'output mut FragmentsBuffer<'a>,
  1563. ) -> Option<IpPacket<'output>> {
  1564. let ieee802154_frame = check!(Ieee802154Frame::new_checked(sixlowpan_payload));
  1565. let ieee802154_repr = check!(Ieee802154Repr::parse(&ieee802154_frame));
  1566. if ieee802154_repr.frame_type != Ieee802154FrameType::Data {
  1567. return None;
  1568. }
  1569. // Drop frames when the user has set a PAN id and the PAN id from frame is not equal to this
  1570. // When the user didn't set a PAN id (so it is None), then we accept all PAN id's.
  1571. // We always accept the broadcast PAN id.
  1572. if self.pan_id.is_some()
  1573. && ieee802154_repr.dst_pan_id != self.pan_id
  1574. && ieee802154_repr.dst_pan_id != Some(Ieee802154Pan::BROADCAST)
  1575. {
  1576. net_debug!(
  1577. "IEEE802.15.4: dropping {:?} because not our PAN id (or not broadcast)",
  1578. ieee802154_repr
  1579. );
  1580. return None;
  1581. }
  1582. match ieee802154_frame.payload() {
  1583. Some(payload) => {
  1584. cfg_if::cfg_if! {
  1585. if #[cfg(feature = "proto-sixlowpan-fragmentation")] {
  1586. self.process_sixlowpan(sockets, &ieee802154_repr, payload, Some((&mut _fragments.sixlowpan_fragments, _fragments.sixlowpan_fragments_cache_timeout)))
  1587. } else {
  1588. self.process_sixlowpan(sockets, &ieee802154_repr, payload, None)
  1589. }
  1590. }
  1591. }
  1592. None => None,
  1593. }
  1594. }
  1595. #[cfg(feature = "proto-sixlowpan")]
  1596. fn process_sixlowpan<'output, 'payload: 'output, T: AsRef<[u8]> + ?Sized>(
  1597. &mut self,
  1598. sockets: &mut SocketSet,
  1599. ieee802154_repr: &Ieee802154Repr,
  1600. payload: &'payload T,
  1601. _fragments: Option<(
  1602. &'output mut PacketAssemblerSet<'a, SixlowpanFragKey>,
  1603. Duration,
  1604. )>,
  1605. ) -> Option<IpPacket<'output>> {
  1606. let payload = match check!(SixlowpanPacket::dispatch(payload)) {
  1607. #[cfg(not(feature = "proto-sixlowpan-fragmentation"))]
  1608. SixlowpanPacket::FragmentHeader => {
  1609. net_debug!("Fragmentation is not supported, use the `proto-sixlowpan-fragmentation` feature to add support.");
  1610. return None;
  1611. }
  1612. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  1613. SixlowpanPacket::FragmentHeader => {
  1614. let (fragments, timeout) = _fragments.unwrap();
  1615. // We have a fragment header, which means we cannot process the 6LoWPAN packet,
  1616. // unless we have a complete one after processing this fragment.
  1617. let frag = check!(SixlowpanFragPacket::new_checked(payload));
  1618. // The key specifies to which 6LoWPAN fragment it belongs too.
  1619. // It is based on the link layer addresses, the tag and the size.
  1620. let key = frag.get_key(ieee802154_repr);
  1621. // The offset of this fragment in increments of 8 octets.
  1622. let offset = frag.datagram_offset() as usize * 8;
  1623. if frag.is_first_fragment() {
  1624. // The first fragment contains the total size of the IPv6 packet.
  1625. // However, we received a packet that is compressed following the 6LoWPAN
  1626. // standard. This means we need to convert the IPv6 packet size to a 6LoWPAN
  1627. // packet size. The packet size can be different because of first the
  1628. // compression of the IP header and when UDP is used (because the UDP header
  1629. // can also be compressed). Other headers are not compressed by 6LoWPAN.
  1630. let iphc = check!(SixlowpanIphcPacket::new_checked(frag.payload()));
  1631. let iphc_repr = check!(SixlowpanIphcRepr::parse(
  1632. &iphc,
  1633. ieee802154_repr.src_addr,
  1634. ieee802154_repr.dst_addr,
  1635. ));
  1636. // The uncompressed header size always starts with 40, since this is the size
  1637. // of a IPv6 header.
  1638. let mut uncompressed_header_size = 40;
  1639. let mut compressed_header_size = iphc.header_len();
  1640. // We need to check if we have an UDP packet, since this header can also be
  1641. // compressed by 6LoWPAN. We currently don't support extension headers yet.
  1642. match iphc_repr.next_header {
  1643. SixlowpanNextHeader::Compressed => {
  1644. match check!(SixlowpanNhcPacket::dispatch(iphc.payload())) {
  1645. SixlowpanNhcPacket::ExtHeader => {
  1646. net_debug!("6LoWPAN: extension headers not supported");
  1647. return None;
  1648. }
  1649. SixlowpanNhcPacket::UdpHeader => {
  1650. let udp_packet =
  1651. check!(SixlowpanUdpNhcPacket::new_checked(iphc.payload()));
  1652. uncompressed_header_size += 8;
  1653. compressed_header_size +=
  1654. 1 + udp_packet.ports_size() + udp_packet.checksum_size();
  1655. }
  1656. }
  1657. }
  1658. SixlowpanNextHeader::Uncompressed(_) => (),
  1659. }
  1660. // We reserve a spot in the packet assembler set and add the required
  1661. // information to the packet assembler.
  1662. // This information is the total size of the packet when it is fully assmbled.
  1663. // We also pass the header size, since this is needed when other fragments
  1664. // (other than the first one) are added.
  1665. let frag_slot = match fragments.reserve_with_key(&key) {
  1666. Ok(frag) => frag,
  1667. Err(Error::PacketAssemblerSetFull) => {
  1668. net_debug!("No available packet assembler for fragmented packet");
  1669. return Default::default();
  1670. }
  1671. e => check!(e),
  1672. };
  1673. check!(frag_slot.start(
  1674. Some(
  1675. frag.datagram_size() as usize - uncompressed_header_size
  1676. + compressed_header_size
  1677. ),
  1678. self.now + timeout,
  1679. -((uncompressed_header_size - compressed_header_size) as isize),
  1680. ));
  1681. }
  1682. let frags = check!(fragments.get_packet_assembler_mut(&key));
  1683. net_trace!("6LoWPAN: received packet fragment");
  1684. // Add the fragment to the packet assembler.
  1685. match frags.add(frag.payload(), offset) {
  1686. Ok(true) => {
  1687. net_trace!("6LoWPAN: fragmented packet now complete");
  1688. check!(fragments.get_assembled_packet(&key))
  1689. }
  1690. Ok(false) => {
  1691. return None;
  1692. }
  1693. Err(Error::PacketAssemblerOverlap) => {
  1694. net_trace!("6LoWPAN: overlap in packet");
  1695. frags.mark_discarded();
  1696. return None;
  1697. }
  1698. Err(_) => return None,
  1699. }
  1700. }
  1701. SixlowpanPacket::IphcHeader => payload.as_ref(),
  1702. };
  1703. // At this point we should have a valid 6LoWPAN packet.
  1704. // The first header needs to be an IPHC header.
  1705. let iphc_packet = check!(SixlowpanIphcPacket::new_checked(payload));
  1706. let iphc_repr = check!(SixlowpanIphcRepr::parse(
  1707. &iphc_packet,
  1708. ieee802154_repr.src_addr,
  1709. ieee802154_repr.dst_addr,
  1710. ));
  1711. let payload = iphc_packet.payload();
  1712. let mut ipv6_repr = Ipv6Repr {
  1713. src_addr: iphc_repr.src_addr,
  1714. dst_addr: iphc_repr.dst_addr,
  1715. hop_limit: iphc_repr.hop_limit,
  1716. next_header: IpProtocol::Unknown(0),
  1717. payload_len: 40,
  1718. };
  1719. match iphc_repr.next_header {
  1720. SixlowpanNextHeader::Compressed => {
  1721. match check!(SixlowpanNhcPacket::dispatch(payload)) {
  1722. SixlowpanNhcPacket::ExtHeader => {
  1723. net_debug!("Extension headers are currently not supported for 6LoWPAN");
  1724. None
  1725. }
  1726. #[cfg(not(feature = "socket-udp"))]
  1727. SixlowpanNhcPacket::UdpHeader => {
  1728. net_debug!("UDP support is disabled, enable cargo feature `socket-udp`.");
  1729. None
  1730. }
  1731. #[cfg(feature = "socket-udp")]
  1732. SixlowpanNhcPacket::UdpHeader => {
  1733. let udp_packet = check!(SixlowpanUdpNhcPacket::new_checked(payload));
  1734. ipv6_repr.next_header = IpProtocol::Udp;
  1735. ipv6_repr.payload_len += 8 + udp_packet.payload().len();
  1736. let udp_repr = check!(SixlowpanUdpNhcRepr::parse(
  1737. &udp_packet,
  1738. &iphc_repr.src_addr,
  1739. &iphc_repr.dst_addr,
  1740. ));
  1741. // Look for UDP sockets that will accept the UDP packet.
  1742. // If it does not accept the packet, then send an ICMP message.
  1743. //
  1744. // NOTE(thvdveld): this is currently the same code as in self.process_udp.
  1745. // However, we cannot use that one because the payload passed to it is a
  1746. // normal IPv6 UDP payload, which is not what we have here.
  1747. for udp_socket in sockets
  1748. .items_mut()
  1749. .filter_map(|i| udp::Socket::downcast_mut(&mut i.socket))
  1750. {
  1751. if udp_socket.accepts(self, &IpRepr::Ipv6(ipv6_repr), &udp_repr) {
  1752. udp_socket.process(
  1753. self,
  1754. &IpRepr::Ipv6(ipv6_repr),
  1755. &udp_repr,
  1756. udp_packet.payload(),
  1757. );
  1758. return None;
  1759. }
  1760. }
  1761. #[cfg(feature = "socket-dns")]
  1762. for dns_socket in sockets
  1763. .items_mut()
  1764. .filter_map(|i| dns::Socket::downcast_mut(&mut i.socket))
  1765. {
  1766. if dns_socket.accepts(&IpRepr::Ipv6(ipv6_repr), &udp_repr) {
  1767. dns_socket.process(
  1768. self,
  1769. &IpRepr::Ipv6(ipv6_repr),
  1770. &udp_repr,
  1771. udp_packet.payload(),
  1772. );
  1773. return None;
  1774. }
  1775. }
  1776. // When we are here then then there was no UDP socket that accepted the UDP
  1777. // message.
  1778. let payload_len = icmp_reply_payload_len(
  1779. payload.len(),
  1780. IPV6_MIN_MTU,
  1781. ipv6_repr.buffer_len(),
  1782. );
  1783. let icmpv6_reply_repr = Icmpv6Repr::DstUnreachable {
  1784. reason: Icmpv6DstUnreachable::PortUnreachable,
  1785. header: ipv6_repr,
  1786. data: &payload[0..payload_len],
  1787. };
  1788. self.icmpv6_reply(ipv6_repr, icmpv6_reply_repr)
  1789. }
  1790. }
  1791. }
  1792. SixlowpanNextHeader::Uncompressed(nxt_hdr) => match nxt_hdr {
  1793. IpProtocol::Icmpv6 => {
  1794. ipv6_repr.next_header = IpProtocol::Icmpv6;
  1795. self.process_icmpv6(sockets, IpRepr::Ipv6(ipv6_repr), iphc_packet.payload())
  1796. }
  1797. #[cfg(feature = "socket-tcp")]
  1798. IpProtocol::Tcp => {
  1799. ipv6_repr.next_header = nxt_hdr;
  1800. ipv6_repr.payload_len += payload.len();
  1801. self.process_tcp(sockets, IpRepr::Ipv6(ipv6_repr), iphc_packet.payload())
  1802. }
  1803. proto => {
  1804. net_debug!("6LoWPAN: {} currently not supported", proto);
  1805. None
  1806. }
  1807. },
  1808. }
  1809. }
  1810. #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
  1811. fn process_arp<'frame, T: AsRef<[u8]>>(
  1812. &mut self,
  1813. timestamp: Instant,
  1814. eth_frame: &EthernetFrame<&'frame T>,
  1815. ) -> Option<EthernetPacket<'frame>> {
  1816. let arp_packet = check!(ArpPacket::new_checked(eth_frame.payload()));
  1817. let arp_repr = check!(ArpRepr::parse(&arp_packet));
  1818. match arp_repr {
  1819. ArpRepr::EthernetIpv4 {
  1820. operation,
  1821. source_hardware_addr,
  1822. source_protocol_addr,
  1823. target_protocol_addr,
  1824. ..
  1825. } => {
  1826. // Only process ARP packets for us.
  1827. if !self.has_ip_addr(target_protocol_addr) {
  1828. return None;
  1829. }
  1830. // Only process REQUEST and RESPONSE.
  1831. if let ArpOperation::Unknown(_) = operation {
  1832. net_debug!("arp: unknown operation code");
  1833. return None;
  1834. }
  1835. // Discard packets with non-unicast source addresses.
  1836. if !source_protocol_addr.is_unicast() || !source_hardware_addr.is_unicast() {
  1837. net_debug!("arp: non-unicast source address");
  1838. return None;
  1839. }
  1840. if !self.in_same_network(&IpAddress::Ipv4(source_protocol_addr)) {
  1841. net_debug!("arp: source IP address not in same network as us");
  1842. return None;
  1843. }
  1844. // Fill the ARP cache from any ARP packet aimed at us (both request or response).
  1845. // We fill from requests too because if someone is requesting our address they
  1846. // are probably going to talk to us, so we avoid having to request their address
  1847. // when we later reply to them.
  1848. self.neighbor_cache.as_mut().unwrap().fill(
  1849. source_protocol_addr.into(),
  1850. source_hardware_addr.into(),
  1851. timestamp,
  1852. );
  1853. if operation == ArpOperation::Request {
  1854. let src_hardware_addr = match self.hardware_addr {
  1855. Some(HardwareAddress::Ethernet(addr)) => addr,
  1856. _ => unreachable!(),
  1857. };
  1858. Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 {
  1859. operation: ArpOperation::Reply,
  1860. source_hardware_addr: src_hardware_addr,
  1861. source_protocol_addr: target_protocol_addr,
  1862. target_hardware_addr: source_hardware_addr,
  1863. target_protocol_addr: source_protocol_addr,
  1864. }))
  1865. } else {
  1866. None
  1867. }
  1868. }
  1869. }
  1870. }
  1871. #[cfg(feature = "socket-raw")]
  1872. fn raw_socket_filter<'frame>(
  1873. &mut self,
  1874. sockets: &mut SocketSet,
  1875. ip_repr: &IpRepr,
  1876. ip_payload: &'frame [u8],
  1877. ) -> bool {
  1878. let mut handled_by_raw_socket = false;
  1879. // Pass every IP packet to all raw sockets we have registered.
  1880. for raw_socket in sockets
  1881. .items_mut()
  1882. .filter_map(|i| raw::Socket::downcast_mut(&mut i.socket))
  1883. {
  1884. if raw_socket.accepts(ip_repr) {
  1885. raw_socket.process(self, ip_repr, ip_payload);
  1886. handled_by_raw_socket = true;
  1887. }
  1888. }
  1889. handled_by_raw_socket
  1890. }
  1891. #[cfg(feature = "proto-ipv6")]
  1892. fn process_ipv6<'frame, T: AsRef<[u8]> + ?Sized>(
  1893. &mut self,
  1894. sockets: &mut SocketSet,
  1895. ipv6_packet: &Ipv6Packet<&'frame T>,
  1896. ) -> Option<IpPacket<'frame>> {
  1897. let ipv6_repr = check!(Ipv6Repr::parse(ipv6_packet));
  1898. if !ipv6_repr.src_addr.is_unicast() {
  1899. // Discard packets with non-unicast source addresses.
  1900. net_debug!("non-unicast source address");
  1901. return None;
  1902. }
  1903. let ip_payload = ipv6_packet.payload();
  1904. #[cfg(feature = "socket-raw")]
  1905. let handled_by_raw_socket = self.raw_socket_filter(sockets, &ipv6_repr.into(), ip_payload);
  1906. #[cfg(not(feature = "socket-raw"))]
  1907. let handled_by_raw_socket = false;
  1908. self.process_nxt_hdr(
  1909. sockets,
  1910. ipv6_repr,
  1911. ipv6_repr.next_header,
  1912. handled_by_raw_socket,
  1913. ip_payload,
  1914. )
  1915. }
  1916. /// Given the next header value forward the payload onto the correct process
  1917. /// function.
  1918. #[cfg(feature = "proto-ipv6")]
  1919. fn process_nxt_hdr<'frame>(
  1920. &mut self,
  1921. sockets: &mut SocketSet,
  1922. ipv6_repr: Ipv6Repr,
  1923. nxt_hdr: IpProtocol,
  1924. handled_by_raw_socket: bool,
  1925. ip_payload: &'frame [u8],
  1926. ) -> Option<IpPacket<'frame>> {
  1927. match nxt_hdr {
  1928. IpProtocol::Icmpv6 => self.process_icmpv6(sockets, ipv6_repr.into(), ip_payload),
  1929. #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
  1930. IpProtocol::Udp => {
  1931. self.process_udp(sockets, ipv6_repr.into(), handled_by_raw_socket, ip_payload)
  1932. }
  1933. #[cfg(feature = "socket-tcp")]
  1934. IpProtocol::Tcp => self.process_tcp(sockets, ipv6_repr.into(), ip_payload),
  1935. IpProtocol::HopByHop => {
  1936. self.process_hopbyhop(sockets, ipv6_repr, handled_by_raw_socket, ip_payload)
  1937. }
  1938. #[cfg(feature = "socket-raw")]
  1939. _ if handled_by_raw_socket => None,
  1940. _ => {
  1941. // Send back as much of the original payload as we can.
  1942. let payload_len =
  1943. icmp_reply_payload_len(ip_payload.len(), IPV6_MIN_MTU, ipv6_repr.buffer_len());
  1944. let icmp_reply_repr = Icmpv6Repr::ParamProblem {
  1945. reason: Icmpv6ParamProblem::UnrecognizedNxtHdr,
  1946. // The offending packet is after the IPv6 header.
  1947. pointer: ipv6_repr.buffer_len() as u32,
  1948. header: ipv6_repr,
  1949. data: &ip_payload[0..payload_len],
  1950. };
  1951. self.icmpv6_reply(ipv6_repr, icmp_reply_repr)
  1952. }
  1953. }
  1954. }
  1955. #[cfg(feature = "proto-ipv4")]
  1956. fn process_ipv4<'output, 'payload: 'output, T: AsRef<[u8]> + ?Sized>(
  1957. &mut self,
  1958. sockets: &mut SocketSet,
  1959. ipv4_packet: &Ipv4Packet<&'payload T>,
  1960. _fragments: Option<&'output mut PacketAssemblerSet<'a, Ipv4FragKey>>,
  1961. ) -> Option<IpPacket<'output>> {
  1962. let ipv4_repr = check!(Ipv4Repr::parse(ipv4_packet, &self.caps.checksum));
  1963. if !self.is_unicast_v4(ipv4_repr.src_addr) {
  1964. // Discard packets with non-unicast source addresses.
  1965. net_debug!("non-unicast source address");
  1966. return None;
  1967. }
  1968. #[cfg(feature = "proto-ipv4-fragmentation")]
  1969. let ip_payload = {
  1970. const REASSEMBLY_TIMEOUT: u64 = 90;
  1971. let fragments = _fragments.unwrap();
  1972. if ipv4_packet.more_frags() || ipv4_packet.frag_offset() != 0 {
  1973. let key = ipv4_packet.get_key();
  1974. let f = match fragments.get_packet_assembler_mut(&key) {
  1975. Ok(f) => f,
  1976. Err(_) => {
  1977. let p = match fragments.reserve_with_key(&key) {
  1978. Ok(p) => p,
  1979. Err(Error::PacketAssemblerSetFull) => {
  1980. net_debug!("No available packet assembler for fragmented packet");
  1981. return Default::default();
  1982. }
  1983. e => check!(e),
  1984. };
  1985. check!(p.start(
  1986. None,
  1987. self.now + Duration::from_secs(REASSEMBLY_TIMEOUT),
  1988. 0
  1989. ));
  1990. check!(fragments.get_packet_assembler_mut(&key))
  1991. }
  1992. };
  1993. if !ipv4_packet.more_frags() {
  1994. // This is the last fragment, so we know the total size
  1995. check!(f.set_total_size(
  1996. ipv4_packet.total_len() as usize - ipv4_packet.header_len() as usize
  1997. + ipv4_packet.frag_offset() as usize,
  1998. ));
  1999. }
  2000. match f.add(ipv4_packet.payload(), ipv4_packet.frag_offset() as usize) {
  2001. Ok(true) => {
  2002. // NOTE: according to the standard, the total length needs to be
  2003. // recomputed, as well as the checksum. However, we don't really use
  2004. // the IPv4 header after the packet is reassembled.
  2005. check!(fragments.get_assembled_packet(&key))
  2006. }
  2007. Ok(false) => {
  2008. return None;
  2009. }
  2010. Err(Error::PacketAssemblerOverlap) => {
  2011. return None;
  2012. }
  2013. Err(e) => {
  2014. net_debug!("fragmentation error: {}", e);
  2015. return None;
  2016. }
  2017. }
  2018. } else {
  2019. ipv4_packet.payload()
  2020. }
  2021. };
  2022. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  2023. let ip_payload = ipv4_packet.payload();
  2024. let ip_repr = IpRepr::Ipv4(ipv4_repr);
  2025. #[cfg(feature = "socket-raw")]
  2026. let handled_by_raw_socket = self.raw_socket_filter(sockets, &ip_repr, ip_payload);
  2027. #[cfg(not(feature = "socket-raw"))]
  2028. let handled_by_raw_socket = false;
  2029. #[cfg(feature = "socket-dhcpv4")]
  2030. {
  2031. if ipv4_repr.next_header == IpProtocol::Udp && self.hardware_addr.is_some() {
  2032. // First check for source and dest ports, then do `UdpRepr::parse` if they match.
  2033. // This way we avoid validating the UDP checksum twice for all non-DHCP UDP packets (one here, one in `process_udp`)
  2034. let udp_packet = check!(UdpPacket::new_checked(ip_payload));
  2035. if udp_packet.src_port() == DHCP_SERVER_PORT
  2036. && udp_packet.dst_port() == DHCP_CLIENT_PORT
  2037. {
  2038. if let Some(dhcp_socket) = sockets
  2039. .items_mut()
  2040. .find_map(|i| dhcpv4::Socket::downcast_mut(&mut i.socket))
  2041. {
  2042. let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
  2043. let udp_repr = check!(UdpRepr::parse(
  2044. &udp_packet,
  2045. &src_addr,
  2046. &dst_addr,
  2047. &self.caps.checksum
  2048. ));
  2049. let udp_payload = udp_packet.payload();
  2050. dhcp_socket.process(self, &ipv4_repr, &udp_repr, udp_payload);
  2051. return None;
  2052. }
  2053. }
  2054. }
  2055. }
  2056. if !self.has_ip_addr(ipv4_repr.dst_addr)
  2057. && !self.has_multicast_group(ipv4_repr.dst_addr)
  2058. && !self.is_broadcast_v4(ipv4_repr.dst_addr)
  2059. {
  2060. // Ignore IP packets not directed at us, or broadcast, or any of the multicast groups.
  2061. // If AnyIP is enabled, also check if the packet is routed locally.
  2062. if !self.any_ip
  2063. || !ipv4_repr.dst_addr.is_unicast()
  2064. || self
  2065. .routes
  2066. .lookup(&IpAddress::Ipv4(ipv4_repr.dst_addr), self.now)
  2067. .map_or(true, |router_addr| !self.has_ip_addr(router_addr))
  2068. {
  2069. return None;
  2070. }
  2071. }
  2072. match ipv4_repr.next_header {
  2073. IpProtocol::Icmp => self.process_icmpv4(sockets, ip_repr, ip_payload),
  2074. #[cfg(feature = "proto-igmp")]
  2075. IpProtocol::Igmp => self.process_igmp(ipv4_repr, ip_payload),
  2076. #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
  2077. IpProtocol::Udp => {
  2078. self.process_udp(sockets, ip_repr, handled_by_raw_socket, ip_payload)
  2079. }
  2080. #[cfg(feature = "socket-tcp")]
  2081. IpProtocol::Tcp => self.process_tcp(sockets, ip_repr, ip_payload),
  2082. _ if handled_by_raw_socket => None,
  2083. _ => {
  2084. // Send back as much of the original payload as we can.
  2085. let payload_len =
  2086. icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU, ipv4_repr.buffer_len());
  2087. let icmp_reply_repr = Icmpv4Repr::DstUnreachable {
  2088. reason: Icmpv4DstUnreachable::ProtoUnreachable,
  2089. header: ipv4_repr,
  2090. data: &ip_payload[0..payload_len],
  2091. };
  2092. self.icmpv4_reply(ipv4_repr, icmp_reply_repr)
  2093. }
  2094. }
  2095. }
  2096. /// Checks if an incoming packet has a broadcast address for the interfaces
  2097. /// associated ipv4 addresses.
  2098. #[cfg(feature = "proto-ipv4")]
  2099. fn is_subnet_broadcast(&self, address: Ipv4Address) -> bool {
  2100. self.ip_addrs
  2101. .iter()
  2102. .filter_map(|own_cidr| match own_cidr {
  2103. IpCidr::Ipv4(own_ip) => Some(own_ip.broadcast()?),
  2104. #[cfg(feature = "proto-ipv6")]
  2105. IpCidr::Ipv6(_) => None,
  2106. })
  2107. .any(|broadcast_address| address == broadcast_address)
  2108. }
  2109. /// Checks if an ipv4 address is broadcast, taking into account subnet broadcast addresses
  2110. #[cfg(feature = "proto-ipv4")]
  2111. fn is_broadcast_v4(&self, address: Ipv4Address) -> bool {
  2112. address.is_broadcast() || self.is_subnet_broadcast(address)
  2113. }
  2114. /// Checks if an ipv4 address is unicast, taking into account subnet broadcast addresses
  2115. #[cfg(feature = "proto-ipv4")]
  2116. fn is_unicast_v4(&self, address: Ipv4Address) -> bool {
  2117. address.is_unicast() && !self.is_subnet_broadcast(address)
  2118. }
  2119. /// Host duties of the **IGMPv2** protocol.
  2120. ///
  2121. /// Sets up `igmp_report_state` for responding to IGMP general/specific membership queries.
  2122. /// Membership must not be reported immediately in order to avoid flooding the network
  2123. /// after a query is broadcasted by a router; this is not currently done.
  2124. #[cfg(feature = "proto-igmp")]
  2125. fn process_igmp<'frame>(
  2126. &mut self,
  2127. ipv4_repr: Ipv4Repr,
  2128. ip_payload: &'frame [u8],
  2129. ) -> Option<IpPacket<'frame>> {
  2130. let igmp_packet = check!(IgmpPacket::new_checked(ip_payload));
  2131. let igmp_repr = check!(IgmpRepr::parse(&igmp_packet));
  2132. // FIXME: report membership after a delay
  2133. match igmp_repr {
  2134. IgmpRepr::MembershipQuery {
  2135. group_addr,
  2136. version,
  2137. max_resp_time,
  2138. } => {
  2139. // General query
  2140. if group_addr.is_unspecified()
  2141. && ipv4_repr.dst_addr == Ipv4Address::MULTICAST_ALL_SYSTEMS
  2142. {
  2143. // Are we member in any groups?
  2144. if self.ipv4_multicast_groups.iter().next().is_some() {
  2145. let interval = match version {
  2146. IgmpVersion::Version1 => Duration::from_millis(100),
  2147. IgmpVersion::Version2 => {
  2148. // No dependence on a random generator
  2149. // (see [#24](https://github.com/m-labs/smoltcp/issues/24))
  2150. // but at least spread reports evenly across max_resp_time.
  2151. let intervals = self.ipv4_multicast_groups.len() as u32 + 1;
  2152. max_resp_time / intervals
  2153. }
  2154. };
  2155. self.igmp_report_state = IgmpReportState::ToGeneralQuery {
  2156. version,
  2157. timeout: self.now + interval,
  2158. interval,
  2159. next_index: 0,
  2160. };
  2161. }
  2162. } else {
  2163. // Group-specific query
  2164. if self.has_multicast_group(group_addr) && ipv4_repr.dst_addr == group_addr {
  2165. // Don't respond immediately
  2166. let timeout = max_resp_time / 4;
  2167. self.igmp_report_state = IgmpReportState::ToSpecificQuery {
  2168. version,
  2169. timeout: self.now + timeout,
  2170. group: group_addr,
  2171. };
  2172. }
  2173. }
  2174. }
  2175. // Ignore membership reports
  2176. IgmpRepr::MembershipReport { .. } => (),
  2177. // Ignore hosts leaving groups
  2178. IgmpRepr::LeaveGroup { .. } => (),
  2179. }
  2180. None
  2181. }
  2182. #[cfg(feature = "proto-ipv6")]
  2183. fn process_icmpv6<'frame>(
  2184. &mut self,
  2185. _sockets: &mut SocketSet,
  2186. ip_repr: IpRepr,
  2187. ip_payload: &'frame [u8],
  2188. ) -> Option<IpPacket<'frame>> {
  2189. let icmp_packet = check!(Icmpv6Packet::new_checked(ip_payload));
  2190. let icmp_repr = check!(Icmpv6Repr::parse(
  2191. &ip_repr.src_addr(),
  2192. &ip_repr.dst_addr(),
  2193. &icmp_packet,
  2194. &self.caps.checksum,
  2195. ));
  2196. #[cfg(feature = "socket-icmp")]
  2197. let mut handled_by_icmp_socket = false;
  2198. #[cfg(all(feature = "socket-icmp", feature = "proto-ipv6"))]
  2199. for icmp_socket in _sockets
  2200. .items_mut()
  2201. .filter_map(|i| icmp::Socket::downcast_mut(&mut i.socket))
  2202. {
  2203. if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) {
  2204. icmp_socket.process(self, &ip_repr, &icmp_repr.into());
  2205. handled_by_icmp_socket = true;
  2206. }
  2207. }
  2208. match icmp_repr {
  2209. // Respond to echo requests.
  2210. Icmpv6Repr::EchoRequest {
  2211. ident,
  2212. seq_no,
  2213. data,
  2214. } => match ip_repr {
  2215. IpRepr::Ipv6(ipv6_repr) => {
  2216. let icmp_reply_repr = Icmpv6Repr::EchoReply {
  2217. ident,
  2218. seq_no,
  2219. data,
  2220. };
  2221. self.icmpv6_reply(ipv6_repr, icmp_reply_repr)
  2222. }
  2223. #[allow(unreachable_patterns)]
  2224. _ => unreachable!(),
  2225. },
  2226. // Ignore any echo replies.
  2227. Icmpv6Repr::EchoReply { .. } => None,
  2228. // Forward any NDISC packets to the ndisc packet handler
  2229. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  2230. Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit() == 0xff => match ip_repr {
  2231. IpRepr::Ipv6(ipv6_repr) => self.process_ndisc(ipv6_repr, repr),
  2232. #[allow(unreachable_patterns)]
  2233. _ => unreachable!(),
  2234. },
  2235. // Don't report an error if a packet with unknown type
  2236. // has been handled by an ICMP socket
  2237. #[cfg(feature = "socket-icmp")]
  2238. _ if handled_by_icmp_socket => None,
  2239. // FIXME: do something correct here?
  2240. _ => None,
  2241. }
  2242. }
  2243. #[cfg(all(
  2244. any(feature = "medium-ethernet", feature = "medium-ieee802154"),
  2245. feature = "proto-ipv6"
  2246. ))]
  2247. fn process_ndisc<'frame>(
  2248. &mut self,
  2249. ip_repr: Ipv6Repr,
  2250. repr: NdiscRepr<'frame>,
  2251. ) -> Option<IpPacket<'frame>> {
  2252. match repr {
  2253. NdiscRepr::NeighborAdvert {
  2254. lladdr,
  2255. target_addr,
  2256. flags,
  2257. } => {
  2258. let ip_addr = ip_repr.src_addr.into();
  2259. if let Some(lladdr) = lladdr {
  2260. let lladdr = check!(lladdr.parse(self.caps.medium));
  2261. if !lladdr.is_unicast() || !target_addr.is_unicast() {
  2262. return None;
  2263. }
  2264. if flags.contains(NdiscNeighborFlags::OVERRIDE)
  2265. || !self
  2266. .neighbor_cache
  2267. .as_mut()
  2268. .unwrap()
  2269. .lookup(&ip_addr, self.now)
  2270. .found()
  2271. {
  2272. self.neighbor_cache
  2273. .as_mut()
  2274. .unwrap()
  2275. .fill(ip_addr, lladdr, self.now)
  2276. }
  2277. }
  2278. None
  2279. }
  2280. NdiscRepr::NeighborSolicit {
  2281. target_addr,
  2282. lladdr,
  2283. ..
  2284. } => {
  2285. if let Some(lladdr) = lladdr {
  2286. let lladdr = check!(lladdr.parse(self.caps.medium));
  2287. if !lladdr.is_unicast() || !target_addr.is_unicast() {
  2288. return None;
  2289. }
  2290. self.neighbor_cache.as_mut().unwrap().fill(
  2291. ip_repr.src_addr.into(),
  2292. lladdr,
  2293. self.now,
  2294. );
  2295. }
  2296. if self.has_solicited_node(ip_repr.dst_addr) && self.has_ip_addr(target_addr) {
  2297. let advert = Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
  2298. flags: NdiscNeighborFlags::SOLICITED,
  2299. target_addr,
  2300. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  2301. lladdr: Some(self.hardware_addr.unwrap().into()),
  2302. });
  2303. let ip_repr = Ipv6Repr {
  2304. src_addr: target_addr,
  2305. dst_addr: ip_repr.src_addr,
  2306. next_header: IpProtocol::Icmpv6,
  2307. hop_limit: 0xff,
  2308. payload_len: advert.buffer_len(),
  2309. };
  2310. Some(IpPacket::Icmpv6((ip_repr, advert)))
  2311. } else {
  2312. None
  2313. }
  2314. }
  2315. _ => None,
  2316. }
  2317. }
  2318. #[cfg(feature = "proto-ipv6")]
  2319. fn process_hopbyhop<'frame>(
  2320. &mut self,
  2321. sockets: &mut SocketSet,
  2322. ipv6_repr: Ipv6Repr,
  2323. handled_by_raw_socket: bool,
  2324. ip_payload: &'frame [u8],
  2325. ) -> Option<IpPacket<'frame>> {
  2326. let hbh_pkt = check!(Ipv6HopByHopHeader::new_checked(ip_payload));
  2327. let hbh_repr = check!(Ipv6HopByHopRepr::parse(&hbh_pkt));
  2328. for opt_repr in hbh_repr.options() {
  2329. let opt_repr = check!(opt_repr);
  2330. match opt_repr {
  2331. Ipv6OptionRepr::Pad1 | Ipv6OptionRepr::PadN(_) => (),
  2332. Ipv6OptionRepr::Unknown { type_, .. } => {
  2333. match Ipv6OptionFailureType::from(type_) {
  2334. Ipv6OptionFailureType::Skip => (),
  2335. Ipv6OptionFailureType::Discard => {
  2336. return None;
  2337. }
  2338. _ => {
  2339. // FIXME(dlrobertson): Send an ICMPv6 parameter problem message
  2340. // here.
  2341. return None;
  2342. }
  2343. }
  2344. }
  2345. }
  2346. }
  2347. self.process_nxt_hdr(
  2348. sockets,
  2349. ipv6_repr,
  2350. hbh_repr.next_header,
  2351. handled_by_raw_socket,
  2352. &ip_payload[hbh_repr.buffer_len()..],
  2353. )
  2354. }
  2355. #[cfg(feature = "proto-ipv4")]
  2356. fn process_icmpv4<'frame>(
  2357. &mut self,
  2358. _sockets: &mut SocketSet,
  2359. ip_repr: IpRepr,
  2360. ip_payload: &'frame [u8],
  2361. ) -> Option<IpPacket<'frame>> {
  2362. let icmp_packet = check!(Icmpv4Packet::new_checked(ip_payload));
  2363. let icmp_repr = check!(Icmpv4Repr::parse(&icmp_packet, &self.caps.checksum));
  2364. #[cfg(feature = "socket-icmp")]
  2365. let mut handled_by_icmp_socket = false;
  2366. #[cfg(all(feature = "socket-icmp", feature = "proto-ipv4"))]
  2367. for icmp_socket in _sockets
  2368. .items_mut()
  2369. .filter_map(|i| icmp::Socket::downcast_mut(&mut i.socket))
  2370. {
  2371. if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) {
  2372. icmp_socket.process(self, &ip_repr, &icmp_repr.into());
  2373. handled_by_icmp_socket = true;
  2374. }
  2375. }
  2376. match icmp_repr {
  2377. // Respond to echo requests.
  2378. #[cfg(feature = "proto-ipv4")]
  2379. Icmpv4Repr::EchoRequest {
  2380. ident,
  2381. seq_no,
  2382. data,
  2383. } => {
  2384. let icmp_reply_repr = Icmpv4Repr::EchoReply {
  2385. ident,
  2386. seq_no,
  2387. data,
  2388. };
  2389. match ip_repr {
  2390. IpRepr::Ipv4(ipv4_repr) => self.icmpv4_reply(ipv4_repr, icmp_reply_repr),
  2391. #[allow(unreachable_patterns)]
  2392. _ => unreachable!(),
  2393. }
  2394. }
  2395. // Ignore any echo replies.
  2396. Icmpv4Repr::EchoReply { .. } => None,
  2397. // Don't report an error if a packet with unknown type
  2398. // has been handled by an ICMP socket
  2399. #[cfg(feature = "socket-icmp")]
  2400. _ if handled_by_icmp_socket => None,
  2401. // FIXME: do something correct here?
  2402. _ => None,
  2403. }
  2404. }
  2405. #[cfg(feature = "proto-ipv4")]
  2406. fn icmpv4_reply<'frame, 'icmp: 'frame>(
  2407. &self,
  2408. ipv4_repr: Ipv4Repr,
  2409. icmp_repr: Icmpv4Repr<'icmp>,
  2410. ) -> Option<IpPacket<'frame>> {
  2411. if !self.is_unicast_v4(ipv4_repr.src_addr) {
  2412. // Do not send ICMP replies to non-unicast sources
  2413. None
  2414. } else if self.is_unicast_v4(ipv4_repr.dst_addr) {
  2415. // Reply as normal when src_addr and dst_addr are both unicast
  2416. let ipv4_reply_repr = Ipv4Repr {
  2417. src_addr: ipv4_repr.dst_addr,
  2418. dst_addr: ipv4_repr.src_addr,
  2419. next_header: IpProtocol::Icmp,
  2420. payload_len: icmp_repr.buffer_len(),
  2421. hop_limit: 64,
  2422. };
  2423. Some(IpPacket::Icmpv4((ipv4_reply_repr, icmp_repr)))
  2424. } else if self.is_broadcast_v4(ipv4_repr.dst_addr) {
  2425. // Only reply to broadcasts for echo replies and not other ICMP messages
  2426. match icmp_repr {
  2427. Icmpv4Repr::EchoReply { .. } => match self.ipv4_address() {
  2428. Some(src_addr) => {
  2429. let ipv4_reply_repr = Ipv4Repr {
  2430. src_addr,
  2431. dst_addr: ipv4_repr.src_addr,
  2432. next_header: IpProtocol::Icmp,
  2433. payload_len: icmp_repr.buffer_len(),
  2434. hop_limit: 64,
  2435. };
  2436. Some(IpPacket::Icmpv4((ipv4_reply_repr, icmp_repr)))
  2437. }
  2438. None => None,
  2439. },
  2440. _ => None,
  2441. }
  2442. } else {
  2443. None
  2444. }
  2445. }
  2446. #[cfg(feature = "proto-ipv6")]
  2447. fn icmpv6_reply<'frame, 'icmp: 'frame>(
  2448. &self,
  2449. ipv6_repr: Ipv6Repr,
  2450. icmp_repr: Icmpv6Repr<'icmp>,
  2451. ) -> Option<IpPacket<'frame>> {
  2452. if ipv6_repr.dst_addr.is_unicast() {
  2453. let ipv6_reply_repr = Ipv6Repr {
  2454. src_addr: ipv6_repr.dst_addr,
  2455. dst_addr: ipv6_repr.src_addr,
  2456. next_header: IpProtocol::Icmpv6,
  2457. payload_len: icmp_repr.buffer_len(),
  2458. hop_limit: 64,
  2459. };
  2460. Some(IpPacket::Icmpv6((ipv6_reply_repr, icmp_repr)))
  2461. } else {
  2462. // Do not send any ICMP replies to a broadcast destination address.
  2463. None
  2464. }
  2465. }
  2466. #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
  2467. fn process_udp<'frame>(
  2468. &mut self,
  2469. sockets: &mut SocketSet,
  2470. ip_repr: IpRepr,
  2471. handled_by_raw_socket: bool,
  2472. ip_payload: &'frame [u8],
  2473. ) -> Option<IpPacket<'frame>> {
  2474. let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
  2475. let udp_packet = check!(UdpPacket::new_checked(ip_payload));
  2476. let udp_repr = check!(UdpRepr::parse(
  2477. &udp_packet,
  2478. &src_addr,
  2479. &dst_addr,
  2480. &self.caps.checksum
  2481. ));
  2482. let udp_payload = udp_packet.payload();
  2483. #[cfg(feature = "socket-udp")]
  2484. for udp_socket in sockets
  2485. .items_mut()
  2486. .filter_map(|i| udp::Socket::downcast_mut(&mut i.socket))
  2487. {
  2488. if udp_socket.accepts(self, &ip_repr, &udp_repr) {
  2489. udp_socket.process(self, &ip_repr, &udp_repr, udp_payload);
  2490. return None;
  2491. }
  2492. }
  2493. #[cfg(feature = "socket-dns")]
  2494. for dns_socket in sockets
  2495. .items_mut()
  2496. .filter_map(|i| dns::Socket::downcast_mut(&mut i.socket))
  2497. {
  2498. if dns_socket.accepts(&ip_repr, &udp_repr) {
  2499. dns_socket.process(self, &ip_repr, &udp_repr, udp_payload);
  2500. return None;
  2501. }
  2502. }
  2503. // The packet wasn't handled by a socket, send an ICMP port unreachable packet.
  2504. match ip_repr {
  2505. #[cfg(feature = "proto-ipv4")]
  2506. IpRepr::Ipv4(_) if handled_by_raw_socket => None,
  2507. #[cfg(feature = "proto-ipv6")]
  2508. IpRepr::Ipv6(_) if handled_by_raw_socket => None,
  2509. #[cfg(feature = "proto-ipv4")]
  2510. IpRepr::Ipv4(ipv4_repr) => {
  2511. let payload_len =
  2512. icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU, ipv4_repr.buffer_len());
  2513. let icmpv4_reply_repr = Icmpv4Repr::DstUnreachable {
  2514. reason: Icmpv4DstUnreachable::PortUnreachable,
  2515. header: ipv4_repr,
  2516. data: &ip_payload[0..payload_len],
  2517. };
  2518. self.icmpv4_reply(ipv4_repr, icmpv4_reply_repr)
  2519. }
  2520. #[cfg(feature = "proto-ipv6")]
  2521. IpRepr::Ipv6(ipv6_repr) => {
  2522. let payload_len =
  2523. icmp_reply_payload_len(ip_payload.len(), IPV6_MIN_MTU, ipv6_repr.buffer_len());
  2524. let icmpv6_reply_repr = Icmpv6Repr::DstUnreachable {
  2525. reason: Icmpv6DstUnreachable::PortUnreachable,
  2526. header: ipv6_repr,
  2527. data: &ip_payload[0..payload_len],
  2528. };
  2529. self.icmpv6_reply(ipv6_repr, icmpv6_reply_repr)
  2530. }
  2531. }
  2532. }
  2533. #[cfg(feature = "socket-tcp")]
  2534. fn process_tcp<'frame>(
  2535. &mut self,
  2536. sockets: &mut SocketSet,
  2537. ip_repr: IpRepr,
  2538. ip_payload: &'frame [u8],
  2539. ) -> Option<IpPacket<'frame>> {
  2540. let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
  2541. let tcp_packet = check!(TcpPacket::new_checked(ip_payload));
  2542. let tcp_repr = check!(TcpRepr::parse(
  2543. &tcp_packet,
  2544. &src_addr,
  2545. &dst_addr,
  2546. &self.caps.checksum
  2547. ));
  2548. for tcp_socket in sockets
  2549. .items_mut()
  2550. .filter_map(|i| tcp::Socket::downcast_mut(&mut i.socket))
  2551. {
  2552. if tcp_socket.accepts(self, &ip_repr, &tcp_repr) {
  2553. return tcp_socket
  2554. .process(self, &ip_repr, &tcp_repr)
  2555. .map(IpPacket::Tcp);
  2556. }
  2557. }
  2558. if tcp_repr.control == TcpControl::Rst {
  2559. // Never reply to a TCP RST packet with another TCP RST packet.
  2560. None
  2561. } else {
  2562. // The packet wasn't handled by a socket, send a TCP RST packet.
  2563. Some(IpPacket::Tcp(tcp::Socket::rst_reply(&ip_repr, &tcp_repr)))
  2564. }
  2565. }
  2566. #[cfg(feature = "medium-ethernet")]
  2567. fn dispatch<Tx>(
  2568. &mut self,
  2569. tx_token: Tx,
  2570. packet: EthernetPacket,
  2571. _out_packet: Option<&mut OutPackets<'_>>,
  2572. ) -> Result<()>
  2573. where
  2574. Tx: TxToken,
  2575. {
  2576. match packet {
  2577. #[cfg(feature = "proto-ipv4")]
  2578. EthernetPacket::Arp(arp_repr) => {
  2579. let dst_hardware_addr = match arp_repr {
  2580. ArpRepr::EthernetIpv4 {
  2581. target_hardware_addr,
  2582. ..
  2583. } => target_hardware_addr,
  2584. };
  2585. self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
  2586. frame.set_dst_addr(dst_hardware_addr);
  2587. frame.set_ethertype(EthernetProtocol::Arp);
  2588. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  2589. arp_repr.emit(&mut packet);
  2590. })
  2591. }
  2592. EthernetPacket::Ip(packet) => self.dispatch_ip(tx_token, packet, _out_packet),
  2593. }
  2594. }
  2595. #[cfg(feature = "medium-ethernet")]
  2596. fn dispatch_ethernet<Tx, F>(&mut self, tx_token: Tx, buffer_len: usize, f: F) -> Result<()>
  2597. where
  2598. Tx: TxToken,
  2599. F: FnOnce(EthernetFrame<&mut [u8]>),
  2600. {
  2601. let tx_len = EthernetFrame::<&[u8]>::buffer_len(buffer_len);
  2602. tx_token.consume(self.now, tx_len, |tx_buffer| {
  2603. debug_assert!(tx_buffer.as_ref().len() == tx_len);
  2604. let mut frame = EthernetFrame::new_unchecked(tx_buffer);
  2605. let src_addr = if let Some(HardwareAddress::Ethernet(addr)) = self.hardware_addr {
  2606. addr
  2607. } else {
  2608. return Err(Error::Malformed);
  2609. };
  2610. frame.set_src_addr(src_addr);
  2611. f(frame);
  2612. Ok(())
  2613. })
  2614. }
  2615. fn in_same_network(&self, addr: &IpAddress) -> bool {
  2616. self.ip_addrs.iter().any(|cidr| cidr.contains_addr(addr))
  2617. }
  2618. fn route(&self, addr: &IpAddress, timestamp: Instant) -> Result<IpAddress> {
  2619. // Send directly.
  2620. if self.in_same_network(addr) || addr.is_broadcast() {
  2621. return Ok(*addr);
  2622. }
  2623. // Route via a router.
  2624. match self.routes.lookup(addr, timestamp) {
  2625. Some(router_addr) => Ok(router_addr),
  2626. None => Err(Error::Unaddressable),
  2627. }
  2628. }
  2629. fn has_neighbor(&self, addr: &IpAddress) -> bool {
  2630. match self.route(addr, self.now) {
  2631. Ok(_routed_addr) => match self.caps.medium {
  2632. #[cfg(feature = "medium-ethernet")]
  2633. Medium::Ethernet => self
  2634. .neighbor_cache
  2635. .as_ref()
  2636. .unwrap()
  2637. .lookup(&_routed_addr, self.now)
  2638. .found(),
  2639. #[cfg(feature = "medium-ieee802154")]
  2640. Medium::Ieee802154 => self
  2641. .neighbor_cache
  2642. .as_ref()
  2643. .unwrap()
  2644. .lookup(&_routed_addr, self.now)
  2645. .found(),
  2646. #[cfg(feature = "medium-ip")]
  2647. Medium::Ip => true,
  2648. },
  2649. Err(_) => false,
  2650. }
  2651. }
  2652. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  2653. fn lookup_hardware_addr<Tx>(
  2654. &mut self,
  2655. tx_token: Tx,
  2656. src_addr: &IpAddress,
  2657. dst_addr: &IpAddress,
  2658. ) -> Result<(HardwareAddress, Tx)>
  2659. where
  2660. Tx: TxToken,
  2661. {
  2662. if dst_addr.is_broadcast() {
  2663. let hardware_addr = match self.caps.medium {
  2664. #[cfg(feature = "medium-ethernet")]
  2665. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::BROADCAST),
  2666. #[cfg(feature = "medium-ieee802154")]
  2667. Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::BROADCAST),
  2668. #[cfg(feature = "medium-ip")]
  2669. Medium::Ip => unreachable!(),
  2670. };
  2671. return Ok((hardware_addr, tx_token));
  2672. }
  2673. if dst_addr.is_multicast() {
  2674. let b = dst_addr.as_bytes();
  2675. let hardware_addr = match *dst_addr {
  2676. #[cfg(feature = "proto-ipv4")]
  2677. IpAddress::Ipv4(_addr) => {
  2678. HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  2679. 0x01,
  2680. 0x00,
  2681. 0x5e,
  2682. b[1] & 0x7F,
  2683. b[2],
  2684. b[3],
  2685. ]))
  2686. }
  2687. #[cfg(feature = "proto-ipv6")]
  2688. IpAddress::Ipv6(_addr) => match self.caps.medium {
  2689. #[cfg(feature = "medium-ethernet")]
  2690. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  2691. 0x33, 0x33, b[12], b[13], b[14], b[15],
  2692. ])),
  2693. #[cfg(feature = "medium-ieee802154")]
  2694. Medium::Ieee802154 => {
  2695. // Not sure if this is correct
  2696. HardwareAddress::Ieee802154(Ieee802154Address::BROADCAST)
  2697. }
  2698. #[cfg(feature = "medium-ip")]
  2699. Medium::Ip => unreachable!(),
  2700. },
  2701. };
  2702. return Ok((hardware_addr, tx_token));
  2703. }
  2704. let dst_addr = self.route(dst_addr, self.now)?;
  2705. match self
  2706. .neighbor_cache
  2707. .as_mut()
  2708. .unwrap()
  2709. .lookup(&dst_addr, self.now)
  2710. {
  2711. NeighborAnswer::Found(hardware_addr) => return Ok((hardware_addr, tx_token)),
  2712. NeighborAnswer::RateLimited => return Err(Error::Unaddressable),
  2713. _ => (), // XXX
  2714. }
  2715. match (src_addr, dst_addr) {
  2716. #[cfg(feature = "proto-ipv4")]
  2717. (&IpAddress::Ipv4(src_addr), IpAddress::Ipv4(dst_addr)) => {
  2718. net_debug!(
  2719. "address {} not in neighbor cache, sending ARP request",
  2720. dst_addr
  2721. );
  2722. let src_hardware_addr =
  2723. if let Some(HardwareAddress::Ethernet(addr)) = self.hardware_addr {
  2724. addr
  2725. } else {
  2726. return Err(Error::Malformed);
  2727. };
  2728. let arp_repr = ArpRepr::EthernetIpv4 {
  2729. operation: ArpOperation::Request,
  2730. source_hardware_addr: src_hardware_addr,
  2731. source_protocol_addr: src_addr,
  2732. target_hardware_addr: EthernetAddress::BROADCAST,
  2733. target_protocol_addr: dst_addr,
  2734. };
  2735. self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
  2736. frame.set_dst_addr(EthernetAddress::BROADCAST);
  2737. frame.set_ethertype(EthernetProtocol::Arp);
  2738. arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
  2739. })?;
  2740. }
  2741. #[cfg(feature = "proto-ipv6")]
  2742. (&IpAddress::Ipv6(src_addr), IpAddress::Ipv6(dst_addr)) => {
  2743. net_debug!(
  2744. "address {} not in neighbor cache, sending Neighbor Solicitation",
  2745. dst_addr
  2746. );
  2747. let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit {
  2748. target_addr: dst_addr,
  2749. lladdr: Some(self.hardware_addr.unwrap().into()),
  2750. });
  2751. let packet = IpPacket::Icmpv6((
  2752. Ipv6Repr {
  2753. src_addr,
  2754. dst_addr: dst_addr.solicited_node(),
  2755. next_header: IpProtocol::Icmpv6,
  2756. payload_len: solicit.buffer_len(),
  2757. hop_limit: 0xff,
  2758. },
  2759. solicit,
  2760. ));
  2761. self.dispatch_ip(tx_token, packet, None)?;
  2762. }
  2763. #[allow(unreachable_patterns)]
  2764. _ => (),
  2765. }
  2766. // The request got dispatched, limit the rate on the cache.
  2767. self.neighbor_cache.as_mut().unwrap().limit_rate(self.now);
  2768. Err(Error::Unaddressable)
  2769. }
  2770. fn flush_cache(&mut self) {
  2771. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  2772. if let Some(cache) = self.neighbor_cache.as_mut() {
  2773. cache.flush()
  2774. }
  2775. }
  2776. fn dispatch_ip<Tx: TxToken>(
  2777. &mut self,
  2778. tx_token: Tx,
  2779. packet: IpPacket,
  2780. _out_packet: Option<&mut OutPackets<'_>>,
  2781. ) -> Result<()> {
  2782. let mut ip_repr = packet.ip_repr();
  2783. assert!(!ip_repr.dst_addr().is_unspecified());
  2784. // Dispatch IEEE802.15.4:
  2785. #[cfg(feature = "medium-ieee802154")]
  2786. if matches!(self.caps.medium, Medium::Ieee802154) {
  2787. let (dst_hardware_addr, tx_token) = match self.lookup_hardware_addr(
  2788. tx_token,
  2789. &ip_repr.src_addr(),
  2790. &ip_repr.dst_addr(),
  2791. )? {
  2792. (HardwareAddress::Ieee802154(addr), tx_token) => (addr, tx_token),
  2793. _ => unreachable!(),
  2794. };
  2795. return self.dispatch_ieee802154(
  2796. dst_hardware_addr,
  2797. &ip_repr,
  2798. tx_token,
  2799. packet,
  2800. _out_packet,
  2801. );
  2802. }
  2803. // Dispatch IP/Ethernet:
  2804. let caps = self.caps.clone();
  2805. #[cfg(feature = "proto-ipv4-fragmentation")]
  2806. let ipv4_id = self.get_ipv4_ident();
  2807. // First we calculate the total length that we will have to emit.
  2808. let mut total_len = ip_repr.buffer_len();
  2809. // Add the size of the Ethernet header if the medium is Ethernet.
  2810. #[cfg(feature = "medium-ethernet")]
  2811. if matches!(self.caps.medium, Medium::Ethernet) {
  2812. total_len = EthernetFrame::<&[u8]>::buffer_len(total_len);
  2813. }
  2814. // If the medium is Ethernet, then we need to retrieve the destination hardware address.
  2815. #[cfg(feature = "medium-ethernet")]
  2816. let (dst_hardware_addr, tx_token) =
  2817. match self.lookup_hardware_addr(tx_token, &ip_repr.src_addr(), &ip_repr.dst_addr())? {
  2818. (HardwareAddress::Ethernet(addr), tx_token) => (addr, tx_token),
  2819. #[cfg(feature = "medium-ieee802154")]
  2820. (HardwareAddress::Ieee802154(_), _) => unreachable!(),
  2821. };
  2822. // Emit function for the Ethernet header.
  2823. #[cfg(feature = "medium-ethernet")]
  2824. let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| {
  2825. let mut frame = EthernetFrame::new_unchecked(tx_buffer);
  2826. let src_addr = if let Some(HardwareAddress::Ethernet(addr)) = self.hardware_addr {
  2827. addr
  2828. } else {
  2829. return Err(Error::Malformed);
  2830. };
  2831. frame.set_src_addr(src_addr);
  2832. frame.set_dst_addr(dst_hardware_addr);
  2833. match repr.version() {
  2834. #[cfg(feature = "proto-ipv4")]
  2835. IpVersion::Ipv4 => frame.set_ethertype(EthernetProtocol::Ipv4),
  2836. #[cfg(feature = "proto-ipv6")]
  2837. IpVersion::Ipv6 => frame.set_ethertype(EthernetProtocol::Ipv6),
  2838. }
  2839. Ok(())
  2840. };
  2841. // Emit function for the IP header and payload.
  2842. let emit_ip = |repr: &IpRepr, mut tx_buffer: &mut [u8]| {
  2843. repr.emit(&mut tx_buffer, &self.caps.checksum);
  2844. let payload = &mut tx_buffer[repr.header_len()..];
  2845. packet.emit_payload(repr, payload, &caps);
  2846. };
  2847. let total_ip_len = ip_repr.buffer_len();
  2848. match ip_repr {
  2849. #[cfg(feature = "proto-ipv4")]
  2850. IpRepr::Ipv4(ref mut repr) => {
  2851. // If we have an IPv4 packet, then we need to check if we need to fragment it.
  2852. if total_ip_len > self.caps.max_transmission_unit {
  2853. cfg_if::cfg_if! {
  2854. if #[cfg(feature = "proto-ipv4-fragmentation")] {
  2855. net_debug!("start fragmentation");
  2856. let Ipv4OutPacket {
  2857. buffer,
  2858. packet_len,
  2859. sent_bytes,
  2860. repr: out_packet_repr,
  2861. frag_offset,
  2862. ident,
  2863. dst_hardware_addr: dst_address,
  2864. } = &mut _out_packet.unwrap().ipv4_out_packet;
  2865. // Calculate how much we will send now (including the Ethernet header).
  2866. let tx_len = self.caps.max_transmission_unit;
  2867. let ip_header_len = repr.buffer_len();
  2868. let first_frag_ip_len = self.caps.ip_mtu();
  2869. if buffer.len() < first_frag_ip_len {
  2870. net_debug!("Fragmentation buffer is too small");
  2871. return Err(Error::Exhausted);
  2872. }
  2873. *dst_address = dst_hardware_addr;
  2874. // Save the total packet len (without the Ethernet header, but with the first
  2875. // IP header).
  2876. *packet_len = total_ip_len;
  2877. // Save the IP header for other fragments.
  2878. *out_packet_repr = *repr;
  2879. // Save how much bytes we will send now.
  2880. *sent_bytes = first_frag_ip_len;
  2881. // Modify the IP header
  2882. repr.payload_len = first_frag_ip_len - repr.buffer_len();
  2883. // Emit the IP header to the buffer.
  2884. emit_ip(&ip_repr, buffer);
  2885. let mut ipv4_packet = Ipv4Packet::new_unchecked(&mut buffer[..]);
  2886. *ident = ipv4_id;
  2887. ipv4_packet.set_ident(ipv4_id);
  2888. ipv4_packet.set_more_frags(true);
  2889. ipv4_packet.set_dont_frag(false);
  2890. ipv4_packet.set_frag_offset(0);
  2891. if caps.checksum.ipv4.tx() {
  2892. ipv4_packet.fill_checksum();
  2893. }
  2894. // Transmit the first packet.
  2895. tx_token.consume(self.now, tx_len, |mut tx_buffer| {
  2896. #[cfg(feature = "medium-ethernet")]
  2897. if matches!(self.caps.medium, Medium::Ethernet) {
  2898. emit_ethernet(&ip_repr, tx_buffer)?;
  2899. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  2900. }
  2901. // Change the offset for the next packet.
  2902. *frag_offset = (first_frag_ip_len - ip_header_len) as u16;
  2903. // Copy the IP header and the payload.
  2904. tx_buffer[..first_frag_ip_len]
  2905. .copy_from_slice(&buffer[..first_frag_ip_len]);
  2906. Ok(())
  2907. })
  2908. } else {
  2909. net_debug!("Enable the `proto-ipv4-fragmentation` feature for fragmentation support.");
  2910. Ok(())
  2911. }
  2912. }
  2913. } else {
  2914. // No fragmentation is required.
  2915. tx_token.consume(self.now, total_len, |mut tx_buffer| {
  2916. #[cfg(feature = "medium-ethernet")]
  2917. if matches!(self.caps.medium, Medium::Ethernet) {
  2918. emit_ethernet(&ip_repr, tx_buffer)?;
  2919. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  2920. }
  2921. emit_ip(&ip_repr, tx_buffer);
  2922. Ok(())
  2923. })
  2924. }
  2925. }
  2926. // We don't support IPv6 fragmentation yet.
  2927. #[cfg(feature = "proto-ipv6")]
  2928. IpRepr::Ipv6(_) => tx_token.consume(self.now, total_len, |mut tx_buffer| {
  2929. #[cfg(feature = "medium-ethernet")]
  2930. if matches!(self.caps.medium, Medium::Ethernet) {
  2931. emit_ethernet(&ip_repr, tx_buffer)?;
  2932. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  2933. }
  2934. emit_ip(&ip_repr, tx_buffer);
  2935. Ok(())
  2936. }),
  2937. }
  2938. }
  2939. #[cfg(all(feature = "medium-ieee802154", feature = "proto-sixlowpan"))]
  2940. fn dispatch_ieee802154<Tx: TxToken>(
  2941. &mut self,
  2942. ll_dst_a: Ieee802154Address,
  2943. ip_repr: &IpRepr,
  2944. tx_token: Tx,
  2945. packet: IpPacket,
  2946. _out_packet: Option<&mut OutPackets>,
  2947. ) -> Result<()> {
  2948. // We first need to convert the IPv6 packet to a 6LoWPAN compressed packet.
  2949. // Whenever this packet is to big to fit in the IEEE802.15.4 packet, then we need to
  2950. // fragment it.
  2951. let ll_src_a = self.hardware_addr.map_or_else(
  2952. || Err(Error::Malformed),
  2953. |addr| match addr {
  2954. HardwareAddress::Ieee802154(addr) => Ok(addr),
  2955. _ => Err(Error::Malformed),
  2956. },
  2957. )?;
  2958. let (src_addr, dst_addr) = match (ip_repr.src_addr(), ip_repr.dst_addr()) {
  2959. (IpAddress::Ipv6(src_addr), IpAddress::Ipv6(dst_addr)) => (src_addr, dst_addr),
  2960. #[allow(unreachable_patterns)]
  2961. _ => return Err(Error::Unaddressable),
  2962. };
  2963. // Create the IEEE802.15.4 header.
  2964. let ieee_repr = Ieee802154Repr {
  2965. frame_type: Ieee802154FrameType::Data,
  2966. security_enabled: false,
  2967. frame_pending: false,
  2968. ack_request: false,
  2969. sequence_number: Some(self.get_sequence_number()),
  2970. pan_id_compression: true,
  2971. frame_version: Ieee802154FrameVersion::Ieee802154_2003,
  2972. dst_pan_id: self.pan_id,
  2973. dst_addr: Some(ll_dst_a),
  2974. src_pan_id: self.pan_id,
  2975. src_addr: Some(ll_src_a),
  2976. };
  2977. // Create the 6LoWPAN IPHC header.
  2978. let iphc_repr = SixlowpanIphcRepr {
  2979. src_addr,
  2980. ll_src_addr: Some(ll_src_a),
  2981. dst_addr,
  2982. ll_dst_addr: Some(ll_dst_a),
  2983. next_header: match &packet {
  2984. IpPacket::Icmpv6(_) => SixlowpanNextHeader::Uncompressed(IpProtocol::Icmpv6),
  2985. #[cfg(feature = "socket-tcp")]
  2986. IpPacket::Tcp(_) => SixlowpanNextHeader::Uncompressed(IpProtocol::Tcp),
  2987. #[cfg(feature = "socket-udp")]
  2988. IpPacket::Udp(_) => SixlowpanNextHeader::Compressed,
  2989. #[allow(unreachable_patterns)]
  2990. _ => return Err(Error::Unrecognized),
  2991. },
  2992. hop_limit: ip_repr.hop_limit(),
  2993. ecn: None,
  2994. dscp: None,
  2995. flow_label: None,
  2996. };
  2997. // Now we calculate the total size of the packet.
  2998. // We need to know this, such that we know when to do the fragmentation.
  2999. let mut total_size = 0;
  3000. total_size += iphc_repr.buffer_len();
  3001. let mut _compressed_headers_len = iphc_repr.buffer_len();
  3002. let mut _uncompressed_headers_len = ip_repr.header_len();
  3003. #[allow(unreachable_patterns)]
  3004. match packet {
  3005. #[cfg(feature = "socket-udp")]
  3006. IpPacket::Udp((_, udpv6_repr, payload)) => {
  3007. let udp_repr = SixlowpanUdpNhcRepr(udpv6_repr);
  3008. _compressed_headers_len += udp_repr.header_len();
  3009. _uncompressed_headers_len += udpv6_repr.header_len();
  3010. total_size += udp_repr.header_len() + payload.len();
  3011. }
  3012. #[cfg(feature = "socket-tcp")]
  3013. IpPacket::Tcp((_, tcp_repr)) => {
  3014. total_size += tcp_repr.buffer_len();
  3015. }
  3016. #[cfg(feature = "proto-ipv6")]
  3017. IpPacket::Icmpv6((_, icmp_repr)) => {
  3018. total_size += icmp_repr.buffer_len();
  3019. }
  3020. _ => return Err(Error::Unrecognized),
  3021. }
  3022. let ieee_len = ieee_repr.buffer_len();
  3023. if total_size + ieee_len > 125 {
  3024. cfg_if::cfg_if! {
  3025. if #[cfg(feature = "proto-sixlowpan-fragmentation")] {
  3026. // The packet does not fit in one Ieee802154 frame, so we need fragmentation.
  3027. // We do this by emitting everything in the `out_packet.buffer` from the interface.
  3028. // After emitting everything into that buffer, we send the first fragment heere.
  3029. // When `poll` is called again, we check if out_packet was fully sent, otherwise we
  3030. // call `dispatch_ieee802154_out_packet`, which will transmit the other fragments.
  3031. // `dispatch_ieee802154_out_packet` requires some information about the total packet size,
  3032. // the link local source and destination address...
  3033. let SixlowpanOutPacket {
  3034. buffer,
  3035. packet_len,
  3036. datagram_size,
  3037. datagram_tag,
  3038. sent_bytes,
  3039. fragn_size,
  3040. ll_dst_addr,
  3041. ll_src_addr,
  3042. datagram_offset,
  3043. ..
  3044. } = &mut _out_packet.unwrap().sixlowpan_out_packet;
  3045. if buffer.len() < total_size {
  3046. net_debug!("6LoWPAN: Fragmentation buffer is too small");
  3047. return Err(Error::Exhausted);
  3048. }
  3049. *ll_dst_addr = ll_dst_a;
  3050. *ll_src_addr = ll_src_a;
  3051. let mut iphc_packet =
  3052. SixlowpanIphcPacket::new_unchecked(&mut buffer[..iphc_repr.buffer_len()]);
  3053. iphc_repr.emit(&mut iphc_packet);
  3054. let b = &mut buffer[iphc_repr.buffer_len()..];
  3055. #[allow(unreachable_patterns)]
  3056. match packet {
  3057. #[cfg(feature = "socket-udp")]
  3058. IpPacket::Udp((_, udpv6_repr, payload)) => {
  3059. let udp_repr = SixlowpanUdpNhcRepr(udpv6_repr);
  3060. let mut udp_packet = SixlowpanUdpNhcPacket::new_unchecked(
  3061. &mut b[..udp_repr.header_len() + payload.len()],
  3062. );
  3063. udp_repr.emit(
  3064. &mut udp_packet,
  3065. &iphc_repr.src_addr,
  3066. &iphc_repr.dst_addr,
  3067. payload.len(),
  3068. |buf| buf.copy_from_slice(payload),
  3069. );
  3070. }
  3071. #[cfg(feature = "socket-tcp")]
  3072. IpPacket::Tcp((_, tcp_repr)) => {
  3073. let mut tcp_packet = TcpPacket::new_unchecked(&mut b[..tcp_repr.buffer_len()]);
  3074. tcp_repr.emit(
  3075. &mut tcp_packet,
  3076. &iphc_repr.src_addr.into(),
  3077. &iphc_repr.dst_addr.into(),
  3078. &self.caps.checksum,
  3079. );
  3080. }
  3081. #[cfg(feature = "proto-ipv6")]
  3082. IpPacket::Icmpv6((_, icmp_repr)) => {
  3083. let mut icmp_packet =
  3084. Icmpv6Packet::new_unchecked(&mut b[..icmp_repr.buffer_len()]);
  3085. icmp_repr.emit(
  3086. &iphc_repr.src_addr.into(),
  3087. &iphc_repr.dst_addr.into(),
  3088. &mut icmp_packet,
  3089. &self.caps.checksum,
  3090. );
  3091. }
  3092. _ => return Err(Error::Unrecognized),
  3093. }
  3094. *packet_len = total_size;
  3095. // The datagram size that we need to set in the first fragment header is equal to the
  3096. // IPv6 payload length + 40.
  3097. *datagram_size = (packet.ip_repr().payload_len() + 40) as u16;
  3098. // We generate a random tag.
  3099. let tag = self.get_sixlowpan_fragment_tag();
  3100. // We save the tag for the other fragments that will be created when calling `poll`
  3101. // multiple times.
  3102. *datagram_tag = tag;
  3103. let frag1 = SixlowpanFragRepr::FirstFragment {
  3104. size: *datagram_size,
  3105. tag,
  3106. };
  3107. let fragn = SixlowpanFragRepr::Fragment {
  3108. size: *datagram_size,
  3109. tag,
  3110. offset: 0,
  3111. };
  3112. // We calculate how much data we can send in the first fragment and the other
  3113. // fragments. The eventual IPv6 sizes of these fragments need to be a multiple of eight
  3114. // (except for the last fragment) since the offset field in the fragment is an offset
  3115. // in multiples of 8 octets. This is explained in [RFC 4944 § 5.3].
  3116. //
  3117. // [RFC 4944 § 5.3]: https://datatracker.ietf.org/doc/html/rfc4944#section-5.3
  3118. let header_diff = _uncompressed_headers_len - _compressed_headers_len;
  3119. let frag1_size =
  3120. (125 - ieee_len - frag1.buffer_len() + header_diff) / 8 * 8 - (header_diff);
  3121. *fragn_size = (125 - ieee_len - fragn.buffer_len()) / 8 * 8;
  3122. *sent_bytes = frag1_size;
  3123. *datagram_offset = frag1_size + header_diff;
  3124. tx_token.consume(
  3125. self.now,
  3126. ieee_len + frag1.buffer_len() + frag1_size,
  3127. |mut tx_buf| {
  3128. // Add the IEEE header.
  3129. let mut ieee_packet = Ieee802154Frame::new_unchecked(&mut tx_buf[..ieee_len]);
  3130. ieee_repr.emit(&mut ieee_packet);
  3131. tx_buf = &mut tx_buf[ieee_len..];
  3132. // Add the first fragment header
  3133. let mut frag1_packet = SixlowpanFragPacket::new_unchecked(&mut tx_buf);
  3134. frag1.emit(&mut frag1_packet);
  3135. tx_buf = &mut tx_buf[frag1.buffer_len()..];
  3136. // Add the buffer part.
  3137. tx_buf[..frag1_size].copy_from_slice(&buffer[..frag1_size]);
  3138. Ok(())
  3139. },
  3140. )
  3141. } else {
  3142. net_debug!("Enable the `proto-sixlowpan-fragmentation` feature for fragmentation support.");
  3143. Ok(())
  3144. }
  3145. }
  3146. } else {
  3147. // We don't need fragmentation, so we emit everything to the TX token.
  3148. tx_token.consume(self.now, total_size + ieee_len, |mut tx_buf| {
  3149. let mut ieee_packet = Ieee802154Frame::new_unchecked(&mut tx_buf[..ieee_len]);
  3150. ieee_repr.emit(&mut ieee_packet);
  3151. tx_buf = &mut tx_buf[ieee_len..];
  3152. let mut iphc_packet =
  3153. SixlowpanIphcPacket::new_unchecked(&mut tx_buf[..iphc_repr.buffer_len()]);
  3154. iphc_repr.emit(&mut iphc_packet);
  3155. tx_buf = &mut tx_buf[iphc_repr.buffer_len()..];
  3156. #[allow(unreachable_patterns)]
  3157. match packet {
  3158. #[cfg(feature = "socket-udp")]
  3159. IpPacket::Udp((_, udpv6_repr, payload)) => {
  3160. let udp_repr = SixlowpanUdpNhcRepr(udpv6_repr);
  3161. let mut udp_packet = SixlowpanUdpNhcPacket::new_unchecked(
  3162. &mut tx_buf[..udp_repr.header_len() + payload.len()],
  3163. );
  3164. udp_repr.emit(
  3165. &mut udp_packet,
  3166. &iphc_repr.src_addr,
  3167. &iphc_repr.dst_addr,
  3168. payload.len(),
  3169. |buf| buf.copy_from_slice(payload),
  3170. );
  3171. }
  3172. #[cfg(feature = "socket-tcp")]
  3173. IpPacket::Tcp((_, tcp_repr)) => {
  3174. let mut tcp_packet =
  3175. TcpPacket::new_unchecked(&mut tx_buf[..tcp_repr.buffer_len()]);
  3176. tcp_repr.emit(
  3177. &mut tcp_packet,
  3178. &iphc_repr.src_addr.into(),
  3179. &iphc_repr.dst_addr.into(),
  3180. &self.caps.checksum,
  3181. );
  3182. }
  3183. #[cfg(feature = "proto-ipv6")]
  3184. IpPacket::Icmpv6((_, icmp_repr)) => {
  3185. let mut icmp_packet =
  3186. Icmpv6Packet::new_unchecked(&mut tx_buf[..icmp_repr.buffer_len()]);
  3187. icmp_repr.emit(
  3188. &iphc_repr.src_addr.into(),
  3189. &iphc_repr.dst_addr.into(),
  3190. &mut icmp_packet,
  3191. &self.caps.checksum,
  3192. );
  3193. }
  3194. _ => return Err(Error::Unrecognized),
  3195. }
  3196. Ok(())
  3197. })
  3198. }
  3199. }
  3200. #[cfg(all(
  3201. feature = "medium-ieee802154",
  3202. feature = "proto-sixlowpan-fragmentation"
  3203. ))]
  3204. fn dispatch_ieee802154_out_packet<Tx: TxToken>(
  3205. &mut self,
  3206. tx_token: Tx,
  3207. out_packet: &mut SixlowpanOutPacket,
  3208. ) -> Result<()> {
  3209. let SixlowpanOutPacket {
  3210. buffer,
  3211. packet_len,
  3212. datagram_size,
  3213. datagram_tag,
  3214. datagram_offset,
  3215. sent_bytes,
  3216. fragn_size,
  3217. ll_dst_addr,
  3218. ll_src_addr,
  3219. ..
  3220. } = out_packet;
  3221. // Create the IEEE802.15.4 header.
  3222. let ieee_repr = Ieee802154Repr {
  3223. frame_type: Ieee802154FrameType::Data,
  3224. security_enabled: false,
  3225. frame_pending: false,
  3226. ack_request: false,
  3227. sequence_number: Some(self.get_sequence_number()),
  3228. pan_id_compression: true,
  3229. frame_version: Ieee802154FrameVersion::Ieee802154_2003,
  3230. dst_pan_id: self.pan_id,
  3231. dst_addr: Some(*ll_dst_addr),
  3232. src_pan_id: self.pan_id,
  3233. src_addr: Some(*ll_src_addr),
  3234. };
  3235. // Create the FRAG_N header.
  3236. let fragn = SixlowpanFragRepr::Fragment {
  3237. size: *datagram_size,
  3238. tag: *datagram_tag,
  3239. offset: (*datagram_offset / 8) as u8,
  3240. };
  3241. let ieee_len = ieee_repr.buffer_len();
  3242. let frag_size = (*packet_len - *sent_bytes).min(*fragn_size);
  3243. tx_token.consume(
  3244. self.now,
  3245. ieee_repr.buffer_len() + fragn.buffer_len() + frag_size,
  3246. |mut tx_buf| {
  3247. let mut ieee_packet = Ieee802154Frame::new_unchecked(&mut tx_buf[..ieee_len]);
  3248. ieee_repr.emit(&mut ieee_packet);
  3249. tx_buf = &mut tx_buf[ieee_len..];
  3250. let mut frag_packet =
  3251. SixlowpanFragPacket::new_unchecked(&mut tx_buf[..fragn.buffer_len()]);
  3252. fragn.emit(&mut frag_packet);
  3253. tx_buf = &mut tx_buf[fragn.buffer_len()..];
  3254. // Add the buffer part
  3255. tx_buf[..frag_size].copy_from_slice(&buffer[*sent_bytes..][..frag_size]);
  3256. *sent_bytes += frag_size;
  3257. *datagram_offset += frag_size;
  3258. Ok(())
  3259. },
  3260. )
  3261. }
  3262. #[cfg(feature = "proto-ipv4-fragmentation")]
  3263. fn dispatch_ipv4_out_packet<Tx: TxToken>(
  3264. &mut self,
  3265. tx_token: Tx,
  3266. out_packet: &mut Ipv4OutPacket,
  3267. ) -> Result<()> {
  3268. let Ipv4OutPacket {
  3269. buffer,
  3270. packet_len,
  3271. sent_bytes,
  3272. repr,
  3273. dst_hardware_addr,
  3274. frag_offset,
  3275. ident,
  3276. ..
  3277. } = out_packet;
  3278. let caps = self.caps.clone();
  3279. let mtu_max = self.ip_mtu();
  3280. let ip_len = (*packet_len - *sent_bytes + repr.buffer_len()).min(mtu_max);
  3281. let payload_len = ip_len - repr.buffer_len();
  3282. let more_frags = (*packet_len - *sent_bytes) != payload_len;
  3283. repr.payload_len = payload_len;
  3284. *sent_bytes += payload_len;
  3285. let mut tx_len = ip_len;
  3286. #[cfg(feature = "medium-ethernet")]
  3287. if matches!(caps.medium, Medium::Ethernet) {
  3288. tx_len += EthernetFrame::<&[u8]>::header_len();
  3289. }
  3290. // Emit function for the Ethernet header.
  3291. let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| {
  3292. let mut frame = EthernetFrame::new_unchecked(tx_buffer);
  3293. let src_addr = if let Some(HardwareAddress::Ethernet(addr)) = self.hardware_addr {
  3294. addr
  3295. } else {
  3296. return Err(Error::Malformed);
  3297. };
  3298. frame.set_src_addr(src_addr);
  3299. frame.set_dst_addr(*dst_hardware_addr);
  3300. match repr.version() {
  3301. #[cfg(feature = "proto-ipv4")]
  3302. IpVersion::Ipv4 => frame.set_ethertype(EthernetProtocol::Ipv4),
  3303. #[cfg(feature = "proto-ipv6")]
  3304. IpVersion::Ipv6 => frame.set_ethertype(EthernetProtocol::Ipv6),
  3305. }
  3306. Ok(())
  3307. };
  3308. tx_token.consume(self.now, tx_len, |mut tx_buffer| {
  3309. #[cfg(feature = "medium-ethernet")]
  3310. if matches!(self.caps.medium, Medium::Ethernet) {
  3311. emit_ethernet(&IpRepr::Ipv4(*repr), tx_buffer)?;
  3312. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  3313. }
  3314. let mut packet = Ipv4Packet::new_unchecked(&mut tx_buffer[..repr.buffer_len()]);
  3315. repr.emit(&mut packet, &caps.checksum);
  3316. packet.set_ident(*ident);
  3317. packet.set_more_frags(more_frags);
  3318. packet.set_dont_frag(false);
  3319. packet.set_frag_offset(*frag_offset);
  3320. if caps.checksum.ipv4.tx() {
  3321. packet.fill_checksum();
  3322. }
  3323. tx_buffer[repr.buffer_len()..][..payload_len].copy_from_slice(
  3324. &buffer[*frag_offset as usize + repr.buffer_len() as usize..][..payload_len],
  3325. );
  3326. // Update the frag offset for the next fragment.
  3327. *frag_offset += payload_len as u16;
  3328. Ok(())
  3329. })
  3330. }
  3331. #[cfg(feature = "proto-igmp")]
  3332. fn igmp_report_packet<'any>(
  3333. &self,
  3334. version: IgmpVersion,
  3335. group_addr: Ipv4Address,
  3336. ) -> Option<IpPacket<'any>> {
  3337. let iface_addr = self.ipv4_address()?;
  3338. let igmp_repr = IgmpRepr::MembershipReport {
  3339. group_addr,
  3340. version,
  3341. };
  3342. let pkt = IpPacket::Igmp((
  3343. Ipv4Repr {
  3344. src_addr: iface_addr,
  3345. // Send to the group being reported
  3346. dst_addr: group_addr,
  3347. next_header: IpProtocol::Igmp,
  3348. payload_len: igmp_repr.buffer_len(),
  3349. hop_limit: 1,
  3350. // [#183](https://github.com/m-labs/smoltcp/issues/183).
  3351. },
  3352. igmp_repr,
  3353. ));
  3354. Some(pkt)
  3355. }
  3356. #[cfg(feature = "proto-igmp")]
  3357. fn igmp_leave_packet<'any>(&self, group_addr: Ipv4Address) -> Option<IpPacket<'any>> {
  3358. self.ipv4_address().map(|iface_addr| {
  3359. let igmp_repr = IgmpRepr::LeaveGroup { group_addr };
  3360. IpPacket::Igmp((
  3361. Ipv4Repr {
  3362. src_addr: iface_addr,
  3363. dst_addr: Ipv4Address::MULTICAST_ALL_ROUTERS,
  3364. next_header: IpProtocol::Igmp,
  3365. payload_len: igmp_repr.buffer_len(),
  3366. hop_limit: 1,
  3367. },
  3368. igmp_repr,
  3369. ))
  3370. })
  3371. }
  3372. }
  3373. #[cfg(test)]
  3374. mod test {
  3375. use std::collections::BTreeMap;
  3376. #[cfg(feature = "proto-igmp")]
  3377. use std::vec::Vec;
  3378. use super::*;
  3379. use crate::iface::Interface;
  3380. #[cfg(feature = "medium-ethernet")]
  3381. use crate::iface::NeighborCache;
  3382. use crate::phy::{ChecksumCapabilities, Loopback};
  3383. #[cfg(feature = "proto-igmp")]
  3384. use crate::time::Instant;
  3385. use crate::{Error, Result};
  3386. #[allow(unused)]
  3387. fn fill_slice(s: &mut [u8], val: u8) {
  3388. for x in s.iter_mut() {
  3389. *x = val
  3390. }
  3391. }
  3392. fn create<'a>() -> (Interface<'a>, SocketSet<'a>, Loopback) {
  3393. #[cfg(feature = "medium-ethernet")]
  3394. return create_ethernet();
  3395. #[cfg(not(feature = "medium-ethernet"))]
  3396. return create_ip();
  3397. }
  3398. #[cfg(all(feature = "medium-ip"))]
  3399. #[allow(unused)]
  3400. fn create_ip<'a>() -> (Interface<'a>, SocketSet<'a>, Loopback) {
  3401. // Create a basic device
  3402. let mut device = Loopback::new(Medium::Ip);
  3403. let ip_addrs = [
  3404. #[cfg(feature = "proto-ipv4")]
  3405. IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8),
  3406. #[cfg(feature = "proto-ipv6")]
  3407. IpCidr::new(IpAddress::v6(0, 0, 0, 0, 0, 0, 0, 1), 128),
  3408. #[cfg(feature = "proto-ipv6")]
  3409. IpCidr::new(IpAddress::v6(0xfdbe, 0, 0, 0, 0, 0, 0, 1), 64),
  3410. ];
  3411. let iface_builder = InterfaceBuilder::new().ip_addrs(ip_addrs);
  3412. #[cfg(feature = "proto-ipv4-fragmentation")]
  3413. let iface_builder = iface_builder
  3414. .ipv4_reassembly_buffer(PacketAssemblerSet::new(vec![], BTreeMap::new()))
  3415. .ipv4_fragmentation_buffer(vec![]);
  3416. #[cfg(feature = "proto-igmp")]
  3417. let iface_builder = iface_builder.ipv4_multicast_groups(BTreeMap::new());
  3418. let iface = iface_builder.finalize(&mut device);
  3419. (iface, SocketSet::new(vec![]), device)
  3420. }
  3421. #[cfg(all(feature = "medium-ethernet"))]
  3422. fn create_ethernet<'a>() -> (Interface<'a>, SocketSet<'a>, Loopback) {
  3423. // Create a basic device
  3424. let mut device = Loopback::new(Medium::Ethernet);
  3425. let ip_addrs = [
  3426. #[cfg(feature = "proto-ipv4")]
  3427. IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8),
  3428. #[cfg(feature = "proto-ipv6")]
  3429. IpCidr::new(IpAddress::v6(0, 0, 0, 0, 0, 0, 0, 1), 128),
  3430. #[cfg(feature = "proto-ipv6")]
  3431. IpCidr::new(IpAddress::v6(0xfdbe, 0, 0, 0, 0, 0, 0, 1), 64),
  3432. ];
  3433. let iface_builder = InterfaceBuilder::new()
  3434. .hardware_addr(EthernetAddress::default().into())
  3435. .neighbor_cache(NeighborCache::new(BTreeMap::new()))
  3436. .ip_addrs(ip_addrs);
  3437. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  3438. let iface_builder = iface_builder
  3439. .sixlowpan_reassembly_buffer(PacketAssemblerSet::new(vec![], BTreeMap::new()))
  3440. .sixlowpan_fragmentation_buffer(vec![]);
  3441. #[cfg(feature = "proto-ipv4-fragmentation")]
  3442. let iface_builder = iface_builder
  3443. .ipv4_reassembly_buffer(PacketAssemblerSet::new(vec![], BTreeMap::new()))
  3444. .ipv4_fragmentation_buffer(vec![]);
  3445. #[cfg(feature = "proto-igmp")]
  3446. let iface_builder = iface_builder.ipv4_multicast_groups(BTreeMap::new());
  3447. let iface = iface_builder.finalize(&mut device);
  3448. (iface, SocketSet::new(vec![]), device)
  3449. }
  3450. #[cfg(feature = "proto-igmp")]
  3451. fn recv_all(device: &mut Loopback, timestamp: Instant) -> Vec<Vec<u8>> {
  3452. let mut pkts = Vec::new();
  3453. while let Some((rx, _tx)) = device.receive() {
  3454. rx.consume(timestamp, |pkt| {
  3455. pkts.push(pkt.to_vec());
  3456. Ok(())
  3457. })
  3458. .unwrap();
  3459. }
  3460. pkts
  3461. }
  3462. #[derive(Debug, PartialEq)]
  3463. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  3464. struct MockTxToken;
  3465. impl TxToken for MockTxToken {
  3466. fn consume<R, F>(self, _: Instant, _: usize, _: F) -> Result<R>
  3467. where
  3468. F: FnOnce(&mut [u8]) -> Result<R>,
  3469. {
  3470. Err(Error::Unaddressable)
  3471. }
  3472. }
  3473. #[test]
  3474. #[should_panic(expected = "hardware_addr required option was not set")]
  3475. #[cfg(all(feature = "medium-ethernet"))]
  3476. fn test_builder_initialization_panic() {
  3477. let mut device = Loopback::new(Medium::Ethernet);
  3478. InterfaceBuilder::new().finalize(&mut device);
  3479. }
  3480. #[test]
  3481. #[cfg(feature = "proto-ipv4")]
  3482. fn test_no_icmp_no_unicast_ipv4() {
  3483. let (mut iface, mut sockets, _device) = create();
  3484. // Unknown Ipv4 Protocol
  3485. //
  3486. // Because the destination is the broadcast address
  3487. // this should not trigger and Destination Unreachable
  3488. // response. See RFC 1122 § 3.2.2.
  3489. let repr = IpRepr::Ipv4(Ipv4Repr {
  3490. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  3491. dst_addr: Ipv4Address::BROADCAST,
  3492. next_header: IpProtocol::Unknown(0x0c),
  3493. payload_len: 0,
  3494. hop_limit: 0x40,
  3495. });
  3496. let mut bytes = vec![0u8; 54];
  3497. repr.emit(&mut bytes, &ChecksumCapabilities::default());
  3498. let frame = Ipv4Packet::new_unchecked(&bytes);
  3499. // Ensure that the unknown protocol frame does not trigger an
  3500. // ICMP error response when the destination address is a
  3501. // broadcast address
  3502. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  3503. assert_eq!(iface.inner.process_ipv4(&mut sockets, &frame, None), None);
  3504. #[cfg(feature = "proto-ipv4-fragmentation")]
  3505. assert_eq!(
  3506. iface.inner.process_ipv4(
  3507. &mut sockets,
  3508. &frame,
  3509. Some(&mut iface.fragments.ipv4_fragments)
  3510. ),
  3511. None
  3512. );
  3513. }
  3514. #[test]
  3515. #[cfg(feature = "proto-ipv6")]
  3516. fn test_no_icmp_no_unicast_ipv6() {
  3517. let (mut iface, mut sockets, _device) = create();
  3518. // Unknown Ipv6 Protocol
  3519. //
  3520. // Because the destination is the broadcast address
  3521. // this should not trigger and Destination Unreachable
  3522. // response. See RFC 1122 § 3.2.2.
  3523. let repr = IpRepr::Ipv6(Ipv6Repr {
  3524. src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
  3525. dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
  3526. next_header: IpProtocol::Unknown(0x0c),
  3527. payload_len: 0,
  3528. hop_limit: 0x40,
  3529. });
  3530. let mut bytes = vec![0u8; 54];
  3531. repr.emit(&mut bytes, &ChecksumCapabilities::default());
  3532. let frame = Ipv6Packet::new_unchecked(&bytes);
  3533. // Ensure that the unknown protocol frame does not trigger an
  3534. // ICMP error response when the destination address is a
  3535. // broadcast address
  3536. assert_eq!(iface.inner.process_ipv6(&mut sockets, &frame), None);
  3537. }
  3538. #[test]
  3539. #[cfg(feature = "proto-ipv4")]
  3540. fn test_icmp_error_no_payload() {
  3541. static NO_BYTES: [u8; 0] = [];
  3542. let (mut iface, mut sockets, _device) = create();
  3543. // Unknown Ipv4 Protocol with no payload
  3544. let repr = IpRepr::Ipv4(Ipv4Repr {
  3545. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  3546. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  3547. next_header: IpProtocol::Unknown(0x0c),
  3548. payload_len: 0,
  3549. hop_limit: 0x40,
  3550. });
  3551. let mut bytes = vec![0u8; 34];
  3552. repr.emit(&mut bytes, &ChecksumCapabilities::default());
  3553. let frame = Ipv4Packet::new_unchecked(&bytes);
  3554. // The expected Destination Unreachable response due to the
  3555. // unknown protocol
  3556. let icmp_repr = Icmpv4Repr::DstUnreachable {
  3557. reason: Icmpv4DstUnreachable::ProtoUnreachable,
  3558. header: Ipv4Repr {
  3559. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  3560. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  3561. next_header: IpProtocol::Unknown(12),
  3562. payload_len: 0,
  3563. hop_limit: 64,
  3564. },
  3565. data: &NO_BYTES,
  3566. };
  3567. let expected_repr = IpPacket::Icmpv4((
  3568. Ipv4Repr {
  3569. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  3570. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  3571. next_header: IpProtocol::Icmp,
  3572. payload_len: icmp_repr.buffer_len(),
  3573. hop_limit: 64,
  3574. },
  3575. icmp_repr,
  3576. ));
  3577. // Ensure that the unknown protocol triggers an error response.
  3578. // And we correctly handle no payload.
  3579. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  3580. assert_eq!(
  3581. iface.inner.process_ipv4(&mut sockets, &frame, None),
  3582. Some(expected_repr)
  3583. );
  3584. #[cfg(feature = "proto-ipv4-fragmentation")]
  3585. assert_eq!(
  3586. iface.inner.process_ipv4(
  3587. &mut sockets,
  3588. &frame,
  3589. Some(&mut iface.fragments.ipv4_fragments)
  3590. ),
  3591. Some(expected_repr)
  3592. );
  3593. }
  3594. #[test]
  3595. #[cfg(feature = "proto-ipv4")]
  3596. fn test_local_subnet_broadcasts() {
  3597. let (mut iface, _, _device) = create();
  3598. iface.update_ip_addrs(|addrs| {
  3599. addrs.iter_mut().next().map(|addr| {
  3600. *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 23]), 24));
  3601. });
  3602. });
  3603. assert!(iface
  3604. .inner
  3605. .is_subnet_broadcast(Ipv4Address([192, 168, 1, 255])),);
  3606. assert!(!iface
  3607. .inner
  3608. .is_subnet_broadcast(Ipv4Address([192, 168, 1, 254])),);
  3609. iface.update_ip_addrs(|addrs| {
  3610. addrs.iter_mut().next().map(|addr| {
  3611. *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 16));
  3612. });
  3613. });
  3614. assert!(!iface
  3615. .inner
  3616. .is_subnet_broadcast(Ipv4Address([192, 168, 23, 255])),);
  3617. assert!(!iface
  3618. .inner
  3619. .is_subnet_broadcast(Ipv4Address([192, 168, 23, 254])),);
  3620. assert!(!iface
  3621. .inner
  3622. .is_subnet_broadcast(Ipv4Address([192, 168, 255, 254])),);
  3623. assert!(iface
  3624. .inner
  3625. .is_subnet_broadcast(Ipv4Address([192, 168, 255, 255])),);
  3626. iface.update_ip_addrs(|addrs| {
  3627. addrs.iter_mut().next().map(|addr| {
  3628. *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 8));
  3629. });
  3630. });
  3631. assert!(!iface
  3632. .inner
  3633. .is_subnet_broadcast(Ipv4Address([192, 23, 1, 255])),);
  3634. assert!(!iface
  3635. .inner
  3636. .is_subnet_broadcast(Ipv4Address([192, 23, 1, 254])),);
  3637. assert!(!iface
  3638. .inner
  3639. .is_subnet_broadcast(Ipv4Address([192, 255, 255, 254])),);
  3640. assert!(iface
  3641. .inner
  3642. .is_subnet_broadcast(Ipv4Address([192, 255, 255, 255])),);
  3643. }
  3644. #[test]
  3645. #[cfg(all(feature = "socket-udp", feature = "proto-ipv4"))]
  3646. fn test_icmp_error_port_unreachable() {
  3647. static UDP_PAYLOAD: [u8; 12] = [
  3648. 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x6c, 0x64, 0x21,
  3649. ];
  3650. let (mut iface, mut sockets, _device) = create();
  3651. let mut udp_bytes_unicast = vec![0u8; 20];
  3652. let mut udp_bytes_broadcast = vec![0u8; 20];
  3653. let mut packet_unicast = UdpPacket::new_unchecked(&mut udp_bytes_unicast);
  3654. let mut packet_broadcast = UdpPacket::new_unchecked(&mut udp_bytes_broadcast);
  3655. let udp_repr = UdpRepr {
  3656. src_port: 67,
  3657. dst_port: 68,
  3658. };
  3659. let ip_repr = IpRepr::Ipv4(Ipv4Repr {
  3660. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  3661. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  3662. next_header: IpProtocol::Udp,
  3663. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  3664. hop_limit: 64,
  3665. });
  3666. // Emit the representations to a packet
  3667. udp_repr.emit(
  3668. &mut packet_unicast,
  3669. &ip_repr.src_addr(),
  3670. &ip_repr.dst_addr(),
  3671. UDP_PAYLOAD.len(),
  3672. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  3673. &ChecksumCapabilities::default(),
  3674. );
  3675. let data = packet_unicast.into_inner();
  3676. // The expected Destination Unreachable ICMPv4 error response due
  3677. // to no sockets listening on the destination port.
  3678. let icmp_repr = Icmpv4Repr::DstUnreachable {
  3679. reason: Icmpv4DstUnreachable::PortUnreachable,
  3680. header: Ipv4Repr {
  3681. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  3682. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  3683. next_header: IpProtocol::Udp,
  3684. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  3685. hop_limit: 64,
  3686. },
  3687. data,
  3688. };
  3689. let expected_repr = IpPacket::Icmpv4((
  3690. Ipv4Repr {
  3691. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  3692. dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  3693. next_header: IpProtocol::Icmp,
  3694. payload_len: icmp_repr.buffer_len(),
  3695. hop_limit: 64,
  3696. },
  3697. icmp_repr,
  3698. ));
  3699. // Ensure that the unknown protocol triggers an error response.
  3700. // And we correctly handle no payload.
  3701. assert_eq!(
  3702. iface.inner.process_udp(&mut sockets, ip_repr, false, data),
  3703. Some(expected_repr)
  3704. );
  3705. let ip_repr = IpRepr::Ipv4(Ipv4Repr {
  3706. src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
  3707. dst_addr: Ipv4Address::BROADCAST,
  3708. next_header: IpProtocol::Udp,
  3709. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  3710. hop_limit: 64,
  3711. });
  3712. // Emit the representations to a packet
  3713. udp_repr.emit(
  3714. &mut packet_broadcast,
  3715. &ip_repr.src_addr(),
  3716. &IpAddress::Ipv4(Ipv4Address::BROADCAST),
  3717. UDP_PAYLOAD.len(),
  3718. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  3719. &ChecksumCapabilities::default(),
  3720. );
  3721. // Ensure that the port unreachable error does not trigger an
  3722. // ICMP error response when the destination address is a
  3723. // broadcast address and no socket is bound to the port.
  3724. assert_eq!(
  3725. iface
  3726. .inner
  3727. .process_udp(&mut sockets, ip_repr, false, packet_broadcast.into_inner()),
  3728. None
  3729. );
  3730. }
  3731. #[test]
  3732. #[cfg(feature = "socket-udp")]
  3733. fn test_handle_udp_broadcast() {
  3734. use crate::wire::IpEndpoint;
  3735. static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];
  3736. let (mut iface, mut sockets, _device) = create();
  3737. let rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
  3738. let tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
  3739. let udp_socket = udp::Socket::new(rx_buffer, tx_buffer);
  3740. let mut udp_bytes = vec![0u8; 13];
  3741. let mut packet = UdpPacket::new_unchecked(&mut udp_bytes);
  3742. let socket_handle = sockets.add(udp_socket);
  3743. #[cfg(feature = "proto-ipv6")]
  3744. let src_ip = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
  3745. #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))]
  3746. let src_ip = Ipv4Address::new(0x7f, 0x00, 0x00, 0x02);
  3747. let udp_repr = UdpRepr {
  3748. src_port: 67,
  3749. dst_port: 68,
  3750. };
  3751. #[cfg(feature = "proto-ipv6")]
  3752. let ip_repr = IpRepr::Ipv6(Ipv6Repr {
  3753. src_addr: src_ip,
  3754. dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
  3755. next_header: IpProtocol::Udp,
  3756. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  3757. hop_limit: 0x40,
  3758. });
  3759. #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))]
  3760. let ip_repr = IpRepr::Ipv4(Ipv4Repr {
  3761. src_addr: src_ip,
  3762. dst_addr: Ipv4Address::BROADCAST,
  3763. next_header: IpProtocol::Udp,
  3764. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  3765. hop_limit: 0x40,
  3766. });
  3767. // Bind the socket to port 68
  3768. let socket = sockets.get_mut::<udp::Socket>(socket_handle);
  3769. assert_eq!(socket.bind(68), Ok(()));
  3770. assert!(!socket.can_recv());
  3771. assert!(socket.can_send());
  3772. udp_repr.emit(
  3773. &mut packet,
  3774. &ip_repr.src_addr(),
  3775. &ip_repr.dst_addr(),
  3776. UDP_PAYLOAD.len(),
  3777. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  3778. &ChecksumCapabilities::default(),
  3779. );
  3780. // Packet should be handled by bound UDP socket
  3781. assert_eq!(
  3782. iface
  3783. .inner
  3784. .process_udp(&mut sockets, ip_repr, false, packet.into_inner()),
  3785. None
  3786. );
  3787. // Make sure the payload to the UDP packet processed by process_udp is
  3788. // appended to the bound sockets rx_buffer
  3789. let socket = sockets.get_mut::<udp::Socket>(socket_handle);
  3790. assert!(socket.can_recv());
  3791. assert_eq!(
  3792. socket.recv(),
  3793. Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_ip.into(), 67)))
  3794. );
  3795. }
  3796. #[test]
  3797. #[cfg(feature = "proto-ipv4")]
  3798. fn test_handle_ipv4_broadcast() {
  3799. use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Packet};
  3800. let (mut iface, mut sockets, _device) = create();
  3801. let our_ipv4_addr = iface.ipv4_address().unwrap();
  3802. let src_ipv4_addr = Ipv4Address([127, 0, 0, 2]);
  3803. // ICMPv4 echo request
  3804. let icmpv4_data: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
  3805. let icmpv4_repr = Icmpv4Repr::EchoRequest {
  3806. ident: 0x1234,
  3807. seq_no: 0xabcd,
  3808. data: &icmpv4_data,
  3809. };
  3810. // Send to IPv4 broadcast address
  3811. let ipv4_repr = Ipv4Repr {
  3812. src_addr: src_ipv4_addr,
  3813. dst_addr: Ipv4Address::BROADCAST,
  3814. next_header: IpProtocol::Icmp,
  3815. hop_limit: 64,
  3816. payload_len: icmpv4_repr.buffer_len(),
  3817. };
  3818. // Emit to ip frame
  3819. let mut bytes = vec![0u8; ipv4_repr.buffer_len() + icmpv4_repr.buffer_len()];
  3820. let frame = {
  3821. ipv4_repr.emit(
  3822. &mut Ipv4Packet::new_unchecked(&mut bytes),
  3823. &ChecksumCapabilities::default(),
  3824. );
  3825. icmpv4_repr.emit(
  3826. &mut Icmpv4Packet::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
  3827. &ChecksumCapabilities::default(),
  3828. );
  3829. Ipv4Packet::new_unchecked(&bytes)
  3830. };
  3831. // Expected ICMPv4 echo reply
  3832. let expected_icmpv4_repr = Icmpv4Repr::EchoReply {
  3833. ident: 0x1234,
  3834. seq_no: 0xabcd,
  3835. data: &icmpv4_data,
  3836. };
  3837. let expected_ipv4_repr = Ipv4Repr {
  3838. src_addr: our_ipv4_addr,
  3839. dst_addr: src_ipv4_addr,
  3840. next_header: IpProtocol::Icmp,
  3841. hop_limit: 64,
  3842. payload_len: expected_icmpv4_repr.buffer_len(),
  3843. };
  3844. let expected_packet = IpPacket::Icmpv4((expected_ipv4_repr, expected_icmpv4_repr));
  3845. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  3846. assert_eq!(
  3847. iface.inner.process_ipv4(&mut sockets, &frame, None),
  3848. Some(expected_packet)
  3849. );
  3850. #[cfg(feature = "proto-ipv4-fragmentation")]
  3851. assert_eq!(
  3852. iface.inner.process_ipv4(
  3853. &mut sockets,
  3854. &frame,
  3855. Some(&mut iface.fragments.ipv4_fragments)
  3856. ),
  3857. Some(expected_packet)
  3858. );
  3859. }
  3860. #[test]
  3861. #[cfg(feature = "socket-udp")]
  3862. fn test_icmp_reply_size() {
  3863. #[cfg(feature = "proto-ipv6")]
  3864. use crate::wire::Icmpv6DstUnreachable;
  3865. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3866. use crate::wire::IPV4_MIN_MTU as MIN_MTU;
  3867. #[cfg(feature = "proto-ipv6")]
  3868. use crate::wire::IPV6_MIN_MTU as MIN_MTU;
  3869. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3870. const MAX_PAYLOAD_LEN: usize = 528;
  3871. #[cfg(feature = "proto-ipv6")]
  3872. const MAX_PAYLOAD_LEN: usize = 1192;
  3873. let (mut iface, mut sockets, _device) = create();
  3874. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3875. let src_addr = Ipv4Address([192, 168, 1, 1]);
  3876. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3877. let dst_addr = Ipv4Address([192, 168, 1, 2]);
  3878. #[cfg(feature = "proto-ipv6")]
  3879. let src_addr = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
  3880. #[cfg(feature = "proto-ipv6")]
  3881. let dst_addr = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
  3882. // UDP packet that if not tructated will cause a icmp port unreachable reply
  3883. // to exeed the minimum mtu bytes in length.
  3884. let udp_repr = UdpRepr {
  3885. src_port: 67,
  3886. dst_port: 68,
  3887. };
  3888. let mut bytes = vec![0xff; udp_repr.header_len() + MAX_PAYLOAD_LEN];
  3889. let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
  3890. udp_repr.emit(
  3891. &mut packet,
  3892. &src_addr.into(),
  3893. &dst_addr.into(),
  3894. MAX_PAYLOAD_LEN,
  3895. |buf| fill_slice(buf, 0x2a),
  3896. &ChecksumCapabilities::default(),
  3897. );
  3898. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3899. let ip_repr = Ipv4Repr {
  3900. src_addr,
  3901. dst_addr,
  3902. next_header: IpProtocol::Udp,
  3903. hop_limit: 64,
  3904. payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN,
  3905. };
  3906. #[cfg(feature = "proto-ipv6")]
  3907. let ip_repr = Ipv6Repr {
  3908. src_addr,
  3909. dst_addr,
  3910. next_header: IpProtocol::Udp,
  3911. hop_limit: 64,
  3912. payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN,
  3913. };
  3914. let payload = packet.into_inner();
  3915. // Expected packets
  3916. #[cfg(feature = "proto-ipv6")]
  3917. let expected_icmp_repr = Icmpv6Repr::DstUnreachable {
  3918. reason: Icmpv6DstUnreachable::PortUnreachable,
  3919. header: ip_repr,
  3920. data: &payload[..MAX_PAYLOAD_LEN],
  3921. };
  3922. #[cfg(feature = "proto-ipv6")]
  3923. let expected_ip_repr = Ipv6Repr {
  3924. src_addr: dst_addr,
  3925. dst_addr: src_addr,
  3926. next_header: IpProtocol::Icmpv6,
  3927. hop_limit: 64,
  3928. payload_len: expected_icmp_repr.buffer_len(),
  3929. };
  3930. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3931. let expected_icmp_repr = Icmpv4Repr::DstUnreachable {
  3932. reason: Icmpv4DstUnreachable::PortUnreachable,
  3933. header: ip_repr,
  3934. data: &payload[..MAX_PAYLOAD_LEN],
  3935. };
  3936. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3937. let expected_ip_repr = Ipv4Repr {
  3938. src_addr: dst_addr,
  3939. dst_addr: src_addr,
  3940. next_header: IpProtocol::Icmp,
  3941. hop_limit: 64,
  3942. payload_len: expected_icmp_repr.buffer_len(),
  3943. };
  3944. // The expected packet does not exceed the IPV4_MIN_MTU
  3945. #[cfg(feature = "proto-ipv6")]
  3946. assert_eq!(
  3947. expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(),
  3948. MIN_MTU
  3949. );
  3950. // The expected packet does not exceed the IPV4_MIN_MTU
  3951. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3952. assert_eq!(
  3953. expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(),
  3954. MIN_MTU
  3955. );
  3956. // The expected packet and the generated packet are equal
  3957. #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
  3958. assert_eq!(
  3959. iface
  3960. .inner
  3961. .process_udp(&mut sockets, ip_repr.into(), false, payload),
  3962. Some(IpPacket::Icmpv4((expected_ip_repr, expected_icmp_repr)))
  3963. );
  3964. #[cfg(feature = "proto-ipv6")]
  3965. assert_eq!(
  3966. iface
  3967. .inner
  3968. .process_udp(&mut sockets, ip_repr.into(), false, payload),
  3969. Some(IpPacket::Icmpv6((expected_ip_repr, expected_icmp_repr)))
  3970. );
  3971. }
  3972. #[test]
  3973. #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
  3974. fn test_handle_valid_arp_request() {
  3975. let (mut iface, mut sockets, _device) = create_ethernet();
  3976. let mut eth_bytes = vec![0u8; 42];
  3977. let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
  3978. let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
  3979. let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  3980. let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
  3981. let repr = ArpRepr::EthernetIpv4 {
  3982. operation: ArpOperation::Request,
  3983. source_hardware_addr: remote_hw_addr,
  3984. source_protocol_addr: remote_ip_addr,
  3985. target_hardware_addr: EthernetAddress::default(),
  3986. target_protocol_addr: local_ip_addr,
  3987. };
  3988. let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
  3989. frame.set_dst_addr(EthernetAddress::BROADCAST);
  3990. frame.set_src_addr(remote_hw_addr);
  3991. frame.set_ethertype(EthernetProtocol::Arp);
  3992. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  3993. repr.emit(&mut packet);
  3994. // Ensure an ARP Request for us triggers an ARP Reply
  3995. assert_eq!(
  3996. iface
  3997. .inner
  3998. .process_ethernet(&mut sockets, frame.into_inner(), &mut iface.fragments),
  3999. Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 {
  4000. operation: ArpOperation::Reply,
  4001. source_hardware_addr: local_hw_addr,
  4002. source_protocol_addr: local_ip_addr,
  4003. target_hardware_addr: remote_hw_addr,
  4004. target_protocol_addr: remote_ip_addr
  4005. }))
  4006. );
  4007. // Ensure the address of the requestor was entered in the cache
  4008. assert_eq!(
  4009. iface.inner.lookup_hardware_addr(
  4010. MockTxToken,
  4011. &IpAddress::Ipv4(local_ip_addr),
  4012. &IpAddress::Ipv4(remote_ip_addr)
  4013. ),
  4014. Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
  4015. );
  4016. }
  4017. #[test]
  4018. #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv6"))]
  4019. fn test_handle_valid_ndisc_request() {
  4020. let (mut iface, mut sockets, _device) = create_ethernet();
  4021. let mut eth_bytes = vec![0u8; 86];
  4022. let local_ip_addr = Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 1);
  4023. let remote_ip_addr = Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 2);
  4024. let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  4025. let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
  4026. let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit {
  4027. target_addr: local_ip_addr,
  4028. lladdr: Some(remote_hw_addr.into()),
  4029. });
  4030. let ip_repr = IpRepr::Ipv6(Ipv6Repr {
  4031. src_addr: remote_ip_addr,
  4032. dst_addr: local_ip_addr.solicited_node(),
  4033. next_header: IpProtocol::Icmpv6,
  4034. hop_limit: 0xff,
  4035. payload_len: solicit.buffer_len(),
  4036. });
  4037. let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
  4038. frame.set_dst_addr(EthernetAddress([0x33, 0x33, 0x00, 0x00, 0x00, 0x00]));
  4039. frame.set_src_addr(remote_hw_addr);
  4040. frame.set_ethertype(EthernetProtocol::Ipv6);
  4041. ip_repr.emit(frame.payload_mut(), &ChecksumCapabilities::default());
  4042. solicit.emit(
  4043. &remote_ip_addr.into(),
  4044. &local_ip_addr.solicited_node().into(),
  4045. &mut Icmpv6Packet::new_unchecked(&mut frame.payload_mut()[ip_repr.header_len()..]),
  4046. &ChecksumCapabilities::default(),
  4047. );
  4048. let icmpv6_expected = Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
  4049. flags: NdiscNeighborFlags::SOLICITED,
  4050. target_addr: local_ip_addr,
  4051. lladdr: Some(local_hw_addr.into()),
  4052. });
  4053. let ipv6_expected = Ipv6Repr {
  4054. src_addr: local_ip_addr,
  4055. dst_addr: remote_ip_addr,
  4056. next_header: IpProtocol::Icmpv6,
  4057. hop_limit: 0xff,
  4058. payload_len: icmpv6_expected.buffer_len(),
  4059. };
  4060. // Ensure an Neighbor Solicitation triggers a Neighbor Advertisement
  4061. assert_eq!(
  4062. iface
  4063. .inner
  4064. .process_ethernet(&mut sockets, frame.into_inner(), &mut iface.fragments),
  4065. Some(EthernetPacket::Ip(IpPacket::Icmpv6((
  4066. ipv6_expected,
  4067. icmpv6_expected
  4068. ))))
  4069. );
  4070. // Ensure the address of the requestor was entered in the cache
  4071. assert_eq!(
  4072. iface.inner.lookup_hardware_addr(
  4073. MockTxToken,
  4074. &IpAddress::Ipv6(local_ip_addr),
  4075. &IpAddress::Ipv6(remote_ip_addr)
  4076. ),
  4077. Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
  4078. );
  4079. }
  4080. #[test]
  4081. #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
  4082. fn test_handle_other_arp_request() {
  4083. let (mut iface, mut sockets, _device) = create_ethernet();
  4084. let mut eth_bytes = vec![0u8; 42];
  4085. let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
  4086. let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
  4087. let repr = ArpRepr::EthernetIpv4 {
  4088. operation: ArpOperation::Request,
  4089. source_hardware_addr: remote_hw_addr,
  4090. source_protocol_addr: remote_ip_addr,
  4091. target_hardware_addr: EthernetAddress::default(),
  4092. target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x03]),
  4093. };
  4094. let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
  4095. frame.set_dst_addr(EthernetAddress::BROADCAST);
  4096. frame.set_src_addr(remote_hw_addr);
  4097. frame.set_ethertype(EthernetProtocol::Arp);
  4098. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  4099. repr.emit(&mut packet);
  4100. // Ensure an ARP Request for someone else does not trigger an ARP Reply
  4101. assert_eq!(
  4102. iface
  4103. .inner
  4104. .process_ethernet(&mut sockets, frame.into_inner(), &mut iface.fragments),
  4105. None
  4106. );
  4107. // Ensure the address of the requestor was NOT entered in the cache
  4108. assert_eq!(
  4109. iface.inner.lookup_hardware_addr(
  4110. MockTxToken,
  4111. &IpAddress::Ipv4(Ipv4Address([0x7f, 0x00, 0x00, 0x01])),
  4112. &IpAddress::Ipv4(remote_ip_addr)
  4113. ),
  4114. Err(Error::Unaddressable)
  4115. );
  4116. }
  4117. #[test]
  4118. #[cfg(all(
  4119. feature = "medium-ethernet",
  4120. feature = "proto-ipv4",
  4121. not(feature = "medium-ieee802154")
  4122. ))]
  4123. fn test_arp_flush_after_update_ip() {
  4124. let (mut iface, mut sockets, _device) = create_ethernet();
  4125. let mut eth_bytes = vec![0u8; 42];
  4126. let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
  4127. let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
  4128. let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  4129. let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
  4130. let repr = ArpRepr::EthernetIpv4 {
  4131. operation: ArpOperation::Request,
  4132. source_hardware_addr: remote_hw_addr,
  4133. source_protocol_addr: remote_ip_addr,
  4134. target_hardware_addr: EthernetAddress::default(),
  4135. target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
  4136. };
  4137. let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
  4138. frame.set_dst_addr(EthernetAddress::BROADCAST);
  4139. frame.set_src_addr(remote_hw_addr);
  4140. frame.set_ethertype(EthernetProtocol::Arp);
  4141. {
  4142. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  4143. repr.emit(&mut packet);
  4144. }
  4145. // Ensure an ARP Request for us triggers an ARP Reply
  4146. assert_eq!(
  4147. iface
  4148. .inner
  4149. .process_ethernet(&mut sockets, frame.into_inner(), &mut iface.fragments),
  4150. Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 {
  4151. operation: ArpOperation::Reply,
  4152. source_hardware_addr: local_hw_addr,
  4153. source_protocol_addr: local_ip_addr,
  4154. target_hardware_addr: remote_hw_addr,
  4155. target_protocol_addr: remote_ip_addr
  4156. }))
  4157. );
  4158. // Ensure the address of the requestor was entered in the cache
  4159. assert_eq!(
  4160. iface.inner.lookup_hardware_addr(
  4161. MockTxToken,
  4162. &IpAddress::Ipv4(local_ip_addr),
  4163. &IpAddress::Ipv4(remote_ip_addr)
  4164. ),
  4165. Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
  4166. );
  4167. // Update IP addrs to trigger ARP cache flush
  4168. let local_ip_addr_new = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
  4169. iface.update_ip_addrs(|addrs| {
  4170. addrs.iter_mut().next().map(|addr| {
  4171. *addr = IpCidr::Ipv4(Ipv4Cidr::new(local_ip_addr_new, 24));
  4172. });
  4173. });
  4174. // ARP cache flush after address change
  4175. assert!(!iface.inner.has_neighbor(&IpAddress::Ipv4(remote_ip_addr)));
  4176. }
  4177. #[test]
  4178. #[cfg(all(feature = "socket-icmp", feature = "proto-ipv4"))]
  4179. fn test_icmpv4_socket() {
  4180. use crate::wire::Icmpv4Packet;
  4181. let (mut iface, mut sockets, _device) = create();
  4182. let rx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 24]);
  4183. let tx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 24]);
  4184. let icmpv4_socket = icmp::Socket::new(rx_buffer, tx_buffer);
  4185. let socket_handle = sockets.add(icmpv4_socket);
  4186. let ident = 0x1234;
  4187. let seq_no = 0x5432;
  4188. let echo_data = &[0xff; 16];
  4189. let socket = sockets.get_mut::<icmp::Socket>(socket_handle);
  4190. // Bind to the ID 0x1234
  4191. assert_eq!(socket.bind(icmp::Endpoint::Ident(ident)), Ok(()));
  4192. // Ensure the ident we bound to and the ident of the packet are the same.
  4193. let mut bytes = [0xff; 24];
  4194. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
  4195. let echo_repr = Icmpv4Repr::EchoRequest {
  4196. ident,
  4197. seq_no,
  4198. data: echo_data,
  4199. };
  4200. echo_repr.emit(&mut packet, &ChecksumCapabilities::default());
  4201. let icmp_data = &*packet.into_inner();
  4202. let ipv4_repr = Ipv4Repr {
  4203. src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02),
  4204. dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01),
  4205. next_header: IpProtocol::Icmp,
  4206. payload_len: 24,
  4207. hop_limit: 64,
  4208. };
  4209. let ip_repr = IpRepr::Ipv4(ipv4_repr);
  4210. // Open a socket and ensure the packet is handled due to the listening
  4211. // socket.
  4212. assert!(!sockets.get_mut::<icmp::Socket>(socket_handle).can_recv());
  4213. // Confirm we still get EchoReply from `smoltcp` even with the ICMP socket listening
  4214. let echo_reply = Icmpv4Repr::EchoReply {
  4215. ident,
  4216. seq_no,
  4217. data: echo_data,
  4218. };
  4219. let ipv4_reply = Ipv4Repr {
  4220. src_addr: ipv4_repr.dst_addr,
  4221. dst_addr: ipv4_repr.src_addr,
  4222. ..ipv4_repr
  4223. };
  4224. assert_eq!(
  4225. iface.inner.process_icmpv4(&mut sockets, ip_repr, icmp_data),
  4226. Some(IpPacket::Icmpv4((ipv4_reply, echo_reply)))
  4227. );
  4228. let socket = sockets.get_mut::<icmp::Socket>(socket_handle);
  4229. assert!(socket.can_recv());
  4230. assert_eq!(
  4231. socket.recv(),
  4232. Ok((
  4233. icmp_data,
  4234. IpAddress::Ipv4(Ipv4Address::new(0x7f, 0x00, 0x00, 0x02))
  4235. ))
  4236. );
  4237. }
  4238. #[test]
  4239. #[cfg(feature = "proto-ipv6")]
  4240. fn test_solicited_node_addrs() {
  4241. let (mut iface, _, _device) = create();
  4242. let mut new_addrs = vec![
  4243. IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 1, 2, 0, 2), 64),
  4244. IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 3, 4, 0, 0xffff), 64),
  4245. ];
  4246. iface.update_ip_addrs(|addrs| {
  4247. new_addrs.extend(addrs.to_vec());
  4248. *addrs = From::from(new_addrs);
  4249. });
  4250. assert!(iface
  4251. .inner
  4252. .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0002)));
  4253. assert!(iface
  4254. .inner
  4255. .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0xffff)));
  4256. assert!(!iface
  4257. .inner
  4258. .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0003)));
  4259. }
  4260. #[test]
  4261. #[cfg(feature = "proto-ipv6")]
  4262. fn test_icmpv6_nxthdr_unknown() {
  4263. let (mut iface, mut sockets, _device) = create();
  4264. let remote_ip_addr = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
  4265. let payload = [0x12, 0x34, 0x56, 0x78];
  4266. let ipv6_repr = Ipv6Repr {
  4267. src_addr: remote_ip_addr,
  4268. dst_addr: Ipv6Address::LOOPBACK,
  4269. next_header: IpProtocol::HopByHop,
  4270. payload_len: 12,
  4271. hop_limit: 0x40,
  4272. };
  4273. let mut bytes = vec![0; 52];
  4274. let frame = {
  4275. let ip_repr = IpRepr::Ipv6(ipv6_repr);
  4276. ip_repr.emit(&mut bytes, &ChecksumCapabilities::default());
  4277. let mut offset = ipv6_repr.buffer_len();
  4278. {
  4279. let mut hbh_pkt = Ipv6HopByHopHeader::new_unchecked(&mut bytes[offset..]);
  4280. hbh_pkt.set_next_header(IpProtocol::Unknown(0x0c));
  4281. hbh_pkt.set_header_len(0);
  4282. offset += 8;
  4283. {
  4284. let mut pad_pkt = Ipv6Option::new_unchecked(&mut *hbh_pkt.options_mut());
  4285. Ipv6OptionRepr::PadN(3).emit(&mut pad_pkt);
  4286. }
  4287. {
  4288. let mut pad_pkt = Ipv6Option::new_unchecked(&mut hbh_pkt.options_mut()[5..]);
  4289. Ipv6OptionRepr::Pad1.emit(&mut pad_pkt);
  4290. }
  4291. }
  4292. bytes[offset..].copy_from_slice(&payload);
  4293. Ipv6Packet::new_unchecked(&bytes)
  4294. };
  4295. let reply_icmp_repr = Icmpv6Repr::ParamProblem {
  4296. reason: Icmpv6ParamProblem::UnrecognizedNxtHdr,
  4297. pointer: 40,
  4298. header: ipv6_repr,
  4299. data: &payload[..],
  4300. };
  4301. let reply_ipv6_repr = Ipv6Repr {
  4302. src_addr: Ipv6Address::LOOPBACK,
  4303. dst_addr: remote_ip_addr,
  4304. next_header: IpProtocol::Icmpv6,
  4305. payload_len: reply_icmp_repr.buffer_len(),
  4306. hop_limit: 0x40,
  4307. };
  4308. // Ensure the unknown next header causes a ICMPv6 Parameter Problem
  4309. // error message to be sent to the sender.
  4310. assert_eq!(
  4311. iface.inner.process_ipv6(&mut sockets, &frame),
  4312. Some(IpPacket::Icmpv6((reply_ipv6_repr, reply_icmp_repr)))
  4313. );
  4314. }
  4315. #[test]
  4316. #[cfg(feature = "proto-igmp")]
  4317. fn test_handle_igmp() {
  4318. fn recv_igmp(device: &mut Loopback, timestamp: Instant) -> Vec<(Ipv4Repr, IgmpRepr)> {
  4319. let caps = device.capabilities();
  4320. let checksum_caps = &caps.checksum;
  4321. recv_all(device, timestamp)
  4322. .iter()
  4323. .filter_map(|frame| {
  4324. let ipv4_packet = match caps.medium {
  4325. #[cfg(feature = "medium-ethernet")]
  4326. Medium::Ethernet => {
  4327. let eth_frame = EthernetFrame::new_checked(frame).ok()?;
  4328. Ipv4Packet::new_checked(eth_frame.payload()).ok()?
  4329. }
  4330. #[cfg(feature = "medium-ip")]
  4331. Medium::Ip => Ipv4Packet::new_checked(&frame[..]).ok()?,
  4332. #[cfg(feature = "medium-ieee802154")]
  4333. Medium::Ieee802154 => todo!(),
  4334. };
  4335. let ipv4_repr = Ipv4Repr::parse(&ipv4_packet, checksum_caps).ok()?;
  4336. let ip_payload = ipv4_packet.payload();
  4337. let igmp_packet = IgmpPacket::new_checked(ip_payload).ok()?;
  4338. let igmp_repr = IgmpRepr::parse(&igmp_packet).ok()?;
  4339. Some((ipv4_repr, igmp_repr))
  4340. })
  4341. .collect::<Vec<_>>()
  4342. }
  4343. let groups = [
  4344. Ipv4Address::new(224, 0, 0, 22),
  4345. Ipv4Address::new(224, 0, 0, 56),
  4346. ];
  4347. let (mut iface, mut sockets, mut device) = create();
  4348. // Join multicast groups
  4349. let timestamp = Instant::now();
  4350. for group in &groups {
  4351. iface
  4352. .join_multicast_group(&mut device, *group, timestamp)
  4353. .unwrap();
  4354. }
  4355. let reports = recv_igmp(&mut device, timestamp);
  4356. assert_eq!(reports.len(), 2);
  4357. for (i, group_addr) in groups.iter().enumerate() {
  4358. assert_eq!(reports[i].0.next_header, IpProtocol::Igmp);
  4359. assert_eq!(reports[i].0.dst_addr, *group_addr);
  4360. assert_eq!(
  4361. reports[i].1,
  4362. IgmpRepr::MembershipReport {
  4363. group_addr: *group_addr,
  4364. version: IgmpVersion::Version2,
  4365. }
  4366. );
  4367. }
  4368. // General query
  4369. let timestamp = Instant::now();
  4370. const GENERAL_QUERY_BYTES: &[u8] = &[
  4371. 0x46, 0xc0, 0x00, 0x24, 0xed, 0xb4, 0x00, 0x00, 0x01, 0x02, 0x47, 0x43, 0xac, 0x16,
  4372. 0x63, 0x04, 0xe0, 0x00, 0x00, 0x01, 0x94, 0x04, 0x00, 0x00, 0x11, 0x64, 0xec, 0x8f,
  4373. 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  4374. 0x00, 0x00, 0x00, 0x00,
  4375. ];
  4376. {
  4377. // Transmit GENERAL_QUERY_BYTES into loopback
  4378. let tx_token = device.transmit().unwrap();
  4379. tx_token
  4380. .consume(timestamp, GENERAL_QUERY_BYTES.len(), |buffer| {
  4381. buffer.copy_from_slice(GENERAL_QUERY_BYTES);
  4382. Ok(())
  4383. })
  4384. .unwrap();
  4385. }
  4386. // Trigger processing until all packets received through the
  4387. // loopback have been processed, including responses to
  4388. // GENERAL_QUERY_BYTES. Therefore `recv_all()` would return 0
  4389. // pkts that could be checked.
  4390. iface.socket_ingress(&mut device, &mut sockets);
  4391. // Leave multicast groups
  4392. let timestamp = Instant::now();
  4393. for group in &groups {
  4394. iface
  4395. .leave_multicast_group(&mut device, *group, timestamp)
  4396. .unwrap();
  4397. }
  4398. let leaves = recv_igmp(&mut device, timestamp);
  4399. assert_eq!(leaves.len(), 2);
  4400. for (i, group_addr) in groups.iter().cloned().enumerate() {
  4401. assert_eq!(leaves[i].0.next_header, IpProtocol::Igmp);
  4402. assert_eq!(leaves[i].0.dst_addr, Ipv4Address::MULTICAST_ALL_ROUTERS);
  4403. assert_eq!(leaves[i].1, IgmpRepr::LeaveGroup { group_addr });
  4404. }
  4405. }
  4406. #[test]
  4407. #[cfg(all(feature = "proto-ipv4", feature = "socket-raw"))]
  4408. fn test_raw_socket_no_reply() {
  4409. use crate::wire::{IpVersion, Ipv4Packet, UdpPacket, UdpRepr};
  4410. let (mut iface, mut sockets, _device) = create();
  4411. let packets = 1;
  4412. let rx_buffer =
  4413. raw::PacketBuffer::new(vec![raw::PacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
  4414. let tx_buffer = raw::PacketBuffer::new(
  4415. vec![raw::PacketMetadata::EMPTY; packets],
  4416. vec![0; 48 * packets],
  4417. );
  4418. let raw_socket = raw::Socket::new(IpVersion::Ipv4, IpProtocol::Udp, rx_buffer, tx_buffer);
  4419. sockets.add(raw_socket);
  4420. let src_addr = Ipv4Address([127, 0, 0, 2]);
  4421. let dst_addr = Ipv4Address([127, 0, 0, 1]);
  4422. const PAYLOAD_LEN: usize = 10;
  4423. let udp_repr = UdpRepr {
  4424. src_port: 67,
  4425. dst_port: 68,
  4426. };
  4427. let mut bytes = vec![0xff; udp_repr.header_len() + PAYLOAD_LEN];
  4428. let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
  4429. udp_repr.emit(
  4430. &mut packet,
  4431. &src_addr.into(),
  4432. &dst_addr.into(),
  4433. PAYLOAD_LEN,
  4434. |buf| fill_slice(buf, 0x2a),
  4435. &ChecksumCapabilities::default(),
  4436. );
  4437. let ipv4_repr = Ipv4Repr {
  4438. src_addr,
  4439. dst_addr,
  4440. next_header: IpProtocol::Udp,
  4441. hop_limit: 64,
  4442. payload_len: udp_repr.header_len() + PAYLOAD_LEN,
  4443. };
  4444. // Emit to frame
  4445. let mut bytes = vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + PAYLOAD_LEN];
  4446. let frame = {
  4447. ipv4_repr.emit(
  4448. &mut Ipv4Packet::new_unchecked(&mut bytes),
  4449. &ChecksumCapabilities::default(),
  4450. );
  4451. udp_repr.emit(
  4452. &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
  4453. &src_addr.into(),
  4454. &dst_addr.into(),
  4455. PAYLOAD_LEN,
  4456. |buf| fill_slice(buf, 0x2a),
  4457. &ChecksumCapabilities::default(),
  4458. );
  4459. Ipv4Packet::new_unchecked(&bytes)
  4460. };
  4461. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  4462. assert_eq!(iface.inner.process_ipv4(&mut sockets, &frame, None), None);
  4463. #[cfg(feature = "proto-ipv4-fragmentation")]
  4464. assert_eq!(
  4465. iface.inner.process_ipv4(
  4466. &mut sockets,
  4467. &frame,
  4468. Some(&mut iface.fragments.ipv4_fragments)
  4469. ),
  4470. None
  4471. );
  4472. }
  4473. #[test]
  4474. #[cfg(all(feature = "proto-ipv4", feature = "socket-raw", feature = "socket-udp"))]
  4475. fn test_raw_socket_with_udp_socket() {
  4476. use crate::wire::{IpEndpoint, IpVersion, Ipv4Packet, UdpPacket, UdpRepr};
  4477. static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];
  4478. let (mut iface, mut sockets, _device) = create();
  4479. let udp_rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
  4480. let udp_tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
  4481. let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
  4482. let udp_socket_handle = sockets.add(udp_socket);
  4483. // Bind the socket to port 68
  4484. let socket = sockets.get_mut::<udp::Socket>(udp_socket_handle);
  4485. assert_eq!(socket.bind(68), Ok(()));
  4486. assert!(!socket.can_recv());
  4487. assert!(socket.can_send());
  4488. let packets = 1;
  4489. let raw_rx_buffer =
  4490. raw::PacketBuffer::new(vec![raw::PacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
  4491. let raw_tx_buffer = raw::PacketBuffer::new(
  4492. vec![raw::PacketMetadata::EMPTY; packets],
  4493. vec![0; 48 * packets],
  4494. );
  4495. let raw_socket = raw::Socket::new(
  4496. IpVersion::Ipv4,
  4497. IpProtocol::Udp,
  4498. raw_rx_buffer,
  4499. raw_tx_buffer,
  4500. );
  4501. sockets.add(raw_socket);
  4502. let src_addr = Ipv4Address([127, 0, 0, 2]);
  4503. let dst_addr = Ipv4Address([127, 0, 0, 1]);
  4504. let udp_repr = UdpRepr {
  4505. src_port: 67,
  4506. dst_port: 68,
  4507. };
  4508. let mut bytes = vec![0xff; udp_repr.header_len() + UDP_PAYLOAD.len()];
  4509. let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
  4510. udp_repr.emit(
  4511. &mut packet,
  4512. &src_addr.into(),
  4513. &dst_addr.into(),
  4514. UDP_PAYLOAD.len(),
  4515. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  4516. &ChecksumCapabilities::default(),
  4517. );
  4518. let ipv4_repr = Ipv4Repr {
  4519. src_addr,
  4520. dst_addr,
  4521. next_header: IpProtocol::Udp,
  4522. hop_limit: 64,
  4523. payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
  4524. };
  4525. // Emit to frame
  4526. let mut bytes =
  4527. vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + UDP_PAYLOAD.len()];
  4528. let frame = {
  4529. ipv4_repr.emit(
  4530. &mut Ipv4Packet::new_unchecked(&mut bytes),
  4531. &ChecksumCapabilities::default(),
  4532. );
  4533. udp_repr.emit(
  4534. &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
  4535. &src_addr.into(),
  4536. &dst_addr.into(),
  4537. UDP_PAYLOAD.len(),
  4538. |buf| buf.copy_from_slice(&UDP_PAYLOAD),
  4539. &ChecksumCapabilities::default(),
  4540. );
  4541. Ipv4Packet::new_unchecked(&bytes)
  4542. };
  4543. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  4544. assert_eq!(iface.inner.process_ipv4(&mut sockets, &frame, None), None);
  4545. #[cfg(feature = "proto-ipv4-fragmentation")]
  4546. assert_eq!(
  4547. iface.inner.process_ipv4(
  4548. &mut sockets,
  4549. &frame,
  4550. Some(&mut iface.fragments.ipv4_fragments)
  4551. ),
  4552. None
  4553. );
  4554. // Make sure the UDP socket can still receive in presence of a Raw socket that handles UDP
  4555. let socket = sockets.get_mut::<udp::Socket>(udp_socket_handle);
  4556. assert!(socket.can_recv());
  4557. assert_eq!(
  4558. socket.recv(),
  4559. Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_addr.into(), 67)))
  4560. );
  4561. }
  4562. }