OSDN Git Service

0703f3e81a7e3a03eff2a14dcc02a9248bef75c1
[android-x86/external-wireless-tools.git] / wireless_tools / iwlist.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPLB '99 - HPL 99->01
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-2002 Jean Tourrilhes <jt@hpl.hp.com>
12  */
13
14 #include "iwlib.h"              /* Header */
15 #include <sys/time.h>
16
17 /*********************** FREQUENCIES/CHANNELS ***********************/
18
19 /*------------------------------------------------------------------*/
20 /*
21  * Print the number of channels and available frequency for the device
22  */
23 static int
24 print_freq_info(int             skfd,
25                 char *          ifname,
26                 char *          args[],         /* Command line args */
27                 int             count)          /* Args count */
28 {
29   float                 freq;
30   struct iw_range       range;
31   int                   k;
32
33   /* Avoid "Unused parameter" warning */
34   args = args; count = count;
35
36   if(iw_get_range_info(skfd, ifname, &range) < 0)
37       fprintf(stderr, "%-8.8s  no frequency information.\n\n",
38                       ifname);
39   else
40     {
41       if(range.num_frequency > 0)
42         {
43           printf("%-8.8s  %d channels in total; available frequencies :\n",
44                  ifname, range.num_channels);
45           /* Print them all */
46           for(k = 0; k < range.num_frequency; k++)
47             {
48               printf("\t  Channel %.2d : ", range.freq[k].i);
49               freq = iw_freq2float(&(range.freq[k]));
50               if(freq >= GIGA)
51                 printf("%g GHz\n", freq / GIGA);
52               else
53                 if(freq >= MEGA)
54                   printf("%g MHz\n", freq / MEGA);
55                 else
56                   printf("%g kHz\n", freq / KILO);
57             }
58           printf("\n\n");
59         }
60       else
61         printf("%-8.8s  %d channels\n\n",
62                ifname, range.num_channels);
63     }
64   return(0);
65 }
66
67 /************************ ACCESS POINT LIST ************************/
68
69 /*------------------------------------------------------------------*/
70 /*
71  * Display the list of ap addresses and the associated stats
72  * Exacly the same as the spy list, only with different IOCTL and messages
73  */
74 static int
75 print_ap_info(int       skfd,
76               char *    ifname,
77               char *    args[],         /* Command line args */
78               int       count)          /* Args count */
79 {
80   struct iwreq          wrq;
81   char          buffer[(sizeof(struct iw_quality) +
82                         sizeof(struct sockaddr)) * IW_MAX_AP];
83   char          temp[128];
84   struct sockaddr *     hwa;
85   struct iw_quality *   qual;
86   iwrange       range;
87   int           has_range = 0;
88   int           has_qual = 0;
89   int           n;
90   int           i;
91
92   /* Avoid "Unused parameter" warning */
93   args = args; count = count;
94
95   /* Collect stats */
96   wrq.u.data.pointer = (caddr_t) buffer;
97   wrq.u.data.length = IW_MAX_AP;
98   wrq.u.data.flags = 0;
99   if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0)
100     {
101       fprintf(stderr, "%-8.8s  Interface doesn't have a list of Access Points\n\n", ifname);
102       return(-1);
103     }
104
105   /* Number of addresses */
106   n = wrq.u.data.length;
107   has_qual = wrq.u.data.flags;
108
109   /* The two lists */
110   hwa = (struct sockaddr *) buffer;
111   qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
112
113   /* Check if we have valid mac address type */
114   if(iw_check_mac_addr_type(skfd, ifname) < 0)
115     {
116       fprintf(stderr, "%-8.8s  Interface doesn't support MAC addresses\n\n", ifname);
117       return(-2);
118     }
119
120   /* Get range info if we can */
121   if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
122     has_range = 1;
123
124   /* Display it */
125   if(n == 0)
126     printf("%-8.8s  No Access Point in range\n", ifname);
127   else
128     printf("%-8.8s  Access Points in range:\n", ifname);
129   for(i = 0; i < n; i++)
130     {
131       if(has_qual)
132         {
133           /* Print stats for this address */
134           printf("    %s : ", iw_pr_ether(temp, hwa[i].sa_data));
135           iw_print_stats(temp, &qual[i], &range, has_range);
136           printf("%s\n", temp);
137         }
138       else
139         /* Only print the address */
140         printf("    %s\n", iw_pr_ether(temp, hwa[i].sa_data));
141     }
142   printf("\n");
143   return(0);
144 }
145
146 /***************************** BITRATES *****************************/
147
148 /*------------------------------------------------------------------*/
149 /*
150  * Print the number of available bitrates for the device
151  */
152 static int
153 print_bitrate_info(int          skfd,
154                    char *       ifname,
155                    char *       args[],         /* Command line args */
156                    int          count)          /* Args count */
157 {
158   struct iw_range       range;
159   int                   k;
160   char                  buffer[128];
161
162   /* Avoid "Unused parameter" warning */
163   args = args; count = count;
164
165   /* Extract range info */
166   if(iw_get_range_info(skfd, ifname, &range) < 0)
167       fprintf(stderr, "%-8.8s  no bit-rate information.\n\n",
168                       ifname);
169   else
170     {
171       if((range.num_bitrates > 0) && (range.num_bitrates < IW_MAX_BITRATES))
172         {
173           printf("%-8.8s  %d available bit-rates :\n",
174                  ifname, range.num_bitrates);
175           /* Print them all */
176           for(k = 0; k < range.num_bitrates; k++)
177             {
178               iw_print_bitrate(buffer, range.bitrate[k]);
179               /* Maybe this should be %10s */
180               printf("\t  %s\n", buffer);
181             }
182           printf("\n\n");
183         }
184       else
185         printf("%-8.8s  No bit-rates ? Please update driver...\n\n", ifname);
186     }
187   return(0);
188 }
189
190 /************************* ENCRYPTION KEYS *************************/
191
192 /*------------------------------------------------------------------*/
193 /*
194  * Print the number of available encryption key for the device
195  */
196 static int
197 print_keys_info(int             skfd,
198                 char *          ifname,
199                 char *          args[],         /* Command line args */
200                 int             count)          /* Args count */
201 {
202   struct iwreq          wrq;
203   struct iw_range       range;
204   unsigned char         key[IW_ENCODING_TOKEN_MAX];
205   int                   k;
206   char                  buffer[128];
207
208   /* Avoid "Unused parameter" warning */
209   args = args; count = count;
210
211   /* Extract range info */
212   if(iw_get_range_info(skfd, ifname, &range) < 0)
213       fprintf(stderr, "%-8.8s  no encryption keys information.\n\n",
214                       ifname);
215   else
216     {
217       printf("%-8.8s  ", ifname);
218       /* Print key sizes */
219       if((range.num_encoding_sizes > 0) &&
220          (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES))
221         {
222           printf("%d key sizes : %d", range.num_encoding_sizes,
223                  range.encoding_size[0] * 8);
224           /* Print them all */
225           for(k = 1; k < range.num_encoding_sizes; k++)
226             printf(", %d", range.encoding_size[k] * 8);
227           printf("bits\n          ");
228         }
229       /* Print the keys and associate mode */
230       printf("%d keys available :\n", range.max_encoding_tokens);
231       for(k = 1; k <= range.max_encoding_tokens; k++)
232         {
233           wrq.u.data.pointer = (caddr_t) key;
234           wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
235           wrq.u.data.flags = k;
236           if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
237             {
238               fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
239               break;
240             }
241           if((wrq.u.data.flags & IW_ENCODE_DISABLED) ||
242              (wrq.u.data.length == 0))
243             printf("\t\t[%d]: off\n", k);
244           else
245             {
246               /* Display the key */
247               iw_print_key(buffer, key, wrq.u.data.length, wrq.u.data.flags);
248               printf("\t\t[%d]: %s", k, buffer);
249
250               /* Other info... */
251               printf(" (%d bits)", wrq.u.data.length * 8);
252               printf("\n");
253             }
254         }
255       /* Print current key and mode */
256       wrq.u.data.pointer = (caddr_t) key;
257       wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
258       wrq.u.data.flags = 0;     /* Set index to zero to get current */
259       if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0)
260         {
261           fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
262           return(-1);
263         }
264       printf("          Current Transmit Key: [%d]\n",
265              wrq.u.data.flags & IW_ENCODE_INDEX);
266       if(wrq.u.data.flags & IW_ENCODE_RESTRICTED)
267         printf("          Encryption mode:restricted\n");
268       if(wrq.u.data.flags & IW_ENCODE_OPEN)
269         printf("          Encryption mode:open\n");
270
271       printf("\n\n");
272     }
273   return(0);
274 }
275
276 /************************* POWER MANAGEMENT *************************/
277
278 /*------------------------------------------------------------------*/
279 /*
280  * Print Power Management info for each device
281  */
282 static inline int
283 get_pm_value(int                skfd,
284              char *             ifname,
285              struct iwreq *     pwrq,
286              int                flags,
287              char *             buffer)
288 {
289   /* Get Another Power Management value */
290   pwrq->u.power.flags = flags;
291   if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0)
292     {
293       /* Let's check the value and its type */
294       if(pwrq->u.power.flags & IW_POWER_TYPE)
295         {
296           iw_print_pm_value(buffer, pwrq->u.power.value, pwrq->u.power.flags);
297           printf("\n                 %s", buffer);
298         }
299     }
300   return(pwrq->u.power.flags);
301 }
302
303 /*------------------------------------------------------------------*/
304 /*
305  * Print Power Management info for each device
306  */
307 static int
308 print_pm_info(int               skfd,
309               char *            ifname,
310               char *            args[],         /* Command line args */
311               int               count)          /* Args count */
312 {
313   struct iwreq          wrq;
314   struct iw_range       range;
315   char                  buffer[128];
316
317   /* Avoid "Unused parameter" warning */
318   args = args; count = count;
319
320   /* Extract range info */
321   if(iw_get_range_info(skfd, ifname, &range) < 0)
322       fprintf(stderr, "%-8.8s  no power management information.\n\n",
323                       ifname);
324   else
325     {
326       printf("%-8.8s  ", ifname);
327 #if WIRELESS_EXT > 9
328       /* Display modes availables */
329       if(range.pm_capa & IW_POWER_MODE)
330         {
331           printf("Supported modes :\n          ");
332           if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R))
333             printf("\t\to Receive all packets (unicast & multicast)\n          ");
334           if(range.pm_capa & IW_POWER_UNICAST_R)
335             printf("\t\to Receive Unicast only (discard multicast)\n          ");
336           if(range.pm_capa & IW_POWER_MULTICAST_R)
337             printf("\t\to Receive Multicast only (discard unicast)\n          ");
338           if(range.pm_capa & IW_POWER_FORCE_S)
339             printf("\t\to Force sending using Power Management\n          ");
340           if(range.pm_capa & IW_POWER_REPEATER)
341             printf("\t\to Repeat multicast\n          ");
342         }
343       /* Display min/max period availables */
344       if(range.pmp_flags & IW_POWER_PERIOD)
345         {
346           int   flags = (range.pmp_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
347           /* Display if auto or fixed */
348           if(range.pmp_flags & IW_POWER_MIN)
349             printf("Auto  period  ; ");
350           else
351             printf("Fixed period  ; ");
352           /* Print the range */
353           iw_print_pm_value(buffer, range.min_pmp, flags | IW_POWER_MIN);
354           printf("%s\n                          ", buffer);
355           iw_print_pm_value(buffer, range.max_pmp, flags | IW_POWER_MAX);
356           printf("%s\n          ", buffer);
357           
358         }
359       /* Display min/max timeout availables */
360       if(range.pmt_flags & IW_POWER_TIMEOUT)
361         {
362           int   flags = (range.pmt_flags & ~(IW_POWER_MIN | IW_POWER_MAX));
363           /* Display if auto or fixed */
364           if(range.pmt_flags & IW_POWER_MIN)
365             printf("Auto  timeout ; ");
366           else
367             printf("Fixed timeout ; ");
368           /* Print the range */
369           iw_print_pm_value(buffer, range.min_pmt, flags | IW_POWER_MIN);
370           printf("%s\n                          ", buffer);
371           iw_print_pm_value(buffer, range.max_pmt, flags | IW_POWER_MAX);
372           printf("%s\n          ", buffer);
373           
374         }
375 #endif /* WIRELESS_EXT > 9 */
376
377       /* Get current Power Management settings */
378       wrq.u.power.flags = 0;
379       if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
380         {
381           int   flags = wrq.u.power.flags;
382
383           /* Is it disabled ? */
384           if(wrq.u.power.disabled)
385             printf("Current mode:off\n          ");
386           else
387             {
388               int       pm_mask = 0;
389
390               /* Let's check the mode */
391               iw_print_pm_mode(buffer, flags);
392               printf("Current %s", buffer);
393
394               /* Let's check if nothing (simply on) */
395               if((flags & IW_POWER_MODE) == IW_POWER_ON)
396                 printf("mode:on");
397               printf("\n                 ");
398
399               /* Let's check the value and its type */
400               if(wrq.u.power.flags & IW_POWER_TYPE)
401                 {
402                   iw_print_pm_value(buffer,
403                                     wrq.u.power.value, wrq.u.power.flags);
404                   printf("%s", buffer);
405                 }
406
407               /* If we have been returned a MIN value, ask for the MAX */
408               if(flags & IW_POWER_MIN)
409                 pm_mask = IW_POWER_MAX;
410               /* If we have been returned a MAX value, ask for the MIN */
411               if(flags & IW_POWER_MAX)
412                 pm_mask = IW_POWER_MIN;
413               /* If we have something to ask for... */
414               if(pm_mask)
415                 get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
416
417 #if WIRELESS_EXT > 9
418               /* And if we have both a period and a timeout, ask the other */
419               pm_mask = (range.pm_capa & (~(wrq.u.power.flags) &
420                                           IW_POWER_TYPE));
421               if(pm_mask)
422                 {
423                   int   base_mask = pm_mask;
424                   flags = get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
425                   pm_mask = 0;
426
427                   /* If we have been returned a MIN value, ask for the MAX */
428                   if(flags & IW_POWER_MIN)
429                     pm_mask = IW_POWER_MAX | base_mask;
430                   /* If we have been returned a MAX value, ask for the MIN */
431                   if(flags & IW_POWER_MAX)
432                     pm_mask = IW_POWER_MIN | base_mask;
433                   /* If we have something to ask for... */
434                   if(pm_mask)
435                     get_pm_value(skfd, ifname, &wrq, pm_mask, buffer);
436                 }
437 #endif /* WIRELESS_EXT > 9 */
438             }
439         }
440       printf("\n");
441     }
442   return(0);
443 }
444
445 /************************** TRANSMIT POWER **************************/
446
447 /*------------------------------------------------------------------*/
448 /*
449  * Print the number of available transmit powers for the device
450  */
451 static int
452 print_txpower_info(int          skfd,
453                    char *       ifname,
454                    char *       args[],         /* Command line args */
455                    int          count)          /* Args count */
456 {
457   struct iw_range       range;
458   int                   dbm;
459   int                   mwatt;
460   int                   k;
461
462   /* Avoid "Unused parameter" warning */
463   args = args; count = count;
464
465 #if WIRELESS_EXT > 9
466   /* Extract range info */
467   if(iw_get_range_info(skfd, ifname, &range) < 0)
468       fprintf(stderr, "%-8.8s  no transmit-power information.\n\n",
469                       ifname);
470   else
471     {
472       if((range.num_txpower > 0) && (range.num_txpower < IW_MAX_TXPOWER))
473         {
474           printf("%-8.8s  %d available transmit-powers :\n",
475                  ifname, range.num_txpower);
476           /* Print them all */
477           for(k = 0; k < range.num_txpower; k++)
478             {
479               if(range.txpower_capa & IW_TXPOW_MWATT)
480                 {
481                   dbm = iw_mwatt2dbm(range.txpower[k]);
482                   mwatt = range.txpower[k];
483                 }
484               else
485                 {
486                   dbm = range.txpower[k];
487                   mwatt = iw_dbm2mwatt(range.txpower[k]);
488                 }
489               printf("\t  %d dBm  \t(%d mW)\n", dbm, mwatt);
490             }
491           printf("\n\n");
492         }
493       else
494         printf("%-8.8s  No transmit-powers ? Please update driver...\n\n", ifname);
495     }
496 #endif /* WIRELESS_EXT > 9 */
497   return(0);
498 }
499
500 /*********************** RETRY LIMIT/LIFETIME ***********************/
501
502 #if WIRELESS_EXT > 10
503 /*------------------------------------------------------------------*/
504 /*
505  * Print one retry value
506  */
507 static inline int
508 get_retry_value(int             skfd,
509                 char *          ifname,
510                 struct iwreq *  pwrq,
511                 int             flags,
512                 char *          buffer)
513 {
514   /* Get Another retry value */
515   pwrq->u.retry.flags = flags;
516   if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0)
517     {
518       /* Let's check the value and its type */
519       if(pwrq->u.retry.flags & IW_RETRY_TYPE)
520         {
521           iw_print_retry_value(buffer,
522                                pwrq->u.retry.value, pwrq->u.retry.flags);
523           printf("%s\n                 ", buffer);
524         }
525     }
526   return(pwrq->u.retry.flags);
527 }
528
529 /*------------------------------------------------------------------*/
530 /*
531  * Print Retry info for each device
532  */
533 static int
534 print_retry_info(int            skfd,
535                  char *         ifname,
536                  char *         args[],         /* Command line args */
537                  int            count)          /* Args count */
538 {
539   struct iwreq          wrq;
540   struct iw_range       range;
541   char                  buffer[128];
542
543   /* Avoid "Unused parameter" warning */
544   args = args; count = count;
545
546   /* Extract range info */
547   if(iw_get_range_info(skfd, ifname, &range) < 0)
548       fprintf(stderr, "%-8.8s  no retry limit/lifetime information.\n\n",
549               ifname);
550   else
551     {
552       printf("%-8.8s  ", ifname);
553
554       /* Display min/max limit availables */
555       if(range.retry_flags & IW_RETRY_LIMIT)
556         {
557           int   flags = (range.retry_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
558           /* Display if auto or fixed */
559           if(range.retry_flags & IW_RETRY_MIN)
560             printf("Auto  limit    ; ");
561           else
562             printf("Fixed limit    ; ");
563           /* Print the range */
564           iw_print_retry_value(buffer, range.min_retry, flags | IW_RETRY_MIN);
565           printf("%s\n                           ", buffer);
566           iw_print_retry_value(buffer, range.max_retry, flags | IW_RETRY_MAX);
567           printf("%s\n          ", buffer);
568           
569         }
570       /* Display min/max lifetime availables */
571       if(range.r_time_flags & IW_RETRY_LIFETIME)
572         {
573           int   flags = (range.r_time_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX));
574           /* Display if auto or fixed */
575           if(range.r_time_flags & IW_RETRY_MIN)
576             printf("Auto  lifetime ; ");
577           else
578             printf("Fixed lifetime ; ");
579           /* Print the range */
580           iw_print_retry_value(buffer, range.min_r_time, flags | IW_RETRY_MIN);
581           printf("%s\n                           ", buffer);
582           iw_print_retry_value(buffer, range.max_r_time, flags | IW_RETRY_MAX);
583           printf("%s\n          ", buffer);
584           
585         }
586
587       /* Get current retry settings */
588       wrq.u.retry.flags = 0;
589       if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
590         {
591           int   flags = wrq.u.retry.flags;
592
593           /* Is it disabled ? */
594           if(wrq.u.retry.disabled)
595             printf("Current mode:off\n          ");
596           else
597             {
598               int       retry_mask = 0;
599
600               /* Let's check the mode */
601               printf("Current mode:on\n                 ");
602
603               /* Let's check the value and its type */
604               if(wrq.u.retry.flags & IW_RETRY_TYPE)
605                 {
606                   iw_print_retry_value(buffer,
607                                        wrq.u.retry.value, wrq.u.retry.flags);
608                   printf("%s", buffer);
609                 }
610
611               /* If we have been returned a MIN value, ask for the MAX */
612               if(flags & IW_RETRY_MIN)
613                 retry_mask = IW_RETRY_MAX;
614               /* If we have been returned a MAX value, ask for the MIN */
615               if(flags & IW_RETRY_MAX)
616                 retry_mask = IW_RETRY_MIN;
617               /* If we have something to ask for... */
618               if(retry_mask)
619                 get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
620
621               /* And if we have both a period and a timeout, ask the other */
622               retry_mask = (range.retry_capa & (~(wrq.u.retry.flags) &
623                                           IW_RETRY_TYPE));
624               if(retry_mask)
625                 {
626                   int   base_mask = retry_mask;
627                   flags = get_retry_value(skfd, ifname, &wrq, retry_mask,
628                                           buffer);
629                   retry_mask = 0;
630
631                   /* If we have been returned a MIN value, ask for the MAX */
632                   if(flags & IW_RETRY_MIN)
633                     retry_mask = IW_RETRY_MAX | base_mask;
634                   /* If we have been returned a MAX value, ask for the MIN */
635                   if(flags & IW_RETRY_MAX)
636                     retry_mask = IW_RETRY_MIN | base_mask;
637                   /* If we have something to ask for... */
638                   if(retry_mask)
639                     get_retry_value(skfd, ifname, &wrq, retry_mask, buffer);
640                 }
641             }
642         }
643       printf("\n");
644     }
645   return(0);
646 }
647
648 #endif  /* WIRELESS_EXT > 10 */
649
650 /***************************** SCANNING *****************************/
651 /*
652  * This one behave quite differently from the others
653  */
654 #if WIRELESS_EXT > 13
655 /*------------------------------------------------------------------*/
656 /*
657  * Print one element from the scanning results
658  */
659 static inline int
660 print_scanning_token(struct iw_event *  event,  /* Extracted token */
661                      int                ap_num, /* AP number */
662                      struct iw_range *  iwrange,        /* Range info */
663                      int                has_range)
664 {
665   char          buffer[128];    /* Temporary buffer */
666
667   /* Now, let's decode the event */
668   switch(event->cmd)
669     {
670     case SIOCGIWAP:
671       printf("          Cell %02d - Address: %s\n", ap_num,
672              iw_pr_ether(buffer, event->u.ap_addr.sa_data));
673       ap_num++;
674       break;
675     case SIOCGIWNWID:
676       if(event->u.nwid.disabled)
677         printf("                    NWID:off/any\n");
678       else
679         printf("                    NWID:%X\n", event->u.nwid.value);
680       break;
681     case SIOCGIWFREQ:
682       {
683         float           freq;                   /* Frequency/channel */
684         freq = iw_freq2float(&(event->u.freq));
685         iw_print_freq(buffer, freq);
686         printf("                    %s\n", buffer);
687       }
688       break;
689     case SIOCGIWMODE:
690       printf("                    Mode:%s\n",
691              iw_operation_mode[event->u.mode]);
692       break;
693     case SIOCGIWESSID:
694       {
695         char essid[IW_ESSID_MAX_SIZE+1];
696         if((event->u.essid.pointer) && (event->u.essid.length))
697           memcpy(essid, event->u.essid.pointer, event->u.essid.length);
698         essid[event->u.essid.length] = '\0';
699         if(event->u.essid.flags)
700           {
701             /* Does it have an ESSID index ? */
702             if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)
703               printf("                    ESSID:\"%s\" [%d]\n", essid,
704                      (event->u.essid.flags & IW_ENCODE_INDEX));
705             else
706               printf("                    ESSID:\"%s\"\n", essid);
707           }
708         else
709           printf("                    ESSID:off/any\n");
710       }
711       break;
712     case SIOCGIWENCODE:
713       {
714         unsigned char   key[IW_ENCODING_TOKEN_MAX];
715         if(event->u.data.pointer)
716           memcpy(key, event->u.essid.pointer, event->u.data.length);
717         else
718           event->u.data.flags |= IW_ENCODE_NOKEY;
719         printf("                    Encryption key:");
720         if(event->u.data.flags & IW_ENCODE_DISABLED)
721           printf("off\n");
722         else
723           {
724             /* Display the key */
725             iw_print_key(buffer, key, event->u.data.length,
726                          event->u.data.flags);
727             printf("%s", buffer);
728
729             /* Other info... */
730             if((event->u.data.flags & IW_ENCODE_INDEX) > 1)
731               printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX);
732             if(event->u.data.flags & IW_ENCODE_RESTRICTED)
733               printf("   Encryption mode:restricted");
734             if(event->u.data.flags & IW_ENCODE_OPEN)
735               printf("   Encryption mode:open");
736             printf("\n");
737           }
738       }
739       break;
740     case SIOCGIWRATE:
741       iw_print_bitrate(buffer, event->u.bitrate.value);
742       printf("                    Bit Rate:%s\n", buffer);
743       break;
744     case IWEVQUAL:
745       {
746         event->u.qual.updated = 0x0;    /* Not that reliable, disable */
747         iw_print_stats(buffer, &event->u.qual, iwrange, has_range);
748         printf("                    %s\n", buffer);
749         break;
750       }
751     default:
752       printf("                    (Unknown Wireless Token 0x%04X)\n",
753              event->cmd);
754    }    /* switch(event->cmd) */
755
756   /* May have changed */
757   return(ap_num);
758 }
759
760 /*------------------------------------------------------------------*/
761 /*
762  * Perform a scanning on one device
763  */
764 static int
765 print_scanning_info(int         skfd,
766                     char *      ifname,
767                     char *      args[],         /* Command line args */
768                     int         count)          /* Args count */
769 {
770   struct iwreq          wrq;
771   unsigned char         buffer[IW_SCAN_MAX_DATA];       /* Results */
772   struct timeval        tv;                             /* Select timeout */
773   int                   timeout = 5000000;              /* 5s */
774
775   /* Avoid "Unused parameter" warning */
776   args = args; count = count;
777
778   /* Init timeout value -> 250ms*/
779   tv.tv_sec = 0;
780   tv.tv_usec = 250000;
781
782   /*
783    * Here we should look at the command line args and set the IW_SCAN_ flags
784    * properly
785    */
786   wrq.u.param.flags = IW_SCAN_DEFAULT;
787   wrq.u.param.value = 0;                /* Later */
788
789   /* Initiate Scanning */
790   if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
791     {
792       if(errno != EPERM)
793         {
794           fprintf(stderr, "%-8.8s  Interface doesn't support scanning : %s\n\n",
795                   ifname, strerror(errno));
796           return(-1);
797         }
798       /* If we don't have the permission to initiate the scan, we may
799        * still have permission to read left-over results.
800        * But, don't wait !!! */
801 #if 0
802       /* Not cool, it display for non wireless interfaces... */
803       fprintf(stderr, "%-8.8s  (Could not trigger scanning, just reading left-over results)\n", ifname);
804 #endif
805       tv.tv_usec = 0;
806     }
807   timeout -= tv.tv_usec;
808
809   /* Forever */
810   while(1)
811     {
812       fd_set            rfds;           /* File descriptors for select */
813       int               last_fd;        /* Last fd */
814       int               ret;
815
816       /* Guess what ? We must re-generate rfds each time */
817       FD_ZERO(&rfds);
818       last_fd = -1;
819
820       /* In here, add the rtnetlink fd in the list */
821
822       /* Wait until something happens */
823       ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
824
825       /* Check if there was an error */
826       if(ret < 0)
827         {
828           if(errno == EAGAIN || errno == EINTR)
829             continue;
830           fprintf(stderr, "Unhandled signal - exiting...\n");
831           return(-1);
832         }
833
834       /* Check if there was a timeout */
835       if(ret == 0)
836         {
837           /* Try to read the results */
838           wrq.u.data.pointer = buffer;
839           wrq.u.data.flags = 0;
840           wrq.u.data.length = sizeof(buffer);
841           if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
842             {
843               /* Check if results not available yet */
844               if(errno == EAGAIN)
845                 {
846                   /* Restart timer for only 100ms*/
847                   tv.tv_sec = 0;
848                   tv.tv_usec = 100000;
849                   timeout -= tv.tv_usec;
850                   if(timeout > 0)
851                     continue;   /* Try again later */
852                 }
853
854               /* Bad error */
855               fprintf(stderr, "%-8.8s  Failed to read scan data : %s\n\n",
856                       ifname, strerror(errno));
857               return(-2);
858             }
859           else
860             /* We have the results, go to process them */
861             break;
862         }
863
864       /* In here, check if event and event type
865        * if scan event, read results. All errors bad & no reset timeout */
866     }
867
868   if(wrq.u.data.length)
869     {
870       struct iw_event           iwe;
871       struct stream_descr       stream;
872       int                       ap_num = 1;
873       int                       ret;
874       struct iw_range           range;
875       int                       has_range;
876 #if 0
877       /* Debugging code. In theory useless, because it's debugged ;-) */
878       int       i;
879       printf("Scan result [%02X", buffer[0]);
880       for(i = 1; i < wrq.u.data.length; i++)
881         printf(":%02X", buffer[i]);
882       printf("]\n");
883 #endif
884       has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);
885       printf("%-8.8s  Scan completed :\n", ifname);
886       iw_init_event_stream(&stream, buffer, wrq.u.data.length);
887       do
888         {
889           /* Extract an event and print it */
890           ret = iw_extract_event_stream(&stream, &iwe);
891           if(ret > 0)
892             ap_num = print_scanning_token(&iwe, ap_num, &range, has_range);
893         }
894       while(ret > 0);
895       printf("\n");
896     }
897   else
898     printf("%-8.8s  No scan results\n", ifname);
899
900   return(0);
901 }
902 #endif  /* WIRELESS_EXT > 13 */
903
904 /************************* COMMON UTILITIES *************************/
905 /*
906  * This section was written by Michael Tokarev <mjt@tls.msk.ru>
907  * But modified by me ;-)
908  */
909
910 /* command list */
911 typedef struct iwlist_entry {
912   const char *cmd;
913   iw_enum_handler fn;
914   int min_count;
915   int max_count;
916 } iwlist_cmd;
917
918 static const struct iwlist_entry iwlist_cmds[] = {
919   { "frequency",        print_freq_info,        0, 0 },
920   { "channel",          print_freq_info,        0, 0 },
921   { "ap",               print_ap_info,          0, 0 },
922   { "accesspoints",     print_ap_info,          0, 0 },
923   { "bitrate",          print_bitrate_info,     0, 0 },
924   { "rate",             print_bitrate_info,     0, 0 },
925   { "encryption",       print_keys_info,        0, 0 },
926   { "key",              print_keys_info,        0, 0 },
927   { "power",            print_pm_info,          0, 0 },
928   { "txpower",          print_txpower_info,     0, 0 },
929 #if WIRELESS_EXT > 10
930   { "retry",            print_retry_info,       0, 0 },
931 #endif
932 #if WIRELESS_EXT > 13
933   { "scanning",         print_scanning_info,    0, 5 },
934 #endif
935   { NULL, NULL, 0, 0 },
936 };
937
938 /*------------------------------------------------------------------*/
939 /*
940  * Find the most appropriate command matching the command line
941  */
942 static inline const iwlist_cmd *
943 find_command(const char *       cmd)
944 {
945   const iwlist_cmd *    found = NULL;
946   int                   ambig = 0;
947   unsigned int          len = strlen(cmd);
948   int                   i;
949
950   /* Go through all commands */
951   for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
952     {
953       /* No match -> next one */
954       if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
955         continue;
956
957       /* Exact match -> perfect */
958       if(len == strlen(iwlist_cmds[i].cmd))
959         return &iwlist_cmds[i];
960
961       /* Partial match */
962       if(found == NULL)
963         /* First time */
964         found = &iwlist_cmds[i];
965       else
966         /* Another time */
967         if (iwlist_cmds[i].fn != found->fn)
968           ambig = 1;
969     }
970
971   if(found == NULL)
972     {
973       fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
974       return NULL;
975     }
976
977   if(ambig)
978     {
979       fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
980       return NULL;
981     }
982
983   return found;
984 }
985
986 /*------------------------------------------------------------------*/
987 /*
988  * Display help
989  */
990 static void iw_usage(int status)
991 {
992   FILE* f = status ? stderr : stdout;
993   int i;
994
995   fprintf(f,   "Usage: iwlist [interface] %s\n", iwlist_cmds[0].cmd);
996   for(i = 1; iwlist_cmds[i].cmd != NULL; ++i)
997     fprintf(f, "              [interface] %s\n", iwlist_cmds[i].cmd);
998   exit(status);
999 }
1000
1001 /******************************* MAIN ********************************/
1002
1003 /*------------------------------------------------------------------*/
1004 /*
1005  * The main !
1006  */
1007 int
1008 main(int        argc,
1009      char **    argv)
1010 {
1011   int skfd;                     /* generic raw socket desc.     */
1012   char *dev;                    /* device name                  */
1013   char *cmd;                    /* command                      */
1014   char **args;                  /* Command arguments */
1015   int count;                    /* Number of arguments */
1016   const iwlist_cmd *iwcmd;
1017
1018   if(argc == 1 || argc > 3)
1019     iw_usage(1);
1020
1021   if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1022     iw_usage(0);
1023
1024   if (argc == 2)
1025     {
1026       cmd = argv[1];
1027       dev = NULL;
1028       args = NULL;
1029       count = 0;
1030     }
1031   else
1032     {
1033       cmd = argv[2];
1034       dev = argv[1];
1035       args = argv + 3;
1036       count = argc - 3;
1037     }
1038
1039   /* find a command */
1040   iwcmd = find_command(cmd);
1041   if(iwcmd == NULL)
1042     return 1;
1043
1044   /* Check arg numbers */
1045   if(count < iwcmd->min_count)
1046     {
1047       fprintf(stderr, "iwlist: command `%s' needs more arguments\n", cmd);
1048       return 1;
1049     }
1050   if(count > iwcmd->max_count)
1051     {
1052       fprintf(stderr, "iwlist: command `%s' needs fewer arguments\n", cmd);
1053       return 1;
1054     }
1055
1056   /* Create a channel to the NET kernel. */
1057   if((skfd = iw_sockets_open()) < 0)
1058     {
1059       perror("socket");
1060       return -1;
1061     }
1062
1063   /* do the actual work */
1064   if (dev)
1065     (*iwcmd->fn)(skfd, dev, args, count);
1066   else
1067     iw_enum_devices(skfd, iwcmd->fn, args, count);
1068
1069   /* Close the socket. */
1070   close(skfd);
1071
1072   return 0;
1073 }