1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021 |
- /*++
- Copyright (c) 2016 Minoca Corp. All Rights Reserved
- Module Name:
- netlink.c
- Abstract:
- This module implements the generic netlink 802.11 family message handling.
- Author:
- Chris Stevens 29-Mar-2016
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "net80211.h"
- #include <minoca/net/netlink.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // Define the multicast group indices. These must match the order of the
- // multicast group array below.
- //
- #define NETLINK_GENERIC_80211_MULTICAST_SCAN 0
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- KSTATUS
- Net80211pNetlinkJoin (
- PNET_SOCKET Socket,
- PNET_PACKET_BUFFER Packet,
- PNETLINK_GENERIC_COMMAND_INFORMATION Command
- );
- KSTATUS
- Net80211pNetlinkLeave (
- PNET_SOCKET Socket,
- PNET_PACKET_BUFFER Packet,
- PNETLINK_GENERIC_COMMAND_INFORMATION Command
- );
- KSTATUS
- Net80211pNetlinkScanStart (
- PNET_SOCKET Socket,
- PNET_PACKET_BUFFER Packet,
- PNETLINK_GENERIC_COMMAND_INFORMATION Command
- );
- VOID
- Net80211pNetlinkScanCompletionRoutine (
- PNET80211_LINK Link,
- KSTATUS ScanStatus
- );
- KSTATUS
- Net80211pNetlinkScanGetResults (
- PNET_SOCKET Socket,
- PNET_PACKET_BUFFER Packet,
- PNETLINK_GENERIC_COMMAND_INFORMATION Command
- );
- KSTATUS
- Net80211pNetlinkGetLink (
- PNET_PACKET_BUFFER Packet,
- PNET80211_LINK *Link
- );
- VOID
- Net80211pNetlinkSendScanNotification (
- PNET80211_LINK Link,
- UCHAR Command
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- NETLINK_GENERIC_COMMAND Net80211NetlinkCommands[] = {
- {
- NETLINK_80211_COMMAND_JOIN,
- 0,
- Net80211pNetlinkJoin
- },
- {
- NETLINK_80211_COMMAND_LEAVE,
- 0,
- Net80211pNetlinkLeave
- },
- {
- NETLINK_80211_COMMAND_SCAN_START,
- 0,
- Net80211pNetlinkScanStart
- },
- {
- NETLINK_80211_COMMAND_SCAN_GET_RESULTS,
- NETLINK_HEADER_FLAG_DUMP,
- Net80211pNetlinkScanGetResults
- },
- };
- NETLINK_GENERIC_MULTICAST_GROUP Net80211NetlinkMulticastGroups[] = {
- {
- NETLINK_GENERIC_80211_MULTICAST_SCAN,
- sizeof(NETLINK_80211_MULTICAST_SCAN_NAME),
- NETLINK_80211_MULTICAST_SCAN_NAME
- },
- };
- NETLINK_GENERIC_FAMILY_PROPERTIES Net80211NetlinkFamilyProperties = {
- NETLINK_GENERIC_FAMILY_PROPERTIES_VERSION,
- 0,
- sizeof(NETLINK_GENERIC_80211_NAME),
- NETLINK_GENERIC_80211_NAME,
- Net80211NetlinkCommands,
- sizeof(Net80211NetlinkCommands) / sizeof(Net80211NetlinkCommands[0]),
- Net80211NetlinkMulticastGroups,
- sizeof(Net80211NetlinkMulticastGroups) /
- sizeof(Net80211NetlinkMulticastGroups[0]),
- };
- PNETLINK_GENERIC_FAMILY Net80211NetlinkFamily = NULL;
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- Net80211pNetlinkInitialize (
- VOID
- )
- /*++
- Routine Description:
- This routine initializes the generic netlink 802.11 family.
- Arguments:
- None.
- Return Value:
- Status code.
- --*/
- {
- KSTATUS Status;
- Status = NetlinkGenericRegisterFamily(&Net80211NetlinkFamilyProperties,
- &Net80211NetlinkFamily);
- return Status;
- }
- VOID
- Net80211pNetlinkDestroy (
- VOID
- )
- /*++
- Routine Description:
- This routine tears down support for the generic netlink 802.11 family.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- if (Net80211NetlinkFamily != NULL) {
- NetlinkGenericUnregisterFamily(Net80211NetlinkFamily);
- Net80211NetlinkFamily = NULL;
- }
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- KSTATUS
- Net80211pNetlinkJoin (
- PNET_SOCKET Socket,
- PNET_PACKET_BUFFER Packet,
- PNETLINK_GENERIC_COMMAND_INFORMATION Command
- )
- /*++
- Routine Description:
- This routine is called to process an 802.11 netlink network join request.
- It attempts to join a device to a network as specified by the netlink
- message.
- Arguments:
- Socket - Supplies a pointer to the socket that received the packet.
- Packet - Supplies a pointer to a structure describing the incoming packet.
- This structure may be used as a scratch space while this routine
- executes and the packet travels up the stack, but will not be accessed
- after this routine returns.
- Command - Supplies a pointer to the command information.
- Return Value:
- Status code.
- --*/
- {
- PVOID Attributes;
- ULONG AttributesLength;
- PVOID Bssid;
- USHORT BssidLength;
- PNET80211_LINK Link;
- PUCHAR Passphrase;
- USHORT PassphraseLength;
- NET80211_SCAN_STATE ScanParameters;
- PUCHAR Ssid;
- USHORT SsidLength;
- KSTATUS Status;
- //
- // Parse the packet to find the 802.11 link that is to join a network.
- //
- Status = Net80211pNetlinkGetLink(Packet, &Link);
- if (!KSUCCESS(Status)) {
- goto NetlinkJoinEnd;
- }
- //
- // An SSID is necessary even if a BSSID is supplied. The user shouldn't
- // join an BSSID that switched SSID's on it.
- //
- Attributes = Packet->Buffer + Packet->DataOffset;
- AttributesLength = Packet->FooterOffset - Packet->DataOffset;
- Status = NetlinkGetAttribute(Attributes,
- AttributesLength,
- NETLINK_80211_ATTRIBUTE_SSID,
- (PVOID *)&Ssid,
- &SsidLength);
- if (!KSUCCESS(Status)) {
- goto NetlinkJoinEnd;
- }
- //
- // The attribute should store a null-terminated SSID string. Fail if it is
- // not present and strip it if it is present. The scan parameters do not
- // take a null-terminator SSID.
- //
- if (Ssid[SsidLength - 1] != STRING_TERMINATOR) {
- Status = STATUS_INVALID_PARAMETER;
- goto NetlinkJoinEnd;
- }
- SsidLength -= 1;
- if (SsidLength > NET80211_MAX_SSID_LENGTH) {
- Status = STATUS_NAME_TOO_LONG;
- goto NetlinkJoinEnd;
- }
- //
- // The passphrase is optional as some network do not require them. Make
- // sure it is null-terminated and strip the null character if it is.
- //
- Status = NetlinkGetAttribute(Attributes,
- AttributesLength,
- NETLINK_80211_ATTRIBUTE_PASSPHRASE,
- (PVOID *)&Passphrase,
- &PassphraseLength);
- if (KSUCCESS(Status)) {
- if (Passphrase[PassphraseLength - 1] != STRING_TERMINATOR) {
- Status = STATUS_INVALID_PARAMETER;
- goto NetlinkJoinEnd;
- }
- PassphraseLength -= 1;
- if (PassphraseLength > NET80211_MAX_PASSPHRASE_LENGTH) {
- Status = STATUS_NAME_TOO_LONG;
- goto NetlinkJoinEnd;
- }
- }
- //
- // The BSSID is optional as the MAC address of the access point is not
- // always known.
- //
- Status = NetlinkGetAttribute(Attributes,
- AttributesLength,
- NETLINK_80211_ATTRIBUTE_BSSID,
- &Bssid,
- &BssidLength);
- if (KSUCCESS(Status)) {
- if (BssidLength != NET80211_ADDRESS_SIZE) {
- Status = STATUS_INVALID_PARAMETER;
- goto NetlinkJoinEnd;
- }
- }
- RtlZeroMemory(&ScanParameters, sizeof(NET80211_SCAN_STATE));
- ScanParameters.Link = Link;
- ScanParameters.Flags = NET80211_SCAN_FLAG_JOIN;
- if (BssidLength == 0) {
- ScanParameters.Flags |= NET80211_SCAN_FLAG_BROADCAST;
- } else {
- RtlCopyMemory(ScanParameters.Bssid, Bssid, BssidLength);
- }
- if (PassphraseLength != 0) {
- ScanParameters.PassphraseLength = PassphraseLength;
- RtlCopyMemory(ScanParameters.Passphrase, Passphrase, PassphraseLength);
- }
- RtlCopyMemory(ScanParameters.Ssid, Ssid, SsidLength);
- ScanParameters.SsidLength = SsidLength;
- Status = Net80211pStartScan(Link, &ScanParameters);
- if (!KSUCCESS(Status)) {
- goto NetlinkJoinEnd;
- }
- NetlinkJoinEnd:
- if (Link != NULL) {
- Net80211LinkReleaseReference(Link);
- }
- return Status;
- }
- KSTATUS
- Net80211pNetlinkLeave (
- PNET_SOCKET Socket,
- PNET_PACKET_BUFFER Packet,
- PNETLINK_GENERIC_COMMAND_INFORMATION Command
- )
- /*++
- Routine Description:
- This routine is called to process an 802.11 netlink request for a device to
- leave its current network.
- Arguments:
- Socket - Supplies a pointer to the socket that received the packet.
- Packet - Supplies a pointer to a structure describing the incoming packet.
- This structure may be used as a scratch space while this routine
- executes and the packet travels up the stack, but will not be accessed
- after this routine returns.
- Command - Supplies a pointer to the command information.
- Return Value:
- Status code.
- --*/
- {
- PNET80211_LINK Link;
- KSTATUS Status;
- //
- // Parse the packet to find the 802.11 link that is to leave its network.
- //
- Status = Net80211pNetlinkGetLink(Packet, &Link);
- if (!KSUCCESS(Status)) {
- goto NetlinkLeaveEnd;
- }
- //
- // Setting the link state to initialized will deactivate the current
- // connection and send the appropriate deactivation messages to the access
- // point.
- //
- Net80211pSetState(Link, Net80211StateInitialized);
- NetlinkLeaveEnd:
- if (Link != NULL) {
- Net80211LinkReleaseReference(Link);
- }
- return Status;
- }
- KSTATUS
- Net80211pNetlinkScanStart (
- PNET_SOCKET Socket,
- PNET_PACKET_BUFFER Packet,
- PNETLINK_GENERIC_COMMAND_INFORMATION Command
- )
- /*++
- Routine Description:
- This routine is called to process an 802.11 netlink request to start
- scanning for available wireless networks.
- Arguments:
- Socket - Supplies a pointer to the socket that received the packet.
- Packet - Supplies a pointer to a structure describing the incoming packet.
- This structure may be used as a scratch space while this routine
- executes and the packet travels up the stack, but will not be accessed
- after this routine returns.
- Command - Supplies a pointer to the command information.
- Return Value:
- Status code.
- --*/
- {
- PNET80211_LINK Link;
- NET80211_SCAN_STATE ScanParameters;
- KSTATUS Status;
- //
- // Parse the packet to find the 802.11 link that is to scan for networks.
- //
- Status = Net80211pNetlinkGetLink(Packet, &Link);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanStartEnd;
- }
- //
- // Kick off a background scan to update the BSS cache for this link.
- //
- RtlZeroMemory(&ScanParameters, sizeof(NET80211_SCAN_STATE));
- ScanParameters.Link = Link;
- ScanParameters.Flags = NET80211_SCAN_FLAG_BROADCAST;
- ScanParameters.CompletionRoutine = Net80211pNetlinkScanCompletionRoutine;
- Status = Net80211pStartScan(Link, &ScanParameters);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanStartEnd;
- }
- //
- // Notify the scan multicast group that this scan is starting.
- //
- Net80211pNetlinkSendScanNotification(Link,
- NETLINK_80211_COMMAND_SCAN_START);
- NetlinkScanStartEnd:
- if (Link != NULL) {
- Net80211LinkReleaseReference(Link);
- }
- return Status;
- }
- VOID
- Net80211pNetlinkScanCompletionRoutine (
- PNET80211_LINK Link,
- KSTATUS ScanStatus
- )
- /*++
- Routine Description:
- This routine is called when a scan for nearby BSS access points has
- completed.
- Arguments:
- Link - Supplies a pointer to the 802.11 link that performed the scan.
- ScanStatus - Supplies the status result of the scan.
- Return Value:
- None.
- --*/
- {
- UCHAR Command;
- //
- // Report success or failure without any further details on an error.
- //
- Command = NETLINK_80211_COMMAND_SCAN_RESULT;
- if (!KSUCCESS(ScanStatus)) {
- Command = NETLINK_80211_COMMAND_SCAN_ABORTED;
- }
- Net80211pNetlinkSendScanNotification(Link, Command);
- return;
- }
- KSTATUS
- Net80211pNetlinkScanGetResults (
- PNET_SOCKET Socket,
- PNET_PACKET_BUFFER Packet,
- PNETLINK_GENERIC_COMMAND_INFORMATION Command
- )
- /*++
- Routine Description:
- This routine gets the results from the latest scan, packages them up as
- a netlink message and sends them back to the caller.
- Arguments:
- Socket - Supplies a pointer to the socket that received the packet.
- Packet - Supplies a pointer to a structure describing the incoming packet.
- This structure may be used as a scratch space while this routine
- executes and the packet travels up the stack, but will not be accessed
- after this routine returns.
- Command - Supplies a pointer to the command information.
- Return Value:
- Status code.
- --*/
- {
- PNET80211_BSS_ENTRY Bss;
- ULONG BssCount;
- ULONG BssLength;
- ULONG BssStatus;
- PLIST_ENTRY CurrentEntry;
- DEVICE_ID DeviceId;
- PNET80211_LINK Link;
- ULONG ResultLength;
- PNET_PACKET_BUFFER Results;
- ULONG ResultsLength;
- LONG SignalMbm;
- KSTATUS Status;
- //
- // Parse the packet to find the 802.11 link whose scan results are to be
- // queried.
- //
- Status = Net80211pNetlinkGetLink(Packet, &Link);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- //
- // Determine the required size of the BSS replies.
- //
- BssCount = 0;
- ResultsLength = 0;
- KeAcquireQueuedLock(Link->Lock);
- CurrentEntry = Link->BssList.Next;
- while (CurrentEntry != &(Link->BssList)) {
- Bss = LIST_VALUE(CurrentEntry, NET80211_BSS_ENTRY, ListEntry);
- CurrentEntry = CurrentEntry->Next;
- ResultsLength += NETLINK_HEADER_LENGTH + NETLINK_GENERIC_HEADER_LENGTH;
- ResultsLength += NETLINK_ATTRIBUTE_SIZE(sizeof(DEVICE_ID));
- BssLength = NETLINK_ATTRIBUTE_SIZE(NET80211_ADDRESS_SIZE) +
- NETLINK_ATTRIBUTE_SIZE(sizeof(Bss->State.Capabilities)) +
- NETLINK_ATTRIBUTE_SIZE(sizeof(Bss->State.BeaconInterval)) +
- NETLINK_ATTRIBUTE_SIZE(sizeof(BssStatus)) +
- NETLINK_ATTRIBUTE_SIZE(sizeof(SignalMbm)) +
- NETLINK_ATTRIBUTE_SIZE(Bss->ElementsSize);
- ResultsLength += NETLINK_ATTRIBUTE_SIZE(BssLength);
- BssCount += 1;
- }
- KeReleaseQueuedLock(Link->Lock);
- //
- // At least always send a done message.
- //
- ResultsLength += NETLINK_HEADER_LENGTH;
- //
- // Allocate the network packet buffer to hold all of the results.
- //
- Status = NetAllocateBuffer(0, ResultsLength, 0, NULL, 0, &Results);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- //
- // Package up the BSS entry list into multiple netlink scan result messages.
- // If new entries arrived since the lock was held before, they came in due
- // to an additional scan. A future scan results request will package them
- // up.
- //
- DeviceId = IoGetDeviceNumericId(Link->Properties.Device);
- KeAcquireQueuedLock(Link->Lock);
- CurrentEntry = Link->BssList.Next;
- while ((CurrentEntry != &(Link->BssList)) && (BssCount != 0)) {
- Bss = LIST_VALUE(CurrentEntry, NET80211_BSS_ENTRY, ListEntry);
- CurrentEntry = CurrentEntry->Next;
- //
- // Determine the length of the entire message.
- //
- ResultLength = NETLINK_ATTRIBUTE_SIZE(sizeof(DEVICE_ID));
- BssLength = NETLINK_ATTRIBUTE_SIZE(NET80211_ADDRESS_SIZE) +
- NETLINK_ATTRIBUTE_SIZE(sizeof(Bss->State.Capabilities)) +
- NETLINK_ATTRIBUTE_SIZE(sizeof(Bss->State.BeaconInterval)) +
- NETLINK_ATTRIBUTE_SIZE(sizeof(BssStatus)) +
- NETLINK_ATTRIBUTE_SIZE(sizeof(SignalMbm)) +
- NETLINK_ATTRIBUTE_SIZE(Bss->ElementsSize);
- ResultLength += NETLINK_ATTRIBUTE_SIZE(BssLength);
- //
- // Add a generic and base header for this entry.
- //
- Status = NetlinkGenericAppendHeaders(Net80211NetlinkFamily,
- Results,
- ResultLength,
- Command->Message.SequenceNumber,
- NETLINK_HEADER_FLAG_MULTIPART,
- NETLINK_80211_COMMAND_SCAN_RESULT,
- 0);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- //
- // Add the attributes.
- //
- Status = NetlinkAppendAttribute(Results,
- NETLINK_80211_ATTRIBUTE_DEVICE_ID,
- &DeviceId,
- sizeof(DEVICE_ID));
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- Status = NetlinkAppendAttribute(Results,
- NETLINK_80211_ATTRIBUTE_BSS,
- NULL,
- BssLength);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- Status = NetlinkAppendAttribute(Results,
- NETLINK_80211_BSS_ATTRIBUTE_BSSID,
- Bss->State.Bssid,
- NET80211_ADDRESS_SIZE);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- Status = NetlinkAppendAttribute(Results,
- NETLINK_80211_BSS_ATTRIBUTE_CAPABILITY,
- &(Bss->State.Capabilities),
- sizeof(Bss->State.Capabilities));
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- Status = NetlinkAppendAttribute(
- Results,
- NETLINK_80211_BSS_ATTRIBUTE_BEACON_INTERVAL,
- &(Bss->State.BeaconInterval),
- sizeof(Bss->State.BeaconInterval));
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- SignalMbm = Bss->State.Rssi * 100;
- Status = NetlinkAppendAttribute(Results,
- NETLINK_80211_BSS_ATTRIBUTE_SIGNAL_MBM,
- &SignalMbm,
- sizeof(SignalMbm));
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- BssStatus = NETLINK_80211_BSS_STATUS_NOT_CONNECTED;
- if (Bss == Link->ActiveBss) {
- switch (Link->State) {
- case Net80211StateAssociated:
- case Net80211StateEncrypted:
- Status = NETLINK_80211_BSS_STATUS_ASSOCIATED;
- break;
- case Net80211StateAssociating:
- Status = NETLINK_80211_BSS_STATUS_AUTHENTICATED;
- break;
- default:
- break;
- }
- }
- Status = NetlinkAppendAttribute(Results,
- NETLINK_80211_BSS_ATTRIBUTE_STATUS,
- &BssStatus,
- sizeof(BssStatus));
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- Status = NetlinkAppendAttribute(
- Results,
- NETLINK_80211_BSS_ATTRIBUTE_INFORMATION_ELEMENTS,
- Bss->Elements,
- Bss->ElementsSize);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- BssCount -= 1;
- }
- KeReleaseQueuedLock(Link->Lock);
- //
- // Send this multipart message back to the source of the request. This
- // routine will add the terminating DONE message and then send the entire
- // set of messages in the results packet.
- //
- Status = NetlinkSendMultipartMessage(Socket,
- Results,
- Command->Message.SourceAddress,
- Command->Message.SequenceNumber);
- if (!KSUCCESS(Status)) {
- goto NetlinkScanGetResultsEnd;
- }
- NetlinkScanGetResultsEnd:
- if (Link != NULL) {
- Net80211LinkReleaseReference(Link);
- }
- return Status;
- }
- KSTATUS
- Net80211pNetlinkGetLink (
- PNET_PACKET_BUFFER Packet,
- PNET80211_LINK *Link
- )
- /*++
- Routine Description:
- This routine parses the given 802.11 netlink message packet for the device
- ID attribute and then looks for the corresponding 802.11 link. If found, a
- reference is taken on the the 802.11 link and it is the caller's
- responsibility to release the reference.
- Arguments:
- Packet - Supplies a pointer to the netlink message to parse for the device
- ID or order to determine the target 802.11 link.
- Link - Supplies a pointer that receives a pointer an 802.11 network link.
- Return Value:
- Status code.
- --*/
- {
- PVOID Attributes;
- ULONG AttributesLength;
- PDEVICE Device;
- PVOID DeviceId;
- USHORT DeviceIdLength;
- PNET80211_LINK Net80211Link;
- PNET_LINK NetLink;
- KSTATUS Status;
- Device = NULL;
- NetLink = NULL;
- Net80211Link = NULL;
- //
- // Get the device ID. It is necessary to find the appropriate link.
- //
- Attributes = Packet->Buffer + Packet->DataOffset;
- AttributesLength = Packet->FooterOffset - Packet->DataOffset;
- Status = NetlinkGetAttribute(Attributes,
- AttributesLength,
- NETLINK_80211_ATTRIBUTE_DEVICE_ID,
- &DeviceId,
- &DeviceIdLength);
- if (!KSUCCESS(Status)) {
- goto NetlinkGetLinkEnd;
- }
- if (DeviceIdLength != sizeof(DEVICE_ID)) {
- Status = STATUS_DATA_LENGTH_MISMATCH;
- goto NetlinkGetLinkEnd;
- }
- Device = IoGetDeviceByNumericId(*((PDEVICE_ID)DeviceId));
- if (Device == NULL) {
- Status = STATUS_NO_SUCH_DEVICE;
- goto NetlinkGetLinkEnd;
- }
- Status = NetLookupLinkByDevice(Device, &NetLink);
- if (!KSUCCESS(Status)) {
- goto NetlinkGetLinkEnd;
- }
- //
- // If the link is not an 802.11 type then nothing can be done.
- //
- if (NetLink->Properties.DataLinkType != NetDomain80211) {
- Status = STATUS_NOT_SUPPORTED;
- goto NetlinkGetLinkEnd;
- }
- //
- // Setting the link state to initialized will deactivate the current
- // connection and send the appropriate deactivation messages to the access
- // point.
- //
- Net80211Link = NetLink->DataLinkContext;
- Net80211LinkAddReference(Net80211Link);
- NetlinkGetLinkEnd:
- if (Device != NULL) {
- IoDeviceReleaseReference(Device);
- }
- if (NetLink != NULL) {
- NetLinkReleaseReference(NetLink);
- }
- *Link = Net80211Link;
- return Status;
- }
- VOID
- Net80211pNetlinkSendScanNotification (
- PNET80211_LINK Link,
- UCHAR Command
- )
- /*++
- Routine Description:
- This routine notifies the scan multicast group about a scan's progress.
- Arguments:
- Link - Supplies a pointer to the 802.11 link that performed the scan.
- Command - Supplies the 802.11 netlink command to send to the scan multicast
- group.
- Return Value:
- None.
- --*/
- {
- DEVICE_ID DeviceId;
- ULONG HeaderSize;
- PNET_PACKET_BUFFER Packet;
- ULONG PayloadSize;
- ULONG Size;
- KSTATUS Status;
- //
- // Allocate and build a network buffer to hold the scan properties.
- //
- Packet = NULL;
- HeaderSize = NETLINK_HEADER_LENGTH + NETLINK_GENERIC_HEADER_LENGTH;
- PayloadSize = NETLINK_ATTRIBUTE_SIZE(sizeof(DEVICE_ID));
- Size = HeaderSize + PayloadSize;
- Status = NetAllocateBuffer(0,
- Size,
- 0,
- NULL,
- 0,
- &Packet);
- if (!KSUCCESS(Status)) {
- goto NetlinkSendScanNotification;
- }
- Status = NetlinkGenericAppendHeaders(Net80211NetlinkFamily,
- Packet,
- PayloadSize,
- 0,
- 0,
- Command,
- 0);
- if (!KSUCCESS(Status)) {
- goto NetlinkSendScanNotification;
- }
- DeviceId = IoGetDeviceNumericId(Link->Properties.Device);
- Status = NetlinkAppendAttribute(Packet,
- NETLINK_80211_ATTRIBUTE_DEVICE_ID,
- &DeviceId,
- sizeof(DEVICE_ID));
- if (!KSUCCESS(Status)) {
- goto NetlinkSendScanNotification;
- }
- //
- // Send the packet out to the 802.11 scan multicast group.
- //
- Status = NetlinkGenericSendMulticastCommand(
- Net80211NetlinkFamily,
- Packet,
- NETLINK_GENERIC_80211_MULTICAST_SCAN);
- if (!KSUCCESS(Status)) {
- goto NetlinkSendScanNotification;
- }
- NetlinkSendScanNotification:
- if (Packet != NULL) {
- NetFreeBuffer(Packet);
- }
- return;
- }
|