mgmt.c 94 KB

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