4 * Jean II - HPLB '99 - HPL 99->07
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".
10 * This file is released under the GPL license.
11 * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
14 #include "iwlib-private.h" /* Private header */
17 /****************************** TYPES ******************************/
20 * Scan state and meta-information, used to decode events...
22 typedef struct iwscan_state
25 int ap_num; /* Access Point number 1->N */
26 int val_index; /* Value in table 0->(N-1) */
32 typedef struct iwmask_name
34 unsigned int mask; /* bit mask for the value */
35 const char * name; /* human readable name for the value */
39 * Types of authentication parameters
41 typedef struct iw_auth_descr
43 int value; /* Type of auth value */
44 const char * label; /* User readable version */
45 const struct iwmask_name * names; /* Names for this value */
46 const int num_names; /* Number of names */
49 /**************************** CONSTANTS ****************************/
51 #define IW_SCAN_HACK 0x8000
53 #define IW_EXTKEY_SIZE (sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX)
55 /* ------------------------ WPA CAPA NAMES ------------------------ */
57 * This is the user readable name of a bunch of WPA constants in wireless.h
58 * Maybe this should go in iwlib.c ?
62 #define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0]))
64 //static const struct iwmask_name iw_enc_mode_name[] = {
65 // { IW_ENCODE_RESTRICTED, "restricted" },
66 // { IW_ENCODE_OPEN, "open" },
68 //#define IW_ENC_MODE_NUM IW_ARRAY_LEN(iw_enc_mode_name)
70 static const struct iwmask_name iw_auth_capa_name[] = {
71 { IW_ENC_CAPA_WPA, "WPA" },
72 { IW_ENC_CAPA_WPA2, "WPA2" },
73 { IW_ENC_CAPA_CIPHER_TKIP, "CIPHER-TKIP" },
74 { IW_ENC_CAPA_CIPHER_CCMP, "CIPHER-CCMP" },
76 #define IW_AUTH_CAPA_NUM IW_ARRAY_LEN(iw_auth_capa_name)
78 static const struct iwmask_name iw_auth_cypher_name[] = {
79 { IW_AUTH_CIPHER_NONE, "none" },
80 { IW_AUTH_CIPHER_WEP40, "WEP-40" },
81 { IW_AUTH_CIPHER_TKIP, "TKIP" },
82 { IW_AUTH_CIPHER_CCMP, "CCMP" },
83 { IW_AUTH_CIPHER_WEP104, "WEP-104" },
85 #define IW_AUTH_CYPHER_NUM IW_ARRAY_LEN(iw_auth_cypher_name)
87 static const struct iwmask_name iw_wpa_ver_name[] = {
88 { IW_AUTH_WPA_VERSION_DISABLED, "disabled" },
89 { IW_AUTH_WPA_VERSION_WPA, "WPA" },
90 { IW_AUTH_WPA_VERSION_WPA2, "WPA2" },
92 #define IW_WPA_VER_NUM IW_ARRAY_LEN(iw_wpa_ver_name)
94 static const struct iwmask_name iw_auth_key_mgmt_name[] = {
95 { IW_AUTH_KEY_MGMT_802_1X, "802.1x" },
96 { IW_AUTH_KEY_MGMT_PSK, "PSK" },
98 #define IW_AUTH_KEY_MGMT_NUM IW_ARRAY_LEN(iw_auth_key_mgmt_name)
100 static const struct iwmask_name iw_auth_alg_name[] = {
101 { IW_AUTH_ALG_OPEN_SYSTEM, "open" },
102 { IW_AUTH_ALG_SHARED_KEY, "shared-key" },
103 { IW_AUTH_ALG_LEAP, "LEAP" },
105 #define IW_AUTH_ALG_NUM IW_ARRAY_LEN(iw_auth_alg_name)
107 static const struct iw_auth_descr iw_auth_settings[] = {
108 { IW_AUTH_WPA_VERSION, "WPA version", iw_wpa_ver_name, IW_WPA_VER_NUM },
109 { IW_AUTH_KEY_MGMT, "Key management", iw_auth_key_mgmt_name, IW_AUTH_KEY_MGMT_NUM },
110 { IW_AUTH_CIPHER_PAIRWISE, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
111 { IW_AUTH_CIPHER_GROUP, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM },
112 { IW_AUTH_TKIP_COUNTERMEASURES, "TKIP countermeasures", NULL, 0 },
113 { IW_AUTH_DROP_UNENCRYPTED, "Drop unencrypted", NULL, 0 },
114 { IW_AUTH_80211_AUTH_ALG, "Authentication algorithm", iw_auth_alg_name, IW_AUTH_ALG_NUM },
115 { IW_AUTH_RX_UNENCRYPTED_EAPOL, "Receive unencrypted EAPOL", NULL, 0 },
116 { IW_AUTH_ROAMING_CONTROL, "Roaming control", NULL, 0 },
117 { IW_AUTH_PRIVACY_INVOKED, "Privacy invoked", NULL, 0 },
119 #define IW_AUTH_SETTINGS_NUM IW_ARRAY_LEN(iw_auth_settings)
121 /* Values for the IW_ENCODE_ALG_* returned by SIOCSIWENCODEEXT */
122 static const char * iw_encode_alg_name[] = {
129 #define IW_ENCODE_ALG_NUM IW_ARRAY_LEN(iw_encode_alg_name)
131 #ifndef IW_IE_CIPHER_NONE
132 /* Cypher values in GENIE (pairwise and group) */
133 #define IW_IE_CIPHER_NONE 0
134 #define IW_IE_CIPHER_WEP40 1
135 #define IW_IE_CIPHER_TKIP 2
136 #define IW_IE_CIPHER_WRAP 3
137 #define IW_IE_CIPHER_CCMP 4
138 #define IW_IE_CIPHER_WEP104 5
139 /* Key management in GENIE */
140 #define IW_IE_KEY_MGMT_NONE 0
141 #define IW_IE_KEY_MGMT_802_1X 1
142 #define IW_IE_KEY_MGMT_PSK 2
143 #endif /* IW_IE_CIPHER_NONE */
145 /* Values for the IW_IE_CIPHER_* in GENIE */
146 static const char * iw_ie_cypher_name[] = {
154 #define IW_IE_CYPHER_NUM IW_ARRAY_LEN(iw_ie_cypher_name)
156 /* Values for the IW_IE_KEY_MGMT_* in GENIE */
157 static const char * iw_ie_key_mgmt_name[] = {
162 #define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name)
164 #endif /* WE_ESSENTIAL */
166 /************************* WPA SUBROUTINES *************************/
169 /*------------------------------------------------------------------*/
171 * Print all names corresponding to a mask.
172 * This may want to be used in iw_print_retry_value() ?
175 iw_print_mask_name(unsigned int mask,
176 const struct iwmask_name names[],
177 const unsigned int num_names,
182 /* Print out all names for the bitmask */
183 for(i = 0; i < num_names; i++)
185 if(mask & names[i].mask)
188 printf("%s%s", sep, names[i].name);
189 /* Remove the bit from the mask */
190 mask &= ~names[i].mask;
193 /* If there is unconsumed bits... */
195 printf("%sUnknown", sep);
198 /*------------------------------------------------------------------*/
200 * Print the name corresponding to a value, with overflow check.
203 iw_print_value_name(unsigned int value,
204 const char * names[],
205 const unsigned int num_names)
207 if(value >= num_names)
208 printf(" unknown (%d)", value);
210 printf(" %s", names[value]);
213 /*------------------------------------------------------------------*/
215 * Parse, and display the results of an unknown IE.
219 iw_print_ie_unknown(unsigned char * iebuf,
222 int ielen = iebuf[1] + 2;
229 for(i = 0; i < ielen; i++)
230 printf("%02X", iebuf[i]);
234 /*------------------------------------------------------------------*/
236 * Parse, and display the results of a WPA or WPA2 IE.
240 iw_print_ie_wpa(unsigned char * iebuf,
243 int ielen = iebuf[1] + 2;
244 int offset = 2; /* Skip the IE id, and the length. */
245 unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
246 unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
247 unsigned char * wpa_oui;
256 /* Debugging code. In theory useless, because it's debugged ;-) */
257 printf("IE raw value %d [%02X", buflen, iebuf[0]);
258 for(i = 1; i < buflen; i++)
259 printf(":%02X", iebuf[i]);
265 case 0x30: /* WPA2 */
266 /* Check if we have enough data */
269 iw_print_ie_unknown(iebuf, buflen);
276 case 0xdd: /* WPA or else */
279 /* Not all IEs that start with 0xdd are WPA.
280 * So check that the OUI is valid. Note : offset==2 */
282 || (memcmp(&iebuf[offset], wpa_oui, 3) != 0)
283 || (iebuf[offset + 3] != 0x01))
285 iw_print_ie_unknown(iebuf, buflen);
289 /* Skip the OUI type */
297 /* Pick version number (little endian) */
298 ver = iebuf[offset] | (iebuf[offset + 1] << 8);
302 printf("WPA Version %d\n", ver);
304 printf("IEEE 802.11i/WPA2 Version %d\n", ver);
306 /* From here, everything is technically optional. */
308 /* Check if we are done */
309 if(ielen < (offset + 4))
311 /* We have a short IE. So we should assume TKIP/TKIP. */
312 printf(" Group Cipher : TKIP\n");
313 printf(" Pairwise Cipher : TKIP\n");
317 /* Next we have our group cipher. */
318 if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
320 printf(" Group Cipher : Proprietary\n");
324 printf(" Group Cipher :");
325 iw_print_value_name(iebuf[offset+3],
326 iw_ie_cypher_name, IW_IE_CYPHER_NUM);
331 /* Check if we are done */
332 if(ielen < (offset + 2))
334 /* We don't have a pairwise cipher, or auth method. Assume TKIP. */
335 printf(" Pairwise Ciphers : TKIP\n");
339 /* Otherwise, we have some number of pairwise ciphers. */
340 cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
342 printf(" Pairwise Ciphers (%d) :", cnt);
344 if(ielen < (offset + 4*cnt))
347 for(i = 0; i < cnt; i++)
349 if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
351 printf(" Proprietary");
355 iw_print_value_name(iebuf[offset+3],
356 iw_ie_cypher_name, IW_IE_CYPHER_NUM);
362 /* Check if we are done */
363 if(ielen < (offset + 2))
366 /* Now, we have authentication suites. */
367 cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
369 printf(" Authentication Suites (%d) :", cnt);
371 if(ielen < (offset + 4*cnt))
374 for(i = 0; i < cnt; i++)
376 if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
378 printf(" Proprietary");
382 iw_print_value_name(iebuf[offset+3],
383 iw_ie_key_mgmt_name, IW_IE_KEY_MGMT_NUM);
389 /* Check if we are done */
390 if(ielen < (offset + 1))
393 /* Otherwise, we have capabilities bytes.
394 * For now, we only care about preauth which is in bit position 1 of the
395 * first byte. (But, preauth with WPA version 1 isn't supposed to be
397 if(iebuf[offset] & 0x01)
399 printf(" Preauthentication Supported\n");
403 /*------------------------------------------------------------------*/
405 * Process a generic IE and display the info in human readable form
406 * for some of the most interesting ones.
407 * For now, we only decode the WPA IEs.
410 iw_print_gen_ie(unsigned char * buffer,
415 /* Loop on each IE, each IE is minimum 2 bytes */
416 while(offset <= (buflen - 2))
421 switch(buffer[offset])
423 case 0xdd: /* WPA1 (and other) */
424 case 0x30: /* WPA2 */
425 iw_print_ie_wpa(buffer + offset, buflen);
428 iw_print_ie_unknown(buffer + offset, buflen);
430 /* Skip over this IE to the next one in the list. */
431 offset += buffer[offset+1] + 2;
434 #endif /* WE_ESSENTIAL */
436 /***************************** SCANNING *****************************/
438 * This one behave quite differently from the others
440 * Note that we don't use the scanning capability of iwlib (functions
441 * iw_process_scan() and iw_scan()). The main reason is that
442 * iw_process_scan() return only a subset of the scan data to the caller,
443 * for example custom elements and bitrates are ommited. Here, we
444 * do the complete job...
447 /*------------------------------------------------------------------*/
449 * Print one element from the scanning results
452 print_scanning_token(struct stream_descr * stream, /* Stream of events */
453 struct iw_event * event, /* Extracted token */
454 struct iwscan_state * state,
455 struct iw_range * iw_range, /* Range info */
458 char buffer[128]; /* Temporary buffer */
460 /* Now, let's decode the event */
464 printf(" Cell %02d - Address: %s\n", state->ap_num,
465 iw_saether_ntop(&event->u.ap_addr, buffer));
469 if(event->u.nwid.disabled)
470 printf(" NWID:off/any\n");
472 printf(" NWID:%X\n", event->u.nwid.value);
476 double freq; /* Frequency/channel */
477 int channel = -1; /* Converted to channel */
478 freq = iw_freq2float(&(event->u.freq));
479 /* Convert to channel if possible */
481 channel = iw_freq_to_channel(freq, iw_range);
482 iw_print_freq(buffer, sizeof(buffer),
483 freq, channel, event->u.freq.flags);
484 printf(" %s\n", buffer);
488 /* Note : event->u.mode is unsigned, no need to check <= 0 */
489 if(event->u.mode >= IW_NUM_OPER_MODE)
490 event->u.mode = IW_NUM_OPER_MODE;
492 iw_operation_mode[event->u.mode]);
495 printf(" Protocol:%-1.16s\n", event->u.name);
499 char essid[4*IW_ESSID_MAX_SIZE+1];
500 memset(essid, '\0', sizeof(essid));
501 if((event->u.essid.pointer) && (event->u.essid.length))
502 iw_essid_escape(essid,
503 event->u.essid.pointer, event->u.essid.length);
504 if(event->u.essid.flags)
506 /* Does it have an ESSID index ? */
507 if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)
508 printf(" ESSID:\"%s\" [%d]\n", essid,
509 (event->u.essid.flags & IW_ENCODE_INDEX));
511 printf(" ESSID:\"%s\"\n", essid);
514 printf(" ESSID:off/any/hidden\n");
519 unsigned char key[IW_ENCODING_TOKEN_MAX];
520 if(event->u.data.pointer)
521 memcpy(key, event->u.data.pointer, event->u.data.length);
523 event->u.data.flags |= IW_ENCODE_NOKEY;
524 printf(" Encryption key:");
525 if(event->u.data.flags & IW_ENCODE_DISABLED)
529 /* Display the key */
530 iw_print_key(buffer, sizeof(buffer), key, event->u.data.length,
531 event->u.data.flags);
532 printf("%s", buffer);
535 if((event->u.data.flags & IW_ENCODE_INDEX) > 1)
536 printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX);
537 if(event->u.data.flags & IW_ENCODE_RESTRICTED)
538 printf(" Security mode:restricted");
539 if(event->u.data.flags & IW_ENCODE_OPEN)
540 printf(" Security mode:open");
546 if(state->val_index == 0)
547 printf(" Bit Rates:");
549 if((state->val_index % 5) == 0)
553 iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);
554 printf("%s", buffer);
555 /* Check for termination */
556 if(stream->value == NULL)
559 state->val_index = 0;
566 unsigned int modul = event->u.param.value;
569 printf(" Modulations :");
570 for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
572 if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
578 printf("%s", iw_modul_list[i].cmd);
585 iw_print_stats(buffer, sizeof(buffer),
586 &event->u.qual, iw_range, has_range);
587 printf(" %s\n", buffer);
591 /* Informations Elements are complex, let's do only some of them */
592 iw_print_gen_ie(event->u.data.pointer, event->u.data.length);
594 #endif /* WE_ESSENTIAL */
597 char custom[IW_CUSTOM_MAX+1];
598 if((event->u.data.pointer) && (event->u.data.length))
599 memcpy(custom, event->u.data.pointer, event->u.data.length);
600 custom[event->u.data.length] = '\0';
601 printf(" Extra:%s\n", custom);
605 printf(" (Unknown Wireless Token 0x%04X)\n",
607 } /* switch(event->cmd) */
610 /*------------------------------------------------------------------*/
612 * Perform a scanning on one device
615 print_scanning_info(int skfd,
617 char * args[], /* Command line args */
618 int count) /* Args count */
621 struct iw_scan_req scanopt; /* Options for 'set' */
622 int scanflags = 0; /* Flags for scan */
623 unsigned char * buffer = NULL; /* Results */
624 int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
625 struct iw_range range;
627 struct timeval tv; /* Select timeout */
628 int timeout = 15000000; /* 15s */
630 /* Avoid "Unused parameter" warning */
631 args = args; count = count;
633 /* Debugging stuff */
634 if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN))
636 fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n");
637 fprintf(stderr, "*** and the following line :\n");
638 fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n",
639 IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN);
642 /* Get range stuff */
643 has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
645 /* Check if the interface could support scanning. */
646 if((!has_range) || (range.we_version_compiled < 14))
648 fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n",
653 /* Init timeout value -> 250ms between set and first get */
657 /* Clean up set args */
658 memset(&scanopt, 0, sizeof(scanopt));
660 /* Parse command line arguments and extract options.
661 * Note : when we have enough options, we should use the parser
662 * from iwconfig... */
665 /* One arg is consumed (the option name) */
669 * Check for Active Scan (scan with specific essid)
671 if(!strncmp(args[0], "essid", 5))
675 fprintf(stderr, "Too few arguments for scanning option [%s]\n",
682 /* Store the ESSID in the scan options */
683 scanopt.essid_len = strlen(args[0]);
684 memcpy(scanopt.essid, args[0], scanopt.essid_len);
685 /* Initialise BSSID as needed */
686 if(scanopt.bssid.sa_family == 0)
688 scanopt.bssid.sa_family = ARPHRD_ETHER;
689 memset(scanopt.bssid.sa_data, 0xff, ETH_ALEN);
691 /* Scan only this ESSID */
692 scanflags |= IW_SCAN_THIS_ESSID;
695 /* Check for last scan result (do not trigger scan) */
696 if(!strncmp(args[0], "last", 4))
699 scanflags |= IW_SCAN_HACK;
703 fprintf(stderr, "Invalid scanning option [%s]\n", args[0]);
711 /* Check if we have scan options */
714 wrq.u.data.pointer = (caddr_t) &scanopt;
715 wrq.u.data.length = sizeof(scanopt);
716 wrq.u.data.flags = scanflags;
720 wrq.u.data.pointer = NULL;
721 wrq.u.data.flags = 0;
722 wrq.u.data.length = 0;
725 /* If only 'last' was specified on command line, don't trigger a scan */
726 if(scanflags == IW_SCAN_HACK)
733 /* Initiate Scanning */
734 if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
736 if((errno != EPERM) || (scanflags != 0))
738 fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
739 ifname, strerror(errno));
742 /* If we don't have the permission to initiate the scan, we may
743 * still have permission to read left-over results.
744 * But, don't wait !!! */
746 /* Not cool, it display for non wireless interfaces... */
747 fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
752 timeout -= tv.tv_usec;
757 fd_set rfds; /* File descriptors for select */
758 int last_fd; /* Last fd */
761 /* Guess what ? We must re-generate rfds each time */
765 /* In here, add the rtnetlink fd in the list */
767 /* Wait until something happens */
768 ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
770 /* Check if there was an error */
773 if(errno == EAGAIN || errno == EINTR)
775 fprintf(stderr, "Unhandled signal - exiting...\n");
779 /* Check if there was a timeout */
782 unsigned char * newbuf;
785 /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
786 newbuf = realloc(buffer, buflen);
791 fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
796 /* Try to read the results */
797 wrq.u.data.pointer = buffer;
798 wrq.u.data.flags = 0;
799 wrq.u.data.length = buflen;
800 if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
802 /* Check if buffer was too small (WE-17 only) */
803 if((errno == E2BIG) && (range.we_version_compiled > 16)
804 && (buflen < 0xFFFF))
806 /* Some driver may return very large scan results, either
807 * because there are many cells, or because they have many
808 * large elements in cells (like IWEVCUSTOM). Most will
809 * only need the regular sized buffer. We now use a dynamic
810 * allocation of the buffer to satisfy everybody. Of course,
811 * as we don't know in advance the size of the array, we try
812 * various increasing sizes. Jean II */
814 /* Check if the driver gave us any hints. */
815 if(wrq.u.data.length > buflen)
816 buflen = wrq.u.data.length;
820 /* wrq.u.data.length is 16 bits so max size is 65535 */
828 /* Check if results not available yet */
831 /* Restart timer for only 100ms*/
834 timeout -= tv.tv_usec;
836 continue; /* Try again later */
841 fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
842 ifname, strerror(errno));
846 /* We have the results, go to process them */
850 /* In here, check if event and event type
851 * if scan event, read results. All errors bad & no reset timeout */
854 if(wrq.u.data.length)
857 struct stream_descr stream;
858 struct iwscan_state state = { .ap_num = 1, .val_index = 0 };
862 /* Debugging code. In theory useless, because it's debugged ;-) */
864 printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
865 for(i = 1; i < wrq.u.data.length; i++)
866 printf(":%02X", buffer[i]);
869 printf("%-8.16s Scan completed :\n", ifname);
870 iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
873 /* Extract an event and print it */
874 ret = iw_extract_event_stream(&stream, &iwe,
875 range.we_version_compiled);
877 print_scanning_token(&stream, &iwe, &state,
884 printf("%-8.16s No scan results\n\n", ifname);
890 /*********************** FREQUENCIES/CHANNELS ***********************/
892 /*------------------------------------------------------------------*/
894 * Print the number of channels and available frequency for the device
897 print_freq_info(int skfd,
899 char * args[], /* Command line args */
900 int count) /* Args count */
903 struct iw_range range;
907 char buffer[128]; /* Temporary buffer */
909 /* Avoid "Unused parameter" warning */
910 args = args; count = count;
912 /* Get list of frequencies / channels */
913 if(iw_get_range_info(skfd, ifname, &range) < 0)
914 fprintf(stderr, "%-8.16s no frequency information.\n\n",
918 if(range.num_frequency > 0)
920 printf("%-8.16s %d channels in total; available frequencies :\n",
921 ifname, range.num_channels);
923 for(k = 0; k < range.num_frequency; k++)
925 freq = iw_freq2float(&(range.freq[k]));
926 iw_print_freq_value(buffer, sizeof(buffer), freq);
927 printf(" Channel %.2d : %s\n",
928 range.freq[k].i, buffer);
932 printf("%-8.16s %d channels\n",
933 ifname, range.num_channels);
935 /* Get current frequency / channel and display it */
936 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
938 freq = iw_freq2float(&(wrq.u.freq));
939 channel = iw_freq_to_channel(freq, &range);
940 iw_print_freq(buffer, sizeof(buffer),
941 freq, channel, wrq.u.freq.flags);
942 printf(" Current %s\n\n", buffer);
948 /***************************** BITRATES *****************************/
950 /*------------------------------------------------------------------*/
952 * Print the number of available bitrates for the device
955 print_bitrate_info(int skfd,
957 char * args[], /* Command line args */
958 int count) /* Args count */
961 struct iw_range range;
965 /* Avoid "Unused parameter" warning */
966 args = args; count = count;
968 /* Extract range info */
969 if(iw_get_range_info(skfd, ifname, &range) < 0)
970 fprintf(stderr, "%-8.16s no bit-rate information.\n\n",
974 if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES))
976 printf("%-8.16s %d available bit-rates :\n",
977 ifname, range.num_bitrates);
979 for(k = 0; k < range.num_bitrates; k++)
981 iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]);
982 /* Maybe this should be %10s */
983 printf("\t %s\n", buffer);
987 printf("%-8.16s unknown bit-rate information.\n", ifname);
989 /* Get current bit rate */
990 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
992 iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
993 printf(" Current Bit Rate%c%s\n",
994 (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
997 /* Try to get the broadcast bitrate if it exist... */
998 if(range.bitrate_capa & IW_BITRATE_BROADCAST)
1000 wrq.u.bitrate.flags = IW_BITRATE_BROADCAST;
1001 if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
1003 iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value);
1004 printf(" Broadcast Bit Rate%c%s\n",
1005 (wrq.u.bitrate.fixed ? '=' : ':'), buffer);
1014 /************************* ENCRYPTION KEYS *************************/
1016 /*------------------------------------------------------------------*/
1018 * Print all the available encryption keys for the device
1021 print_keys_info(int skfd,
1023 char * args[], /* Command line args */
1024 int count) /* Args count */
1027 struct iw_range range;
1028 unsigned char key[IW_ENCODING_TOKEN_MAX];
1032 /* Avoid "Unused parameter" warning */
1033 args = args; count = count;
1035 /* Extract range info */
1036 if(iw_get_range_info(skfd, ifname, &range) < 0)
1037 fprintf(stderr, "%-8.16s no encryption keys information.\n\n",
1041 printf("%-8.16s ", ifname);
1042 /* Print key sizes */
1043 if((range.num_encoding_sizes > 0) &&
1044 (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
1046 printf("%d key sizes : %d", range.num_encoding_sizes,
1047 range.encoding_size[0] * 8);
1048 /* Print them all */
1049 for(k = 1; k < range.num_encoding_sizes; k++)
1050 printf(", %d", range.encoding_size[k] * 8);
1053 /* Print the keys and associate mode */
1054 printf("%d keys available :\n", range.max_encoding_tokens);
1055 for(k = 1; k <= range.max_encoding_tokens; k++)
1057 wrq.u.data.pointer = (caddr_t) key;
1058 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
1059 wrq.u.data.flags = k;
1060 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
1062 fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno));
1065 if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
1066 (wrq.u.data.length == 0))
1067 printf("\t\t[%d]: off\n", k);
1070 /* Display the key */
1071 iw_print_key(buffer, sizeof(buffer),
1072 key, wrq.u.data.length, wrq.u.data.flags);
1073 printf("\t\t[%d]: %s", k, buffer);
1076 printf(" (%d bits)", wrq.u.data.length * 8);
1080 /* Print current key index and mode */
1081 wrq.u.data.pointer = (caddr_t) key;
1082 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
1083 wrq.u.data.flags = 0; /* Set index to zero to get current */
1084 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
1086 /* Note : if above fails, we have already printed an error
1087 * message int the loop above */
1088 printf(" Current Transmit Key: [%d]\n",
1089 wrq.u.data.flags & IW_ENCODE_INDEX);
1090 if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
1091 printf(" Security mode:restricted\n");
1092 if(wrq.u.data.flags & IW_ENCODE_OPEN)
1093 printf(" Security mode:open\n");
1101 /************************* POWER MANAGEMENT *************************/
1103 /*------------------------------------------------------------------*/
1105 * Print Power Management info for each device
1108 get_pm_value(int skfd,
1110 struct iwreq * pwrq,
1114 int we_version_compiled)
1116 /* Get Another Power Management value */
1117 pwrq->u.power.flags = flags;
1118 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
1120 /* Let's check the value and its type */
1121 if(pwrq->u.power.flags & IW_POWER_TYPE)
1123 iw_print_pm_value(buffer, buflen,
1124 pwrq->u.power.value, pwrq->u.power.flags,
1125 we_version_compiled);
1126 printf("\n %s", buffer);
1129 return(pwrq->u.power.flags);
1132 /*------------------------------------------------------------------*/
1134 * Print Power Management range for each type
1137 print_pm_value_range(char * name,
1144 int we_version_compiled)
1146 if(iwr_flags & mask)
1148 int flags = (iwr_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
1149 /* Display if auto or fixed */
1151 (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
1153 /* Print the range */
1154 iw_print_pm_value(buffer, buflen,
1155 iwr_min, flags | IW_POWER_MIN,
1156 we_version_compiled);
1157 printf("%s\n ", buffer);
1158 iw_print_pm_value(buffer, buflen,
1159 iwr_max, flags | IW_POWER_MAX,
1160 we_version_compiled);
1161 printf("%s\n ", buffer);
1165 /*------------------------------------------------------------------*/
1167 * Power Management types of values
1169 static const unsigned int pm_type_flags[] = {
1174 static const int pm_type_flags_size = (sizeof(pm_type_flags)/sizeof(pm_type_flags[0]));
1176 /*------------------------------------------------------------------*/
1178 * Print Power Management info for each device
1181 print_pm_info(int skfd,
1183 char * args[], /* Command line args */
1184 int count) /* Args count */
1187 struct iw_range range;
1190 /* Avoid "Unused parameter" warning */
1191 args = args; count = count;
1193 /* Extract range info */
1194 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1195 (range.we_version_compiled < 10))
1196 fprintf(stderr, "%-8.16s no power management information.\n\n",
1200 printf("%-8.16s ", ifname);
1202 /* Display modes availables */
1203 if(range.pm_capa & IW_POWER_MODE)
1205 printf("Supported modes :\n ");
1206 if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
1207 printf("\t\to Receive all packets (unicast & multicast)\n ");
1208 if(range.pm_capa & IW_POWER_UNICAST_R)
1209 printf("\t\to Receive Unicast only (discard multicast)\n ");
1210 if(range.pm_capa & IW_POWER_MULTICAST_R)
1211 printf("\t\to Receive Multicast only (discard unicast)\n ");
1212 if(range.pm_capa & IW_POWER_FORCE_S)
1213 printf("\t\to Force sending using Power Management\n ");
1214 if(range.pm_capa & IW_POWER_REPEATER)
1215 printf("\t\to Repeat multicast\n ");
1217 /* Display min/max period availables */
1218 print_pm_value_range("period ", IW_POWER_PERIOD,
1219 range.pmp_flags, range.min_pmp, range.max_pmp,
1220 buffer, sizeof(buffer), range.we_version_compiled);
1221 /* Display min/max timeout availables */
1222 print_pm_value_range("timeout", IW_POWER_TIMEOUT,
1223 range.pmt_flags, range.min_pmt, range.max_pmt,
1224 buffer, sizeof(buffer), range.we_version_compiled);
1225 /* Display min/max saving availables */
1226 print_pm_value_range("saving ", IW_POWER_SAVING,
1227 range.pms_flags, range.min_pms, range.max_pms,
1228 buffer, sizeof(buffer), range.we_version_compiled);
1230 /* Get current Power Management settings */
1231 wrq.u.power.flags = 0;
1232 if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
1234 int flags = wrq.u.power.flags;
1236 /* Is it disabled ? */
1237 if(wrq.u.power.disabled)
1238 printf("Current mode:off\n");
1241 unsigned int pm_type = 0;
1242 unsigned int pm_mask = 0;
1243 unsigned int remain_mask = range.pm_capa & IW_POWER_TYPE;
1246 /* Let's check the mode */
1247 iw_print_pm_mode(buffer, sizeof(buffer), flags);
1248 printf("Current %s", buffer);
1250 /* Let's check if nothing (simply on) */
1251 if((flags & IW_POWER_MODE) == IW_POWER_ON)
1254 /* Let's check the value and its type */
1255 if(wrq.u.power.flags & IW_POWER_TYPE)
1257 iw_print_pm_value(buffer, sizeof(buffer),
1258 wrq.u.power.value, wrq.u.power.flags,
1259 range.we_version_compiled);
1260 printf("\n %s", buffer);
1265 /* Deal with min/max for the current value */
1267 /* If we have been returned a MIN value, ask for the MAX */
1268 if(flags & IW_POWER_MIN)
1269 pm_mask = IW_POWER_MAX;
1270 /* If we have been returned a MAX value, ask for the MIN */
1271 if(flags & IW_POWER_MAX)
1272 pm_mask = IW_POWER_MIN;
1273 /* If we have something to ask for... */
1277 get_pm_value(skfd, ifname, &wrq, pm_mask,
1278 buffer, sizeof(buffer),
1279 range.we_version_compiled);
1282 /* Remove current type from mask */
1283 remain_mask &= ~(wrq.u.power.flags);
1285 /* Check what other types we still have to read */
1286 while(i < pm_type_flags_size)
1288 pm_type = remain_mask & pm_type_flags[i];
1293 /* Nothing anymore : exit the loop */
1297 /* Ask for this other type of value */
1298 flags = get_pm_value(skfd, ifname, &wrq, pm_type,
1299 buffer, sizeof(buffer),
1300 range.we_version_compiled);
1301 /* Loop back for min/max */
1311 #ifndef WE_ESSENTIAL
1312 /************************** TRANSMIT POWER **************************/
1314 /*------------------------------------------------------------------*/
1316 * Print the number of available transmit powers for the device
1319 print_txpower_info(int skfd,
1321 char * args[], /* Command line args */
1322 int count) /* Args count */
1325 struct iw_range range;
1330 /* Avoid "Unused parameter" warning */
1331 args = args; count = count;
1333 /* Extract range info */
1334 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1335 (range.we_version_compiled < 10))
1336 fprintf(stderr, "%-8.16s no transmit-power information.\n\n",
1340 if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER))
1341 printf("%-8.16s unknown transmit-power information.\n\n", ifname);
1344 printf("%-8.16s %d available transmit-powers :\n",
1345 ifname, range.num_txpower);
1346 /* Print them all */
1347 for(k = 0; k < range.num_txpower; k++)
1349 /* Check for relative values */
1350 if(range.txpower_capa & IW_TXPOW_RELATIVE)
1352 printf("\t %d (no units)\n", range.txpower[k]);
1356 if(range.txpower_capa & IW_TXPOW_MWATT)
1358 dbm = iw_mwatt2dbm(range.txpower[k]);
1359 mwatt = range.txpower[k];
1363 dbm = range.txpower[k];
1364 mwatt = iw_dbm2mwatt(range.txpower[k]);
1366 printf("\t %d dBm \t(%d mW)\n", dbm, mwatt);
1371 /* Get current Transmit Power */
1372 if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
1374 printf(" Current Tx-Power");
1376 if(wrq.u.txpower.disabled)
1381 if(wrq.u.txpower.fixed)
1385 /* Check for relative values */
1386 if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE)
1388 /* I just hate relative value, because they are
1389 * driver specific, so not very meaningfull to apps.
1390 * But, we have to support that, because
1391 * this is the way hardware is... */
1392 printf("\t %d (no units)\n", wrq.u.txpower.value);
1396 if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
1398 dbm = iw_mwatt2dbm(wrq.u.txpower.value);
1399 mwatt = wrq.u.txpower.value;
1403 dbm = wrq.u.txpower.value;
1404 mwatt = iw_dbm2mwatt(wrq.u.txpower.value);
1406 printf("%d dBm \t(%d mW)\n\n", dbm, mwatt);
1414 /*********************** RETRY LIMIT/LIFETIME ***********************/
1416 /*------------------------------------------------------------------*/
1418 * Print one retry value
1421 get_retry_value(int skfd,
1423 struct iwreq * pwrq,
1427 int we_version_compiled)
1429 /* Get Another retry value */
1430 pwrq->u.retry.flags = flags;
1431 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
1433 /* Let's check the value and its type */
1434 if(pwrq->u.retry.flags & IW_RETRY_TYPE)
1436 iw_print_retry_value(buffer, buflen,
1437 pwrq->u.retry.value, pwrq->u.retry.flags,
1438 we_version_compiled);
1439 printf("%s\n ", buffer);
1442 return(pwrq->u.retry.flags);
1445 /*------------------------------------------------------------------*/
1447 * Print Power Management range for each type
1450 print_retry_value_range(char * name,
1457 int we_version_compiled)
1459 if(iwr_flags & mask)
1461 int flags = (iwr_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
1462 /* Display if auto or fixed */
1464 (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed",
1466 /* Print the range */
1467 iw_print_retry_value(buffer, buflen,
1468 iwr_min, flags | IW_POWER_MIN,
1469 we_version_compiled);
1470 printf("%s\n ", buffer);
1471 iw_print_retry_value(buffer, buflen,
1472 iwr_max, flags | IW_POWER_MAX,
1473 we_version_compiled);
1474 printf("%s\n ", buffer);
1478 /*------------------------------------------------------------------*/
1480 * Print Retry info for each device
1483 print_retry_info(int skfd,
1485 char * args[], /* Command line args */
1486 int count) /* Args count */
1489 struct iw_range range;
1492 /* Avoid "Unused parameter" warning */
1493 args = args; count = count;
1495 /* Extract range info */
1496 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1497 (range.we_version_compiled < 11))
1498 fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n",
1502 printf("%-8.16s ", ifname);
1504 /* Display min/max limit availables */
1505 print_retry_value_range("limit ", IW_RETRY_LIMIT, range.retry_flags,
1506 range.min_retry, range.max_retry,
1507 buffer, sizeof(buffer),
1508 range.we_version_compiled);
1509 /* Display min/max lifetime availables */
1510 print_retry_value_range("lifetime", IW_RETRY_LIFETIME,
1512 range.min_r_time, range.max_r_time,
1513 buffer, sizeof(buffer),
1514 range.we_version_compiled);
1516 /* Get current retry settings */
1517 wrq.u.retry.flags = 0;
1518 if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
1520 int flags = wrq.u.retry.flags;
1522 /* Is it disabled ? */
1523 if(wrq.u.retry.disabled)
1524 printf("Current mode:off\n ");
1527 unsigned int retry_type = 0;
1528 unsigned int retry_mask = 0;
1529 unsigned int remain_mask = range.retry_capa & IW_RETRY_TYPE;
1531 /* Let's check the mode */
1532 printf("Current mode:on\n ");
1534 /* Let's check the value and its type */
1535 if(wrq.u.retry.flags & IW_RETRY_TYPE)
1537 iw_print_retry_value(buffer, sizeof(buffer),
1538 wrq.u.retry.value, wrq.u.retry.flags,
1539 range.we_version_compiled);
1540 printf("%s\n ", buffer);
1545 /* Deal with min/max/short/long for the current value */
1547 /* If we have been returned a MIN value, ask for the MAX */
1548 if(flags & IW_RETRY_MIN)
1549 retry_mask = IW_RETRY_MAX;
1550 /* If we have been returned a MAX value, ask for the MIN */
1551 if(flags & IW_RETRY_MAX)
1552 retry_mask = IW_RETRY_MIN;
1553 /* Same for SHORT and LONG */
1554 if(flags & IW_RETRY_SHORT)
1555 retry_mask = IW_RETRY_LONG;
1556 if(flags & IW_RETRY_LONG)
1557 retry_mask = IW_RETRY_SHORT;
1558 /* If we have something to ask for... */
1561 retry_mask |= retry_type;
1562 get_retry_value(skfd, ifname, &wrq, retry_mask,
1563 buffer, sizeof(buffer),
1564 range.we_version_compiled);
1567 /* And if we have both a limit and a lifetime,
1568 * ask the other one */
1569 remain_mask &= ~(wrq.u.retry.flags);
1570 retry_type = remain_mask;
1571 /* Nothing anymore : exit the loop */
1575 /* Ask for this other type of value */
1576 flags = get_retry_value(skfd, ifname, &wrq, retry_type,
1577 buffer, sizeof(buffer),
1578 range.we_version_compiled);
1579 /* Loop back for min/max/short/long */
1588 /************************ ACCESS POINT LIST ************************/
1590 * Note : now that we have scanning support, this is depracted and
1591 * won't survive long. Actually, next version it's out !
1594 /*------------------------------------------------------------------*/
1596 * Display the list of ap addresses and the associated stats
1597 * Exacly the same as the spy list, only with different IOCTL and messages
1600 print_ap_info(int skfd,
1602 char * args[], /* Command line args */
1603 int count) /* Args count */
1606 char buffer[(sizeof(struct iw_quality) +
1607 sizeof(struct sockaddr)) * IW_MAX_AP];
1609 struct sockaddr * hwa;
1610 struct iw_quality * qual;
1617 /* Avoid "Unused parameter" warning */
1618 args = args; count = count;
1621 wrq.u.data.pointer = (caddr_t) buffer;
1622 wrq.u.data.length = IW_MAX_AP;
1623 wrq.u.data.flags = 0;
1624 if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
1626 fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname);
1630 /* Number of addresses */
1631 n = wrq.u.data.length;
1632 has_qual = wrq.u.data.flags;
1635 hwa = (struct sockaddr *) buffer;
1636 qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
1638 /* Check if we have valid mac address type */
1639 if(iw_check_mac_addr_type(skfd, ifname) < 0)
1641 fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
1645 /* Get range info if we can */
1646 if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
1651 printf("%-8.16s No Peers/Access-Point in range\n", ifname);
1653 printf("%-8.16s Peers/Access-Points in range:\n", ifname);
1654 for(i = 0; i < n; i++)
1658 /* Print stats for this address */
1659 printf(" %s : ", iw_saether_ntop(&hwa[i], temp));
1660 iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range);
1661 printf("%s\n", temp);
1664 /* Only print the address */
1665 printf(" %s\n", iw_saether_ntop(&hwa[i], temp));
1671 /******************** WIRELESS EVENT CAPABILITY ********************/
1673 static const char * event_capa_req[] =
1675 [SIOCSIWNWID - SIOCIWFIRST] = "Set NWID (kernel generated)",
1676 [SIOCSIWFREQ - SIOCIWFIRST] = "Set Frequency/Channel (kernel generated)",
1677 [SIOCGIWFREQ - SIOCIWFIRST] = "New Frequency/Channel",
1678 [SIOCSIWMODE - SIOCIWFIRST] = "Set Mode (kernel generated)",
1679 [SIOCGIWTHRSPY - SIOCIWFIRST] = "Spy threshold crossed",
1680 [SIOCGIWAP - SIOCIWFIRST] = "New Access Point/Cell address - roaming",
1681 [SIOCGIWSCAN - SIOCIWFIRST] = "Scan request completed",
1682 [SIOCSIWESSID - SIOCIWFIRST] = "Set ESSID (kernel generated)",
1683 [SIOCGIWESSID - SIOCIWFIRST] = "New ESSID",
1684 [SIOCGIWRATE - SIOCIWFIRST] = "New bit-rate",
1685 [SIOCSIWENCODE - SIOCIWFIRST] = "Set Encoding (kernel generated)",
1686 [SIOCGIWPOWER - SIOCIWFIRST] = NULL,
1689 static const char * event_capa_evt[] =
1691 [IWEVTXDROP - IWEVFIRST] = "Tx packet dropped - retry exceeded",
1692 [IWEVCUSTOM - IWEVFIRST] = "Custom driver event",
1693 [IWEVREGISTERED - IWEVFIRST] = "Registered node",
1694 [IWEVEXPIRED - IWEVFIRST] = "Expired node",
1697 static const struct iwmask_name iw_scan_capa_name[] = {
1698 { IW_SCAN_CAPA_ESSID, "ESSID" },
1699 { IW_SCAN_CAPA_BSSID, "BSSID" },
1700 { IW_SCAN_CAPA_CHANNEL, "Channel" },
1701 { IW_SCAN_CAPA_MODE, "Mode" },
1702 { IW_SCAN_CAPA_RATE, "Rate" },
1703 { IW_SCAN_CAPA_TYPE, "Type" },
1704 { IW_SCAN_CAPA_TIME, "Time" },
1706 #define IW_SCAN_CAPA_NUM IW_ARRAY_LEN(iw_scan_capa_name)
1708 /*------------------------------------------------------------------*/
1710 * Print the event capability for the device
1713 print_event_capa_info(int skfd,
1715 char * args[], /* Command line args */
1716 int count) /* Args count */
1718 struct iw_range range;
1721 /* Avoid "Unused parameter" warning */
1722 args = args; count = count;
1724 /* Extract range info */
1725 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1726 (range.we_version_compiled < 10))
1727 fprintf(stderr, "%-8.16s no wireless event capability information.\n\n",
1733 for(cmd = 0x8B00; cmd < 0x8C0F; cmd++)
1735 int idx = IW_EVENT_CAPA_INDEX(cmd);
1736 int mask = IW_EVENT_CAPA_MASK(cmd);
1737 printf("0x%X - %d - %X\n", cmd, idx, mask);
1741 printf("%-8.16s Wireless Events supported :\n", ifname);
1743 for(cmd = SIOCIWFIRST; cmd <= SIOCGIWPOWER; cmd++)
1745 int idx = IW_EVENT_CAPA_INDEX(cmd);
1746 int mask = IW_EVENT_CAPA_MASK(cmd);
1747 if(range.event_capa[idx] & mask)
1748 printf(" 0x%04X : %s\n",
1749 cmd, event_capa_req[cmd - SIOCIWFIRST]);
1751 for(cmd = IWEVFIRST; cmd <= IWEVEXPIRED; cmd++)
1753 int idx = IW_EVENT_CAPA_INDEX(cmd);
1754 int mask = IW_EVENT_CAPA_MASK(cmd);
1755 if(range.event_capa[idx] & mask)
1756 printf(" 0x%04X : %s\n",
1757 cmd, event_capa_evt[cmd - IWEVFIRST]);
1761 /* Add Scanning Capacity as a bonus, if available */
1762 if(range.scan_capa != 0)
1764 printf("%-8.16s Scanning capabilities :", ifname);
1765 iw_print_mask_name(range.scan_capa,
1766 iw_scan_capa_name, IW_SCAN_CAPA_NUM,
1774 /*************************** WPA SUPPORT ***************************/
1776 /*------------------------------------------------------------------*/
1778 * Print the authentication parameters for the device
1781 print_auth_info(int skfd,
1783 char * args[], /* Command line args */
1784 int count) /* Args count */
1787 struct iw_range range;
1790 /* Avoid "Unused parameter" warning */
1791 args = args; count = count;
1793 /* Extract range info */
1794 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
1795 (range.we_version_compiled < 18))
1796 fprintf(stderr, "%-8.16s no authentication information.\n\n",
1800 /* Print WPA/802.1x/802.11i security parameters */
1803 printf("%-8.16s unknown authentication information.\n\n", ifname);
1807 /* Display advanced encryption capabilities */
1808 printf("%-8.16s Authentication capabilities :", ifname);
1809 iw_print_mask_name(range.enc_capa,
1810 iw_auth_capa_name, IW_AUTH_CAPA_NUM,
1814 /* Extract all auth settings */
1815 for(k = 0; k < IW_AUTH_SETTINGS_NUM; k++)
1817 wrq.u.param.flags = iw_auth_settings[k].value;
1818 if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0)
1820 printf(" Current %s :", iw_auth_settings[k].label);
1821 if(iw_auth_settings[k].names != NULL)
1822 iw_print_mask_name(wrq.u.param.value,
1823 iw_auth_settings[k].names,
1824 iw_auth_settings[k].num_names,
1827 printf((wrq.u.param.value) ? " yes" : " no");
1838 /*------------------------------------------------------------------*/
1840 * Print all the available wpa keys for the device
1843 print_wpakeys_info(int skfd,
1845 char * args[], /* Command line args */
1846 int count) /* Args count */
1849 struct iw_range range;
1850 unsigned char extbuf[IW_EXTKEY_SIZE];
1851 struct iw_encode_ext *extinfo;
1855 /* Avoid "Unused parameter" warning */
1856 args = args; count = count;
1858 /* This always point to the same place */
1859 extinfo = (struct iw_encode_ext *) extbuf;
1861 /* Extract range info */
1862 if(iw_get_range_info(skfd, ifname, &range) < 0)
1863 fprintf(stderr, "%-8.16s no wpa key information.\n\n",
1867 printf("%-8.16s ", ifname);
1868 /* Print key sizes */
1869 if((range.num_encoding_sizes > 0) &&
1870 (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
1872 printf("%d key sizes : %d", range.num_encoding_sizes,
1873 range.encoding_size[0] * 8);
1874 /* Print them all */
1875 for(k = 1; k < range.num_encoding_sizes; k++)
1876 printf(", %d", range.encoding_size[k] * 8);
1880 /* Print the keys */
1881 printf("%d keys available :\n", range.max_encoding_tokens);
1882 for(k = 1; k <= range.max_encoding_tokens; k++)
1884 /* Cleanup. Driver may not fill everything */
1885 memset(extbuf, '\0', IW_EXTKEY_SIZE);
1887 /* Get whole struct containing one WPA key */
1888 wrq.u.data.pointer = (caddr_t) extbuf;
1889 wrq.u.data.length = IW_EXTKEY_SIZE;
1890 wrq.u.data.flags = k;
1891 if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) < 0)
1893 fprintf(stderr, "Error reading wpa keys (SIOCGIWENCODEEXT): %s\n", strerror(errno));
1898 if(wrq.u.data.length <
1899 (sizeof(struct iw_encode_ext) + extinfo->key_len))
1902 /* Check if key is disabled */
1903 if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
1904 (extinfo->key_len == 0))
1905 printf("\t\t[%d]: off\n", k);
1908 /* Display the key */
1909 iw_print_key(buffer, sizeof(buffer),
1910 extinfo->key, extinfo->key_len, wrq.u.data.flags);
1911 printf("\t\t[%d]: %s", k, buffer);
1914 printf(" (%d bits)", extinfo->key_len * 8);
1918 printf("\t\t Address: %s\n",
1919 iw_saether_ntop(&extinfo->addr, buffer));
1921 printf("\t\t Algorithm:");
1922 iw_print_value_name(extinfo->alg,
1923 iw_encode_alg_name, IW_ENCODE_ALG_NUM);
1925 printf("\n\t\t Flags: 0x%08x\n", extinfo->ext_flags);
1926 if (extinfo->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID)
1927 printf("\t\t tx-seq-valid\n");
1928 if (extinfo->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1929 printf("\t\t rx-seq-valid\n");
1930 if (extinfo->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
1931 printf("\t\t group-key\n");
1934 /* Print current key index and mode */
1935 wrq.u.data.pointer = (caddr_t) extbuf;
1936 wrq.u.data.length = IW_EXTKEY_SIZE;
1937 wrq.u.data.flags = 0; /* Set index to zero to get current */
1938 if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) >= 0)
1940 /* Note : if above fails, we have already printed an error
1941 * message int the loop above */
1942 printf(" Current Transmit Key: [%d]\n",
1943 wrq.u.data.flags & IW_ENCODE_INDEX);
1944 if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
1945 printf(" Security mode:restricted\n");
1946 if(wrq.u.data.flags & IW_ENCODE_OPEN)
1947 printf(" Security mode:open\n");
1955 /*------------------------------------------------------------------*/
1957 * Print the Generic IE for the device
1958 * Note : indentation is broken. We need to fix that.
1961 print_gen_ie_info(int skfd,
1963 char * args[], /* Command line args */
1964 int count) /* Args count */
1967 unsigned char buf[IW_GENERIC_IE_MAX];
1969 /* Avoid "Unused parameter" warning */
1970 args = args; count = count;
1972 wrq.u.data.pointer = (caddr_t)buf;
1973 wrq.u.data.length = IW_GENERIC_IE_MAX;
1974 wrq.u.data.flags = 0;
1976 if(iw_get_ext(skfd, ifname, SIOCGIWGENIE, &wrq) < 0)
1977 fprintf(stderr, "%-8.16s no generic IE (%s).\n\n",
1978 ifname, strerror(errno));
1981 fprintf(stderr, "%-8.16s\n", ifname);
1982 if(wrq.u.data.length == 0)
1983 printf(" empty generic IE\n");
1985 iw_print_gen_ie(buf, wrq.u.data.length);
1991 /**************************** MODULATION ****************************/
1993 /*------------------------------------------------------------------*/
1995 * Print Modulation info for each device
1998 print_modul_info(int skfd,
2000 char * args[], /* Command line args */
2001 int count) /* Args count */
2004 struct iw_range range;
2006 /* Avoid "Unused parameter" warning */
2007 args = args; count = count;
2009 /* Extract range info */
2010 if((iw_get_range_info(skfd, ifname, &range) < 0) ||
2011 (range.we_version_compiled < 11))
2012 fprintf(stderr, "%-8.16s no modulation information.\n\n",
2016 if(range.modul_capa == 0x0)
2017 printf("%-8.16s unknown modulation information.\n\n", ifname);
2021 printf("%-8.16s Modulations available :\n", ifname);
2023 /* Display each modulation available */
2024 for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
2026 if((range.modul_capa & iw_modul_list[i].mask)
2027 == iw_modul_list[i].mask)
2028 printf(" %-8s: %s\n",
2029 iw_modul_list[i].cmd, iw_modul_list[i].verbose);
2032 /* Get current modulations settings */
2033 wrq.u.param.flags = 0;
2034 if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) >= 0)
2036 unsigned int modul = wrq.u.param.value;
2039 printf(" Current modulations %c",
2040 wrq.u.param.fixed ? '=' : ':');
2042 /* Display each modulation enabled */
2043 for(i = 0; i < IW_SIZE_MODUL_LIST; i++)
2045 if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask)
2051 printf("%s", iw_modul_list[i].cmd);
2062 #endif /* WE_ESSENTIAL */
2064 /************************* COMMON UTILITIES *************************/
2066 * This section was initially written by Michael Tokarev <mjt@tls.msk.ru>
2067 * but heavily modified by me ;-)
2070 /*------------------------------------------------------------------*/
2072 * Map command line arguments to the proper procedure...
2074 typedef struct iwlist_entry {
2075 const char * cmd; /* Command line shorthand */
2076 iw_enum_handler fn; /* Subroutine */
2078 const char * argsname; /* Args as human readable string */
2081 static const struct iwlist_entry iwlist_cmds[] = {
2082 { "scanning", print_scanning_info, -1, "[essid NNN] [last]" },
2083 { "frequency", print_freq_info, 0, NULL },
2084 { "channel", print_freq_info, 0, NULL },
2085 { "bitrate", print_bitrate_info, 0, NULL },
2086 { "rate", print_bitrate_info, 0, NULL },
2087 { "encryption", print_keys_info, 0, NULL },
2088 { "keys", print_keys_info, 0, NULL },
2089 { "power", print_pm_info, 0, NULL },
2090 #ifndef WE_ESSENTIAL
2091 { "txpower", print_txpower_info, 0, NULL },
2092 { "retry", print_retry_info, 0, NULL },
2093 { "ap", print_ap_info, 0, NULL },
2094 { "accesspoints", print_ap_info, 0, NULL },
2095 { "peers", print_ap_info, 0, NULL },
2096 { "event", print_event_capa_info, 0, NULL },
2097 { "auth", print_auth_info, 0, NULL },
2098 { "wpakeys", print_wpakeys_info, 0, NULL },
2099 { "genie", print_gen_ie_info, 0, NULL },
2100 { "modulation", print_modul_info, 0, NULL },
2101 #endif /* WE_ESSENTIAL */
2102 { NULL, NULL, 0, 0 },
2105 /*------------------------------------------------------------------*/
2107 * Find the most appropriate command matching the command line
2109 static inline const iwlist_cmd *
2110 find_command(const char * cmd)
2112 const iwlist_cmd * found = NULL;
2114 unsigned int len = strlen(cmd);
2117 /* Go through all commands */
2118 for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
2120 /* No match -> next one */
2121 if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
2124 /* Exact match -> perfect */
2125 if(len == strlen(iwlist_cmds[i].cmd))
2126 return &iwlist_cmds[i];
2131 found = &iwlist_cmds[i];
2134 if (iwlist_cmds[i].fn != found->fn)
2140 fprintf(stderr, "iwlist: unknown command `%s' (check 'iwlist --help').\n", cmd);
2146 fprintf(stderr, "iwlist: command `%s' is ambiguous (check 'iwlist --help').\n", cmd);
2153 /*------------------------------------------------------------------*/
2157 static void iw_usage(int status)
2159 FILE * f = status ? stderr : stdout;
2162 for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
2164 fprintf(f, "%s [interface] %s %s\n",
2165 (i ? " " : "Usage: iwlist"),
2167 iwlist_cmds[i].argsname ? iwlist_cmds[i].argsname : "");
2173 /******************************* MAIN ********************************/
2175 /*------------------------------------------------------------------*/
2183 int skfd; /* generic raw socket desc. */
2184 char *dev; /* device name */
2185 char *cmd; /* command */
2186 char **args; /* Command arguments */
2187 int count; /* Number of arguments */
2188 const iwlist_cmd *iwcmd;
2194 /* Those don't apply to all interfaces */
2195 if((argc == 2) && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))
2197 if((argc == 2) && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")))
2198 return(iw_print_version_info("iwlist"));
2215 /* find a command */
2216 iwcmd = find_command(cmd);
2220 /* Check arg numbers */
2221 if((iwcmd->max_count >= 0) && (count > iwcmd->max_count))
2223 fprintf(stderr, "iwlist: command `%s' needs fewer arguments (max %d)\n",
2224 iwcmd->cmd, iwcmd->max_count);
2228 /* Create a channel to the NET kernel. */
2229 if((skfd = iw_sockets_open()) < 0)
2235 /* do the actual work */
2237 goterr = (*iwcmd->fn)(skfd, dev, args, count);
2239 iw_enum_devices(skfd, iwcmd->fn, args, count);
2241 /* Close the socket. */
2242 iw_sockets_close(skfd);