addr.c 137 KB

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