mgmt.c 94 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. mgmt.c
  5. Abstract:
  6. This module implements management frame handling functionality for the
  7. 802.11 core wireless networking library.
  8. Author:
  9. Chris Steven 19-Oct-2015
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include "net80211.h"
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. //
  21. // Define default values for the local station's RSN capabilities.
  22. //
  23. #define NET80211_DEFAULT_RSN_ELEMENT_LENGTH \
  24. (sizeof(NET80211_DEFAULT_RSN_INFORMATION) - (2 * sizeof(UCHAR)))
  25. #define NET80211_DEFAULT_RSN_CAPABILITIES 0
  26. #define NET80211_DEFAULT_RSN_PAIRWISE_CIPHER_SUITE_COUNT 1
  27. #define NET80211_DEFAULT_RSN_AKM_SUITE_COUNT 1
  28. //
  29. // Define the default RSN group cipher suite. This is
  30. // NET80211_CIPHER_SUITE_CCMP in network byte order.
  31. //
  32. #define NET80211_DEFAULT_RSN_GROUP_CIPHER_SUITE 0x04AC0F00
  33. //
  34. // Define the default RSN pairwise cipher suite. This is
  35. // NET80211_CIPHER_SUITE_CCMP in network byte order.
  36. //
  37. #define NET80211_DEFAULT_RSN_PAIRWISE_CIPHER_SUITE 0x04AC0F00
  38. //
  39. // Define the default RSN AKM cipher suite. This is NET80211_AKM_SUITE_PSK in
  40. // network byte order.
  41. //
  42. #define NET80211_DEFAULT_RSN_AKM_SUITE 0x02AC0F00
  43. //
  44. // Define the time to wait for a state management frame.
  45. //
  46. #define NET80211_STATE_TIMEOUT (2 * MICROSECONDS_PER_SECOND)
  47. //
  48. // Define the time to wait for advanced authentication.
  49. //
  50. #define NET80211_AUTHENTICATION_TIMEOUT (5 * MICROSECONDS_PER_SECOND)
  51. //
  52. // Define the timeout until a BSS entry has expired in microseconds.
  53. //
  54. #define NET80211_BSS_ENTRY_TIMEOUT (10 * MICROSECONDS_PER_SECOND)
  55. //
  56. // Define the pad to subtract from the beacon interval during a background
  57. // scan in order to determine the amount of time to dwell on a channel without
  58. // missing a beacon from the active BSS.
  59. //
  60. #define NET80211_BEACON_INTERVAL_PAD (10 * MICROSECONDS_PER_MILLISECOND)
  61. //
  62. // Define the default amount of time to wait between scanning channels when
  63. // performing a background scan.
  64. //
  65. #define NET80211_BACKGROUND_SCAN_CHANNEL_DELAY \
  66. (200 * MICROSECONDS_PER_MILLISECOND)
  67. //
  68. // ------------------------------------------------------ Data Type Definitions
  69. //
  70. /*++
  71. Structure Description:
  72. This structure defines the set of information gathered from a probe
  73. response management frame or a beacon management frame.
  74. Members:
  75. Bssid - Stores a pointer to the BSSID, which is always
  76. NET80211_ADDRESS_SIZE bytes long.
  77. BeaconInterval - Stores the interval between beacons sent by an AP.
  78. Capabilities - Stores the 802.11 capabilities of the AP. See
  79. NET80211_CAPABILITY_FLAG_* for definitions.
  80. Timestamp - Stores the timestamp from the AP.
  81. Elements - Stores a pointer to the information elements.
  82. ElementsSize - Stores the size of the information elements, in bytes.
  83. Channel - Stores a pointer to the channel element, that indicates the
  84. channel on which the AP is operating.
  85. Ssid - Stores a pointer to the SSID element from the AP.
  86. Rates - Stores a pointer to the supported rates element.
  87. ExtendedRates - Stores a pointer to the extended supported rates element.
  88. Rsn - Stores the optional RSN element broadcasted by the AP.
  89. --*/
  90. typedef struct _NET80211_PROBE_RESPONSE {
  91. PUCHAR Bssid;
  92. USHORT BeaconInterval;
  93. USHORT Capabilities;
  94. ULONGLONG Timestamp;
  95. PVOID Elements;
  96. ULONG ElementsSize;
  97. PVOID Channel;
  98. PVOID Ssid;
  99. PVOID Rates;
  100. PVOID ExtendedRates;
  101. PVOID Rsn;
  102. } NET80211_PROBE_RESPONSE, *PNET80211_PROBE_RESPONSE;
  103. /*++
  104. Structure Description:
  105. This structure defines the frame body used for open system authentication.
  106. For other types of authentication, other fields may be required.
  107. Members:
  108. AlgorithmNumber - Stores the algorithm in use for the authentication
  109. process.
  110. TransactionSequenceNumber - Stores the sequence number of the
  111. authentication transaction process.
  112. StatusCode - Stores the states of the authentication process.
  113. --*/
  114. typedef struct _NET80211_AUTHENTICATION_OPEN_BODY {
  115. USHORT AlgorithmNumber;
  116. USHORT TransactionSequenceNumber;
  117. USHORT StatusCode;
  118. } PACKED NET80211_AUTHENTICATION_OPEN_BODY, *PNET80211_AUTHENTICATION_OPEN_BODY;
  119. /*++
  120. Structure Description:
  121. This structure defines the default RSN information used by the 802.11
  122. networking library.
  123. Members:
  124. ElementId - Stores the RSN element ID. This should be NET80211_ELEMENT_RSN.
  125. ElementLength - Stores the length of the RSN information, not including the
  126. first two bytes.
  127. RsnVersion - Stores the RSN information version.
  128. GroupCipherSuite - Stores the group cipher suite.
  129. PairwiseCipherSuiteCount - Stores the number of pairwise cipher suites that
  130. follow this field. There should only be 1.
  131. PairwiseCipherSuite - Stores the only supported pairwise cipher suite.
  132. AkmSuiteCount - Stores the number of AKM cipher suites that follow this
  133. field. There should be only 1.
  134. AkmSuite - Stores the only supported AKM cipher suite.
  135. RsnCapabilites - Stores the RSN capapbilites for the node.
  136. --*/
  137. typedef struct _NET80211_DEFAULT_RSN_INFORMATION {
  138. UCHAR ElementId;
  139. UCHAR ElementLength;
  140. USHORT RsnVersion;
  141. ULONG GroupCipherSuite;
  142. USHORT PairwiseCipherSuiteCount;
  143. ULONG PairwiseCipherSuite;
  144. USHORT AkmSuiteCount;
  145. ULONG AkmSuite;
  146. USHORT RsnCapabilities;
  147. } PACKED NET80211_DEFAULT_RSN_INFORMATION, *PNET80211_DEFAULT_RSN_INFORMATION;
  148. //
  149. // ----------------------------------------------- Internal Function Prototypes
  150. //
  151. VOID
  152. Net80211pSetStateUnlocked (
  153. PNET80211_LINK Link,
  154. NET80211_STATE State
  155. );
  156. VOID
  157. Net80211pScanThread (
  158. PVOID Parameter
  159. );
  160. VOID
  161. Net80211pStartProbing (
  162. PNET80211_LINK Link
  163. );
  164. VOID
  165. Net80211pStopProbing (
  166. PNET80211_LINK Link
  167. );
  168. KSTATUS
  169. Net80211pPrepareForReconnect (
  170. PNET80211_LINK Link,
  171. PNET80211_BSS_ENTRY *Bss
  172. );
  173. VOID
  174. Net80211pJoinBss (
  175. PNET80211_LINK Link,
  176. PNET80211_BSS_ENTRY Bss
  177. );
  178. VOID
  179. Net80211pLeaveBss (
  180. PNET80211_LINK Link,
  181. PNET80211_BSS_ENTRY Bss,
  182. BOOL SendNotification,
  183. ULONG Subtype,
  184. USHORT Reason
  185. );
  186. KSTATUS
  187. Net80211pSendProbeRequest (
  188. PNET80211_LINK Link,
  189. PNET80211_SCAN_STATE Scan
  190. );
  191. VOID
  192. Net80211pProcessProbeResponse (
  193. PNET80211_LINK Link,
  194. PNET_PACKET_BUFFER Packet
  195. );
  196. KSTATUS
  197. Net80211pSendAuthenticationRequest (
  198. PNET80211_LINK Link,
  199. PNET80211_BSS_ENTRY Bss
  200. );
  201. VOID
  202. Net80211pProcessAuthenticationResponse (
  203. PNET80211_LINK Link,
  204. PNET_PACKET_BUFFER Packet
  205. );
  206. KSTATUS
  207. Net80211pSendAssociationRequest (
  208. PNET80211_LINK Link,
  209. PNET80211_BSS_ENTRY Bss
  210. );
  211. VOID
  212. Net80211pProcessAssociationResponse (
  213. PNET80211_LINK Link,
  214. PNET_PACKET_BUFFER Packet
  215. );
  216. KSTATUS
  217. Net80211pSendManagementFrame (
  218. PNET80211_LINK Link,
  219. PUCHAR DestinationAddress,
  220. PUCHAR Bssid,
  221. ULONG FrameSubtype,
  222. PVOID FrameBody,
  223. ULONG FrameBodySize
  224. );
  225. KSTATUS
  226. Net80211pQueueStateTransitionTimer (
  227. PNET80211_LINK Link,
  228. ULONGLONG Timeout
  229. );
  230. VOID
  231. Net80211pCancelStateTransitionTimer (
  232. PNET80211_LINK Link
  233. );
  234. KSTATUS
  235. Net80211pValidateRates (
  236. PNET80211_LINK Link,
  237. PNET80211_BSS_ENTRY Bss
  238. );
  239. KSTATUS
  240. Net80211pParseRsnElement (
  241. PUCHAR Rsn,
  242. PNET80211_ENCRYPTION Encryption
  243. );
  244. VOID
  245. Net80211pUpdateBssCache (
  246. PNET80211_LINK Link,
  247. PNET80211_PROBE_RESPONSE Response
  248. );
  249. VOID
  250. Net80211pTrimBssCache (
  251. PNET80211_LINK Link
  252. );
  253. PNET80211_BSS_ENTRY
  254. Net80211pCopyBssEntry (
  255. PNET80211_BSS_ENTRY Bss
  256. );
  257. PNET80211_BSS_ENTRY
  258. Net80211pCreateBssEntry (
  259. PUCHAR Bssid
  260. );
  261. VOID
  262. Net80211pDestroyBssEntry (
  263. PNET80211_BSS_ENTRY BssEntry
  264. );
  265. //
  266. // -------------------------------------------------------------------- Globals
  267. //
  268. //
  269. // Store the default RSN information to send out for association requests.
  270. //
  271. NET80211_DEFAULT_RSN_INFORMATION Net80211DefaultRsnInformation = {
  272. NET80211_ELEMENT_RSN,
  273. NET80211_DEFAULT_RSN_ELEMENT_LENGTH,
  274. NET80211_RSN_VERSION,
  275. NET80211_DEFAULT_RSN_GROUP_CIPHER_SUITE,
  276. NET80211_DEFAULT_RSN_PAIRWISE_CIPHER_SUITE_COUNT,
  277. NET80211_DEFAULT_RSN_PAIRWISE_CIPHER_SUITE,
  278. NET80211_DEFAULT_RSN_AKM_SUITE_COUNT,
  279. NET80211_DEFAULT_RSN_AKM_SUITE,
  280. NET80211_DEFAULT_RSN_CAPABILITIES
  281. };
  282. //
  283. // ------------------------------------------------------------------ Functions
  284. //
  285. VOID
  286. Net80211pProcessManagementFrame (
  287. PNET80211_LINK Link,
  288. PNET_PACKET_BUFFER Packet
  289. )
  290. /*++
  291. Routine Description:
  292. This routine processes 802.11 management frames.
  293. Arguments:
  294. Link - Supplies a pointer to the 802.11 link on which the frame arrived.
  295. Packet - Supplies a pointer to the network packet.
  296. Return Value:
  297. None.
  298. --*/
  299. {
  300. ULONG FrameSubtype;
  301. PNET80211_MANAGEMENT_FRAME_HEADER Header;
  302. Header = Packet->Buffer + Packet->DataOffset;
  303. FrameSubtype = NET80211_GET_FRAME_SUBTYPE(Header);
  304. switch (FrameSubtype) {
  305. case NET80211_MANAGEMENT_FRAME_SUBTYPE_PROBE_RESPONSE:
  306. Net80211pProcessProbeResponse(Link, Packet);
  307. break;
  308. case NET80211_MANAGEMENT_FRAME_SUBTYPE_AUTHENTICATION:
  309. Net80211pProcessAuthenticationResponse(Link, Packet);
  310. break;
  311. case NET80211_MANAGEMENT_FRAME_SUBTYPE_ASSOCIATION_RESPONSE:
  312. Net80211pProcessAssociationResponse(Link, Packet);
  313. break;
  314. case NET80211_MANAGEMENT_FRAME_SUBTYPE_DISASSOCIATION:
  315. if ((Link->State != Net80211StateAssociated) &&
  316. (Link->State != Net80211StateEncrypted)) {
  317. break;
  318. }
  319. Net80211pSetState(Link, Net80211StateAssociating);
  320. break;
  321. case NET80211_MANAGEMENT_FRAME_SUBTYPE_DEAUTHENTICATION:
  322. if ((Link->State != Net80211StateAssociating) &&
  323. (Link->State != Net80211StateReassociating) &&
  324. (Link->State != Net80211StateAssociated) &&
  325. (Link->State != Net80211StateEncrypted)) {
  326. break;
  327. }
  328. Net80211pSetState(Link, Net80211StateAuthenticating);
  329. break;
  330. //
  331. // Ignore packets that are not yet handled.
  332. //
  333. case NET80211_MANAGEMENT_FRAME_SUBTYPE_REASSOCIATION_RESPONSE:
  334. case NET80211_MANAGEMENT_FRAME_SUBTYPE_BEACON:
  335. case NET80211_MANAGEMENT_FRAME_SUBTYPE_TIMING_ADVERTISEMENT:
  336. case NET80211_MANAGEMENT_FRAME_SUBTYPE_ATIM:
  337. case NET80211_MANAGEMENT_FRAME_SUBTYPE_ACTION:
  338. case NET80211_MANAGEMENT_FRAME_SUBTYPE_ACTION_NO_ACK:
  339. break;
  340. //
  341. // Toss out these request packets until AP mode is supported.
  342. //
  343. case NET80211_MANAGEMENT_FRAME_SUBTYPE_PROBE_REQUEST:
  344. case NET80211_MANAGEMENT_FRAME_SUBTYPE_REASSOCIATION_REQUEST:
  345. case NET80211_MANAGEMENT_FRAME_SUBTYPE_ASSOCIATION_REQUEST:
  346. default:
  347. break;
  348. }
  349. return;
  350. }
  351. KSTATUS
  352. Net80211pStartScan (
  353. PNET80211_LINK Link,
  354. PNET80211_SCAN_STATE Parameters
  355. )
  356. /*++
  357. Routine Description:
  358. This routine starts a scan for one or more BSSs within range of this
  359. station.
  360. Arguments:
  361. Link - Supplies a pointer to the 802.11 link on which to perform the scan.
  362. Parameters - Supplies a pointer to a scan state used to initialize the
  363. scan. This memory will not be referenced after the function returns,
  364. so this may be a stack allocated structure.
  365. Return Value:
  366. Status code.
  367. --*/
  368. {
  369. PNET80211_SCAN_STATE ScanState;
  370. KSTATUS Status;
  371. ASSERT(Parameters->SsidLength <= NET80211_MAX_SSID_LENGTH);
  372. ASSERT(Parameters->PassphraseLength <= NET80211_MAX_PASSPHRASE_LENGTH);
  373. ScanState = MmAllocatePagedPool(sizeof(NET80211_SCAN_STATE),
  374. NET80211_ALLOCATION_TAG);
  375. if (ScanState == NULL) {
  376. Status = STATUS_INSUFFICIENT_RESOURCES;
  377. goto StartScanEnd;
  378. }
  379. RtlCopyMemory(ScanState, Parameters, sizeof(NET80211_SCAN_STATE));
  380. Net80211LinkAddReference(Link);
  381. ScanState->Link = Link;
  382. //
  383. // Kick off a thread to complete the scan.
  384. //
  385. Status = PsCreateKernelThread(Net80211pScanThread,
  386. ScanState,
  387. "Net80211ScanThread");
  388. if (!KSUCCESS(Status)) {
  389. goto StartScanEnd;
  390. }
  391. StartScanEnd:
  392. if (!KSUCCESS(Status)) {
  393. if (ScanState != NULL) {
  394. Net80211pSetState(Link, Net80211StateInitialized);
  395. Net80211LinkReleaseReference(ScanState->Link);
  396. MmFreePagedPool(ScanState);
  397. }
  398. }
  399. return Status;
  400. }
  401. VOID
  402. Net80211pSetState (
  403. PNET80211_LINK Link,
  404. NET80211_STATE State
  405. )
  406. /*++
  407. Routine Description:
  408. This routine sets the given link's 802.11 state by alerting the driver of
  409. the state change and then performing any necessary actions based on the
  410. state transition.
  411. Arguments:
  412. Link - Supplies a pointer to the 802.11 link whose state is being updated.
  413. State - Supplies the state to which the link is transitioning.
  414. Return Value:
  415. None.
  416. --*/
  417. {
  418. KeAcquireQueuedLock(Link->Lock);
  419. Net80211pSetStateUnlocked(Link, State);
  420. KeReleaseQueuedLock(Link->Lock);
  421. return;
  422. }
  423. PNET80211_BSS_ENTRY
  424. Net80211pGetBss (
  425. PNET80211_LINK Link
  426. )
  427. /*++
  428. Routine Description:
  429. This routine gets the link's active BSS entry and hands back a pointer with
  430. a reference to the caller.
  431. Arguments:
  432. Link - Supplies a pointer to the 802.11 link whose active BSS is to be
  433. returned.
  434. Return Value:
  435. Returns a pointer to the active BSS.
  436. --*/
  437. {
  438. PNET80211_BSS_ENTRY Bss;
  439. Bss = NULL;
  440. if (Link->ActiveBss != NULL) {
  441. KeAcquireQueuedLock(Link->Lock);
  442. Bss = Link->ActiveBss;
  443. if (Bss != NULL) {
  444. Net80211pBssEntryAddReference(Bss);
  445. }
  446. KeReleaseQueuedLock(Link->Lock);
  447. }
  448. return Bss;
  449. }
  450. VOID
  451. Net80211pBssEntryAddReference (
  452. PNET80211_BSS_ENTRY BssEntry
  453. )
  454. /*++
  455. Routine Description:
  456. This routine increments the reference count of the given BSS entry.
  457. Arguments:
  458. BssEntry - Supplies a pointer to the BSS entry whose reference count is to
  459. be incremented.
  460. Return Value:
  461. None.
  462. --*/
  463. {
  464. ULONG OldReferenceCount;
  465. OldReferenceCount = RtlAtomicAdd32(&(BssEntry->ReferenceCount), 1);
  466. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  467. return;
  468. }
  469. VOID
  470. Net80211pBssEntryReleaseReference (
  471. PNET80211_BSS_ENTRY BssEntry
  472. )
  473. /*++
  474. Routine Description:
  475. This routine decrements the reference count of the given BSS entry,
  476. destroying the entry if there are no more references.
  477. Arguments:
  478. BssEntry - Supplies a pointer to the BSS entry whose reference count is to
  479. be decremented.
  480. Return Value:
  481. None.
  482. --*/
  483. {
  484. ULONG OldReferenceCount;
  485. OldReferenceCount = RtlAtomicAdd32(&(BssEntry->ReferenceCount), -1);
  486. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  487. if (OldReferenceCount == 1) {
  488. Net80211pDestroyBssEntry(BssEntry);
  489. }
  490. return;
  491. }
  492. VOID
  493. Net80211pStateTimeoutDpcRoutine (
  494. PDPC Dpc
  495. )
  496. /*++
  497. Routine Description:
  498. This routine implements the 802.11 state transition timeout DPC that gets
  499. called after a remote node does not respond to a management frame.
  500. Arguments:
  501. Dpc - Supplies a pointer to the DPC that is running.
  502. Return Value:
  503. None.
  504. --*/
  505. {
  506. PNET_LINK Link;
  507. PNET80211_LINK Net80211Link;
  508. Link = (PNET_LINK)Dpc->UserData;
  509. Net80211Link = Link->DataLinkContext;
  510. KeQueueWorkItem(Net80211Link->TimeoutWorkItem);
  511. return;
  512. }
  513. VOID
  514. Net80211pStateTimeoutWorker (
  515. PVOID Parameter
  516. )
  517. /*++
  518. Routine Description:
  519. This routine performs the low level work when an 802.11 state transition
  520. times out due to a remote node not responding.
  521. Arguments:
  522. Parameter - Supplies a pointer to the nework link whose 802.11 state
  523. transition has timed out.
  524. Return Value:
  525. None.
  526. --*/
  527. {
  528. PNET80211_LINK Link;
  529. Link = (PNET80211_LINK)Parameter;
  530. //
  531. // If a packet did not arrive to advance the state and cancel the timer,
  532. // then this really is a timeout. Set the state back to initialized.
  533. //
  534. KeAcquireQueuedLock(Link->Lock);
  535. if ((Link->Flags & NET80211_LINK_FLAG_TIMER_QUEUED) != 0) {
  536. Link->Flags &= ~NET80211_LINK_FLAG_TIMER_QUEUED;
  537. Net80211pSetStateUnlocked(Link, Net80211StateInitialized);
  538. }
  539. KeReleaseQueuedLock(Link->Lock);
  540. return;
  541. }
  542. PNET80211_BSS_ENTRY
  543. Net80211pLookupBssEntry (
  544. PNET80211_LINK Link,
  545. PUCHAR Bssid
  546. )
  547. /*++
  548. Routine Description:
  549. This routine searches the link for a known BSS entry with the given BSSID.
  550. It does not take a reference on the BSS entry and assumes that the link's
  551. lock is already held.
  552. Arguments:
  553. Link - Supplies a pointer to the 802.11 link on which to search.
  554. Bssid - Supplies a pointer to the BSSID for the desired BSS entry.
  555. Return Value:
  556. Returns a pointer to the matching BSS entry on success, or NULL on failure.
  557. --*/
  558. {
  559. PNET80211_BSS_ENTRY Bss;
  560. PLIST_ENTRY CurrentEntry;
  561. BOOL Match;
  562. PNET80211_BSS_ENTRY MatchedBss;
  563. ASSERT(KeIsQueuedLockHeld(Link->Lock) != FALSE);
  564. MatchedBss = NULL;
  565. CurrentEntry = Link->BssList.Next;
  566. while (CurrentEntry != &(Link->BssList)) {
  567. Bss = LIST_VALUE(CurrentEntry, NET80211_BSS_ENTRY, ListEntry);
  568. Match = RtlCompareMemory(Bssid,
  569. Bss->State.Bssid,
  570. NET80211_ADDRESS_SIZE);
  571. if (Match != FALSE) {
  572. MatchedBss = Bss;
  573. break;
  574. }
  575. CurrentEntry = CurrentEntry->Next;
  576. }
  577. return MatchedBss;
  578. }
  579. //
  580. // --------------------------------------------------------- Internal Functions
  581. //
  582. VOID
  583. Net80211pSetStateUnlocked (
  584. PNET80211_LINK Link,
  585. NET80211_STATE State
  586. )
  587. /*++
  588. Routine Description:
  589. This routine sets the given link's 802.11 state by alerting the driver of
  590. the state change and then performing any necessary actions based on the
  591. state transition. This routine assumes that the 802.11 link's lock is held.
  592. Arguments:
  593. Link - Supplies a pointer to the link whose state is being updated.
  594. State - Supplies the state to which the link is transitioning.
  595. Return Value:
  596. None.
  597. --*/
  598. {
  599. PNET80211_BSS_ENTRY Bss;
  600. PNET80211_BSS BssState;
  601. PVOID DeviceContext;
  602. ULONGLONG LinkSpeed;
  603. BOOL Notify;
  604. NET80211_STATE OldState;
  605. USHORT Reason;
  606. BOOL SetLinkUp;
  607. KSTATUS Status;
  608. ULONG Subtype;
  609. ASSERT(KeIsQueuedLockHeld(Link->Lock) != FALSE);
  610. Bss = Link->ActiveBss;
  611. OldState = Link->State;
  612. //
  613. // State transitions are not allowed from the probing state. Save the
  614. // transition so it can be replayed later after the link moves out of the
  615. // probing state.
  616. //
  617. if (OldState == Net80211StateProbing) {
  618. Link->ProbeNextState = State;
  619. goto SetStateUnlockedEnd;
  620. }
  621. //
  622. // Notify the driver about the state transition first, allowing it to
  623. // prepare for the type of packets to be sent and received in the new state.
  624. //
  625. BssState = NULL;
  626. if (Bss != NULL) {
  627. BssState = &(Bss->State);
  628. }
  629. DeviceContext = Link->Properties.DeviceContext;
  630. Status = Link->Properties.Interface.SetState(DeviceContext,
  631. State,
  632. BssState);
  633. if (!KSUCCESS(Status)) {
  634. RtlDebugPrint("802.11: Failed to set state %d: 0x%08x\n",
  635. State,
  636. Status);
  637. goto SetStateUnlockedEnd;
  638. }
  639. //
  640. // Officially update the state.
  641. //
  642. Link->State = State;
  643. //
  644. // Make sure the state transition timer is canceled.
  645. //
  646. Net80211pCancelStateTransitionTimer(Link);
  647. //
  648. // Perform the necessary steps according to the state transition.
  649. //
  650. SetLinkUp = FALSE;
  651. switch (State) {
  652. case Net80211StateAuthenticating:
  653. switch (OldState) {
  654. case Net80211StateAssociated:
  655. case Net80211StateEncrypted:
  656. Status = Net80211pPrepareForReconnect(Link, &Bss);
  657. if (!KSUCCESS(Status)) {
  658. goto SetStateUnlockedEnd;
  659. }
  660. //
  661. // Fall through to send the authentication request.
  662. //
  663. case Net80211StateAssociating:
  664. case Net80211StateReassociating:
  665. case Net80211StateInitialized:
  666. Status = Net80211pSendAuthenticationRequest(Link, Bss);
  667. if (!KSUCCESS(Status)) {
  668. goto SetStateUnlockedEnd;
  669. }
  670. Status = Net80211pQueueStateTransitionTimer(Link,
  671. NET80211_STATE_TIMEOUT);
  672. if (!KSUCCESS(Status)) {
  673. goto SetStateUnlockedEnd;
  674. }
  675. break;
  676. default:
  677. break;
  678. }
  679. break;
  680. case Net80211StateAssociating:
  681. switch (OldState) {
  682. case Net80211StateAssociated:
  683. case Net80211StateEncrypted:
  684. Status = Net80211pPrepareForReconnect(Link, &Bss);
  685. if (!KSUCCESS(Status)) {
  686. goto SetStateUnlockedEnd;
  687. }
  688. //
  689. // Fall through to send the association request.
  690. //
  691. case Net80211StateAuthenticating:
  692. //
  693. // Send out an association request and set the timeout.
  694. //
  695. Status = Net80211pSendAssociationRequest(Link, Bss);
  696. if (!KSUCCESS(Status)) {
  697. goto SetStateUnlockedEnd;
  698. }
  699. Status = Net80211pQueueStateTransitionTimer(Link,
  700. NET80211_STATE_TIMEOUT);
  701. if (!KSUCCESS(Status)) {
  702. goto SetStateUnlockedEnd;
  703. }
  704. break;
  705. default:
  706. break;
  707. }
  708. break;
  709. //
  710. // In the associated state, if no advanced encryption is involved, the link
  711. // is ready to start transmitting and receiving data.
  712. //
  713. case Net80211StateAssociated:
  714. ASSERT(Bss != NULL);
  715. if ((Bss->Encryption.Pairwise == NetworkEncryptionNone) ||
  716. (Bss->Encryption.Pairwise == NetworkEncryptionWep)) {
  717. SetLinkUp = TRUE;
  718. } else {
  719. //
  720. // Initialize the encryption authentication process so that it is
  721. // ready to receive key exchange packets.
  722. //
  723. Status = Net80211pInitializeEncryption(Link, Bss);
  724. if (!KSUCCESS(Status)) {
  725. goto SetStateUnlockedEnd;
  726. }
  727. Status = Net80211pQueueStateTransitionTimer(
  728. Link,
  729. NET80211_AUTHENTICATION_TIMEOUT);
  730. if (!KSUCCESS(Status)) {
  731. goto SetStateUnlockedEnd;
  732. }
  733. }
  734. break;
  735. //
  736. // If advanced encryption was involved, then the link is not ready until
  737. // the encrypted state is reached.
  738. //
  739. case Net80211StateEncrypted:
  740. ASSERT((Bss->Encryption.Pairwise == NetworkEncryptionWpaPsk) ||
  741. (Bss->Encryption.Pairwise == NetworkEncryptionWpa2Psk));
  742. Net80211pDestroyEncryption(Bss);
  743. SetLinkUp = TRUE;
  744. break;
  745. case Net80211StateInitialized:
  746. case Net80211StateUninitialized:
  747. switch (OldState) {
  748. case Net80211StateAssociated:
  749. case Net80211StateEncrypted:
  750. Notify = TRUE;
  751. Subtype = NET80211_MANAGEMENT_FRAME_SUBTYPE_DISASSOCIATION;
  752. Reason = NET80211_REASON_CODE_DISASSOCIATION_LEAVING;
  753. break;
  754. case Net80211StateAssociating:
  755. Notify = TRUE;
  756. Subtype = NET80211_MANAGEMENT_FRAME_SUBTYPE_DEAUTHENTICATION;
  757. Reason = NET80211_REASON_CODE_DEAUTHENTICATION_LEAVING;
  758. break;
  759. default:
  760. Notify = FALSE;
  761. Subtype = 0;
  762. Reason = 0;
  763. break;
  764. }
  765. if (Bss != NULL) {
  766. Net80211pDestroyEncryption(Bss);
  767. Net80211pLeaveBss(Link, Bss, Notify, Subtype, Reason);
  768. NetSetLinkState(Link->NetworkLink, FALSE, 0);
  769. }
  770. break;
  771. default:
  772. break;
  773. }
  774. //
  775. // If requested, fire up the link and get traffic going in the upper layers.
  776. //
  777. if (SetLinkUp != FALSE) {
  778. Net80211pResumeDataFrames(Link);
  779. LinkSpeed = Bss->State.MaxRate * NET80211_RATE_UNIT;
  780. NetSetLinkState(Link->NetworkLink, TRUE, LinkSpeed);
  781. }
  782. SetStateUnlockedEnd:
  783. return;
  784. }
  785. VOID
  786. Net80211pScanThread (
  787. PVOID Parameter
  788. )
  789. /*++
  790. Routine Description:
  791. This routine is the entry point for the scan thread.
  792. Arguments:
  793. Parameter - Supplies a pointer supplied by the creator of the thread. In
  794. this can it is a pointer to an 802.11 scan state structure.
  795. Return Value:
  796. None.
  797. --*/
  798. {
  799. PNET80211_BSS_ENTRY ActiveBss;
  800. PNET80211_BSS_ENTRY BssEntry;
  801. PLIST_ENTRY CurrentEntry;
  802. PNET80211_BSS_ENTRY FoundEntry;
  803. PNET80211_LINK Link;
  804. BOOL LockHeld;
  805. BOOL Match;
  806. LONG MaxRssi;
  807. PNET80211_SCAN_STATE Scan;
  808. ULONGLONG ScanDelay;
  809. ULONG SsidLength;
  810. KSTATUS Status;
  811. LockHeld = FALSE;
  812. Scan = (PNET80211_SCAN_STATE)Parameter;
  813. Link = Scan->Link;
  814. //
  815. // Acquire the link's scan lock to prevent multiple scans from happening
  816. // simultaneously. This protects the hardware from being set to different
  817. // channels and protects against a network being joined during a scan.
  818. //
  819. KeAcquireQueuedLock(Link->ScanLock);
  820. //
  821. // Before pulling in new BSS entries, clean out the old ones.
  822. //
  823. Net80211pTrimBssCache(Link);
  824. //
  825. // If there is an active BSS, then this is a background scan.
  826. //
  827. ActiveBss = Net80211pGetBss(Link);
  828. if (ActiveBss != NULL) {
  829. Scan->Flags |= NET80211_SCAN_FLAG_BACKGROUND;
  830. }
  831. //
  832. // If this is a foreground scan, just set the state to probing and start
  833. // running through the channels.
  834. //
  835. if ((Scan->Flags & NET80211_SCAN_FLAG_BACKGROUND) == 0) {
  836. Net80211pStartProbing(Link);
  837. ScanDelay = NET80211_DEFAULT_SCAN_DWELL_TIME;
  838. } else {
  839. ScanDelay = ActiveBss->State.BeaconInterval * NET80211_TIME_UNIT;
  840. if (ScanDelay > NET80211_BEACON_INTERVAL_PAD) {
  841. ScanDelay -= NET80211_BEACON_INTERVAL_PAD;
  842. }
  843. }
  844. //
  845. // Always start scanning on channel 1.
  846. //
  847. Scan->Channel = 1;
  848. //
  849. // Search for BSS entries on all channels.
  850. //
  851. FoundEntry = NULL;
  852. while (Scan->Channel < Link->Properties.MaxChannel) {
  853. //
  854. // If this a background scan, temporarily set the state to probing to
  855. // alert that hardware that it's in scan mode.
  856. //
  857. if ((Scan->Flags & NET80211_SCAN_FLAG_BACKGROUND) != 0) {
  858. Net80211pStartProbing(Link);
  859. }
  860. //
  861. // Set the channel to send the packet over.
  862. //
  863. Status = Net80211pSetChannel(Link, Scan->Channel);
  864. if (!KSUCCESS(Status)) {
  865. goto ScanThreadEnd;
  866. }
  867. //
  868. // Send a probe request over the link, this will look in the
  869. // current scan state and set the correct channel and BSSID
  870. // (broadcast or a specific ID).
  871. //
  872. Status = Net80211pSendProbeRequest(Link, Scan);
  873. if (!KSUCCESS(Status)) {
  874. goto ScanThreadEnd;
  875. }
  876. //
  877. // Give the responses a chance before moving to the next channel.
  878. //
  879. KeDelayExecution(FALSE, FALSE, ScanDelay);
  880. //
  881. // If this a background scan, set the state back to what it was and
  882. // continue sending packets for a period.
  883. //
  884. if ((Scan->Flags & NET80211_SCAN_FLAG_BACKGROUND) != 0) {
  885. if (ActiveBss != NULL) {
  886. Status = Net80211pSetChannel(Link, ActiveBss->State.Channel);
  887. if (!KSUCCESS(Status)) {
  888. goto ScanThreadEnd;
  889. }
  890. }
  891. Net80211pStopProbing(Link);
  892. }
  893. //
  894. // Now that the channel has been probed, search to see if the
  895. // targeted BSS is in range. This should only be done if a specific
  896. // BSSID is being probed.
  897. //
  898. if (((Scan->Flags & NET80211_SCAN_FLAG_BROADCAST) == 0) &&
  899. ((Scan->Flags & NET80211_SCAN_FLAG_JOIN) != 0)) {
  900. KeAcquireQueuedLock(Link->Lock);
  901. LockHeld = TRUE;
  902. FoundEntry = Net80211pLookupBssEntry(Link, Scan->Bssid);
  903. if (FoundEntry != NULL) {
  904. Status = Net80211pValidateRates(Link, FoundEntry);
  905. if (!KSUCCESS(Status)) {
  906. goto ScanThreadEnd;
  907. }
  908. break;
  909. }
  910. KeReleaseQueuedLock(Link->Lock);
  911. LockHeld = FALSE;
  912. }
  913. Scan->Channel += 1;
  914. //
  915. // When performing background scans, wait a bit before moving to the
  916. // next channel to allow normal traffic to progress.
  917. //
  918. if ((Scan->Flags & NET80211_SCAN_FLAG_BACKGROUND) != 0) {
  919. KeDelayExecution(FALSE,
  920. FALSE,
  921. NET80211_BACKGROUND_SCAN_CHANNEL_DELAY);
  922. }
  923. }
  924. //
  925. // Stop probing if this is not a background scan.
  926. //
  927. if ((Scan->Flags & NET80211_SCAN_FLAG_BACKGROUND) == 0) {
  928. Net80211pStopProbing(Link);
  929. }
  930. //
  931. // If the scan completed and a join is required, then search for the
  932. // BSS with the most signal strength.
  933. //
  934. if (((Scan->Flags & NET80211_SCAN_FLAG_BROADCAST) != 0) &&
  935. ((Scan->Flags & NET80211_SCAN_FLAG_JOIN) != 0)) {
  936. ASSERT(Scan->SsidLength != 0);
  937. ASSERT(FoundEntry == NULL);
  938. MaxRssi = MIN_LONG;
  939. KeAcquireQueuedLock(Link->Lock);
  940. LockHeld = TRUE;
  941. CurrentEntry = Link->BssList.Next;
  942. while (CurrentEntry != &(Link->BssList)) {
  943. BssEntry = LIST_VALUE(CurrentEntry,
  944. NET80211_BSS_ENTRY,
  945. ListEntry);
  946. CurrentEntry = CurrentEntry->Next;
  947. SsidLength = NET80211_GET_ELEMENT_LENGTH(BssEntry->Ssid);
  948. if (SsidLength != Scan->SsidLength) {
  949. continue;
  950. }
  951. Match = RtlCompareMemory(NET80211_GET_ELEMENT_DATA(BssEntry->Ssid),
  952. Scan->Ssid,
  953. Scan->SsidLength);
  954. if (Match == FALSE) {
  955. continue;
  956. }
  957. //
  958. // Validate that the BSS and station agree on a basic rate set.
  959. // Also determine the mode at which it would connect.
  960. //
  961. Status = Net80211pValidateRates(Link, BssEntry);
  962. if (!KSUCCESS(Status)) {
  963. continue;
  964. }
  965. if (BssEntry->State.Rssi >= MaxRssi) {
  966. MaxRssi = BssEntry->State.Rssi;
  967. FoundEntry = BssEntry;
  968. }
  969. }
  970. if (FoundEntry == NULL) {
  971. KeReleaseQueuedLock(Link->Lock);
  972. LockHeld = FALSE;
  973. }
  974. }
  975. //
  976. // If an entry was found, join that BSS and start the authentication
  977. // process.
  978. //
  979. if (FoundEntry != NULL) {
  980. ASSERT(KeIsQueuedLockHeld(Link->Lock) != FALSE);
  981. if (FoundEntry->Encryption.Pairwise != NetworkEncryptionNone) {
  982. if (Scan->PassphraseLength == 0) {
  983. Status = STATUS_ACCESS_DENIED;
  984. goto ScanThreadEnd;
  985. }
  986. if (FoundEntry->Encryption.Pairwise != NetworkEncryptionWpa2Psk) {
  987. Status = STATUS_NOT_SUPPORTED;
  988. goto ScanThreadEnd;
  989. }
  990. RtlCopyMemory(FoundEntry->Passphrase,
  991. Scan->Passphrase,
  992. Scan->PassphraseLength);
  993. FoundEntry->PassphraseLength = Scan->PassphraseLength;
  994. }
  995. //
  996. // Leave the active BSS by setting the state back to initialized.
  997. //
  998. Net80211pSetStateUnlocked(Link, Net80211StateInitialized);
  999. Net80211pJoinBss(Link, FoundEntry);
  1000. Net80211pSetChannel(Link, FoundEntry->State.Channel);
  1001. Net80211pSetStateUnlocked(Link, Net80211StateAuthenticating);
  1002. Status = STATUS_SUCCESS;
  1003. } else if ((Scan->Flags & NET80211_SCAN_FLAG_JOIN) != 0) {
  1004. Status = STATUS_UNSUCCESSFUL;
  1005. } else {
  1006. Status = STATUS_SUCCESS;
  1007. }
  1008. ScanThreadEnd:
  1009. if (LockHeld != FALSE) {
  1010. KeReleaseQueuedLock(Link->Lock);
  1011. }
  1012. KeReleaseQueuedLock(Link->ScanLock);
  1013. if (!KSUCCESS(Status)) {
  1014. Net80211pSetState(Link, Net80211StateInitialized);
  1015. }
  1016. if (Scan->CompletionRoutine != NULL) {
  1017. Scan->CompletionRoutine(Link, Status);
  1018. }
  1019. if (ActiveBss != NULL) {
  1020. Net80211pBssEntryReleaseReference(ActiveBss);
  1021. }
  1022. Net80211LinkReleaseReference(Link);
  1023. MmFreePagedPool(Scan);
  1024. return;
  1025. }
  1026. VOID
  1027. Net80211pStartProbing (
  1028. PNET80211_LINK Link
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. This routine prepares the given link for a network probe by pausing data
  1033. frames and saving the current state.
  1034. Arguments:
  1035. Link - Supplies a pointer to the 802.11 link that is about to start probing
  1036. for networks.
  1037. Return Value:
  1038. None.
  1039. --*/
  1040. {
  1041. PNET80211_BSS BssState;
  1042. PVOID DeviceContext;
  1043. KSTATUS Status;
  1044. KeAcquireQueuedLock(Link->Lock);
  1045. ASSERT(Link->State != Net80211StateProbing);
  1046. ASSERT(Link->ProbePreviousState == Net80211StateInvalid);
  1047. ASSERT(Link->ProbeNextState == Net80211StateInvalid);
  1048. //
  1049. // Set the next state to invalid.
  1050. //
  1051. Link->ProbeNextState = Net80211StateInvalid;
  1052. //
  1053. // When entering the probe state, immediately pause data packet
  1054. // transmission. This must be done before the hardware is notified of the
  1055. // switch.
  1056. //
  1057. Net80211pPauseDataFrames(Link);
  1058. //
  1059. // Notify the hardware about the transition to probing.
  1060. //
  1061. BssState = NULL;
  1062. if (Link->ActiveBss != NULL) {
  1063. BssState = &(Link->ActiveBss->State);
  1064. }
  1065. DeviceContext = Link->Properties.DeviceContext;
  1066. Status = Link->Properties.Interface.SetState(DeviceContext,
  1067. Net80211StateProbing,
  1068. BssState);
  1069. if (!KSUCCESS(Status)) {
  1070. RtlDebugPrint("802.11: Failed to set state %d: 0x%08x\n",
  1071. Net80211StateProbing,
  1072. Status);
  1073. goto StartProbingEnd;
  1074. }
  1075. //
  1076. // Save the current state and transition to the probing state.
  1077. //
  1078. Link->ProbePreviousState = Link->State;
  1079. Link->State = Net80211StateProbing;
  1080. StartProbingEnd:
  1081. if (!KSUCCESS(Status)) {
  1082. Net80211pResumeDataFrames(Link);
  1083. }
  1084. KeReleaseQueuedLock(Link->Lock);
  1085. return;
  1086. }
  1087. VOID
  1088. Net80211pStopProbing (
  1089. PNET80211_LINK Link
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. This routine takes the given link for out of the probing state, restoring
  1094. the previous state. Keep in mind that an attempt to transition the state
  1095. may have occurred while the link was probing. This routine will replay that
  1096. transition after reverting the previous state.
  1097. Arguments:
  1098. Link - Supplies a pointer to the 802.11 link that is exiting the probing
  1099. state.
  1100. Return Value:
  1101. None.
  1102. --*/
  1103. {
  1104. PNET80211_BSS BssState;
  1105. PVOID DeviceContext;
  1106. KSTATUS Status;
  1107. KeAcquireQueuedLock(Link->Lock);
  1108. ASSERT(Link->State == Net80211StateProbing);
  1109. //
  1110. // Restore the initial state, notify the hardware of the transition and
  1111. // resume the data frames.
  1112. //
  1113. BssState = NULL;
  1114. if (Link->ActiveBss != NULL) {
  1115. BssState = &(Link->ActiveBss->State);
  1116. }
  1117. DeviceContext = Link->Properties.DeviceContext;
  1118. Status = Link->Properties.Interface.SetState(DeviceContext,
  1119. Link->ProbePreviousState,
  1120. BssState);
  1121. if (!KSUCCESS(Status)) {
  1122. RtlDebugPrint("802.11: Failed to set state %d: 0x%08x\n",
  1123. Link->ProbePreviousState,
  1124. Status);
  1125. goto StopProbingEnd;
  1126. }
  1127. Link->State = Link->ProbePreviousState;
  1128. Net80211pResumeDataFrames(Link);
  1129. //
  1130. // If the transition state is not invalid, then the link tried to move to
  1131. // a new state while the probe was active. Replay that transition now that
  1132. // the original state is restored.
  1133. //
  1134. if (Link->ProbeNextState != Net80211StateInvalid) {
  1135. Net80211pSetStateUnlocked(Link, Link->ProbeNextState);
  1136. }
  1137. Link->ProbePreviousState = Net80211StateInvalid;
  1138. Link->ProbeNextState = Net80211StateInvalid;
  1139. StopProbingEnd:
  1140. KeReleaseQueuedLock(Link->Lock);
  1141. return;
  1142. }
  1143. KSTATUS
  1144. Net80211pPrepareForReconnect (
  1145. PNET80211_LINK Link,
  1146. PNET80211_BSS_ENTRY *Bss
  1147. )
  1148. /*++
  1149. Routine Description:
  1150. This routine prepares the network link for reconnecting to the given BSS.
  1151. This includes pausing all outgoing data traffic and creating a copy of the
  1152. BSS entry to use for the new association.
  1153. Arguments:
  1154. Link - Supplies a pointer to the 802.11 link to be connected to the BSS.
  1155. Bss - Supplies a pointer to a BSS on entry on input that is being left and
  1156. on output, receives a pointer to the copied BSS entry to join.
  1157. Return Value:
  1158. Status code.
  1159. --*/
  1160. {
  1161. PNET80211_BSS_ENTRY BssCopy;
  1162. PNET80211_BSS_ENTRY BssOriginal;
  1163. KSTATUS Status;
  1164. BssOriginal = *Bss;
  1165. ASSERT(KeIsQueuedLockHeld(Link->Lock) != FALSE);
  1166. ASSERT(BssOriginal = Link->ActiveBss);
  1167. //
  1168. // Copy the BSS so a fresh state is used for the reconnection. Old
  1169. // encryption keys must be reacquired.
  1170. //
  1171. BssCopy = Net80211pCopyBssEntry(BssOriginal);
  1172. if (BssCopy == NULL) {
  1173. Status = STATUS_INSUFFICIENT_RESOURCES;
  1174. goto PrepareForReconnectEnd;
  1175. }
  1176. //
  1177. // Pause all data frames while the link is attempting to reconnect to the
  1178. // BSS.
  1179. //
  1180. Net80211pPauseDataFrames(Link);
  1181. //
  1182. // Leave the original BSS and join the copy.
  1183. //
  1184. Net80211pLeaveBss(Link, BssOriginal, FALSE, 0, 0);
  1185. Net80211pJoinBss(Link, BssCopy);
  1186. INSERT_BEFORE(&(BssCopy->ListEntry), &(Link->BssList));
  1187. *Bss = BssCopy;
  1188. Status = STATUS_SUCCESS;
  1189. PrepareForReconnectEnd:
  1190. return Status;
  1191. }
  1192. VOID
  1193. Net80211pJoinBss (
  1194. PNET80211_LINK Link,
  1195. PNET80211_BSS_ENTRY Bss
  1196. )
  1197. /*++
  1198. Routine Description:
  1199. This routine joins the given network link to the BSS.
  1200. Arguments:
  1201. Link - Supplies a pointer to the 802.11 link that is joining the BSS.
  1202. Bss - Supplies a pointer to the BSS to join.
  1203. Return Value:
  1204. None.
  1205. --*/
  1206. {
  1207. ASSERT(Link->ActiveBss == NULL);
  1208. ASSERT(KeIsQueuedLockHeld(Link->Lock) != FALSE);
  1209. Link->ActiveBss = Bss;
  1210. Net80211pBssEntryAddReference(Bss);
  1211. return;
  1212. }
  1213. VOID
  1214. Net80211pLeaveBss (
  1215. PNET80211_LINK Link,
  1216. PNET80211_BSS_ENTRY Bss,
  1217. BOOL SendNotification,
  1218. ULONG Subtype,
  1219. USHORT Reason
  1220. )
  1221. /*++
  1222. Routine Description:
  1223. This routine disconnects the network link from the given BSS. With this
  1224. disconnection, any encryption keys are now invalid. To safely move said
  1225. keys out of the system, this routine removes the BSS from the global list
  1226. and releases the reference taken by the list. The BSS entry should be
  1227. destroyed shortly.
  1228. Arguments:
  1229. Link - Supplies a pointer to the 802.11 link that is leaving the BSS.
  1230. Bss - Supplies a pointer to the BSS to leave.
  1231. SendNotification - Supplies a boolean indicating whether or not this
  1232. station should notify the BSS that it is leaving.
  1233. Subtype - Supplies the notification type in the form of a management frame
  1234. subtype. It should either be disassociation or deauthentication.
  1235. Reason - Supplies the reason for leaving. See NET80211_REASON_CODE_* for
  1236. definitions.
  1237. Return Value:
  1238. None.
  1239. --*/
  1240. {
  1241. ASSERT(Link->ActiveBss == Bss);
  1242. ASSERT(KeIsQueuedLockHeld(Link->Lock) != FALSE);
  1243. if (SendNotification != FALSE) {
  1244. Net80211pSendManagementFrame(Link,
  1245. Bss->State.Bssid,
  1246. Bss->State.Bssid,
  1247. Subtype,
  1248. &Reason,
  1249. sizeof(USHORT));
  1250. }
  1251. Link->ActiveBss = NULL;
  1252. //
  1253. // Remove the BSS from the global list, destroy the reference taken on join
  1254. // and the list's reference. This really just needs to destroy the keys,
  1255. // but while the BSS is on the list and reference are outstanding, the keys
  1256. // may be in use. The best thing to do is destroy the BSS entry.
  1257. //
  1258. LIST_REMOVE(&(Bss->ListEntry));
  1259. Net80211pBssEntryReleaseReference(Bss);
  1260. Net80211pBssEntryReleaseReference(Bss);
  1261. return;
  1262. }
  1263. KSTATUS
  1264. Net80211pSendProbeRequest (
  1265. PNET80211_LINK Link,
  1266. PNET80211_SCAN_STATE Scan
  1267. )
  1268. /*++
  1269. Routine Description:
  1270. This routine sends an 802.11 management probe request frame based on the
  1271. given scan state.
  1272. Arguments:
  1273. Link - Supplies a pointer to the 802.11 link on which to send the probe
  1274. request.
  1275. Scan - Supplies a pointer to the scan state that is requesting the probe.
  1276. Return Value:
  1277. Status code.
  1278. --*/
  1279. {
  1280. PUCHAR Bssid;
  1281. PUCHAR DestinationAddress;
  1282. PUCHAR FrameBody;
  1283. ULONG FrameBodySize;
  1284. ULONG FrameSubtype;
  1285. PUCHAR InformationByte;
  1286. PNET80211_RATE_INFORMATION Rates;
  1287. KSTATUS Status;
  1288. FrameBody = NULL;
  1289. //
  1290. // The probe request packed always includes the SSID, supported rates and
  1291. // channel (DSSS).
  1292. //
  1293. ASSERT(Scan->SsidLength <= NET80211_MAX_SSID_LENGTH);
  1294. FrameBodySize = 0;
  1295. FrameBodySize += NET80211_ELEMENT_HEADER_SIZE;
  1296. FrameBodySize += Scan->SsidLength;
  1297. //
  1298. // Get the supported rates size.
  1299. //
  1300. Rates = Link->Properties.SupportedRates;
  1301. FrameBodySize += NET80211_ELEMENT_HEADER_SIZE;
  1302. if (Rates->Count > NET80211_MAX_SUPPORTED_RATES) {
  1303. FrameBodySize += NET80211_ELEMENT_HEADER_SIZE;
  1304. }
  1305. FrameBodySize += Rates->Count;
  1306. //
  1307. // Get the DSSS (channel) size.
  1308. //
  1309. FrameBodySize += NET80211_DSSS_SIZE;
  1310. //
  1311. // Allocate a buffer to hold the probe request frame body.
  1312. //
  1313. FrameBody = MmAllocatePagedPool(FrameBodySize, NET80211_ALLOCATION_TAG);
  1314. if (FrameBody == NULL) {
  1315. Status = STATUS_INSUFFICIENT_RESOURCES;
  1316. goto SendProbeRequestEnd;
  1317. }
  1318. //
  1319. // Fill out the frame body. There is a strict order here, so do not
  1320. // rearrange the information elements.
  1321. //
  1322. InformationByte = FrameBody;
  1323. *InformationByte = NET80211_ELEMENT_SSID;
  1324. InformationByte += 1;
  1325. *InformationByte = Scan->SsidLength;
  1326. InformationByte += 1;
  1327. if (Scan->SsidLength != 0) {
  1328. RtlCopyMemory(InformationByte, Scan->Ssid, Scan->SsidLength);
  1329. InformationByte += Scan->SsidLength;
  1330. }
  1331. *InformationByte = NET80211_ELEMENT_SUPPORTED_RATES;
  1332. InformationByte += 1;
  1333. if (Rates->Count <= NET80211_MAX_SUPPORTED_RATES) {
  1334. *InformationByte = Rates->Count;
  1335. InformationByte += 1;
  1336. RtlCopyMemory(InformationByte, Rates->Rate, Rates->Count);
  1337. InformationByte += Rates->Count;
  1338. } else {
  1339. *InformationByte = NET80211_MAX_SUPPORTED_RATES;
  1340. InformationByte += 1;
  1341. RtlCopyMemory(InformationByte,
  1342. Rates->Rate,
  1343. NET80211_MAX_SUPPORTED_RATES);
  1344. InformationByte += NET80211_MAX_SUPPORTED_RATES;
  1345. *InformationByte = NET80211_ELEMENT_EXTENDED_SUPPORTED_RATES;
  1346. InformationByte += 1;
  1347. *InformationByte = Rates->Count - NET80211_MAX_SUPPORTED_RATES;
  1348. InformationByte += 1;
  1349. RtlCopyMemory(InformationByte,
  1350. &(Rates->Rate[NET80211_MAX_SUPPORTED_RATES]),
  1351. Rates->Count - NET80211_MAX_SUPPORTED_RATES);
  1352. InformationByte += Rates->Count - NET80211_MAX_SUPPORTED_RATES;
  1353. }
  1354. *InformationByte = NET80211_ELEMENT_DSSS;
  1355. InformationByte += 1;
  1356. *InformationByte = 1;
  1357. InformationByte += 1;
  1358. *InformationByte = (UCHAR)Scan->Channel;
  1359. InformationByte += 1;
  1360. ASSERT(FrameBodySize == (InformationByte - FrameBody));
  1361. //
  1362. // Send the management frame down to the lower layers.
  1363. //
  1364. if ((Scan->Flags & NET80211_SCAN_FLAG_BROADCAST) != 0) {
  1365. Bssid = NULL;
  1366. DestinationAddress = NULL;
  1367. } else {
  1368. Bssid = Scan->Bssid;
  1369. DestinationAddress = Scan->Bssid;
  1370. }
  1371. FrameSubtype = NET80211_MANAGEMENT_FRAME_SUBTYPE_PROBE_REQUEST;
  1372. Status = Net80211pSendManagementFrame(Link,
  1373. DestinationAddress,
  1374. Bssid,
  1375. FrameSubtype,
  1376. FrameBody,
  1377. FrameBodySize);
  1378. if (!KSUCCESS(Status)) {
  1379. goto SendProbeRequestEnd;
  1380. }
  1381. SendProbeRequestEnd:
  1382. if (FrameBody != NULL) {
  1383. MmFreePagedPool(FrameBody);
  1384. }
  1385. return Status;
  1386. }
  1387. VOID
  1388. Net80211pProcessProbeResponse (
  1389. PNET80211_LINK Link,
  1390. PNET_PACKET_BUFFER Packet
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. This routine processes an 802.11 management probe response frame. It stores
  1395. the information for the transmitting BSS in the BSS cache.
  1396. Arguments:
  1397. Link - Supplies a pointer to the 802.11 link that received the probe
  1398. response.
  1399. Packet - Supplies a pointer to the packet to process.
  1400. Return Value:
  1401. None.
  1402. --*/
  1403. {
  1404. UCHAR ElementId;
  1405. ULONG ElementLength;
  1406. ULONG ExpectedFrameSize;
  1407. PUCHAR FrameBody;
  1408. ULONG FrameSize;
  1409. PNET80211_MANAGEMENT_FRAME_HEADER Header;
  1410. ULONG Offset;
  1411. NET80211_PROBE_RESPONSE Response;
  1412. ULONG Subtype;
  1413. if (Link->State != Net80211StateProbing) {
  1414. goto ProcessProbeResponseEnd;
  1415. }
  1416. Header = Packet->Buffer + Packet->DataOffset;
  1417. Subtype = NET80211_GET_FRAME_SUBTYPE(Header);
  1418. RtlZeroMemory(&Response, sizeof(NET80211_PROBE_RESPONSE));
  1419. ASSERT((Subtype == NET80211_MANAGEMENT_FRAME_SUBTYPE_BEACON) ||
  1420. (Subtype == NET80211_MANAGEMENT_FRAME_SUBTYPE_PROBE_RESPONSE));
  1421. //
  1422. // Parse the response. It should at least have a timestamp, beacon
  1423. // interval, and capabilities field.
  1424. //
  1425. FrameBody = Packet->Buffer + Packet->DataOffset;
  1426. FrameSize = Packet->FooterOffset - Packet->DataOffset;
  1427. Offset = sizeof(NET80211_MANAGEMENT_FRAME_HEADER);
  1428. ExpectedFrameSize = Offset +
  1429. NET80211_TIMESTAMP_SIZE +
  1430. NET80211_BEACON_INTERVAL_SIZE +
  1431. NET80211_CAPABILITY_SIZE;
  1432. if (ExpectedFrameSize > FrameSize) {
  1433. goto ProcessProbeResponseEnd;
  1434. }
  1435. //
  1436. // Save the timestamp.
  1437. //
  1438. Response.Timestamp = *((PULONGLONG)&(FrameBody[Offset]));
  1439. Offset += NET80211_TIMESTAMP_SIZE;
  1440. //
  1441. // Save the beacon internval.
  1442. //
  1443. Response.BeaconInterval = *((PUSHORT)&(FrameBody[Offset]));
  1444. Offset += NET80211_BEACON_INTERVAL_SIZE;
  1445. //
  1446. // Save the capabilities.
  1447. //
  1448. Response.Capabilities = *((PUSHORT)&(FrameBody[Offset]));
  1449. Offset += NET80211_CAPABILITY_SIZE;
  1450. //
  1451. // Collect the information elements.
  1452. //
  1453. Response.Elements = FrameBody + Offset;
  1454. Response.ElementsSize = FrameSize - Offset;
  1455. while (Offset < FrameSize) {
  1456. if ((Offset + NET80211_ELEMENT_HEADER_SIZE) > FrameSize) {
  1457. goto ProcessProbeResponseEnd;
  1458. }
  1459. ElementId = FrameBody[Offset + NET80211_ELEMENT_ID_OFFSET];
  1460. ElementLength = FrameBody[Offset + NET80211_ELEMENT_LENGTH_OFFSET];
  1461. ExpectedFrameSize = Offset +
  1462. NET80211_ELEMENT_HEADER_SIZE +
  1463. ElementLength;
  1464. if (ExpectedFrameSize > FrameSize) {
  1465. goto ProcessProbeResponseEnd;
  1466. }
  1467. switch (ElementId) {
  1468. case NET80211_ELEMENT_SSID:
  1469. Response.Ssid = FrameBody + Offset;
  1470. break;
  1471. case NET80211_ELEMENT_DSSS:
  1472. if (ElementLength == 0) {
  1473. goto ProcessProbeResponseEnd;
  1474. }
  1475. Response.Channel = FrameBody + Offset;
  1476. break;
  1477. case NET80211_ELEMENT_RSN:
  1478. Response.Rsn = FrameBody + Offset;
  1479. break;
  1480. case NET80211_ELEMENT_SUPPORTED_RATES:
  1481. if (ElementLength == 0) {
  1482. goto ProcessProbeResponseEnd;
  1483. }
  1484. Response.Rates = FrameBody + Offset;
  1485. break;
  1486. case NET80211_ELEMENT_EXTENDED_SUPPORTED_RATES:
  1487. if (ElementLength == 0) {
  1488. goto ProcessProbeResponseEnd;
  1489. }
  1490. Response.ExtendedRates = FrameBody + Offset;
  1491. break;
  1492. default:
  1493. break;
  1494. }
  1495. Offset += NET80211_ELEMENT_HEADER_SIZE + ElementLength;
  1496. }
  1497. //
  1498. // Toss out the packet if not all of the expected information is present.
  1499. //
  1500. if ((Response.Rates == NULL) ||
  1501. (Response.Channel == NULL) ||
  1502. (Response.Ssid == NULL)) {
  1503. goto ProcessProbeResponseEnd;
  1504. }
  1505. //
  1506. // Filter out any beacon/probe responses that claim to be open but still
  1507. // include encryption information. Also filter out the opposite where
  1508. // privacy is a required capability, but no encryption information was
  1509. // provided.
  1510. //
  1511. if (Response.Rsn != NULL) {
  1512. if ((Response.Capabilities & NET80211_CAPABILITY_FLAG_PRIVACY) == 0) {
  1513. RtlDebugPrint("802.11: Found RSN element in probe/beacon that does "
  1514. "not require privacy.\n");
  1515. goto ProcessProbeResponseEnd;
  1516. }
  1517. } else {
  1518. if ((Response.Capabilities & NET80211_CAPABILITY_FLAG_PRIVACY) != 0) {
  1519. RtlDebugPrint("802.11: Did not find RSN element in probe/beacon "
  1520. "that requires privacy.\n");
  1521. goto ProcessProbeResponseEnd;
  1522. }
  1523. }
  1524. //
  1525. // Update the BSS cache with the latest information from this beacon /
  1526. // probe response. The SSID, encryption method, and rates are subject to
  1527. // change for a BSSID.
  1528. //
  1529. Response.Bssid = Header->SourceAddress;
  1530. Net80211pUpdateBssCache(Link, &Response);
  1531. ProcessProbeResponseEnd:
  1532. return;
  1533. }
  1534. KSTATUS
  1535. Net80211pSendAuthenticationRequest (
  1536. PNET80211_LINK Link,
  1537. PNET80211_BSS_ENTRY Bss
  1538. )
  1539. /*++
  1540. Routine Description:
  1541. This routine sends an 802.11 management authentication frame to the AP of
  1542. the given BSS.
  1543. Arguments:
  1544. Link - Supplies a pointer to the 802.11 link on which to send an
  1545. authentication request.
  1546. Bss - Supplies a pointer to the BSS over which to send the authentication
  1547. frame.
  1548. Return Value:
  1549. Status code.
  1550. --*/
  1551. {
  1552. NET80211_AUTHENTICATION_OPEN_BODY FrameBody;
  1553. ULONG FrameBodySize;
  1554. ULONG FrameSubtype;
  1555. KSTATUS Status;
  1556. //
  1557. // Fill out the authentication body.
  1558. //
  1559. FrameBody.AlgorithmNumber = NET80211_AUTHENTICATION_ALGORITHM_OPEN;
  1560. FrameBody.TransactionSequenceNumber =
  1561. NET80211_AUTHENTICATION_REQUEST_SEQUENCE_NUMBER;
  1562. FrameBody.StatusCode = NET80211_STATUS_CODE_SUCCESS;
  1563. //
  1564. // Send the authentication frame off. The destination address and BSSID
  1565. // should match.
  1566. //
  1567. FrameBodySize = sizeof(NET80211_AUTHENTICATION_OPEN_BODY);
  1568. FrameSubtype = NET80211_MANAGEMENT_FRAME_SUBTYPE_AUTHENTICATION;
  1569. Status = Net80211pSendManagementFrame(Link,
  1570. Bss->State.Bssid,
  1571. Bss->State.Bssid,
  1572. FrameSubtype,
  1573. &FrameBody,
  1574. FrameBodySize);
  1575. if (!KSUCCESS(Status)) {
  1576. goto SendAuthenticationEnd;
  1577. }
  1578. SendAuthenticationEnd:
  1579. return Status;
  1580. }
  1581. VOID
  1582. Net80211pProcessAuthenticationResponse (
  1583. PNET80211_LINK Link,
  1584. PNET_PACKET_BUFFER Packet
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. This routine processes an authentication response frame. It is expected to
  1589. be sent from the BSSID stored in the link's BSS context.
  1590. Arguments:
  1591. Link - Supplies a pointer to the 802.11 link on which the authentication
  1592. packet was received.
  1593. Packet - Supplies a pointer to the network packet containing the
  1594. authentication frame.
  1595. Return Value:
  1596. None.
  1597. --*/
  1598. {
  1599. PNET80211_AUTHENTICATION_OPEN_BODY Body;
  1600. PNET80211_BSS_ENTRY Bss;
  1601. ULONG ExpectedFrameSize;
  1602. ULONG FrameSize;
  1603. PNET80211_MANAGEMENT_FRAME_HEADER Header;
  1604. BOOL Match;
  1605. KSTATUS Status;
  1606. Status = STATUS_SUCCESS;
  1607. if (Link->State != Net80211StateAuthenticating) {
  1608. return;
  1609. }
  1610. KeAcquireQueuedLock(Link->Lock);
  1611. if (Link->State != Net80211StateAuthenticating) {
  1612. goto ProcessAuthenticationResponseEnd;
  1613. }
  1614. ASSERT(Link->ActiveBss != NULL);
  1615. Bss = Link->ActiveBss;
  1616. //
  1617. // Make sure the this frame was sent from the AP of the BSS.
  1618. //
  1619. Header = Packet->Buffer + Packet->DataOffset;
  1620. Match = RtlCompareMemory(Header->SourceAddress,
  1621. Bss->State.Bssid,
  1622. NET80211_ADDRESS_SIZE);
  1623. if (Match == FALSE) {
  1624. Status = STATUS_INVALID_ADDRESS;
  1625. goto ProcessAuthenticationResponseEnd;
  1626. }
  1627. //
  1628. // Make sure it is large enough to hold the authentication body.
  1629. //
  1630. FrameSize = Packet->FooterOffset - Packet->DataOffset;
  1631. ExpectedFrameSize = sizeof(NET80211_MANAGEMENT_FRAME_HEADER) +
  1632. sizeof(NET80211_AUTHENTICATION_OPEN_BODY);
  1633. if (FrameSize < ExpectedFrameSize) {
  1634. Status = STATUS_DATA_LENGTH_MISMATCH;
  1635. goto ProcessAuthenticationResponseEnd;
  1636. }
  1637. //
  1638. // The authentication response has a very fixed frame body.
  1639. //
  1640. Body = Packet->Buffer +
  1641. Packet->DataOffset +
  1642. sizeof(NET80211_MANAGEMENT_FRAME_HEADER);
  1643. if (Body->AlgorithmNumber != NET80211_AUTHENTICATION_ALGORITHM_OPEN) {
  1644. RtlDebugPrint("802.11: Unexpected algorithm type %d. Expected %d.\n",
  1645. Body->AlgorithmNumber,
  1646. NET80211_AUTHENTICATION_ALGORITHM_OPEN);
  1647. Status = STATUS_NOT_SUPPORTED;
  1648. goto ProcessAuthenticationResponseEnd;
  1649. }
  1650. if (Body->TransactionSequenceNumber !=
  1651. NET80211_AUTHENTICATION_RESPONSE_SEQUENCE_NUMBER) {
  1652. RtlDebugPrint("802.11: Unexpected authentication transaction "
  1653. "sequence number 0x%04x. Expected 0x%04x.\n",
  1654. Body->TransactionSequenceNumber,
  1655. NET80211_AUTHENTICATION_RESPONSE_SEQUENCE_NUMBER);
  1656. Status = STATUS_UNSUCCESSFUL;
  1657. goto ProcessAuthenticationResponseEnd;
  1658. }
  1659. if (Body->StatusCode != NET80211_STATUS_CODE_SUCCESS) {
  1660. RtlDebugPrint("802.11: Authentication failed with status %d\n",
  1661. Body->StatusCode);
  1662. Status = STATUS_UNSUCCESSFUL;
  1663. goto ProcessAuthenticationResponseEnd;
  1664. }
  1665. Net80211pSetStateUnlocked(Link, Net80211StateAssociating);
  1666. Status = STATUS_SUCCESS;
  1667. ProcessAuthenticationResponseEnd:
  1668. if (!KSUCCESS(Status)) {
  1669. Net80211pSetStateUnlocked(Link, Net80211StateInitialized);
  1670. }
  1671. KeReleaseQueuedLock(Link->Lock);
  1672. return;
  1673. }
  1674. KSTATUS
  1675. Net80211pSendAssociationRequest (
  1676. PNET80211_LINK Link,
  1677. PNET80211_BSS_ENTRY Bss
  1678. )
  1679. /*++
  1680. Routine Description:
  1681. This routine sends an 802.11 management association request frame to the
  1682. to the AP of the given BSS.
  1683. Arguments:
  1684. Link - Supplies a pointer to the 802.11 link over which to send the
  1685. association request.
  1686. Bss - Supplies a pointer to the BSS over which to send the association
  1687. request.
  1688. Return Value:
  1689. Status code.
  1690. --*/
  1691. {
  1692. PUCHAR FrameBody;
  1693. ULONG FrameBodySize;
  1694. ULONG FrameSubtype;
  1695. PUCHAR InformationByte;
  1696. PNET80211_RATE_INFORMATION Rates;
  1697. ULONG SsidLength;
  1698. KSTATUS Status;
  1699. ASSERT(Bss != NULL);
  1700. ASSERT(Bss->Ssid != NULL);
  1701. FrameBody = NULL;
  1702. SsidLength = NET80211_GET_ELEMENT_LENGTH(Bss->Ssid);
  1703. //
  1704. // Determine the size of the probe response packet, which always includes
  1705. // the capabilities, listen interval, SSID, and supported rates.
  1706. //
  1707. ASSERT((SsidLength <= NET80211_MAX_SSID_LENGTH) && (SsidLength != 0));
  1708. FrameBodySize = NET80211_CAPABILITY_SIZE + NET80211_LISTEN_INTERVAL_SIZE;
  1709. FrameBodySize += NET80211_ELEMENT_HEADER_SIZE + SsidLength;
  1710. //
  1711. // Get the supported rates size, including the extended rates if necessary.
  1712. //
  1713. Rates = Link->Properties.SupportedRates;
  1714. FrameBodySize += NET80211_ELEMENT_HEADER_SIZE;
  1715. if (Rates->Count > NET80211_MAX_SUPPORTED_RATES) {
  1716. FrameBodySize += NET80211_ELEMENT_HEADER_SIZE;
  1717. }
  1718. FrameBodySize += Rates->Count;
  1719. //
  1720. // Only include the RSN information if advanced encryption is required.
  1721. //
  1722. if ((Bss->Encryption.Pairwise != NetworkEncryptionNone) &&
  1723. (Bss->Encryption.Pairwise != NetworkEncryptionWep)) {
  1724. FrameBodySize += sizeof(NET80211_DEFAULT_RSN_INFORMATION);
  1725. }
  1726. //
  1727. // Allocate a buffer to hold the assocation request frame body.
  1728. //
  1729. FrameBody = MmAllocatePagedPool(FrameBodySize, NET80211_ALLOCATION_TAG);
  1730. if (FrameBody == NULL) {
  1731. Status = STATUS_INSUFFICIENT_RESOURCES;
  1732. goto SendAssociationRequestEnd;
  1733. }
  1734. //
  1735. // Fill out the frame body. There is a strict order here, so do not
  1736. // rearrage the information elements.
  1737. //
  1738. InformationByte = FrameBody;
  1739. *((PUSHORT)InformationByte) = Link->Properties.Capabilities |
  1740. NET80211_CAPABILITY_FLAG_ESS;
  1741. InformationByte += NET80211_CAPABILITY_SIZE;
  1742. //
  1743. // TODO: Implement a non-zero 802.11 listen interval for power save mode.
  1744. //
  1745. *((PUSHORT)InformationByte) = 0;
  1746. InformationByte += NET80211_LISTEN_INTERVAL_SIZE;
  1747. *InformationByte = NET80211_ELEMENT_SSID;
  1748. InformationByte += 1;
  1749. *InformationByte = SsidLength;
  1750. InformationByte += 1;
  1751. RtlCopyMemory(InformationByte,
  1752. NET80211_GET_ELEMENT_DATA(Bss->Ssid),
  1753. SsidLength);
  1754. InformationByte += SsidLength;
  1755. *InformationByte = NET80211_ELEMENT_SUPPORTED_RATES;
  1756. InformationByte += 1;
  1757. if (Rates->Count <= NET80211_MAX_SUPPORTED_RATES) {
  1758. *InformationByte = Rates->Count;
  1759. InformationByte += 1;
  1760. RtlCopyMemory(InformationByte, Rates->Rate, Rates->Count);
  1761. InformationByte += Rates->Count;
  1762. } else {
  1763. *InformationByte = NET80211_MAX_SUPPORTED_RATES;
  1764. InformationByte += 1;
  1765. RtlCopyMemory(InformationByte,
  1766. Rates->Rate,
  1767. NET80211_MAX_SUPPORTED_RATES);
  1768. InformationByte += NET80211_MAX_SUPPORTED_RATES;
  1769. *InformationByte = NET80211_ELEMENT_EXTENDED_SUPPORTED_RATES;
  1770. InformationByte += 1;
  1771. *InformationByte = Rates->Count - NET80211_MAX_SUPPORTED_RATES;
  1772. InformationByte += 1;
  1773. RtlCopyMemory(InformationByte,
  1774. &(Rates->Rate[NET80211_MAX_SUPPORTED_RATES]),
  1775. Rates->Count - NET80211_MAX_SUPPORTED_RATES);
  1776. InformationByte += Rates->Count - NET80211_MAX_SUPPORTED_RATES;
  1777. }
  1778. //
  1779. // Set the RSN information if advanced encryption is required.
  1780. //
  1781. if ((Bss->Encryption.Pairwise != NetworkEncryptionNone) &&
  1782. (Bss->Encryption.Pairwise != NetworkEncryptionWep)) {
  1783. RtlCopyMemory(InformationByte,
  1784. &Net80211DefaultRsnInformation,
  1785. sizeof(NET80211_DEFAULT_RSN_INFORMATION));
  1786. InformationByte += sizeof(NET80211_DEFAULT_RSN_INFORMATION);
  1787. }
  1788. ASSERT(FrameBodySize == (InformationByte - FrameBody));
  1789. //
  1790. // Send the management frame down to the lower layers.
  1791. //
  1792. FrameSubtype = NET80211_MANAGEMENT_FRAME_SUBTYPE_ASSOCIATION_REQUEST;
  1793. Status = Net80211pSendManagementFrame(Link,
  1794. Bss->State.Bssid,
  1795. Bss->State.Bssid,
  1796. FrameSubtype,
  1797. FrameBody,
  1798. FrameBodySize);
  1799. if (!KSUCCESS(Status)) {
  1800. goto SendAssociationRequestEnd;
  1801. }
  1802. SendAssociationRequestEnd:
  1803. if (FrameBody != NULL) {
  1804. MmFreePagedPool(FrameBody);
  1805. }
  1806. return Status;
  1807. }
  1808. VOID
  1809. Net80211pProcessAssociationResponse (
  1810. PNET80211_LINK Link,
  1811. PNET_PACKET_BUFFER Packet
  1812. )
  1813. /*++
  1814. Routine Description:
  1815. This routine processes an 802.11 management association response frame from
  1816. an access point.
  1817. Arguments:
  1818. Link - Supplies a pointer to the 802.11 link that received the association
  1819. response.
  1820. Packet - Supplies a pointer to the network packet that contains the
  1821. association response frame.
  1822. Return Value:
  1823. None.
  1824. --*/
  1825. {
  1826. USHORT AssociationId;
  1827. PNET80211_BSS_ENTRY Bss;
  1828. USHORT Capabilities;
  1829. PUCHAR ElementBytePointer;
  1830. UCHAR ElementId;
  1831. ULONG ElementLength;
  1832. ULONG ExpectedFrameSize;
  1833. ULONG ExtendedRateCount;
  1834. PUCHAR ExtendedRates;
  1835. ULONG FrameSize;
  1836. USHORT FrameStatus;
  1837. PNET80211_MANAGEMENT_FRAME_HEADER Header;
  1838. BOOL Match;
  1839. ULONG Offset;
  1840. ULONG RateCount;
  1841. PUCHAR Rates;
  1842. KSTATUS Status;
  1843. ULONG TotalRateCount;
  1844. Status = STATUS_SUCCESS;
  1845. if (Link->State != Net80211StateAssociating) {
  1846. return;
  1847. }
  1848. KeAcquireQueuedLock(Link->Lock);
  1849. if (Link->State != Net80211StateAssociating) {
  1850. goto ProcessAssociationResponseEnd;
  1851. }
  1852. ASSERT(Link->ActiveBss != NULL);
  1853. Bss = Link->ActiveBss;
  1854. //
  1855. // Make sure the this frame was sent from the destination.
  1856. //
  1857. Header = Packet->Buffer + Packet->DataOffset;
  1858. Match = RtlCompareMemory(Header->SourceAddress,
  1859. Bss->State.Bssid,
  1860. NET80211_ADDRESS_SIZE);
  1861. if (Match == FALSE) {
  1862. Status = STATUS_INVALID_ADDRESS;
  1863. goto ProcessAssociationResponseEnd;
  1864. }
  1865. //
  1866. // There should at least be capabilities, a status code and the AID.
  1867. //
  1868. FrameSize = Packet->FooterOffset - Packet->DataOffset;
  1869. Offset = sizeof(NET80211_MANAGEMENT_FRAME_HEADER);
  1870. ExpectedFrameSize = Offset +
  1871. NET80211_CAPABILITY_SIZE +
  1872. NET80211_STATUS_CODE_SIZE +
  1873. NET80211_ASSOCIATION_ID_SIZE;
  1874. if (FrameSize < ExpectedFrameSize) {
  1875. Status = STATUS_DATA_LENGTH_MISMATCH;
  1876. goto ProcessAssociationResponseEnd;
  1877. }
  1878. ElementBytePointer = Packet->Buffer + Packet->DataOffset;
  1879. //
  1880. // Save the capabilities.
  1881. //
  1882. Capabilities = *((PUSHORT)&(ElementBytePointer[Offset]));
  1883. Offset += NET80211_CAPABILITY_SIZE;
  1884. //
  1885. // Don't continue unless the association was a success.
  1886. //
  1887. FrameStatus = *((PUSHORT)(&(ElementBytePointer[Offset])));
  1888. if (FrameStatus != NET80211_STATUS_CODE_SUCCESS) {
  1889. RtlDebugPrint("802.11: Association response failed with status "
  1890. "0x%04x.\n",
  1891. FrameStatus);
  1892. Status = STATUS_UNSUCCESSFUL;
  1893. goto ProcessAssociationResponseEnd;
  1894. }
  1895. Offset += NET80211_STATUS_CODE_SIZE;
  1896. //
  1897. // Save the association ID.
  1898. //
  1899. AssociationId = *((PUSHORT)&(ElementBytePointer[Offset]));
  1900. AssociationId &= NET80211_ASSOCIATION_ID_MASK;
  1901. Offset += NET80211_ASSOCIATION_ID_SIZE;
  1902. //
  1903. // Now look at the supplied elements.
  1904. //
  1905. Rates = NULL;
  1906. RateCount = 0;
  1907. ExtendedRates = NULL;
  1908. ExtendedRateCount = 0;
  1909. while (Offset < FrameSize) {
  1910. ElementId = ElementBytePointer[Offset];
  1911. Offset += 1;
  1912. if (Offset >= FrameSize) {
  1913. Status = STATUS_DATA_LENGTH_MISMATCH;
  1914. goto ProcessAssociationResponseEnd;
  1915. }
  1916. ElementLength = ElementBytePointer[Offset];
  1917. Offset += 1;
  1918. if ((Offset + ElementLength) > FrameSize) {
  1919. Status = STATUS_DATA_LENGTH_MISMATCH;
  1920. goto ProcessAssociationResponseEnd;
  1921. }
  1922. switch (ElementId) {
  1923. case NET80211_ELEMENT_SUPPORTED_RATES:
  1924. if (ElementLength == 0) {
  1925. Status = STATUS_INVALID_CONFIGURATION;
  1926. goto ProcessAssociationResponseEnd;
  1927. }
  1928. Rates = ElementBytePointer + Offset;
  1929. RateCount = ElementLength;
  1930. break;
  1931. case NET80211_ELEMENT_EXTENDED_SUPPORTED_RATES:
  1932. if (ElementLength == 0) {
  1933. Status = STATUS_INVALID_CONFIGURATION;
  1934. goto ProcessAssociationResponseEnd;
  1935. }
  1936. ExtendedRates = ElementBytePointer + Offset;
  1937. ExtendedRateCount = ElementLength;
  1938. break;
  1939. default:
  1940. break;
  1941. }
  1942. Offset += ElementLength;
  1943. }
  1944. //
  1945. // If the capabilities or rates have changed from the probe response or
  1946. // beacon, do not proceed with the association. The AP has changed since
  1947. // the association process began. Deauthenticate instead.
  1948. //
  1949. if (Capabilities != Bss->State.Capabilities) {
  1950. Status = STATUS_OPERATION_CANCELLED;
  1951. goto ProcessAssociationResponseEnd;
  1952. }
  1953. TotalRateCount = RateCount + ExtendedRateCount;
  1954. if (TotalRateCount != Bss->State.Rates.Count) {
  1955. Status = STATUS_OPERATION_CANCELLED;
  1956. goto ProcessAssociationResponseEnd;
  1957. }
  1958. //
  1959. // Copy the current rates into the BSS entry.
  1960. //
  1961. RtlCopyMemory(Bss->State.Rates.Rate, Rates, RateCount);
  1962. RtlCopyMemory(Bss->State.Rates.Rate + RateCount,
  1963. ExtendedRates,
  1964. ExtendedRateCount);
  1965. Status = Net80211pValidateRates(Link, Bss);
  1966. if (!KSUCCESS(Status)) {
  1967. goto ProcessAssociationResponseEnd;
  1968. }
  1969. Bss->State.AssociationId = AssociationId;
  1970. Net80211pSetStateUnlocked(Link, Net80211StateAssociated);
  1971. ProcessAssociationResponseEnd:
  1972. if (!KSUCCESS(Status)) {
  1973. Net80211pSetStateUnlocked(Link, Net80211StateInitialized);
  1974. }
  1975. KeReleaseQueuedLock(Link->Lock);
  1976. return;
  1977. }
  1978. KSTATUS
  1979. Net80211pSendManagementFrame (
  1980. PNET80211_LINK Link,
  1981. PUCHAR DestinationAddress,
  1982. PUCHAR Bssid,
  1983. ULONG FrameSubtype,
  1984. PVOID FrameBody,
  1985. ULONG FrameBodySize
  1986. )
  1987. /*++
  1988. Routine Description:
  1989. This routine sends an 802.11 management frame with the given data and
  1990. subtype out over the link.
  1991. Arguments:
  1992. Link - Supplies a pointer to the link on which to send the management frame.
  1993. DestinationAddress - Supplies a pointer to an optional destination address
  1994. for the management frame. Supply NULL to indicate the broadcast address.
  1995. Bssid - Supplies a pointer to an optional BSSID for the management frame.
  1996. Supply NULL to indicate the wildcard BSSID.
  1997. FrameSubtype - Supplies the management frame subtype for the packet.
  1998. FrameBody - Supplies a pointer to the body data to be sent within the frame.
  1999. FrameBodySize - Supplies the size of the body to send in the frame.
  2000. Return Value:
  2001. Status code.
  2002. --*/
  2003. {
  2004. PVOID DeviceContext;
  2005. ULONG Flags;
  2006. PNET80211_MANAGEMENT_FRAME_HEADER Header;
  2007. PNET_PACKET_BUFFER Packet;
  2008. NET_PACKET_LIST PacketList;
  2009. KSTATUS Status;
  2010. NET_INITIALIZE_PACKET_LIST(&PacketList);
  2011. //
  2012. // Allocate a network packet to send down to the lower layers.
  2013. //
  2014. Flags = NET_ALLOCATE_BUFFER_FLAG_ADD_DEVICE_LINK_HEADERS |
  2015. NET_ALLOCATE_BUFFER_FLAG_ADD_DEVICE_LINK_FOOTERS;
  2016. Packet = NULL;
  2017. Status = NetAllocateBuffer(sizeof(NET80211_MANAGEMENT_FRAME_HEADER),
  2018. FrameBodySize,
  2019. 0,
  2020. Link->NetworkLink,
  2021. Flags,
  2022. &Packet);
  2023. if (!KSUCCESS(Status)) {
  2024. goto SendManagementFrameEnd;
  2025. }
  2026. //
  2027. // Copy the data to the newly allocated network packet.
  2028. //
  2029. RtlCopyMemory(Packet->Buffer + Packet->DataOffset,
  2030. FrameBody,
  2031. FrameBodySize);
  2032. //
  2033. // Move the offset backwards and fill in the 802.11 management frame header.
  2034. //
  2035. Packet->DataOffset -= sizeof(NET80211_MANAGEMENT_FRAME_HEADER);
  2036. Header = Packet->Buffer + Packet->DataOffset;
  2037. Header->FrameControl = (NET80211_FRAME_CONTROL_PROTOCOL_VERSION <<
  2038. NET80211_FRAME_CONTROL_PROTOCOL_VERSION_SHIFT) |
  2039. (NET80211_FRAME_TYPE_MANAGEMENT <<
  2040. NET80211_FRAME_CONTROL_TYPE_SHIFT) |
  2041. (FrameSubtype <<
  2042. NET80211_FRAME_CONTROL_SUBTYPE_SHIFT);
  2043. //
  2044. // The hardware handles the duration.
  2045. //
  2046. Header->Duration = 0;
  2047. //
  2048. // Initialize the header's addresses. If the destination or BSSID are NULL,
  2049. // the the broadcast address is to be set.
  2050. //
  2051. if (DestinationAddress != NULL) {
  2052. RtlCopyMemory(Header->DestinationAddress,
  2053. DestinationAddress,
  2054. NET80211_ADDRESS_SIZE);
  2055. } else {
  2056. RtlSetMemory(Header->DestinationAddress, 0xFF, NET80211_ADDRESS_SIZE);
  2057. }
  2058. //
  2059. // The source address is always the local link's physical address (i.e. the
  2060. // MAC address).
  2061. //
  2062. RtlCopyMemory(Header->SourceAddress,
  2063. Link->Properties.PhysicalAddress.Address,
  2064. NET80211_ADDRESS_SIZE);
  2065. if (Bssid != NULL) {
  2066. RtlCopyMemory(Header->Bssid, Bssid, NET80211_ADDRESS_SIZE);
  2067. } else {
  2068. RtlSetMemory(Header->Bssid, 0xFF, NET80211_ADDRESS_SIZE);
  2069. }
  2070. //
  2071. // The header gets the next sequence number for the link. This is only 1
  2072. // fragment, so that remains 0.
  2073. //
  2074. Header->SequenceControl = Net80211pGetSequenceNumber(Link);
  2075. Header->SequenceControl <<= NET80211_SEQUENCE_CONTROL_SEQUENCE_NUMBER_SHIFT;
  2076. //
  2077. // Send the packet off.
  2078. //
  2079. NET_ADD_PACKET_TO_LIST(Packet, &PacketList);
  2080. DeviceContext = Link->Properties.DeviceContext;
  2081. Status = Link->Properties.Interface.Send(DeviceContext, &PacketList);
  2082. if (!KSUCCESS(Status)) {
  2083. goto SendManagementFrameEnd;
  2084. }
  2085. SendManagementFrameEnd:
  2086. if (!KSUCCESS(Status)) {
  2087. NetDestroyBufferList(&PacketList);
  2088. }
  2089. return Status;
  2090. }
  2091. KSTATUS
  2092. Net80211pQueueStateTransitionTimer (
  2093. PNET80211_LINK Link,
  2094. ULONGLONG Timeout
  2095. )
  2096. /*++
  2097. Routine Description:
  2098. This routine queues the given network link's state transition timer.
  2099. Arguments:
  2100. Link - Supplies a pointer to a 802.11 link.
  2101. Timeout - Supplies the desired timeout in microseconds.
  2102. Return Value:
  2103. Status code.
  2104. --*/
  2105. {
  2106. ULONGLONG DueTime;
  2107. KSTATUS Status;
  2108. ASSERT(KeIsQueuedLockHeld(Link->Lock) != FALSE);
  2109. DueTime = KeGetRecentTimeCounter();
  2110. DueTime += KeConvertMicrosecondsToTimeTicks(Timeout);
  2111. Status = KeQueueTimer(Link->StateTimer,
  2112. TimerQueueSoft,
  2113. DueTime,
  2114. 0,
  2115. 0,
  2116. Link->TimeoutDpc);
  2117. if (KSUCCESS(Status)) {
  2118. Link->Flags |= NET80211_LINK_FLAG_TIMER_QUEUED;
  2119. }
  2120. return Status;
  2121. }
  2122. VOID
  2123. Net80211pCancelStateTransitionTimer (
  2124. PNET80211_LINK Link
  2125. )
  2126. /*++
  2127. Routine Description:
  2128. This routine cancels the given link's state transition timer if it is
  2129. queued.
  2130. Arguments:
  2131. Link - Supplies a pointer to the 802.11 link whose state transition timer
  2132. shall be canceled.
  2133. Return Value:
  2134. None.
  2135. --*/
  2136. {
  2137. KSTATUS Status;
  2138. ASSERT(KeIsQueuedLockHeld(Link->Lock) != FALSE);
  2139. //
  2140. // Cancel the timer if it is queued. Also make sure the DPC is flushed if
  2141. // the timer just expired. The timer may be requeued at any time and a DPC
  2142. // cannot be queued twice.
  2143. //
  2144. if ((Link->Flags & NET80211_LINK_FLAG_TIMER_QUEUED) != 0) {
  2145. Status = KeCancelTimer(Link->StateTimer);
  2146. if (!KSUCCESS(Status)) {
  2147. KeFlushDpc(Link->TimeoutDpc);
  2148. }
  2149. Link->Flags &= ~NET80211_LINK_FLAG_TIMER_QUEUED;
  2150. }
  2151. return;
  2152. }
  2153. KSTATUS
  2154. Net80211pValidateRates (
  2155. PNET80211_LINK Link,
  2156. PNET80211_BSS_ENTRY Bss
  2157. )
  2158. /*++
  2159. Routine Description:
  2160. This routine validates that the link and BSS share the same basic rates and
  2161. detects the maximum mode for a future connection, storing the result in the
  2162. BSS entry.
  2163. Arguments:
  2164. Link - Supplies a pointer to the 802.11 link for which to validate the BSS
  2165. entry's rates.
  2166. Bss - Supplies a pointer to a BSS entry.
  2167. Return Value:
  2168. Status code.
  2169. --*/
  2170. {
  2171. ULONG BssIndex;
  2172. UCHAR BssRate;
  2173. PNET80211_RATE_INFORMATION BssRates;
  2174. UCHAR BssRateValue;
  2175. ULONGLONG LinkSpeed;
  2176. ULONG LocalIndex;
  2177. UCHAR LocalRate;
  2178. PNET80211_RATE_INFORMATION LocalRates;
  2179. UCHAR MaxRate;
  2180. KSTATUS Status;
  2181. BssRates = &(Bss->State.Rates);
  2182. LocalRates = Link->Properties.SupportedRates;
  2183. //
  2184. // Make sure the basic rates are supported. Unfortunately, there is no
  2185. // guarantee about the ordering of the rates. There aren't that many so do
  2186. // not bother sorting.
  2187. //
  2188. MaxRate = 0;
  2189. for (BssIndex = 0; BssIndex < BssRates->Count; BssIndex += 1) {
  2190. BssRate = BssRates->Rate[BssIndex];
  2191. BssRateValue = BssRate & NET80211_RATE_VALUE_MASK;
  2192. if ((BssRate & NET80211_RATE_BASIC) != 0) {
  2193. if (BssRateValue == NET80211_MEMBERSHIP_SELECTOR_HT_PHY) {
  2194. continue;
  2195. }
  2196. } else if (BssRateValue <= MaxRate) {
  2197. continue;
  2198. }
  2199. //
  2200. // Attempt to find the rate in the local supported rates.
  2201. //
  2202. for (LocalIndex = 0; LocalIndex < LocalRates->Count; LocalIndex += 1) {
  2203. LocalRate = LocalRates->Rate[LocalIndex] & NET80211_RATE_VALUE_MASK;
  2204. if (LocalRate == BssRateValue) {
  2205. break;
  2206. }
  2207. }
  2208. //
  2209. // If this is a basic rate and it is not supported locally, then
  2210. // connecting to this BSS is not allowed.
  2211. //
  2212. if (LocalIndex == LocalRates->Count) {
  2213. if ((BssRate & NET80211_RATE_BASIC) != 0) {
  2214. Status = STATUS_NOT_SUPPORTED;
  2215. goto ValidateRatesEnd;
  2216. }
  2217. continue;
  2218. }
  2219. if (BssRateValue > MaxRate) {
  2220. MaxRate = BssRateValue;
  2221. }
  2222. }
  2223. //
  2224. // If no rate could be agreed upon, then fail to connect to the BSS.
  2225. //
  2226. if (MaxRate == 0) {
  2227. Status = STATUS_NOT_SUPPORTED;
  2228. goto ValidateRatesEnd;
  2229. }
  2230. //
  2231. // Fill in the connection mode based on the maximum supported rate.
  2232. //
  2233. Bss->State.MaxRate = MaxRate;
  2234. LinkSpeed = MaxRate * NET80211_RATE_UNIT;
  2235. if (LinkSpeed <= NET80211_MODE_B_MAX_RATE) {
  2236. Bss->State.Mode = Net80211ModeB;
  2237. } else if (LinkSpeed <= NET80211_MODE_G_MAX_RATE) {
  2238. Bss->State.Mode = Net80211ModeG;
  2239. } else {
  2240. Status = STATUS_NOT_SUPPORTED;
  2241. goto ValidateRatesEnd;
  2242. }
  2243. Status = STATUS_SUCCESS;
  2244. ValidateRatesEnd:
  2245. return Status;
  2246. }
  2247. KSTATUS
  2248. Net80211pParseRsnElement (
  2249. PUCHAR Rsn,
  2250. PNET80211_ENCRYPTION Encryption
  2251. )
  2252. /*++
  2253. Routine Description:
  2254. This routine parses the RSN information element in order to detect which
  2255. encryption methods are supported by the BSS to which it belongs.
  2256. Arguments:
  2257. Rsn - Supplies a pointer to the RSN element, the first byte of which must
  2258. be the element ID.
  2259. Encryption - Supplies a pointer to an 802.11 encryption structure that
  2260. receives the parsed data from the RSN element.
  2261. Return Value:
  2262. Status code.
  2263. --*/
  2264. {
  2265. NETWORK_ENCRYPTION_TYPE GroupEncryption;
  2266. ULONG Index;
  2267. ULONG Offset;
  2268. NETWORK_ENCRYPTION_TYPE PairwiseEncryption;
  2269. USHORT PmkidCount;
  2270. BOOL PskSupported;
  2271. ULONG RsnLength;
  2272. KSTATUS Status;
  2273. ULONG Suite;
  2274. USHORT SuiteCount;
  2275. PULONG Suites;
  2276. USHORT Version;
  2277. ASSERT(NET80211_GET_ELEMENT_ID(Rsn) == NET80211_ELEMENT_RSN);
  2278. Status = STATUS_SUCCESS;
  2279. Offset = NET80211_ELEMENT_HEADER_SIZE;
  2280. PairwiseEncryption = NetworkEncryptionNone;
  2281. GroupEncryption = NetworkEncryptionNone;
  2282. RsnLength = NET80211_GET_ELEMENT_LENGTH(Rsn);
  2283. //
  2284. // The version field is the only non-optional field.
  2285. //
  2286. if ((Offset + sizeof(USHORT)) > RsnLength) {
  2287. Status = STATUS_DATA_LENGTH_MISMATCH;
  2288. goto ParseRsnElementEnd;
  2289. }
  2290. Version = *((PUSHORT)&(Rsn[Offset]));
  2291. Offset += sizeof(USHORT);
  2292. if (Version != NET80211_RSN_VERSION) {
  2293. RtlDebugPrint("802.11: Unexpected RSN version %d\n", Version);
  2294. Status = STATUS_VERSION_MISMATCH;
  2295. goto ParseRsnElementEnd;
  2296. }
  2297. //
  2298. // Get the optional group suite.
  2299. //
  2300. if ((Offset + sizeof(ULONG)) > RsnLength) {
  2301. goto ParseRsnElementEnd;
  2302. }
  2303. Suite = NETWORK_TO_CPU32(*((PULONG)&(Rsn[Offset])));
  2304. Offset += sizeof(ULONG);
  2305. switch (Suite) {
  2306. case NET80211_CIPHER_SUITE_WEP_40:
  2307. case NET80211_CIPHER_SUITE_WEP_104:
  2308. GroupEncryption = NetworkEncryptionWep;
  2309. break;
  2310. case NET80211_CIPHER_SUITE_TKIP:
  2311. GroupEncryption = NetworkEncryptionWpaEap;
  2312. break;
  2313. case NET80211_CIPHER_SUITE_CCMP:
  2314. GroupEncryption = NetworkEncryptionWpa2Eap;
  2315. break;
  2316. case NET80211_CIPHER_SUITE_GROUP_NOT_ALLOWED:
  2317. GroupEncryption = NetworkEncryptionNone;
  2318. break;
  2319. default:
  2320. GroupEncryption = NetworkEncryptionInvalid;
  2321. RtlDebugPrint("802.11: Group cipher suite not supported 0x%08x\n",
  2322. Suite);
  2323. break;
  2324. }
  2325. if (GroupEncryption == NetworkEncryptionInvalid) {
  2326. Status = STATUS_NOT_SUPPORTED;
  2327. goto ParseRsnElementEnd;
  2328. }
  2329. //
  2330. // Gather the pairwise suites.
  2331. //
  2332. if ((Offset + sizeof(USHORT)) > RsnLength) {
  2333. goto ParseRsnElementEnd;
  2334. }
  2335. SuiteCount = *((PUSHORT)&(Rsn[Offset]));
  2336. Offset += sizeof(USHORT);
  2337. if ((Offset + (SuiteCount * sizeof(ULONG))) > RsnLength) {
  2338. Status = STATUS_DATA_LENGTH_MISMATCH;
  2339. goto ParseRsnElementEnd;
  2340. }
  2341. Suites = (PULONG)&(Rsn[Offset]);
  2342. Offset += SuiteCount * sizeof(ULONG);
  2343. for (Index = 0; Index < SuiteCount; Index += 1) {
  2344. Suite = NETWORK_TO_CPU32(Suites[Index]);
  2345. //
  2346. // As soon as CCMP is found, prefer that. None of the others are
  2347. // supported anyway.
  2348. //
  2349. if (Suite == NET80211_CIPHER_SUITE_CCMP) {
  2350. PairwiseEncryption = NetworkEncryptionWpa2Eap;
  2351. break;
  2352. }
  2353. switch (Suite) {
  2354. case NET80211_CIPHER_SUITE_WEP_40:
  2355. case NET80211_CIPHER_SUITE_WEP_104:
  2356. PairwiseEncryption = NetworkEncryptionWep;
  2357. break;
  2358. case NET80211_CIPHER_SUITE_TKIP:
  2359. PairwiseEncryption = NetworkEncryptionWpaEap;
  2360. break;
  2361. case NET80211_CIPHER_SUITE_USE_GROUP_CIPHER:
  2362. PairwiseEncryption = GroupEncryption;
  2363. Encryption->Flags |= NET80211_ENCRYPTION_FLAG_USE_GROUP_CIPHER;
  2364. break;
  2365. default:
  2366. PairwiseEncryption = NetworkEncryptionInvalid;
  2367. RtlDebugPrint("802.11: Pairwise cipher suite not supported "
  2368. "0x%08x\n",
  2369. Suite);
  2370. break;
  2371. }
  2372. }
  2373. if (PairwiseEncryption == NetworkEncryptionInvalid) {
  2374. Status = STATUS_NOT_SUPPORTED;
  2375. goto ParseRsnElementEnd;
  2376. }
  2377. //
  2378. // Upgrade the group and pairwise encryption methods from EAP to PSK if
  2379. // PSK is present.
  2380. //
  2381. if ((Offset + sizeof(USHORT)) > RsnLength) {
  2382. goto ParseRsnElementEnd;
  2383. }
  2384. SuiteCount = *((PUSHORT)&(Rsn[Offset]));
  2385. Offset += sizeof(USHORT);
  2386. if ((Offset + (SuiteCount * sizeof(ULONG))) > RsnLength) {
  2387. Status = STATUS_DATA_LENGTH_MISMATCH;
  2388. goto ParseRsnElementEnd;
  2389. }
  2390. Suites = (PULONG)&(Rsn[Offset]);
  2391. Offset += SuiteCount * sizeof(ULONG);
  2392. PskSupported = FALSE;
  2393. for (Index = 0; Index < SuiteCount; Index += 1) {
  2394. Suite = NETWORK_TO_CPU32(Suites[Index]);
  2395. if ((Suite == NET80211_AKM_SUITE_PSK) ||
  2396. (Suite == NET80211_AKM_SUITE_PSK_SHA256)) {
  2397. PskSupported = TRUE;
  2398. break;
  2399. }
  2400. }
  2401. if (PskSupported != FALSE) {
  2402. if (GroupEncryption == NetworkEncryptionWpaEap) {
  2403. GroupEncryption = NetworkEncryptionWpaPsk;
  2404. } else if (GroupEncryption == NetworkEncryptionWpa2Eap) {
  2405. GroupEncryption = NetworkEncryptionWpa2Psk;
  2406. }
  2407. if (PairwiseEncryption == NetworkEncryptionWpaEap) {
  2408. PairwiseEncryption = NetworkEncryptionWpaPsk;
  2409. } else if (PairwiseEncryption == NetworkEncryptionWpa2Eap) {
  2410. PairwiseEncryption = NetworkEncryptionWpa2Psk;
  2411. }
  2412. }
  2413. //
  2414. // Skip the RSN capabilities.
  2415. //
  2416. if ((Offset + sizeof(USHORT)) > RsnLength) {
  2417. goto ParseRsnElementEnd;
  2418. }
  2419. Offset += sizeof(USHORT);
  2420. //
  2421. // Skip the PMKIDs.
  2422. //
  2423. if ((Offset + sizeof(USHORT)) > RsnLength) {
  2424. goto ParseRsnElementEnd;
  2425. }
  2426. PmkidCount = *((PUSHORT)&(Rsn[Offset]));
  2427. Offset += sizeof(USHORT);
  2428. if ((Offset + (PmkidCount * NET80211_RSN_PMKID_LENGTH)) > RsnLength) {
  2429. Status = STATUS_DATA_LENGTH_MISMATCH;
  2430. goto ParseRsnElementEnd;
  2431. }
  2432. Offset += PmkidCount * NET80211_RSN_PMKID_LENGTH;
  2433. //
  2434. // Skip the group management suite.
  2435. //
  2436. if ((Offset + sizeof(ULONG)) > RsnLength) {
  2437. goto ParseRsnElementEnd;
  2438. }
  2439. Suite = *((PULONG)&(Rsn[Offset]));
  2440. Offset += sizeof(ULONG);
  2441. ParseRsnElementEnd:
  2442. Encryption->Pairwise = PairwiseEncryption;
  2443. Encryption->Group = GroupEncryption;
  2444. return Status;
  2445. }
  2446. VOID
  2447. Net80211pUpdateBssCache (
  2448. PNET80211_LINK Link,
  2449. PNET80211_PROBE_RESPONSE Response
  2450. )
  2451. /*++
  2452. Routine Description:
  2453. This routine updates the given BSS cache based on the data found in a
  2454. beacon or probe response packet.
  2455. Arguments:
  2456. Link - Supplies a pointer to the 802.11 link that received the packet.
  2457. Response - Supplies a pointer to a parsed representation of a beacon or
  2458. probe response packet.
  2459. Return Value:
  2460. None.
  2461. --*/
  2462. {
  2463. PNET80211_BSS_ENTRY Bss;
  2464. ULONG Channel;
  2465. BOOL DestroyBss;
  2466. BOOL LinkDown;
  2467. BOOL Match;
  2468. PUCHAR NewRsn;
  2469. ULONG NewRsnLength;
  2470. ULONG NewSsidLength;
  2471. ULONG Offset;
  2472. PUCHAR OldRsn;
  2473. ULONG OldRsnLength;
  2474. ULONG OldSsidLength;
  2475. PUCHAR RatesArray;
  2476. KSTATUS Status;
  2477. ULONG TotalRateCount;
  2478. TotalRateCount = NET80211_GET_ELEMENT_LENGTH(Response->Rates);
  2479. if (Response->ExtendedRates != NULL) {
  2480. TotalRateCount += NET80211_GET_ELEMENT_LENGTH(Response->ExtendedRates);
  2481. }
  2482. //
  2483. // First look for an existing BSS entry based on the BSSID. But if no
  2484. // matching BSS entry is found, then create a new one and insert it into
  2485. // the list.
  2486. //
  2487. KeAcquireQueuedLock(Link->Lock);
  2488. Bss = Net80211pLookupBssEntry(Link, Response->Bssid);
  2489. if (Bss == NULL) {
  2490. Bss = Net80211pCreateBssEntry(Response->Bssid);
  2491. if (Bss == NULL) {
  2492. Status = STATUS_INSUFFICIENT_RESOURCES;
  2493. goto UpdateBssCacheEnd;
  2494. }
  2495. INSERT_BEFORE(&(Bss->ListEntry), &(Link->BssList));
  2496. }
  2497. //
  2498. // Gather some locals from the response elements.
  2499. //
  2500. Channel = *NET80211_GET_ELEMENT_DATA(Response->Channel);
  2501. //
  2502. // If this is an update for the active BSS, then any changes will cause
  2503. // the link to go down.
  2504. //
  2505. if (Link->ActiveBss == Bss) {
  2506. LinkDown = FALSE;
  2507. NewSsidLength = NET80211_GET_ELEMENT_LENGTH(Response->Ssid);
  2508. OldSsidLength = NET80211_GET_ELEMENT_LENGTH(Bss->Ssid);
  2509. NewRsnLength = 0;
  2510. NewRsn = Response->Rsn;
  2511. if (NewRsn != NULL) {
  2512. NewRsnLength = NET80211_ELEMENT_HEADER_SIZE +
  2513. NET80211_GET_ELEMENT_LENGTH(Response->Rsn);
  2514. }
  2515. OldRsnLength = 0;
  2516. OldRsn = Bss->Encryption.ApRsn;
  2517. if (OldRsn != NULL) {
  2518. OldRsnLength = NET80211_ELEMENT_HEADER_SIZE +
  2519. NET80211_GET_ELEMENT_LENGTH(Bss->Encryption.ApRsn);
  2520. }
  2521. ASSERT(NewSsidLength <= NET80211_MAX_SSID_LENGTH);
  2522. if ((Bss->State.BeaconInterval != Response->BeaconInterval) ||
  2523. (Bss->State.Capabilities != Response->Capabilities) ||
  2524. (Bss->State.Channel != Channel) ||
  2525. (Bss->State.Rates.Count != TotalRateCount) ||
  2526. (OldSsidLength != NewSsidLength) ||
  2527. (OldRsnLength != NewRsnLength)) {
  2528. LinkDown = TRUE;
  2529. }
  2530. if (LinkDown == FALSE) {
  2531. Match = RtlCompareMemory(NET80211_GET_ELEMENT_DATA(Bss->Ssid),
  2532. NET80211_GET_ELEMENT_DATA(Response->Ssid),
  2533. NewSsidLength);
  2534. if (Match == FALSE) {
  2535. LinkDown = TRUE;
  2536. }
  2537. }
  2538. if (LinkDown == FALSE) {
  2539. Match = RtlCompareMemory(OldRsn, NewRsn, NewRsnLength);
  2540. if (Match == FALSE) {
  2541. LinkDown = TRUE;
  2542. }
  2543. }
  2544. if (LinkDown != FALSE) {
  2545. Net80211pSetStateUnlocked(Link, Net80211StateInitialized);
  2546. }
  2547. }
  2548. //
  2549. // Update the BSS entry with the latest information from the AP.
  2550. //
  2551. Bss->State.BeaconInterval = Response->BeaconInterval;
  2552. Bss->State.Capabilities = Response->Capabilities;
  2553. Bss->State.Channel = Channel;
  2554. Bss->State.Timestamp = Response->Timestamp;
  2555. //
  2556. // Allocate a new elements buffer with the newest data. This will include
  2557. // resetting the SSID and AP's RSN pointers.
  2558. //
  2559. if (Response->ElementsSize != 0) {
  2560. if (Bss->Elements != NULL) {
  2561. MmFreePagedPool(Bss->Elements);
  2562. Bss->ElementsSize = 0;
  2563. }
  2564. Bss->Ssid = NULL;
  2565. Bss->Encryption.ApRsn = NULL;
  2566. Bss->Elements = MmAllocatePagedPool(Response->ElementsSize,
  2567. NET80211_ALLOCATION_TAG);
  2568. if (Bss->Elements == NULL) {
  2569. Status = STATUS_INSUFFICIENT_RESOURCES;
  2570. goto UpdateBssCacheEnd;
  2571. }
  2572. Bss->ElementsSize = Response->ElementsSize;
  2573. RtlCopyMemory(Bss->Elements, Response->Elements, Bss->ElementsSize);
  2574. Offset = Response->Ssid - Response->Elements;
  2575. Bss->Ssid = Bss->Elements + Offset;
  2576. if (Response->Rsn != NULL) {
  2577. Offset = Response->Rsn - Response->Elements;
  2578. Bss->Encryption.ApRsn = Bss->Elements + Offset;
  2579. //
  2580. // Parse the RSN information to determine the encryption algorithms
  2581. // in use by the BSS.
  2582. //
  2583. Status = Net80211pParseRsnElement(Bss->Encryption.ApRsn,
  2584. &(Bss->Encryption));
  2585. if (!KSUCCESS(Status)) {
  2586. goto UpdateBssCacheEnd;
  2587. }
  2588. }
  2589. }
  2590. //
  2591. // Gather the rates from the response into one array.
  2592. //
  2593. ASSERT(TotalRateCount != 0);
  2594. RatesArray = Bss->State.Rates.Rate;
  2595. if (Bss->State.Rates.Count < TotalRateCount) {
  2596. if (RatesArray != NULL) {
  2597. MmFreePagedPool(RatesArray);
  2598. Bss->State.Rates.Rate = NULL;
  2599. }
  2600. RatesArray = MmAllocatePagedPool(TotalRateCount * sizeof(UCHAR),
  2601. NET80211_ALLOCATION_TAG);
  2602. if (RatesArray == NULL) {
  2603. Status = STATUS_INSUFFICIENT_RESOURCES;
  2604. goto UpdateBssCacheEnd;
  2605. }
  2606. Bss->State.Rates.Rate = RatesArray;
  2607. }
  2608. Bss->State.Rates.Count = TotalRateCount;
  2609. RtlCopyMemory(RatesArray,
  2610. NET80211_GET_ELEMENT_DATA(Response->Rates),
  2611. NET80211_GET_ELEMENT_LENGTH(Response->Rates));
  2612. if (Response->ExtendedRates != NULL) {
  2613. RtlCopyMemory(RatesArray + NET80211_GET_ELEMENT_LENGTH(Response->Rates),
  2614. NET80211_GET_ELEMENT_DATA(Response->ExtendedRates),
  2615. NET80211_GET_ELEMENT_LENGTH(Response->ExtendedRates));
  2616. }
  2617. //
  2618. // Record that this BSS needs to encrypt/decrypt data.
  2619. //
  2620. if (Bss->Encryption.Pairwise != NetworkEncryptionNone) {
  2621. Bss->Flags |= NET80211_BSS_FLAG_ENCRYPT_DATA;
  2622. }
  2623. //
  2624. // For now, the station always advertises the same RSN information. Just
  2625. // point at the global.
  2626. //
  2627. Bss->Encryption.StationRsn = (PUCHAR)&Net80211DefaultRsnInformation;
  2628. Bss->LastUpdated = KeGetRecentTimeCounter();
  2629. Status = STATUS_SUCCESS;
  2630. UpdateBssCacheEnd:
  2631. DestroyBss = FALSE;
  2632. if (!KSUCCESS(Status)) {
  2633. if (Bss != NULL) {
  2634. LIST_REMOVE(&(Bss->ListEntry));
  2635. DestroyBss = TRUE;
  2636. }
  2637. }
  2638. KeReleaseQueuedLock(Link->Lock);
  2639. if (DestroyBss != FALSE) {
  2640. Net80211pBssEntryReleaseReference(Bss);
  2641. }
  2642. return;
  2643. }
  2644. VOID
  2645. Net80211pTrimBssCache (
  2646. PNET80211_LINK Link
  2647. )
  2648. /*++
  2649. Routine Description:
  2650. This routine removes the expired BSS entries from the given link's list.
  2651. Arguments:
  2652. Link - Supplies a pointer to the 802.11 link whose old BSS entries are to
  2653. be removed.
  2654. Return Value:
  2655. None.
  2656. --*/
  2657. {
  2658. PNET80211_BSS_ENTRY Bss;
  2659. PLIST_ENTRY CurrentEntry;
  2660. ULONGLONG CurrentTime;
  2661. ULONGLONG ElapsedTime;
  2662. LIST_ENTRY LocalList;
  2663. ULONGLONG Timeout;
  2664. INITIALIZE_LIST_HEAD(&LocalList);
  2665. CurrentTime = KeGetRecentTimeCounter();
  2666. Timeout = KeConvertMicrosecondsToTimeTicks(NET80211_BSS_ENTRY_TIMEOUT);
  2667. //
  2668. // Go through the list once and find all the expired entries, moving them
  2669. // to a local list.
  2670. //
  2671. KeAcquireQueuedLock(Link->Lock);
  2672. CurrentEntry = Link->BssList.Next;
  2673. while (CurrentEntry != &(Link->BssList)) {
  2674. Bss = LIST_VALUE(CurrentEntry, NET80211_BSS_ENTRY, ListEntry);
  2675. CurrentEntry = CurrentEntry->Next;
  2676. //
  2677. // Don't trim the active BSS.
  2678. //
  2679. if (Bss == Link->ActiveBss) {
  2680. continue;
  2681. }
  2682. ElapsedTime = CurrentTime - Bss->LastUpdated;
  2683. if (ElapsedTime > Timeout) {
  2684. LIST_REMOVE(&(Bss->ListEntry));
  2685. INSERT_BEFORE(&(Bss->ListEntry), &LocalList);
  2686. }
  2687. }
  2688. KeReleaseQueuedLock(Link->Lock);
  2689. //
  2690. // Run through the local list and release a reference on each.
  2691. //
  2692. while (LIST_EMPTY(&LocalList) == FALSE) {
  2693. Bss = LIST_VALUE(LocalList.Next, NET80211_BSS_ENTRY, ListEntry);
  2694. LIST_REMOVE(&(Bss->ListEntry));
  2695. Net80211pBssEntryReleaseReference(Bss);
  2696. }
  2697. return;
  2698. }
  2699. PNET80211_BSS_ENTRY
  2700. Net80211pCopyBssEntry (
  2701. PNET80211_BSS_ENTRY Bss
  2702. )
  2703. /*++
  2704. Routine Description:
  2705. This routine creates a copy of the given BSS entry with the encryption keys
  2706. removed.
  2707. Arguments:
  2708. Bss - Supplies a pointer to the BSS from a prior connection that the link
  2709. is now trying to reconnect with.
  2710. Return Value:
  2711. Status code.
  2712. --*/
  2713. {
  2714. PNET80211_BSS_ENTRY BssCopy;
  2715. ULONG Offset;
  2716. ULONG RatesSize;
  2717. KSTATUS Status;
  2718. BssCopy = NULL;
  2719. //
  2720. // Allocate a copy of the BSS entry, but do not copy any encryption keys as
  2721. // those are associated with a single connection to a BSS.
  2722. //
  2723. BssCopy = Net80211pCreateBssEntry(Bss->State.Bssid);
  2724. if (BssCopy == NULL) {
  2725. Status = STATUS_INSUFFICIENT_RESOURCES;
  2726. goto CopyBssEntryEnd;
  2727. }
  2728. BssCopy->Flags = Bss->Flags;
  2729. RtlCopyMemory(&(BssCopy->State), &(Bss->State), sizeof(NET80211_BSS));
  2730. RtlCopyMemory(&(BssCopy->Encryption),
  2731. &(Bss->Encryption),
  2732. sizeof(NET80211_ENCRYPTION));
  2733. if (Bss->ElementsSize != 0) {
  2734. BssCopy->ElementsSize = Bss->ElementsSize;
  2735. BssCopy->Elements = MmAllocatePagedPool(BssCopy->ElementsSize,
  2736. NET80211_ALLOCATION_TAG);
  2737. if (BssCopy->Elements == NULL) {
  2738. Status = STATUS_INSUFFICIENT_RESOURCES;
  2739. goto CopyBssEntryEnd;
  2740. }
  2741. RtlCopyMemory(BssCopy->Elements, Bss->Elements, BssCopy->ElementsSize);
  2742. Offset = Bss->Ssid - Bss->Elements;
  2743. BssCopy->Ssid = BssCopy->Elements + Offset;
  2744. if (Bss->Encryption.ApRsn != NULL) {
  2745. Offset = Bss->Encryption.ApRsn - Bss->Elements;
  2746. BssCopy->Encryption.ApRsn = BssCopy->Elements + Offset;
  2747. }
  2748. }
  2749. RtlCopyMemory(BssCopy->Passphrase, Bss->Passphrase, Bss->PassphraseLength);
  2750. BssCopy->PassphraseLength = Bss->PassphraseLength;
  2751. BssCopy->State.Rates.Rate = NULL;
  2752. RtlZeroMemory(BssCopy->Encryption.Keys,
  2753. sizeof(PNET80211_KEY) * NET80211_MAX_KEY_COUNT);
  2754. ASSERT(BssCopy->Encryption.StationRsn ==
  2755. (PUCHAR)&Net80211DefaultRsnInformation);
  2756. RatesSize = BssCopy->State.Rates.Count * sizeof(UCHAR);
  2757. BssCopy->State.Rates.Rate = MmAllocatePagedPool(RatesSize,
  2758. NET80211_ALLOCATION_TAG);
  2759. if (BssCopy->State.Rates.Rate == NULL) {
  2760. Status = STATUS_INSUFFICIENT_RESOURCES;
  2761. goto CopyBssEntryEnd;
  2762. }
  2763. RtlCopyMemory(BssCopy->State.Rates.Rate, Bss->State.Rates.Rate, RatesSize);
  2764. Status = STATUS_SUCCESS;
  2765. CopyBssEntryEnd:
  2766. if (!KSUCCESS(Status)) {
  2767. if (BssCopy != NULL) {
  2768. Net80211pBssEntryReleaseReference(BssCopy);
  2769. BssCopy = NULL;
  2770. }
  2771. }
  2772. return BssCopy;
  2773. }
  2774. PNET80211_BSS_ENTRY
  2775. Net80211pCreateBssEntry (
  2776. PUCHAR Bssid
  2777. )
  2778. /*++
  2779. Routine Description:
  2780. This routine creates a BSS entry.
  2781. Arguments:
  2782. Bssid - Supplies a pointer to the BSSID.
  2783. Return Value:
  2784. Returns a pointer to the newly allocated BSS entry on success or NULL on
  2785. failure.
  2786. --*/
  2787. {
  2788. PNET80211_BSS_ENTRY Bss;
  2789. Bss = MmAllocatePagedPool(sizeof(NET80211_BSS_ENTRY),
  2790. NET80211_ALLOCATION_TAG);
  2791. if (Bss == NULL) {
  2792. goto CreateBssEntryEnd;
  2793. }
  2794. RtlZeroMemory(Bss, sizeof(NET80211_BSS_ENTRY));
  2795. Bss->State.Version = NET80211_BSS_VERSION;
  2796. Bss->ReferenceCount = 1;
  2797. Bss->EapolHandle = INVALID_HANDLE;
  2798. RtlCopyMemory(Bss->State.Bssid, Bssid, NET80211_ADDRESS_SIZE);
  2799. CreateBssEntryEnd:
  2800. return Bss;
  2801. }
  2802. VOID
  2803. Net80211pDestroyBssEntry (
  2804. PNET80211_BSS_ENTRY BssEntry
  2805. )
  2806. /*++
  2807. Routine Description:
  2808. This routine destroys the resources for the given BSS entry.
  2809. Arguments:
  2810. BssEntry - Supplies a pointer to the BSS entry to destroy.
  2811. Return Value:
  2812. None.
  2813. --*/
  2814. {
  2815. ULONG Index;
  2816. ASSERT((BssEntry->Encryption.StationRsn == NULL) ||
  2817. (BssEntry->Encryption.StationRsn ==
  2818. (PUCHAR)&Net80211DefaultRsnInformation));
  2819. Net80211pDestroyEncryption(BssEntry);
  2820. if (BssEntry->State.Rates.Rate != NULL) {
  2821. MmFreePagedPool(BssEntry->State.Rates.Rate);
  2822. }
  2823. if (BssEntry->Elements != NULL) {
  2824. MmFreePagedPool(BssEntry->Elements);
  2825. }
  2826. for (Index = 0; Index < NET80211_MAX_KEY_COUNT; Index += 1) {
  2827. if (BssEntry->Encryption.Keys[Index] != NULL) {
  2828. Net80211pDestroyKey(BssEntry->Encryption.Keys[Index]);
  2829. }
  2830. }
  2831. MmFreePagedPool(BssEntry);
  2832. return;
  2833. }