123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550 |
- /*++
- Copyright (c) 2016 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- netcon.c
- Abstract:
- This module implements the network configuration program.
- Author:
- Chris Stevens 14-Mar-2016
- Environment:
- User
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/lib/minocaos.h>
- #include <minoca/net/netdrv.h>
- #include <minoca/net/net80211.h>
- #include <minoca/net/netlink.h>
- #include <minoca/lib/mlibc.h>
- #include <minoca/lib/netlink.h>
- #include <assert.h>
- #include <errno.h>
- #include <getopt.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define NETCON_VERSION_MAJOR 1
- #define NETCON_VERSION_MINOR 0
- #define NETCON_USAGE \
- "usage: netcon [-d device] [-j ssid -p] [-l] [-s] [-v]\n\n" \
- "The netcon utility configures network devices.\n\n" \
- "Options:\n" \
- " -d --device=device -- Specifies the network device to configure.\n" \
- " This is optional for wireless commands if there is only 1\n" \
- " wireless device on the system.\n" \
- " -j --join=ssid -- Attempts to join the given wireless network.\n" \
- " -l --leave -- Attempts to leave the current wireless network.\n" \
- " -p --password -- Indicates that the user wants to be prompted for a\n" \
- " password during a join operation.\n" \
- " -s --scan -- Displays the list of wireless networks available to\n" \
- " the network device specified by -d.\n" \
- " -v --verbose -- Display more detailed information.\n" \
- " --help -- Display this help text.\n" \
- " --version -- Display the application version and exit.\n\n"
- #define NETCON_OPTIONS_STRING "d:j:lspvh"
- //
- // Define the set of network configuration flags.
- //
- #define NETCON_FLAG_DEVICE_ID 0x00000001
- #define NETCON_FLAG_JOIN 0x00000002
- #define NETCON_FLAG_LEAVE 0x00000004
- #define NETCON_FLAG_PASSWORD 0x00000008
- #define NETCON_FLAG_SCAN 0x00000010
- #define NETCON_FLAG_VERBOSE 0x00000020
- #define NETCON_FLAG_WIRELESS_MASK \
- (NETCON_FLAG_JOIN | NETCON_FLAG_LEAVE | NETCON_FLAG_SCAN)
- //
- // Define the set of network device description flags.
- //
- #define NETCON_DEVICE_FLAG_IP4 0x00000001
- #define NETCON_DEVICE_FLAG_IP6 0x00000002
- #define NETCON_DEVICE_FLAG_80211 0x00000004
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure defines the context for network configuration requests.
- Members:
- Flags - Stores a bitmask of network configuration flags. See NETCON_FLAG_*
- for definitions.
- Device - Stores the ID of the network device that is being configured.
- Ssid - Stores a pointer to the SSID of the network to join.
- --*/
- typedef struct _NETCON_CONTEXT {
- ULONG Flags;
- DEVICE_ID DeviceId;
- PSTR Ssid;
- } NETCON_CONTEXT, *PNETCON_CONTEXT;
- /*++
- Structure Description:
- This structure defines a network device.
- Members:
- Flags - Stores a bitmask of flags. See NETCON_DEVICE_FLAG_* for definitions.
- DeviceId - Stores the network device's ID.
- NetworkIp4 - Stores the IPv4 network information.
- NetworkIp6 - Stores the IPv6 network information.
- Net80211 - Stores the 802.11 device information.
- --*/
- typedef struct _NETCON_DEVICE_DESCRIPTION {
- ULONG Flags;
- DEVICE_ID DeviceId;
- NETWORK_DEVICE_INFORMATION NetworkIp4;
- NETWORK_DEVICE_INFORMATION NetworkIp6;
- NETWORK_80211_DEVICE_INFORMATION Net80211;
- } NETCON_DEVICE_DESCRIPTION, *PNETCON_DEVICE_DESCRIPTION;
- /*++
- Structure Description:
- This structure defines a BSS scan result.
- Members:
- Bssid - Stores the BSSID.
- SignalStrength - Stores the BSS's signal strength in MBM's.
- Status - Stores the BSS's status.
- Capability - Stores the BSS's capability flags.
- BeaconInterval - Stores the BSS's beacon interval.
- Elements - Stores a pointer to the BSS's information elements. These
- include the SSID, channel, and security information.
- ElementsSize - Stores the size of the information elements, in bytes.
- --*/
- typedef struct _NETCON_BSS {
- NETWORK_ADDRESS Bssid;
- LONG SignalStrength;
- ULONG Status;
- USHORT BeaconInterval;
- USHORT Capabilities;
- PVOID Elements;
- ULONG ElementsSize;
- } NETCON_BSS, *PNETCON_BSS;
- /*++
- Structure Description:
- This structure defines a set of scan results.
- Members:
- Valid - Stores a boolean indicating whether or not the results are valid.
- BssCount - Stores the number of BSS element pointers in the array.
- BssArray - Stores an array of pointers to the BSS elements.
- --*/
- typedef struct _NETCON_SCAN_RESULTS {
- BOOL Valid;
- ULONG BssCount;
- PNETCON_BSS *BssArray;
- } NETCON_SCAN_RESULTS, *PNETCON_SCAN_RESULTS;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- VOID
- NetconListDevices (
- VOID
- );
- INT
- NetconEnumerateDevices (
- PNETCON_DEVICE_DESCRIPTION *DeviceArray,
- PULONG DeviceCount
- );
- INT
- NetconGetDeviceInformation (
- DEVICE_ID DeviceId,
- PNETCON_DEVICE_DESCRIPTION Device
- );
- VOID
- NetconJoinNetwork (
- PNETCON_CONTEXT Context
- );
- VOID
- NetconLeaveNetwork (
- PNETCON_CONTEXT Context
- );
- VOID
- NetconScanForNetworks (
- PNETCON_CONTEXT Context
- );
- VOID
- NetconParseScanNotification (
- PNL_SOCKET Socket,
- PNL_RECEIVE_CONTEXT Context,
- PVOID Message
- );
- VOID
- NetconParseScanResult (
- PNL_SOCKET Socket,
- PNL_RECEIVE_CONTEXT Context,
- PVOID Message
- );
- VOID
- NetconPrintScanResults (
- PNETCON_CONTEXT Context,
- PNETCON_SCAN_RESULTS Results
- );
- PVOID
- NetconGet80211InformationElement (
- PVOID Elements,
- ULONG ElementsSize,
- UCHAR ElementId
- );
- VOID
- NetconPrintRsnInformation (
- PUCHAR Rsn
- );
- VOID
- NetconPrintDeviceInformation (
- PNETCON_DEVICE_DESCRIPTION Device
- );
- VOID
- NetconPrintAddress (
- PNETWORK_ADDRESS Address
- );
- VOID
- NetconPrintEncryption (
- NETWORK_ENCRYPTION_TYPE EncryptionType
- );
- VOID
- NetconPrintCipherSuite (
- ULONG Suite
- );
- VOID
- NetconPrintRssi (
- LONG Rssi
- );
- VOID
- NetconPrintRates (
- PVOID RatesElement
- );
- INT
- NetconGet80211DeviceId (
- PDEVICE_ID DeviceId
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- struct option NetconLongOptions[] = {
- {"device", required_argument, 0, 'd'},
- {"join", required_argument, 0, 'j'},
- {"leave", no_argument, 0, 'l'},
- {"password", no_argument, 0, 'p'},
- {"scan", no_argument, 0, 's'},
- {"verbose", no_argument, 0, 'v'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {NULL, 0, 0, 0}
- };
- UUID NetconDeviceInformationUuid = NETWORK_DEVICE_INFORMATION_UUID;
- UUID Netcon80211DeviceInformationUuid = NETWORK_80211_DEVICE_INFORMATION_UUID;
- //
- // ------------------------------------------------------------------ Functions
- //
- INT
- main (
- INT ArgumentCount,
- CHAR **Arguments
- )
- /*++
- Routine Description:
- This routine implements the network configuration user mode program.
- Arguments:
- ArgumentCount - Supplies the number of elements in the arguments array.
- Arguments - Supplies an array of strings. The array count is bounded by the
- previous parameter, and the strings are null-terminated.
- Return Value:
- 0 on success.
- Non-zero on failure.
- --*/
- {
- PSTR AfterScan;
- NETCON_CONTEXT Context;
- NETCON_DEVICE_DESCRIPTION Device;
- INT Option;
- INT ReturnValue;
- memset(&Context, 0, sizeof(NETCON_CONTEXT));
- ReturnValue = 0;
- NlInitialize(NULL);
- //
- // Process the control arguments.
- //
- while (TRUE) {
- Option = getopt_long(ArgumentCount,
- Arguments,
- NETCON_OPTIONS_STRING,
- NetconLongOptions,
- NULL);
- if (Option == -1) {
- break;
- }
- if ((Option == '?') || (Option == ':')) {
- ReturnValue = 1;
- goto mainEnd;
- }
- switch (Option) {
- case 'd':
- Context.DeviceId = strtoull(optarg, &AfterScan, 0);
- if (AfterScan == optarg) {
- fprintf(stderr, "Error: Invalid device id '%s'.\n", optarg);
- ReturnValue = EINVAL;
- goto mainEnd;
- }
- Context.Flags |= NETCON_FLAG_DEVICE_ID;
- break;
- case 'j':
- Context.Ssid = optarg;
- Context.Flags |= NETCON_FLAG_JOIN;
- break;
- case 'l':
- Context.Flags |= NETCON_FLAG_LEAVE;
- break;
- case 's':
- Context.Flags |= NETCON_FLAG_SCAN;
- break;
- case 'p':
- Context.Flags |= NETCON_FLAG_PASSWORD;
- break;
- case 'v':
- Context.Flags |= NETCON_FLAG_VERBOSE;
- break;
- case 'V':
- printf("netcon version %d.%02d\n",
- NETCON_VERSION_MAJOR,
- NETCON_VERSION_MINOR);
- ReturnValue = 1;
- goto mainEnd;
- case 'h':
- printf(NETCON_USAGE);
- return 1;
- default:
- assert(FALSE);
- ReturnValue = 1;
- goto mainEnd;
- }
- }
- //
- // Wireless commands require a device ID to operate. If no ID is specified,
- // then attempt to find one. If there is more than one device present on
- // the system, an error will be printed along with the available devices.
- //
- if (((Context.Flags & NETCON_FLAG_DEVICE_ID) == 0) &&
- ((Context.Flags & NETCON_FLAG_WIRELESS_MASK) != 0)) {
- ReturnValue = NetconGet80211DeviceId(&(Context.DeviceId));
- if (ReturnValue != 0) {
- goto mainEnd;
- }
- Context.Flags |= NETCON_FLAG_DEVICE_ID;
- }
- //
- // Process the command.
- //
- if ((Context.Flags & NETCON_FLAG_JOIN) != 0) {
- NetconJoinNetwork(&Context);
- } else if ((Context.Flags & NETCON_FLAG_LEAVE) != 0) {
- NetconLeaveNetwork(&Context);
- } else if ((Context.Flags & NETCON_FLAG_SCAN) != 0) {
- NetconScanForNetworks(&Context);
- } else if ((Context.Flags & NETCON_FLAG_DEVICE_ID) != 0) {
- ReturnValue = NetconGetDeviceInformation(Context.DeviceId, &Device);
- if (ReturnValue != 0) {
- goto mainEnd;
- }
- NetconPrintDeviceInformation(&Device);
- } else {
- NetconListDevices();
- }
- mainEnd:
- if (ReturnValue == EINVAL) {
- printf(NETCON_USAGE);
- }
- return ReturnValue;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- NetconListDevices (
- VOID
- )
- /*++
- Routine Description:
- This routine prints the list of available network devices.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- PNETCON_DEVICE_DESCRIPTION DeviceArray;
- ULONG DeviceCount;
- ULONG Index;
- INT Result;
- Result = NetconEnumerateDevices(&DeviceArray, &DeviceCount);
- if (Result != 0) {
- return;
- }
- if (DeviceCount == 0) {
- printf("No network devices detected.\n");
- return;
- }
- printf("Minoca Network Configuration:\n\n");
- for (Index = 0; Index < DeviceCount; Index += 1) {
- NetconPrintDeviceInformation(&(DeviceArray[Index]));
- printf("\n");
- }
- free(DeviceArray);
- return;
- }
- INT
- NetconEnumerateDevices (
- PNETCON_DEVICE_DESCRIPTION *DeviceArray,
- PULONG DeviceCount
- )
- /*++
- Routine Description:
- This routine enumerates all the network devices on the system.
- Arguments:
- DeviceArray - Supplies a pointer where an array of network structures
- will be returned on success.
- DeviceCount - Supplies a pointer where the number of elements in the
- partition array will be returned on success.
- Return Value:
- 0 on success.
- Returns an error code on failure.
- --*/
- {
- UINTN AllocationSize;
- UINTN ArrayIndex;
- PNETCON_DEVICE_DESCRIPTION Devices;
- INT Result;
- ULONG ResultCount;
- UINTN ResultIndex;
- PDEVICE_INFORMATION_RESULT Results;
- KSTATUS Status;
- ArrayIndex = 0;
- Devices = NULL;
- ResultCount = 0;
- Results = NULL;
- //
- // Enumerate all the devices that support getting network device
- // information.
- //
- Status = OsLocateDeviceInformation(&NetconDeviceInformationUuid,
- NULL,
- NULL,
- &ResultCount);
- if (Status != STATUS_BUFFER_TOO_SMALL) {
- goto EnumerateDevicesEnd;
- }
- if (ResultCount == 0) {
- Status = STATUS_SUCCESS;
- goto EnumerateDevicesEnd;
- }
- AllocationSize = sizeof(DEVICE_INFORMATION_RESULT) * ResultCount;
- Results = malloc(AllocationSize);
- if (Results == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto EnumerateDevicesEnd;
- }
- memset(Results, 0, AllocationSize);
- Status = OsLocateDeviceInformation(&NetconDeviceInformationUuid,
- NULL,
- Results,
- &ResultCount);
- if (!KSUCCESS(Status)) {
- goto EnumerateDevicesEnd;
- }
- if (ResultCount == 0) {
- Status = STATUS_SUCCESS;
- goto EnumerateDevicesEnd;
- }
- //
- // Allocate the real array.
- //
- AllocationSize = sizeof(NETCON_DEVICE_DESCRIPTION) * ResultCount;
- Devices = malloc(AllocationSize);
- if (Devices == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto EnumerateDevicesEnd;
- }
- memset(Devices, 0, AllocationSize);
- //
- // Loop through the results setting up the structure elements.
- //
- for (ResultIndex = 0; ResultIndex < ResultCount; ResultIndex += 1) {
- Result = NetconGetDeviceInformation(Results[ResultIndex].DeviceId,
- &(Devices[ArrayIndex]));
- if (Result != 0) {
- continue;
- }
- ArrayIndex += 1;
- }
- Status = STATUS_SUCCESS;
- EnumerateDevicesEnd:
- if (Results != NULL) {
- free(Results);
- }
- if (!KSUCCESS(Status)) {
- if (Devices != NULL) {
- free(Devices);
- Devices = NULL;
- }
- return ClConvertKstatusToErrorNumber(Status);
- }
- *DeviceArray = Devices;
- *DeviceCount = ArrayIndex;
- return 0;
- }
- INT
- NetconGetDeviceInformation (
- DEVICE_ID DeviceId,
- PNETCON_DEVICE_DESCRIPTION Device
- )
- /*++
- Routine Description:
- This routine retrieves the network information for the given network device.
- Arguments:
- DeviceId - Supplies the device ID of the device whose information is to be
- retrieved.
- Device - Supplies a pointer to a network device descriptor that receives
- the retrieved device information.
- Return Value:
- 0 on success.
- Returns an error code on failure.
- --*/
- {
- UINTN DataSize;
- PNETWORK_80211_DEVICE_INFORMATION Net80211;
- PNETWORK_DEVICE_INFORMATION Network;
- PNETWORK_ADDRESS PhysicalAddress;
- KSTATUS Status;
- Device->Flags = 0;
- Device->DeviceId = DeviceId;
- PhysicalAddress = NULL;
- //
- // Get the IPv4 network information.
- //
- DataSize = sizeof(NETWORK_DEVICE_INFORMATION);
- Network = &(Device->NetworkIp4);
- Network->Version = NETWORK_DEVICE_INFORMATION_VERSION;
- Network->Domain = NetDomainIp4;
- Status = OsGetSetDeviceInformation(Device->DeviceId,
- &NetconDeviceInformationUuid,
- Network,
- &DataSize,
- FALSE);
- if (KSUCCESS(Status)) {
- Device->Flags |= NETCON_DEVICE_FLAG_IP4;
- PhysicalAddress = &(Network->PhysicalAddress);
- }
- //
- // Get the IPv6 network information.
- //
- DataSize = sizeof(NETWORK_DEVICE_INFORMATION);
- Network = &(Device->NetworkIp6);
- Network->Version = NETWORK_DEVICE_INFORMATION_VERSION;
- Network->Domain = NetDomainIp6;
- Status = OsGetSetDeviceInformation(Device->DeviceId,
- &NetconDeviceInformationUuid,
- Network,
- &DataSize,
- FALSE);
- if (KSUCCESS(Status)) {
- Device->Flags |= NETCON_DEVICE_FLAG_IP6;
- PhysicalAddress = &(Network->PhysicalAddress);
- }
- //
- // If the physical address is an 802.11 address, then attempt to get the
- // 802.11 information.
- //
- if ((PhysicalAddress != NULL) &&
- (PhysicalAddress->Domain == NetDomain80211)) {
- DataSize = sizeof(NETWORK_80211_DEVICE_INFORMATION);
- Net80211 = &(Device->Net80211);
- Net80211->Version = NETWORK_80211_DEVICE_INFORMATION_VERSION;
- Status = OsGetSetDeviceInformation(Device->DeviceId,
- &Netcon80211DeviceInformationUuid,
- Net80211,
- &DataSize,
- FALSE);
- if (!KSUCCESS(Status)) {
- goto GetDeviceInformationEnd;
- }
- Device->Flags |= NETCON_DEVICE_FLAG_80211;
- }
- Status = STATUS_SUCCESS;
- GetDeviceInformationEnd:
- return ClConvertKstatusToErrorNumber(Status);
- }
- VOID
- NetconJoinNetwork (
- PNETCON_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine attempts to join the network specified by the SSID in the
- given netcon context.
- Arguments:
- Context - Supplies a pointer to the network connection context.
- Return Value:
- None.
- --*/
- {
- USHORT FamilyId;
- PNL_MESSAGE_BUFFER Message;
- ULONG MessageLength;
- NL_RECEIVE_PARAMETERS Parameters;
- PSTR Password;
- UINTN PasswordLength;
- ULONG PayloadLength;
- PNL_SOCKET Socket;
- UINTN SsidLength;
- INT Status;
- Password = NULL;
- Socket = NULL;
- //
- // Validate the SSID.
- //
- SsidLength = strlen(Context->Ssid) + 1;
- if (SsidLength > (NET80211_MAX_SSID_LENGTH + 1)) {
- printf("netcon: SSID \"%s\" is too long. Max SSID length is %d.\n",
- Context->Ssid,
- NET80211_MAX_SSID_LENGTH);
- errno = EINVAL;
- Status = -1;
- goto JoinNetworkEnd;
- }
- //
- // If a password is required, get it now.
- //
- if ((Context->Flags & NETCON_FLAG_PASSWORD) != 0) {
- Password = getpass("Password: ");
- if (Password == NULL) {
- Status = -1;
- goto JoinNetworkEnd;
- }
- PasswordLength = strlen(Password) + 1;
- }
- Status = NlCreateSocket(NETLINK_GENERIC, NL_ANY_PORT_ID, 0, &Socket);
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- Status = NlGenericGetFamilyId(Socket,
- NETLINK_GENERIC_80211_NAME,
- &FamilyId);
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- //
- // Build out a message to join a network. This requires specifying the
- // device ID of the wireless networking device that is to join the network,
- // the SSID of the network and an optional passphrase.
- //
- PayloadLength = NETLINK_ATTRIBUTE_SIZE(sizeof(DEVICE_ID)) +
- NETLINK_ATTRIBUTE_SIZE(SsidLength);
- if (Password != NULL) {
- PayloadLength += NETLINK_ATTRIBUTE_SIZE(PasswordLength);
- }
- MessageLength = NETLINK_GENERIC_HEADER_LENGTH + PayloadLength;
- Status = NlAllocateBuffer(MessageLength, &Message);
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- Status = NlGenericAppendHeaders(Socket,
- Message,
- PayloadLength,
- 0,
- FamilyId,
- 0,
- NETLINK_80211_COMMAND_JOIN,
- 0);
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- Status = NlAppendAttribute(Message,
- NETLINK_80211_ATTRIBUTE_DEVICE_ID,
- &(Context->DeviceId),
- sizeof(DEVICE_ID));
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- Status = NlAppendAttribute(Message,
- NETLINK_80211_ATTRIBUTE_SSID,
- Context->Ssid,
- SsidLength);
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- if (Password != NULL) {
- Status = NlAppendAttribute(Message,
- NETLINK_80211_ATTRIBUTE_PASSPHRASE,
- Password,
- PasswordLength);
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- }
- //
- // Send off the request to join the given network.
- //
- Status = NlSendMessage(Socket, Message, NETLINK_KERNEL_PORT_ID, 0, NULL);
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- //
- // Wait for an acknowledgement message.
- //
- memset(&Parameters, 0, sizeof(NL_RECEIVE_PARAMETERS));
- Parameters.Flags |= NL_RECEIVE_FLAG_PORT_ID;
- Parameters.PortId = NETLINK_KERNEL_PORT_ID;
- Status = NlReceiveMessage(Socket, &Parameters);
- if (Status != 0) {
- goto JoinNetworkEnd;
- }
- JoinNetworkEnd:
- if (Password != NULL) {
- memset(Password, 0, strlen(Password));
- }
- if (Socket != NULL) {
- NlDestroySocket(Socket);
- }
- if (Status != 0) {
- perror("netcon: failed to join network");
- }
- return;
- }
- VOID
- NetconLeaveNetwork (
- PNETCON_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine attempts to leave the network to which the specified device
- is connected. The device is stored in the context structure.
- Arguments:
- Context - Supplies a pointer to the network connection context.
- Return Value:
- None.
- --*/
- {
- USHORT FamilyId;
- PNL_MESSAGE_BUFFER Message;
- ULONG MessageLength;
- NL_RECEIVE_PARAMETERS Parameters;
- ULONG PayloadLength;
- PNL_SOCKET Socket;
- INT Status;
- Status = NlCreateSocket(NETLINK_GENERIC, NL_ANY_PORT_ID, 0, &Socket);
- if (Status != 0) {
- goto LeaveNetworkEnd;
- }
- Status = NlGenericGetFamilyId(Socket,
- NETLINK_GENERIC_80211_NAME,
- &FamilyId);
- if (Status != 0) {
- goto LeaveNetworkEnd;
- }
- //
- // Build out a request to leave the current network on the given device.
- // This only requires supplying the device ID as an attribute.
- //
- PayloadLength = NETLINK_ATTRIBUTE_SIZE(sizeof(DEVICE_ID));
- MessageLength = NETLINK_GENERIC_HEADER_LENGTH + PayloadLength;
- Status = NlAllocateBuffer(MessageLength, &Message);
- if (Status != 0) {
- goto LeaveNetworkEnd;
- }
- Status = NlGenericAppendHeaders(Socket,
- Message,
- PayloadLength,
- 0,
- FamilyId,
- 0,
- NETLINK_80211_COMMAND_LEAVE,
- 0);
- if (Status != 0) {
- goto LeaveNetworkEnd;
- }
- Status = NlAppendAttribute(Message,
- NETLINK_80211_ATTRIBUTE_DEVICE_ID,
- &(Context->DeviceId),
- sizeof(DEVICE_ID));
- if (Status != 0) {
- goto LeaveNetworkEnd;
- }
- //
- // Send off the request to leave the current network.
- //
- Status = NlSendMessage(Socket, Message, NETLINK_KERNEL_PORT_ID, 0, NULL);
- if (Status != 0) {
- goto LeaveNetworkEnd;
- }
- //
- // Wait for an acknowledgement message.
- //
- memset(&Parameters, 0, sizeof(NL_RECEIVE_PARAMETERS));
- Parameters.Flags |= NL_RECEIVE_FLAG_PORT_ID;
- Parameters.PortId = NETLINK_KERNEL_PORT_ID;
- Status = NlReceiveMessage(Socket, &Parameters);
- if (Status != 0) {
- goto LeaveNetworkEnd;
- }
- LeaveNetworkEnd:
- if (Socket != NULL) {
- NlDestroySocket(Socket);
- }
- if (Status != 0) {
- perror("netcon: failed to leave network");
- }
- return;
- }
- VOID
- NetconScanForNetworks (
- PNETCON_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine scans for all the wireless networks that are within range of
- the device stored in the given context. It then prints them to standard out.
- Arguments:
- Context - Supplies a pointer to the network connection context.
- Return Value:
- None.
- --*/
- {
- BOOL AckReceived;
- USHORT FamilyId;
- ULONG Flags;
- PNL_MESSAGE_BUFFER Message;
- ULONG MessageLength;
- NL_RECEIVE_PARAMETERS Parameters;
- ULONG PayloadLength;
- NETCON_SCAN_RESULTS ScanResults;
- BOOL ScanResultsReady;
- PNL_SOCKET Socket;
- INT Status;
- Message = NULL;
- Status = NlCreateSocket(NETLINK_GENERIC, NL_ANY_PORT_ID, 0, &Socket);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- Status = NlGenericGetFamilyId(Socket,
- NETLINK_GENERIC_80211_NAME,
- &FamilyId);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- //
- // Join the 802.11 scan multicast group in order to get progress updates
- // from the scan.
- //
- Status = NlGenericJoinMulticastGroup(Socket,
- FamilyId,
- NETLINK_80211_MULTICAST_SCAN_NAME);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- //
- // Build and send a request to scan for all networks on the given device.
- // This only requires supplying the device ID as an attribute.
- //
- PayloadLength = NETLINK_ATTRIBUTE_SIZE(sizeof(DEVICE_ID));
- MessageLength = NETLINK_GENERIC_HEADER_LENGTH + PayloadLength;
- Status = NlAllocateBuffer(MessageLength, &Message);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- Status = NlGenericAppendHeaders(Socket,
- Message,
- PayloadLength,
- 0,
- FamilyId,
- 0,
- NETLINK_80211_COMMAND_SCAN_START,
- 0);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- Status = NlAppendAttribute(Message,
- NETLINK_80211_ATTRIBUTE_DEVICE_ID,
- &(Context->DeviceId),
- sizeof(DEVICE_ID));
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- Status = NlSendMessage(Socket, Message, NETLINK_KERNEL_PORT_ID, 0, NULL);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- NlFreeBuffer(Message);
- Message = NULL;
- //
- // Loop waiting for a few possible messages. The scan start request should
- // be acknowledged by the kernel. If the scan is acknowledged, then either
- // a scan aborted or scan results message should arrive. That is not to
- // say that the acknowledge will always come before a scan aborted or
- // results message.
- //
- memset(&Parameters, 0, sizeof(NL_RECEIVE_PARAMETERS));
- Parameters.ReceiveRoutine = NetconParseScanNotification;
- Parameters.ReceiveContext.Type = FamilyId;
- Parameters.ReceiveContext.PrivateContext = &ScanResultsReady;
- Parameters.PortId = NETLINK_KERNEL_PORT_ID;
- Flags = NL_RECEIVE_FLAG_PORT_ID;
- ScanResultsReady = FALSE;
- AckReceived = FALSE;
- while ((AckReceived == FALSE) || (ScanResultsReady == FALSE)) {
- Parameters.Flags = Flags;
- Status = NlReceiveMessage(Socket, &Parameters);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- if (Parameters.ReceiveContext.Status != 0) {
- Status = Parameters.ReceiveContext.Status;
- goto ScanForNetworksEnd;
- }
- //
- // If an ACK was received, make sure to stop waiting for one.
- //
- if ((Parameters.Flags & NL_RECEIVE_FLAG_ACK_RECEIVED) != 0) {
- AckReceived = TRUE;
- Flags |= NL_RECEIVE_FLAG_NO_ACK_WAIT;
- }
- }
- //
- // The scan has completed. Get the scan results and print them out for
- // the user. Start by building a scan results get request and sending that
- // off to the kernel.
- //
- Message = NULL;
- PayloadLength = NETLINK_ATTRIBUTE_SIZE(sizeof(DEVICE_ID));
- MessageLength = NETLINK_GENERIC_HEADER_LENGTH + PayloadLength;
- Status = NlAllocateBuffer(MessageLength, &Message);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- Status = NlGenericAppendHeaders(Socket,
- Message,
- PayloadLength,
- 0,
- FamilyId,
- NETLINK_HEADER_FLAG_DUMP,
- NETLINK_80211_COMMAND_SCAN_GET_RESULTS,
- 0);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- Status = NlAppendAttribute(Message,
- NETLINK_80211_ATTRIBUTE_DEVICE_ID,
- &(Context->DeviceId),
- sizeof(DEVICE_ID));
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- Status = NlSendMessage(Socket, Message, NETLINK_KERNEL_PORT_ID, 0, NULL);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- //
- // Now wait for the ACK and the results messages to come in.
- //
- memset(&Parameters, 0, sizeof(NL_RECEIVE_PARAMETERS));
- memset(&ScanResults, 0, sizeof(NETCON_SCAN_RESULTS));
- Parameters.ReceiveRoutine = NetconParseScanResult;
- Parameters.ReceiveContext.Type = FamilyId;
- Parameters.ReceiveContext.PrivateContext = &ScanResults;
- Parameters.PortId = NETLINK_KERNEL_PORT_ID;
- Flags = NL_RECEIVE_FLAG_PORT_ID;
- ScanResultsReady = FALSE;
- AckReceived = FALSE;
- while ((AckReceived == FALSE) || (ScanResults.Valid == FALSE)) {
- Parameters.Flags = Flags;
- Status = NlReceiveMessage(Socket, &Parameters);
- if (Status != 0) {
- goto ScanForNetworksEnd;
- }
- if (Parameters.ReceiveContext.Status != 0) {
- Status = Parameters.ReceiveContext.Status;
- goto ScanForNetworksEnd;
- }
- //
- // If an ACK was received, make sure to stop waiting for one.
- //
- if ((Parameters.Flags & NL_RECEIVE_FLAG_ACK_RECEIVED) != 0) {
- AckReceived = TRUE;
- Flags |= NL_RECEIVE_FLAG_NO_ACK_WAIT;
- }
- }
- //
- // Print out those scan results!
- //
- NetconPrintScanResults(Context, &ScanResults);
- ScanForNetworksEnd:
- if (Message != NULL) {
- NlFreeBuffer(Message);
- }
- if (Socket != NULL) {
- NlDestroySocket(Socket);
- }
- if (Status != 0) {
- perror("netcon: failed to scan for networks");
- }
- return;
- }
- VOID
- NetconParseScanNotification (
- PNL_SOCKET Socket,
- PNL_RECEIVE_CONTEXT Context,
- PVOID Message
- )
- /*++
- Routine Description:
- This routine parses a netlink message looking for a scan notification.
- Arguments:
- Socket - Supplies a pointer to the netlink socket that received the message.
- Context - Supplies a pointer to the receive context given to the receive
- message handler.
- Message - Supplies a pointer to the beginning of the netlink message. The
- length of which can be obtained from the header; it was already
- validated.
- Return Value:
- None.
- --*/
- {
- PNETLINK_GENERIC_HEADER GenericHeader;
- PNETLINK_HEADER Header;
- ULONG MessageLength;
- PBOOL ScanResultsReady;
- Header = (PNETLINK_HEADER)Message;
- //
- // Skip any messages that are not of the 802.11 family type.
- //
- if (Header->Type != Context->Type) {
- return;
- }
- //
- // Parse the generic header to determine the 802.11 command.
- //
- MessageLength = Header->Length;
- MessageLength -= NETLINK_HEADER_LENGTH;
- if (MessageLength < sizeof(NETLINK_GENERIC_HEADER)) {
- return;
- }
- //
- // Fail the scan request if the system aborted the scan.
- //
- GenericHeader = NETLINK_DATA(Header);
- if (GenericHeader->Command == NETLINK_80211_COMMAND_SCAN_ABORTED) {
- errno = ECANCELED;
- Context->Status = -1;
- //
- // If it is a scan result notification, mark that it has been seen.
- //
- } else if (GenericHeader->Command == NETLINK_80211_COMMAND_SCAN_RESULT) {
- ScanResultsReady = (PBOOL)Context->PrivateContext;
- *ScanResultsReady = TRUE;
- Context->Status = 0;
- }
- return;
- }
- VOID
- NetconParseScanResult (
- PNL_SOCKET Socket,
- PNL_RECEIVE_CONTEXT Context,
- PVOID Message
- )
- /*++
- Routine Description:
- This routine parses a netlink message looking for a scan result.
- Arguments:
- Socket - Supplies a pointer to the netlink socket that received the message.
- Context - Supplies a pointer to the receive context given to the receive
- message handler.
- Message - Supplies a pointer to the beginning of the netlink message. The
- length of which can be obtained from the header; it was already
- validated.
- Return Value:
- None.
- --*/
- {
- USHORT AttributeLength;
- PVOID Attributes;
- PUSHORT BeaconInterval;
- PNETCON_BSS Bss;
- PNETCON_BSS *BssArray;
- PVOID BssAttribute;
- USHORT BssAttributeLength;
- ULONG BssCount;
- PVOID Bssid;
- PULONG BssStatus;
- PUSHORT Capabilities;
- PVOID Elements;
- USHORT ElementsSize;
- PNETLINK_GENERIC_HEADER GenericHeader;
- PNETLINK_HEADER Header;
- ULONG MessageLength;
- PNETCON_SCAN_RESULTS ScanResults;
- PLONG SignalMbm;
- KSTATUS Status;
- Bss = NULL;
- Header = (PNETLINK_HEADER)Message;
- Status = 0;
- //
- // Skip any messages that are not of the 802.11 family type.
- //
- if (Header->Type != Context->Type) {
- goto ParseScanResultEnd;
- }
- //
- // Parse the generic header to determine the 802.11 command and toss
- // anything that isn't a scan result.
- //
- MessageLength = Header->Length;
- MessageLength -= NETLINK_HEADER_LENGTH;
- if (MessageLength < sizeof(NETLINK_GENERIC_HEADER)) {
- goto ParseScanResultEnd;
- }
- GenericHeader = NETLINK_DATA(Header);
- if (GenericHeader->Command != NETLINK_80211_COMMAND_SCAN_RESULT) {
- goto ParseScanResultEnd;
- }
- //
- // Get the BSS region of the attributes.
- //
- MessageLength -= NETLINK_GENERIC_HEADER_LENGTH;
- Attributes = NETLINK_GENERIC_DATA(GenericHeader);
- Status = NlGetAttribute(Attributes,
- MessageLength,
- NETLINK_80211_ATTRIBUTE_BSS,
- &BssAttribute,
- &BssAttributeLength);
- if (Status != 0) {
- goto ParseScanResultEnd;
- }
- Status = NlGetAttribute(BssAttribute,
- BssAttributeLength,
- NETLINK_80211_BSS_ATTRIBUTE_BSSID,
- &Bssid,
- &AttributeLength);
- if (Status != 0) {
- goto ParseScanResultEnd;
- }
- if (AttributeLength != NET80211_ADDRESS_SIZE) {
- errno = ERANGE;
- Status = -1;
- goto ParseScanResultEnd;
- }
- Status = NlGetAttribute(BssAttribute,
- BssAttributeLength,
- NETLINK_80211_BSS_ATTRIBUTE_CAPABILITY,
- (PVOID *)&Capabilities,
- &AttributeLength);
- if (Status != 0) {
- goto ParseScanResultEnd;
- }
- if (AttributeLength != sizeof(USHORT)) {
- errno = ERANGE;
- Status = -1;
- goto ParseScanResultEnd;
- }
- Status = NlGetAttribute(BssAttribute,
- BssAttributeLength,
- NETLINK_80211_BSS_ATTRIBUTE_BEACON_INTERVAL,
- (PVOID *)&BeaconInterval,
- &AttributeLength);
- if (Status != 0) {
- goto ParseScanResultEnd;
- }
- if (AttributeLength != sizeof(USHORT)) {
- errno = ERANGE;
- Status = -1;
- goto ParseScanResultEnd;
- }
- Status = NlGetAttribute(BssAttribute,
- BssAttributeLength,
- NETLINK_80211_BSS_ATTRIBUTE_SIGNAL_MBM,
- (PVOID *)&SignalMbm,
- &AttributeLength);
- if (Status != 0) {
- goto ParseScanResultEnd;
- }
- if (AttributeLength != sizeof(LONG)) {
- errno = ERANGE;
- Status = -1;
- goto ParseScanResultEnd;
- }
- Status = NlGetAttribute(BssAttribute,
- BssAttributeLength,
- NETLINK_80211_BSS_ATTRIBUTE_SIGNAL_MBM,
- (PVOID *)&BssStatus,
- &AttributeLength);
- if (Status != 0) {
- goto ParseScanResultEnd;
- }
- if (AttributeLength != sizeof(ULONG)) {
- errno = ERANGE;
- Status = -1;
- goto ParseScanResultEnd;
- }
- Status = NlGetAttribute(BssAttribute,
- BssAttributeLength,
- NETLINK_80211_BSS_ATTRIBUTE_INFORMATION_ELEMENTS,
- &Elements,
- &ElementsSize);
- if (Status != 0) {
- goto ParseScanResultEnd;
- }
- //
- // Allocate a new BSS element and fill it out with the information
- // collected above.
- //
- Bss = malloc(sizeof(NETCON_BSS) + ElementsSize);
- if (Bss == NULL) {
- goto ParseScanResultEnd;
- }
- memset(Bss, 0, sizeof(NETCON_BSS));
- Bss->Bssid.Domain = NetDomain80211;
- memcpy(Bss->Bssid.Address, Bssid, NET80211_ADDRESS_SIZE);
- Bss->SignalStrength = *SignalMbm;
- Bss->Status = *BssStatus;
- Bss->BeaconInterval = *BeaconInterval;
- Bss->Capabilities = *Capabilities;
- Bss->Elements = Bss + 1;
- Bss->ElementsSize = ElementsSize;
- memcpy(Bss->Elements, Elements, ElementsSize);
- //
- // Expand the scan results array to incorporate this BSS element.
- //
- ScanResults = (PNETCON_SCAN_RESULTS)Context->PrivateContext;
- BssCount = ScanResults->BssCount + 1;
- BssArray = realloc(ScanResults->BssArray,
- BssCount * sizeof(PNETCON_BSS));
- if (BssArray == NULL) {
- ScanResults->BssCount = 0;
- Status = -1;
- goto ParseScanResultEnd;
- }
- ScanResults->BssArray = BssArray;
- ScanResults->BssCount = BssCount;
- ScanResults->BssArray[BssCount - 1] = Bss;
- ScanResults->Valid = TRUE;
- ParseScanResultEnd:
- if (Status != 0) {
- if (Bss != NULL) {
- free(Bss);
- }
- }
- return;
- }
- VOID
- NetconPrintScanResults (
- PNETCON_CONTEXT Context,
- PNETCON_SCAN_RESULTS Results
- )
- /*++
- Routine Description:
- This routine prints the given scan results list to standard out.
- Arguments:
- Context - Supplies a pointer to the network connection context.
- Results - Supplies a pointer to the network scan results.
- Return Value:
- None.
- --*/
- {
- PNETCON_BSS Bss;
- PVOID Channel;
- ULONG Index;
- PVOID RatesElement;
- PVOID Rsn;
- UCHAR Ssid[NET80211_MAX_SSID_LENGTH + 1];
- PVOID SsidElement;
- ULONG SsidLength;
- printf("Device 0x%I64x:\n", Context->DeviceId);
- printf("Networks Visisble: %d\n\n", Results->BssCount);
- for (Index = 0; Index < Results->BssCount; Index += 1) {
- Bss = Results->BssArray[Index];
- SsidElement = NetconGet80211InformationElement(Bss->Elements,
- Bss->ElementsSize,
- NET80211_ELEMENT_SSID);
- SsidLength = 0;
- if (SsidElement != NULL) {
- SsidLength = NET80211_GET_ELEMENT_LENGTH(SsidElement);
- memcpy(Ssid, NET80211_GET_ELEMENT_DATA(SsidElement), SsidLength);
- }
- Ssid[SsidLength] = STRING_TERMINATOR;
- printf("SSID %d: %s\n", Index, Ssid);
- if (Bss->Status == NETLINK_80211_BSS_STATUS_ASSOCIATED) {
- printf("\tStatus: Connected\n");
- }
- Rsn = NetconGet80211InformationElement(Bss->Elements,
- Bss->ElementsSize,
- NET80211_ELEMENT_RSN);
- if (Rsn != NULL) {
- NetconPrintRsnInformation(Rsn);
- } else {
- printf("\tAuthentication: Open\n");
- printf("\tEncryption: None\n");
- }
- if ((Context->Flags & NETCON_FLAG_VERBOSE) == 0) {
- printf("\n");
- continue;
- }
- printf("\tBSSID: ");
- NetconPrintAddress(&(Bss->Bssid));
- NetconPrintRssi(Bss->SignalStrength / 100);
- Channel = NetconGet80211InformationElement(Bss->Elements,
- Bss->ElementsSize,
- NET80211_ELEMENT_DSSS);
- if (Channel != NULL) {
- printf("\tChannel: %d\n", *NET80211_GET_ELEMENT_DATA(Channel));
- }
- printf("\tBeacon Interval: %d ms\n", Bss->BeaconInterval);
- printf("\tCapabilities: 0x%04x\n", Bss->Capabilities);
- RatesElement = NetconGet80211InformationElement(
- Bss->Elements,
- Bss->ElementsSize,
- NET80211_ELEMENT_SUPPORTED_RATES);
- if (RatesElement != NULL) {
- printf("\tSupported Rates (Mbps):");
- NetconPrintRates(RatesElement);
- }
- RatesElement = NetconGet80211InformationElement(
- Bss->Elements,
- Bss->ElementsSize,
- NET80211_ELEMENT_EXTENDED_SUPPORTED_RATES);
- if (RatesElement != NULL) {
- printf("\tExtended Rates (Mbps):");
- NetconPrintRates(RatesElement);
- }
- printf("\n");
- }
- return;
- }
- PVOID
- NetconGet80211InformationElement (
- PVOID Elements,
- ULONG ElementsSize,
- UCHAR ElementId
- )
- /*++
- Routine Description:
- This routine searches the given information element buffer for the element
- with the given ID, returning a pointer to the element's header.
- Arguments:
- Elements - Supplies a pointer to the set of information elements to search.
- ElementsSize - Supplies the size of the informatin elements, in bytes.
- ElementId - Supplies the ID of the element to lookup.
- Return Value:
- Returns a pointer to the information element on success or NULL on failure.
- --*/
- {
- PVOID Element;
- ULONG ElementLength;
- PVOID FoundElement;
- ULONG RemainingSize;
- FoundElement = NULL;
- //
- // A valid element must have at least two bytes - the ID and the length.
- //
- Element = Elements;
- RemainingSize = ElementsSize;
- while (RemainingSize >= NET80211_ELEMENT_HEADER_SIZE) {
- ElementLength = NET80211_GET_ELEMENT_LENGTH(Element) +
- NET80211_ELEMENT_HEADER_SIZE;
- if (ElementLength > RemainingSize) {
- break;
- }
- if (NET80211_GET_ELEMENT_ID(Element) == ElementId) {
- FoundElement = Element;
- break;
- }
- RemainingSize -= ElementLength;
- Element += ElementLength;
- }
- return FoundElement;
- }
- VOID
- NetconPrintRsnInformation (
- PUCHAR Rsn
- )
- /*++
- Routine Description:
- This routine prints the encryption information encapsulated by the RSN
- information element.
- Arguments:
- Rsn - Supplies a pointer to the RSN element, the first byte of which is the
- element ID.
- Return Value:
- None.
- --*/
- {
- ULONG AkmSuite;
- ULONG AkmSuiteCount;
- PULONG AkmSuites;
- NETWORK_ENCRYPTION_TYPE Authentication;
- ULONG GroupSuite;
- ULONG Index;
- ULONG Offset;
- ULONG PairwiseSuite;
- ULONG PairwiseSuiteCount;
- PULONG PairwiseSuites;
- ULONG RsnLength;
- INT Status;
- ULONG Suite;
- USHORT Version;
- ASSERT(NET80211_GET_ELEMENT_ID(Rsn) == NET80211_ELEMENT_RSN);
- Status = 0;
- Offset = NET80211_ELEMENT_HEADER_SIZE;
- RsnLength = NET80211_GET_ELEMENT_LENGTH(Rsn);
- AkmSuite = 0;
- GroupSuite = 0;
- PairwiseSuite = 0;
- PairwiseSuites = NULL;
- //
- // The version field is the only non-optional field.
- //
- if ((Offset + sizeof(USHORT)) > RsnLength) {
- Status = -1;
- goto PrintRsnInformationEnd;
- }
- Version = *((PUSHORT)&(Rsn[Offset]));
- Offset += sizeof(USHORT);
- if (Version != NET80211_RSN_VERSION) {
- Status = -1;
- goto PrintRsnInformationEnd;
- }
- //
- // Save the group suite if it is present.
- //
- if ((Offset + sizeof(ULONG)) > RsnLength) {
- goto PrintRsnInformationEnd;
- }
- GroupSuite = NETWORK_TO_CPU32(*((PULONG)&(Rsn[Offset])));
- Offset += sizeof(ULONG);
- //
- // Save a pointer to the pairwise suites, if present.
- //
- if ((Offset + sizeof(USHORT)) > RsnLength) {
- goto PrintRsnInformationEnd;
- }
- PairwiseSuiteCount = *((PUSHORT)&(Rsn[Offset]));
- Offset += sizeof(USHORT);
- if ((Offset + (sizeof(ULONG) * PairwiseSuiteCount)) > RsnLength) {
- goto PrintRsnInformationEnd;
- }
- PairwiseSuites = (PULONG)&(Rsn[Offset]);
- Offset += sizeof(ULONG) * PairwiseSuiteCount;
- //
- // Run through the pairwise suites to determine the most secure option.
- //
- for (Index = 0; Index < PairwiseSuiteCount; Index += 1) {
- Suite = NETWORK_TO_CPU32(PairwiseSuites[Index]);
- //
- // CCMP is always the highest.
- //
- if (Suite == NET80211_CIPHER_SUITE_CCMP) {
- PairwiseSuite = Suite;
- break;
- }
- //
- // TKIP beats nothing and WEP.
- //
- if ((Suite == NET80211_CIPHER_SUITE_TKIP) &&
- ((PairwiseSuite == 0) ||
- (PairwiseSuite == NET80211_CIPHER_SUITE_WEP_40) ||
- (PairwiseSuite == NET80211_CIPHER_SUITE_WEP_104))) {
- PairwiseSuite = Suite;
- }
- //
- // WEP only beats nothing.
- //
- if ((PairwiseSuite == 0) &&
- ((Suite == NET80211_CIPHER_SUITE_WEP_40) ||
- (Suite == NET80211_CIPHER_SUITE_WEP_104))) {
- PairwiseSuite = Suite;
- }
- }
- //
- // The PSK authentication and key management (AKM) must be one of the
- // optional AKM suites.
- //
- if ((Offset + sizeof(USHORT)) > RsnLength) {
- goto PrintRsnInformationEnd;
- }
- AkmSuiteCount = *((PUSHORT)&(Rsn[Offset]));
- Offset += sizeof(USHORT);
- if ((Offset + (AkmSuiteCount * sizeof(ULONG))) > RsnLength) {
- goto PrintRsnInformationEnd;
- }
- AkmSuites = (PULONG)&(Rsn[Offset]);
- for (Index = 0; Index < AkmSuiteCount; Index += 1) {
- Suite = NETWORK_TO_CPU32(AkmSuites[Index]);
- if ((Suite == NET80211_AKM_SUITE_PSK) ||
- (Suite == NET80211_AKM_SUITE_PSK_SHA256)) {
- AkmSuite = Suite;
- break;
- }
- if ((Suite == NET80211_AKM_SUITE_8021X) ||
- (Suite == NET80211_AKM_SUITE_8021X_SHA256)) {
- AkmSuite = Suite;
- break;
- }
- }
- Offset += sizeof(ULONG) * AkmSuiteCount;
- PrintRsnInformationEnd:
- if (Status != 0) {
- printf("\tAuthentication: unknown\n");
- } else {
- Authentication = NetworkEncryptionInvalid;
- switch (PairwiseSuite) {
- case NET80211_CIPHER_SUITE_WEP_40:
- case NET80211_CIPHER_SUITE_WEP_104:
- Authentication = NetworkEncryptionWep;
- break;
- case NET80211_CIPHER_SUITE_TKIP:
- switch (AkmSuite) {
- case NET80211_AKM_SUITE_PSK:
- case NET80211_AKM_SUITE_PSK_SHA256:
- Authentication = NetworkEncryptionWpaPsk;
- break;
- case NET80211_AKM_SUITE_8021X:
- case NET80211_AKM_SUITE_8021X_SHA256:
- Authentication = NetworkEncryptionWpaEap;
- break;
- default:
- break;
- }
- break;
- case NET80211_CIPHER_SUITE_CCMP:
- switch (AkmSuite) {
- case NET80211_AKM_SUITE_PSK:
- case NET80211_AKM_SUITE_PSK_SHA256:
- Authentication = NetworkEncryptionWpa2Psk;
- break;
- case NET80211_AKM_SUITE_8021X:
- case NET80211_AKM_SUITE_8021X_SHA256:
- Authentication = NetworkEncryptionWpa2Eap;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- printf("\tAuthentication: ");
- NetconPrintEncryption(Authentication);
- if (PairwiseSuites != NULL) {
- printf("\tPairwise Encryption:");
- for (Index = 0; Index < PairwiseSuiteCount; Index += 1) {
- Suite = NETWORK_TO_CPU32(PairwiseSuites[Index]);
- printf(" ");
- NetconPrintCipherSuite(Suite);
- }
- printf("\n");
- }
- if ((GroupSuite != 0) &&
- (GroupSuite != NET80211_CIPHER_SUITE_GROUP_NOT_ALLOWED)) {
- printf("\tGroup Encryption: ");
- NetconPrintCipherSuite(GroupSuite);
- printf("\n");
- }
- }
- return;
- }
- VOID
- NetconPrintDeviceInformation (
- PNETCON_DEVICE_DESCRIPTION Device
- )
- /*++
- Routine Description:
- This routine prints out the network information for the given device.
- Arguments:
- Device - Supplies a pointer to the network device whose information is to
- be printed.
- Return Value:
- None.
- --*/
- {
- NETWORK_ADDRESS_CONFIGURATION_METHOD Configuration;
- PNETWORK_80211_DEVICE_INFORMATION Net80211;
- PNETWORK_DEVICE_INFORMATION Network;
- PNETWORK_ADDRESS PhysicalAddress;
- printf("Network Device 0x%I64x:\n", Device->DeviceId);
- PhysicalAddress = NULL;
- if ((Device->Flags & NETCON_DEVICE_FLAG_IP4) != 0) {
- PhysicalAddress = &(Device->NetworkIp4.PhysicalAddress);
- } else if ((Device->Flags & NETCON_DEVICE_FLAG_IP6) == 0) {
- PhysicalAddress = &(Device->NetworkIp6.PhysicalAddress);
- }
- if (PhysicalAddress == NULL) {
- return;
- }
- //
- // The physical address should always be present.
- //
- printf("\tPhysical Address: ");
- NetconPrintAddress(PhysicalAddress);
- //
- // Print the IPv4 address line to show that the device is IPv4 capable, but
- // only print the actual address if it is configured.
- //
- if ((Device->Flags & NETCON_DEVICE_FLAG_IP4) != 0) {
- printf("\tIPv4 Address: ");
- Network = &(Device->NetworkIp4);
- Configuration = Network->ConfigurationMethod;
- if ((Configuration != NetworkAddressConfigurationInvalid) &&
- (Configuration != NetworkAddressConfigurationNone)) {
- NetconPrintAddress(&(Network->Address));
- printf("\tSubnet Mask: ");
- NetconPrintAddress(&(Network->Subnet));
- printf("\tGateway: ");
- NetconPrintAddress(&(Network->Gateway));
- } else {
- printf("(not configured)\n");
- }
- }
- //
- // Print the IPv6 address line to show that the device is IPv4 capable, but
- // only print the actual address if it is configured.
- //
- if ((Device->Flags & NETCON_DEVICE_FLAG_IP6) != 0) {
- printf("\tIPv6 Address: ");
- Network = &(Device->NetworkIp6);
- Configuration = Network->ConfigurationMethod;
- if ((Configuration != NetworkAddressConfigurationInvalid) &&
- (Configuration != NetworkAddressConfigurationNone)) {
- NetconPrintAddress(&(Network->Address));
- printf("\tSubnet Mask: ");
- NetconPrintAddress(&(Network->Subnet));
- printf("\tGateway: ");
- NetconPrintAddress(&(Network->Gateway));
- } else {
- printf("(not configured)\n");
- }
- }
- //
- // If the device supports 802.11, at least print the SSID or
- // "Not Associated".
- //
- if ((Device->Flags & NETCON_DEVICE_FLAG_80211) != 0) {
- Net80211 = &(Device->Net80211);
- printf("\tSSID: ");
- if ((Net80211->Flags & NETWORK_80211_DEVICE_FLAG_ASSOCIATED) != 0) {
- printf("\"%s\"\n", Net80211->Ssid);
- printf("\tBSSID: ");
- NetconPrintAddress(&(Net80211->Bssid));
- printf("\tChannel: %d\n", Net80211->Channel);
- printf("\tMax Rate: %.1f Mbps\n",
- (double)Net80211->MaxRate / 1000000ULL);
- NetconPrintRssi(Net80211->Rssi);
- printf("\tPairwise Encryption: ");
- NetconPrintEncryption(Net80211->PairwiseEncryption);
- printf("\tGroup Encryption: ");
- NetconPrintEncryption(Net80211->GroupEncryption);
- } else {
- printf("(not associated)\n");
- }
- }
- printf("\n");
- return;
- }
- VOID
- NetconPrintAddress (
- PNETWORK_ADDRESS Address
- )
- /*++
- Routine Description:
- This routine prints the given network address to standard out.
- Arguments:
- Address - Supplies a pointer to the network address to print.
- Return Value:
- None.
- --*/
- {
- socklen_t AddressLength;
- PUCHAR BytePointer;
- struct sockaddr_in Ip4Address;
- struct sockaddr_in6 Ip6Address;
- CHAR PrintBuffer[60];
- KSTATUS Status;
- switch (Address->Domain) {
- case NetDomainIp4:
- AddressLength = sizeof(struct sockaddr_in);
- Status = ClConvertFromNetworkAddress(Address,
- (struct sockaddr *)&Ip4Address,
- &AddressLength,
- NULL,
- 0);
- if (!KSUCCESS(Status)) {
- break;
- }
- inet_ntop(Ip4Address.sin_family,
- &(Ip4Address.sin_addr.s_addr),
- PrintBuffer,
- sizeof(PrintBuffer));
- printf("%s", PrintBuffer);
- break;
- case NetDomainIp6:
- AddressLength = sizeof(struct sockaddr_in6);
- Status = ClConvertFromNetworkAddress(Address,
- (struct sockaddr *)&Ip6Address,
- &AddressLength,
- NULL,
- 0);
- if (!KSUCCESS(Status)) {
- break;
- }
- inet_ntop(Ip6Address.sin6_family,
- &(Ip6Address.sin6_addr.s6_addr),
- PrintBuffer,
- sizeof(PrintBuffer));
- printf("%s", PrintBuffer);
- break;
- case NetDomain80211:
- case NetDomainEthernet:
- BytePointer = (PUCHAR)(Address->Address);
- printf("%02X:%02X:%02X:%02X:%02X:%02X",
- BytePointer[0],
- BytePointer[1],
- BytePointer[2],
- BytePointer[3],
- BytePointer[4],
- BytePointer[5]);
- break;
- default:
- break;
- }
- printf("\n");
- return;
- }
- VOID
- NetconPrintEncryption (
- NETWORK_ENCRYPTION_TYPE EncryptionType
- )
- /*++
- Routine Description:
- This routine prints the name of the given encryption type.
- Arguments:
- EncryptionType - Supplies the encryption type to print.
- Return Value:
- None.
- --*/
- {
- switch (EncryptionType) {
- case NetworkEncryptionNone:
- printf("none");
- break;
- case NetworkEncryptionWep:
- printf("WEP");
- break;
- case NetworkEncryptionWpaPsk:
- printf("WPA-PSK");
- break;
- case NetworkEncryptionWpaEap:
- printf("WPA-EAP");
- break;
- case NetworkEncryptionWpa2Psk:
- printf("WPA2-PSK");
- break;
- case NetworkEncryptionWpa2Eap:
- printf("WPA2-EAP");
- break;
- default:
- printf("unknown");
- break;
- }
- printf("\n");
- return;
- }
- VOID
- NetconPrintCipherSuite (
- ULONG Suite
- )
- /*++
- Routine Description:
- This routine prints the name of the given cipher suite.
- Arguments:
- Suite - Supplies the cipher suite to print.
- Return Value:
- None.
- --*/
- {
- switch (Suite) {
- case NET80211_CIPHER_SUITE_USE_GROUP_CIPHER:
- printf("Group Only");
- break;
- case NET80211_CIPHER_SUITE_WEP_40:
- printf("WEP-40");
- break;
- case NET80211_CIPHER_SUITE_TKIP:
- printf("TKIP");
- break;
- case NET80211_CIPHER_SUITE_CCMP:
- printf("CCMP");
- break;
- case NET80211_CIPHER_SUITE_WEP_104:
- printf("WEP-104");
- break;
- case NET80211_CIPHER_SUITE_BIP:
- printf("BIP");
- break;
- default:
- printf("unknown");
- break;
- }
- return;
- }
- VOID
- NetconPrintRssi (
- LONG Rssi
- )
- /*++
- Routine Description:
- This routine prints the signal strength out to standard out.
- Arguments:
- Rssi - Supplies the RSSI value for signal strength in dBm.
- Return Value:
- None.
- --*/
- {
- ULONG Percentage;
- if (Rssi < -100) {
- Percentage = 0;
- } else if (Rssi > -50) {
- Percentage = 100;
- } else {
- Percentage = 2 * (Rssi + 100);
- }
- printf("\tSignal Strength: %d%% (%d dBm)\n", Percentage, Rssi);
- return;
- }
- VOID
- NetconPrintRates (
- PVOID RatesElement
- )
- /*++
- Routine Description:
- This routine prints out each rate stored in the given rate information
- element. That values are printed out in Mbps.
- Arguments:
- RatesElement - Supplies a pointer to the rates element to print.
- Return Value:
- None.
- --*/
- {
- ULONG Index;
- ULONG Rate;
- PUCHAR Rates;
- Rates = NET80211_GET_ELEMENT_DATA(RatesElement);
- for (Index = 0;
- Index < NET80211_GET_ELEMENT_LENGTH(RatesElement);
- Index += 1) {
- Rate = Rates[Index] & NET80211_RATE_VALUE_MASK;
- Rate *= NET80211_RATE_UNIT;
- if ((Rate % 1000000) == 0) {
- printf(" %d", Rate / 1000000);
- } else {
- printf(" %.1f", (double)Rate / 1000000);
- }
- }
- printf("\n");
- return;
- }
- INT
- NetconGet80211DeviceId (
- PDEVICE_ID DeviceId
- )
- /*++
- Routine Description:
- This routine gets the device ID of the system's 802.11 device. If there
- are multiple 802.11 devices then it prints an error and the available
- wireless devices.
- Arguments:
- DeviceId - Supplies a pointer that receives the 802.11 device's ID.
- Return Value:
- 0 on success.
- Returns an error code on failure.
- --*/
- {
- PNETCON_DEVICE_DESCRIPTION DeviceArray;
- ULONG DeviceCount;
- ULONG Index;
- ULONG Net80211DeviceCount;
- ULONG Net80211DeviceIndex;
- INT Result;
- Result = NetconEnumerateDevices(&DeviceArray, &DeviceCount);
- if (Result != 0) {
- return Result;
- }
- Net80211DeviceIndex = 0;
- Net80211DeviceCount = 0;
- for (Index = 0; Index < DeviceCount; Index += 1) {
- if ((DeviceArray[Index].Flags & NETCON_DEVICE_FLAG_80211) != 0) {
- Net80211DeviceCount += 1;
- Net80211DeviceIndex = Index;
- }
- }
- if (Net80211DeviceCount == 0) {
- printf("netcon: failed to find a wireless device.\n");
- Result = ENODEV;
- } else if (Net80211DeviceCount == 1) {
- *DeviceId = DeviceArray[Net80211DeviceIndex].DeviceId;
- } else {
- printf("There are %d wireless devices available. Please specify "
- "a device ID with the -d parameter.\n",
- Net80211DeviceCount);
- printf("Wireless Devices:\n\n");
- for (Index = 0; Index < DeviceCount; Index += 1) {
- if ((DeviceArray[Index].Flags & NETCON_DEVICE_FLAG_80211) != 0) {
- NetconPrintDeviceInformation(&(DeviceArray[Index]));
- printf("\n");
- }
- }
- Result = ENODEV;
- }
- free(DeviceArray);
- return Result;
- }
|