net80211.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. net80211.c
  5. Abstract:
  6. This module implements the 802.11 networking core library.
  7. Author:
  8. Chris Stevens 19-Oct-2015
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "net80211.h"
  16. //
  17. // ---------------------------------------------------------------- Definitions
  18. //
  19. //
  20. // Printed strings of ethernet addresses look something like:
  21. // "12:34:56:78:9A:BC". Include the null terminator.
  22. //
  23. #define NET80211_ADDRESS_STRING_LENGTH 18
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. //
  28. // ----------------------------------------------- Internal Function Prototypes
  29. //
  30. VOID
  31. Net80211DriverUnload (
  32. PVOID Driver
  33. );
  34. KSTATUS
  35. Net80211pInitializeLink (
  36. PNET_LINK Link
  37. );
  38. VOID
  39. Net80211pDestroyLink (
  40. PNET_LINK Link
  41. );
  42. KSTATUS
  43. Net80211pSend (
  44. PVOID DataLinkContext,
  45. PNET_PACKET_LIST PacketList,
  46. PNETWORK_ADDRESS SourcePhysicalAddress,
  47. PNETWORK_ADDRESS DestinationPhysicalAddress,
  48. ULONG ProtocolNumber
  49. );
  50. VOID
  51. Net80211pProcessReceivedPacket (
  52. PVOID DataLinkContext,
  53. PNET_PACKET_BUFFER Packet
  54. );
  55. VOID
  56. Net80211pGetBroadcastAddress (
  57. PNETWORK_ADDRESS PhysicalNetworkAddress
  58. );
  59. ULONG
  60. Net80211pPrintAddress (
  61. PNETWORK_ADDRESS Address,
  62. PSTR Buffer,
  63. ULONG BufferLength
  64. );
  65. VOID
  66. Net80211pGetPacketSizeInformation (
  67. PVOID DataLinkContext,
  68. PNET_PACKET_SIZE_INFORMATION PacketSizeInformation,
  69. ULONG Flags
  70. );
  71. VOID
  72. Net80211pDestroy80211Link (
  73. PNET80211_LINK Net80211Link
  74. );
  75. KSTATUS
  76. Net80211pGetSetNetworkDeviceInformation (
  77. PNET80211_LINK Link,
  78. PNETWORK_80211_DEVICE_INFORMATION Information,
  79. BOOL Set
  80. );
  81. //
  82. // -------------------------------------------------------------------- Globals
  83. //
  84. HANDLE Net80211DataLinkLayerHandle = INVALID_HANDLE;
  85. UUID Net80211NetworkDeviceInformationUuid =
  86. NETWORK_80211_DEVICE_INFORMATION_UUID;
  87. //
  88. // ------------------------------------------------------------------ Functions
  89. //
  90. KSTATUS
  91. DriverEntry (
  92. PDRIVER Driver
  93. )
  94. /*++
  95. Routine Description:
  96. This routine implements the initial entry point of the networking core
  97. library, called when the library is first loaded.
  98. Arguments:
  99. Driver - Supplies a pointer to the driver object.
  100. Return Value:
  101. Status code.
  102. --*/
  103. {
  104. NET_DATA_LINK_ENTRY DataLinkEntry;
  105. HANDLE DataLinkHandle;
  106. DRIVER_FUNCTION_TABLE FunctionTable;
  107. PNET_DATA_LINK_INTERFACE Interface;
  108. KSTATUS Status;
  109. ASSERT(Net80211DataLinkLayerHandle == INVALID_HANDLE);
  110. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  111. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  112. FunctionTable.Unload = Net80211DriverUnload;
  113. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  114. if (!KSUCCESS(Status)) {
  115. goto DriverEntryEnd;
  116. }
  117. //
  118. // Register the 802.11 data link layer with the networking core.
  119. //
  120. DataLinkEntry.Domain = NetDomain80211;
  121. Interface = &(DataLinkEntry.Interface);
  122. Interface->InitializeLink = Net80211pInitializeLink;
  123. Interface->DestroyLink = Net80211pDestroyLink;
  124. Interface->Send = Net80211pSend;
  125. Interface->ProcessReceivedPacket = Net80211pProcessReceivedPacket;
  126. Interface->GetBroadcastAddress = Net80211pGetBroadcastAddress;
  127. Interface->PrintAddress = Net80211pPrintAddress;
  128. Interface->GetPacketSizeInformation = Net80211pGetPacketSizeInformation;
  129. Status = NetRegisterDataLinkLayer(&DataLinkEntry, &DataLinkHandle);
  130. if (!KSUCCESS(Status)) {
  131. goto DriverEntryEnd;
  132. }
  133. Net80211DataLinkLayerHandle = DataLinkHandle;
  134. //
  135. // Initialize any built-in networks.
  136. //
  137. Status = Net80211pEapolInitialize();
  138. if (!KSUCCESS(Status)) {
  139. goto DriverEntryEnd;
  140. }
  141. Status = Net80211pNetlinkInitialize();
  142. if (!KSUCCESS(Status)) {
  143. goto DriverEntryEnd;
  144. }
  145. DriverEntryEnd:
  146. if (!KSUCCESS(Status)) {
  147. if (Net80211DataLinkLayerHandle != INVALID_HANDLE) {
  148. NetUnregisterDataLinkLayer(Net80211DataLinkLayerHandle);
  149. Net80211DataLinkLayerHandle = INVALID_HANDLE;
  150. }
  151. }
  152. return Status;
  153. }
  154. VOID
  155. Net80211DriverUnload (
  156. PVOID Driver
  157. )
  158. /*++
  159. Routine Description:
  160. This routine is called before a driver is about to be unloaded from memory.
  161. The driver should take this opportunity to free any resources it may have
  162. set up in the driver entry routine.
  163. Arguments:
  164. Driver - Supplies a pointer to the driver being torn down.
  165. Return Value:
  166. None.
  167. --*/
  168. {
  169. //
  170. // Tear down built-in networks.
  171. //
  172. Net80211pNetlinkDestroy();
  173. Net80211pEapolDestroy();
  174. //
  175. // Unregister the 802.11 data link layer from the networking core.
  176. //
  177. if (Net80211DataLinkLayerHandle != INVALID_HANDLE) {
  178. NetUnregisterDataLinkLayer(Net80211DataLinkLayerHandle);
  179. Net80211DataLinkLayerHandle = INVALID_HANDLE;
  180. }
  181. return;
  182. }
  183. NET80211_API
  184. KSTATUS
  185. Net80211AddLink (
  186. PNET80211_LINK_PROPERTIES Properties,
  187. PNET80211_LINK *NewLink
  188. )
  189. /*++
  190. Routine Description:
  191. This routine adds the device link to the 802.11 networking core. The device
  192. must be ready to start sending and receiving 802.11 management frames in
  193. order to establish a BSS connection.
  194. Arguments:
  195. Properties - Supplies a pointer describing the properties and interface of
  196. the 802.11 link. This memory will not be referenced after the function
  197. returns, so this may be a stack allocated structure.
  198. NewLink - Supplies a pointer where a pointer to the new 802.11 link will be
  199. returned on success.
  200. Return Value:
  201. Status code.
  202. --*/
  203. {
  204. ULONG AllocationSize;
  205. PNET80211_LINK Link;
  206. NET_LINK_PROPERTIES NetProperties;
  207. PNET_LINK NetworkLink;
  208. PNET80211_RATE_INFORMATION Rates;
  209. KSTATUS Status;
  210. ASSERT(KeGetRunLevel() == RunLevelLow);
  211. Link = NULL;
  212. if (Properties->Version < NET80211_LINK_PROPERTIES_VERSION) {
  213. Status = STATUS_VERSION_MISMATCH;
  214. goto AddLinkEnd;
  215. }
  216. //
  217. // Convert the 802.11 properties to the networking core properties and
  218. // add the networking core link. In order for this to work like the
  219. // data link layers built into the networking core (e.g. Ethernet) the
  220. // networking core routine will call 802.11 back to have it create it's
  221. // private context.
  222. //
  223. RtlZeroMemory(&NetProperties, sizeof(NET_LINK_PROPERTIES));
  224. NetProperties.Version = NET_LINK_PROPERTIES_VERSION;
  225. NetProperties.TransmitAlignment = Properties->TransmitAlignment;
  226. NetProperties.Device = Properties->Device;
  227. NetProperties.DeviceContext = Properties->DeviceContext;
  228. NetProperties.PacketSizeInformation = Properties->PacketSizeInformation;
  229. NetProperties.ChecksumFlags = Properties->ChecksumFlags;
  230. NetProperties.DataLinkType = NetDomain80211;
  231. NetProperties.MaxPhysicalAddress = Properties->MaxPhysicalAddress;
  232. NetProperties.PhysicalAddress = Properties->PhysicalAddress;
  233. NetProperties.Interface.Send = Properties->Interface.Send;
  234. NetProperties.Interface.GetSetInformation =
  235. Properties->Interface.GetSetInformation;
  236. NetProperties.Interface.DestroyLink = Properties->Interface.DestroyLink;
  237. Status = NetAddLink(&NetProperties, &NetworkLink);
  238. if (!KSUCCESS(Status)) {
  239. goto AddLinkEnd;
  240. }
  241. ASSERT(NetworkLink->DataLinkContext != NULL);
  242. Link = (PNET80211_LINK)NetworkLink->DataLinkContext;
  243. //
  244. // Copy the properties, except the pointer to the supported rates.
  245. //
  246. RtlCopyMemory(&(Link->Properties),
  247. Properties,
  248. sizeof(NET80211_LINK_PROPERTIES));
  249. Link->Properties.SupportedRates = NULL;
  250. //
  251. // All supported station modes currently set the ESS capability.
  252. //
  253. Link->Properties.Capabilities |= NET80211_CAPABILITY_FLAG_ESS;
  254. //
  255. // The rate information has a dynamic length, so it needs to be reallocated
  256. // and copied.
  257. //
  258. AllocationSize = sizeof(NET80211_RATE_INFORMATION) +
  259. (Properties->SupportedRates->Count * sizeof(UCHAR));
  260. Rates = MmAllocatePagedPool(AllocationSize, NET80211_ALLOCATION_TAG);
  261. if (Rates == NULL) {
  262. Status = STATUS_INSUFFICIENT_RESOURCES;
  263. goto AddLinkEnd;
  264. }
  265. Rates->Count = Properties->SupportedRates->Count;
  266. Rates->Rate = (PUCHAR)(Rates + 1);
  267. RtlCopyMemory(Rates->Rate,
  268. Properties->SupportedRates->Rate,
  269. Rates->Count * sizeof(UCHAR));
  270. Link->Properties.SupportedRates = Rates;
  271. //
  272. // All 802.11 network devices respond to 802.11 network device information
  273. // requests.
  274. //
  275. Status = IoRegisterDeviceInformation(Link->Properties.Device,
  276. &Net80211NetworkDeviceInformationUuid,
  277. TRUE);
  278. if (!KSUCCESS(Status)) {
  279. goto AddLinkEnd;
  280. }
  281. NetSetLinkState(Link->NetworkLink, FALSE, 0);
  282. *NewLink = Link;
  283. Status = STATUS_SUCCESS;
  284. AddLinkEnd:
  285. if (!KSUCCESS(Status)) {
  286. if (Link != NULL) {
  287. Net80211RemoveLink(Link);
  288. }
  289. }
  290. return Status;
  291. }
  292. NET80211_API
  293. VOID
  294. Net80211RemoveLink (
  295. PNET80211_LINK Link
  296. )
  297. /*++
  298. Routine Description:
  299. This routine removes a link from the 802.11 core after its device has been
  300. removed. There may be outstanding references on the link, so the 802.11
  301. core will invoke the link destruction callback when all the references are
  302. released.
  303. Arguments:
  304. Link - Supplies a pointer to the link to remove.
  305. Return Value:
  306. None.
  307. --*/
  308. {
  309. //
  310. // The device has been removed, the link should no longer respond to
  311. // information requests.
  312. //
  313. IoRegisterDeviceInformation(Link->Properties.Device,
  314. &Net80211NetworkDeviceInformationUuid,
  315. FALSE);
  316. //
  317. // Remove the network link. When the last reference is released on the
  318. // network link it will call the data link destruction routine to destroy
  319. // the context.
  320. //
  321. Net80211pSetState(Link, Net80211StateUninitialized);
  322. NetRemoveLink(Link->NetworkLink);
  323. Net80211LinkReleaseReference(Link);
  324. return;
  325. }
  326. NET80211_API
  327. VOID
  328. Net80211LinkAddReference (
  329. PNET80211_LINK Link
  330. )
  331. /*++
  332. Routine Description:
  333. This routine increases the reference count on a 802.11 link.
  334. Arguments:
  335. Link - Supplies a pointer to the 802.11 link whose reference count
  336. should be incremented.
  337. Return Value:
  338. None.
  339. --*/
  340. {
  341. ULONG OldReferenceCount;
  342. OldReferenceCount = RtlAtomicAdd32(&(Link->ReferenceCount), 1);
  343. ASSERT((OldReferenceCount != 0) & (OldReferenceCount < 0x20000000));
  344. return;
  345. }
  346. NET80211_API
  347. VOID
  348. Net80211LinkReleaseReference (
  349. PNET80211_LINK Link
  350. )
  351. /*++
  352. Routine Description:
  353. This routine decreases the reference count of a 802.11 link, and destroys
  354. the link if the reference count drops to zero.
  355. Arguments:
  356. Link - Supplies a pointer to the 802.11 link whose reference count
  357. should be decremented.
  358. Return Value:
  359. None.
  360. --*/
  361. {
  362. ULONG OldReferenceCount;
  363. OldReferenceCount = RtlAtomicAdd32(&(Link->ReferenceCount), -1);
  364. ASSERT(OldReferenceCount != 0);
  365. //
  366. // Since the 802.11 link is owned by the network link. It cannot and should
  367. // not actually be destroyed until the network link's last reference goes
  368. // away. So release the initial reference taken on the network link.
  369. //
  370. if (OldReferenceCount == 1) {
  371. NetLinkReleaseReference(Link->NetworkLink);
  372. }
  373. return;
  374. }
  375. NET80211_API
  376. VOID
  377. Net80211ProcessReceivedPacket (
  378. PNET80211_LINK Link,
  379. PNET80211_RECEIVE_PACKET Packet
  380. )
  381. /*++
  382. Routine Description:
  383. This routine is called by the low level WiFi driver to pass received
  384. packets onto the 802.11 core networking library for dispatching.
  385. Arguments:
  386. Link - Supplies a pointer to the 802.11 link that received the packet.
  387. Packet - Supplies a pointer to a structure describing the incoming packet.
  388. This structure and the network packet it contains may be used as a
  389. scratch space while this routine executes and the packet travels up the
  390. stack, but will not be accessed after this routine returns.
  391. Return Value:
  392. None. When the function returns, the memory associated with the packet may
  393. be reclaimed and reused.
  394. --*/
  395. {
  396. PNET80211_BSS_ENTRY Bss;
  397. PNET80211_FRAME_HEADER Header;
  398. NetProcessReceivedPacket(Link->NetworkLink, Packet->NetPacket);
  399. //
  400. // Update the RSSI for the BSS that sent the packet. If this station is
  401. // associated (i.e. has an active BSS) and is not scanning, then assume the
  402. // packet came from the associated BSS.
  403. //
  404. KeAcquireQueuedLock(Link->Lock);
  405. if ((Link->ActiveBss != NULL) &&
  406. ((Link->Flags & NET80211_LINK_FLAG_SCANNING) == 0)) {
  407. Bss = Link->ActiveBss;
  408. //
  409. // Otherwise search the list of BSS's and update the one with the matching
  410. // ID.
  411. //
  412. } else {
  413. Header = Packet->NetPacket->Buffer + Packet->NetPacket->DataOffset;
  414. Bss = Net80211pLookupBssEntry(Link, Header->Address2);
  415. }
  416. if (Bss != NULL) {
  417. Bss->State.Rssi = Packet->Rssi;
  418. }
  419. KeReleaseQueuedLock(Link->Lock);
  420. return;
  421. }
  422. NET80211_API
  423. KSTATUS
  424. Net80211GetSetLinkDeviceInformation (
  425. PNET80211_LINK Link,
  426. PUUID Uuid,
  427. PVOID Data,
  428. PUINTN DataSize,
  429. BOOL Set
  430. )
  431. /*++
  432. Routine Description:
  433. This routine gets or sets device information for an 802.11 link.
  434. Arguments:
  435. Link - Supplies a pointer to the 802.11 link whose device information is
  436. being retrieved or set.
  437. Uuid - Supplies a pointer to the information identifier.
  438. Data - Supplies a pointer to the data buffer.
  439. DataSize - Supplies a pointer that on input contains the size of the data
  440. buffer in bytes. On output, returns the needed size of the data buffer,
  441. even if the supplied buffer was nonexistant or too small.
  442. Set - Supplies a boolean indicating whether to get the information (FALSE)
  443. or set the information (TRUE).
  444. Return Value:
  445. STATUS_SUCCESS on success.
  446. STATUS_BUFFER_TOO_SMALL if the supplied buffer was too small.
  447. STATUS_NOT_HANDLED if the given UUID was not recognized.
  448. --*/
  449. {
  450. KSTATUS Status;
  451. Status = STATUS_NOT_HANDLED;
  452. if (RtlAreUuidsEqual(Uuid, &Net80211NetworkDeviceInformationUuid)) {
  453. if (*DataSize < sizeof(NETWORK_80211_DEVICE_INFORMATION)) {
  454. *DataSize = sizeof(NETWORK_80211_DEVICE_INFORMATION);
  455. goto GetSetLinkDeviceInformationEnd;
  456. }
  457. *DataSize = sizeof(NETWORK_80211_DEVICE_INFORMATION);
  458. Status = Net80211pGetSetNetworkDeviceInformation(Link, Data, Set);
  459. goto GetSetLinkDeviceInformationEnd;
  460. } else {
  461. Status = NetGetSetLinkDeviceInformation(Link->NetworkLink,
  462. Uuid,
  463. Data,
  464. DataSize,
  465. Set);
  466. goto GetSetLinkDeviceInformationEnd;
  467. }
  468. GetSetLinkDeviceInformationEnd:
  469. return Status;
  470. }
  471. KSTATUS
  472. Net80211pInitializeLink (
  473. PNET_LINK Link
  474. )
  475. /*++
  476. Routine Description:
  477. This routine initializes any pieces of information needed by the data link
  478. layer for a new link.
  479. Arguments:
  480. Link - Supplies a pointer to the new link.
  481. Return Value:
  482. Status code.
  483. --*/
  484. {
  485. PNET80211_LINK Net80211Link;
  486. KSTATUS Status;
  487. Net80211Link = MmAllocatePagedPool(sizeof(NET80211_LINK),
  488. NET80211_ALLOCATION_TAG);
  489. if (Net80211Link == NULL) {
  490. Status = STATUS_INSUFFICIENT_RESOURCES;
  491. goto InitializeLinkEnd;
  492. }
  493. RtlZeroMemory(Net80211Link, sizeof(NET80211_LINK));
  494. Net80211Link->ReferenceCount = 1;
  495. NET_INITIALIZE_PACKET_LIST(&(Net80211Link->PausedPacketList));
  496. Net80211Link->Lock = KeCreateQueuedLock();
  497. if (Net80211Link->Lock == NULL) {
  498. Status = STATUS_INSUFFICIENT_RESOURCES;
  499. goto InitializeLinkEnd;
  500. }
  501. Net80211Link->ScanLock = KeCreateQueuedLock();
  502. if (Net80211Link->ScanLock == NULL) {
  503. Status = STATUS_INSUFFICIENT_RESOURCES;
  504. goto InitializeLinkEnd;
  505. }
  506. Net80211Link->StateTimer = KeCreateTimer(NET80211_ALLOCATION_TAG);
  507. if (Net80211Link->StateTimer == NULL) {
  508. Status = STATUS_INSUFFICIENT_RESOURCES;
  509. goto InitializeLinkEnd;
  510. }
  511. Net80211Link->TimeoutDpc = KeCreateDpc(Net80211pStateTimeoutDpcRoutine,
  512. Link);
  513. if (Net80211Link->TimeoutDpc == NULL) {
  514. Status = STATUS_INSUFFICIENT_RESOURCES;
  515. goto InitializeLinkEnd;
  516. }
  517. Net80211Link->TimeoutWorkItem = KeCreateWorkItem(
  518. NULL,
  519. WorkPriorityNormal,
  520. Net80211pStateTimeoutWorker,
  521. Link,
  522. NET80211_ALLOCATION_TAG);
  523. if (Net80211Link->TimeoutWorkItem == NULL) {
  524. Status = STATUS_INSUFFICIENT_RESOURCES;
  525. goto InitializeLinkEnd;
  526. }
  527. Net80211Link->State = Net80211StateUninitialized;
  528. INITIALIZE_LIST_HEAD(&(Net80211Link->BssList));
  529. NetLinkAddReference(Link);
  530. Net80211Link->NetworkLink = Link;
  531. Link->DataLinkContext = Net80211Link;
  532. Status = STATUS_SUCCESS;
  533. InitializeLinkEnd:
  534. if (!KSUCCESS(Status)) {
  535. Net80211pDestroy80211Link(Net80211Link);
  536. }
  537. return Status;
  538. }
  539. VOID
  540. Net80211pDestroyLink (
  541. PNET_LINK Link
  542. )
  543. /*++
  544. Routine Description:
  545. This routine allows the data link layer to tear down any state before a
  546. link is destroyed.
  547. Arguments:
  548. Link - Supplies a pointer to the dying link.
  549. Return Value:
  550. None.
  551. --*/
  552. {
  553. if (Link->DataLinkContext != NULL) {
  554. Net80211pDestroy80211Link(Link->DataLinkContext);
  555. Link->DataLinkContext = NULL;
  556. }
  557. return;
  558. }
  559. KSTATUS
  560. Net80211pSend (
  561. PVOID DataLinkContext,
  562. PNET_PACKET_LIST PacketList,
  563. PNETWORK_ADDRESS SourcePhysicalAddress,
  564. PNETWORK_ADDRESS DestinationPhysicalAddress,
  565. ULONG ProtocolNumber
  566. )
  567. /*++
  568. Routine Description:
  569. This routine sends data through the data link layer and out the link.
  570. Arguments:
  571. DataLinkContext - Supplies a pointer to the data link context for the
  572. link on which to send the data.
  573. PacketList - Supplies a pointer to a list of network packets to send. Data
  574. in these packets may be modified by this routine, but must not be used
  575. once this routine returns.
  576. SourcePhysicalAddress - Supplies a pointer to the source (local) physical
  577. network address.
  578. DestinationPhysicalAddress - Supplies the optional physical address of the
  579. destination, or at least the next hop. If NULL is provided, then the
  580. packets will be sent to the data link layer's broadcast address.
  581. ProtocolNumber - Supplies the protocol number of the data inside the data
  582. link header.
  583. Return Value:
  584. Status code.
  585. --*/
  586. {
  587. PNET80211_LINK Link;
  588. KSTATUS Status;
  589. Link = (PNET80211_LINK)DataLinkContext;
  590. Status = Net80211pSendDataFrames(Link,
  591. PacketList,
  592. SourcePhysicalAddress,
  593. DestinationPhysicalAddress,
  594. ProtocolNumber);
  595. return Status;
  596. }
  597. VOID
  598. Net80211pProcessReceivedPacket (
  599. PVOID DataLinkContext,
  600. PNET_PACKET_BUFFER Packet
  601. )
  602. /*++
  603. Routine Description:
  604. This routine is called to process a received ethernet packet.
  605. Arguments:
  606. DataLinkContext - Supplies a pointer to the data link context for the link
  607. that received the packet.
  608. Packet - Supplies a pointer to a structure describing the incoming packet.
  609. This structure may be used as a scratch space while this routine
  610. executes and the packet travels up the stack, but will not be accessed
  611. after this routine returns.
  612. Return Value:
  613. None. When the function returns, the memory associated with the packet may
  614. be reclaimed and reused.
  615. --*/
  616. {
  617. ULONG FrameType;
  618. PNET80211_FRAME_HEADER Header;
  619. PNET80211_LINK Link;
  620. //
  621. // Parse the the 802.11 header to determine the kind of packet.
  622. //
  623. Link = (PNET80211_LINK)DataLinkContext;
  624. Header = Packet->Buffer + Packet->DataOffset;
  625. FrameType = NET80211_GET_FRAME_TYPE(Header);
  626. switch (FrameType) {
  627. case NET80211_FRAME_TYPE_DATA:
  628. Net80211pProcessDataFrame(Link, Packet);
  629. break;
  630. case NET80211_FRAME_TYPE_MANAGEMENT:
  631. Net80211pProcessManagementFrame(Link, Packet);
  632. break;
  633. case NET80211_FRAME_TYPE_CONTROL:
  634. Net80211pProcessControlFrame(Link, Packet);
  635. break;
  636. default:
  637. ASSERT(FALSE);
  638. break;
  639. }
  640. return;
  641. }
  642. VOID
  643. Net80211pGetBroadcastAddress (
  644. PNETWORK_ADDRESS PhysicalNetworkAddress
  645. )
  646. /*++
  647. Routine Description:
  648. This routine gets the 802.11 broadcast address.
  649. Arguments:
  650. PhysicalNetworkAddress - Supplies a pointer where the physical network
  651. broadcast address will be returned.
  652. Return Value:
  653. None.
  654. --*/
  655. {
  656. ULONG ByteIndex;
  657. PUCHAR BytePointer;
  658. BytePointer = (PUCHAR)(PhysicalNetworkAddress->Address);
  659. RtlZeroMemory(BytePointer, sizeof(PhysicalNetworkAddress->Address));
  660. PhysicalNetworkAddress->Domain = NetDomain80211;
  661. PhysicalNetworkAddress->Port = 0;
  662. for (ByteIndex = 0; ByteIndex < NET80211_ADDRESS_SIZE; ByteIndex += 1) {
  663. BytePointer[ByteIndex] = 0xFF;
  664. }
  665. return;
  666. }
  667. ULONG
  668. Net80211pPrintAddress (
  669. PNETWORK_ADDRESS Address,
  670. PSTR Buffer,
  671. ULONG BufferLength
  672. )
  673. /*++
  674. Routine Description:
  675. This routine is called to convert a network address into a string, or
  676. determine the length of the buffer needed to convert an address into a
  677. string.
  678. Arguments:
  679. Address - Supplies an optional pointer to a network address to convert to
  680. a string.
  681. Buffer - Supplies an optional pointer where the string representation of
  682. the address will be returned.
  683. BufferLength - Supplies the length of the supplied buffer, in bytes.
  684. Return Value:
  685. Returns the maximum length of any address if no network address is
  686. supplied.
  687. Returns the actual length of the network address string if a network address
  688. was supplied, including the null terminator.
  689. --*/
  690. {
  691. PUCHAR BytePointer;
  692. ULONG Length;
  693. if (Address == NULL) {
  694. return NET80211_ADDRESS_STRING_LENGTH;
  695. }
  696. ASSERT(Address->Domain == NetDomain80211);
  697. BytePointer = (PUCHAR)(Address->Address);
  698. Length = RtlPrintToString(Buffer,
  699. BufferLength,
  700. CharacterEncodingAscii,
  701. "%02X:%02X:%02X:%02X:%02X:%02X",
  702. BytePointer[0],
  703. BytePointer[1],
  704. BytePointer[2],
  705. BytePointer[3],
  706. BytePointer[4],
  707. BytePointer[5]);
  708. return Length;
  709. }
  710. VOID
  711. Net80211pGetPacketSizeInformation (
  712. PVOID DataLinkContext,
  713. PNET_PACKET_SIZE_INFORMATION PacketSizeInformation,
  714. ULONG Flags
  715. )
  716. /*++
  717. Routine Description:
  718. This routine gets the current packet size information for the given link.
  719. As the number of required headers can be different for each link, the
  720. packet size information is not a constant for an entire data link layer.
  721. Arguments:
  722. DataLinkContext - Supplies a pointer to the data link context of the link
  723. whose packet size information is being queried.
  724. PacketSizeInformation - Supplies a pointer to a structure that receives the
  725. link's data link layer packet size information.
  726. Flags - Supplies a bitmask of flags indicating which packet size
  727. information is desired. See NET_PACKET_SIZE_FLAG_* for definitions.
  728. Return Value:
  729. None.
  730. --*/
  731. {
  732. PNET80211_BSS_ENTRY Bss;
  733. PNET80211_LINK Link;
  734. Link = (PNET80211_LINK)DataLinkContext;
  735. //
  736. // The header size depends on whether QoS is implemented. If QoS is not
  737. // implemented, then the header size is always the same. If QoS is
  738. // implemented, it depends on whether or not the other station implements
  739. // QoS.
  740. //
  741. PacketSizeInformation->HeaderSize = sizeof(NET80211_DATA_FRAME_HEADER) +
  742. sizeof(NET8022_LLC_HEADER) +
  743. sizeof(NET8022_SNAP_EXTENSION);
  744. PacketSizeInformation->FooterSize = 0;
  745. //
  746. // If encryption is required for the current BSS, then there is an
  747. // additional header and an additional footer.
  748. //
  749. if ((Flags & NET_PACKET_SIZE_FLAG_UNENCRYPTED) == 0) {
  750. Bss = Net80211pGetBss(Link);
  751. if (Bss != NULL) {
  752. if ((Bss->Encryption.Pairwise == NetworkEncryptionWpa2Eap) ||
  753. (Bss->Encryption.Pairwise == NetworkEncryptionWpa2Psk)) {
  754. PacketSizeInformation->FooterSize += NET80211_CCMP_MIC_SIZE;
  755. PacketSizeInformation->HeaderSize +=
  756. sizeof(NET80211_CCMP_HEADER);
  757. }
  758. Net80211pBssEntryReleaseReference(Bss);
  759. }
  760. }
  761. PacketSizeInformation->MaxPacketSize = NET80211_MAX_DATA_FRAME_BODY_SIZE +
  762. PacketSizeInformation->HeaderSize +
  763. PacketSizeInformation->FooterSize;
  764. PacketSizeInformation->MinPacketSize = 0;
  765. return;
  766. }
  767. ULONG
  768. Net80211pGetSequenceNumber (
  769. PNET80211_LINK Link
  770. )
  771. /*++
  772. Routine Description:
  773. This routine returns the sequence number to use for the given link.
  774. Arguments:
  775. Link - Supplies a pointer to the 802.11 link whose sequence number is
  776. requested.
  777. Return Value:
  778. Returns the sequence number to use for the given link.
  779. --*/
  780. {
  781. return RtlAtomicAdd32(&(Link->SequenceNumber), 1);
  782. }
  783. KSTATUS
  784. Net80211pSetChannel (
  785. PNET80211_LINK Link,
  786. ULONG Channel
  787. )
  788. /*++
  789. Routine Description:
  790. This routine sets the 802.11 link's channel to the given value.
  791. Arguments:
  792. Link - Supplies a pointer to the 802.11 link whose channel is being updated.
  793. Channel - Supplies the channel to which the link should be set.
  794. Return Value:
  795. Status code.
  796. --*/
  797. {
  798. PVOID DeviceContext;
  799. DeviceContext = Link->Properties.DeviceContext;
  800. return Link->Properties.Interface.SetChannel(DeviceContext, Channel);
  801. }
  802. //
  803. // --------------------------------------------------------- Internal Functions
  804. //
  805. VOID
  806. Net80211pDestroy80211Link (
  807. PNET80211_LINK Net80211Link
  808. )
  809. /*++
  810. Routine Description:
  811. This routine destroys the given 802.11 link structure.
  812. Arguments:
  813. Net80211Link - Supplies a pointer to the 802.11 link to destroy.
  814. Return Value:
  815. None.
  816. --*/
  817. {
  818. if (Net80211Link->Properties.SupportedRates != NULL) {
  819. MmFreePagedPool(Net80211Link->Properties.SupportedRates);
  820. }
  821. if (Net80211Link->Lock != NULL) {
  822. KeDestroyQueuedLock(Net80211Link->Lock);
  823. }
  824. if (Net80211Link->ScanLock != NULL) {
  825. KeDestroyQueuedLock(Net80211Link->ScanLock);
  826. }
  827. if (Net80211Link->StateTimer != NULL) {
  828. KeDestroyTimer(Net80211Link->StateTimer);
  829. }
  830. if (Net80211Link->TimeoutDpc != NULL) {
  831. KeDestroyDpc(Net80211Link->TimeoutDpc);
  832. }
  833. if (Net80211Link->TimeoutWorkItem != NULL) {
  834. KeDestroyWorkItem(Net80211Link->TimeoutWorkItem);
  835. }
  836. MmFreePagedPool(Net80211Link);
  837. return;
  838. }
  839. KSTATUS
  840. Net80211pGetSetNetworkDeviceInformation (
  841. PNET80211_LINK Link,
  842. PNETWORK_80211_DEVICE_INFORMATION Information,
  843. BOOL Set
  844. )
  845. /*++
  846. Routine Description:
  847. This routine gets or sets the 802.11 network device information for a
  848. particular link.
  849. Arguments:
  850. Link - Supplies a pointer to the link to work with.
  851. Information - Supplies a pointer that either receives the device
  852. information, or contains the new information to set. For set operations,
  853. the information buffer will contain the current settings on return.
  854. Set - Supplies a boolean indicating if the information should be set or
  855. returned.
  856. Return Value:
  857. Status code.
  858. --*/
  859. {
  860. ULONG SsidLength;
  861. ASSERT(KeGetRunLevel() == RunLevelLow);
  862. if (Information->Version < NETWORK_80211_DEVICE_INFORMATION_VERSION) {
  863. return STATUS_INVALID_PARAMETER;
  864. }
  865. if (Set != FALSE) {
  866. return STATUS_NOT_SUPPORTED;
  867. }
  868. Information->Flags = 0;
  869. RtlCopyMemory(&(Information->PhysicalAddress),
  870. &(Link->Properties.PhysicalAddress),
  871. sizeof(NETWORK_ADDRESS));
  872. KeAcquireQueuedLock(Link->Lock);
  873. if ((Link->State == Net80211StateAssociated) ||
  874. (Link->State == Net80211StateEncrypted)) {
  875. ASSERT(Link->ActiveBss != NULL);
  876. Information->Flags |= NETWORK_80211_DEVICE_FLAG_ASSOCIATED;
  877. Information->Bssid.Domain = NetDomain80211;
  878. Information->Bssid.Port = 0;
  879. RtlCopyMemory(Information->Bssid.Address,
  880. Link->ActiveBss->State.Bssid,
  881. NET80211_ADDRESS_SIZE);
  882. SsidLength = NET80211_GET_ELEMENT_LENGTH(Link->ActiveBss->Ssid);
  883. RtlCopyMemory(Information->Ssid,
  884. NET80211_GET_ELEMENT_DATA(Link->ActiveBss->Ssid),
  885. SsidLength);
  886. Information->Ssid[SsidLength] = STRING_TERMINATOR;
  887. Information->Channel = Link->ActiveBss->State.Channel;
  888. Information->MaxRate = Link->ActiveBss->State.MaxRate *
  889. NET80211_RATE_UNIT;
  890. Information->Rssi = Link->ActiveBss->State.Rssi;
  891. Information->PairwiseEncryption = Link->ActiveBss->Encryption.Pairwise;
  892. Information->GroupEncryption = Link->ActiveBss->Encryption.Group;
  893. }
  894. KeReleaseQueuedLock(Link->Lock);
  895. return STATUS_SUCCESS;
  896. }