iwlist.c 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217
  1. /*
  2. * Wireless Tools
  3. *
  4. * Jean II - HPLB '99 - HPL 99->07
  5. *
  6. * This tool can access various piece of information on the card
  7. * not part of iwconfig...
  8. * You need to link this code against "iwlist.c" and "-lm".
  9. *
  10. * This file is released under the GPL license.
  11. * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
  12. */
  13. #include "iwlib.h" /* Header */
  14. #include <sys/time.h>
  15. /****************************** TYPES ******************************/
  16. /*
  17. * Scan state and meta-information, used to decode events...
  18. */
  19. typedef struct iwscan_state
  20. {
  21. /* State */
  22. int ap_num; /* Access Point number 1->N */
  23. int val_index; /* Value in table 0->(N-1) */
  24. } iwscan_state;
  25. /*
  26. * Bit to name mapping
  27. */
  28. typedef struct iwmask_name
  29. {
  30. unsigned int mask; /* bit mask for the value */
  31. const char * name; /* human readable name for the value */
  32. } iwmask_name;
  33. /*
  34. * Types of authentication parameters
  35. */
  36. typedef struct iw_auth_descr
  37. {
  38. int value; /* Type of auth value */
  39. const char * label; /* User readable version */
  40. const struct iwmask_name * names; /* Names for this value */
  41. const int num_names; /* Number of names */
  42. } iw_auth_descr;
  43. /**************************** CONSTANTS ****************************/
  44. #define IW_SCAN_HACK 0x8000
  45. #define IW_EXTKEY_SIZE (sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX)
  46. /* ------------------------ WPA CAPA NAMES ------------------------ */
  47. /*
  48. * This is the user readable name of a bunch of WPA constants in wireless.h
  49. * Maybe this should go in iwlib.c ?
  50. */
  51. #ifndef WE_ESSENTIAL
  52. #define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0]))
  53. //static const struct iwmask_name iw_enc_mode_name[] = {
  54. // { IW_ENCODE_RESTRICTED, "restricted" },
  55. // { IW_ENCODE_OPEN, "open" },
  56. //};
  57. //#define IW_ENC_MODE_NUM IW_ARRAY_LEN(iw_enc_mode_name)
  58. static const struct iwmask_name iw_auth_capa_name[] = {
  59. { IW_ENC_CAPA_WPA, "WPA" },
  60. { IW_ENC_CAPA_WPA2, "WPA2" },
  61. { IW_ENC_CAPA_CIPHER_TKIP, "CIPHER-TKIP" },
  62. { IW_ENC_CAPA_CIPHER_CCMP, "CIPHER-CCMP" },
  63. };
  64. #define IW_AUTH_CAPA_NUM IW_ARRAY_LEN(iw_auth_capa_name)
  65. static const struct iwmask_name iw_auth_cypher_name[] = {
  66. { IW_AUTH_CIPHER_NONE, "none" },
  67. { IW_AUTH_CIPHER_WEP40, "WEP-40" },
  68. { IW_AUTH_CIPHER_TKIP, "TKIP" },
  69. { IW_AUTH_CIPHER_CCMP, "CCMP" },
  70. { IW_AUTH_CIPHER_WEP104, "WEP-104" },
  71. };
  72. #define IW_AUTH_CYPHER_NUM IW_ARRAY_LEN(iw_auth_cypher_name)
  73. static const struct iwmask_name iw_wpa_ver_name[] = {
  74. { IW_AUTH_WPA_VERSION_DISABLED, "disabled" },
  75. { IW_AUTH_WPA_VERSION_WPA, "WPA" },
  76. { IW_AUTH_WPA_VERSION_WPA2, "WPA2" },
  77. };
  78. #define IW_WPA_VER_NUM IW_ARRAY_LEN(iw_wpa_ver_name)
  79. static const struct iwmask_name iw_auth_key_mgmt_name[] = {
  80. { IW_AUTH_KEY_MGMT_802_1X, "802.1x" },
  81. { IW_AUTH_KEY_MGMT_PSK, "PSK" },
  82. };
  83. #define IW_AUTH_KEY_MGMT_NUM IW_ARRAY_LEN(iw_auth_key_mgmt_name)
  84. static const struct iwmask_name iw_auth_alg_name[] = {
  85. { IW_AUTH_ALG_OPEN_SYSTEM, "open" },
  86. { IW_AUTH_ALG_SHARED_KEY, "shared-key" },
  87. { IW_AUTH_ALG_LEAP, "LEAP" },
  88. };
  89. #define IW_AUTH_ALG_NUM IW_ARRAY_LEN(iw_auth_alg_name)
  90. static const struct iw_auth_descr iw_auth_settings[] = {
  91. { IW_AUTH_WPA_VERSION, "WPA version", iw_wpa_ver_name, IW_WPA_VER_NUM },
  92. { IW_AUTH_KEY_MGMT, "Key management", iw_auth_key_mgmt_name, IW_AUTH_KEY_MGMT_NUM },
  93. { IW_AUTH_CIPHER_PAIRWISE, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
  94. { IW_AUTH_CIPHER_GROUP, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
  95. { IW_AUTH_TKIP_COUNTERMEASURES, "TKIP countermeasures", NULL, 0 },
  96. { IW_AUTH_DROP_UNENCRYPTED, "Drop unencrypted", NULL, 0 },
  97. { IW_AUTH_80211_AUTH_ALG, "Authentication algorithm", iw_auth_alg_name, IW_AUTH_ALG_NUM },
  98. { IW_AUTH_RX_UNENCRYPTED_EAPOL, "Receive unencrypted EAPOL", NULL, 0 },
  99. { IW_AUTH_ROAMING_CONTROL, "Roaming control", NULL, 0 },
  100. { IW_AUTH_PRIVACY_INVOKED, "Privacy invoked", NULL, 0 },
  101. };
  102. #define IW_AUTH_SETTINGS_NUM IW_ARRAY_LEN(iw_auth_settings)
  103. /* Values for the IW_ENCODE_ALG_* returned by SIOCSIWENCODEEXT */
  104. static const char * iw_encode_alg_name[] = {
  105. "none",
  106. "WEP",
  107. "TKIP",
  108. "CCMP",
  109. "unknown"
  110. };
  111. #define IW_ENCODE_ALG_NUM IW_ARRAY_LEN(iw_encode_alg_name)
  112. #ifndef IW_IE_CIPHER_NONE
  113. /* Cypher values in GENIE (pairwise and group) */
  114. #define IW_IE_CIPHER_NONE 0
  115. #define IW_IE_CIPHER_WEP40 1
  116. #define IW_IE_CIPHER_TKIP 2
  117. #define IW_IE_CIPHER_WRAP 3
  118. #define IW_IE_CIPHER_CCMP 4
  119. #define IW_IE_CIPHER_WEP104 5
  120. /* Key management in GENIE */
  121. #define IW_IE_KEY_MGMT_NONE 0
  122. #define IW_IE_KEY_MGMT_802_1X 1
  123. #define IW_IE_KEY_MGMT_PSK 2
  124. #endif /* IW_IE_CIPHER_NONE */
  125. /* Values for the IW_IE_CIPHER_* in GENIE */
  126. static const char * iw_ie_cypher_name[] = {
  127. "none",
  128. "WEP-40",
  129. "TKIP",
  130. "WRAP",
  131. "CCMP",
  132. "WEP-104",
  133. };
  134. #define IW_IE_CYPHER_NUM IW_ARRAY_LEN(iw_ie_cypher_name)
  135. /* Values for the IW_IE_KEY_MGMT_* in GENIE */
  136. static const char * iw_ie_key_mgmt_name[] = {
  137. "none",
  138. "802.1x",
  139. "PSK",
  140. };
  141. #define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name)
  142. #endif /* WE_ESSENTIAL */
  143. /************************* WPA SUBROUTINES *************************/
  144. #ifndef WE_ESSENTIAL
  145. /*------------------------------------------------------------------*/
  146. /*
  147. * Print all names corresponding to a mask.
  148. * This may want to be used in iw_print_retry_value() ?
  149. */
  150. static void
  151. iw_print_mask_name(unsigned int mask,
  152. const struct iwmask_name names[],
  153. const unsigned int num_names,
  154. const char * sep)
  155. {
  156. unsigned int i;
  157. /* Print out all names for the bitmask */
  158. for(i = 0; i < num_names; i++)
  159. {
  160. if(mask & names[i].mask)
  161. {
  162. /* Print out */
  163. printf("%s%s", sep, names[i].name);
  164. /* Remove the bit from the mask */
  165. mask &= ~names[i].mask;
  166. }
  167. }
  168. /* If there is unconsumed bits... */
  169. if(mask != 0)
  170. printf("%sUnknown", sep);
  171. }
  172. /*------------------------------------------------------------------*/
  173. /*
  174. * Print the name corresponding to a value, with overflow check.
  175. */
  176. static void
  177. iw_print_value_name(unsigned int value,
  178. const char * names[],
  179. const unsigned int num_names)
  180. {
  181. if(value >= num_names)
  182. printf(" unknown (%d)", value);
  183. else
  184. printf(" %s", names[value]);
  185. }
  186. /*------------------------------------------------------------------*/
  187. /*
  188. * Parse, and display the results of an unknown IE.
  189. *
  190. */
  191. static void
  192. iw_print_ie_unknown(unsigned char * iebuf,
  193. int buflen)
  194. {
  195. int ielen = iebuf[1] + 2;
  196. int i;
  197. if(ielen > buflen)
  198. ielen = buflen;
  199. printf("Unknown: ");
  200. for(i = 0; i < ielen; i++)
  201. printf("%02X", iebuf[i]);
  202. printf("\n");
  203. }
  204. /*------------------------------------------------------------------*/
  205. /*
  206. * Parse, and display the results of a WPA or WPA2 IE.
  207. *
  208. */
  209. static inline void
  210. iw_print_ie_wpa(unsigned char * iebuf,
  211. int buflen)
  212. {
  213. int ielen = iebuf[1] + 2;
  214. int offset = 2; /* Skip the IE id, and the length. */
  215. unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
  216. unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
  217. unsigned char * wpa_oui;
  218. int i;
  219. uint16_t ver = 0;
  220. uint16_t cnt = 0;
  221. if(ielen > buflen)
  222. ielen = buflen;
  223. #ifdef DEBUG
  224. /* Debugging code. In theory useless, because it's debugged ;-) */
  225. printf("IE raw value %d [%02X", buflen, iebuf[0]);
  226. for(i = 1; i < buflen; i++)
  227. printf(":%02X", iebuf[i]);
  228. printf("]\n");
  229. #endif
  230. switch(iebuf[0])
  231. {
  232. case 0x30: /* WPA2 */
  233. /* Check if we have enough data */
  234. if(ielen < 4)
  235. {
  236. iw_print_ie_unknown(iebuf, buflen);
  237. return;
  238. }
  239. wpa_oui = wpa2_oui;
  240. break;
  241. case 0xdd: /* WPA or else */
  242. wpa_oui = wpa1_oui;
  243. /* Not all IEs that start with 0xdd are WPA.
  244. * So check that the OUI is valid. Note : offset==2 */
  245. if((ielen < 8)
  246. || (memcmp(&iebuf[offset], wpa_oui, 3) != 0)
  247. || (iebuf[offset + 3] != 0x01))
  248. {
  249. iw_print_ie_unknown(iebuf, buflen);
  250. return;
  251. }
  252. /* Skip the OUI type */
  253. offset += 4;
  254. break;
  255. default:
  256. return;
  257. }
  258. /* Pick version number (little endian) */
  259. ver = iebuf[offset] | (iebuf[offset + 1] << 8);
  260. offset += 2;
  261. if(iebuf[0] == 0xdd)
  262. printf("WPA Version %d\n", ver);
  263. if(iebuf[0] == 0x30)
  264. printf("IEEE 802.11i/WPA2 Version %d\n", ver);
  265. /* From here, everything is technically optional. */
  266. /* Check if we are done */
  267. if(ielen < (offset + 4))
  268. {
  269. /* We have a short IE. So we should assume TKIP/TKIP. */
  270. printf(" Group Cipher : TKIP\n");
  271. printf(" Pairwise Cipher : TKIP\n");
  272. return;
  273. }
  274. /* Next we have our group cipher. */
  275. if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
  276. {
  277. printf(" Group Cipher : Proprietary\n");
  278. }
  279. else
  280. {
  281. printf(" Group Cipher :");
  282. iw_print_value_name(iebuf[offset+3],
  283. iw_ie_cypher_name, IW_IE_CYPHER_NUM);
  284. printf("\n");
  285. }
  286. offset += 4;
  287. /* Check if we are done */
  288. if(ielen < (offset + 2))
  289. {
  290. /* We don't have a pairwise cipher, or auth method. Assume TKIP. */
  291. printf(" Pairwise Ciphers : TKIP\n");
  292. return;
  293. }
  294. /* Otherwise, we have some number of pairwise ciphers. */
  295. cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
  296. offset += 2;
  297. printf(" Pairwise Ciphers (%d) :", cnt);
  298. if(ielen < (offset + 4*cnt))
  299. return;
  300. for(i = 0; i < cnt; i++)
  301. {
  302. if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
  303. {
  304. printf(" Proprietary");
  305. }
  306. else
  307. {
  308. iw_print_value_name(iebuf[offset+3],
  309. iw_ie_cypher_name, IW_IE_CYPHER_NUM);
  310. }
  311. offset+=4;
  312. }
  313. printf("\n");
  314. /* Check if we are done */
  315. if(ielen < (offset + 2))
  316. return;
  317. /* Now, we have authentication suites. */
  318. cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
  319. offset += 2;
  320. printf(" Authentication Suites (%d) :", cnt);
  321. if(ielen < (offset + 4*cnt))
  322. return;
  323. for(i = 0; i < cnt; i++)
  324. {
  325. if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
  326. {
  327. printf(" Proprietary");
  328. }
  329. else
  330. {
  331. iw_print_value_name(iebuf[offset+3],
  332. iw_ie_key_mgmt_name, IW_IE_KEY_MGMT_NUM);
  333. }
  334. offset+=4;
  335. }
  336. printf("\n");
  337. /* Check if we are done */
  338. if(ielen < (offset + 1))
  339. return;
  340. /* Otherwise, we have capabilities bytes.
  341. * For now, we only care about preauth which is in bit position 1 of the
  342. * first byte. (But, preauth with WPA version 1 isn't supposed to be
  343. * allowed.) 8-) */
  344. if(iebuf[offset] & 0x01)
  345. {
  346. printf(" Preauthentication Supported\n");
  347. }
  348. }
  349. /*------------------------------------------------------------------*/
  350. /*
  351. * Process a generic IE and display the info in human readable form
  352. * for some of the most interesting ones.
  353. * For now, we only decode the WPA IEs.
  354. */
  355. static inline void
  356. iw_print_gen_ie(unsigned char * buffer,
  357. int buflen)
  358. {
  359. int offset = 0;
  360. /* Loop on each IE, each IE is minimum 2 bytes */
  361. while(offset <= (buflen - 2))
  362. {
  363. printf(" IE: ");
  364. /* Check IE type */
  365. switch(buffer[offset])
  366. {
  367. case 0xdd: /* WPA1 (and other) */
  368. case 0x30: /* WPA2 */
  369. iw_print_ie_wpa(buffer + offset, buflen);
  370. break;
  371. default:
  372. iw_print_ie_unknown(buffer + offset, buflen);
  373. }
  374. /* Skip over this IE to the next one in the list. */
  375. offset += buffer[offset+1] + 2;
  376. }
  377. }
  378. #endif /* WE_ESSENTIAL */
  379. /***************************** SCANNING *****************************/
  380. /*
  381. * This one behave quite differently from the others
  382. *
  383. * Note that we don't use the scanning capability of iwlib (functions
  384. * iw_process_scan() and iw_scan()). The main reason is that
  385. * iw_process_scan() return only a subset of the scan data to the caller,
  386. * for example custom elements and bitrates are ommited. Here, we
  387. * do the complete job...
  388. */
  389. /*------------------------------------------------------------------*/
  390. /*
  391. * Print one element from the scanning results
  392. */
  393. static inline void
  394. print_scanning_token(struct stream_descr * stream, /* Stream of events */
  395. struct iw_event * event, /* Extracted token */
  396. struct iwscan_state * state,
  397. struct iw_range * iw_range, /* Range info */
  398. int has_range)
  399. {
  400. char buffer[128]; /* Temporary buffer */
  401. /* Now, let's decode the event */
  402. switch(event->cmd)
  403. {
  404. case SIOCGIWAP:
  405. printf(" Cell %02d - Address: %s\n", state->ap_num,
  406. iw_saether_ntop(&event->u.ap_addr, buffer));
  407. state->ap_num++;
  408. break;
  409. case SIOCGIWNWID:
  410. if(event->u.nwid.disabled)
  411. printf(" NWID:off/any\n");
  412. else
  413. printf(" NWID:%X\n", event->u.nwid.value);
  414. break;
  415. case SIOCGIWFREQ:
  416. {
  417. double freq; /* Frequency/channel */
  418. int channel = -1; /* Converted to channel */
  419. freq = iw_freq2float(&(event->u.freq));
  420. /* Convert to channel if possible */
  421. if(has_range)
  422. channel = iw_freq_to_channel(freq, iw_range);
  423. iw_print_freq(buffer, sizeof(buffer),
  424. freq, channel, event->u.freq.flags);
  425. printf(" %s\n", buffer);
  426. }
  427. break;
  428. case SIOCGIWMODE:
  429. /* Note : event->u.mode is unsigned, no need to check <= 0 */
  430. if(event->u.mode >= IW_NUM_OPER_MODE)
  431. event->u.mode = IW_NUM_OPER_MODE;
  432. printf(" Mode:%s\n",
  433. iw_operation_mode[event->u.mode]);
  434. break;
  435. case SIOCGIWNAME:
  436. printf(" Protocol:%-1.16s\n", event->u.name);
  437. break;
  438. case SIOCGIWESSID:
  439. {
  440. char essid[IW_ESSID_MAX_SIZE+1];
  441. memset(essid, '\0', sizeof(essid));
  442. if((event->u.essid.pointer) && (event->u.essid.length))
  443. memcpy(essid, event->u.essid.pointer, event->u.essid.length);
  444. if(event->u.essid.flags)
  445. {
  446. /* Does it have an ESSID index ? */
  447. if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)
  448. printf(" ESSID:\"%s\" [%d]\n", essid,
  449. (event->u.essid.flags & IW_ENCODE_INDEX));
  450. else
  451. printf(" ESSID:\"%s\"\n", essid);
  452. }
  453. else
  454. printf(" ESSID:off/any/hidden\n");
  455. }
  456. break;
  457. case SIOCGIWENCODE:
  458. {
  459. unsigned char key[IW_ENCODING_TOKEN_MAX];
  460. if(event->u.data.pointer)
  461. memcpy(key, event->u.data.pointer, event->u.data.length);
  462. else
  463. event->u.data.flags |= IW_ENCODE_NOKEY;
  464. printf(" Encryption key:");
  465. if(event->u.data.flags & IW_ENCODE_DISABLED)
  466. printf("off\n");
  467. else
  468. {
  469. /* Display the key */
  470. iw_print_key(buffer, sizeof(buffer), key, event->u.data.length,
  471. event->u.data.flags);
  472. printf("%s", buffer);
  473. /* Other info... */
  474. if((event->u.data.flags & IW_ENCODE_INDEX) > 1)
  475. printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX);
  476. if(event->u.data.flags & IW_ENCODE_RESTRICTED)
  477. printf(" Security mode:restricted");
  478. if(event->u.data.flags & IW_ENCODE_OPEN)
  479. printf(" Security mode:open");
  480. printf("\n");
  481. }
  482. }
  483. break;
  484. case SIOCGIWRATE:
  485. if(state->val_index == 0)
  486. printf(" Bit Rates:");
  487. else
  488. if((state->val_index % 5) == 0)
  489. printf("\n ");
  490. else
  491. printf("; ");
  492. iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);
  493. printf("%s", buffer);
  494. /* Check for termination */
  495. if(stream->value == NULL)
  496. {
  497. printf("\n");
  498. state->val_index = 0;
  499. }
  500. else
  501. state->val_index++;
  502. break;
  503. case SIOCGIWMODUL:
  504. {
  505. unsigned int modul = event->u.param.value;
  506. int i;
  507. int n = 0;
  508. printf(" Modulations :");
  509. for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
  510. {
  511. if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
  512. {
  513. if((n++ % 8) == 7)
  514. printf("\n ");
  515. else
  516. printf(" ; ");
  517. printf("%s", iw_modul_list[i].cmd);
  518. }
  519. }
  520. printf("\n");
  521. }
  522. break;
  523. case IWEVQUAL:
  524. iw_print_stats(buffer, sizeof(buffer),
  525. &event->u.qual, iw_range, has_range);
  526. printf(" %s\n", buffer);
  527. break;
  528. #ifndef WE_ESSENTIAL
  529. case IWEVGENIE:
  530. /* Informations Elements are complex, let's do only some of them */
  531. iw_print_gen_ie(event->u.data.pointer, event->u.data.length);
  532. break;
  533. #endif /* WE_ESSENTIAL */
  534. case IWEVCUSTOM:
  535. {
  536. char custom[IW_CUSTOM_MAX+1];
  537. if((event->u.data.pointer) && (event->u.data.length))
  538. memcpy(custom, event->u.data.pointer, event->u.data.length);
  539. custom[event->u.data.length] = '\0';
  540. printf(" Extra:%s\n", custom);
  541. }
  542. break;
  543. default:
  544. printf(" (Unknown Wireless Token 0x%04X)\n",
  545. event->cmd);
  546. } /* switch(event->cmd) */
  547. }
  548. /*------------------------------------------------------------------*/
  549. /*
  550. * Perform a scanning on one device
  551. */
  552. static int
  553. print_scanning_info(int skfd,
  554. char * ifname,
  555. char * args[], /* Command line args */
  556. int count) /* Args count */
  557. {
  558. struct iwreq wrq;
  559. struct iw_scan_req scanopt; /* Options for 'set' */
  560. int scanflags = 0; /* Flags for scan */
  561. unsigned char * buffer = NULL; /* Results */
  562. int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
  563. struct iw_range range;
  564. int has_range;
  565. struct timeval tv; /* Select timeout */
  566. int timeout = 15000000; /* 15s */
  567. /* Avoid "Unused parameter" warning */
  568. args = args; count = count;
  569. /* Debugging stuff */
  570. if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN))
  571. {
  572. fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n");
  573. fprintf(stderr, "*** and the following line :\n");
  574. fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n",
  575. IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN);
  576. }
  577. /* Get range stuff */
  578. has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
  579. /* Check if the interface could support scanning. */
  580. if((!has_range) || (range.we_version_compiled < 14))
  581. {
  582. fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n",
  583. ifname);
  584. return(-1);
  585. }
  586. /* Init timeout value -> 250ms between set and first get */
  587. tv.tv_sec = 0;
  588. tv.tv_usec = 250000;
  589. /* Clean up set args */
  590. memset(&scanopt, 0, sizeof(scanopt));
  591. /* Parse command line arguments and extract options.
  592. * Note : when we have enough options, we should use the parser
  593. * from iwconfig... */
  594. while(count > 0)
  595. {
  596. /* One arg is consumed (the option name) */
  597. count--;
  598. /*
  599. * Check for Active Scan (scan with specific essid)
  600. */
  601. if(!strncmp(args[0], "essid", 5))
  602. {
  603. if(count < 1)
  604. {
  605. fprintf(stderr, "Too few arguments for scanning option [%s]\n",
  606. args[0]);
  607. return(-1);
  608. }
  609. args++;
  610. count--;
  611. /* Store the ESSID in the scan options */
  612. scanopt.essid_len = strlen(args[0]);
  613. memcpy(scanopt.essid, args[0], scanopt.essid_len);
  614. /* Initialise BSSID as needed */
  615. if(scanopt.bssid.sa_family == 0)
  616. {
  617. scanopt.bssid.sa_family = ARPHRD_ETHER;
  618. memset(scanopt.bssid.sa_data, 0xff, ETH_ALEN);
  619. }
  620. /* Scan only this ESSID */
  621. scanflags |= IW_SCAN_THIS_ESSID;
  622. }
  623. else
  624. /* Check for last scan result (do not trigger scan) */
  625. if(!strncmp(args[0], "last", 4))
  626. {
  627. /* Hack */
  628. scanflags |= IW_SCAN_HACK;
  629. }
  630. else
  631. {
  632. fprintf(stderr, "Invalid scanning option [%s]\n", args[0]);
  633. return(-1);
  634. }
  635. /* Next arg */
  636. args++;
  637. }
  638. /* Check if we have scan options */
  639. if(scanflags)
  640. {
  641. wrq.u.data.pointer = (caddr_t) &scanopt;
  642. wrq.u.data.length = sizeof(scanopt);
  643. wrq.u.data.flags = scanflags;
  644. }
  645. else
  646. {
  647. wrq.u.data.pointer = NULL;
  648. wrq.u.data.flags = 0;
  649. wrq.u.data.length = 0;
  650. }
  651. /* If only 'last' was specified on command line, don't trigger a scan */
  652. if(scanflags == IW_SCAN_HACK)
  653. {
  654. /* Skip waiting */
  655. tv.tv_usec = 0;
  656. }
  657. else
  658. {
  659. /* Initiate Scanning */
  660. if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
  661. {
  662. if((errno != EPERM) || (scanflags != 0))
  663. {
  664. fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
  665. ifname, strerror(errno));
  666. return(-1);
  667. }
  668. /* If we don't have the permission to initiate the scan, we may
  669. * still have permission to read left-over results.
  670. * But, don't wait !!! */
  671. #if 0
  672. /* Not cool, it display for non wireless interfaces... */
  673. fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
  674. #endif
  675. tv.tv_usec = 0;
  676. }
  677. }
  678. timeout -= tv.tv_usec;
  679. /* Forever */
  680. while(1)
  681. {
  682. fd_set rfds; /* File descriptors for select */
  683. int last_fd; /* Last fd */
  684. int ret;
  685. /* Guess what ? We must re-generate rfds each time */
  686. FD_ZERO(&rfds);
  687. last_fd = -1;
  688. /* In here, add the rtnetlink fd in the list */
  689. /* Wait until something happens */
  690. ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
  691. /* Check if there was an error */
  692. if(ret < 0)
  693. {
  694. if(errno == EAGAIN || errno == EINTR)
  695. continue;
  696. fprintf(stderr, "Unhandled signal - exiting...\n");
  697. return(-1);
  698. }
  699. /* Check if there was a timeout */
  700. if(ret == 0)
  701. {
  702. unsigned char * newbuf;
  703. realloc:
  704. /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
  705. newbuf = realloc(buffer, buflen);
  706. if(newbuf == NULL)
  707. {
  708. if(buffer)
  709. free(buffer);
  710. fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
  711. return(-1);
  712. }
  713. buffer = newbuf;
  714. /* Try to read the results */
  715. wrq.u.data.pointer = buffer;
  716. wrq.u.data.flags = 0;
  717. wrq.u.data.length = buflen;
  718. if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
  719. {
  720. /* Check if buffer was too small (WE-17 only) */
  721. if((errno == E2BIG) && (range.we_version_compiled > 16))
  722. {
  723. /* Some driver may return very large scan results, either
  724. * because there are many cells, or because they have many
  725. * large elements in cells (like IWEVCUSTOM). Most will
  726. * only need the regular sized buffer. We now use a dynamic
  727. * allocation of the buffer to satisfy everybody. Of course,
  728. * as we don't know in advance the size of the array, we try
  729. * various increasing sizes. Jean II */
  730. /* Check if the driver gave us any hints. */
  731. if(wrq.u.data.length > buflen)
  732. buflen = wrq.u.data.length;
  733. else
  734. buflen *= 2;
  735. /* Try again */
  736. goto realloc;
  737. }
  738. /* Check if results not available yet */
  739. if(errno == EAGAIN)
  740. {
  741. /* Restart timer for only 100ms*/
  742. tv.tv_sec = 0;
  743. tv.tv_usec = 100000;
  744. timeout -= tv.tv_usec;
  745. if(timeout > 0)
  746. continue; /* Try again later */
  747. }
  748. /* Bad error */
  749. free(buffer);
  750. fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
  751. ifname, strerror(errno));
  752. return(-2);
  753. }
  754. else
  755. /* We have the results, go to process them */
  756. break;
  757. }
  758. /* In here, check if event and event type
  759. * if scan event, read results. All errors bad & no reset timeout */
  760. }
  761. if(wrq.u.data.length)
  762. {
  763. struct iw_event iwe;
  764. struct stream_descr stream;
  765. struct iwscan_state state = { .ap_num = 1, .val_index = 0 };
  766. int ret;
  767. #ifdef DEBUG
  768. /* Debugging code. In theory useless, because it's debugged ;-) */
  769. int i;
  770. printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
  771. for(i = 1; i < wrq.u.data.length; i++)
  772. printf(":%02X", buffer[i]);
  773. printf("]\n");
  774. #endif
  775. printf("%-8.16s Scan completed :\n", ifname);
  776. iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
  777. do
  778. {
  779. /* Extract an event and print it */
  780. ret = iw_extract_event_stream(&stream, &iwe,
  781. range.we_version_compiled);
  782. if(ret > 0)
  783. print_scanning_token(&stream, &iwe, &state,
  784. &range, has_range);
  785. }
  786. while(ret > 0);
  787. printf("\n");
  788. }
  789. else
  790. printf("%-8.16s No scan results\n\n", ifname);
  791. free(buffer);
  792. return(0);
  793. }
  794. /*********************** FREQUENCIES/CHANNELS ***********************/
  795. /*------------------------------------------------------------------*/
  796. /*
  797. * Print the number of channels and available frequency for the device
  798. */
  799. static int
  800. print_freq_info(int skfd,
  801. char * ifname,
  802. char * args[], /* Command line args */
  803. int count) /* Args count */
  804. {
  805. struct iwreq wrq;
  806. struct iw_range range;
  807. double freq;
  808. int k;
  809. int channel;
  810. char buffer[128]; /* Temporary buffer */
  811. /* Avoid "Unused parameter" warning */
  812. args = args; count = count;
  813. /* Get list of frequencies / channels */
  814. if(iw_get_range_info(skfd, ifname, &range) < 0)
  815. fprintf(stderr, "%-8.16s no frequency information.\n\n",
  816. ifname);
  817. else
  818. {
  819. if(range.num_frequency > 0)
  820. {
  821. printf("%-8.16s %d channels in total; available frequencies :\n",
  822. ifname, range.num_channels);
  823. /* Print them all */
  824. for(k = 0; k < range.num_frequency; k++)
  825. {
  826. freq = iw_freq2float(&(range.freq[k]));
  827. iw_print_freq_value(buffer, sizeof(buffer), freq);
  828. printf(" Channel %.2d : %s\n",
  829. range.freq[k].i, buffer);
  830. }
  831. }
  832. else
  833. printf("%-8.16s %d channels\n",
  834. ifname, range.num_channels);
  835. /* Get current frequency / channel and display it */
  836. if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
  837. {
  838. freq = iw_freq2float(&(wrq.u.freq));
  839. channel = iw_freq_to_channel(freq, &range);
  840. iw_print_freq(buffer, sizeof(buffer),
  841. freq, channel, wrq.u.freq.flags);
  842. printf(" Current %s\n\n", buffer);
  843. }
  844. }
  845. return(0);
  846. }
  847. /***************************** BITRATES *****************************/
  848. /*------------------------------------------------------------------*/
  849. /*
  850. * Print the number of available bitrates for the device
  851. */
  852. static int
  853. print_bitrate_info(int skfd,
  854. char * ifname,
  855. char * args[], /* Command line args */
  856. int count) /* Args count */
  857. {
  858. struct iwreq wrq;
  859. struct iw_range range;
  860. int k;
  861. char buffer[128];
  862. /* Avoid "Unused parameter" warning */
  863. args = args; count = count;
  864. /* Extract range info */
  865. if(iw_get_range_info(skfd, ifname, &range) < 0)
  866. fprintf(stderr, "%-8.16s no bit-rate information.\n\n",
  867. ifname);
  868. else
  869. {
  870. if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
  871. {
  872. printf("%-8.16s %d available bit-rates :\n",
  873. ifname, range.num_bitrates);
  874. /* Print them all */
  875. for(k = 0; k < range.num_bitrates; k++)
  876. {
  877. iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
  878. /* Maybe this should be %10s */
  879. printf("\t %s\n", buffer);
  880. }
  881. }
  882. else
  883. printf("%-8.16s unknown bit-rate information.\n", ifname);
  884. /* Get current bit rate */
  885. if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
  886. {
  887. iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
  888. printf(" Current Bit Rate%c%s\n",
  889. (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
  890. }
  891. /* Try to get the broadcast bitrate if it exist... */
  892. if(range.bitrate_capa & IW_BITRATE_BROADCAST)
  893. {
  894. wrq.u.bitrate.flags = IW_BITRATE_BROADCAST;
  895. if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
  896. {
  897. iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
  898. printf(" Broadcast Bit Rate%c%s\n",
  899. (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
  900. }
  901. }
  902. printf("\n");
  903. }
  904. return(0);
  905. }
  906. /************************* ENCRYPTION KEYS *************************/
  907. /*------------------------------------------------------------------*/
  908. /*
  909. * Print all the available encryption keys for the device
  910. */
  911. static int
  912. print_keys_info(int skfd,
  913. char * ifname,
  914. char * args[], /* Command line args */
  915. int count) /* Args count */
  916. {
  917. struct iwreq wrq;
  918. struct iw_range range;
  919. unsigned char key[IW_ENCODING_TOKEN_MAX];
  920. unsigned int k;
  921. char buffer[128];
  922. /* Avoid "Unused parameter" warning */
  923. args = args; count = count;
  924. /* Extract range info */
  925. if(iw_get_range_info(skfd, ifname, &range) < 0)
  926. fprintf(stderr, "%-8.16s no encryption keys information.\n\n",
  927. ifname);
  928. else
  929. {
  930. printf("%-8.16s ", ifname);
  931. /* Print key sizes */
  932. if((range.num_encoding_sizes > 0) &&
  933. (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
  934. {
  935. printf("%d key sizes : %d", range.num_encoding_sizes,
  936. range.encoding_size[0] * 8);
  937. /* Print them all */
  938. for(k = 1; k < range.num_encoding_sizes; k++)
  939. printf(", %d", range.encoding_size[k] * 8);
  940. printf("bits\n ");
  941. }
  942. /* Print the keys and associate mode */
  943. printf("%d keys available :\n", range.max_encoding_tokens);
  944. for(k = 1; k <= range.max_encoding_tokens; k++)
  945. {
  946. wrq.u.data.pointer = (caddr_t) key;
  947. wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
  948. wrq.u.data.flags = k;
  949. if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
  950. {
  951. fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno));
  952. break;
  953. }
  954. if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
  955. (wrq.u.data.length == 0))
  956. printf("\t\t[%d]: off\n", k);
  957. else
  958. {
  959. /* Display the key */
  960. iw_print_key(buffer, sizeof(buffer),
  961. key, wrq.u.data.length, wrq.u.data.flags);
  962. printf("\t\t[%d]: %s", k, buffer);
  963. /* Other info... */
  964. printf(" (%d bits)", wrq.u.data.length * 8);
  965. printf("\n");
  966. }
  967. }
  968. /* Print current key index and mode */
  969. wrq.u.data.pointer = (caddr_t) key;
  970. wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
  971. wrq.u.data.flags = 0; /* Set index to zero to get current */
  972. if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
  973. {
  974. /* Note : if above fails, we have already printed an error
  975. * message int the loop above */
  976. printf(" Current Transmit Key: [%d]\n",
  977. wrq.u.data.flags & IW_ENCODE_INDEX);
  978. if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
  979. printf(" Security mode:restricted\n");
  980. if(wrq.u.data.flags & IW_ENCODE_OPEN)
  981. printf(" Security mode:open\n");
  982. }
  983. printf("\n\n");
  984. }
  985. return(0);
  986. }
  987. /************************* POWER MANAGEMENT *************************/
  988. /*------------------------------------------------------------------*/
  989. /*
  990. * Print Power Management info for each device
  991. */
  992. static int
  993. get_pm_value(int skfd,
  994. char * ifname,
  995. struct iwreq * pwrq,
  996. int flags,
  997. char * buffer,
  998. int buflen,
  999. int we_version_compiled)
  1000. {
  1001. /* Get Another Power Management value */
  1002. pwrq->u.power.flags = flags;
  1003. if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
  1004. {
  1005. /* Let's check the value and its type */
  1006. if(pwrq->u.power.flags & IW_POWER_TYPE)
  1007. {
  1008. iw_print_pm_value(buffer, buflen,
  1009. pwrq->u.power.value, pwrq->u.power.flags,
  1010. we_version_compiled);
  1011. printf("\n %s", buffer);
  1012. }
  1013. }
  1014. return(pwrq->u.power.flags);
  1015. }
  1016. /*------------------------------------------------------------------*/
  1017. /*
  1018. * Print Power Management range for each type
  1019. */
  1020. static void
  1021. print_pm_value_range(char * name,
  1022. int mask,
  1023. int iwr_flags,
  1024. int iwr_min,
  1025. int iwr_max,
  1026. char * buffer,
  1027. int buflen,
  1028. int we_version_compiled)
  1029. {
  1030. if(iwr_flags & mask)
  1031. {
  1032. int flags = (iwr_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
  1033. /* Display if auto or fixed */
  1034. printf("%s %s ; ",
  1035. (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
  1036. name);
  1037. /* Print the range */
  1038. iw_print_pm_value(buffer, buflen,
  1039. iwr_min, flags | IW_POWER_MIN,
  1040. we_version_compiled);
  1041. printf("%s\n ", buffer);
  1042. iw_print_pm_value(buffer, buflen,
  1043. iwr_max, flags | IW_POWER_MAX,
  1044. we_version_compiled);
  1045. printf("%s\n ", buffer);
  1046. }
  1047. }
  1048. /*------------------------------------------------------------------*/
  1049. /*
  1050. * Power Management types of values
  1051. */
  1052. static const unsigned int pm_type_flags[] = {
  1053. IW_POWER_PERIOD,
  1054. IW_POWER_TIMEOUT,
  1055. IW_POWER_SAVING,
  1056. };
  1057. static const int pm_type_flags_size = (sizeof(pm_type_flags)/sizeof(pm_type_flags[0]));
  1058. /*------------------------------------------------------------------*/
  1059. /*
  1060. * Print Power Management info for each device
  1061. */
  1062. static int
  1063. print_pm_info(int skfd,
  1064. char * ifname,
  1065. char * args[], /* Command line args */
  1066. int count) /* Args count */
  1067. {
  1068. struct iwreq wrq;
  1069. struct iw_range range;
  1070. char buffer[128];
  1071. /* Avoid "Unused parameter" warning */
  1072. args = args; count = count;
  1073. /* Extract range info */
  1074. if((iw_get_range_info(skfd, ifname, &range) < 0) ||
  1075. (range.we_version_compiled < 10))
  1076. fprintf(stderr, "%-8.16s no power management information.\n\n",
  1077. ifname);
  1078. else
  1079. {
  1080. printf("%-8.16s ", ifname);
  1081. /* Display modes availables */
  1082. if(range.pm_capa & IW_POWER_MODE)
  1083. {
  1084. printf("Supported modes :\n ");
  1085. if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
  1086. printf("\t\to Receive all packets (unicast & multicast)\n ");
  1087. if(range.pm_capa & IW_POWER_UNICAST_R)
  1088. printf("\t\to Receive Unicast only (discard multicast)\n ");
  1089. if(range.pm_capa & IW_POWER_MULTICAST_R)
  1090. printf("\t\to Receive Multicast only (discard unicast)\n ");
  1091. if(range.pm_capa & IW_POWER_FORCE_S)
  1092. printf("\t\to Force sending using Power Management\n ");
  1093. if(range.pm_capa & IW_POWER_REPEATER)
  1094. printf("\t\to Repeat multicast\n ");
  1095. }
  1096. /* Display min/max period availables */
  1097. print_pm_value_range("period ", IW_POWER_PERIOD,
  1098. range.pmp_flags, range.min_pmp, range.max_pmp,
  1099. buffer, sizeof(buffer), range.we_version_compiled);
  1100. /* Display min/max timeout availables */
  1101. print_pm_value_range("timeout", IW_POWER_TIMEOUT,
  1102. range.pmt_flags, range.min_pmt, range.max_pmt,
  1103. buffer, sizeof(buffer), range.we_version_compiled);
  1104. /* Display min/max saving availables */
  1105. print_pm_value_range("saving ", IW_POWER_SAVING,
  1106. range.pms_flags, range.min_pms, range.max_pms,
  1107. buffer, sizeof(buffer), range.we_version_compiled);
  1108. /* Get current Power Management settings */
  1109. wrq.u.power.flags = 0;
  1110. if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
  1111. {
  1112. int flags = wrq.u.power.flags;
  1113. /* Is it disabled ? */
  1114. if(wrq.u.power.disabled)
  1115. printf("Current mode:off\n");
  1116. else
  1117. {
  1118. unsigned int pm_type = 0;
  1119. unsigned int pm_mask = 0;
  1120. unsigned int remain_mask = range.pm_capa & IW_POWER_TYPE;
  1121. int i = 0;
  1122. /* Let's check the mode */
  1123. iw_print_pm_mode(buffer, sizeof(buffer), flags);
  1124. printf("Current %s", buffer);
  1125. /* Let's check if nothing (simply on) */
  1126. if((flags & IW_POWER_MODE) == IW_POWER_ON)
  1127. printf("mode:on");
  1128. /* Let's check the value and its type */
  1129. if(wrq.u.power.flags & IW_POWER_TYPE)
  1130. {
  1131. iw_print_pm_value(buffer, sizeof(buffer),
  1132. wrq.u.power.value, wrq.u.power.flags,
  1133. range.we_version_compiled);
  1134. printf("\n %s", buffer);
  1135. }
  1136. while(1)
  1137. {
  1138. /* Deal with min/max for the current value */
  1139. pm_mask = 0;
  1140. /* If we have been returned a MIN value, ask for the MAX */
  1141. if(flags & IW_POWER_MIN)
  1142. pm_mask = IW_POWER_MAX;
  1143. /* If we have been returned a MAX value, ask for the MIN */
  1144. if(flags & IW_POWER_MAX)
  1145. pm_mask = IW_POWER_MIN;
  1146. /* If we have something to ask for... */
  1147. if(pm_mask)
  1148. {
  1149. pm_mask |= pm_type;
  1150. get_pm_value(skfd, ifname, &wrq, pm_mask,
  1151. buffer, sizeof(buffer),
  1152. range.we_version_compiled);
  1153. }
  1154. /* Remove current type from mask */
  1155. remain_mask &= ~(wrq.u.power.flags);
  1156. /* Check what other types we still have to read */
  1157. while(i < pm_type_flags_size)
  1158. {
  1159. pm_type = remain_mask & pm_type_flags[i];
  1160. if(pm_type)
  1161. break;
  1162. i++;
  1163. }
  1164. /* Nothing anymore : exit the loop */
  1165. if(!pm_type)
  1166. break;
  1167. /* Ask for this other type of value */
  1168. flags = get_pm_value(skfd, ifname, &wrq, pm_type,
  1169. buffer, sizeof(buffer),
  1170. range.we_version_compiled);
  1171. /* Loop back for min/max */
  1172. }
  1173. printf("\n");
  1174. }
  1175. }
  1176. printf("\n");
  1177. }
  1178. return(0);
  1179. }
  1180. #ifndef WE_ESSENTIAL
  1181. /************************** TRANSMIT POWER **************************/
  1182. /*------------------------------------------------------------------*/
  1183. /*
  1184. * Print the number of available transmit powers for the device
  1185. */
  1186. static int
  1187. print_txpower_info(int skfd,
  1188. char * ifname,
  1189. char * args[], /* Command line args */
  1190. int count) /* Args count */
  1191. {
  1192. struct iwreq wrq;
  1193. struct iw_range range;
  1194. int dbm;
  1195. int mwatt;
  1196. int k;
  1197. /* Avoid "Unused parameter" warning */
  1198. args = args; count = count;
  1199. /* Extract range info */
  1200. if((iw_get_range_info(skfd, ifname, &range) < 0) ||
  1201. (range.we_version_compiled < 10))
  1202. fprintf(stderr, "%-8.16s no transmit-power information.\n\n",
  1203. ifname);
  1204. else
  1205. {
  1206. if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
  1207. printf("%-8.16s unknown transmit-power information.\n\n", ifname);
  1208. else
  1209. {
  1210. printf("%-8.16s %d available transmit-powers :\n",
  1211. ifname, range.num_txpower);
  1212. /* Print them all */
  1213. for(k = 0; k < range.num_txpower; k++)
  1214. {
  1215. /* Check for relative values */
  1216. if(range.txpower_capa & IW_TXPOW_RELATIVE)
  1217. {
  1218. printf("\t %d (no units)\n", range.txpower[k]);
  1219. }
  1220. else
  1221. {
  1222. if(range.txpower_capa & IW_TXPOW_MWATT)
  1223. {
  1224. dbm = iw_mwatt2dbm(range.txpower[k]);
  1225. mwatt = range.txpower[k];
  1226. }
  1227. else
  1228. {
  1229. dbm = range.txpower[k];
  1230. mwatt = iw_dbm2mwatt(range.txpower[k]);
  1231. }
  1232. printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
  1233. }
  1234. }
  1235. }
  1236. /* Get current Transmit Power */
  1237. if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
  1238. {
  1239. printf(" Current Tx-Power");
  1240. /* Disabled ? */
  1241. if(wrq.u.txpower.disabled)
  1242. printf(":off\n\n");
  1243. else
  1244. {
  1245. /* Fixed ? */
  1246. if(wrq.u.txpower.fixed)
  1247. printf("=");
  1248. else
  1249. printf(":");
  1250. /* Check for relative values */
  1251. if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
  1252. {
  1253. /* I just hate relative value, because they are
  1254. * driver specific, so not very meaningfull to apps.
  1255. * But, we have to support that, because
  1256. * this is the way hardware is... */
  1257. printf("\t %d (no units)\n", wrq.u.txpower.value);
  1258. }
  1259. else
  1260. {
  1261. if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
  1262. {
  1263. dbm = iw_mwatt2dbm(wrq.u.txpower.value);
  1264. mwatt = wrq.u.txpower.value;
  1265. }
  1266. else
  1267. {
  1268. dbm = wrq.u.txpower.value;
  1269. mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
  1270. }
  1271. printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
  1272. }
  1273. }
  1274. }
  1275. }
  1276. return(0);
  1277. }
  1278. /*********************** RETRY LIMIT/LIFETIME ***********************/
  1279. /*------------------------------------------------------------------*/
  1280. /*
  1281. * Print one retry value
  1282. */
  1283. static int
  1284. get_retry_value(int skfd,
  1285. char * ifname,
  1286. struct iwreq * pwrq,
  1287. int flags,
  1288. char * buffer,
  1289. int buflen,
  1290. int we_version_compiled)
  1291. {
  1292. /* Get Another retry value */
  1293. pwrq->u.retry.flags = flags;
  1294. if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
  1295. {
  1296. /* Let's check the value and its type */
  1297. if(pwrq->u.retry.flags & IW_RETRY_TYPE)
  1298. {
  1299. iw_print_retry_value(buffer, buflen,
  1300. pwrq->u.retry.value, pwrq->u.retry.flags,
  1301. we_version_compiled);
  1302. printf("%s\n ", buffer);
  1303. }
  1304. }
  1305. return(pwrq->u.retry.flags);
  1306. }
  1307. /*------------------------------------------------------------------*/
  1308. /*
  1309. * Print Power Management range for each type
  1310. */
  1311. static void
  1312. print_retry_value_range(char * name,
  1313. int mask,
  1314. int iwr_flags,
  1315. int iwr_min,
  1316. int iwr_max,
  1317. char * buffer,
  1318. int buflen,
  1319. int we_version_compiled)
  1320. {
  1321. if(iwr_flags & mask)
  1322. {
  1323. int flags = (iwr_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
  1324. /* Display if auto or fixed */
  1325. printf("%s %s ; ",
  1326. (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
  1327. name);
  1328. /* Print the range */
  1329. iw_print_retry_value(buffer, buflen,
  1330. iwr_min, flags | IW_POWER_MIN,
  1331. we_version_compiled);
  1332. printf("%s\n ", buffer);
  1333. iw_print_retry_value(buffer, buflen,
  1334. iwr_max, flags | IW_POWER_MAX,
  1335. we_version_compiled);
  1336. printf("%s\n ", buffer);
  1337. }
  1338. }
  1339. /*------------------------------------------------------------------*/
  1340. /*
  1341. * Print Retry info for each device
  1342. */
  1343. static int
  1344. print_retry_info(int skfd,
  1345. char * ifname,
  1346. char * args[], /* Command line args */
  1347. int count) /* Args count */
  1348. {
  1349. struct iwreq wrq;
  1350. struct iw_range range;
  1351. char buffer[128];
  1352. /* Avoid "Unused parameter" warning */
  1353. args = args; count = count;
  1354. /* Extract range info */
  1355. if((iw_get_range_info(skfd, ifname, &range) < 0) ||
  1356. (range.we_version_compiled < 11))
  1357. fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n",
  1358. ifname);
  1359. else
  1360. {
  1361. printf("%-8.16s ", ifname);
  1362. /* Display min/max limit availables */
  1363. print_retry_value_range("limit ", IW_RETRY_LIMIT, range.retry_flags,
  1364. range.min_retry, range.max_retry,
  1365. buffer, sizeof(buffer),
  1366. range.we_version_compiled);
  1367. /* Display min/max lifetime availables */
  1368. print_retry_value_range("lifetime", IW_RETRY_LIFETIME,
  1369. range.r_time_flags,
  1370. range.min_r_time, range.max_r_time,
  1371. buffer, sizeof(buffer),
  1372. range.we_version_compiled);
  1373. /* Get current retry settings */
  1374. wrq.u.retry.flags = 0;
  1375. if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
  1376. {
  1377. int flags = wrq.u.retry.flags;
  1378. /* Is it disabled ? */
  1379. if(wrq.u.retry.disabled)
  1380. printf("Current mode:off\n ");
  1381. else
  1382. {
  1383. unsigned int retry_type = 0;
  1384. unsigned int retry_mask = 0;
  1385. unsigned int remain_mask = range.retry_capa & IW_RETRY_TYPE;
  1386. /* Let's check the mode */
  1387. printf("Current mode:on\n ");
  1388. /* Let's check the value and its type */
  1389. if(wrq.u.retry.flags & IW_RETRY_TYPE)
  1390. {
  1391. iw_print_retry_value(buffer, sizeof(buffer),
  1392. wrq.u.retry.value, wrq.u.retry.flags,
  1393. range.we_version_compiled);
  1394. printf("%s\n ", buffer);
  1395. }
  1396. while(1)
  1397. {
  1398. /* Deal with min/max/short/long for the current value */
  1399. retry_mask = 0;
  1400. /* If we have been returned a MIN value, ask for the MAX */
  1401. if(flags & IW_RETRY_MIN)
  1402. retry_mask = IW_RETRY_MAX;
  1403. /* If we have been returned a MAX value, ask for the MIN */
  1404. if(flags & IW_RETRY_MAX)
  1405. retry_mask = IW_RETRY_MIN;
  1406. /* Same for SHORT and LONG */
  1407. if(flags & IW_RETRY_SHORT)
  1408. retry_mask = IW_RETRY_LONG;
  1409. if(flags & IW_RETRY_LONG)
  1410. retry_mask = IW_RETRY_SHORT;
  1411. /* If we have something to ask for... */
  1412. if(retry_mask)
  1413. {
  1414. retry_mask |= retry_type;
  1415. get_retry_value(skfd, ifname, &wrq, retry_mask,
  1416. buffer, sizeof(buffer),
  1417. range.we_version_compiled);
  1418. }
  1419. /* And if we have both a limit and a lifetime,
  1420. * ask the other one */
  1421. remain_mask &= ~(wrq.u.retry.flags);
  1422. retry_type = remain_mask;
  1423. /* Nothing anymore : exit the loop */
  1424. if(!retry_type)
  1425. break;
  1426. /* Ask for this other type of value */
  1427. flags = get_retry_value(skfd, ifname, &wrq, retry_type,
  1428. buffer, sizeof(buffer),
  1429. range.we_version_compiled);
  1430. /* Loop back for min/max/short/long */
  1431. }
  1432. }
  1433. }
  1434. printf("\n");
  1435. }
  1436. return(0);
  1437. }
  1438. /************************ ACCESS POINT LIST ************************/
  1439. /*
  1440. * Note : now that we have scanning support, this is depracted and
  1441. * won't survive long. Actually, next version it's out !
  1442. */
  1443. /*------------------------------------------------------------------*/
  1444. /*
  1445. * Display the list of ap addresses and the associated stats
  1446. * Exacly the same as the spy list, only with different IOCTL and messages
  1447. */
  1448. static int
  1449. print_ap_info(int skfd,
  1450. char * ifname,
  1451. char * args[], /* Command line args */
  1452. int count) /* Args count */
  1453. {
  1454. struct iwreq wrq;
  1455. char buffer[(sizeof(struct iw_quality) +
  1456. sizeof(struct sockaddr)) * IW_MAX_AP];
  1457. char temp[128];
  1458. struct sockaddr * hwa;
  1459. struct iw_quality * qual;
  1460. iwrange range;
  1461. int has_range = 0;
  1462. int has_qual = 0;
  1463. int n;
  1464. int i;
  1465. /* Avoid "Unused parameter" warning */
  1466. args = args; count = count;
  1467. /* Collect stats */
  1468. wrq.u.data.pointer = (caddr_t) buffer;
  1469. wrq.u.data.length = IW_MAX_AP;
  1470. wrq.u.data.flags = 0;
  1471. if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
  1472. {
  1473. fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
  1474. return(-1);
  1475. }
  1476. /* Number of addresses */
  1477. n = wrq.u.data.length;
  1478. has_qual = wrq.u.data.flags;
  1479. /* The two lists */
  1480. hwa = (struct sockaddr *) buffer;
  1481. qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
  1482. /* Check if we have valid mac address type */
  1483. if(iw_check_mac_addr_type(skfd, ifname) < 0)
  1484. {
  1485. fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
  1486. return(-2);
  1487. }
  1488. /* Get range info if we can */
  1489. if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
  1490. has_range = 1;
  1491. /* Display it */
  1492. if(n == 0)
  1493. printf("%-8.16s No Peers/Access-Point in range\n", ifname);
  1494. else
  1495. printf("%-8.16s Peers/Access-Points in range:\n", ifname);
  1496. for(i = 0; i < n; i++)
  1497. {
  1498. if(has_qual)
  1499. {
  1500. /* Print stats for this address */
  1501. printf(" %s : ", iw_saether_ntop(&hwa[i], temp));
  1502. iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
  1503. printf("%s\n", temp);
  1504. }
  1505. else
  1506. /* Only print the address */
  1507. printf(" %s\n", iw_saether_ntop(&hwa[i], temp));
  1508. }
  1509. printf("\n");
  1510. return(0);
  1511. }
  1512. /******************** WIRELESS EVENT CAPABILITY ********************/
  1513. static const char * event_capa_req[] =
  1514. {
  1515. [SIOCSIWNWID - SIOCIWFIRST] = "Set NWID (kernel generated)",
  1516. [SIOCSIWFREQ - SIOCIWFIRST] = "Set Frequency/Channel (kernel generated)",
  1517. [SIOCGIWFREQ - SIOCIWFIRST] = "New Frequency/Channel",
  1518. [SIOCSIWMODE - SIOCIWFIRST] = "Set Mode (kernel generated)",
  1519. [SIOCGIWTHRSPY - SIOCIWFIRST] = "Spy threshold crossed",
  1520. [SIOCGIWAP - SIOCIWFIRST] = "New Access Point/Cell address - roaming",
  1521. [SIOCGIWSCAN - SIOCIWFIRST] = "Scan request completed",
  1522. [SIOCSIWESSID - SIOCIWFIRST] = "Set ESSID (kernel generated)",
  1523. [SIOCGIWESSID - SIOCIWFIRST] = "New ESSID",
  1524. [SIOCGIWRATE - SIOCIWFIRST] = "New bit-rate",
  1525. [SIOCSIWENCODE - SIOCIWFIRST] = "Set Encoding (kernel generated)",
  1526. [SIOCGIWPOWER - SIOCIWFIRST] = NULL,
  1527. };
  1528. static const char * event_capa_evt[] =
  1529. {
  1530. [IWEVTXDROP - IWEVFIRST] = "Tx packet dropped - retry exceeded",
  1531. [IWEVCUSTOM - IWEVFIRST] = "Custom driver event",
  1532. [IWEVREGISTERED - IWEVFIRST] = "Registered node",
  1533. [IWEVEXPIRED - IWEVFIRST] = "Expired node",
  1534. };
  1535. /*------------------------------------------------------------------*/
  1536. /*
  1537. * Print the event capability for the device
  1538. */
  1539. static int
  1540. print_event_capa_info(int skfd,
  1541. char * ifname,
  1542. char * args[], /* Command line args */
  1543. int count) /* Args count */
  1544. {
  1545. struct iw_range range;
  1546. int cmd;
  1547. /* Avoid "Unused parameter" warning */
  1548. args = args; count = count;
  1549. /* Extract range info */
  1550. if((iw_get_range_info(skfd, ifname, &range) < 0) ||
  1551. (range.we_version_compiled < 10))
  1552. fprintf(stderr, "%-8.16s no wireless event capability information.\n\n",
  1553. ifname);
  1554. else
  1555. {
  1556. #ifdef DEBUG
  1557. /* Debugging ;-) */
  1558. for(cmd = 0x8B00; cmd < 0x8C0F; cmd++)
  1559. {
  1560. int idx = IW_EVENT_CAPA_INDEX(cmd);
  1561. int mask = IW_EVENT_CAPA_MASK(cmd);
  1562. printf("0x%X - %d - %X\n", cmd, idx, mask);
  1563. }
  1564. #endif
  1565. printf("%-8.16s Wireless Events supported :\n", ifname);
  1566. for(cmd = SIOCIWFIRST; cmd <= SIOCGIWPOWER; cmd++)
  1567. {
  1568. int idx = IW_EVENT_CAPA_INDEX(cmd);
  1569. int mask = IW_EVENT_CAPA_MASK(cmd);
  1570. if(range.event_capa[idx] & mask)
  1571. printf(" 0x%04X : %s\n",
  1572. cmd, event_capa_req[cmd - SIOCIWFIRST]);
  1573. }
  1574. for(cmd = IWEVFIRST; cmd <= IWEVEXPIRED; cmd++)
  1575. {
  1576. int idx = IW_EVENT_CAPA_INDEX(cmd);
  1577. int mask = IW_EVENT_CAPA_MASK(cmd);
  1578. if(range.event_capa[idx] & mask)
  1579. printf(" 0x%04X : %s\n",
  1580. cmd, event_capa_evt[cmd - IWEVFIRST]);
  1581. }
  1582. printf("\n");
  1583. }
  1584. return(0);
  1585. }
  1586. /*************************** WPA SUPPORT ***************************/
  1587. /*------------------------------------------------------------------*/
  1588. /*
  1589. * Print the authentication parameters for the device
  1590. */
  1591. static int
  1592. print_auth_info(int skfd,
  1593. char * ifname,
  1594. char * args[], /* Command line args */
  1595. int count) /* Args count */
  1596. {
  1597. struct iwreq wrq;
  1598. struct iw_range range;
  1599. unsigned int k;
  1600. /* Avoid "Unused parameter" warning */
  1601. args = args; count = count;
  1602. /* Extract range info */
  1603. if((iw_get_range_info(skfd, ifname, &range) < 0) ||
  1604. (range.we_version_compiled < 18))
  1605. fprintf(stderr, "%-8.16s no authentication information.\n\n",
  1606. ifname);
  1607. else
  1608. {
  1609. /* Print WPA/802.1x/802.11i security parameters */
  1610. if(!range.enc_capa)
  1611. {
  1612. printf("%-8.16s unknown authentication information.\n\n", ifname);
  1613. }
  1614. else
  1615. {
  1616. /* Display advanced encryption capabilities */
  1617. printf("%-8.16s Authentication capabilities :", ifname);
  1618. iw_print_mask_name(range.enc_capa,
  1619. iw_auth_capa_name, IW_AUTH_CAPA_NUM,
  1620. "\n\t\t");
  1621. printf("\n");
  1622. /* Extract all auth settings */
  1623. for(k = 0; k < IW_AUTH_SETTINGS_NUM; k++)
  1624. {
  1625. wrq.u.param.flags = iw_auth_settings[k].value;
  1626. if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
  1627. {
  1628. printf(" Current %s :", iw_auth_settings[k].label);
  1629. if(iw_auth_settings[k].names != NULL)
  1630. iw_print_mask_name(wrq.u.param.value,
  1631. iw_auth_settings[k].names,
  1632. iw_auth_settings[k].num_names,
  1633. "\n\t\t");
  1634. else
  1635. printf((wrq.u.param.value) ? " yes" : " no");
  1636. printf("\n");
  1637. }
  1638. }
  1639. }
  1640. printf("\n\n");
  1641. }
  1642. return(0);
  1643. }
  1644. /*------------------------------------------------------------------*/
  1645. /*
  1646. * Print all the available wpa keys for the device
  1647. */
  1648. static int
  1649. print_wpakeys_info(int skfd,
  1650. char * ifname,
  1651. char * args[], /* Command line args */
  1652. int count) /* Args count */
  1653. {
  1654. struct iwreq wrq;
  1655. struct iw_range range;
  1656. unsigned char extbuf[IW_EXTKEY_SIZE];
  1657. struct iw_encode_ext *extinfo;
  1658. unsigned int k;
  1659. char buffer[128];
  1660. /* Avoid "Unused parameter" warning */
  1661. args = args; count = count;
  1662. /* This always point to the same place */
  1663. extinfo = (struct iw_encode_ext *) extbuf;
  1664. /* Extract range info */
  1665. if(iw_get_range_info(skfd, ifname, &range) < 0)
  1666. fprintf(stderr, "%-8.16s no wpa key information.\n\n",
  1667. ifname);
  1668. else
  1669. {
  1670. printf("%-8.16s ", ifname);
  1671. /* Print key sizes */
  1672. if((range.num_encoding_sizes > 0) &&
  1673. (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
  1674. {
  1675. printf("%d key sizes : %d", range.num_encoding_sizes,
  1676. range.encoding_size[0] * 8);
  1677. /* Print them all */
  1678. for(k = 1; k < range.num_encoding_sizes; k++)
  1679. printf(", %d", range.encoding_size[k] * 8);
  1680. printf("bits\n ");
  1681. }
  1682. /* Print the keys */
  1683. printf("%d keys available :\n", range.max_encoding_tokens);
  1684. for(k = 1; k <= range.max_encoding_tokens; k++)
  1685. {
  1686. /* Cleanup. Driver may not fill everything */
  1687. memset(extbuf, '\0', IW_EXTKEY_SIZE);
  1688. /* Get whole struct containing one WPA key */
  1689. wrq.u.data.pointer = (caddr_t) extbuf;
  1690. wrq.u.data.length = IW_EXTKEY_SIZE;
  1691. wrq.u.data.flags = k;
  1692. if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) < 0)
  1693. {
  1694. fprintf(stderr, "Error reading wpa keys (SIOCGIWENCODEEXT): %s\n", strerror(errno));
  1695. break;
  1696. }
  1697. /* Sanity check */
  1698. if(wrq.u.data.length <
  1699. (sizeof(struct iw_encode_ext) + extinfo->key_len))
  1700. break;
  1701. /* Check if key is disabled */
  1702. if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
  1703. (extinfo->key_len == 0))
  1704. printf("\t\t[%d]: off\n", k);
  1705. else
  1706. {
  1707. /* Display the key */
  1708. iw_print_key(buffer, sizeof(buffer),
  1709. extinfo->key, extinfo->key_len, wrq.u.data.flags);
  1710. printf("\t\t[%d]: %s", k, buffer);
  1711. /* Key size */
  1712. printf(" (%d bits)", extinfo->key_len * 8);
  1713. printf("\n");
  1714. /* Other info... */
  1715. printf("\t\t Address: %s\n",
  1716. iw_saether_ntop(&extinfo->addr, buffer));
  1717. printf("\t\t Algorithm:");
  1718. iw_print_value_name(extinfo->alg,
  1719. iw_encode_alg_name, IW_ENCODE_ALG_NUM);
  1720. printf("\n\t\t Flags: 0x%08x\n", extinfo->ext_flags);
  1721. if (extinfo->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID)
  1722. printf("\t\t tx-seq-valid\n");
  1723. if (extinfo->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
  1724. printf("\t\t rx-seq-valid\n");
  1725. if (extinfo->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
  1726. printf("\t\t group-key\n");
  1727. }
  1728. }
  1729. /* Print current key index and mode */
  1730. wrq.u.data.pointer = (caddr_t) extbuf;
  1731. wrq.u.data.length = IW_EXTKEY_SIZE;
  1732. wrq.u.data.flags = 0; /* Set index to zero to get current */
  1733. if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) >= 0)
  1734. {
  1735. /* Note : if above fails, we have already printed an error
  1736. * message int the loop above */
  1737. printf(" Current Transmit Key: [%d]\n",
  1738. wrq.u.data.flags & IW_ENCODE_INDEX);
  1739. if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
  1740. printf(" Security mode:restricted\n");
  1741. if(wrq.u.data.flags & IW_ENCODE_OPEN)
  1742. printf(" Security mode:open\n");
  1743. }
  1744. printf("\n\n");
  1745. }
  1746. return(0);
  1747. }
  1748. /*------------------------------------------------------------------*/
  1749. /*
  1750. * Print the Generic IE for the device
  1751. * Note : indentation is broken. We need to fix that.
  1752. */
  1753. static int
  1754. print_gen_ie_info(int skfd,
  1755. char * ifname,
  1756. char * args[], /* Command line args */
  1757. int count) /* Args count */
  1758. {
  1759. struct iwreq wrq;
  1760. unsigned char buf[IW_GENERIC_IE_MAX];
  1761. /* Avoid "Unused parameter" warning */
  1762. args = args; count = count;
  1763. wrq.u.data.pointer = (caddr_t)buf;
  1764. wrq.u.data.length = IW_GENERIC_IE_MAX;
  1765. wrq.u.data.flags = 0;
  1766. if(iw_get_ext(skfd, ifname, SIOCGIWGENIE, &wrq) < 0)
  1767. fprintf(stderr, "%-8.16s no generic IE (%s).\n\n",
  1768. ifname, strerror(errno));
  1769. else
  1770. {
  1771. fprintf(stderr, "%-8.16s\n", ifname);
  1772. if(wrq.u.data.length == 0)
  1773. printf(" empty generic IE\n");
  1774. else
  1775. iw_print_gen_ie(buf, wrq.u.data.length);
  1776. printf("\n");
  1777. }
  1778. return(0);
  1779. }
  1780. /**************************** MODULATION ****************************/
  1781. /*------------------------------------------------------------------*/
  1782. /*
  1783. * Print Modulation info for each device
  1784. */
  1785. static int
  1786. print_modul_info(int skfd,
  1787. char * ifname,
  1788. char * args[], /* Command line args */
  1789. int count) /* Args count */
  1790. {
  1791. struct iwreq wrq;
  1792. struct iw_range range;
  1793. /* Avoid "Unused parameter" warning */
  1794. args = args; count = count;
  1795. /* Extract range info */
  1796. if((iw_get_range_info(skfd, ifname, &range) < 0) ||
  1797. (range.we_version_compiled < 11))
  1798. fprintf(stderr, "%-8.16s no modulation information.\n\n",
  1799. ifname);
  1800. else
  1801. {
  1802. if(range.modul_capa == 0x0)
  1803. printf("%-8.16s unknown modulation information.\n\n", ifname);
  1804. else
  1805. {
  1806. int i;
  1807. printf("%-8.16s Modulations available :\n", ifname);
  1808. /* Display each modulation available */
  1809. for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
  1810. {
  1811. if((range.modul_capa & iw_modul_list[i].mask)
  1812. == iw_modul_list[i].mask)
  1813. printf(" %-8s: %s\n",
  1814. iw_modul_list[i].cmd, iw_modul_list[i].verbose);
  1815. }
  1816. /* Get current modulations settings */
  1817. wrq.u.param.flags = 0;
  1818. if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) >= 0)
  1819. {
  1820. unsigned int modul = wrq.u.param.value;
  1821. int n = 0;
  1822. printf(" Current modulations %c",
  1823. wrq.u.param.fixed ? '=' : ':');
  1824. /* Display each modulation enabled */
  1825. for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
  1826. {
  1827. if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
  1828. {
  1829. if((n++ % 8) == 0)
  1830. printf("\n ");
  1831. else
  1832. printf(" ; ");
  1833. printf("%s", iw_modul_list[i].cmd);
  1834. }
  1835. }
  1836. printf("\n");
  1837. }
  1838. printf("\n");
  1839. }
  1840. }
  1841. return(0);
  1842. }
  1843. #endif /* WE_ESSENTIAL */
  1844. /************************* COMMON UTILITIES *************************/
  1845. /*
  1846. * This section was initially written by Michael Tokarev <mjt@tls.msk.ru>
  1847. * but heavily modified by me ;-)
  1848. */
  1849. /*------------------------------------------------------------------*/
  1850. /*
  1851. * Map command line arguments to the proper procedure...
  1852. */
  1853. typedef struct iwlist_entry {
  1854. const char * cmd; /* Command line shorthand */
  1855. iw_enum_handler fn; /* Subroutine */
  1856. int max_count;
  1857. const char * argsname; /* Args as human readable string */
  1858. } iwlist_cmd;
  1859. static const struct iwlist_entry iwlist_cmds[] = {
  1860. { "scanning", print_scanning_info, -1, "[essid NNN] [last]" },
  1861. { "frequency", print_freq_info, 0, NULL },
  1862. { "channel", print_freq_info, 0, NULL },
  1863. { "bitrate", print_bitrate_info, 0, NULL },
  1864. { "rate", print_bitrate_info, 0, NULL },
  1865. { "encryption", print_keys_info, 0, NULL },
  1866. { "keys", print_keys_info, 0, NULL },
  1867. { "power", print_pm_info, 0, NULL },
  1868. #ifndef WE_ESSENTIAL
  1869. { "txpower", print_txpower_info, 0, NULL },
  1870. { "retry", print_retry_info, 0, NULL },
  1871. { "ap", print_ap_info, 0, NULL },
  1872. { "accesspoints", print_ap_info, 0, NULL },
  1873. { "peers", print_ap_info, 0, NULL },
  1874. { "event", print_event_capa_info, 0, NULL },
  1875. { "auth", print_auth_info, 0, NULL },
  1876. { "wpakeys", print_wpakeys_info, 0, NULL },
  1877. { "genie", print_gen_ie_info, 0, NULL },
  1878. { "modulation", print_modul_info, 0, NULL },
  1879. #endif /* WE_ESSENTIAL */
  1880. { NULL, NULL, 0, 0 },
  1881. };
  1882. /*------------------------------------------------------------------*/
  1883. /*
  1884. * Find the most appropriate command matching the command line
  1885. */
  1886. static inline const iwlist_cmd *
  1887. find_command(const char * cmd)
  1888. {
  1889. const iwlist_cmd * found = NULL;
  1890. int ambig = 0;
  1891. unsigned int len = strlen(cmd);
  1892. int i;
  1893. /* Go through all commands */
  1894. for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
  1895. {
  1896. /* No match -> next one */
  1897. if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
  1898. continue;
  1899. /* Exact match -> perfect */
  1900. if(len == strlen(iwlist_cmds[i].cmd))
  1901. return &iwlist_cmds[i];
  1902. /* Partial match */
  1903. if(found == NULL)
  1904. /* First time */
  1905. found = &iwlist_cmds[i];
  1906. else
  1907. /* Another time */
  1908. if (iwlist_cmds[i].fn != found->fn)
  1909. ambig = 1;
  1910. }
  1911. if(found == NULL)
  1912. {
  1913. fprintf(stderr, "iwlist: unknown command `%s' (check 'iwlist --help').\n", cmd);
  1914. return NULL;
  1915. }
  1916. if(ambig)
  1917. {
  1918. fprintf(stderr, "iwlist: command `%s' is ambiguous (check 'iwlist --help').\n", cmd);
  1919. return NULL;
  1920. }
  1921. return found;
  1922. }
  1923. /*------------------------------------------------------------------*/
  1924. /*
  1925. * Display help
  1926. */
  1927. static void iw_usage(int status)
  1928. {
  1929. FILE * f = status ? stderr : stdout;
  1930. int i;
  1931. for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
  1932. {
  1933. fprintf(f, "%s [interface] %s %s\n",
  1934. (i ? " " : "Usage: iwlist"),
  1935. iwlist_cmds[i].cmd,
  1936. iwlist_cmds[i].argsname ? iwlist_cmds[i].argsname : "");
  1937. }
  1938. exit(status);
  1939. }
  1940. /******************************* MAIN ********************************/
  1941. /*------------------------------------------------------------------*/
  1942. /*
  1943. * The main !
  1944. */
  1945. int
  1946. main(int argc,
  1947. char ** argv)
  1948. {
  1949. int skfd; /* generic raw socket desc. */
  1950. char *dev; /* device name */
  1951. char *cmd; /* command */
  1952. char **args; /* Command arguments */
  1953. int count; /* Number of arguments */
  1954. const iwlist_cmd *iwcmd;
  1955. if(argc < 2)
  1956. iw_usage(1);
  1957. /* Those don't apply to all interfaces */
  1958. if((argc == 2) && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))
  1959. iw_usage(0);
  1960. if((argc == 2) && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")))
  1961. return(iw_print_version_info("iwlist"));
  1962. if(argc == 2)
  1963. {
  1964. cmd = argv[1];
  1965. dev = NULL;
  1966. args = NULL;
  1967. count = 0;
  1968. }
  1969. else
  1970. {
  1971. cmd = argv[2];
  1972. dev = argv[1];
  1973. args = argv + 3;
  1974. count = argc - 3;
  1975. }
  1976. /* find a command */
  1977. iwcmd = find_command(cmd);
  1978. if(iwcmd == NULL)
  1979. return 1;
  1980. /* Check arg numbers */
  1981. if((iwcmd->max_count >= 0) && (count > iwcmd->max_count))
  1982. {
  1983. fprintf(stderr, "iwlist: command `%s' needs fewer arguments (max %d)\n",
  1984. iwcmd->cmd, iwcmd->max_count);
  1985. return 1;
  1986. }
  1987. /* Create a channel to the NET kernel. */
  1988. if((skfd = iw_sockets_open()) < 0)
  1989. {
  1990. perror("socket");
  1991. return -1;
  1992. }
  1993. /* do the actual work */
  1994. if (dev)
  1995. (*iwcmd->fn)(skfd, dev, args, count);
  1996. else
  1997. iw_enum_devices(skfd, iwcmd->fn, args, count);
  1998. /* Close the socket. */
  1999. iw_sockets_close(skfd);
  2000. return 0;
  2001. }