123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217 |
- /*
- * Wireless Tools
- *
- * Jean II - HPLB '99 - HPL 99->07
- *
- * This tool can access various piece of information on the card
- * not part of iwconfig...
- * You need to link this code against "iwlist.c" and "-lm".
- *
- * This file is released under the GPL license.
- * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
- */
- #include "iwlib.h" /* Header */
- #include <sys/time.h>
- /****************************** TYPES ******************************/
- /*
- * Scan state and meta-information, used to decode events...
- */
- typedef struct iwscan_state
- {
- /* State */
- int ap_num; /* Access Point number 1->N */
- int val_index; /* Value in table 0->(N-1) */
- } iwscan_state;
- /*
- * Bit to name mapping
- */
- typedef struct iwmask_name
- {
- unsigned int mask; /* bit mask for the value */
- const char * name; /* human readable name for the value */
- } iwmask_name;
- /*
- * Types of authentication parameters
- */
- typedef struct iw_auth_descr
- {
- int value; /* Type of auth value */
- const char * label; /* User readable version */
- const struct iwmask_name * names; /* Names for this value */
- const int num_names; /* Number of names */
- } iw_auth_descr;
- /**************************** CONSTANTS ****************************/
- #define IW_SCAN_HACK 0x8000
- #define IW_EXTKEY_SIZE (sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX)
- /* ------------------------ WPA CAPA NAMES ------------------------ */
- /*
- * This is the user readable name of a bunch of WPA constants in wireless.h
- * Maybe this should go in iwlib.c ?
- */
- #ifndef WE_ESSENTIAL
- #define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0]))
- //static const struct iwmask_name iw_enc_mode_name[] = {
- // { IW_ENCODE_RESTRICTED, "restricted" },
- // { IW_ENCODE_OPEN, "open" },
- //};
- //#define IW_ENC_MODE_NUM IW_ARRAY_LEN(iw_enc_mode_name)
- static const struct iwmask_name iw_auth_capa_name[] = {
- { IW_ENC_CAPA_WPA, "WPA" },
- { IW_ENC_CAPA_WPA2, "WPA2" },
- { IW_ENC_CAPA_CIPHER_TKIP, "CIPHER-TKIP" },
- { IW_ENC_CAPA_CIPHER_CCMP, "CIPHER-CCMP" },
- };
- #define IW_AUTH_CAPA_NUM IW_ARRAY_LEN(iw_auth_capa_name)
- static const struct iwmask_name iw_auth_cypher_name[] = {
- { IW_AUTH_CIPHER_NONE, "none" },
- { IW_AUTH_CIPHER_WEP40, "WEP-40" },
- { IW_AUTH_CIPHER_TKIP, "TKIP" },
- { IW_AUTH_CIPHER_CCMP, "CCMP" },
- { IW_AUTH_CIPHER_WEP104, "WEP-104" },
- };
- #define IW_AUTH_CYPHER_NUM IW_ARRAY_LEN(iw_auth_cypher_name)
- static const struct iwmask_name iw_wpa_ver_name[] = {
- { IW_AUTH_WPA_VERSION_DISABLED, "disabled" },
- { IW_AUTH_WPA_VERSION_WPA, "WPA" },
- { IW_AUTH_WPA_VERSION_WPA2, "WPA2" },
- };
- #define IW_WPA_VER_NUM IW_ARRAY_LEN(iw_wpa_ver_name)
- static const struct iwmask_name iw_auth_key_mgmt_name[] = {
- { IW_AUTH_KEY_MGMT_802_1X, "802.1x" },
- { IW_AUTH_KEY_MGMT_PSK, "PSK" },
- };
- #define IW_AUTH_KEY_MGMT_NUM IW_ARRAY_LEN(iw_auth_key_mgmt_name)
- static const struct iwmask_name iw_auth_alg_name[] = {
- { IW_AUTH_ALG_OPEN_SYSTEM, "open" },
- { IW_AUTH_ALG_SHARED_KEY, "shared-key" },
- { IW_AUTH_ALG_LEAP, "LEAP" },
- };
- #define IW_AUTH_ALG_NUM IW_ARRAY_LEN(iw_auth_alg_name)
- static const struct iw_auth_descr iw_auth_settings[] = {
- { IW_AUTH_WPA_VERSION, "WPA version", iw_wpa_ver_name, IW_WPA_VER_NUM },
- { IW_AUTH_KEY_MGMT, "Key management", iw_auth_key_mgmt_name, IW_AUTH_KEY_MGMT_NUM },
- { IW_AUTH_CIPHER_PAIRWISE, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
- { IW_AUTH_CIPHER_GROUP, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
- { IW_AUTH_TKIP_COUNTERMEASURES, "TKIP countermeasures", NULL, 0 },
- { IW_AUTH_DROP_UNENCRYPTED, "Drop unencrypted", NULL, 0 },
- { IW_AUTH_80211_AUTH_ALG, "Authentication algorithm", iw_auth_alg_name, IW_AUTH_ALG_NUM },
- { IW_AUTH_RX_UNENCRYPTED_EAPOL, "Receive unencrypted EAPOL", NULL, 0 },
- { IW_AUTH_ROAMING_CONTROL, "Roaming control", NULL, 0 },
- { IW_AUTH_PRIVACY_INVOKED, "Privacy invoked", NULL, 0 },
- };
- #define IW_AUTH_SETTINGS_NUM IW_ARRAY_LEN(iw_auth_settings)
- /* Values for the IW_ENCODE_ALG_* returned by SIOCSIWENCODEEXT */
- static const char * iw_encode_alg_name[] = {
- "none",
- "WEP",
- "TKIP",
- "CCMP",
- "unknown"
- };
- #define IW_ENCODE_ALG_NUM IW_ARRAY_LEN(iw_encode_alg_name)
- #ifndef IW_IE_CIPHER_NONE
- /* Cypher values in GENIE (pairwise and group) */
- #define IW_IE_CIPHER_NONE 0
- #define IW_IE_CIPHER_WEP40 1
- #define IW_IE_CIPHER_TKIP 2
- #define IW_IE_CIPHER_WRAP 3
- #define IW_IE_CIPHER_CCMP 4
- #define IW_IE_CIPHER_WEP104 5
- /* Key management in GENIE */
- #define IW_IE_KEY_MGMT_NONE 0
- #define IW_IE_KEY_MGMT_802_1X 1
- #define IW_IE_KEY_MGMT_PSK 2
- #endif /* IW_IE_CIPHER_NONE */
- /* Values for the IW_IE_CIPHER_* in GENIE */
- static const char * iw_ie_cypher_name[] = {
- "none",
- "WEP-40",
- "TKIP",
- "WRAP",
- "CCMP",
- "WEP-104",
- };
- #define IW_IE_CYPHER_NUM IW_ARRAY_LEN(iw_ie_cypher_name)
- /* Values for the IW_IE_KEY_MGMT_* in GENIE */
- static const char * iw_ie_key_mgmt_name[] = {
- "none",
- "802.1x",
- "PSK",
- };
- #define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name)
- #endif /* WE_ESSENTIAL */
- /************************* WPA SUBROUTINES *************************/
- #ifndef WE_ESSENTIAL
- /*------------------------------------------------------------------*/
- /*
- * Print all names corresponding to a mask.
- * This may want to be used in iw_print_retry_value() ?
- */
- static void
- iw_print_mask_name(unsigned int mask,
- const struct iwmask_name names[],
- const unsigned int num_names,
- const char * sep)
- {
- unsigned int i;
- /* Print out all names for the bitmask */
- for(i = 0; i < num_names; i++)
- {
- if(mask & names[i].mask)
- {
- /* Print out */
- printf("%s%s", sep, names[i].name);
- /* Remove the bit from the mask */
- mask &= ~names[i].mask;
- }
- }
- /* If there is unconsumed bits... */
- if(mask != 0)
- printf("%sUnknown", sep);
- }
- /*------------------------------------------------------------------*/
- /*
- * Print the name corresponding to a value, with overflow check.
- */
- static void
- iw_print_value_name(unsigned int value,
- const char * names[],
- const unsigned int num_names)
- {
- if(value >= num_names)
- printf(" unknown (%d)", value);
- else
- printf(" %s", names[value]);
- }
- /*------------------------------------------------------------------*/
- /*
- * Parse, and display the results of an unknown IE.
- *
- */
- static void
- iw_print_ie_unknown(unsigned char * iebuf,
- int buflen)
- {
- int ielen = iebuf[1] + 2;
- int i;
- if(ielen > buflen)
- ielen = buflen;
- printf("Unknown: ");
- for(i = 0; i < ielen; i++)
- printf("%02X", iebuf[i]);
- printf("\n");
- }
- /*------------------------------------------------------------------*/
- /*
- * Parse, and display the results of a WPA or WPA2 IE.
- *
- */
- static inline void
- iw_print_ie_wpa(unsigned char * iebuf,
- int buflen)
- {
- int ielen = iebuf[1] + 2;
- int offset = 2; /* Skip the IE id, and the length. */
- unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
- unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
- unsigned char * wpa_oui;
- int i;
- uint16_t ver = 0;
- uint16_t cnt = 0;
- if(ielen > buflen)
- ielen = buflen;
- #ifdef DEBUG
- /* Debugging code. In theory useless, because it's debugged ;-) */
- printf("IE raw value %d [%02X", buflen, iebuf[0]);
- for(i = 1; i < buflen; i++)
- printf(":%02X", iebuf[i]);
- printf("]\n");
- #endif
- switch(iebuf[0])
- {
- case 0x30: /* WPA2 */
- /* Check if we have enough data */
- if(ielen < 4)
- {
- iw_print_ie_unknown(iebuf, buflen);
- return;
- }
- wpa_oui = wpa2_oui;
- break;
- case 0xdd: /* WPA or else */
- wpa_oui = wpa1_oui;
-
- /* Not all IEs that start with 0xdd are WPA.
- * So check that the OUI is valid. Note : offset==2 */
- if((ielen < 8)
- || (memcmp(&iebuf[offset], wpa_oui, 3) != 0)
- || (iebuf[offset + 3] != 0x01))
- {
- iw_print_ie_unknown(iebuf, buflen);
- return;
- }
- /* Skip the OUI type */
- offset += 4;
- break;
- default:
- return;
- }
-
- /* Pick version number (little endian) */
- ver = iebuf[offset] | (iebuf[offset + 1] << 8);
- offset += 2;
- if(iebuf[0] == 0xdd)
- printf("WPA Version %d\n", ver);
- if(iebuf[0] == 0x30)
- printf("IEEE 802.11i/WPA2 Version %d\n", ver);
- /* From here, everything is technically optional. */
- /* Check if we are done */
- if(ielen < (offset + 4))
- {
- /* We have a short IE. So we should assume TKIP/TKIP. */
- printf(" Group Cipher : TKIP\n");
- printf(" Pairwise Cipher : TKIP\n");
- return;
- }
-
- /* Next we have our group cipher. */
- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
- {
- printf(" Group Cipher : Proprietary\n");
- }
- else
- {
- printf(" Group Cipher :");
- iw_print_value_name(iebuf[offset+3],
- iw_ie_cypher_name, IW_IE_CYPHER_NUM);
- printf("\n");
- }
- offset += 4;
- /* Check if we are done */
- if(ielen < (offset + 2))
- {
- /* We don't have a pairwise cipher, or auth method. Assume TKIP. */
- printf(" Pairwise Ciphers : TKIP\n");
- return;
- }
- /* Otherwise, we have some number of pairwise ciphers. */
- cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
- offset += 2;
- printf(" Pairwise Ciphers (%d) :", cnt);
- if(ielen < (offset + 4*cnt))
- return;
- for(i = 0; i < cnt; i++)
- {
- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
- {
- printf(" Proprietary");
- }
- else
- {
- iw_print_value_name(iebuf[offset+3],
- iw_ie_cypher_name, IW_IE_CYPHER_NUM);
- }
- offset+=4;
- }
- printf("\n");
-
- /* Check if we are done */
- if(ielen < (offset + 2))
- return;
- /* Now, we have authentication suites. */
- cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
- offset += 2;
- printf(" Authentication Suites (%d) :", cnt);
- if(ielen < (offset + 4*cnt))
- return;
- for(i = 0; i < cnt; i++)
- {
- if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
- {
- printf(" Proprietary");
- }
- else
- {
- iw_print_value_name(iebuf[offset+3],
- iw_ie_key_mgmt_name, IW_IE_KEY_MGMT_NUM);
- }
- offset+=4;
- }
- printf("\n");
-
- /* Check if we are done */
- if(ielen < (offset + 1))
- return;
- /* Otherwise, we have capabilities bytes.
- * For now, we only care about preauth which is in bit position 1 of the
- * first byte. (But, preauth with WPA version 1 isn't supposed to be
- * allowed.) 8-) */
- if(iebuf[offset] & 0x01)
- {
- printf(" Preauthentication Supported\n");
- }
- }
-
- /*------------------------------------------------------------------*/
- /*
- * Process a generic IE and display the info in human readable form
- * for some of the most interesting ones.
- * For now, we only decode the WPA IEs.
- */
- static inline void
- iw_print_gen_ie(unsigned char * buffer,
- int buflen)
- {
- int offset = 0;
- /* Loop on each IE, each IE is minimum 2 bytes */
- while(offset <= (buflen - 2))
- {
- printf(" IE: ");
- /* Check IE type */
- switch(buffer[offset])
- {
- case 0xdd: /* WPA1 (and other) */
- case 0x30: /* WPA2 */
- iw_print_ie_wpa(buffer + offset, buflen);
- break;
- default:
- iw_print_ie_unknown(buffer + offset, buflen);
- }
- /* Skip over this IE to the next one in the list. */
- offset += buffer[offset+1] + 2;
- }
- }
- #endif /* WE_ESSENTIAL */
- /***************************** SCANNING *****************************/
- /*
- * This one behave quite differently from the others
- *
- * Note that we don't use the scanning capability of iwlib (functions
- * iw_process_scan() and iw_scan()). The main reason is that
- * iw_process_scan() return only a subset of the scan data to the caller,
- * for example custom elements and bitrates are ommited. Here, we
- * do the complete job...
- */
- /*------------------------------------------------------------------*/
- /*
- * Print one element from the scanning results
- */
- static inline void
- print_scanning_token(struct stream_descr * stream, /* Stream of events */
- struct iw_event * event, /* Extracted token */
- struct iwscan_state * state,
- struct iw_range * iw_range, /* Range info */
- int has_range)
- {
- char buffer[128]; /* Temporary buffer */
- /* Now, let's decode the event */
- switch(event->cmd)
- {
- case SIOCGIWAP:
- printf(" Cell %02d - Address: %s\n", state->ap_num,
- iw_saether_ntop(&event->u.ap_addr, buffer));
- state->ap_num++;
- break;
- case SIOCGIWNWID:
- if(event->u.nwid.disabled)
- printf(" NWID:off/any\n");
- else
- printf(" NWID:%X\n", event->u.nwid.value);
- break;
- case SIOCGIWFREQ:
- {
- double freq; /* Frequency/channel */
- int channel = -1; /* Converted to channel */
- freq = iw_freq2float(&(event->u.freq));
- /* Convert to channel if possible */
- if(has_range)
- channel = iw_freq_to_channel(freq, iw_range);
- iw_print_freq(buffer, sizeof(buffer),
- freq, channel, event->u.freq.flags);
- printf(" %s\n", buffer);
- }
- break;
- case SIOCGIWMODE:
- /* Note : event->u.mode is unsigned, no need to check <= 0 */
- if(event->u.mode >= IW_NUM_OPER_MODE)
- event->u.mode = IW_NUM_OPER_MODE;
- printf(" Mode:%s\n",
- iw_operation_mode[event->u.mode]);
- break;
- case SIOCGIWNAME:
- printf(" Protocol:%-1.16s\n", event->u.name);
- break;
- case SIOCGIWESSID:
- {
- char essid[IW_ESSID_MAX_SIZE+1];
- memset(essid, '\0', sizeof(essid));
- if((event->u.essid.pointer) && (event->u.essid.length))
- memcpy(essid, event->u.essid.pointer, event->u.essid.length);
- if(event->u.essid.flags)
- {
- /* Does it have an ESSID index ? */
- if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)
- printf(" ESSID:\"%s\" [%d]\n", essid,
- (event->u.essid.flags & IW_ENCODE_INDEX));
- else
- printf(" ESSID:\"%s\"\n", essid);
- }
- else
- printf(" ESSID:off/any/hidden\n");
- }
- break;
- case SIOCGIWENCODE:
- {
- unsigned char key[IW_ENCODING_TOKEN_MAX];
- if(event->u.data.pointer)
- memcpy(key, event->u.data.pointer, event->u.data.length);
- else
- event->u.data.flags |= IW_ENCODE_NOKEY;
- printf(" Encryption key:");
- if(event->u.data.flags & IW_ENCODE_DISABLED)
- printf("off\n");
- else
- {
- /* Display the key */
- iw_print_key(buffer, sizeof(buffer), key, event->u.data.length,
- event->u.data.flags);
- printf("%s", buffer);
- /* Other info... */
- if((event->u.data.flags & IW_ENCODE_INDEX) > 1)
- printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX);
- if(event->u.data.flags & IW_ENCODE_RESTRICTED)
- printf(" Security mode:restricted");
- if(event->u.data.flags & IW_ENCODE_OPEN)
- printf(" Security mode:open");
- printf("\n");
- }
- }
- break;
- case SIOCGIWRATE:
- if(state->val_index == 0)
- printf(" Bit Rates:");
- else
- if((state->val_index % 5) == 0)
- printf("\n ");
- else
- printf("; ");
- iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);
- printf("%s", buffer);
- /* Check for termination */
- if(stream->value == NULL)
- {
- printf("\n");
- state->val_index = 0;
- }
- else
- state->val_index++;
- break;
- case SIOCGIWMODUL:
- {
- unsigned int modul = event->u.param.value;
- int i;
- int n = 0;
- printf(" Modulations :");
- for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
- {
- if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
- {
- if((n++ % 8) == 7)
- printf("\n ");
- else
- printf(" ; ");
- printf("%s", iw_modul_list[i].cmd);
- }
- }
- printf("\n");
- }
- break;
- case IWEVQUAL:
- iw_print_stats(buffer, sizeof(buffer),
- &event->u.qual, iw_range, has_range);
- printf(" %s\n", buffer);
- break;
- #ifndef WE_ESSENTIAL
- case IWEVGENIE:
- /* Informations Elements are complex, let's do only some of them */
- iw_print_gen_ie(event->u.data.pointer, event->u.data.length);
- break;
- #endif /* WE_ESSENTIAL */
- case IWEVCUSTOM:
- {
- char custom[IW_CUSTOM_MAX+1];
- if((event->u.data.pointer) && (event->u.data.length))
- memcpy(custom, event->u.data.pointer, event->u.data.length);
- custom[event->u.data.length] = '\0';
- printf(" Extra:%s\n", custom);
- }
- break;
- default:
- printf(" (Unknown Wireless Token 0x%04X)\n",
- event->cmd);
- } /* switch(event->cmd) */
- }
- /*------------------------------------------------------------------*/
- /*
- * Perform a scanning on one device
- */
- static int
- print_scanning_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_scan_req scanopt; /* Options for 'set' */
- int scanflags = 0; /* Flags for scan */
- unsigned char * buffer = NULL; /* Results */
- int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
- struct iw_range range;
- int has_range;
- struct timeval tv; /* Select timeout */
- int timeout = 15000000; /* 15s */
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Debugging stuff */
- if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN))
- {
- fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n");
- fprintf(stderr, "*** and the following line :\n");
- fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n",
- IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN);
- }
- /* Get range stuff */
- has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
- /* Check if the interface could support scanning. */
- if((!has_range) || (range.we_version_compiled < 14))
- {
- fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n",
- ifname);
- return(-1);
- }
- /* Init timeout value -> 250ms between set and first get */
- tv.tv_sec = 0;
- tv.tv_usec = 250000;
- /* Clean up set args */
- memset(&scanopt, 0, sizeof(scanopt));
- /* Parse command line arguments and extract options.
- * Note : when we have enough options, we should use the parser
- * from iwconfig... */
- while(count > 0)
- {
- /* One arg is consumed (the option name) */
- count--;
-
- /*
- * Check for Active Scan (scan with specific essid)
- */
- if(!strncmp(args[0], "essid", 5))
- {
- if(count < 1)
- {
- fprintf(stderr, "Too few arguments for scanning option [%s]\n",
- args[0]);
- return(-1);
- }
- args++;
- count--;
- /* Store the ESSID in the scan options */
- scanopt.essid_len = strlen(args[0]);
- memcpy(scanopt.essid, args[0], scanopt.essid_len);
- /* Initialise BSSID as needed */
- if(scanopt.bssid.sa_family == 0)
- {
- scanopt.bssid.sa_family = ARPHRD_ETHER;
- memset(scanopt.bssid.sa_data, 0xff, ETH_ALEN);
- }
- /* Scan only this ESSID */
- scanflags |= IW_SCAN_THIS_ESSID;
- }
- else
- /* Check for last scan result (do not trigger scan) */
- if(!strncmp(args[0], "last", 4))
- {
- /* Hack */
- scanflags |= IW_SCAN_HACK;
- }
- else
- {
- fprintf(stderr, "Invalid scanning option [%s]\n", args[0]);
- return(-1);
- }
- /* Next arg */
- args++;
- }
- /* Check if we have scan options */
- if(scanflags)
- {
- wrq.u.data.pointer = (caddr_t) &scanopt;
- wrq.u.data.length = sizeof(scanopt);
- wrq.u.data.flags = scanflags;
- }
- else
- {
- wrq.u.data.pointer = NULL;
- wrq.u.data.flags = 0;
- wrq.u.data.length = 0;
- }
- /* If only 'last' was specified on command line, don't trigger a scan */
- if(scanflags == IW_SCAN_HACK)
- {
- /* Skip waiting */
- tv.tv_usec = 0;
- }
- else
- {
- /* Initiate Scanning */
- if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
- {
- if((errno != EPERM) || (scanflags != 0))
- {
- fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
- ifname, strerror(errno));
- return(-1);
- }
- /* If we don't have the permission to initiate the scan, we may
- * still have permission to read left-over results.
- * But, don't wait !!! */
- #if 0
- /* Not cool, it display for non wireless interfaces... */
- fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
- #endif
- tv.tv_usec = 0;
- }
- }
- timeout -= tv.tv_usec;
- /* Forever */
- while(1)
- {
- fd_set rfds; /* File descriptors for select */
- int last_fd; /* Last fd */
- int ret;
- /* Guess what ? We must re-generate rfds each time */
- FD_ZERO(&rfds);
- last_fd = -1;
- /* In here, add the rtnetlink fd in the list */
- /* Wait until something happens */
- ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
- /* Check if there was an error */
- if(ret < 0)
- {
- if(errno == EAGAIN || errno == EINTR)
- continue;
- fprintf(stderr, "Unhandled signal - exiting...\n");
- return(-1);
- }
- /* Check if there was a timeout */
- if(ret == 0)
- {
- unsigned char * newbuf;
- realloc:
- /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
- newbuf = realloc(buffer, buflen);
- if(newbuf == NULL)
- {
- if(buffer)
- free(buffer);
- fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
- return(-1);
- }
- buffer = newbuf;
- /* Try to read the results */
- wrq.u.data.pointer = buffer;
- wrq.u.data.flags = 0;
- wrq.u.data.length = buflen;
- if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
- {
- /* Check if buffer was too small (WE-17 only) */
- if((errno == E2BIG) && (range.we_version_compiled > 16))
- {
- /* Some driver may return very large scan results, either
- * because there are many cells, or because they have many
- * large elements in cells (like IWEVCUSTOM). Most will
- * only need the regular sized buffer. We now use a dynamic
- * allocation of the buffer to satisfy everybody. Of course,
- * as we don't know in advance the size of the array, we try
- * various increasing sizes. Jean II */
- /* Check if the driver gave us any hints. */
- if(wrq.u.data.length > buflen)
- buflen = wrq.u.data.length;
- else
- buflen *= 2;
- /* Try again */
- goto realloc;
- }
- /* Check if results not available yet */
- if(errno == EAGAIN)
- {
- /* Restart timer for only 100ms*/
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
- timeout -= tv.tv_usec;
- if(timeout > 0)
- continue; /* Try again later */
- }
- /* Bad error */
- free(buffer);
- fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
- ifname, strerror(errno));
- return(-2);
- }
- else
- /* We have the results, go to process them */
- break;
- }
- /* In here, check if event and event type
- * if scan event, read results. All errors bad & no reset timeout */
- }
- if(wrq.u.data.length)
- {
- struct iw_event iwe;
- struct stream_descr stream;
- struct iwscan_state state = { .ap_num = 1, .val_index = 0 };
- int ret;
-
- #ifdef DEBUG
- /* Debugging code. In theory useless, because it's debugged ;-) */
- int i;
- printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
- for(i = 1; i < wrq.u.data.length; i++)
- printf(":%02X", buffer[i]);
- printf("]\n");
- #endif
- printf("%-8.16s Scan completed :\n", ifname);
- iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
- do
- {
- /* Extract an event and print it */
- ret = iw_extract_event_stream(&stream, &iwe,
- range.we_version_compiled);
- if(ret > 0)
- print_scanning_token(&stream, &iwe, &state,
- &range, has_range);
- }
- while(ret > 0);
- printf("\n");
- }
- else
- printf("%-8.16s No scan results\n\n", ifname);
- free(buffer);
- return(0);
- }
- /*********************** FREQUENCIES/CHANNELS ***********************/
- /*------------------------------------------------------------------*/
- /*
- * Print the number of channels and available frequency for the device
- */
- static int
- print_freq_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- double freq;
- int k;
- int channel;
- char buffer[128]; /* Temporary buffer */
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Get list of frequencies / channels */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- fprintf(stderr, "%-8.16s no frequency information.\n\n",
- ifname);
- else
- {
- if(range.num_frequency > 0)
- {
- printf("%-8.16s %d channels in total; available frequencies :\n",
- ifname, range.num_channels);
- /* Print them all */
- for(k = 0; k < range.num_frequency; k++)
- {
- freq = iw_freq2float(&(range.freq[k]));
- iw_print_freq_value(buffer, sizeof(buffer), freq);
- printf(" Channel %.2d : %s\n",
- range.freq[k].i, buffer);
- }
- }
- else
- printf("%-8.16s %d channels\n",
- ifname, range.num_channels);
- /* Get current frequency / channel and display it */
- if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
- {
- freq = iw_freq2float(&(wrq.u.freq));
- channel = iw_freq_to_channel(freq, &range);
- iw_print_freq(buffer, sizeof(buffer),
- freq, channel, wrq.u.freq.flags);
- printf(" Current %s\n\n", buffer);
- }
- }
- return(0);
- }
- /***************************** BITRATES *****************************/
- /*------------------------------------------------------------------*/
- /*
- * Print the number of available bitrates for the device
- */
- static int
- print_bitrate_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- int k;
- char buffer[128];
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Extract range info */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- fprintf(stderr, "%-8.16s no bit-rate information.\n\n",
- ifname);
- else
- {
- if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
- {
- printf("%-8.16s %d available bit-rates :\n",
- ifname, range.num_bitrates);
- /* Print them all */
- for(k = 0; k < range.num_bitrates; k++)
- {
- iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
- /* Maybe this should be %10s */
- printf("\t %s\n", buffer);
- }
- }
- else
- printf("%-8.16s unknown bit-rate information.\n", ifname);
- /* Get current bit rate */
- if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
- {
- iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
- printf(" Current Bit Rate%c%s\n",
- (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
- }
- /* Try to get the broadcast bitrate if it exist... */
- if(range.bitrate_capa & IW_BITRATE_BROADCAST)
- {
- wrq.u.bitrate.flags = IW_BITRATE_BROADCAST;
- if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
- {
- iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
- printf(" Broadcast Bit Rate%c%s\n",
- (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
- }
- }
- printf("\n");
- }
- return(0);
- }
- /************************* ENCRYPTION KEYS *************************/
- /*------------------------------------------------------------------*/
- /*
- * Print all the available encryption keys for the device
- */
- static int
- print_keys_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- unsigned char key[IW_ENCODING_TOKEN_MAX];
- unsigned int k;
- char buffer[128];
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Extract range info */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- fprintf(stderr, "%-8.16s no encryption keys information.\n\n",
- ifname);
- else
- {
- printf("%-8.16s ", ifname);
- /* Print key sizes */
- if((range.num_encoding_sizes > 0) &&
- (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
- {
- printf("%d key sizes : %d", range.num_encoding_sizes,
- range.encoding_size[0] * 8);
- /* Print them all */
- for(k = 1; k < range.num_encoding_sizes; k++)
- printf(", %d", range.encoding_size[k] * 8);
- printf("bits\n ");
- }
- /* Print the keys and associate mode */
- printf("%d keys available :\n", range.max_encoding_tokens);
- for(k = 1; k <= range.max_encoding_tokens; k++)
- {
- wrq.u.data.pointer = (caddr_t) key;
- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
- wrq.u.data.flags = k;
- if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
- {
- fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno));
- break;
- }
- if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
- (wrq.u.data.length == 0))
- printf("\t\t[%d]: off\n", k);
- else
- {
- /* Display the key */
- iw_print_key(buffer, sizeof(buffer),
- key, wrq.u.data.length, wrq.u.data.flags);
- printf("\t\t[%d]: %s", k, buffer);
- /* Other info... */
- printf(" (%d bits)", wrq.u.data.length * 8);
- printf("\n");
- }
- }
- /* Print current key index and mode */
- wrq.u.data.pointer = (caddr_t) key;
- wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
- wrq.u.data.flags = 0; /* Set index to zero to get current */
- if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
- {
- /* Note : if above fails, we have already printed an error
- * message int the loop above */
- printf(" Current Transmit Key: [%d]\n",
- wrq.u.data.flags & IW_ENCODE_INDEX);
- if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
- printf(" Security mode:restricted\n");
- if(wrq.u.data.flags & IW_ENCODE_OPEN)
- printf(" Security mode:open\n");
- }
- printf("\n\n");
- }
- return(0);
- }
- /************************* POWER MANAGEMENT *************************/
- /*------------------------------------------------------------------*/
- /*
- * Print Power Management info for each device
- */
- static int
- get_pm_value(int skfd,
- char * ifname,
- struct iwreq * pwrq,
- int flags,
- char * buffer,
- int buflen,
- int we_version_compiled)
- {
- /* Get Another Power Management value */
- pwrq->u.power.flags = flags;
- if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
- {
- /* Let's check the value and its type */
- if(pwrq->u.power.flags & IW_POWER_TYPE)
- {
- iw_print_pm_value(buffer, buflen,
- pwrq->u.power.value, pwrq->u.power.flags,
- we_version_compiled);
- printf("\n %s", buffer);
- }
- }
- return(pwrq->u.power.flags);
- }
- /*------------------------------------------------------------------*/
- /*
- * Print Power Management range for each type
- */
- static void
- print_pm_value_range(char * name,
- int mask,
- int iwr_flags,
- int iwr_min,
- int iwr_max,
- char * buffer,
- int buflen,
- int we_version_compiled)
- {
- if(iwr_flags & mask)
- {
- int flags = (iwr_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
- /* Display if auto or fixed */
- printf("%s %s ; ",
- (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
- name);
- /* Print the range */
- iw_print_pm_value(buffer, buflen,
- iwr_min, flags | IW_POWER_MIN,
- we_version_compiled);
- printf("%s\n ", buffer);
- iw_print_pm_value(buffer, buflen,
- iwr_max, flags | IW_POWER_MAX,
- we_version_compiled);
- printf("%s\n ", buffer);
- }
- }
- /*------------------------------------------------------------------*/
- /*
- * Power Management types of values
- */
- static const unsigned int pm_type_flags[] = {
- IW_POWER_PERIOD,
- IW_POWER_TIMEOUT,
- IW_POWER_SAVING,
- };
- static const int pm_type_flags_size = (sizeof(pm_type_flags)/sizeof(pm_type_flags[0]));
- /*------------------------------------------------------------------*/
- /*
- * Print Power Management info for each device
- */
- static int
- print_pm_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- char buffer[128];
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 10))
- fprintf(stderr, "%-8.16s no power management information.\n\n",
- ifname);
- else
- {
- printf("%-8.16s ", ifname);
- /* Display modes availables */
- if(range.pm_capa & IW_POWER_MODE)
- {
- printf("Supported modes :\n ");
- if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
- printf("\t\to Receive all packets (unicast & multicast)\n ");
- if(range.pm_capa & IW_POWER_UNICAST_R)
- printf("\t\to Receive Unicast only (discard multicast)\n ");
- if(range.pm_capa & IW_POWER_MULTICAST_R)
- printf("\t\to Receive Multicast only (discard unicast)\n ");
- if(range.pm_capa & IW_POWER_FORCE_S)
- printf("\t\to Force sending using Power Management\n ");
- if(range.pm_capa & IW_POWER_REPEATER)
- printf("\t\to Repeat multicast\n ");
- }
- /* Display min/max period availables */
- print_pm_value_range("period ", IW_POWER_PERIOD,
- range.pmp_flags, range.min_pmp, range.max_pmp,
- buffer, sizeof(buffer), range.we_version_compiled);
- /* Display min/max timeout availables */
- print_pm_value_range("timeout", IW_POWER_TIMEOUT,
- range.pmt_flags, range.min_pmt, range.max_pmt,
- buffer, sizeof(buffer), range.we_version_compiled);
- /* Display min/max saving availables */
- print_pm_value_range("saving ", IW_POWER_SAVING,
- range.pms_flags, range.min_pms, range.max_pms,
- buffer, sizeof(buffer), range.we_version_compiled);
- /* Get current Power Management settings */
- wrq.u.power.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
- {
- int flags = wrq.u.power.flags;
- /* Is it disabled ? */
- if(wrq.u.power.disabled)
- printf("Current mode:off\n");
- else
- {
- unsigned int pm_type = 0;
- unsigned int pm_mask = 0;
- unsigned int remain_mask = range.pm_capa & IW_POWER_TYPE;
- int i = 0;
- /* Let's check the mode */
- iw_print_pm_mode(buffer, sizeof(buffer), flags);
- printf("Current %s", buffer);
- /* Let's check if nothing (simply on) */
- if((flags & IW_POWER_MODE) == IW_POWER_ON)
- printf("mode:on");
- /* Let's check the value and its type */
- if(wrq.u.power.flags & IW_POWER_TYPE)
- {
- iw_print_pm_value(buffer, sizeof(buffer),
- wrq.u.power.value, wrq.u.power.flags,
- range.we_version_compiled);
- printf("\n %s", buffer);
- }
- while(1)
- {
- /* Deal with min/max for the current value */
- pm_mask = 0;
- /* If we have been returned a MIN value, ask for the MAX */
- if(flags & IW_POWER_MIN)
- pm_mask = IW_POWER_MAX;
- /* If we have been returned a MAX value, ask for the MIN */
- if(flags & IW_POWER_MAX)
- pm_mask = IW_POWER_MIN;
- /* If we have something to ask for... */
- if(pm_mask)
- {
- pm_mask |= pm_type;
- get_pm_value(skfd, ifname, &wrq, pm_mask,
- buffer, sizeof(buffer),
- range.we_version_compiled);
- }
- /* Remove current type from mask */
- remain_mask &= ~(wrq.u.power.flags);
- /* Check what other types we still have to read */
- while(i < pm_type_flags_size)
- {
- pm_type = remain_mask & pm_type_flags[i];
- if(pm_type)
- break;
- i++;
- }
- /* Nothing anymore : exit the loop */
- if(!pm_type)
- break;
- /* Ask for this other type of value */
- flags = get_pm_value(skfd, ifname, &wrq, pm_type,
- buffer, sizeof(buffer),
- range.we_version_compiled);
- /* Loop back for min/max */
- }
- printf("\n");
- }
- }
- printf("\n");
- }
- return(0);
- }
- #ifndef WE_ESSENTIAL
- /************************** TRANSMIT POWER **************************/
- /*------------------------------------------------------------------*/
- /*
- * Print the number of available transmit powers for the device
- */
- static int
- print_txpower_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- int dbm;
- int mwatt;
- int k;
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 10))
- fprintf(stderr, "%-8.16s no transmit-power information.\n\n",
- ifname);
- else
- {
- if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
- printf("%-8.16s unknown transmit-power information.\n\n", ifname);
- else
- {
- printf("%-8.16s %d available transmit-powers :\n",
- ifname, range.num_txpower);
- /* Print them all */
- for(k = 0; k < range.num_txpower; k++)
- {
- /* Check for relative values */
- if(range.txpower_capa & IW_TXPOW_RELATIVE)
- {
- printf("\t %d (no units)\n", range.txpower[k]);
- }
- else
- {
- if(range.txpower_capa & IW_TXPOW_MWATT)
- {
- dbm = iw_mwatt2dbm(range.txpower[k]);
- mwatt = range.txpower[k];
- }
- else
- {
- dbm = range.txpower[k];
- mwatt = iw_dbm2mwatt(range.txpower[k]);
- }
- printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
- }
- }
- }
- /* Get current Transmit Power */
- if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
- {
- printf(" Current Tx-Power");
- /* Disabled ? */
- if(wrq.u.txpower.disabled)
- printf(":off\n\n");
- else
- {
- /* Fixed ? */
- if(wrq.u.txpower.fixed)
- printf("=");
- else
- printf(":");
- /* Check for relative values */
- if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
- {
- /* I just hate relative value, because they are
- * driver specific, so not very meaningfull to apps.
- * But, we have to support that, because
- * this is the way hardware is... */
- printf("\t %d (no units)\n", wrq.u.txpower.value);
- }
- else
- {
- if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
- {
- dbm = iw_mwatt2dbm(wrq.u.txpower.value);
- mwatt = wrq.u.txpower.value;
- }
- else
- {
- dbm = wrq.u.txpower.value;
- mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
- }
- printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
- }
- }
- }
- }
- return(0);
- }
- /*********************** RETRY LIMIT/LIFETIME ***********************/
- /*------------------------------------------------------------------*/
- /*
- * Print one retry value
- */
- static int
- get_retry_value(int skfd,
- char * ifname,
- struct iwreq * pwrq,
- int flags,
- char * buffer,
- int buflen,
- int we_version_compiled)
- {
- /* Get Another retry value */
- pwrq->u.retry.flags = flags;
- if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
- {
- /* Let's check the value and its type */
- if(pwrq->u.retry.flags & IW_RETRY_TYPE)
- {
- iw_print_retry_value(buffer, buflen,
- pwrq->u.retry.value, pwrq->u.retry.flags,
- we_version_compiled);
- printf("%s\n ", buffer);
- }
- }
- return(pwrq->u.retry.flags);
- }
- /*------------------------------------------------------------------*/
- /*
- * Print Power Management range for each type
- */
- static void
- print_retry_value_range(char * name,
- int mask,
- int iwr_flags,
- int iwr_min,
- int iwr_max,
- char * buffer,
- int buflen,
- int we_version_compiled)
- {
- if(iwr_flags & mask)
- {
- int flags = (iwr_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
- /* Display if auto or fixed */
- printf("%s %s ; ",
- (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
- name);
- /* Print the range */
- iw_print_retry_value(buffer, buflen,
- iwr_min, flags | IW_POWER_MIN,
- we_version_compiled);
- printf("%s\n ", buffer);
- iw_print_retry_value(buffer, buflen,
- iwr_max, flags | IW_POWER_MAX,
- we_version_compiled);
- printf("%s\n ", buffer);
- }
- }
- /*------------------------------------------------------------------*/
- /*
- * Print Retry info for each device
- */
- static int
- print_retry_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- char buffer[128];
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 11))
- fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n",
- ifname);
- else
- {
- printf("%-8.16s ", ifname);
- /* Display min/max limit availables */
- print_retry_value_range("limit ", IW_RETRY_LIMIT, range.retry_flags,
- range.min_retry, range.max_retry,
- buffer, sizeof(buffer),
- range.we_version_compiled);
- /* Display min/max lifetime availables */
- print_retry_value_range("lifetime", IW_RETRY_LIFETIME,
- range.r_time_flags,
- range.min_r_time, range.max_r_time,
- buffer, sizeof(buffer),
- range.we_version_compiled);
- /* Get current retry settings */
- wrq.u.retry.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
- {
- int flags = wrq.u.retry.flags;
- /* Is it disabled ? */
- if(wrq.u.retry.disabled)
- printf("Current mode:off\n ");
- else
- {
- unsigned int retry_type = 0;
- unsigned int retry_mask = 0;
- unsigned int remain_mask = range.retry_capa & IW_RETRY_TYPE;
- /* Let's check the mode */
- printf("Current mode:on\n ");
- /* Let's check the value and its type */
- if(wrq.u.retry.flags & IW_RETRY_TYPE)
- {
- iw_print_retry_value(buffer, sizeof(buffer),
- wrq.u.retry.value, wrq.u.retry.flags,
- range.we_version_compiled);
- printf("%s\n ", buffer);
- }
- while(1)
- {
- /* Deal with min/max/short/long for the current value */
- retry_mask = 0;
- /* If we have been returned a MIN value, ask for the MAX */
- if(flags & IW_RETRY_MIN)
- retry_mask = IW_RETRY_MAX;
- /* If we have been returned a MAX value, ask for the MIN */
- if(flags & IW_RETRY_MAX)
- retry_mask = IW_RETRY_MIN;
- /* Same for SHORT and LONG */
- if(flags & IW_RETRY_SHORT)
- retry_mask = IW_RETRY_LONG;
- if(flags & IW_RETRY_LONG)
- retry_mask = IW_RETRY_SHORT;
- /* If we have something to ask for... */
- if(retry_mask)
- {
- retry_mask |= retry_type;
- get_retry_value(skfd, ifname, &wrq, retry_mask,
- buffer, sizeof(buffer),
- range.we_version_compiled);
- }
- /* And if we have both a limit and a lifetime,
- * ask the other one */
- remain_mask &= ~(wrq.u.retry.flags);
- retry_type = remain_mask;
- /* Nothing anymore : exit the loop */
- if(!retry_type)
- break;
- /* Ask for this other type of value */
- flags = get_retry_value(skfd, ifname, &wrq, retry_type,
- buffer, sizeof(buffer),
- range.we_version_compiled);
- /* Loop back for min/max/short/long */
- }
- }
- }
- printf("\n");
- }
- return(0);
- }
- /************************ ACCESS POINT LIST ************************/
- /*
- * Note : now that we have scanning support, this is depracted and
- * won't survive long. Actually, next version it's out !
- */
- /*------------------------------------------------------------------*/
- /*
- * Display the list of ap addresses and the associated stats
- * Exacly the same as the spy list, only with different IOCTL and messages
- */
- static int
- print_ap_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- char buffer[(sizeof(struct iw_quality) +
- sizeof(struct sockaddr)) * IW_MAX_AP];
- char temp[128];
- struct sockaddr * hwa;
- struct iw_quality * qual;
- iwrange range;
- int has_range = 0;
- int has_qual = 0;
- int n;
- int i;
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Collect stats */
- wrq.u.data.pointer = (caddr_t) buffer;
- wrq.u.data.length = IW_MAX_AP;
- wrq.u.data.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
- {
- fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
- return(-1);
- }
- /* Number of addresses */
- n = wrq.u.data.length;
- has_qual = wrq.u.data.flags;
- /* The two lists */
- hwa = (struct sockaddr *) buffer;
- qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
- /* Check if we have valid mac address type */
- if(iw_check_mac_addr_type(skfd, ifname) < 0)
- {
- fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
- return(-2);
- }
- /* Get range info if we can */
- if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
- has_range = 1;
- /* Display it */
- if(n == 0)
- printf("%-8.16s No Peers/Access-Point in range\n", ifname);
- else
- printf("%-8.16s Peers/Access-Points in range:\n", ifname);
- for(i = 0; i < n; i++)
- {
- if(has_qual)
- {
- /* Print stats for this address */
- printf(" %s : ", iw_saether_ntop(&hwa[i], temp));
- iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
- printf("%s\n", temp);
- }
- else
- /* Only print the address */
- printf(" %s\n", iw_saether_ntop(&hwa[i], temp));
- }
- printf("\n");
- return(0);
- }
- /******************** WIRELESS EVENT CAPABILITY ********************/
- static const char * event_capa_req[] =
- {
- [SIOCSIWNWID - SIOCIWFIRST] = "Set NWID (kernel generated)",
- [SIOCSIWFREQ - SIOCIWFIRST] = "Set Frequency/Channel (kernel generated)",
- [SIOCGIWFREQ - SIOCIWFIRST] = "New Frequency/Channel",
- [SIOCSIWMODE - SIOCIWFIRST] = "Set Mode (kernel generated)",
- [SIOCGIWTHRSPY - SIOCIWFIRST] = "Spy threshold crossed",
- [SIOCGIWAP - SIOCIWFIRST] = "New Access Point/Cell address - roaming",
- [SIOCGIWSCAN - SIOCIWFIRST] = "Scan request completed",
- [SIOCSIWESSID - SIOCIWFIRST] = "Set ESSID (kernel generated)",
- [SIOCGIWESSID - SIOCIWFIRST] = "New ESSID",
- [SIOCGIWRATE - SIOCIWFIRST] = "New bit-rate",
- [SIOCSIWENCODE - SIOCIWFIRST] = "Set Encoding (kernel generated)",
- [SIOCGIWPOWER - SIOCIWFIRST] = NULL,
- };
- static const char * event_capa_evt[] =
- {
- [IWEVTXDROP - IWEVFIRST] = "Tx packet dropped - retry exceeded",
- [IWEVCUSTOM - IWEVFIRST] = "Custom driver event",
- [IWEVREGISTERED - IWEVFIRST] = "Registered node",
- [IWEVEXPIRED - IWEVFIRST] = "Expired node",
- };
- /*------------------------------------------------------------------*/
- /*
- * Print the event capability for the device
- */
- static int
- print_event_capa_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iw_range range;
- int cmd;
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 10))
- fprintf(stderr, "%-8.16s no wireless event capability information.\n\n",
- ifname);
- else
- {
- #ifdef DEBUG
- /* Debugging ;-) */
- for(cmd = 0x8B00; cmd < 0x8C0F; cmd++)
- {
- int idx = IW_EVENT_CAPA_INDEX(cmd);
- int mask = IW_EVENT_CAPA_MASK(cmd);
- printf("0x%X - %d - %X\n", cmd, idx, mask);
- }
- #endif
- printf("%-8.16s Wireless Events supported :\n", ifname);
- for(cmd = SIOCIWFIRST; cmd <= SIOCGIWPOWER; cmd++)
- {
- int idx = IW_EVENT_CAPA_INDEX(cmd);
- int mask = IW_EVENT_CAPA_MASK(cmd);
- if(range.event_capa[idx] & mask)
- printf(" 0x%04X : %s\n",
- cmd, event_capa_req[cmd - SIOCIWFIRST]);
- }
- for(cmd = IWEVFIRST; cmd <= IWEVEXPIRED; cmd++)
- {
- int idx = IW_EVENT_CAPA_INDEX(cmd);
- int mask = IW_EVENT_CAPA_MASK(cmd);
- if(range.event_capa[idx] & mask)
- printf(" 0x%04X : %s\n",
- cmd, event_capa_evt[cmd - IWEVFIRST]);
- }
- printf("\n");
- }
- return(0);
- }
- /*************************** WPA SUPPORT ***************************/
- /*------------------------------------------------------------------*/
- /*
- * Print the authentication parameters for the device
- */
- static int
- print_auth_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- unsigned int k;
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 18))
- fprintf(stderr, "%-8.16s no authentication information.\n\n",
- ifname);
- else
- {
- /* Print WPA/802.1x/802.11i security parameters */
- if(!range.enc_capa)
- {
- printf("%-8.16s unknown authentication information.\n\n", ifname);
- }
- else
- {
- /* Display advanced encryption capabilities */
- printf("%-8.16s Authentication capabilities :", ifname);
- iw_print_mask_name(range.enc_capa,
- iw_auth_capa_name, IW_AUTH_CAPA_NUM,
- "\n\t\t");
- printf("\n");
- /* Extract all auth settings */
- for(k = 0; k < IW_AUTH_SETTINGS_NUM; k++)
- {
- wrq.u.param.flags = iw_auth_settings[k].value;
- if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
- {
- printf(" Current %s :", iw_auth_settings[k].label);
- if(iw_auth_settings[k].names != NULL)
- iw_print_mask_name(wrq.u.param.value,
- iw_auth_settings[k].names,
- iw_auth_settings[k].num_names,
- "\n\t\t");
- else
- printf((wrq.u.param.value) ? " yes" : " no");
- printf("\n");
- }
- }
- }
- printf("\n\n");
- }
- return(0);
- }
- /*------------------------------------------------------------------*/
- /*
- * Print all the available wpa keys for the device
- */
- static int
- print_wpakeys_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- unsigned char extbuf[IW_EXTKEY_SIZE];
- struct iw_encode_ext *extinfo;
- unsigned int k;
- char buffer[128];
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* This always point to the same place */
- extinfo = (struct iw_encode_ext *) extbuf;
- /* Extract range info */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- fprintf(stderr, "%-8.16s no wpa key information.\n\n",
- ifname);
- else
- {
- printf("%-8.16s ", ifname);
- /* Print key sizes */
- if((range.num_encoding_sizes > 0) &&
- (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
- {
- printf("%d key sizes : %d", range.num_encoding_sizes,
- range.encoding_size[0] * 8);
- /* Print them all */
- for(k = 1; k < range.num_encoding_sizes; k++)
- printf(", %d", range.encoding_size[k] * 8);
- printf("bits\n ");
- }
- /* Print the keys */
- printf("%d keys available :\n", range.max_encoding_tokens);
- for(k = 1; k <= range.max_encoding_tokens; k++)
- {
- /* Cleanup. Driver may not fill everything */
- memset(extbuf, '\0', IW_EXTKEY_SIZE);
- /* Get whole struct containing one WPA key */
- wrq.u.data.pointer = (caddr_t) extbuf;
- wrq.u.data.length = IW_EXTKEY_SIZE;
- wrq.u.data.flags = k;
- if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) < 0)
- {
- fprintf(stderr, "Error reading wpa keys (SIOCGIWENCODEEXT): %s\n", strerror(errno));
- break;
- }
- /* Sanity check */
- if(wrq.u.data.length <
- (sizeof(struct iw_encode_ext) + extinfo->key_len))
- break;
- /* Check if key is disabled */
- if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
- (extinfo->key_len == 0))
- printf("\t\t[%d]: off\n", k);
- else
- {
- /* Display the key */
- iw_print_key(buffer, sizeof(buffer),
- extinfo->key, extinfo->key_len, wrq.u.data.flags);
- printf("\t\t[%d]: %s", k, buffer);
- /* Key size */
- printf(" (%d bits)", extinfo->key_len * 8);
- printf("\n");
- /* Other info... */
- printf("\t\t Address: %s\n",
- iw_saether_ntop(&extinfo->addr, buffer));
- printf("\t\t Algorithm:");
- iw_print_value_name(extinfo->alg,
- iw_encode_alg_name, IW_ENCODE_ALG_NUM);
- printf("\n\t\t Flags: 0x%08x\n", extinfo->ext_flags);
- if (extinfo->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID)
- printf("\t\t tx-seq-valid\n");
- if (extinfo->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- printf("\t\t rx-seq-valid\n");
- if (extinfo->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
- printf("\t\t group-key\n");
- }
- }
- /* Print current key index and mode */
- wrq.u.data.pointer = (caddr_t) extbuf;
- wrq.u.data.length = IW_EXTKEY_SIZE;
- wrq.u.data.flags = 0; /* Set index to zero to get current */
- if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) >= 0)
- {
- /* Note : if above fails, we have already printed an error
- * message int the loop above */
- printf(" Current Transmit Key: [%d]\n",
- wrq.u.data.flags & IW_ENCODE_INDEX);
- if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
- printf(" Security mode:restricted\n");
- if(wrq.u.data.flags & IW_ENCODE_OPEN)
- printf(" Security mode:open\n");
- }
- printf("\n\n");
- }
- return(0);
- }
- /*------------------------------------------------------------------*/
- /*
- * Print the Generic IE for the device
- * Note : indentation is broken. We need to fix that.
- */
- static int
- print_gen_ie_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- unsigned char buf[IW_GENERIC_IE_MAX];
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- wrq.u.data.pointer = (caddr_t)buf;
- wrq.u.data.length = IW_GENERIC_IE_MAX;
- wrq.u.data.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWGENIE, &wrq) < 0)
- fprintf(stderr, "%-8.16s no generic IE (%s).\n\n",
- ifname, strerror(errno));
- else
- {
- fprintf(stderr, "%-8.16s\n", ifname);
- if(wrq.u.data.length == 0)
- printf(" empty generic IE\n");
- else
- iw_print_gen_ie(buf, wrq.u.data.length);
- printf("\n");
- }
- return(0);
- }
- /**************************** MODULATION ****************************/
- /*------------------------------------------------------------------*/
- /*
- * Print Modulation info for each device
- */
- static int
- print_modul_info(int skfd,
- char * ifname,
- char * args[], /* Command line args */
- int count) /* Args count */
- {
- struct iwreq wrq;
- struct iw_range range;
- /* Avoid "Unused parameter" warning */
- args = args; count = count;
- /* Extract range info */
- if((iw_get_range_info(skfd, ifname, &range) < 0) ||
- (range.we_version_compiled < 11))
- fprintf(stderr, "%-8.16s no modulation information.\n\n",
- ifname);
- else
- {
- if(range.modul_capa == 0x0)
- printf("%-8.16s unknown modulation information.\n\n", ifname);
- else
- {
- int i;
- printf("%-8.16s Modulations available :\n", ifname);
- /* Display each modulation available */
- for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
- {
- if((range.modul_capa & iw_modul_list[i].mask)
- == iw_modul_list[i].mask)
- printf(" %-8s: %s\n",
- iw_modul_list[i].cmd, iw_modul_list[i].verbose);
- }
- /* Get current modulations settings */
- wrq.u.param.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) >= 0)
- {
- unsigned int modul = wrq.u.param.value;
- int n = 0;
- printf(" Current modulations %c",
- wrq.u.param.fixed ? '=' : ':');
- /* Display each modulation enabled */
- for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
- {
- if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
- {
- if((n++ % 8) == 0)
- printf("\n ");
- else
- printf(" ; ");
- printf("%s", iw_modul_list[i].cmd);
- }
- }
- printf("\n");
- }
- printf("\n");
- }
- }
- return(0);
- }
- #endif /* WE_ESSENTIAL */
- /************************* COMMON UTILITIES *************************/
- /*
- * This section was initially written by Michael Tokarev <mjt@tls.msk.ru>
- * but heavily modified by me ;-)
- */
- /*------------------------------------------------------------------*/
- /*
- * Map command line arguments to the proper procedure...
- */
- typedef struct iwlist_entry {
- const char * cmd; /* Command line shorthand */
- iw_enum_handler fn; /* Subroutine */
- int max_count;
- const char * argsname; /* Args as human readable string */
- } iwlist_cmd;
- static const struct iwlist_entry iwlist_cmds[] = {
- { "scanning", print_scanning_info, -1, "[essid NNN] [last]" },
- { "frequency", print_freq_info, 0, NULL },
- { "channel", print_freq_info, 0, NULL },
- { "bitrate", print_bitrate_info, 0, NULL },
- { "rate", print_bitrate_info, 0, NULL },
- { "encryption", print_keys_info, 0, NULL },
- { "keys", print_keys_info, 0, NULL },
- { "power", print_pm_info, 0, NULL },
- #ifndef WE_ESSENTIAL
- { "txpower", print_txpower_info, 0, NULL },
- { "retry", print_retry_info, 0, NULL },
- { "ap", print_ap_info, 0, NULL },
- { "accesspoints", print_ap_info, 0, NULL },
- { "peers", print_ap_info, 0, NULL },
- { "event", print_event_capa_info, 0, NULL },
- { "auth", print_auth_info, 0, NULL },
- { "wpakeys", print_wpakeys_info, 0, NULL },
- { "genie", print_gen_ie_info, 0, NULL },
- { "modulation", print_modul_info, 0, NULL },
- #endif /* WE_ESSENTIAL */
- { NULL, NULL, 0, 0 },
- };
- /*------------------------------------------------------------------*/
- /*
- * Find the most appropriate command matching the command line
- */
- static inline const iwlist_cmd *
- find_command(const char * cmd)
- {
- const iwlist_cmd * found = NULL;
- int ambig = 0;
- unsigned int len = strlen(cmd);
- int i;
- /* Go through all commands */
- for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
- {
- /* No match -> next one */
- if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
- continue;
- /* Exact match -> perfect */
- if(len == strlen(iwlist_cmds[i].cmd))
- return &iwlist_cmds[i];
- /* Partial match */
- if(found == NULL)
- /* First time */
- found = &iwlist_cmds[i];
- else
- /* Another time */
- if (iwlist_cmds[i].fn != found->fn)
- ambig = 1;
- }
- if(found == NULL)
- {
- fprintf(stderr, "iwlist: unknown command `%s' (check 'iwlist --help').\n", cmd);
- return NULL;
- }
- if(ambig)
- {
- fprintf(stderr, "iwlist: command `%s' is ambiguous (check 'iwlist --help').\n", cmd);
- return NULL;
- }
- return found;
- }
- /*------------------------------------------------------------------*/
- /*
- * Display help
- */
- static void iw_usage(int status)
- {
- FILE * f = status ? stderr : stdout;
- int i;
- for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
- {
- fprintf(f, "%s [interface] %s %s\n",
- (i ? " " : "Usage: iwlist"),
- iwlist_cmds[i].cmd,
- iwlist_cmds[i].argsname ? iwlist_cmds[i].argsname : "");
- }
- exit(status);
- }
- /******************************* MAIN ********************************/
- /*------------------------------------------------------------------*/
- /*
- * The main !
- */
- int
- main(int argc,
- char ** argv)
- {
- int skfd; /* generic raw socket desc. */
- char *dev; /* device name */
- char *cmd; /* command */
- char **args; /* Command arguments */
- int count; /* Number of arguments */
- const iwlist_cmd *iwcmd;
- if(argc < 2)
- iw_usage(1);
- /* Those don't apply to all interfaces */
- if((argc == 2) && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))
- iw_usage(0);
- if((argc == 2) && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")))
- return(iw_print_version_info("iwlist"));
- if(argc == 2)
- {
- cmd = argv[1];
- dev = NULL;
- args = NULL;
- count = 0;
- }
- else
- {
- cmd = argv[2];
- dev = argv[1];
- args = argv + 3;
- count = argc - 3;
- }
- /* find a command */
- iwcmd = find_command(cmd);
- if(iwcmd == NULL)
- return 1;
- /* Check arg numbers */
- if((iwcmd->max_count >= 0) && (count > iwcmd->max_count))
- {
- fprintf(stderr, "iwlist: command `%s' needs fewer arguments (max %d)\n",
- iwcmd->cmd, iwcmd->max_count);
- return 1;
- }
- /* Create a channel to the NET kernel. */
- if((skfd = iw_sockets_open()) < 0)
- {
- perror("socket");
- return -1;
- }
- /* do the actual work */
- if (dev)
- (*iwcmd->fn)(skfd, dev, args, count);
- else
- iw_enum_devices(skfd, iwcmd->fn, args, count);
- /* Close the socket. */
- iw_sockets_close(skfd);
- return 0;
- }
|