addr.c 129 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. addr.c
  5. Abstract:
  6. This module implements generic Network layer functionality, largely
  7. addressing.
  8. Author:
  9. Evan Green 4-Apr-2013
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/driver.h>
  17. #include "netcore.h"
  18. #include "arp.h"
  19. #include "dhcp.h"
  20. //
  21. // --------------------------------------------------------------------- Macros
  22. //
  23. //
  24. // This macro determines whether or not reuse of the any address is allowed
  25. // between the two sockets.
  26. //
  27. #define CAN_REUSE_ANY_ADDRESS(_NewSocket, _OldSocket) \
  28. ((((_NewSocket)->Flags & NET_SOCKET_FLAG_REUSE_ANY_ADDRESS) != 0) && \
  29. (((_OldSocket)->Flags & NET_SOCKET_FLAG_REUSE_ANY_ADDRESS) != 0))
  30. //
  31. // This macro determines whether or not reuse of the exact address is allowed
  32. // between the two sockets.
  33. //
  34. #define CAN_REUSE_EXACT_ADDRESS(_NewSocket, _OldSocket) \
  35. ((((_NewSocket)->Flags & NET_SOCKET_FLAG_REUSE_EXACT_ADDRESS) != 0) && \
  36. (((_OldSocket)->Flags & NET_SOCKET_FLAG_REUSE_EXACT_ADDRESS) != 0))
  37. //
  38. // This macro determines whether or not reuse of the exact address in the time
  39. // wait state is allowed between the two sockets.
  40. //
  41. #define CAN_REUSE_TIME_WAIT(_NewSocket, _OldSocket) \
  42. ((((_OldSocket)->Flags & NET_SOCKET_FLAG_TIME_WAIT) != 0) && \
  43. (((_NewSocket)->Flags & NET_SOCKET_FLAG_REUSE_TIME_WAIT) != 0) && \
  44. (((_OldSocket)->Flags & NET_SOCKET_FLAG_REUSE_TIME_WAIT) != 0))
  45. //
  46. // ---------------------------------------------------------------- Definitions
  47. //
  48. //
  49. // Define the amount of time to wait for an address translation to come back,
  50. // in milliseconds.
  51. //
  52. #define ADDRESS_TRANSLATION_TIMEOUT (5 * MILLISECONDS_PER_SECOND)
  53. #define ADDRESS_TRANSLATION_RETRY_INTERVAL MILLISECONDS_PER_SECOND
  54. //
  55. // Define the ephemeral port range.
  56. //
  57. #define NET_EPHEMERAL_PORT_START 49152
  58. #define NET_EPHEMERAL_PORT_END 65536
  59. #define NET_EPHEMERAL_PORT_COUNT \
  60. (NET_EPHEMERAL_PORT_END - NET_EPHEMERAL_PORT_START)
  61. //
  62. // ------------------------------------------------------ Data Type Definitions
  63. //
  64. /*++
  65. Structure Description:
  66. This structure defines a translation between a network address and a
  67. physical one.
  68. Members:
  69. TreeEntry - Stores the red black tree information for this node.
  70. NetworkAddress - Stores the network address, the key for the red black
  71. tree node.
  72. PhysicalAddress - Stores the physical address that corresponds to the
  73. network address.
  74. --*/
  75. typedef struct _ADDRESS_TRANSLATION_ENTRY {
  76. RED_BLACK_TREE_NODE TreeEntry;
  77. NETWORK_ADDRESS NetworkAddress;
  78. NETWORK_ADDRESS PhysicalAddress;
  79. } ADDRESS_TRANSLATION_ENTRY, *PADDRESS_TRANSLATION_ENTRY;
  80. //
  81. // ----------------------------------------------- Internal Function Prototypes
  82. //
  83. VOID
  84. NetpDestroyLink (
  85. PNET_LINK Link
  86. );
  87. VOID
  88. NetpDeactivateSocketUnlocked (
  89. PNET_SOCKET Socket
  90. );
  91. VOID
  92. NetpDeactivateRawSocketUnlocked (
  93. PNET_SOCKET Socket
  94. );
  95. VOID
  96. NetpDetachSockets (
  97. PNET_LINK Link,
  98. PNET_LINK_ADDRESS_ENTRY LinkAddress
  99. );
  100. VOID
  101. NetpDetachSocket (
  102. PNET_SOCKET Socket
  103. );
  104. VOID
  105. NetpDetachRawSocket (
  106. PNET_SOCKET Socket
  107. );
  108. KSTATUS
  109. NetpBindRawSocket (
  110. PNET_SOCKET Socket,
  111. NET_SOCKET_BINDING_TYPE BindingType,
  112. PNET_LINK_LOCAL_ADDRESS LocalInformation,
  113. PNETWORK_ADDRESS RemoteAddress,
  114. ULONG Flags
  115. );
  116. KSTATUS
  117. NetpLookupAddressTranslation (
  118. PNET_LINK Link,
  119. PNETWORK_ADDRESS NetworkAddress,
  120. PNETWORK_ADDRESS PhysicalAddress
  121. );
  122. COMPARISON_RESULT
  123. NetpCompareFullyBoundSockets (
  124. PRED_BLACK_TREE Tree,
  125. PRED_BLACK_TREE_NODE FirstNode,
  126. PRED_BLACK_TREE_NODE SecondNode
  127. );
  128. COMPARISON_RESULT
  129. NetpMatchFullyBoundSocket (
  130. PNET_SOCKET Socket,
  131. PNETWORK_ADDRESS LocalAddress,
  132. PNETWORK_ADDRESS RemoteAddress
  133. );
  134. COMPARISON_RESULT
  135. NetpCompareLocallyBoundSockets (
  136. PRED_BLACK_TREE Tree,
  137. PRED_BLACK_TREE_NODE FirstNode,
  138. PRED_BLACK_TREE_NODE SecondNode
  139. );
  140. COMPARISON_RESULT
  141. NetpCompareUnboundSockets (
  142. PRED_BLACK_TREE Tree,
  143. PRED_BLACK_TREE_NODE FirstNode,
  144. PRED_BLACK_TREE_NODE SecondNode
  145. );
  146. COMPARISON_RESULT
  147. NetpCompareAddressTranslationEntries (
  148. PRED_BLACK_TREE Tree,
  149. PRED_BLACK_TREE_NODE FirstNode,
  150. PRED_BLACK_TREE_NODE SecondNode
  151. );
  152. BOOL
  153. NetpCheckLocalAddressAvailability (
  154. PNET_SOCKET Socket,
  155. PNETWORK_ADDRESS LocalAddress
  156. );
  157. VOID
  158. NetpGetPacketSizeInformation (
  159. PNET_LINK Link,
  160. PNET_SOCKET Socket,
  161. PNET_PACKET_SIZE_INFORMATION SizeInformation
  162. );
  163. VOID
  164. NetpDebugPrintNetworkAddress (
  165. PNET_NETWORK_ENTRY Network,
  166. PNETWORK_ADDRESS Address
  167. );
  168. //
  169. // -------------------------------------------------------------------- Globals
  170. //
  171. //
  172. // Define the list of raw sockets. These do not get put in the socket trees.
  173. //
  174. LIST_ENTRY NetRawSocketsList;
  175. PSHARED_EXCLUSIVE_LOCK NetRawSocketsLock;
  176. //
  177. // Define the list of available network links (things that can actually send
  178. // packets). Any party accessing this list must have acquired the link list
  179. // lock. The lock can only be acquired at low level.
  180. //
  181. LIST_ENTRY NetLinkList;
  182. PSHARED_EXCLUSIVE_LOCK NetLinkListLock;
  183. UUID NetNetworkDeviceInformationUuid = NETWORK_DEVICE_INFORMATION_UUID;
  184. //
  185. // ------------------------------------------------------------------ Functions
  186. //
  187. NET_API
  188. KSTATUS
  189. NetAddLink (
  190. PNET_LINK_PROPERTIES Properties,
  191. PNET_LINK *NewLink
  192. )
  193. /*++
  194. Routine Description:
  195. This routine adds a new network link based on the given properties. The
  196. link must be ready to send and receive traffic and have a valid physical
  197. layer address supplied in the properties.
  198. Arguments:
  199. Properties - Supplies a pointer describing the properties and interface of
  200. the link. This memory will not be referenced after the function returns,
  201. so this may be a stack allocated structure.
  202. NewLink - Supplies a pointer where a pointer to the new link will be
  203. returned on success.
  204. Return Value:
  205. STATUS_SUCCESS on success.
  206. STATUS_INSUFFICIENT_RESOURCES if memory could not be allocated for the
  207. structure.
  208. --*/
  209. {
  210. PNET_DATA_LINK_ENTRY CurrentDataLink;
  211. PLIST_ENTRY CurrentEntry;
  212. PNET_NETWORK_ENTRY CurrentNetwork;
  213. PNET_DATA_LINK_ENTRY FoundDataLink;
  214. PLIST_ENTRY LastEntry;
  215. PNET_LINK Link;
  216. BOOL LockHeld;
  217. KSTATUS Status;
  218. ASSERT(KeGetRunLevel() == RunLevelLow);
  219. LastEntry = NULL;
  220. Link = NULL;
  221. LockHeld = FALSE;
  222. Status = STATUS_SUCCESS;
  223. if (Properties->Version < NET_LINK_PROPERTIES_VERSION) {
  224. Status = STATUS_VERSION_MISMATCH;
  225. goto AddLinkEnd;
  226. }
  227. if (Properties->TransmitAlignment == 0) {
  228. Properties->TransmitAlignment = 1;
  229. }
  230. if ((!POWER_OF_2(Properties->TransmitAlignment)) ||
  231. (Properties->PhysicalAddress.Domain == NetDomainInvalid) ||
  232. (Properties->MaxPhysicalAddress == 0) ||
  233. (Properties->Interface.Send == NULL) ||
  234. (Properties->Interface.GetSetInformation == NULL)) {
  235. Status = STATUS_INVALID_PARAMETER;
  236. goto AddLinkEnd;
  237. }
  238. Link = MmAllocatePagedPool(sizeof(NET_LINK), NET_CORE_ALLOCATION_TAG);
  239. if (Link == NULL) {
  240. Status = STATUS_INSUFFICIENT_RESOURCES;
  241. goto AddLinkEnd;
  242. }
  243. RtlZeroMemory(Link, sizeof(NET_LINK));
  244. Link->ReferenceCount = 1;
  245. RtlCopyMemory(&(Link->Properties), Properties, sizeof(NET_LINK_PROPERTIES));
  246. Link->QueuedLock = KeCreateQueuedLock();
  247. if (Link->QueuedLock == NULL) {
  248. Status = STATUS_INSUFFICIENT_RESOURCES;
  249. goto AddLinkEnd;
  250. }
  251. INITIALIZE_LIST_HEAD(&(Link->LinkAddressList));
  252. Link->AddressTranslationEvent = KeCreateEvent(NULL);
  253. if (Link->AddressTranslationEvent == NULL) {
  254. Status = STATUS_INSUFFICIENT_RESOURCES;
  255. goto AddLinkEnd;
  256. }
  257. KeSignalEvent(Link->AddressTranslationEvent, SignalOptionUnsignal);
  258. RtlRedBlackTreeInitialize(&(Link->AddressTranslationTree),
  259. 0,
  260. NetpCompareAddressTranslationEntries);
  261. //
  262. // Find the appropriate data link layer and initialize it for this link.
  263. //
  264. FoundDataLink = NULL;
  265. KeAcquireSharedExclusiveLockShared(NetPluginListLock);
  266. LockHeld = TRUE;
  267. CurrentEntry = NetDataLinkList.Next;
  268. while (CurrentEntry != &NetDataLinkList) {
  269. CurrentDataLink = LIST_VALUE(CurrentEntry,
  270. NET_DATA_LINK_ENTRY,
  271. ListEntry);
  272. if (CurrentDataLink->Domain == Properties->DataLinkType) {
  273. FoundDataLink = CurrentDataLink;
  274. break;
  275. }
  276. CurrentEntry = CurrentEntry->Next;
  277. }
  278. if (FoundDataLink == NULL) {
  279. Status = STATUS_NOT_SUPPORTED;
  280. goto AddLinkEnd;
  281. }
  282. Status = FoundDataLink->Interface.InitializeLink(Link);
  283. if (!KSUCCESS(Status)) {
  284. goto AddLinkEnd;
  285. }
  286. Link->DataLinkEntry = FoundDataLink;
  287. //
  288. // Let the network layers have their shot at initializing state for this
  289. // link.
  290. //
  291. CurrentEntry = NetNetworkList.Next;
  292. while (CurrentEntry != &NetNetworkList) {
  293. CurrentNetwork = LIST_VALUE(CurrentEntry, NET_NETWORK_ENTRY, ListEntry);
  294. Status = CurrentNetwork->Interface.InitializeLink(Link);
  295. if (!KSUCCESS(Status)) {
  296. goto AddLinkEnd;
  297. }
  298. CurrentEntry = CurrentEntry->Next;
  299. LastEntry = CurrentEntry;
  300. }
  301. KeReleaseSharedExclusiveLockShared(NetPluginListLock);
  302. LockHeld = FALSE;
  303. //
  304. // All network devices respond to the network device information requests.
  305. //
  306. Status = IoRegisterDeviceInformation(Link->Properties.Device,
  307. &NetNetworkDeviceInformationUuid,
  308. TRUE);
  309. if (!KSUCCESS(Status)) {
  310. goto AddLinkEnd;
  311. }
  312. //
  313. // With success a sure thing, take a reference on the OS device that
  314. // registered the link with netcore. Its device context and driver need to
  315. // remain available as long as netcore can access the device link interface.
  316. //
  317. IoDeviceAddReference(Link->Properties.Device);
  318. //
  319. // Add the link to the global list. It is all ready to send and receive
  320. // data.
  321. //
  322. KeAcquireSharedExclusiveLockExclusive(NetLinkListLock);
  323. ASSERT(Link->ListEntry.Next == NULL);
  324. INSERT_BEFORE(&(Link->ListEntry), &NetLinkList);
  325. KeReleaseSharedExclusiveLockExclusive(NetLinkListLock);
  326. Status = STATUS_SUCCESS;
  327. AddLinkEnd:
  328. if (!KSUCCESS(Status)) {
  329. if (Link != NULL) {
  330. IoRegisterDeviceInformation(Link->Properties.Device,
  331. &NetNetworkDeviceInformationUuid,
  332. FALSE);
  333. //
  334. // If some network layer entries have initialized already, call
  335. // them back to cancel.
  336. //
  337. if (LastEntry != NULL) {
  338. if (LockHeld == FALSE) {
  339. KeAcquireSharedExclusiveLockShared(NetPluginListLock);
  340. LockHeld = TRUE;
  341. }
  342. CurrentEntry = NetNetworkList.Next;
  343. while (CurrentEntry != LastEntry) {
  344. CurrentNetwork = LIST_VALUE(CurrentEntry,
  345. NET_NETWORK_ENTRY,
  346. ListEntry);
  347. CurrentNetwork->Interface.DestroyLink(Link);
  348. CurrentEntry = CurrentEntry->Next;
  349. }
  350. }
  351. if (LockHeld != FALSE) {
  352. KeReleaseSharedExclusiveLockShared(NetPluginListLock);
  353. LockHeld = FALSE;
  354. }
  355. if (Link->DataLinkEntry != NULL) {
  356. Link->DataLinkEntry->Interface.DestroyLink(Link);
  357. }
  358. if (Link->QueuedLock != NULL) {
  359. KeDestroyQueuedLock(Link->QueuedLock);
  360. }
  361. if (Link->AddressTranslationEvent != NULL) {
  362. KeDestroyEvent(Link->AddressTranslationEvent);
  363. }
  364. MmFreePagedPool(Link);
  365. Link = NULL;
  366. }
  367. }
  368. ASSERT(LockHeld == FALSE);
  369. *NewLink = Link;
  370. return Status;
  371. }
  372. NET_API
  373. VOID
  374. NetLinkAddReference (
  375. PNET_LINK Link
  376. )
  377. /*++
  378. Routine Description:
  379. This routine increases the reference count on a network link.
  380. Arguments:
  381. Link - Supplies a pointer to the network link whose reference count
  382. should be incremented.
  383. Return Value:
  384. None.
  385. --*/
  386. {
  387. ULONG OldReferenceCount;
  388. OldReferenceCount = RtlAtomicAdd32(&(Link->ReferenceCount), 1);
  389. ASSERT((OldReferenceCount != 0) & (OldReferenceCount < 0x20000000));
  390. return;
  391. }
  392. NET_API
  393. VOID
  394. NetLinkReleaseReference (
  395. PNET_LINK Link
  396. )
  397. /*++
  398. Routine Description:
  399. This routine decreases the reference count of a network link, and destroys
  400. the link if the reference count drops to zero.
  401. Arguments:
  402. Link - Supplies a pointer to the network link whose reference count
  403. should be decremented.
  404. Return Value:
  405. None.
  406. --*/
  407. {
  408. ULONG OldReferenceCount;
  409. OldReferenceCount = RtlAtomicAdd32(&(Link->ReferenceCount), -1);
  410. ASSERT(OldReferenceCount != 0);
  411. if (OldReferenceCount == 1) {
  412. NetpDestroyLink(Link);
  413. }
  414. return;
  415. }
  416. NET_API
  417. VOID
  418. NetSetLinkState (
  419. PNET_LINK Link,
  420. BOOL LinkUp,
  421. ULONGLONG LinkSpeed
  422. )
  423. /*++
  424. Routine Description:
  425. This routine sets the link state of the given link. The physical device
  426. layer is responsible for synchronizing link state changes.
  427. Arguments:
  428. Link - Supplies a pointer to the link whose state is changing.
  429. LinkUp - Supplies a boolean indicating whether the link is active (TRUE) or
  430. disconnected (FALSE).
  431. LinkSpeed - Supplies the speed of the link, in bits per second.
  432. Return Value:
  433. None.
  434. --*/
  435. {
  436. PLIST_ENTRY CurrentEntry;
  437. NET_DOMAIN_TYPE Domain;
  438. PNET_LINK_ADDRESS_ENTRY LinkAddress;
  439. BOOL OriginalLinkUp;
  440. KSTATUS Status;
  441. PADDRESS_TRANSLATION_ENTRY Translation;
  442. PRED_BLACK_TREE Tree;
  443. PRED_BLACK_TREE_NODE TreeNode;
  444. ASSERT(KeGetRunLevel() == RunLevelLow);
  445. ASSERT(Link != NULL);
  446. //
  447. // Link state is synchronized under the global link list lock.
  448. //
  449. KeAcquireSharedExclusiveLockExclusive(NetLinkListLock);
  450. OriginalLinkUp = Link->LinkUp;
  451. Link->LinkUp = LinkUp;
  452. Link->LinkSpeed = LinkSpeed;
  453. RtlDebugPrint("NET: ");
  454. NetDebugPrintAddress(&(Link->Properties.PhysicalAddress));
  455. if (LinkUp != FALSE) {
  456. RtlDebugPrint(" up, Speed %I64d mbps\n", LinkSpeed / 1000000ULL);
  457. } else {
  458. RtlDebugPrint(" down\n");
  459. }
  460. KeReleaseSharedExclusiveLockExclusive(NetLinkListLock);
  461. //
  462. // If the link state was not changed, then take no action.
  463. //
  464. if (LinkUp == OriginalLinkUp) {
  465. return;
  466. }
  467. //
  468. // If the link is now up, then use DHCP to get an address. It is assumed
  469. // that the link will not go down before handing off to DHCP.
  470. //
  471. if (LinkUp != FALSE) {
  472. ASSERT(Link->LinkUp != FALSE);
  473. ASSERT(LIST_EMPTY(&(Link->LinkAddressList)) == FALSE);
  474. //
  475. // If the link had previously gone down then the address translation
  476. // event was left signalled.
  477. //
  478. KeSignalEvent(Link->AddressTranslationEvent, SignalOptionUnsignal);
  479. //
  480. // Request an address for the first link.
  481. //
  482. LinkAddress = LIST_VALUE(Link->LinkAddressList.Next,
  483. NET_LINK_ADDRESS_ENTRY,
  484. ListEntry);
  485. Status = NetpDhcpBeginAssignment(Link, LinkAddress);
  486. if (!KSUCCESS(Status)) {
  487. //
  488. // TODO: Handle failed DHCP.
  489. //
  490. ASSERT(FALSE);
  491. }
  492. //
  493. // The link has gone down. Sockets can no longer take references on the
  494. // link via bind until it goes back up. It is assumed that the link will
  495. // not go back up while in the middle of this process to take it down.
  496. //
  497. } else {
  498. ASSERT(Link->LinkUp == FALSE);
  499. //
  500. // Clean up the address translation tree. If the link reconnects after
  501. // moving to a new network, some of the address translations may be
  502. // incorrect.
  503. //
  504. Tree = &(Link->AddressTranslationTree);
  505. KeAcquireQueuedLock(Link->QueuedLock);
  506. while (TRUE) {
  507. TreeNode = RtlRedBlackTreeGetLowestNode(Tree);
  508. if (TreeNode == NULL) {
  509. break;
  510. }
  511. RtlRedBlackTreeRemove(Tree, TreeNode);
  512. Translation = RED_BLACK_TREE_VALUE(TreeNode,
  513. ADDRESS_TRANSLATION_ENTRY,
  514. TreeEntry);
  515. MmFreePagedPool(Translation);
  516. }
  517. KeReleaseQueuedLock(Link->QueuedLock);
  518. //
  519. // Now that the address translation tree is empty, signal anyone
  520. // waiting for address translations on this event once and for all.
  521. //
  522. KeSignalEvent(Link->AddressTranslationEvent, SignalOptionSignalAll);
  523. //
  524. // Notify every fully bound, locally bound, and raw socket using this
  525. // link that the link has gone down. Sockets may be waiting on data or
  526. // in the middle of sending data.
  527. //
  528. NetpDetachSockets(Link, NULL);
  529. //
  530. // Now that the sockets are out of the way, go through and gut the
  531. // non-static link address entries.
  532. //
  533. KeAcquireQueuedLock(Link->QueuedLock);
  534. CurrentEntry = Link->LinkAddressList.Next;
  535. while (CurrentEntry != &(Link->LinkAddressList)) {
  536. LinkAddress = LIST_VALUE(CurrentEntry,
  537. NET_LINK_ADDRESS_ENTRY,
  538. ListEntry);
  539. CurrentEntry = CurrentEntry->Next;
  540. if (LinkAddress->Configured == FALSE) {
  541. continue;
  542. }
  543. //
  544. // If the link address was configured via DHCP, then release the IP
  545. // address.
  546. //
  547. if (LinkAddress->StaticAddress == FALSE) {
  548. //
  549. // Zero out the network address, except the network type which
  550. // is needed to reconfigure the link. The rest of the state can
  551. // be left stale.
  552. //
  553. Domain = LinkAddress->Address.Domain;
  554. RtlZeroMemory(&(LinkAddress->Address), sizeof(NETWORK_ADDRESS));
  555. LinkAddress->Address.Domain = Domain;
  556. //
  557. // Notify DHCP that the link and link address combination is
  558. // now invalid. It may have saved state.
  559. //
  560. NetpDhcpCancelLease(Link, LinkAddress);
  561. }
  562. LinkAddress->Configured = FALSE;
  563. }
  564. KeReleaseQueuedLock(Link->QueuedLock);
  565. }
  566. return;
  567. }
  568. NET_API
  569. VOID
  570. NetGetLinkState (
  571. PNET_LINK Link,
  572. PBOOL LinkUp,
  573. PULONGLONG LinkSpeed
  574. )
  575. /*++
  576. Routine Description:
  577. This routine gets the link state of the given link.
  578. Arguments:
  579. Link - Supplies a pointer to the link whose state is being retrieved.
  580. LinkUp - Supplies a pointer that receives a boolean indicating whether the
  581. link is active (TRUE) or disconnected (FALSE). This parameter is
  582. optional.
  583. LinkSpeed - Supplies a pointer that receives the speed of the link, in bits
  584. per second. This parameter is optional.
  585. Return Value:
  586. None.
  587. --*/
  588. {
  589. ASSERT(Link != NULL);
  590. if (LinkUp != NULL) {
  591. *LinkUp = Link->LinkUp;
  592. }
  593. if (LinkSpeed != NULL) {
  594. *LinkSpeed = Link->LinkSpeed;
  595. }
  596. return;
  597. }
  598. NET_API
  599. KSTATUS
  600. NetGetSetLinkDeviceInformation (
  601. PNET_LINK Link,
  602. PUUID Uuid,
  603. PVOID Data,
  604. PUINTN DataSize,
  605. BOOL Set
  606. )
  607. /*++
  608. Routine Description:
  609. This routine gets or sets device information for a link.
  610. Arguments:
  611. Link - Supplies a pointer to the link whose device information is being
  612. retrieved or set.
  613. Uuid - Supplies a pointer to the information identifier.
  614. Data - Supplies a pointer to the data buffer.
  615. DataSize - Supplies a pointer that on input contains the size of the data
  616. buffer in bytes. On output, returns the needed size of the data buffer,
  617. even if the supplied buffer was nonexistant or too small.
  618. Set - Supplies a boolean indicating whether to get the information (FALSE)
  619. or set the information (TRUE).
  620. Return Value:
  621. STATUS_SUCCESS on success.
  622. STATUS_BUFFER_TOO_SMALL if the supplied buffer was too small.
  623. STATUS_NOT_HANDLED if the given UUID was not recognized.
  624. --*/
  625. {
  626. KSTATUS Status;
  627. Status = STATUS_NOT_HANDLED;
  628. if (RtlAreUuidsEqual(Uuid, &NetNetworkDeviceInformationUuid) != FALSE) {
  629. if (*DataSize < sizeof(NETWORK_DEVICE_INFORMATION)) {
  630. *DataSize = sizeof(NETWORK_DEVICE_INFORMATION);
  631. goto GetSetLinkDeviceInformationEnd;
  632. }
  633. *DataSize = sizeof(NETWORK_DEVICE_INFORMATION);
  634. Status = NetGetSetNetworkDeviceInformation(Link, NULL, Data, Set);
  635. goto GetSetLinkDeviceInformationEnd;
  636. }
  637. GetSetLinkDeviceInformationEnd:
  638. return Status;
  639. }
  640. NET_API
  641. VOID
  642. NetRemoveLink (
  643. PNET_LINK Link
  644. )
  645. /*++
  646. Routine Description:
  647. This routine removes a link from the networking core after its device has
  648. been removed. This should not be used if the media has simply been removed.
  649. In that case, setting the link state to 'down' is suffiient. There may
  650. still be outstanding references on the link, so the networking core will
  651. call the device back to notify it when the link is destroyed.
  652. Arguments:
  653. Link - Supplies a pointer to the link to remove.
  654. Return Value:
  655. None.
  656. --*/
  657. {
  658. //
  659. // The device has been removed, the link should no longer respond to
  660. // information requests.
  661. //
  662. IoRegisterDeviceInformation(Link->Properties.Device,
  663. &NetNetworkDeviceInformationUuid,
  664. FALSE);
  665. //
  666. // If the link is still up, then send out the notice that is is actually
  667. // down.
  668. //
  669. if (Link->LinkUp != FALSE) {
  670. NetSetLinkState(Link, FALSE, 0);
  671. }
  672. //
  673. // Remove the link from the net link list. Disconnecting the link by
  674. // setting its state to down should have already stopped sockets from
  675. // taking new references on the link.
  676. //
  677. if (Link->ListEntry.Next != NULL) {
  678. KeAcquireSharedExclusiveLockExclusive(NetLinkListLock);
  679. LIST_REMOVE(&(Link->ListEntry));
  680. Link->ListEntry.Next = NULL;
  681. KeReleaseSharedExclusiveLockExclusive(NetLinkListLock);
  682. }
  683. //
  684. // Dereference the link. The final clean-up will be triggered once the last
  685. // reference is released.
  686. //
  687. NetLinkReleaseReference(Link);
  688. return;
  689. }
  690. NET_API
  691. KSTATUS
  692. NetFindLinkForLocalAddress (
  693. PNETWORK_ADDRESS LocalAddress,
  694. BOOL AnyAddress,
  695. PNET_LINK Link,
  696. PNET_LINK_LOCAL_ADDRESS LinkResult
  697. )
  698. /*++
  699. Routine Description:
  700. This routine searches for a link and the associated address entry that
  701. matches the given local address. If a link is supplied as a hint, then the
  702. given link must be able to service the given address for this routine to
  703. succeed.
  704. Arguments:
  705. LocalAddress - Supplies a pointer to the local address to test against.
  706. AnyAddress - Supplies a boolean indicating whether or not the local address
  707. is the network's any address.
  708. Link - Supplies an optional pointer to a link that the local address must
  709. be from.
  710. LinkResult - Supplies a pointer that receives the found link, link address
  711. entry, and local address.
  712. Return Value:
  713. STATUS_SUCCESS if a link was found and bound with the socket.
  714. STATUS_INVALID_ADDRESS if no link was found to own that address.
  715. STATUS_NO_NETWORK_CONNECTION if no networks are available.
  716. --*/
  717. {
  718. PLIST_ENTRY CurrentEntry;
  719. PNET_LINK CurrentLink;
  720. PNET_LINK_ADDRESS_ENTRY LinkAddress;
  721. KSTATUS Status;
  722. ASSERT(KeGetRunLevel() == RunLevelLow);
  723. Status = STATUS_INVALID_ADDRESS;
  724. KeAcquireSharedExclusiveLockShared(NetLinkListLock);
  725. if (LIST_EMPTY(&NetLinkList)) {
  726. Status = STATUS_NO_NETWORK_CONNECTION;
  727. goto FindLinkForLocalAddress;
  728. }
  729. //
  730. // If there's a specific link being bound to, then just try to find the
  731. // address entry within that link.
  732. //
  733. if (Link != NULL) {
  734. if (Link->LinkUp == FALSE) {
  735. Status = STATUS_NO_NETWORK_CONNECTION;
  736. goto FindLinkForLocalAddress;
  737. }
  738. Status = NetFindEntryForAddress(Link,
  739. LocalAddress,
  740. AnyAddress,
  741. &LinkAddress);
  742. //
  743. // There is no specific link, so scan through them all.
  744. //
  745. } else {
  746. CurrentEntry = NetLinkList.Next;
  747. while (CurrentEntry != &NetLinkList) {
  748. CurrentLink = LIST_VALUE(CurrentEntry, NET_LINK, ListEntry);
  749. CurrentEntry = CurrentEntry->Next;
  750. //
  751. // Don't bother if the link is down.
  752. //
  753. if (CurrentLink->LinkUp == FALSE) {
  754. continue;
  755. }
  756. Status = NetFindEntryForAddress(CurrentLink,
  757. LocalAddress,
  758. AnyAddress,
  759. &LinkAddress);
  760. if (KSUCCESS(Status)) {
  761. Link = CurrentLink;
  762. break;
  763. }
  764. }
  765. }
  766. //
  767. // If a link address entry was found, then fill out the link information.
  768. //
  769. if (KSUCCESS(Status)) {
  770. NetLinkAddReference(Link);
  771. LinkResult->Link = Link;
  772. LinkResult->LinkAddress = LinkAddress;
  773. RtlCopyMemory(&(LinkResult->LocalAddress),
  774. LocalAddress,
  775. sizeof(NETWORK_ADDRESS));
  776. }
  777. FindLinkForLocalAddress:
  778. KeReleaseSharedExclusiveLockShared(NetLinkListLock);
  779. return Status;
  780. }
  781. NET_API
  782. KSTATUS
  783. NetFindLinkForRemoteAddress (
  784. PNETWORK_ADDRESS RemoteAddress,
  785. PNET_LINK_LOCAL_ADDRESS LinkResult
  786. )
  787. /*++
  788. Routine Description:
  789. This routine searches for a link and associated address entry that can
  790. reach the given remote address.
  791. Arguments:
  792. RemoteAddress - Supplies a pointer to the address to test against.
  793. LinkResult - Supplies a pointer that receives the link information,
  794. including the link, link address entry, and associated local address.
  795. Return Value:
  796. STATUS_SUCCESS if a link was found and bound with the socket.
  797. STATUS_NO_NETWORK_CONNECTION if no networks are available.
  798. --*/
  799. {
  800. PNET_LINK CurrentLink;
  801. PNET_LINK_ADDRESS_ENTRY CurrentLinkAddressEntry;
  802. PLIST_ENTRY CurrentLinkEntry;
  803. PNET_LINK_ADDRESS_ENTRY FoundAddress;
  804. KSTATUS Status;
  805. ASSERT(KeGetRunLevel() == RunLevelLow);
  806. KeAcquireSharedExclusiveLockShared(NetLinkListLock);
  807. if (LIST_EMPTY(&NetLinkList)) {
  808. Status = STATUS_NO_NETWORK_CONNECTION;
  809. goto FindLinkForDestinationAddressEnd;
  810. }
  811. Status = STATUS_NO_NETWORK_CONNECTION;
  812. FoundAddress = NULL;
  813. CurrentLinkEntry = NetLinkList.Next;
  814. while (CurrentLinkEntry != &NetLinkList) {
  815. CurrentLink = LIST_VALUE(CurrentLinkEntry, NET_LINK, ListEntry);
  816. CurrentLinkEntry = CurrentLinkEntry->Next;
  817. //
  818. // Don't bother if the link is down.
  819. //
  820. if (CurrentLink->LinkUp == FALSE) {
  821. continue;
  822. }
  823. //
  824. // TODO: Properly determine the route for this destination, rather
  825. // than just connecting through the first working network link and first
  826. // address inside it. Make sure to not use the routing tables if
  827. // SOCKET_IO_DONT_ROUTE is set at time of send/receive.
  828. //
  829. KeAcquireQueuedLock(CurrentLink->QueuedLock);
  830. ASSERT(!LIST_EMPTY(&(CurrentLink->LinkAddressList)));
  831. CurrentLinkAddressEntry = LIST_VALUE(CurrentLink->LinkAddressList.Next,
  832. NET_LINK_ADDRESS_ENTRY,
  833. ListEntry);
  834. if (CurrentLinkAddressEntry->Configured != FALSE) {
  835. FoundAddress = CurrentLinkAddressEntry;
  836. RtlCopyMemory(&(LinkResult->LocalAddress),
  837. &(FoundAddress->Address),
  838. sizeof(NETWORK_ADDRESS));
  839. ASSERT(LinkResult->LocalAddress.Port == 0);
  840. }
  841. KeReleaseQueuedLock(CurrentLink->QueuedLock);
  842. //
  843. // If a suitable link address was not found, continue on to the next
  844. // link.
  845. //
  846. if (FoundAddress == NULL) {
  847. continue;
  848. }
  849. //
  850. // Fill out the link information. The local address was copied above
  851. // under the lock in order to prevent a torn read.
  852. //
  853. NetLinkAddReference(CurrentLink);
  854. LinkResult->Link = CurrentLink;
  855. LinkResult->LinkAddress = FoundAddress;
  856. Status = STATUS_SUCCESS;
  857. break;
  858. }
  859. FindLinkForDestinationAddressEnd:
  860. KeReleaseSharedExclusiveLockShared(NetLinkListLock);
  861. return Status;
  862. }
  863. NET_API
  864. KSTATUS
  865. NetLookupLinkByDevice (
  866. PDEVICE Device,
  867. PNET_LINK *Link
  868. )
  869. /*++
  870. Routine Description:
  871. This routine looks for a link that belongs to the given device. If a link
  872. is found, a reference will be added. It is the callers responsibility to
  873. release this reference.
  874. Arguments:
  875. Device - Supplies a pointer to the device for which the link is being
  876. searched.
  877. Link - Supplies a pointer that receives a pointer to the link, if found.
  878. Return Value:
  879. Status code.
  880. --*/
  881. {
  882. PLIST_ENTRY CurrentEntry;
  883. PNET_LINK CurrentLink;
  884. KSTATUS Status;
  885. if (LIST_EMPTY(&NetLinkList) != FALSE) {
  886. return STATUS_NOT_FOUND;
  887. }
  888. Status = STATUS_NOT_FOUND;
  889. KeAcquireSharedExclusiveLockShared(NetLinkListLock);
  890. CurrentEntry = NetLinkList.Next;
  891. while (CurrentEntry != &NetLinkList) {
  892. CurrentLink = LIST_VALUE(CurrentEntry, NET_LINK, ListEntry);
  893. if (CurrentLink->Properties.Device == Device) {
  894. NetLinkAddReference(CurrentLink);
  895. *Link = CurrentLink;
  896. Status = STATUS_SUCCESS;
  897. break;
  898. }
  899. CurrentEntry = CurrentEntry->Next;
  900. }
  901. KeReleaseSharedExclusiveLockShared(NetLinkListLock);
  902. return Status;
  903. }
  904. NET_API
  905. KSTATUS
  906. NetCreateLinkAddressEntry (
  907. PNET_LINK Link,
  908. PNETWORK_ADDRESS Address,
  909. PNETWORK_ADDRESS Subnet,
  910. PNETWORK_ADDRESS DefaultGateway,
  911. BOOL StaticAddress,
  912. PNET_LINK_ADDRESS_ENTRY *NewLinkAddress
  913. )
  914. /*++
  915. Routine Description:
  916. This routine initializes a new network link address entry.
  917. Arguments:
  918. Link - Supplies a pointer to the physical link that has the new network
  919. address.
  920. Address - Supplies an optional pointer to the address to assign to the link
  921. address entry.
  922. Subnet - Supplies an optional pointer to the subnet mask to assign to the
  923. link address entry.
  924. DefaultGateway - Supplies an optional pointer to the default gateway
  925. address to assign to the link address entry.
  926. StaticAddress - Supplies a boolean indicating if the provided information
  927. is a static configuration of the link address entry. This parameter is
  928. only used when the Address, Subnet, and DefaultGateway parameters are
  929. supplied.
  930. NewLinkAddress - Supplies a pointer where a pointer to the new link address
  931. will be returned. The new link address will also be inserted onto the
  932. link.
  933. Return Value:
  934. Status code.
  935. --*/
  936. {
  937. PNET_LINK_ADDRESS_ENTRY LinkAddress;
  938. KSTATUS Status;
  939. ASSERT(KeGetRunLevel() == RunLevelLow);
  940. LinkAddress = MmAllocatePagedPool(sizeof(NET_LINK_ADDRESS_ENTRY),
  941. NET_CORE_ALLOCATION_TAG);
  942. if (LinkAddress == NULL) {
  943. Status = STATUS_INSUFFICIENT_RESOURCES;
  944. goto CreateLinkAddressEnd;
  945. }
  946. //
  947. // Copy in the initial addressing parameters if supplied.
  948. //
  949. RtlZeroMemory(LinkAddress, sizeof(NET_LINK_ADDRESS_ENTRY));
  950. if (Address != NULL) {
  951. RtlCopyMemory(&(LinkAddress->Address),
  952. Address,
  953. sizeof(NETWORK_ADDRESS));
  954. }
  955. if (Subnet != NULL) {
  956. RtlCopyMemory(&(LinkAddress->Subnet), Subnet, sizeof(NETWORK_ADDRESS));
  957. }
  958. if (DefaultGateway != NULL) {
  959. RtlCopyMemory(&(LinkAddress->DefaultGateway),
  960. DefaultGateway,
  961. sizeof(NETWORK_ADDRESS));
  962. }
  963. //
  964. // Start the link address off with the built-in physical address.
  965. //
  966. RtlCopyMemory(&(LinkAddress->PhysicalAddress),
  967. &(Link->Properties.PhysicalAddress),
  968. sizeof(NETWORK_ADDRESS));
  969. //
  970. // If an address, subnet, and default gateway were supplied, then this link
  971. // address entry is as good as configured.
  972. //
  973. ASSERT(LinkAddress->Configured == FALSE);
  974. if ((Address != NULL) && (Subnet != NULL) && (DefaultGateway != NULL)) {
  975. LinkAddress->StaticAddress = StaticAddress;
  976. LinkAddress->Configured = TRUE;
  977. }
  978. //
  979. // Everything's good to go, add the address to the link's list.
  980. //
  981. KeAcquireQueuedLock(Link->QueuedLock);
  982. INSERT_AFTER(&(LinkAddress->ListEntry), &(Link->LinkAddressList));
  983. KeReleaseQueuedLock(Link->QueuedLock);
  984. Status = STATUS_SUCCESS;
  985. CreateLinkAddressEnd:
  986. if (!KSUCCESS(Status)) {
  987. if (LinkAddress != NULL) {
  988. MmFreePagedPool(LinkAddress);
  989. LinkAddress = NULL;
  990. }
  991. }
  992. *NewLinkAddress = LinkAddress;
  993. return Status;
  994. }
  995. NET_API
  996. VOID
  997. NetDestroyLinkAddressEntry (
  998. PNET_LINK Link,
  999. PNET_LINK_ADDRESS_ENTRY LinkAddress
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. This routine removes and destroys a link address.
  1004. Arguments:
  1005. Link - Supplies a pointer to the physical link that has the network address.
  1006. LinkAddress - Supplies a pointer to the link address to remove and destroy.
  1007. Return Value:
  1008. None.
  1009. --*/
  1010. {
  1011. ASSERT(KeGetRunLevel() == RunLevelLow);
  1012. KeAcquireQueuedLock(Link->QueuedLock);
  1013. LIST_REMOVE(&(LinkAddress->ListEntry));
  1014. KeReleaseQueuedLock(Link->QueuedLock);
  1015. MmFreePagedPool(LinkAddress);
  1016. return;
  1017. }
  1018. NET_API
  1019. KSTATUS
  1020. NetTranslateNetworkAddress (
  1021. PNETWORK_ADDRESS NetworkAddress,
  1022. PNET_LINK Link,
  1023. PNET_LINK_ADDRESS_ENTRY LinkAddress,
  1024. PNETWORK_ADDRESS PhysicalAddress
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. This routine translates a network level address to a physical address.
  1029. Arguments:
  1030. NetworkAddress - Supplies a pointer to the network address to translate.
  1031. Link - Supplies a pointer to the link to use.
  1032. LinkAddress - Supplies a pointer to the link address entry to use for this
  1033. request.
  1034. PhysicalAddress - Supplies a pointer where the corresponding physical
  1035. address for this network address will be returned.
  1036. Return Value:
  1037. Status code.
  1038. --*/
  1039. {
  1040. ULONGLONG EndTime;
  1041. KSTATUS Status;
  1042. ULONGLONG TimeDelta;
  1043. EndTime = 0;
  1044. //
  1045. // Loop trying to get the address, and waiting for an answer.
  1046. //
  1047. while (TRUE) {
  1048. Status = NetpLookupAddressTranslation(Link,
  1049. NetworkAddress,
  1050. PhysicalAddress);
  1051. if (KSUCCESS(Status)) {
  1052. break;
  1053. }
  1054. //
  1055. // If the lookup failed once, but this is the first time, set an end
  1056. // time to give up.
  1057. //
  1058. if (EndTime == 0) {
  1059. TimeDelta = ADDRESS_TRANSLATION_TIMEOUT *
  1060. MICROSECONDS_PER_MILLISECOND;
  1061. EndTime = KeGetRecentTimeCounter() +
  1062. KeConvertMicrosecondsToTimeTicks(TimeDelta);
  1063. Status = NetpArpSendRequest(Link, LinkAddress, NetworkAddress);
  1064. if (!KSUCCESS(Status)) {
  1065. return Status;
  1066. }
  1067. //
  1068. // If this loop has already been around at least once, look for a
  1069. // timeout event.
  1070. //
  1071. } else if (KeGetRecentTimeCounter() >= EndTime) {
  1072. Status = STATUS_TIMEOUT;
  1073. break;
  1074. }
  1075. //
  1076. // Wait for some new address translation to come in.
  1077. //
  1078. Status = KeWaitForEvent(Link->AddressTranslationEvent,
  1079. FALSE,
  1080. ADDRESS_TRANSLATION_RETRY_INTERVAL);
  1081. //
  1082. // On timeouts, re-send the ARP request.
  1083. //
  1084. if (Status == STATUS_TIMEOUT) {
  1085. Status = NetpArpSendRequest(Link, LinkAddress, NetworkAddress);
  1086. if (!KSUCCESS(Status)) {
  1087. return Status;
  1088. }
  1089. }
  1090. //
  1091. // On all other failures to wait for the event, break.
  1092. //
  1093. if (!KSUCCESS(Status)) {
  1094. break;
  1095. }
  1096. }
  1097. return Status;
  1098. }
  1099. NET_API
  1100. KSTATUS
  1101. NetAddNetworkAddressTranslation (
  1102. PNET_LINK Link,
  1103. PNETWORK_ADDRESS NetworkAddress,
  1104. PNETWORK_ADDRESS PhysicalAddress
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. This routine adds a mapping between a network address and its associated
  1109. physical address.
  1110. Arguments:
  1111. Link - Supplies a pointer to the link receiving the mapping.
  1112. NetworkAddress - Supplies a pointer to the network address whose physical
  1113. mapping is known.
  1114. PhysicalAddress - Supplies a pointer to the physical address corresponding
  1115. to the network address.
  1116. Return Value:
  1117. Status code.
  1118. --*/
  1119. {
  1120. PADDRESS_TRANSLATION_ENTRY FoundEntry;
  1121. PRED_BLACK_TREE_NODE FoundNode;
  1122. BOOL LockHeld;
  1123. PADDRESS_TRANSLATION_ENTRY NewEntry;
  1124. KSTATUS Status;
  1125. ASSERT(KeGetRunLevel() == RunLevelLow);
  1126. LockHeld = FALSE;
  1127. //
  1128. // Create the new address translation entry.
  1129. //
  1130. NewEntry = MmAllocatePagedPool(sizeof(ADDRESS_TRANSLATION_ENTRY),
  1131. NET_CORE_ALLOCATION_TAG);
  1132. if (NewEntry == NULL) {
  1133. Status = STATUS_INSUFFICIENT_RESOURCES;
  1134. goto AddNetworkAddressTranslationEnd;
  1135. }
  1136. RtlCopyMemory(&(NewEntry->NetworkAddress),
  1137. NetworkAddress,
  1138. sizeof(NETWORK_ADDRESS));
  1139. RtlCopyMemory(&(NewEntry->PhysicalAddress),
  1140. PhysicalAddress,
  1141. sizeof(NETWORK_ADDRESS));
  1142. Status = STATUS_SUCCESS;
  1143. KeAcquireQueuedLock(Link->QueuedLock);
  1144. LockHeld = TRUE;
  1145. FoundNode = RtlRedBlackTreeSearch(&(Link->AddressTranslationTree),
  1146. &(NewEntry->TreeEntry));
  1147. //
  1148. // If a node is found, update it.
  1149. //
  1150. if (FoundNode != NULL) {
  1151. FoundEntry = RED_BLACK_TREE_VALUE(FoundNode,
  1152. ADDRESS_TRANSLATION_ENTRY,
  1153. TreeEntry);
  1154. RtlCopyMemory(&(FoundEntry->NetworkAddress),
  1155. NetworkAddress,
  1156. sizeof(NETWORK_ADDRESS));
  1157. RtlCopyMemory(&(FoundEntry->PhysicalAddress),
  1158. PhysicalAddress,
  1159. sizeof(NETWORK_ADDRESS));
  1160. //
  1161. // No pre-existing entry exists for this network address, add the new
  1162. // entry. Null out the local to indicate the entry was added.
  1163. //
  1164. } else {
  1165. RtlRedBlackTreeInsert(&(Link->AddressTranslationTree),
  1166. &(NewEntry->TreeEntry));
  1167. KeSignalEvent(Link->AddressTranslationEvent, SignalOptionPulse);
  1168. NewEntry = NULL;
  1169. }
  1170. AddNetworkAddressTranslationEnd:
  1171. if (LockHeld != FALSE) {
  1172. KeReleaseQueuedLock(Link->QueuedLock);
  1173. }
  1174. if (NewEntry != NULL) {
  1175. MmFreePagedPool(NewEntry);
  1176. }
  1177. return Status;
  1178. }
  1179. NET_API
  1180. KSTATUS
  1181. NetFindEntryForAddress (
  1182. PNET_LINK Link,
  1183. PNETWORK_ADDRESS Address,
  1184. BOOL AnyAddress,
  1185. PNET_LINK_ADDRESS_ENTRY *AddressEntry
  1186. )
  1187. /*++
  1188. Routine Description:
  1189. This routine searches for a link address entry within the given link
  1190. matching the desired address.
  1191. Arguments:
  1192. Link - Supplies the link whose address entries should be searched.
  1193. Address - Supplies the address to search for.
  1194. AnyAddress - Supplies a boolean indicating whether or not the given address
  1195. is the owning network's any address.
  1196. AddressEntry - Supplies a pointer where the address entry will be returned
  1197. on success.
  1198. Return Value:
  1199. STATUS_SUCCESS if a link was found and bound with the socket.
  1200. STATUS_INVALID_ADDRESS if no link was found to own that address.
  1201. --*/
  1202. {
  1203. COMPARISON_RESULT ComparisonResult;
  1204. PNET_LINK_ADDRESS_ENTRY CurrentAddress;
  1205. PLIST_ENTRY CurrentAddressEntry;
  1206. KSTATUS Status;
  1207. ASSERT(KeGetRunLevel() == RunLevelLow);
  1208. Status = STATUS_INVALID_ADDRESS;
  1209. *AddressEntry = NULL;
  1210. //
  1211. // Loop over all the addresses owned by this link.
  1212. //
  1213. KeAcquireQueuedLock(Link->QueuedLock);
  1214. CurrentAddressEntry = Link->LinkAddressList.Next;
  1215. while (CurrentAddressEntry != &(Link->LinkAddressList)) {
  1216. CurrentAddress = LIST_VALUE(CurrentAddressEntry,
  1217. NET_LINK_ADDRESS_ENTRY,
  1218. ListEntry);
  1219. CurrentAddressEntry = CurrentAddressEntry->Next;
  1220. //
  1221. // Only a search for an any address can match a non-configured link
  1222. // address entry.
  1223. //
  1224. if ((CurrentAddress->Configured == FALSE) && (AnyAddress == FALSE)) {
  1225. continue;
  1226. }
  1227. //
  1228. // Compare the full addresses unless the any address was supplied. In
  1229. // that case, only the port and network need to match.
  1230. //
  1231. if (AnyAddress == FALSE) {
  1232. ComparisonResult = NetpCompareNetworkAddresses(
  1233. &(CurrentAddress->Address),
  1234. Address);
  1235. if (ComparisonResult == ComparisonResultSame) {
  1236. *AddressEntry = CurrentAddress;
  1237. Status = STATUS_SUCCESS;
  1238. break;
  1239. }
  1240. } else if ((CurrentAddress->Address.Port == Address->Port) &&
  1241. (CurrentAddress->Address.Domain == Address->Domain)) {
  1242. *AddressEntry = CurrentAddress;
  1243. Status = STATUS_SUCCESS;
  1244. break;
  1245. }
  1246. }
  1247. KeReleaseQueuedLock(Link->QueuedLock);
  1248. return Status;
  1249. }
  1250. NET_API
  1251. KSTATUS
  1252. NetActivateSocket (
  1253. PNET_SOCKET Socket
  1254. )
  1255. /*++
  1256. Routine Description:
  1257. This routine activates a socket, making it eligible to receive data.
  1258. Arguments:
  1259. Socket - Supplies a pointer to the initialized socket to activate.
  1260. Return Value:
  1261. Status code.
  1262. --*/
  1263. {
  1264. if (Socket->BindingType == SocketBindingInvalid) {
  1265. return STATUS_NOT_CONFIGURED;
  1266. }
  1267. //
  1268. // Activate the socket and move on.
  1269. //
  1270. RtlAtomicOr32(&(Socket->Flags), NET_SOCKET_FLAG_ACTIVE);
  1271. return STATUS_SUCCESS;
  1272. }
  1273. NET_API
  1274. VOID
  1275. NetDeactivateSocket (
  1276. PNET_SOCKET Socket
  1277. )
  1278. /*++
  1279. Routine Description:
  1280. This routine removes a socket from the socket tree it's on, removing it
  1281. from eligibility to receive packets. If the socket is removed from the
  1282. tree then a reference will be released.
  1283. Arguments:
  1284. Socket - Supplies a pointer to the initialized socket to remove from the
  1285. socket tree.
  1286. Return Value:
  1287. None.
  1288. --*/
  1289. {
  1290. if (((Socket->Flags & NET_SOCKET_FLAG_ACTIVE) == 0) &&
  1291. (Socket->BindingType == SocketBindingInvalid)) {
  1292. return;
  1293. }
  1294. if (Socket->KernelSocket.Type == NetSocketRaw) {
  1295. KeAcquireSharedExclusiveLockExclusive(NetRawSocketsLock);
  1296. NetpDeactivateRawSocketUnlocked(Socket);
  1297. KeReleaseSharedExclusiveLockExclusive(NetRawSocketsLock);
  1298. } else {
  1299. KeAcquireSharedExclusiveLockExclusive(Socket->Protocol->SocketLock);
  1300. NetpDeactivateSocketUnlocked(Socket);
  1301. KeReleaseSharedExclusiveLockExclusive(Socket->Protocol->SocketLock);
  1302. }
  1303. return;
  1304. }
  1305. NET_API
  1306. KSTATUS
  1307. NetBindSocket (
  1308. PNET_SOCKET Socket,
  1309. NET_SOCKET_BINDING_TYPE BindingType,
  1310. PNET_LINK_LOCAL_ADDRESS LocalInformation,
  1311. PNETWORK_ADDRESS RemoteAddress,
  1312. ULONG Flags
  1313. )
  1314. /*++
  1315. Routine Description:
  1316. This routine officially binds a socket to a local address, local port,
  1317. remote address and remote port tuple by adding it to the appropriate socket
  1318. tree. It can also re-bind a socket in the case where it has already been
  1319. bound to a different tree. Raw sockets are handled specially as ports do
  1320. not make sense for raw sockets; they are put in a list that contains all
  1321. raw sockets.
  1322. Arguments:
  1323. Socket - Supplies a pointer to the initialized socket to bind.
  1324. BindingType - Supplies the type of binding for the socket.
  1325. LocalInformation - Supplies an optional pointer to the information for the
  1326. local link or address to which the socket shall be bound. Use this for
  1327. unbound sockets, leaving the link and link address NULL.
  1328. RemoteAddress - Supplies an optional pointer to a remote address to use
  1329. when fully binding the socket.
  1330. Flags - Supplies a bitmask of binding flags. See NET_SOCKET_BINDING_FLAG_*
  1331. for definitions.
  1332. Return Value:
  1333. Status code.
  1334. --*/
  1335. {
  1336. ULONG AttemptIndex;
  1337. BOOL Available;
  1338. ULONG CurrentPort;
  1339. PRED_BLACK_TREE_NODE ExistingNode;
  1340. PNET_SOCKET ExistingSocket;
  1341. PNET_LINK Link;
  1342. PNETWORK_ADDRESS LocalAddress;
  1343. NET_LINK_LOCAL_ADDRESS LocalInformationBuffer;
  1344. BOOL LockHeld;
  1345. ULONG OldFlags;
  1346. ULONG OriginalPort;
  1347. PNET_PROTOCOL_ENTRY Protocol;
  1348. BOOL Reinsert;
  1349. NET_SOCKET SearchSocket;
  1350. BOOL SkipValidation;
  1351. KSTATUS Status;
  1352. PRED_BLACK_TREE Tree;
  1353. ASSERT(KeGetRunLevel() == RunLevelLow);
  1354. ASSERT((LocalInformation != NULL) || (RemoteAddress != NULL));
  1355. ASSERT((BindingType == SocketFullyBound) || (LocalInformation != NULL));
  1356. ASSERT((BindingType != SocketFullyBound) || (RemoteAddress != NULL));
  1357. LockHeld = FALSE;
  1358. Protocol = Socket->Protocol;
  1359. Reinsert = FALSE;
  1360. //
  1361. // If the socket is to be fully bound, then a remote address must have been
  1362. // supplied. Make sure local information is present as well via an implicit
  1363. // local binding.
  1364. //
  1365. if ((BindingType == SocketFullyBound) && (LocalInformation == NULL)) {
  1366. OriginalPort = RemoteAddress->Port;
  1367. RemoteAddress->Port = 0;
  1368. Status = NetFindLinkForRemoteAddress(RemoteAddress,
  1369. &LocalInformationBuffer);
  1370. RemoteAddress->Port = OriginalPort;
  1371. if (!KSUCCESS(Status)) {
  1372. goto BindSocketEnd;
  1373. }
  1374. LocalInformation = &LocalInformationBuffer;
  1375. }
  1376. //
  1377. // Raw sockets are treated a bit differently. Handle that separately.
  1378. //
  1379. if (Socket->KernelSocket.Type == NetSocketRaw) {
  1380. Status = NetpBindRawSocket(Socket,
  1381. BindingType,
  1382. LocalInformation,
  1383. RemoteAddress,
  1384. Flags);
  1385. goto BindSocketEnd;
  1386. }
  1387. SkipValidation = FALSE;
  1388. KeAcquireSharedExclusiveLockExclusive(Protocol->SocketLock);
  1389. LockHeld = TRUE;
  1390. //
  1391. // A socket is not allowed to become "less bound".
  1392. //
  1393. if ((Socket->BindingType != SocketBindingInvalid) &&
  1394. (Socket->BindingType > BindingType)) {
  1395. Status = STATUS_INVALID_PARAMETER;
  1396. goto BindSocketEnd;
  1397. }
  1398. //
  1399. // A socket is not allowed to rebind unless it is to the fully bound state.
  1400. //
  1401. if ((Socket->BindingType != SocketFullyBound) &&
  1402. (Socket->BindingType == BindingType)) {
  1403. Status = STATUS_INVALID_PARAMETER;
  1404. goto BindSocketEnd;
  1405. }
  1406. //
  1407. // Either the existing local port or the future local port better be zero
  1408. // if they do not match.
  1409. //
  1410. if ((Socket->LocalAddress.Port != LocalInformation->LocalAddress.Port) &&
  1411. (Socket->LocalAddress.Port != 0) &&
  1412. (LocalInformation->LocalAddress.Port != 0)) {
  1413. Status = STATUS_INVALID_PARAMETER;
  1414. goto BindSocketEnd;
  1415. }
  1416. //
  1417. // If the socket is locally bound and destined to be fully bound, then the
  1418. // link and link address entry better match. The supplied link was chosen
  1419. // specifically as a link that can reach the remote address.
  1420. //
  1421. if (((Socket->BindingType == SocketLocallyBound) ||
  1422. (Socket->BindingType == SocketFullyBound)) &&
  1423. (BindingType == SocketFullyBound) &&
  1424. ((Socket->Link != LocalInformation->Link) ||
  1425. (Socket->LinkAddress != LocalInformation->LinkAddress))) {
  1426. Status = STATUS_INVALID_PARAMETER;
  1427. goto BindSocketEnd;
  1428. }
  1429. //
  1430. // If the socket is already in a tree, temporarily remove it. It will
  1431. // either get moved to the new tree or be restored, untouched, on error.
  1432. //
  1433. if (Socket->BindingType != SocketBindingInvalid) {
  1434. RtlRedBlackTreeRemove(&(Protocol->SocketTree[Socket->BindingType]),
  1435. &(Socket->U.TreeEntry));
  1436. SkipValidation = TRUE;
  1437. Reinsert = TRUE;
  1438. //
  1439. // If the socket is the forked copy of some listening socket, skip
  1440. // validation. This socket is allowed to share the same local address and
  1441. // port.
  1442. //
  1443. } else if ((Socket->Flags & NET_SOCKET_FLAG_FORKED_LISTENER) != 0) {
  1444. ASSERT(LocalInformation != NULL);
  1445. ASSERT(BindingType == SocketLocallyBound);
  1446. ASSERT(LocalInformation->LocalAddress.Port != 0);
  1447. SkipValidation = TRUE;
  1448. }
  1449. //
  1450. // Determine the local address and link. They're in the socket if the
  1451. // socket was already locally bound. Otherwise they're in the local
  1452. // information.
  1453. //
  1454. if ((Socket->BindingType == SocketLocallyBound) ||
  1455. (Socket->BindingType == SocketFullyBound)) {
  1456. ASSERT(Socket->Link != NULL);
  1457. Link = Socket->Link;
  1458. LocalAddress = &(Socket->LocalAddress);
  1459. } else {
  1460. ASSERT(LocalInformation != NULL);
  1461. ASSERT(Socket->Link == NULL);
  1462. Link = LocalInformation->Link;
  1463. LocalAddress = &(LocalInformation->LocalAddress);
  1464. //
  1465. // If the socket used to be unbound, then the local address gets the
  1466. // unbound port.
  1467. //
  1468. if (Socket->BindingType == SocketUnbound) {
  1469. LocalAddress->Port = Socket->LocalAddress.Port;
  1470. }
  1471. }
  1472. //
  1473. // Debug print the socket binding.
  1474. //
  1475. if (NetGlobalDebug != FALSE) {
  1476. switch (BindingType) {
  1477. case SocketUnbound:
  1478. RtlDebugPrint("Net: Binding unbound socket %x.\n", Socket);
  1479. break;
  1480. case SocketLocallyBound:
  1481. RtlDebugPrint("Net: Binding locally bound socket %x: ", Socket);
  1482. NetpDebugPrintNetworkAddress(Socket->Network, LocalAddress);
  1483. RtlDebugPrint("\n");
  1484. break;
  1485. case SocketFullyBound:
  1486. RtlDebugPrint("Net: Binding fully bound socket %x, Local ", Socket);
  1487. NetpDebugPrintNetworkAddress(Socket->Network, LocalAddress);
  1488. RtlDebugPrint(", Remote ");
  1489. NetpDebugPrintNetworkAddress(Socket->Network, RemoteAddress);
  1490. RtlDebugPrint(".\n");
  1491. break;
  1492. default:
  1493. ASSERT(FALSE);
  1494. break;
  1495. }
  1496. }
  1497. //
  1498. // If the socket is bound to a link and the link is down, then do not
  1499. // insert the socket.
  1500. //
  1501. // N.B. Because taking a link down requires iterating over the socket
  1502. // trees, this does not require any additional synchronization. The
  1503. // link state is updated and then it waits on the socket lock. So,
  1504. // either changing the link state acquired the socket lock first, in
  1505. // which case the link state is already set to 'down' and this should
  1506. // fail. Or this routine acquired the lock first and if it notices the
  1507. // link is down, great. If it doesn't, then the socket will get put in
  1508. // the tree and the process of taking the link down will clean it up.
  1509. // Of course the link could come back up after this check, but that's
  1510. // OK. It's up to the caller to try again.
  1511. //
  1512. if ((Link != NULL) && (Link->LinkUp == FALSE)) {
  1513. NetpDetachSocket(Socket);
  1514. Status = STATUS_NO_NETWORK_CONNECTION;
  1515. goto BindSocketEnd;
  1516. }
  1517. //
  1518. // If no local port number is assigned, attempt to assign one from the
  1519. // ephemeral port range. This will result in a unique tuple, even for fully
  1520. // bound sockets. Some networks allow use of port zero, so skip this if
  1521. // indicated by the binding flags.
  1522. //
  1523. if ((LocalAddress->Port == 0) &&
  1524. ((Flags & NET_SOCKET_BINDING_FLAG_NO_PORT_ASSIGNMENT) == 0)) {
  1525. ASSERT(SkipValidation == FALSE);
  1526. CurrentPort = HlQueryTimeCounter() % NET_EPHEMERAL_PORT_COUNT;
  1527. //
  1528. // Find an ephemeral port for this connection.
  1529. //
  1530. Status = STATUS_RESOURCE_IN_USE;
  1531. for (AttemptIndex = 0;
  1532. AttemptIndex < NET_EPHEMERAL_PORT_COUNT;
  1533. AttemptIndex += 1) {
  1534. LocalAddress->Port = CurrentPort + NET_EPHEMERAL_PORT_START;
  1535. //
  1536. // If the ephemeral port is already being used by a socket, then
  1537. // try again.
  1538. //
  1539. Available = NetpCheckLocalAddressAvailability(Socket, LocalAddress);
  1540. if (Available != FALSE) {
  1541. if (NetGlobalDebug != FALSE) {
  1542. RtlDebugPrint("Net: Using ephemeral port %d.\n",
  1543. LocalAddress->Port);
  1544. }
  1545. Status = STATUS_SUCCESS;
  1546. break;
  1547. }
  1548. CurrentPort += 1;
  1549. if (CurrentPort >= NET_EPHEMERAL_PORT_COUNT) {
  1550. CurrentPort = 0;
  1551. }
  1552. }
  1553. if (!KSUCCESS(Status)) {
  1554. if (NetGlobalDebug != FALSE) {
  1555. RtlDebugPrint("Net: Rejecting binding for socket %x because "
  1556. "ephemeral ports exhausted.\n",
  1557. Socket);
  1558. goto BindSocketEnd;
  1559. }
  1560. }
  1561. //
  1562. // Do checks for the case where the port was already defined. If the socket
  1563. // was previously in the tree, then the local address is OK. Just make sure
  1564. // that if this is to be a fully bound socket, that the 5-tuple is unique.
  1565. // The exception is if the existing fully bound socket is in the time wait
  1566. // state; deactivate such a socket.
  1567. //
  1568. } else {
  1569. if (SkipValidation == FALSE) {
  1570. Available = NetpCheckLocalAddressAvailability(Socket, LocalAddress);
  1571. if (Available == FALSE) {
  1572. Status = STATUS_ADDRESS_IN_USE;
  1573. goto BindSocketEnd;
  1574. }
  1575. }
  1576. if (BindingType == SocketFullyBound) {
  1577. SearchSocket.Protocol = Socket->Protocol;
  1578. RtlCopyMemory(&(SearchSocket.LocalAddress),
  1579. LocalAddress,
  1580. sizeof(NETWORK_ADDRESS));
  1581. RtlCopyMemory(&(SearchSocket.RemoteAddress),
  1582. RemoteAddress,
  1583. sizeof(NETWORK_ADDRESS));
  1584. Tree = &(Protocol->SocketTree[SocketFullyBound]);
  1585. ExistingNode = RtlRedBlackTreeSearch(Tree,
  1586. &(SearchSocket.U.TreeEntry));
  1587. if (ExistingNode != NULL) {
  1588. ExistingSocket = RED_BLACK_TREE_VALUE(ExistingNode,
  1589. NET_SOCKET,
  1590. U.TreeEntry);
  1591. if ((ExistingSocket->Flags & NET_SOCKET_FLAG_TIME_WAIT) != 0) {
  1592. NetpDeactivateSocketUnlocked(ExistingSocket);
  1593. } else {
  1594. if (NetGlobalDebug != FALSE) {
  1595. RtlDebugPrint("Net: Rejected binding of socket %x "
  1596. "because of existing socket %x.\n",
  1597. Socket,
  1598. ExistingSocket);
  1599. }
  1600. Status = STATUS_ADDRESS_IN_USE;
  1601. goto BindSocketEnd;
  1602. }
  1603. }
  1604. }
  1605. }
  1606. //
  1607. // This socket is good to go to use the remote address.
  1608. //
  1609. if (RemoteAddress != NULL) {
  1610. ASSERT(BindingType == SocketFullyBound);
  1611. RtlCopyMemory(&(Socket->RemoteAddress),
  1612. RemoteAddress,
  1613. sizeof(NETWORK_ADDRESS));
  1614. }
  1615. //
  1616. // Set the local information in the socket if it isn't already locally
  1617. // bound.
  1618. //
  1619. if ((Socket->BindingType != SocketLocallyBound) &&
  1620. (Socket->BindingType != SocketFullyBound)) {
  1621. ASSERT(Socket->Link == NULL);
  1622. ASSERT(LocalInformation != NULL);
  1623. if (LocalInformation->Link != NULL) {
  1624. ASSERT(LocalInformation->LinkAddress != NULL);
  1625. NetLinkAddReference(LocalInformation->Link);
  1626. Socket->Link = LocalInformation->Link;
  1627. Socket->LinkAddress = LocalInformation->LinkAddress;
  1628. //
  1629. // Now is the time to update the socket's max packet size,
  1630. // header size, and footer size based on the link.
  1631. //
  1632. NetpGetPacketSizeInformation(Socket->Link,
  1633. Socket,
  1634. &(Socket->PacketSizeInformation));
  1635. }
  1636. RtlCopyMemory(&(Socket->LocalAddress),
  1637. LocalAddress,
  1638. sizeof(NETWORK_ADDRESS));
  1639. }
  1640. //
  1641. // Mark the socket as active if requested. If this is moving to the fully
  1642. // bound state from another state, record whether or not it was previously
  1643. // active.
  1644. //
  1645. if ((Flags & NET_SOCKET_BINDING_FLAG_ACTIVATE) != 0) {
  1646. OldFlags = RtlAtomicOr32(&(Socket->Flags), NET_SOCKET_FLAG_ACTIVE);
  1647. if ((BindingType == SocketFullyBound) &&
  1648. (Socket->BindingType != SocketFullyBound) &&
  1649. ((OldFlags & NET_SOCKET_FLAG_ACTIVE) != 0)) {
  1650. RtlAtomicOr32(&(Socket->Flags), NET_SOCKET_FLAG_PREVIOUSLY_ACTIVE);
  1651. }
  1652. }
  1653. //
  1654. // Welcome this new friend into the bound sockets tree.
  1655. //
  1656. RtlRedBlackTreeInsert(&(Protocol->SocketTree[BindingType]),
  1657. &(Socket->U.TreeEntry));
  1658. Socket->BindingType = BindingType;
  1659. //
  1660. // Increment the reference count on the socket so that it cannot disappear
  1661. // while being on the tree.
  1662. //
  1663. IoSocketAddReference(&(Socket->KernelSocket));
  1664. Status = STATUS_SUCCESS;
  1665. BindSocketEnd:
  1666. if (!KSUCCESS(Status)) {
  1667. if (Reinsert != FALSE) {
  1668. ASSERT(Socket->BindingType != SocketBindingInvalid);
  1669. Tree = &(Protocol->SocketTree[Socket->BindingType]);
  1670. RtlRedBlackTreeInsert(Tree, &(Socket->U.TreeEntry));
  1671. }
  1672. }
  1673. if (LockHeld != FALSE) {
  1674. KeReleaseSharedExclusiveLockExclusive(Protocol->SocketLock);
  1675. }
  1676. if ((LocalInformation == &LocalInformationBuffer) &&
  1677. (LocalInformationBuffer.Link != NULL)) {
  1678. NetLinkReleaseReference(LocalInformationBuffer.Link);
  1679. }
  1680. return Status;
  1681. }
  1682. NET_API
  1683. KSTATUS
  1684. NetDisconnectSocket (
  1685. PNET_SOCKET Socket
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. This routine disconnects a socket from the fully bound state, rolling it
  1690. back to the locally bound state.
  1691. Arguments:
  1692. Socket - Supplies a pointer to the socket to disconnect.
  1693. Return Value:
  1694. Status code.
  1695. --*/
  1696. {
  1697. PNET_PROTOCOL_ENTRY Protocol;
  1698. KSTATUS Status;
  1699. //
  1700. // Disconnect only makes sense on fully bound sockets.
  1701. //
  1702. if (Socket->BindingType != SocketFullyBound) {
  1703. return STATUS_INVALID_PARAMETER;
  1704. }
  1705. //
  1706. // Handle raw sockets separately.
  1707. //
  1708. Protocol = Socket->Protocol;
  1709. if (Socket->KernelSocket.Type == NetSocketRaw) {
  1710. KeAcquireSharedExclusiveLockExclusive(NetRawSocketsLock);
  1711. if (Socket->BindingType != SocketFullyBound) {
  1712. Status = STATUS_INVALID_PARAMETER;
  1713. goto DisconnectSocketEnd;
  1714. }
  1715. //
  1716. // The disconnect just wipes out the remote address. The socket may
  1717. // have been implicitly bound on the connect. So be it. It stays
  1718. // locally bound.
  1719. //
  1720. RtlZeroMemory(&(Socket->RemoteAddress), sizeof(NETWORK_ADDRESS));
  1721. //
  1722. // If the socket was previously inactive before becoming fully bound,
  1723. // return it to the inactivate state.
  1724. //
  1725. if ((Socket->Flags & NET_SOCKET_FLAG_PREVIOUSLY_ACTIVE) == 0) {
  1726. RtlAtomicAnd32(&(Socket->Flags), ~NET_SOCKET_FLAG_ACTIVE);
  1727. }
  1728. Socket->BindingType = SocketLocallyBound;
  1729. } else {
  1730. KeAcquireSharedExclusiveLockExclusive(Protocol->SocketLock);
  1731. if (Socket->BindingType != SocketFullyBound) {
  1732. Status = STATUS_INVALID_PARAMETER;
  1733. goto DisconnectSocketEnd;
  1734. }
  1735. //
  1736. // The disconnect just wipes out the remote address. The socket may
  1737. // have been implicitly bound on the connect. So be it. It stays
  1738. // locally bound.
  1739. //
  1740. RtlZeroMemory(&(Socket->RemoteAddress), sizeof(NETWORK_ADDRESS));
  1741. //
  1742. // If the socket was previously inactive before becoming fully bound,
  1743. // return it to the inactive state and clear it from the last found
  1744. // cache of one.
  1745. //
  1746. if ((Socket->Flags & NET_SOCKET_FLAG_PREVIOUSLY_ACTIVE) == 0) {
  1747. RtlAtomicAnd32(&(Socket->Flags), ~NET_SOCKET_FLAG_ACTIVE);
  1748. if (Socket == Protocol->LastSocket) {
  1749. Protocol->LastSocket = NULL;
  1750. }
  1751. }
  1752. //
  1753. // Remove the socket from the fully bound tree and put it in the
  1754. // locally bound tree. As the socket remains in the tree, the reference
  1755. // on the link does not need to be updated.
  1756. //
  1757. RtlRedBlackTreeRemove(&(Protocol->SocketTree[SocketFullyBound]),
  1758. &(Socket->U.TreeEntry));
  1759. RtlRedBlackTreeInsert(&(Protocol->SocketTree[SocketLocallyBound]),
  1760. &(Socket->U.TreeEntry));
  1761. Socket->BindingType = SocketLocallyBound;
  1762. }
  1763. DisconnectSocketEnd:
  1764. if (Socket->KernelSocket.Type == NetSocketRaw) {
  1765. KeReleaseSharedExclusiveLockExclusive(NetRawSocketsLock);
  1766. } else {
  1767. KeReleaseSharedExclusiveLockExclusive(Protocol->SocketLock);
  1768. }
  1769. return Status;
  1770. }
  1771. NET_API
  1772. KSTATUS
  1773. NetInitializeSocketLinkOverride (
  1774. PNET_SOCKET Socket,
  1775. PNET_LINK_LOCAL_ADDRESS LinkInformation,
  1776. PNET_SOCKET_LINK_OVERRIDE LinkOverride
  1777. )
  1778. /*++
  1779. Routine Description:
  1780. This routine initializes the given socket link override structure with the
  1781. appropriate mix of socket and link information. The routine will fail if it
  1782. determines that the socket is already bound to a link.
  1783. Arguments:
  1784. Socket - Supplies a pointer to a network socket.
  1785. LinkInformation - Supplies a pointer to link local address information.
  1786. LinkOverride - Supplies a pointer to a socket link override structure that
  1787. will be filled in by this routine.
  1788. Return Value:
  1789. STATUS_SUCCESS if the link override was successfully filled in.
  1790. STATUS_CONNECTION_EXISTS if the socket is already bound to a link.
  1791. --*/
  1792. {
  1793. if (Socket->Link != NULL) {
  1794. return STATUS_CONNECTION_EXISTS;
  1795. }
  1796. //
  1797. // The socket is not yet associated with a link. Since the unbound header
  1798. // size, footer size, and max packet size are saved in the socket, there is
  1799. // no need to protect this under a socket lock.
  1800. //
  1801. NetpGetPacketSizeInformation(LinkInformation->Link,
  1802. Socket,
  1803. &(LinkOverride->PacketSizeInformation));
  1804. RtlCopyMemory(&(LinkOverride->LinkInformation),
  1805. LinkInformation,
  1806. sizeof(NET_LINK_LOCAL_ADDRESS));
  1807. NetLinkAddReference(LinkOverride->LinkInformation.Link);
  1808. return STATUS_SUCCESS;
  1809. }
  1810. NET_API
  1811. PNET_SOCKET
  1812. NetFindSocket (
  1813. PNET_PROTOCOL_ENTRY ProtocolEntry,
  1814. PNETWORK_ADDRESS LocalAddress,
  1815. PNETWORK_ADDRESS RemoteAddress
  1816. )
  1817. /*++
  1818. Routine Description:
  1819. This routine attempts to find an active socket that matches the given
  1820. parameters. If the socket is found and returned, the reference count will
  1821. be increased on it. It is the caller's responsiblity to release that
  1822. reference.
  1823. Arguments:
  1824. ProtocolEntry - Supplies the protocol the socket must be on.
  1825. LocalAddress - Supplies a pointer to the local address of the socket.
  1826. RemoteAddress - Supplies a pointer to the remote address of the socket.
  1827. Return Value:
  1828. Returns a pointer to a socket matching the given parameters, with an
  1829. increased reference count.
  1830. NULL if no socket matches.
  1831. --*/
  1832. {
  1833. PRED_BLACK_TREE_NODE FoundNode;
  1834. PNET_SOCKET FoundSocket;
  1835. PNET_SOCKET LastSocket;
  1836. COMPARISON_RESULT Result;
  1837. NET_SOCKET SearchEntry;
  1838. PRED_BLACK_TREE Tree;
  1839. ASSERT(KeGetRunLevel() == RunLevelLow);
  1840. FoundSocket = NULL;
  1841. //
  1842. // Check to see if the given remote and local addresses match the last
  1843. // fully bound socket found. This speeds up the search process when there
  1844. // isn't a whole lot of activity.
  1845. //
  1846. KeAcquireSharedExclusiveLockShared(ProtocolEntry->SocketLock);
  1847. LastSocket = ProtocolEntry->LastSocket;
  1848. if (LastSocket != NULL) {
  1849. ASSERT(LastSocket->BindingType == SocketFullyBound);
  1850. Result = NetpMatchFullyBoundSocket(LastSocket,
  1851. LocalAddress,
  1852. RemoteAddress);
  1853. if (Result == ComparisonResultSame) {
  1854. FoundNode = NULL;
  1855. FoundSocket = LastSocket;
  1856. goto FindSocketEnd;
  1857. }
  1858. }
  1859. //
  1860. // Fill out a fake socket entry for search purposes.
  1861. //
  1862. RtlCopyMemory(&(SearchEntry.LocalAddress),
  1863. LocalAddress,
  1864. sizeof(NETWORK_ADDRESS));
  1865. RtlCopyMemory(&(SearchEntry.RemoteAddress),
  1866. RemoteAddress,
  1867. sizeof(NETWORK_ADDRESS));
  1868. //
  1869. // Loop through each tree looking for a match, starting with the most
  1870. // specified parameters (local and remote address), and working towards the
  1871. // most generic parameters (local port only).
  1872. //
  1873. Tree = &(ProtocolEntry->SocketTree[SocketFullyBound]);
  1874. FoundNode = RtlRedBlackTreeSearch(Tree, &(SearchEntry.U.TreeEntry));
  1875. if (FoundNode != NULL) {
  1876. goto FindSocketEnd;
  1877. }
  1878. Tree = &(ProtocolEntry->SocketTree[SocketLocallyBound]);
  1879. FoundNode = RtlRedBlackTreeSearch(Tree, &(SearchEntry.U.TreeEntry));
  1880. if (FoundNode != NULL) {
  1881. goto FindSocketEnd;
  1882. }
  1883. Tree = &(ProtocolEntry->SocketTree[SocketUnbound]);
  1884. FoundNode = RtlRedBlackTreeSearch(Tree, &(SearchEntry.U.TreeEntry));
  1885. if (FoundNode != NULL) {
  1886. goto FindSocketEnd;
  1887. }
  1888. FindSocketEnd:
  1889. if (FoundNode != NULL) {
  1890. FoundSocket = RED_BLACK_TREE_VALUE(FoundNode, NET_SOCKET, U.TreeEntry);
  1891. }
  1892. if (FoundSocket != NULL) {
  1893. //
  1894. // If the socket is not active, act as if it were never seen. The
  1895. // cached socket should never be found as inactive. Deactivating the
  1896. // cached socket clears the cache.
  1897. //
  1898. if ((FoundSocket->Flags & NET_SOCKET_FLAG_ACTIVE) == 0) {
  1899. ASSERT(FoundSocket != ProtocolEntry->LastSocket);
  1900. FoundSocket = NULL;
  1901. //
  1902. // Otherwise, increment the reference count so the socket cannot
  1903. // disappear once the lock is released.
  1904. //
  1905. } else {
  1906. IoSocketAddReference(&(FoundSocket->KernelSocket));
  1907. if (FoundSocket->BindingType == SocketFullyBound) {
  1908. ProtocolEntry->LastSocket = FoundSocket;
  1909. }
  1910. }
  1911. }
  1912. KeReleaseSharedExclusiveLockShared(ProtocolEntry->SocketLock);
  1913. return FoundSocket;
  1914. }
  1915. NET_API
  1916. KSTATUS
  1917. NetGetSetNetworkDeviceInformation (
  1918. PNET_LINK Link,
  1919. PNET_LINK_ADDRESS_ENTRY LinkAddressEntry,
  1920. PNETWORK_DEVICE_INFORMATION Information,
  1921. BOOL Set
  1922. )
  1923. /*++
  1924. Routine Description:
  1925. This routine gets or sets the network device information for a particular
  1926. link.
  1927. Arguments:
  1928. Link - Supplies a pointer to the link to work with.
  1929. LinkAddressEntry - Supplies an optional pointer to the specific address
  1930. entry to set. If NULL, a link address entry matching the network type
  1931. contained in the information will be found.
  1932. Information - Supplies a pointer that either receives the device
  1933. information, or contains the new information to set. For set operations,
  1934. the information buffer will contain the current settings on return.
  1935. Set - Supplies a boolean indicating if the information should be set or
  1936. returned.
  1937. Return Value:
  1938. Status code.
  1939. --*/
  1940. {
  1941. PLIST_ENTRY CurrentEntry;
  1942. ULONG DnsServerIndex;
  1943. NET_DOMAIN_TYPE Domain;
  1944. BOOL LockHeld;
  1945. BOOL OriginalConfiguredState;
  1946. BOOL SameAddress;
  1947. BOOL StaticAddress;
  1948. KSTATUS Status;
  1949. ASSERT(KeGetRunLevel() == RunLevelLow);
  1950. if (Information->Version < NETWORK_DEVICE_INFORMATION_VERSION) {
  1951. return STATUS_INVALID_PARAMETER;
  1952. }
  1953. //
  1954. // Currently only IPv4 is supported.
  1955. //
  1956. Domain = Information->Domain;
  1957. if (Domain != NetDomainIp4) {
  1958. return STATUS_INVALID_CONFIGURATION;
  1959. }
  1960. KeAcquireQueuedLock(Link->QueuedLock);
  1961. LockHeld = TRUE;
  1962. //
  1963. // If the caller passed in a link address entry, ensure it corresponds to
  1964. // the network type they are working with.
  1965. //
  1966. if (LinkAddressEntry != NULL) {
  1967. if (Information->Domain != LinkAddressEntry->Address.Domain) {
  1968. Status = STATUS_INVALID_CONFIGURATION;
  1969. goto GetSetNetworkDeviceInformationEnd;
  1970. }
  1971. //
  1972. // Find a link address entry for this network type.
  1973. //
  1974. } else {
  1975. CurrentEntry = Link->LinkAddressList.Next;
  1976. while (CurrentEntry != &(Link->LinkAddressList)) {
  1977. LinkAddressEntry = LIST_VALUE(CurrentEntry,
  1978. NET_LINK_ADDRESS_ENTRY,
  1979. ListEntry);
  1980. if (LinkAddressEntry->Address.Domain == Information->Domain) {
  1981. break;
  1982. }
  1983. CurrentEntry = CurrentEntry->Next;
  1984. }
  1985. if (CurrentEntry == &(Link->LinkAddressList)) {
  1986. Status = STATUS_INVALID_CONFIGURATION;
  1987. goto GetSetNetworkDeviceInformationEnd;
  1988. }
  1989. }
  1990. if (Set != FALSE) {
  1991. StaticAddress = TRUE;
  1992. SameAddress = FALSE;
  1993. //
  1994. // If the caller is setting up the link, copy the parameters in.
  1995. //
  1996. if ((Information->Flags & NETWORK_DEVICE_FLAG_CONFIGURED) != 0) {
  1997. if ((Information->Address.Domain != Domain) ||
  1998. (Information->Subnet.Domain != Domain) ||
  1999. (Information->Gateway.Domain != Domain) ||
  2000. ((Information->ConfigurationMethod !=
  2001. NetworkAddressConfigurationStatic) &&
  2002. (Information->ConfigurationMethod !=
  2003. NetworkAddressConfigurationDhcp))) {
  2004. Status = STATUS_INVALID_CONFIGURATION;
  2005. goto GetSetNetworkDeviceInformationEnd;
  2006. }
  2007. if (Information->DnsServerCount > NETWORK_DEVICE_MAX_DNS_SERVERS) {
  2008. Information->DnsServerCount = NETWORK_DEVICE_MAX_DNS_SERVERS;
  2009. }
  2010. for (DnsServerIndex = 0;
  2011. DnsServerIndex < Information->DnsServerCount;
  2012. DnsServerIndex += 1) {
  2013. if (Information->DnsServers[DnsServerIndex].Domain != Domain) {
  2014. Status = STATUS_INVALID_CONFIGURATION;
  2015. goto GetSetNetworkDeviceInformationEnd;
  2016. }
  2017. }
  2018. SameAddress = RtlCompareMemory(&(LinkAddressEntry->Address),
  2019. &(Information->Address),
  2020. sizeof(NETWORK_ADDRESS));
  2021. if (SameAddress == FALSE) {
  2022. RtlCopyMemory(&(LinkAddressEntry->Address),
  2023. &(Information->Address),
  2024. sizeof(NETWORK_ADDRESS));
  2025. }
  2026. LinkAddressEntry->Address.Port = 0;
  2027. RtlCopyMemory(&(LinkAddressEntry->Subnet),
  2028. &(Information->Subnet),
  2029. sizeof(NETWORK_ADDRESS));
  2030. LinkAddressEntry->Subnet.Port = 0;
  2031. RtlCopyMemory(&(LinkAddressEntry->DefaultGateway),
  2032. &(Information->Gateway),
  2033. sizeof(NETWORK_ADDRESS));
  2034. LinkAddressEntry->DefaultGateway.Port = 0;
  2035. for (DnsServerIndex = 0;
  2036. DnsServerIndex < Information->DnsServerCount;
  2037. DnsServerIndex += 1) {
  2038. RtlCopyMemory(&(LinkAddressEntry->DnsServer[DnsServerIndex]),
  2039. &(Information->DnsServers[DnsServerIndex]),
  2040. sizeof(NETWORK_ADDRESS));
  2041. }
  2042. LinkAddressEntry->DnsServerCount = Information->DnsServerCount;
  2043. LinkAddressEntry->StaticAddress = TRUE;
  2044. if (Information->ConfigurationMethod ==
  2045. NetworkAddressConfigurationDhcp) {
  2046. LinkAddressEntry->StaticAddress = FALSE;
  2047. RtlCopyMemory(&(LinkAddressEntry->LeaseServerAddress),
  2048. &(Information->LeaseServerAddress),
  2049. sizeof(NETWORK_ADDRESS));
  2050. RtlCopyMemory(&(LinkAddressEntry->LeaseStartTime),
  2051. &(Information->LeaseStartTime),
  2052. sizeof(SYSTEM_TIME));
  2053. RtlCopyMemory(&(LinkAddressEntry->LeaseEndTime),
  2054. &(Information->LeaseEndTime),
  2055. sizeof(SYSTEM_TIME));
  2056. }
  2057. LinkAddressEntry->Configured = TRUE;
  2058. //
  2059. // Unconfigure the link and bring it down.
  2060. //
  2061. } else {
  2062. //
  2063. // If the link address is not static, then zero the address,
  2064. // leaving the network type.
  2065. //
  2066. StaticAddress = TRUE;
  2067. if (LinkAddressEntry->StaticAddress == FALSE) {
  2068. Domain = LinkAddressEntry->Address.Domain;
  2069. RtlZeroMemory(&(LinkAddressEntry->Address),
  2070. sizeof(NETWORK_ADDRESS));
  2071. LinkAddressEntry->Address.Domain = Domain;
  2072. StaticAddress = FALSE;
  2073. }
  2074. LinkAddressEntry->Configured = FALSE;
  2075. }
  2076. //
  2077. // If the address is changing or going down, invalidate all sockets
  2078. // using the address. Make sure that the link address entry is not
  2079. // marked as configured, otherwise new sockets could show up while the
  2080. // link's queued lock is relesaed.
  2081. //
  2082. if (SameAddress == FALSE) {
  2083. OriginalConfiguredState = LinkAddressEntry->Configured;
  2084. LinkAddressEntry->Configured = FALSE;
  2085. KeReleaseQueuedLock(Link->QueuedLock);
  2086. LockHeld = FALSE;
  2087. //
  2088. // Notify DHCP that the link and link address combination is now
  2089. // invalid. It may have saved state.
  2090. //
  2091. if (((Information->Flags & NETWORK_DEVICE_FLAG_CONFIGURED) == 0) &&
  2092. (StaticAddress == FALSE)) {
  2093. NetpDhcpCancelLease(Link, LinkAddressEntry);
  2094. }
  2095. //
  2096. // Notify every fully bound, locally bound, and raw socket using
  2097. // this link and link address pair that the link address is being
  2098. // disabled. Sockets may be waiting on data or in the middle of
  2099. // sending data.
  2100. //
  2101. NetpDetachSockets(Link, LinkAddressEntry);
  2102. KeAcquireQueuedLock(Link->QueuedLock);
  2103. LockHeld = TRUE;
  2104. LinkAddressEntry->Configured = OriginalConfiguredState;
  2105. }
  2106. }
  2107. //
  2108. // Now that the information has potentially been set, get the new
  2109. // information.
  2110. //
  2111. if (LockHeld == FALSE) {
  2112. KeAcquireQueuedLock(Link->QueuedLock);
  2113. LockHeld = TRUE;
  2114. }
  2115. Information->Flags = 0;
  2116. RtlCopyMemory(&(Information->PhysicalAddress),
  2117. &(LinkAddressEntry->PhysicalAddress),
  2118. sizeof(NETWORK_ADDRESS));
  2119. if (Link->LinkUp != FALSE) {
  2120. Information->Flags |= NETWORK_DEVICE_FLAG_MEDIA_CONNECTED;
  2121. }
  2122. if (LinkAddressEntry->Configured == FALSE) {
  2123. Information->ConfigurationMethod = NetworkAddressConfigurationNone;
  2124. Status = STATUS_SUCCESS;
  2125. goto GetSetNetworkDeviceInformationEnd;
  2126. }
  2127. Information->Flags |= NETWORK_DEVICE_FLAG_CONFIGURED;
  2128. Information->ConfigurationMethod = NetworkAddressConfigurationDhcp;
  2129. if (LinkAddressEntry->StaticAddress != FALSE) {
  2130. Information->ConfigurationMethod = NetworkAddressConfigurationStatic;
  2131. }
  2132. RtlCopyMemory(&(Information->Address),
  2133. &(LinkAddressEntry->Address),
  2134. sizeof(NETWORK_ADDRESS));
  2135. RtlCopyMemory(&(Information->Subnet),
  2136. &(LinkAddressEntry->Subnet),
  2137. sizeof(NETWORK_ADDRESS));
  2138. RtlCopyMemory(&(Information->Gateway),
  2139. &(LinkAddressEntry->DefaultGateway),
  2140. sizeof(NETWORK_ADDRESS));
  2141. Information->DnsServerCount = LinkAddressEntry->DnsServerCount;
  2142. for (DnsServerIndex = 0;
  2143. DnsServerIndex < Information->DnsServerCount;
  2144. DnsServerIndex += 1) {
  2145. RtlCopyMemory(&(Information->DnsServers[DnsServerIndex]),
  2146. &(LinkAddressEntry->DnsServer[DnsServerIndex]),
  2147. sizeof(NETWORK_ADDRESS));
  2148. }
  2149. if (LinkAddressEntry->StaticAddress == FALSE) {
  2150. RtlCopyMemory(&(Information->LeaseServerAddress),
  2151. &(LinkAddressEntry->LeaseServerAddress),
  2152. sizeof(NETWORK_ADDRESS));
  2153. RtlCopyMemory(&(Information->LeaseStartTime),
  2154. &(LinkAddressEntry->LeaseStartTime),
  2155. sizeof(SYSTEM_TIME));
  2156. RtlCopyMemory(&(Information->LeaseEndTime),
  2157. &(LinkAddressEntry->LeaseEndTime),
  2158. sizeof(SYSTEM_TIME));
  2159. }
  2160. Status = STATUS_SUCCESS;
  2161. GetSetNetworkDeviceInformationEnd:
  2162. if (LockHeld != FALSE) {
  2163. KeReleaseQueuedLock(Link->QueuedLock);
  2164. }
  2165. return Status;
  2166. }
  2167. NET_API
  2168. VOID
  2169. NetRawSocketsProcessReceivedData (
  2170. PNET_LINK Link,
  2171. PNET_PACKET_BUFFER Packet,
  2172. PNETWORK_ADDRESS SourceAddress,
  2173. PNETWORK_ADDRESS DestinationAddress,
  2174. ULONG NetworkProtocol
  2175. )
  2176. /*++
  2177. Routine Description:
  2178. This routine processes a received packet and sends it to any raw sockets
  2179. that should be receiving it based on the protocol, source address, and
  2180. destination address.
  2181. Arguments:
  2182. Link - Supplies a pointer to the link that received the packet.
  2183. Packet - Supplies a pointer to the network packet. It is only guaranteed to
  2184. include network layer headers, not physical layer headers.
  2185. SourceAddress - Supplies a pointer to the source (remote) address of the
  2186. packet.
  2187. DestinationAddress - Supplies a pointer to the destination (local) address
  2188. of the packet.
  2189. NetworkProtocol - Supplies the network protocol of the packet.
  2190. Return Value:
  2191. None.
  2192. --*/
  2193. {
  2194. PLIST_ENTRY CurrentEntry;
  2195. BOOL Match;
  2196. ULONG PartIndex;
  2197. PNET_PROTOCOL_ENTRY RawProtocol;
  2198. PNET_SOCKET Socket;
  2199. ASSERT(SourceAddress->Port == 0);
  2200. ASSERT(DestinationAddress->Port == 0);
  2201. ASSERT(SourceAddress->Domain == DestinationAddress->Domain);
  2202. //
  2203. // Exit immediately if the raw socket list is empty.
  2204. //
  2205. if (LIST_EMPTY(&NetRawSocketsList) != FALSE) {
  2206. return;
  2207. }
  2208. //
  2209. // Lookup the protocol used for raw sockets.
  2210. //
  2211. RawProtocol = NetGetProtocolEntry(SOCKET_INTERNET_PROTOCOL_RAW);
  2212. if (RawProtocol == NULL) {
  2213. return;
  2214. }
  2215. //
  2216. // Iterate over the raw sockets list. If any socket should be receiving the
  2217. // packet, allow it to process the data.
  2218. //
  2219. KeAcquireSharedExclusiveLockShared(NetRawSocketsLock);
  2220. CurrentEntry = NetRawSocketsList.Next;
  2221. while (CurrentEntry != &NetRawSocketsList) {
  2222. Socket = LIST_VALUE(CurrentEntry, NET_SOCKET, U.ListEntry);
  2223. CurrentEntry = CurrentEntry->Next;
  2224. ASSERT(Socket->Protocol == RawProtocol);
  2225. //
  2226. // The networks must match, first and foremost. Otherwise the protocol
  2227. // might not make sense.
  2228. //
  2229. if (Socket->KernelSocket.Domain != DestinationAddress->Domain) {
  2230. continue;
  2231. }
  2232. //
  2233. // The protocol must match. There are no wildcard protocols to receive
  2234. // all packets.
  2235. //
  2236. if (Socket->KernelSocket.Protocol != NetworkProtocol) {
  2237. continue;
  2238. }
  2239. //
  2240. // If the socket is locally bound, then the local address must match
  2241. // the destination address.
  2242. //
  2243. if ((Socket->BindingType == SocketLocallyBound) ||
  2244. (Socket->BindingType == SocketFullyBound)) {
  2245. ASSERT(Socket->LocalAddress.Port == 0);
  2246. Match = TRUE;
  2247. for (PartIndex = 0;
  2248. PartIndex < MAX_NETWORK_ADDRESS_SIZE / sizeof(UINTN);
  2249. PartIndex += 1) {
  2250. if (Socket->LocalAddress.Address[PartIndex] !=
  2251. DestinationAddress->Address[PartIndex]) {
  2252. Match = FALSE;
  2253. break;
  2254. }
  2255. }
  2256. if (Match == FALSE) {
  2257. continue;
  2258. }
  2259. }
  2260. //
  2261. // If the socket is fully bound, then the remote address must match the
  2262. // source address.
  2263. //
  2264. if (Socket->BindingType == SocketFullyBound) {
  2265. ASSERT(Socket->RemoteAddress.Port == 0);
  2266. Match = TRUE;
  2267. for (PartIndex = 0;
  2268. PartIndex < MAX_NETWORK_ADDRESS_SIZE / sizeof(UINTN);
  2269. PartIndex += 1) {
  2270. if (Socket->RemoteAddress.Address[PartIndex] !=
  2271. SourceAddress->Address[PartIndex]) {
  2272. Match = FALSE;
  2273. break;
  2274. }
  2275. }
  2276. if (Match == FALSE) {
  2277. continue;
  2278. }
  2279. }
  2280. //
  2281. // This raw socket is lucky. It gets to look at the packet.
  2282. //
  2283. RawProtocol->Interface.ProcessReceivedSocketData(Link,
  2284. Socket,
  2285. Packet,
  2286. SourceAddress,
  2287. DestinationAddress);
  2288. }
  2289. KeReleaseSharedExclusiveLockShared(NetRawSocketsLock);
  2290. return;
  2291. }
  2292. NET_API
  2293. COMPARISON_RESULT
  2294. NetCompareNetworkAddresses (
  2295. PNETWORK_ADDRESS FirstAddress,
  2296. PNETWORK_ADDRESS SecondAddress
  2297. )
  2298. /*++
  2299. Routine Description:
  2300. This routine compares two network addresses.
  2301. Arguments:
  2302. FirstAddress - Supplies a pointer to the left side of the comparison.
  2303. SecondAddress - Supplies a pointer to the second side of the comparison.
  2304. Return Value:
  2305. Same if the two nodes have the same value.
  2306. Ascending if the first node is less than the second node.
  2307. Descending if the second node is less than the first node.
  2308. --*/
  2309. {
  2310. return NetpCompareNetworkAddresses(FirstAddress, SecondAddress);
  2311. }
  2312. KSTATUS
  2313. NetpInitializeNetworkLayer (
  2314. VOID
  2315. )
  2316. /*++
  2317. Routine Description:
  2318. This routine initialize support for generic Network layer functionality.
  2319. Arguments:
  2320. None.
  2321. Return Value:
  2322. Status code.
  2323. --*/
  2324. {
  2325. KSTATUS Status;
  2326. NetLinkListLock = KeCreateSharedExclusiveLock();
  2327. if (NetLinkListLock == NULL) {
  2328. Status = STATUS_INSUFFICIENT_RESOURCES;
  2329. goto InitializeNetworkLayerEnd;
  2330. }
  2331. NetRawSocketsLock = KeCreateSharedExclusiveLock();
  2332. if (NetRawSocketsLock == NULL) {
  2333. Status = STATUS_INSUFFICIENT_RESOURCES;
  2334. goto InitializeNetworkLayerEnd;
  2335. }
  2336. INITIALIZE_LIST_HEAD(&NetRawSocketsList);
  2337. INITIALIZE_LIST_HEAD(&NetLinkList);
  2338. Status = STATUS_SUCCESS;
  2339. InitializeNetworkLayerEnd:
  2340. if (!KSUCCESS(Status)) {
  2341. if (NetLinkListLock != NULL) {
  2342. KeDestroySharedExclusiveLock(NetLinkListLock);
  2343. NetLinkListLock = NULL;
  2344. }
  2345. if (NetRawSocketsLock != NULL) {
  2346. KeDestroySharedExclusiveLock(NetRawSocketsLock);
  2347. NetRawSocketsLock = NULL;
  2348. }
  2349. }
  2350. return Status;
  2351. }
  2352. COMPARISON_RESULT
  2353. NetpCompareNetworkAddresses (
  2354. PNETWORK_ADDRESS FirstAddress,
  2355. PNETWORK_ADDRESS SecondAddress
  2356. )
  2357. /*++
  2358. Routine Description:
  2359. This routine compares two network addresses.
  2360. Arguments:
  2361. FirstAddress - Supplies a pointer to the left side of the comparison.
  2362. SecondAddress - Supplies a pointer to the second side of the comparison.
  2363. Return Value:
  2364. Same if the two nodes have the same value.
  2365. Ascending if the first node is less than the second node.
  2366. Descending if the second node is less than the first node.
  2367. --*/
  2368. {
  2369. ULONG PartIndex;
  2370. if (FirstAddress == SecondAddress) {
  2371. return ComparisonResultSame;
  2372. }
  2373. //
  2374. // Very likely the ports will disagree, so check those first.
  2375. //
  2376. if (FirstAddress->Port < SecondAddress->Port) {
  2377. return ComparisonResultAscending;
  2378. } else if (FirstAddress->Port > SecondAddress->Port) {
  2379. return ComparisonResultDescending;
  2380. }
  2381. //
  2382. // Compare the networks before the addresses. This is necessary because
  2383. // binding requires a search for addresses of the same protocol and network
  2384. // that use the same port. Sorting by network before address makes this
  2385. // easier.
  2386. //
  2387. if (FirstAddress->Domain < SecondAddress->Domain) {
  2388. return ComparisonResultAscending;
  2389. } else if (FirstAddress->Domain > SecondAddress->Domain) {
  2390. return ComparisonResultDescending;
  2391. }
  2392. //
  2393. // Check the address itself.
  2394. //
  2395. for (PartIndex = 0;
  2396. PartIndex < MAX_NETWORK_ADDRESS_SIZE / sizeof(UINTN);
  2397. PartIndex += 1) {
  2398. if (FirstAddress->Address[PartIndex] <
  2399. SecondAddress->Address[PartIndex]) {
  2400. return ComparisonResultAscending;
  2401. } else if (FirstAddress->Address[PartIndex] >
  2402. SecondAddress->Address[PartIndex]) {
  2403. return ComparisonResultDescending;
  2404. }
  2405. //
  2406. // The parts here are equal, move on to the next part.
  2407. //
  2408. }
  2409. //
  2410. // Well, nothing's not different, so they must be the same.
  2411. //
  2412. return ComparisonResultSame;
  2413. }
  2414. COMPARISON_RESULT
  2415. NetpCompareFullyBoundSockets (
  2416. PRED_BLACK_TREE Tree,
  2417. PRED_BLACK_TREE_NODE FirstNode,
  2418. PRED_BLACK_TREE_NODE SecondNode
  2419. )
  2420. /*++
  2421. Routine Description:
  2422. This routine compares two fully bound sockets, where both the local and
  2423. remote addresses are fixed.
  2424. Arguments:
  2425. Tree - Supplies a pointer to the Red-Black tree that owns both nodes.
  2426. FirstNode - Supplies a pointer to the left side of the comparison.
  2427. SecondNode - Supplies a pointer to the second side of the comparison.
  2428. Return Value:
  2429. Same if the two nodes have the same value.
  2430. Ascending if the first node is less than the second node.
  2431. Descending if the second node is less than the first node.
  2432. --*/
  2433. {
  2434. PNET_SOCKET FirstSocket;
  2435. COMPARISON_RESULT Result;
  2436. PNET_SOCKET SecondSocket;
  2437. FirstSocket = RED_BLACK_TREE_VALUE(FirstNode, NET_SOCKET, U.TreeEntry);
  2438. SecondSocket = RED_BLACK_TREE_VALUE(SecondNode, NET_SOCKET, U.TreeEntry);
  2439. Result = NetpMatchFullyBoundSocket(FirstSocket,
  2440. &(SecondSocket->LocalAddress),
  2441. &(SecondSocket->RemoteAddress));
  2442. return Result;
  2443. }
  2444. COMPARISON_RESULT
  2445. NetpCompareLocallyBoundSockets (
  2446. PRED_BLACK_TREE Tree,
  2447. PRED_BLACK_TREE_NODE FirstNode,
  2448. PRED_BLACK_TREE_NODE SecondNode
  2449. )
  2450. /*++
  2451. Routine Description:
  2452. This routine compares two locally bound sockets, where the local address
  2453. and port are fixed.
  2454. Arguments:
  2455. Tree - Supplies a pointer to the Red-Black tree that owns both nodes.
  2456. FirstNode - Supplies a pointer to the left side of the comparison.
  2457. SecondNode - Supplies a pointer to the second side of the comparison.
  2458. Return Value:
  2459. Same if the two nodes have the same value.
  2460. Ascending if the first node is less than the second node.
  2461. Descending if the second node is less than the first node.
  2462. --*/
  2463. {
  2464. PNET_SOCKET FirstSocket;
  2465. COMPARISON_RESULT Result;
  2466. PNET_SOCKET SecondSocket;
  2467. FirstSocket = RED_BLACK_TREE_VALUE(FirstNode, NET_SOCKET, U.TreeEntry);
  2468. SecondSocket = RED_BLACK_TREE_VALUE(SecondNode, NET_SOCKET, U.TreeEntry);
  2469. Result = NetpCompareNetworkAddresses(&(FirstSocket->LocalAddress),
  2470. &(SecondSocket->LocalAddress));
  2471. return Result;
  2472. }
  2473. COMPARISON_RESULT
  2474. NetpCompareUnboundSockets (
  2475. PRED_BLACK_TREE Tree,
  2476. PRED_BLACK_TREE_NODE FirstNode,
  2477. PRED_BLACK_TREE_NODE SecondNode
  2478. )
  2479. /*++
  2480. Routine Description:
  2481. This routine compares two unbound sockets, meaning only the local port
  2482. number is known.
  2483. Arguments:
  2484. Tree - Supplies a pointer to the Red-Black tree that owns both nodes.
  2485. FirstNode - Supplies a pointer to the left side of the comparison.
  2486. SecondNode - Supplies a pointer to the second side of the comparison.
  2487. Return Value:
  2488. Same if the two nodes have the same value.
  2489. Ascending if the first node is less than the second node.
  2490. Descending if the second node is less than the first node.
  2491. --*/
  2492. {
  2493. PNETWORK_ADDRESS FirstLocalAddress;
  2494. PNET_SOCKET FirstSocket;
  2495. PNETWORK_ADDRESS SecondLocalAddress;
  2496. PNET_SOCKET SecondSocket;
  2497. FirstSocket = RED_BLACK_TREE_VALUE(FirstNode, NET_SOCKET, U.TreeEntry);
  2498. SecondSocket = RED_BLACK_TREE_VALUE(SecondNode, NET_SOCKET, U.TreeEntry);
  2499. //
  2500. // Compare the local port numbers.
  2501. //
  2502. FirstLocalAddress = &(FirstSocket->LocalAddress);
  2503. SecondLocalAddress = &(SecondSocket->LocalAddress);
  2504. if (FirstLocalAddress->Port < SecondLocalAddress->Port) {
  2505. return ComparisonResultAscending;
  2506. } else if (FirstLocalAddress->Port > SecondLocalAddress->Port) {
  2507. return ComparisonResultDescending;
  2508. }
  2509. //
  2510. // Compare the networks.
  2511. //
  2512. if (FirstLocalAddress->Domain < SecondLocalAddress->Domain) {
  2513. return ComparisonResultAscending;
  2514. } else if (FirstLocalAddress->Domain > SecondLocalAddress->Domain) {
  2515. return ComparisonResultDescending;
  2516. }
  2517. return ComparisonResultSame;
  2518. }
  2519. //
  2520. // --------------------------------------------------------- Internal Functions
  2521. //
  2522. VOID
  2523. NetpDestroyLink (
  2524. PNET_LINK Link
  2525. )
  2526. /*++
  2527. Routine Description:
  2528. This routine destroys the state for the given link.
  2529. Arguments:
  2530. Link - Supplies a pointer to the link that needs to be destroyed.
  2531. Return Value:
  2532. None.
  2533. --*/
  2534. {
  2535. PLIST_ENTRY CurrentEntry;
  2536. PNET_NETWORK_ENTRY CurrentNetwork;
  2537. PNET_LINK_ADDRESS_ENTRY LinkAddressEntry;
  2538. ASSERT(Link->ReferenceCount == 0);
  2539. ASSERT(Link->ListEntry.Next == NULL);
  2540. //
  2541. // Destroy all the link address entries. Don't bother to lock the list as
  2542. // all the references are gone.
  2543. //
  2544. while (LIST_EMPTY(&(Link->LinkAddressList)) == FALSE) {
  2545. LinkAddressEntry = LIST_VALUE(Link->LinkAddressList.Next,
  2546. NET_LINK_ADDRESS_ENTRY,
  2547. ListEntry);
  2548. LIST_REMOVE(&(LinkAddressEntry->ListEntry));
  2549. MmFreePagedPool(LinkAddressEntry);
  2550. }
  2551. KeDestroyEvent(Link->AddressTranslationEvent);
  2552. KeAcquireSharedExclusiveLockShared(NetPluginListLock);
  2553. CurrentEntry = NetNetworkList.Next;
  2554. while (CurrentEntry != &NetNetworkList) {
  2555. CurrentNetwork = LIST_VALUE(CurrentEntry, NET_NETWORK_ENTRY, ListEntry);
  2556. CurrentNetwork->Interface.DestroyLink(Link);
  2557. CurrentEntry = CurrentEntry->Next;
  2558. }
  2559. KeReleaseSharedExclusiveLockShared(NetPluginListLock);
  2560. Link->DataLinkEntry->Interface.DestroyLink(Link);
  2561. Link->Properties.Interface.DestroyLink(Link->Properties.DeviceContext);
  2562. IoDeviceReleaseReference(Link->Properties.Device);
  2563. MmFreePagedPool(Link);
  2564. return;
  2565. }
  2566. VOID
  2567. NetpDeactivateSocketUnlocked (
  2568. PNET_SOCKET Socket
  2569. )
  2570. /*++
  2571. Routine Description:
  2572. This routine deactivates and unbinds a socket, preventing the socket from
  2573. receiving incoming packets. It assumes that the net socket tree lock is
  2574. already held. It does not, however, disassociate a socket from its local
  2575. or remote address. Those are still valid properties of the socket, while
  2576. its on its way out.
  2577. Arguments:
  2578. Socket - Supplies a pointer to the initialized socket to remove from the
  2579. socket tree.
  2580. Return Value:
  2581. None.
  2582. --*/
  2583. {
  2584. PNET_PROTOCOL_ENTRY Protocol;
  2585. PRED_BLACK_TREE Tree;
  2586. Protocol = Socket->Protocol;
  2587. ASSERT(KeIsSharedExclusiveLockHeldExclusive(Protocol->SocketLock) != FALSE);
  2588. ASSERT(Socket->BindingType < SocketBindingTypeCount);
  2589. if (((Socket->Flags & NET_SOCKET_FLAG_ACTIVE) == 0) &&
  2590. (Socket->BindingType == SocketBindingInvalid)) {
  2591. ASSERT(Socket != Protocol->LastSocket);
  2592. return;
  2593. }
  2594. RtlAtomicAnd32(&(Socket->Flags), ~NET_SOCKET_FLAG_ACTIVE);
  2595. Tree = &(Protocol->SocketTree[Socket->BindingType]);
  2596. if (NetGlobalDebug != FALSE) {
  2597. RtlDebugPrint("Net: Deactivating socket %x\n", Socket);
  2598. }
  2599. //
  2600. // Remove this old friend from the tree.
  2601. //
  2602. RtlRedBlackTreeRemove(Tree, &(Socket->U.TreeEntry));
  2603. Socket->BindingType = SocketBindingInvalid;
  2604. //
  2605. // If it was in the socket "cache", then remove it.
  2606. //
  2607. if (Socket == Protocol->LastSocket) {
  2608. Protocol->LastSocket = NULL;
  2609. }
  2610. //
  2611. // Release that reference that was added when the socket was added to the
  2612. // tree. This should not be the last reference on the kernel socket.
  2613. //
  2614. ASSERT(Socket->KernelSocket.ReferenceCount > 1);
  2615. IoSocketReleaseReference(&(Socket->KernelSocket));
  2616. return;
  2617. }
  2618. VOID
  2619. NetpDeactivateRawSocketUnlocked (
  2620. PNET_SOCKET Socket
  2621. )
  2622. /*++
  2623. Routine Description:
  2624. This routine deactivates and unbinds a raw socket, preventing the socket
  2625. from receiving incoming packets. It assumes that the raw socket lock is
  2626. already held. It does not, however, disassociate a socket from its local or
  2627. remote address. Those are still valid properties of the socket, while its
  2628. on its way out.
  2629. Arguments:
  2630. Socket - Supplies a pointer to the initialized raw socket to remove from
  2631. the raw socket list.
  2632. Return Value:
  2633. None.
  2634. --*/
  2635. {
  2636. ASSERT(KeIsSharedExclusiveLockHeldExclusive(NetRawSocketsLock) != FALSE);
  2637. ASSERT(Socket->KernelSocket.Type == NetSocketRaw);
  2638. if (((Socket->Flags & NET_SOCKET_FLAG_ACTIVE) == 0) &&
  2639. (Socket->BindingType == SocketBindingInvalid)) {
  2640. return;
  2641. }
  2642. RtlAtomicAnd32(&(Socket->Flags), ~NET_SOCKET_FLAG_ACTIVE);
  2643. if (NetGlobalDebug != FALSE) {
  2644. RtlDebugPrint("Net: Deactivating raw socket %x\n", Socket);
  2645. }
  2646. //
  2647. // Remove this old friend from the list.
  2648. //
  2649. LIST_REMOVE(&(Socket->U.ListEntry));
  2650. Socket->BindingType = SocketBindingInvalid;
  2651. //
  2652. // Release that reference that was added when the socket was added to the
  2653. // tree. This should not be the last reference on the kernel socket.
  2654. //
  2655. ASSERT(Socket->KernelSocket.ReferenceCount > 1);
  2656. IoSocketReleaseReference(&(Socket->KernelSocket));
  2657. return;
  2658. }
  2659. VOID
  2660. NetpDetachSockets (
  2661. PNET_LINK Link,
  2662. PNET_LINK_ADDRESS_ENTRY LinkAddress
  2663. )
  2664. /*++
  2665. Routine Description:
  2666. This routine detaches all of the sockets associated with the given link
  2667. and optional link address.
  2668. Arguments:
  2669. Link - Supplies a pointer to the network link whose sockets are to be
  2670. detached.
  2671. LinkAddress - Supplies a pointer to an optional link address entry. If
  2672. supplied then only the link's sockets bound to the given link address
  2673. will be detached.
  2674. Return Value:
  2675. None.
  2676. --*/
  2677. {
  2678. PLIST_ENTRY CurrentEntry;
  2679. PRED_BLACK_TREE_NODE Node;
  2680. PNET_PROTOCOL_ENTRY Protocol;
  2681. PNET_SOCKET Socket;
  2682. PRED_BLACK_TREE Tree;
  2683. //
  2684. // The fully and locally bound socket trees must be pruned for each
  2685. // protocol.
  2686. //
  2687. KeAcquireSharedExclusiveLockShared(NetPluginListLock);
  2688. CurrentEntry = NetProtocolList.Next;
  2689. while (CurrentEntry != &NetProtocolList) {
  2690. Protocol = LIST_VALUE(CurrentEntry, NET_PROTOCOL_ENTRY, ListEntry);
  2691. CurrentEntry = CurrentEntry->Next;
  2692. KeAcquireSharedExclusiveLockExclusive(Protocol->SocketLock);
  2693. Tree = &(Protocol->SocketTree[SocketFullyBound]);
  2694. Node = RtlRedBlackTreeGetNextNode(Tree, FALSE, NULL);
  2695. while (Node != NULL) {
  2696. Socket = RED_BLACK_TREE_VALUE(Node, NET_SOCKET, U.TreeEntry);
  2697. Node = RtlRedBlackTreeGetNextNode(Tree, FALSE, Node);
  2698. if ((Socket->Link != Link) ||
  2699. ((LinkAddress != NULL) &&
  2700. (Socket->LinkAddress != LinkAddress))) {
  2701. continue;
  2702. }
  2703. NetpDetachSocket(Socket);
  2704. }
  2705. //
  2706. // Do the same for locally bound sockets using this link.
  2707. //
  2708. Tree = &(Protocol->SocketTree[SocketLocallyBound]);
  2709. Node = RtlRedBlackTreeGetNextNode(Tree, FALSE, NULL);
  2710. while (Node != NULL) {
  2711. Socket = RED_BLACK_TREE_VALUE(Node, NET_SOCKET, U.TreeEntry);
  2712. Node = RtlRedBlackTreeGetNextNode(Tree, FALSE, Node);
  2713. if ((Socket->Link != Link) ||
  2714. ((LinkAddress != NULL) &&
  2715. (Socket->LinkAddress != LinkAddress))) {
  2716. continue;
  2717. }
  2718. NetpDetachSocket(Socket);
  2719. }
  2720. KeReleaseSharedExclusiveLockExclusive(Protocol->SocketLock);
  2721. }
  2722. KeReleaseSharedExclusiveLockShared(NetPluginListLock);
  2723. //
  2724. // Detach all the raw sockets that were using this link.
  2725. //
  2726. KeAcquireSharedExclusiveLockExclusive(NetRawSocketsLock);
  2727. CurrentEntry = NetRawSocketsList.Next;
  2728. while (CurrentEntry != &NetRawSocketsList) {
  2729. Socket = LIST_VALUE(CurrentEntry, NET_SOCKET, U.ListEntry);
  2730. CurrentEntry = CurrentEntry->Next;
  2731. if ((Socket->Link != Link) ||
  2732. ((LinkAddress != NULL) && (Socket->LinkAddress != LinkAddress))) {
  2733. continue;
  2734. }
  2735. NetpDetachRawSocket(Socket);
  2736. }
  2737. KeReleaseSharedExclusiveLockExclusive(NetRawSocketsLock);
  2738. return;
  2739. }
  2740. VOID
  2741. NetpDetachSocket (
  2742. PNET_SOCKET Socket
  2743. )
  2744. /*++
  2745. Routine Description:
  2746. This routine detaches a socket from all activity as a result of its link
  2747. going down. It assumes the socket lock is held.
  2748. Arguments:
  2749. Socket - Supplies a pointer to the network socket that is to be unbound
  2750. from its link.
  2751. Return Value:
  2752. None.
  2753. --*/
  2754. {
  2755. ASSERT((Socket->Link->LinkUp == FALSE) ||
  2756. (Socket->LinkAddress->Configured == FALSE));
  2757. ASSERT((Socket->BindingType == SocketLocallyBound) ||
  2758. (Socket->BindingType == SocketFullyBound));
  2759. NetpDeactivateSocketUnlocked(Socket);
  2760. NET_SOCKET_SET_LAST_ERROR(Socket, STATUS_NO_NETWORK_CONNECTION);
  2761. IoSetIoObjectState(Socket->KernelSocket.IoState,
  2762. POLL_EVENT_DISCONNECTED,
  2763. TRUE);
  2764. return;
  2765. }
  2766. VOID
  2767. NetpDetachRawSocket (
  2768. PNET_SOCKET Socket
  2769. )
  2770. /*++
  2771. Routine Description:
  2772. This routine detaches a raw socket from all activity as a result of its
  2773. link going down. It assumes the raw socket lock is held.
  2774. Arguments:
  2775. Socket - Supplies a pointer to the network socket that is to be unbound
  2776. from its link.
  2777. Return Value:
  2778. None.
  2779. --*/
  2780. {
  2781. ASSERT((Socket->Link->LinkUp == FALSE) ||
  2782. (Socket->LinkAddress->Configured == FALSE));
  2783. ASSERT((Socket->BindingType == SocketLocallyBound) ||
  2784. (Socket->BindingType == SocketFullyBound));
  2785. NetpDeactivateRawSocketUnlocked(Socket);
  2786. NET_SOCKET_SET_LAST_ERROR(Socket, STATUS_NO_NETWORK_CONNECTION);
  2787. IoSetIoObjectState(Socket->KernelSocket.IoState,
  2788. POLL_EVENT_DISCONNECTED,
  2789. TRUE);
  2790. return;
  2791. }
  2792. KSTATUS
  2793. NetpBindRawSocket (
  2794. PNET_SOCKET Socket,
  2795. NET_SOCKET_BINDING_TYPE BindingType,
  2796. PNET_LINK_LOCAL_ADDRESS LocalInformation,
  2797. PNETWORK_ADDRESS RemoteAddress,
  2798. ULONG Flags
  2799. )
  2800. /*++
  2801. Routine Description:
  2802. This routine officially binds a raw socket to a local address and/or remote
  2803. address. It can also re-bind a socket in the case where it has already been
  2804. bound to a different address.
  2805. Arguments:
  2806. Socket - Supplies a pointer to the initialized socket to bind.
  2807. BindingType - Supplies the type of binding for the socket.
  2808. LocalInformation - Supplies a pointer to the information for the local link
  2809. or address to which the socket shall be bound. Use this for unbound
  2810. sockets, leaving the link and link address NULL.
  2811. RemoteAddress - Supplies an optional pointer to a remote address to use
  2812. when fully binding the socket.
  2813. Flags - Supplies a bitmask of binding flags. See NET_SOCKET_BINDING_FLAG_*
  2814. for definitions.
  2815. Return Value:
  2816. Status code.
  2817. --*/
  2818. {
  2819. ULONG OldFlags;
  2820. KSTATUS Status;
  2821. ASSERT(Socket->KernelSocket.Type == NetSocketRaw);
  2822. ASSERT(LocalInformation != NULL);
  2823. //
  2824. // This routine is simple. It updates the local and/or remote address for
  2825. // the socket.
  2826. //
  2827. KeAcquireSharedExclusiveLockExclusive(NetRawSocketsLock);
  2828. //
  2829. // If the socket is locally bound and destined to be fully bound, then the
  2830. // link and link address entry better match. The supplied link was chosen
  2831. // specifically as a link that can reach the remote address.
  2832. //
  2833. if (((Socket->BindingType == SocketLocallyBound) ||
  2834. (Socket->BindingType == SocketFullyBound)) &&
  2835. (BindingType == SocketFullyBound) &&
  2836. ((Socket->Link != LocalInformation->Link) ||
  2837. (Socket->LinkAddress != LocalInformation->LinkAddress))) {
  2838. Status = STATUS_INVALID_PARAMETER;
  2839. goto BindRawSocketEnd;
  2840. }
  2841. //
  2842. // Debug print the socket binding.
  2843. //
  2844. if (NetGlobalDebug != FALSE) {
  2845. switch (BindingType) {
  2846. case SocketUnbound:
  2847. RtlDebugPrint("Net: Binding unbound raw socket %x.\n", Socket);
  2848. break;
  2849. case SocketLocallyBound:
  2850. RtlDebugPrint("Net: Binding locally bound raw socket %x: ", Socket);
  2851. NetDebugPrintAddress(&(LocalInformation->LocalAddress));
  2852. RtlDebugPrint("\n");
  2853. break;
  2854. case SocketFullyBound:
  2855. RtlDebugPrint("Net: Binding fully bound raw socket %x, Local ",
  2856. Socket);
  2857. NetDebugPrintAddress(&(LocalInformation->LocalAddress));
  2858. RtlDebugPrint(", Remote ");
  2859. NetDebugPrintAddress(RemoteAddress);
  2860. RtlDebugPrint(".\n");
  2861. break;
  2862. default:
  2863. ASSERT(FALSE);
  2864. break;
  2865. }
  2866. }
  2867. //
  2868. // If the socket is bound to a link and the link is down, then do not
  2869. // insert the socket.
  2870. //
  2871. // N.B. Because taking a link down requires iterating over the raw socket
  2872. // list, this does not require any additional synchronization. The
  2873. // link state is updated and then it waits on the raw socket lock. So,
  2874. // either changing the link state acquired the raw socket lock first,
  2875. // in which case the link state is already set to 'down' and this
  2876. // should fail. Or this routine acquired the raw socket lock first and
  2877. // if it notices the link is down, great. If it doesn't, then the
  2878. // socket will get put in the list and the process of taking the link
  2879. // down will clean it up. Of course the link could come back up after
  2880. // this check, but that's OK. It's up to the caller to try again.
  2881. //
  2882. if ((LocalInformation->Link != NULL) &&
  2883. (LocalInformation->Link->LinkUp == FALSE)) {
  2884. NetpDetachRawSocket(Socket);
  2885. Status = STATUS_NO_NETWORK_CONNECTION;
  2886. goto BindRawSocketEnd;
  2887. }
  2888. //
  2889. // This socket is good to go to use the remote address.
  2890. //
  2891. if (RemoteAddress != NULL) {
  2892. ASSERT(BindingType == SocketFullyBound);
  2893. RtlCopyMemory(&(Socket->RemoteAddress),
  2894. RemoteAddress,
  2895. sizeof(NETWORK_ADDRESS));
  2896. }
  2897. //
  2898. // Clear out any old link information.
  2899. //
  2900. if (Socket->Link != NULL) {
  2901. NetLinkReleaseReference(Socket->Link);
  2902. Socket->Link = NULL;
  2903. Socket->LinkAddress = NULL;
  2904. RtlCopyMemory(&(Socket->PacketSizeInformation),
  2905. &(Socket->UnboundPacketSizeInformation),
  2906. sizeof(NET_PACKET_SIZE_INFORMATION));
  2907. }
  2908. //
  2909. // Set the link information in the socket.
  2910. //
  2911. if (LocalInformation->Link != NULL) {
  2912. ASSERT(LocalInformation->LinkAddress != NULL);
  2913. NetLinkAddReference(LocalInformation->Link);
  2914. Socket->Link = LocalInformation->Link;
  2915. Socket->LinkAddress = LocalInformation->LinkAddress;
  2916. //
  2917. // Now is the time to update the socket's max packet size,
  2918. // header size, and footer size based on the link.
  2919. //
  2920. NetpGetPacketSizeInformation(Socket->Link,
  2921. Socket,
  2922. &(Socket->PacketSizeInformation));
  2923. }
  2924. RtlCopyMemory(&(Socket->LocalAddress),
  2925. &(LocalInformation->LocalAddress),
  2926. sizeof(NETWORK_ADDRESS));
  2927. //
  2928. // Mark the socket as active if requested. If this is moving to the fully
  2929. // bound state from another state, record whether or not it was previously
  2930. // active.
  2931. //
  2932. if ((Flags & NET_SOCKET_BINDING_FLAG_ACTIVATE) != 0) {
  2933. OldFlags = RtlAtomicOr32(&(Socket->Flags), NET_SOCKET_FLAG_ACTIVE);
  2934. if ((BindingType == SocketFullyBound) &&
  2935. (Socket->BindingType != SocketFullyBound) &&
  2936. ((OldFlags & NET_SOCKET_FLAG_ACTIVE) != 0)) {
  2937. RtlAtomicOr32(&(Socket->Flags), NET_SOCKET_FLAG_PREVIOUSLY_ACTIVE);
  2938. }
  2939. }
  2940. //
  2941. // Insert the socket into the list of raw sockets, unless it's already in
  2942. // the list.
  2943. //
  2944. if (Socket->BindingType == SocketBindingInvalid) {
  2945. INSERT_BEFORE(&(Socket->U.ListEntry), &NetRawSocketsList);
  2946. }
  2947. Socket->BindingType = BindingType;
  2948. //
  2949. // Increment the reference count on the socket so that it cannot disappear
  2950. // while being in the list.
  2951. //
  2952. IoSocketAddReference(&(Socket->KernelSocket));
  2953. Status = STATUS_SUCCESS;
  2954. BindRawSocketEnd:
  2955. KeReleaseSharedExclusiveLockExclusive(NetRawSocketsLock);
  2956. return Status;
  2957. }
  2958. KSTATUS
  2959. NetpLookupAddressTranslation (
  2960. PNET_LINK Link,
  2961. PNETWORK_ADDRESS NetworkAddress,
  2962. PNETWORK_ADDRESS PhysicalAddress
  2963. )
  2964. /*++
  2965. Routine Description:
  2966. This routine performs a lookup from network address to physical address
  2967. using the link address translation tree.
  2968. Arguments:
  2969. Link - Supplies a pointer to the link that supposedly owns the network
  2970. address.
  2971. NetworkAddress - Supplies the network address to look up.
  2972. PhysicalAddress - Supplies a pointer where the corresponding physical
  2973. address for this network address will be returned on success.
  2974. Return Value:
  2975. STATUS_SUCCESS on success.
  2976. STATUS_NOT_FOUND if no corresponding entry could be found.
  2977. --*/
  2978. {
  2979. PADDRESS_TRANSLATION_ENTRY FoundEntry;
  2980. PRED_BLACK_TREE_NODE FoundNode;
  2981. ADDRESS_TRANSLATION_ENTRY SearchEntry;
  2982. KSTATUS Status;
  2983. ASSERT(KeGetRunLevel() == RunLevelLow);
  2984. RtlCopyMemory(&(SearchEntry.NetworkAddress),
  2985. NetworkAddress,
  2986. sizeof(NETWORK_ADDRESS));
  2987. SearchEntry.NetworkAddress.Port = 0;
  2988. Status = STATUS_NOT_FOUND;
  2989. KeAcquireQueuedLock(Link->QueuedLock);
  2990. FoundNode = RtlRedBlackTreeSearch(&(Link->AddressTranslationTree),
  2991. &(SearchEntry.TreeEntry));
  2992. //
  2993. // If a node is found, copy the translation into the result while the lock
  2994. // is still held to avoid racing with someone destroying this node.
  2995. //
  2996. if (FoundNode != NULL) {
  2997. FoundEntry = RED_BLACK_TREE_VALUE(FoundNode,
  2998. ADDRESS_TRANSLATION_ENTRY,
  2999. TreeEntry);
  3000. RtlCopyMemory(PhysicalAddress,
  3001. &(FoundEntry->PhysicalAddress),
  3002. sizeof(NETWORK_ADDRESS));
  3003. Status = STATUS_SUCCESS;
  3004. }
  3005. KeReleaseQueuedLock(Link->QueuedLock);
  3006. return Status;
  3007. }
  3008. COMPARISON_RESULT
  3009. NetpMatchFullyBoundSocket (
  3010. PNET_SOCKET Socket,
  3011. PNETWORK_ADDRESS LocalAddress,
  3012. PNETWORK_ADDRESS RemoteAddress
  3013. )
  3014. /*++
  3015. Routine Description:
  3016. This routine compares a socket to a local address and remote address to
  3017. determine if the socket matches the provided information in a fully bound
  3018. way.
  3019. Arguments:
  3020. Socket - Supplies a pointer to a socket to match against the given data.
  3021. LocalAddress - Supplies a pointer to a local network address.
  3022. RemoteAddress - Supplies a pointer to a remote network address.
  3023. Return Value:
  3024. Same if the socket has the same values as the data.
  3025. Ascending if the socket's values are less than the data's.
  3026. Descending if the socket's values are greater than the data's.
  3027. --*/
  3028. {
  3029. ULONG PartIndex;
  3030. COMPARISON_RESULT Result;
  3031. //
  3032. // Compare the local port and local network first. This is required because
  3033. // binding needs to look for fully-bound sockets already using the same
  3034. // local port. This allows bind to iterate over a sub-tree that contains
  3035. // only matching local ports.
  3036. //
  3037. if (Socket->LocalAddress.Port < LocalAddress->Port) {
  3038. return ComparisonResultAscending;
  3039. } else if (Socket->LocalAddress.Port > LocalAddress->Port) {
  3040. return ComparisonResultDescending;
  3041. }
  3042. if (Socket->LocalAddress.Domain < LocalAddress->Domain) {
  3043. return ComparisonResultAscending;
  3044. } else if (Socket->LocalAddress.Domain > LocalAddress->Domain) {
  3045. return ComparisonResultDescending;
  3046. }
  3047. //
  3048. // The nodes are really only the same if the local and remote addresses are
  3049. // the same. The remote address is the more likely to be different, so try
  3050. // that one first.
  3051. //
  3052. Result = NetpCompareNetworkAddresses(&(Socket->RemoteAddress),
  3053. RemoteAddress);
  3054. if (Result != ComparisonResultSame) {
  3055. return Result;
  3056. }
  3057. //
  3058. // Ugh, their remote addresses are the same, check the local addresses.
  3059. //
  3060. for (PartIndex = 0;
  3061. PartIndex < MAX_NETWORK_ADDRESS_SIZE / sizeof(UINTN);
  3062. PartIndex += 1) {
  3063. if (Socket->LocalAddress.Address[PartIndex] <
  3064. LocalAddress->Address[PartIndex]) {
  3065. return ComparisonResultAscending;
  3066. } else if (Socket->LocalAddress.Address[PartIndex] >
  3067. LocalAddress->Address[PartIndex]) {
  3068. return ComparisonResultDescending;
  3069. }
  3070. //
  3071. // The parts here are equal, move on to the next part.
  3072. //
  3073. }
  3074. return ComparisonResultSame;
  3075. }
  3076. COMPARISON_RESULT
  3077. NetpCompareAddressTranslationEntries (
  3078. PRED_BLACK_TREE Tree,
  3079. PRED_BLACK_TREE_NODE FirstNode,
  3080. PRED_BLACK_TREE_NODE SecondNode
  3081. )
  3082. /*++
  3083. Routine Description:
  3084. This routine compares two Red-Black tree nodes, in this case two
  3085. network address translation entries.
  3086. Arguments:
  3087. Tree - Supplies a pointer to the Red-Black tree that owns both nodes.
  3088. FirstNode - Supplies a pointer to the left side of the comparison.
  3089. SecondNode - Supplies a pointer to the second side of the comparison.
  3090. Return Value:
  3091. Same if the two nodes have the same value.
  3092. Ascending if the first node is less than the second node.
  3093. Descending if the second node is less than the first node.
  3094. --*/
  3095. {
  3096. PADDRESS_TRANSLATION_ENTRY FirstEntry;
  3097. COMPARISON_RESULT Result;
  3098. PADDRESS_TRANSLATION_ENTRY SecondEntry;
  3099. FirstEntry = RED_BLACK_TREE_VALUE(FirstNode,
  3100. ADDRESS_TRANSLATION_ENTRY,
  3101. TreeEntry);
  3102. SecondEntry = RED_BLACK_TREE_VALUE(SecondNode,
  3103. ADDRESS_TRANSLATION_ENTRY,
  3104. TreeEntry);
  3105. Result = NetpCompareNetworkAddresses(&(FirstEntry->NetworkAddress),
  3106. &(SecondEntry->NetworkAddress));
  3107. return Result;
  3108. }
  3109. BOOL
  3110. NetpCheckLocalAddressAvailability (
  3111. PNET_SOCKET Socket,
  3112. PNETWORK_ADDRESS LocalAddress
  3113. )
  3114. /*++
  3115. Routine Description:
  3116. This routine determines whether or not the given local address can be used
  3117. by the given socket. It takes into account address and port reusability as
  3118. indicated by the socket's flags. It assumes that the socket lock is held.
  3119. Arguments:
  3120. Socket - Supplies a pointer to the socket whose local address is to be
  3121. validated.
  3122. LocalAddress - Supplies a pointer to a local network address to validate.
  3123. Return Value:
  3124. Returns TRUE if the given local address is OK for the socket to use or
  3125. FALSE otherwise.
  3126. --*/
  3127. {
  3128. BOOL AddressesMatch;
  3129. BOOL AvailableAddress;
  3130. BOOL DeactivateSocket;
  3131. BOOL Descending;
  3132. PRED_BLACK_TREE_NODE FirstFound;
  3133. BOOL FirstFoundMatched;
  3134. PRED_BLACK_TREE_NODE FoundNode;
  3135. PNET_SOCKET FoundSocket;
  3136. ULONG PartIndex;
  3137. PNET_PROTOCOL_ENTRY Protocol;
  3138. NET_SOCKET SearchSocket;
  3139. PRED_BLACK_TREE Tree;
  3140. BOOL UnspecifiedAddress;
  3141. Protocol = Socket->Protocol;
  3142. FoundSocket = NULL;
  3143. ASSERT(KeIsSharedExclusiveLockHeldExclusive(Protocol->SocketLock) != FALSE);
  3144. //
  3145. // Remember if the supplied socket is for the unspecified address.
  3146. //
  3147. UnspecifiedAddress = TRUE;
  3148. for (PartIndex = 0;
  3149. PartIndex < MAX_NETWORK_ADDRESS_SIZE / sizeof(UINTN);
  3150. PartIndex += 1) {
  3151. if (LocalAddress->Address[PartIndex] != 0) {
  3152. UnspecifiedAddress = FALSE;
  3153. break;
  3154. }
  3155. }
  3156. //
  3157. // Create a search entry that does not have a remote address.
  3158. //
  3159. RtlCopyMemory(&(SearchSocket.LocalAddress),
  3160. LocalAddress,
  3161. sizeof(NETWORK_ADDRESS));
  3162. RtlZeroMemory(&(SearchSocket.RemoteAddress), sizeof(NETWORK_ADDRESS));
  3163. //
  3164. // Assume this is going to be a resounding success.
  3165. //
  3166. AvailableAddress = TRUE;
  3167. //
  3168. // Search the tree of fully bound sockets for any using this local address
  3169. // and port combination. Because the search entry's remote address is zero,
  3170. // this should never match exactly, and just return the lowest entry in the
  3171. // tree that matches on network and local port. The compare routine looks
  3172. // at remote address before local address, so this may end up doing a bit
  3173. // of iterating to get through all the necessary entries.
  3174. //
  3175. DeactivateSocket = FALSE;
  3176. Tree = &(Protocol->SocketTree[SocketFullyBound]);
  3177. FoundNode = RtlRedBlackTreeSearchClosest(Tree,
  3178. &(SearchSocket.U.TreeEntry),
  3179. TRUE);
  3180. while (FoundNode != NULL) {
  3181. FoundSocket = RED_BLACK_TREE_VALUE(FoundNode, NET_SOCKET, U.TreeEntry);
  3182. if (FoundSocket->LocalAddress.Port != LocalAddress->Port) {
  3183. break;
  3184. }
  3185. if (FoundSocket->LocalAddress.Domain != LocalAddress->Domain) {
  3186. break;
  3187. }
  3188. //
  3189. // If the supplied socket contains the unspecified address, do not
  3190. // compare it with the found address. It should never match. But if
  3191. // both sockets do not allow address reuse with the any address, then
  3192. // do not allow the any address to use the port.
  3193. //
  3194. if (UnspecifiedAddress != FALSE) {
  3195. if (CAN_REUSE_ANY_ADDRESS(Socket, FoundSocket) == FALSE) {
  3196. AvailableAddress = FALSE;
  3197. break;
  3198. }
  3199. //
  3200. // Otherwise test to see if the addresses match.
  3201. //
  3202. } else {
  3203. AddressesMatch = TRUE;
  3204. for (PartIndex = 0;
  3205. PartIndex < MAX_NETWORK_ADDRESS_SIZE / sizeof(UINTN);
  3206. PartIndex += 1) {
  3207. if (FoundSocket->LocalAddress.Address[PartIndex] !=
  3208. LocalAddress->Address[PartIndex]) {
  3209. AddressesMatch = FALSE;
  3210. break;
  3211. }
  3212. }
  3213. //
  3214. // If the addresses match, then the new socket is only allowed to
  3215. // use the address if either both sockets allow exact address reuse
  3216. // or both sockets allow time wait state address reuse and the
  3217. // found socket is in the time wait state. Deactivate any sockets
  3218. // found in the time wait state if the address is going to be
  3219. // reused.
  3220. //
  3221. if (AddressesMatch != FALSE) {
  3222. if ((CAN_REUSE_EXACT_ADDRESS(Socket, FoundSocket) == FALSE) &&
  3223. (CAN_REUSE_TIME_WAIT(Socket, FoundSocket) == FALSE)) {
  3224. AvailableAddress = FALSE;
  3225. break;
  3226. }
  3227. if ((FoundSocket->Flags & NET_SOCKET_FLAG_TIME_WAIT) != 0) {
  3228. DeactivateSocket = TRUE;
  3229. }
  3230. }
  3231. }
  3232. //
  3233. // So far, so good. Try the next node.
  3234. //
  3235. FoundNode = RtlRedBlackTreeGetNextNode(Tree, FALSE, FoundNode);
  3236. //
  3237. // If the last socket needed deactivating, do it now that the iteration
  3238. // has moved on. Removing a node does not break iteration.
  3239. //
  3240. if (DeactivateSocket != FALSE) {
  3241. NetpDeactivateSocketUnlocked(FoundSocket);
  3242. DeactivateSocket = FALSE;
  3243. }
  3244. }
  3245. //
  3246. // Exit now if it has already been determined that the address is not valid
  3247. // for use.
  3248. //
  3249. if (AvailableAddress == FALSE) {
  3250. goto CheckLocalAddressAvailabilityEnd;
  3251. }
  3252. //
  3253. // Search the tree of locally bound sockets for any using this local
  3254. // address and port combination. If the search socket is using the
  3255. // unspecified address, then this will not match. It should return the
  3256. // lowest entry in the tree that shares the same port and network. If the
  3257. // search socket is using a complete local address, then this may need to
  3258. // search in both directions on the tree if the first node matches.
  3259. //
  3260. Tree = &(Protocol->SocketTree[SocketLocallyBound]);
  3261. FirstFound = RtlRedBlackTreeSearchClosest(Tree,
  3262. &(SearchSocket.U.TreeEntry),
  3263. TRUE);
  3264. Descending = FALSE;
  3265. FoundNode = FirstFound;
  3266. FirstFoundMatched = FALSE;
  3267. while (FoundNode != NULL) {
  3268. while (FoundNode != NULL) {
  3269. FoundSocket = RED_BLACK_TREE_VALUE(FoundNode,
  3270. NET_SOCKET,
  3271. U.TreeEntry);
  3272. if (FoundSocket->LocalAddress.Port != LocalAddress->Port) {
  3273. break;
  3274. }
  3275. if (FoundSocket->LocalAddress.Domain != LocalAddress->Domain) {
  3276. break;
  3277. }
  3278. //
  3279. // Locally bound sockets should not be in the time wait state.
  3280. //
  3281. ASSERT((FoundSocket->Flags & NET_SOCKET_FLAG_TIME_WAIT) == 0);
  3282. //
  3283. // If the supplied socket contains the unspecified address, do not
  3284. // compare it with the found address. It should never match. But if
  3285. // both sockets do not allow any address reuse, then do not allow
  3286. // the unspecified address to use the port.
  3287. //
  3288. if (UnspecifiedAddress != FALSE) {
  3289. if (CAN_REUSE_ANY_ADDRESS(Socket, FoundSocket) == FALSE) {
  3290. AvailableAddress = FALSE;
  3291. break;
  3292. }
  3293. //
  3294. // Otherwise test to see if the addresses match.
  3295. //
  3296. } else {
  3297. AddressesMatch = TRUE;
  3298. for (PartIndex = 0;
  3299. PartIndex < MAX_NETWORK_ADDRESS_SIZE / sizeof(UINTN);
  3300. PartIndex += 1) {
  3301. if (FoundSocket->LocalAddress.Address[PartIndex] !=
  3302. LocalAddress->Address[PartIndex]) {
  3303. AddressesMatch = FALSE;
  3304. break;
  3305. }
  3306. }
  3307. //
  3308. // If the local addresses do not match, then this has gone
  3309. // beyond the range of any matches.
  3310. //
  3311. if (AddressesMatch == FALSE) {
  3312. break;
  3313. }
  3314. //
  3315. // Record if this was the first found and it matched.
  3316. //
  3317. if (FoundNode == FirstFound) {
  3318. FirstFoundMatched = TRUE;
  3319. }
  3320. //
  3321. // If the addresses match, then the new socket is only allowed
  3322. // to use the address if both sockets allow exact address reuse.
  3323. //
  3324. if (CAN_REUSE_EXACT_ADDRESS(Socket, FoundSocket) == FALSE) {
  3325. AvailableAddress = FALSE;
  3326. break;
  3327. }
  3328. }
  3329. //
  3330. // So far, so good. Try the next node.
  3331. //
  3332. FoundNode = RtlRedBlackTreeGetNextNode(Tree, Descending, FoundNode);
  3333. }
  3334. //
  3335. // Exit now if it has already been determined that the address is not
  3336. // valid for use.
  3337. //
  3338. if (AvailableAddress == FALSE) {
  3339. goto CheckLocalAddressAvailabilityEnd;
  3340. }
  3341. //
  3342. // If the first found was not a match, then the tree does not need to
  3343. // be searched in the descending direction.
  3344. //
  3345. if (FirstFoundMatched == FALSE) {
  3346. break;
  3347. }
  3348. ASSERT(UnspecifiedAddress == FALSE);
  3349. //
  3350. // Switch the search direction once and start over from the node before
  3351. // the first found.
  3352. //
  3353. if (Descending != FALSE) {
  3354. break;
  3355. }
  3356. Descending = TRUE;
  3357. FoundNode = RtlRedBlackTreeGetNextNode(Tree, Descending, FirstFound);
  3358. }
  3359. //
  3360. // Search the tree of unbound sockets for any using this local port. This
  3361. // has to deal with the same situation as the locally bound search because
  3362. // the closest may match with other matches entries both above and below in
  3363. // the tree.
  3364. //
  3365. Tree = &(Protocol->SocketTree[SocketUnbound]);
  3366. FirstFound = RtlRedBlackTreeSearchClosest(Tree,
  3367. &(SearchSocket.U.TreeEntry),
  3368. TRUE);
  3369. Descending = FALSE;
  3370. FoundNode = FirstFound;
  3371. FirstFoundMatched = FALSE;
  3372. while (FoundNode != NULL) {
  3373. while (FoundNode != NULL) {
  3374. FoundSocket = RED_BLACK_TREE_VALUE(FoundNode,
  3375. NET_SOCKET,
  3376. U.TreeEntry);
  3377. if (FoundSocket->LocalAddress.Port != LocalAddress->Port) {
  3378. break;
  3379. }
  3380. if (FoundSocket->LocalAddress.Domain != LocalAddress->Domain) {
  3381. break;
  3382. }
  3383. //
  3384. // If the first found got this far, then it's a match.
  3385. //
  3386. if (FoundNode == FirstFound) {
  3387. FirstFoundMatched = TRUE;
  3388. }
  3389. //
  3390. // An unbound socket should not be in the time-wait state.
  3391. //
  3392. ASSERT((FoundSocket->Flags & NET_SOCKET_FLAG_TIME_WAIT) == 0);
  3393. //
  3394. // If the supplied socket has an unspecified address, then the
  3395. // addresses match as well. The only way for the new socket to use
  3396. // the address is if reusing the exact address is allowed on both
  3397. // sockets.
  3398. //
  3399. if (UnspecifiedAddress != FALSE) {
  3400. if (CAN_REUSE_EXACT_ADDRESS(Socket, FoundSocket) == FALSE) {
  3401. AvailableAddress = FALSE;
  3402. break;
  3403. }
  3404. //
  3405. // Otherwise, the addresses are different. Reuse of the port is
  3406. // only allowed if reusing the any address is allowed on both
  3407. // sockets.
  3408. //
  3409. } else {
  3410. if (CAN_REUSE_ANY_ADDRESS(Socket, FoundSocket) == FALSE) {
  3411. AvailableAddress = FALSE;
  3412. break;
  3413. }
  3414. }
  3415. //
  3416. // So far, so good. Try the next node.
  3417. //
  3418. FoundNode = RtlRedBlackTreeGetNextNode(Tree, Descending, FoundNode);
  3419. }
  3420. //
  3421. // Exit now if it has already been determined that the address is not
  3422. // valid for use.
  3423. //
  3424. if (AvailableAddress == FALSE) {
  3425. goto CheckLocalAddressAvailabilityEnd;
  3426. }
  3427. //
  3428. // If the first found was not a match, then the tree does not need to
  3429. // be searched in the descending direction.
  3430. //
  3431. if (FirstFoundMatched == FALSE) {
  3432. break;
  3433. }
  3434. //
  3435. // Switch the search direction once and start over from the node before
  3436. // the first found.
  3437. //
  3438. if (Descending != FALSE) {
  3439. break;
  3440. }
  3441. Descending = TRUE;
  3442. FoundNode = RtlRedBlackTreeGetNextNode(Tree, Descending, FirstFound);
  3443. }
  3444. CheckLocalAddressAvailabilityEnd:
  3445. if (AvailableAddress == FALSE) {
  3446. if (NetGlobalDebug != FALSE) {
  3447. ASSERT(FoundSocket != NULL);
  3448. RtlDebugPrint("Net: Rejected address availability of socket %x "
  3449. "because of existing socket %x.\n",
  3450. Socket,
  3451. FoundSocket);
  3452. }
  3453. }
  3454. return AvailableAddress;
  3455. }
  3456. VOID
  3457. NetpGetPacketSizeInformation (
  3458. PNET_LINK Link,
  3459. PNET_SOCKET Socket,
  3460. PNET_PACKET_SIZE_INFORMATION SizeInformation
  3461. )
  3462. /*++
  3463. Routine Description:
  3464. This routine calculates the packet size information given an link and a
  3465. socket. It uses the unbound packet size information from the socket in
  3466. order to calculate the resulting size information.
  3467. Arguments:
  3468. Link - Supplies a pointer to a network link.
  3469. Socket - Supplies a pointer to a network socket.
  3470. SizeInformation - Supplies a pointer to a packet size information structure
  3471. that receives the calculated max packet, header, and footer size to
  3472. use for sending packets from the given socket out over the given
  3473. network link.
  3474. Return Value:
  3475. None.
  3476. --*/
  3477. {
  3478. PNET_DATA_LINK_ENTRY DataLinkEntry;
  3479. NET_PACKET_SIZE_INFORMATION DataLinkInformation;
  3480. ULONG FooterSize;
  3481. ULONG HeaderSize;
  3482. ULONG MaxPacketSize;
  3483. ULONG MinPacketSize;
  3484. //
  3485. // Add the data link layer's header and footer sizes to the socket's
  3486. // unbound max packet size. If this is greater than the allowed maximum
  3487. // packet size for the data link layer, then truncate it.
  3488. //
  3489. DataLinkEntry = Link->DataLinkEntry;
  3490. DataLinkEntry->Interface.GetPacketSizeInformation(Link->DataLinkContext,
  3491. &DataLinkInformation,
  3492. 0);
  3493. MaxPacketSize = DataLinkInformation.HeaderSize +
  3494. Socket->UnboundPacketSizeInformation.MaxPacketSize +
  3495. DataLinkInformation.FooterSize;
  3496. if (MaxPacketSize > DataLinkInformation.MaxPacketSize) {
  3497. MaxPacketSize = DataLinkInformation.MaxPacketSize;
  3498. }
  3499. //
  3500. // Add the data link layer's header and footer sizes to the socket's
  3501. // unbound minimum packet size. The maximum of the minimum packet size is
  3502. // what wins here.
  3503. //
  3504. MinPacketSize = DataLinkInformation.HeaderSize +
  3505. Socket->UnboundPacketSizeInformation.MinPacketSize +
  3506. DataLinkInformation.FooterSize;
  3507. if (MinPacketSize < DataLinkInformation.MinPacketSize) {
  3508. MinPacketSize = DataLinkInformation.MinPacketSize;
  3509. }
  3510. //
  3511. // Repeat for the device link layer, truncating the allowed maximum packet
  3512. // size if necessary.
  3513. //
  3514. MaxPacketSize = Link->Properties.PacketSizeInformation.HeaderSize +
  3515. MaxPacketSize +
  3516. Link->Properties.PacketSizeInformation.FooterSize;
  3517. if (MaxPacketSize > Link->Properties.PacketSizeInformation.MaxPacketSize) {
  3518. MaxPacketSize = Link->Properties.PacketSizeInformation.MaxPacketSize;
  3519. }
  3520. //
  3521. // Repeat for the device link layer, increasing the the minimum packet
  3522. // size if necessary.
  3523. //
  3524. MinPacketSize = Link->Properties.PacketSizeInformation.HeaderSize +
  3525. MinPacketSize +
  3526. Link->Properties.PacketSizeInformation.FooterSize;
  3527. if (MinPacketSize < Link->Properties.PacketSizeInformation.MinPacketSize) {
  3528. MinPacketSize = Link->Properties.PacketSizeInformation.MinPacketSize;
  3529. }
  3530. SizeInformation->MaxPacketSize = MaxPacketSize;
  3531. SizeInformation->MinPacketSize = MinPacketSize;
  3532. //
  3533. // The headers and footers of all layers are included in the final tally.
  3534. //
  3535. HeaderSize = Socket->UnboundPacketSizeInformation.HeaderSize +
  3536. DataLinkInformation.HeaderSize +
  3537. Link->Properties.PacketSizeInformation.HeaderSize;
  3538. SizeInformation->HeaderSize = HeaderSize;
  3539. FooterSize = Socket->UnboundPacketSizeInformation.FooterSize +
  3540. DataLinkInformation.FooterSize +
  3541. Link->Properties.PacketSizeInformation.FooterSize;
  3542. SizeInformation->FooterSize = FooterSize;
  3543. return;
  3544. }
  3545. VOID
  3546. NetpDebugPrintNetworkAddress (
  3547. PNET_NETWORK_ENTRY Network,
  3548. PNETWORK_ADDRESS Address
  3549. )
  3550. /*++
  3551. Routine Description:
  3552. This routine prints the given address to the debug console. It must belong
  3553. to the given network.
  3554. Arguments:
  3555. Network - Supplies a pointer to the network to which the address belongs.
  3556. Address - Supplies a pointer to the address to print.
  3557. Return Value:
  3558. None.
  3559. --*/
  3560. {
  3561. ULONG Length;
  3562. CHAR StringBuffer[NET_PRINT_ADDRESS_STRING_LENGTH];
  3563. ASSERT(Network->Domain == Address->Domain);
  3564. StringBuffer[0] = '\0';
  3565. Length = Network->Interface.PrintAddress(Address,
  3566. StringBuffer,
  3567. NET_PRINT_ADDRESS_STRING_LENGTH);
  3568. ASSERT(Length <= NET_PRINT_ADDRESS_STRING_LENGTH);
  3569. StringBuffer[NET_PRINT_ADDRESS_STRING_LENGTH - 1] = '\0';
  3570. RtlDebugPrint("%s", StringBuffer);
  3571. return;
  3572. }