OSDN Git Service

b78882f2087555b40160e8870c50585379e8943a
[android-x86/external-wireless-tools.git] / wireless_tools / iwlib.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPLB 97->99 - HPL 99->04
5  *
6  * Common subroutines to all the wireless tools...
7  *
8  * This file is released under the GPL license.
9  *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
10  */
11
12 /***************************** INCLUDES *****************************/
13
14 #include "iwlib.h"              /* Header */
15
16 /************************ CONSTANTS & MACROS ************************/
17
18 /*
19  * Constants fof WE-9->15
20  */
21 #define IW15_MAX_FREQUENCIES    16
22 #define IW15_MAX_BITRATES       8
23 #define IW15_MAX_TXPOWER        8
24 #define IW15_MAX_ENCODING_SIZES 8
25 #define IW15_MAX_SPY            8
26 #define IW15_MAX_AP             8
27
28 /****************************** TYPES ******************************/
29
30 /*
31  *      Struct iw_range up to WE-15
32  */
33 struct  iw15_range
34 {
35         __u32           throughput;
36         __u32           min_nwid;
37         __u32           max_nwid;
38         __u16           num_channels;
39         __u8            num_frequency;
40         struct iw_freq  freq[IW15_MAX_FREQUENCIES];
41         __s32           sensitivity;
42         struct iw_quality       max_qual;
43         __u8            num_bitrates;
44         __s32           bitrate[IW15_MAX_BITRATES];
45         __s32           min_rts;
46         __s32           max_rts;
47         __s32           min_frag;
48         __s32           max_frag;
49         __s32           min_pmp;
50         __s32           max_pmp;
51         __s32           min_pmt;
52         __s32           max_pmt;
53         __u16           pmp_flags;
54         __u16           pmt_flags;
55         __u16           pm_capa;
56         __u16           encoding_size[IW15_MAX_ENCODING_SIZES];
57         __u8            num_encoding_sizes;
58         __u8            max_encoding_tokens;
59         __u16           txpower_capa;
60         __u8            num_txpower;
61         __s32           txpower[IW15_MAX_TXPOWER];
62         __u8            we_version_compiled;
63         __u8            we_version_source;
64         __u16           retry_capa;
65         __u16           retry_flags;
66         __u16           r_time_flags;
67         __s32           min_retry;
68         __s32           max_retry;
69         __s32           min_r_time;
70         __s32           max_r_time;
71         struct iw_quality       avg_qual;
72 };
73
74 /*
75  * Union for all the versions of iwrange.
76  * Fortunately, I mostly only add fields at the end, and big-bang
77  * reorganisations are few.
78  */
79 union   iw_range_raw
80 {
81         struct iw15_range       range15;        /* WE 9->15 */
82         struct iw_range         range;          /* WE 16->current */
83 };
84
85 /*
86  * Offsets in iw_range struct
87  */
88 #define iwr15_off(f)    ( ((char *) &(((struct iw15_range *) NULL)->f)) - \
89                           (char *) NULL)
90 #define iwr_off(f)      ( ((char *) &(((struct iw_range *) NULL)->f)) - \
91                           (char *) NULL)
92
93 /**************************** VARIABLES ****************************/
94
95 /* Modes as human readable strings */
96 const char * const iw_operation_mode[] = { "Auto",
97                                         "Ad-Hoc",
98                                         "Managed",
99                                         "Master",
100                                         "Repeater",
101                                         "Secondary",
102                                         "Monitor" };
103
104 /* Disable runtime version warning in iw_get_range_info() */
105 int     iw_ignore_version = 0;
106
107 /************************ SOCKET SUBROUTINES *************************/
108
109 /*------------------------------------------------------------------*/
110 /*
111  * Open a socket.
112  * Depending on the protocol present, open the right socket. The socket
113  * will allow us to talk to the driver.
114  */
115 int
116 iw_sockets_open(void)
117 {
118   static const int families[] = {
119     AF_INET, AF_IPX, AF_AX25, AF_APPLETALK
120   };
121   unsigned int  i;
122   int           sock;
123
124   /*
125    * Now pick any (exisiting) useful socket family for generic queries
126    * Note : don't open all the socket, only returns when one matches,
127    * all protocols might not be valid.
128    * Workaround by Jim Kaba <jkaba@sarnoff.com>
129    * Note : in 99% of the case, we will just open the inet_sock.
130    * The remaining 1% case are not fully correct...
131    */
132
133   /* Try all families we support */
134   for(i = 0; i < sizeof(families)/sizeof(int); ++i)
135     {
136       /* Try to open the socket, if success returns it */
137       sock = socket(families[i], SOCK_DGRAM, 0);
138       if(sock >= 0)
139         return sock;
140   }
141
142   return -1;
143 }
144
145 /*------------------------------------------------------------------*/
146 /*
147  * Extract the interface name out of /proc/net/wireless or /proc/net/dev.
148  */
149 static inline char *
150 iw_get_ifname(char *    name,   /* Where to store the name */
151               int       nsize,  /* Size of name buffer */
152               char *    buf)    /* Current position in buffer */
153 {
154   char *        end;
155
156   /* Skip leading spaces */
157   while(isspace(*buf))
158     buf++;
159
160 #ifndef IW_RESTRIC_ENUM
161   /* Get name up to the last ':'. Aliases may contain ':' in them,
162    * but the last one should be the separator */
163   end = strrchr(buf, ':');
164 #else
165   /* Get name up to ": "
166    * Note : we compare to ": " to make sure to process aliased interfaces
167    * properly. Doesn't work on /proc/net/dev, because it doesn't guarantee
168    * a ' ' after the ':'*/
169   end = strstr(buf, ": ");
170 #endif
171
172   /* Not found ??? To big ??? */
173   if((end == NULL) || (((end - buf) + 1) > nsize))
174     return(NULL);
175
176   /* Copy */
177   memcpy(name, buf, (end - buf));
178   name[end - buf] = '\0';
179
180   return(end + 2);
181 }
182
183 /*------------------------------------------------------------------*/
184 /*
185  * Enumerate devices and call specified routine
186  * The new way just use /proc/net/wireless, so get all wireless interfaces,
187  * whether configured or not. This is the default if available.
188  * The old way use SIOCGIFCONF, so get only configured interfaces (wireless
189  * or not).
190  */
191 void
192 iw_enum_devices(int             skfd,
193                 iw_enum_handler fn,
194                 char *          args[],
195                 int             count)
196 {
197   char          buff[1024];
198   FILE *        fh;
199   struct ifconf ifc;
200   struct ifreq *ifr;
201   int           i;
202
203 #ifndef IW_RESTRIC_ENUM
204   /* Check if /proc/net/wireless is available */
205   fh = fopen(PROC_NET_DEV, "r");
206 #else
207   /* Check if /proc/net/wireless is available */
208   fh = fopen(PROC_NET_WIRELESS, "r");
209 #endif
210
211   if(fh != NULL)
212     {
213       /* Success : use data from /proc/net/wireless */
214
215       /* Eat 2 lines of header */
216       fgets(buff, sizeof(buff), fh);
217       fgets(buff, sizeof(buff), fh);
218
219       /* Read each device line */
220       while(fgets(buff, sizeof(buff), fh))
221         {
222           char  name[IFNAMSIZ + 1];
223           char *s;
224
225           /* Extract interface name */
226           s = iw_get_ifname(name, sizeof(name), buff);
227
228           if(!s)
229             /* Failed to parse, complain and continue */
230 #ifndef IW_RESTRIC_ENUM
231             fprintf(stderr, "Cannot parse " PROC_NET_DEV "\n");
232 #else
233             fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
234 #endif
235           else
236             /* Got it, print info about this interface */
237             (*fn)(skfd, name, args, count);
238         }
239
240       fclose(fh);
241     }
242   else
243     {
244       /* Get list of configured devices using "traditional" way */
245       ifc.ifc_len = sizeof(buff);
246       ifc.ifc_buf = buff;
247       if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
248         {
249           fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
250           return;
251         }
252       ifr = ifc.ifc_req;
253
254       /* Print them */
255       for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
256         (*fn)(skfd, ifr->ifr_name, args, count);
257     }
258 }
259
260 /*********************** WIRELESS SUBROUTINES ************************/
261
262 /*------------------------------------------------------------------*/
263 /*
264  * Extract WE version number from /proc/net/wireless
265  * In most cases, you really want to get version information from
266  * the range info (range->we_version_compiled), see below...
267  *
268  * If we have WE-16 and later, the WE version is available at the
269  * end of the header line of the file.
270  * For version prior to that, we can only detect the change from
271  * v11 to v12, so we do an approximate job. Fortunately, v12 to v15
272  * are highly binary compatible (on the struct level).
273  */
274 int
275 iw_get_kernel_we_version(void)
276 {
277   char          buff[1024];
278   FILE *        fh;
279   char *        p;
280   int           v;
281
282   /* Check if /proc/net/wireless is available */
283   fh = fopen(PROC_NET_WIRELESS, "r");
284
285   if(fh == NULL)
286     {
287       fprintf(stderr, "Cannot read " PROC_NET_WIRELESS "\n");
288       return(-1);
289     }
290
291   /* Read the first line of buffer */
292   fgets(buff, sizeof(buff), fh);
293
294   if(strstr(buff, "| WE") == NULL)
295     {
296       /* Prior to WE16, so explicit version not present */
297
298       /* Black magic */
299       if(strstr(buff, "| Missed") == NULL)
300         v = 11;
301       else
302         v = 15;
303       fclose(fh);
304       return(v);
305     }
306
307   /* Read the second line of buffer */
308   fgets(buff, sizeof(buff), fh);
309
310   /* Get to the last separator, to get the version */
311   p = strrchr(buff, '|');
312   if((p == NULL) || (sscanf(p + 1, "%d", &v) != 1))
313     {
314       fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
315       fclose(fh);
316       return(-1);
317     }
318
319   fclose(fh);
320   return(v);
321 }
322
323 /*------------------------------------------------------------------*/
324 /*
325  * Print the WE versions of the interface.
326  */
327 static int
328 print_iface_version_info(int    skfd,
329                          char * ifname,
330                          char * args[],         /* Command line args */
331                          int    count)          /* Args count */
332 {
333   struct iwreq          wrq;
334   char                  buffer[sizeof(iwrange) * 2];    /* Large enough */
335   struct iw_range *     range;
336
337   /* Avoid "Unused parameter" warning */
338   args = args; count = count;
339
340   /* If no wireless name : no wireless extensions.
341    * This enable us to treat the SIOCGIWRANGE failure below properly. */
342   if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
343     return(-1);
344
345   /* Cleanup */
346   memset(buffer, 0, sizeof(buffer));
347
348   wrq.u.data.pointer = (caddr_t) buffer;
349   wrq.u.data.length = sizeof(buffer);
350   wrq.u.data.flags = 0;
351   if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
352     {
353       /* Interface support WE (see above), but not IWRANGE */
354       fprintf(stderr, "%-8.16s  Driver has no Wireless Extension version information.\n\n", ifname);
355       return(0);
356     }
357
358   /* Copy stuff at the right place, ignore extra */
359   range = (struct iw_range *) buffer;
360
361   /* For new versions, we can check the version directly, for old versions
362    * we use magic. 300 bytes is a also magic number, don't touch... */
363   if(wrq.u.data.length >= 300)
364     {
365       /* Version is always at the same offset, so it's ok */
366       printf("%-8.16s  Recommend Wireless Extension v%d or later,\n",
367              ifname, range->we_version_source);
368       printf("          Currently compiled with Wireless Extension v%d.\n\n",
369              range->we_version_compiled);
370     }
371   else
372     {
373       fprintf(stderr, "%-8.16s  Wireless Extension version too old.\n\n",
374                       ifname);
375     }
376
377
378   return(0);
379 }
380
381 /*------------------------------------------------------------------*/
382 /*
383  * Print the WE versions of the tools.
384  */
385 int
386 iw_print_version_info(const char *      toolname)
387 {
388   int           skfd;                   /* generic raw socket desc.     */
389   int           we_kernel_version;
390
391   /* Create a channel to the NET kernel. */
392   if((skfd = iw_sockets_open()) < 0)
393     {
394       perror("socket");
395       return -1;
396     }
397
398   /* Information about the tools themselves */
399   if(toolname != NULL)
400     printf("%-8.16s  Wireless-Tools version %d\n", toolname, WT_VERSION);
401   printf("          Compatible with Wireless Extension v11 to v%d.\n\n",
402          WE_VERSION);
403
404   /* Get version from kernel */
405   we_kernel_version = iw_get_kernel_we_version();
406   /* Only version >= 16 can be verified, other are guessed */
407   if(we_kernel_version > 15)
408     printf("Kernel    Currently compiled with Wireless Extension v%d.\n\n",
409            we_kernel_version);
410
411   /* Version for each device */
412   iw_enum_devices(skfd, &print_iface_version_info, NULL, 0);
413
414   iw_sockets_close(skfd);
415
416   return 0;
417 }
418
419 /*------------------------------------------------------------------*/
420 /*
421  * Get the range information out of the driver
422  */
423 int
424 iw_get_range_info(int           skfd,
425                   const char *  ifname,
426                   iwrange *     range)
427 {
428   struct iwreq          wrq;
429   char                  buffer[sizeof(iwrange) * 2];    /* Large enough */
430   union iw_range_raw *  range_raw;
431
432   /* Cleanup */
433   bzero(buffer, sizeof(buffer));
434
435   wrq.u.data.pointer = (caddr_t) buffer;
436   wrq.u.data.length = sizeof(buffer);
437   wrq.u.data.flags = 0;
438   if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
439     return(-1);
440
441   /* Point to the buffer */
442   range_raw = (union iw_range_raw *) buffer;
443
444   /* For new versions, we can check the version directly, for old versions
445    * we use magic. 300 bytes is a also magic number, don't touch... */
446   if(wrq.u.data.length < 300)
447     {
448       /* That's v10 or earlier. Ouch ! Let's make a guess...*/
449       range_raw->range.we_version_compiled = 9;
450     }
451
452   /* Check how it needs to be processed */
453   if(range_raw->range.we_version_compiled > 15)
454     {
455       /* This is our native format, that's easy... */
456       /* Copy stuff at the right place, ignore extra */
457       memcpy((char *) range, buffer, sizeof(iwrange));
458     }
459   else
460     {
461       /* Zero unknown fields */
462       bzero((char *) range, sizeof(struct iw_range));
463
464       /* Initial part unmoved */
465       memcpy((char *) range,
466              buffer,
467              iwr15_off(num_channels));
468       /* Frequencies pushed futher down towards the end */
469       memcpy((char *) range + iwr_off(num_channels),
470              buffer + iwr15_off(num_channels),
471              iwr15_off(sensitivity) - iwr15_off(num_channels));
472       /* This one moved up */
473       memcpy((char *) range + iwr_off(sensitivity),
474              buffer + iwr15_off(sensitivity),
475              iwr15_off(num_bitrates) - iwr15_off(sensitivity));
476       /* This one goes after avg_qual */
477       memcpy((char *) range + iwr_off(num_bitrates),
478              buffer + iwr15_off(num_bitrates),
479              iwr15_off(min_rts) - iwr15_off(num_bitrates));
480       /* Number of bitrates has changed, put it after */
481       memcpy((char *) range + iwr_off(min_rts),
482              buffer + iwr15_off(min_rts),
483              iwr15_off(txpower_capa) - iwr15_off(min_rts));
484       /* Added encoding_login_index, put it after */
485       memcpy((char *) range + iwr_off(txpower_capa),
486              buffer + iwr15_off(txpower_capa),
487              iwr15_off(txpower) - iwr15_off(txpower_capa));
488       /* Hum... That's an unexpected glitch. Bummer. */
489       memcpy((char *) range + iwr_off(txpower),
490              buffer + iwr15_off(txpower),
491              iwr15_off(avg_qual) - iwr15_off(txpower));
492       /* Avg qual moved up next to max_qual */
493       memcpy((char *) range + iwr_off(avg_qual),
494              buffer + iwr15_off(avg_qual),
495              sizeof(struct iw_quality));
496     }
497
498   /* We are now checking much less than we used to do, because we can
499    * accomodate more WE version. But, there are still cases where things
500    * will break... */
501   if(!iw_ignore_version)
502     {
503       /* We don't like very old version (unfortunately kernel 2.2.X) */
504       if(range->we_version_compiled <= 10)
505         {
506           fprintf(stderr, "Warning: Driver for device %s has been compiled with an ancient version\n", ifname);
507           fprintf(stderr, "of Wireless Extension, while this program support version 11 and later.\n");
508           fprintf(stderr, "Some things may be broken...\n\n");
509         }
510
511       /* We don't like future versions of WE, because we can't cope with
512        * the unknown */
513       if(range->we_version_compiled > WE_VERSION)
514         {
515           fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled);
516           fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_VERSION);
517           fprintf(stderr, "Some things may be broken...\n\n");
518         }
519
520       /* Driver version verification */
521       if((range->we_version_compiled > 10) &&
522          (range->we_version_compiled < range->we_version_source))
523         {
524           fprintf(stderr, "Warning: Driver for device %s recommend version %d of Wireless Extension,\n", ifname, range->we_version_source);
525           fprintf(stderr, "but has been compiled with version %d, therefore some driver features\n", range->we_version_compiled);
526           fprintf(stderr, "may not be available...\n\n");
527         }
528       /* Note : we are only trying to catch compile difference, not source.
529        * If the driver source has not been updated to the latest, it doesn't
530        * matter because the new fields are set to zero */
531     }
532
533   /* Don't complain twice.
534    * In theory, the test apply to each individual driver, but usually
535    * all drivers are compiled from the same kernel. */
536   iw_ignore_version = 1;
537
538   return(0);
539 }
540
541 /*------------------------------------------------------------------*/
542 /*
543  * Get information about what private ioctls are supported by the driver
544  *
545  * Note : there is one danger using this function. If it return 0, you
546  * still need to free() the buffer. Beware.
547  */
548 int
549 iw_get_priv_info(int            skfd,
550                  const char *   ifname,
551                  iwprivargs **  ppriv)
552 {
553   struct iwreq          wrq;
554   iwprivargs *          priv = NULL;    /* Not allocated yet */
555   int                   maxpriv = 16;   /* Minimum for compatibility WE<13 */
556   iwprivargs *          newpriv;
557
558   /* Some driver may return a very large number of ioctls. Some
559    * others a very small number. We now use a dynamic allocation
560    * of the array to satisfy everybody. Of course, as we don't know
561    * in advance the size of the array, we try various increasing
562    * sizes. Jean II */
563   do
564     {
565       /* (Re)allocate the buffer */
566       newpriv = realloc(priv, maxpriv * sizeof(priv[0]));
567       if(newpriv == NULL)
568         {
569           fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
570           break;
571         }
572       priv = newpriv;
573
574       /* Ask the driver if it's large enough */
575       wrq.u.data.pointer = (caddr_t) priv;
576       wrq.u.data.length = maxpriv;
577       wrq.u.data.flags = 0;
578       if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) >= 0)
579         {
580           /* Success. Pass the buffer by pointer */
581           *ppriv = priv;
582           /* Return the number of ioctls */
583           return(wrq.u.data.length);
584         }
585
586       /* Only E2BIG means the buffer was too small, abort on other errors */
587       if(errno != E2BIG)
588         {
589           /* Most likely "not supported". Don't barf. */
590           break;
591         }
592
593       /* Failed. We probably need a bigger buffer. Check if the kernel
594        * gave us any hints. */
595       if(wrq.u.data.length > maxpriv)
596         maxpriv = wrq.u.data.length;
597       else
598         maxpriv *= 2;
599     }
600   while(maxpriv < 1000);
601
602   /* Cleanup */
603   if(priv)
604     free(priv);
605   *ppriv = NULL;
606
607   return(-1);
608 }
609
610 /*------------------------------------------------------------------*/
611 /*
612  * Get essential wireless config from the device driver
613  * We will call all the classical wireless ioctl on the driver through
614  * the socket to know what is supported and to get the settings...
615  * Note : compare to the version in iwconfig, we extract only
616  * what's *really* needed to configure a device...
617  */
618 int
619 iw_get_basic_config(int                 skfd,
620                     const char *        ifname,
621                     wireless_config *   info)
622 {
623   struct iwreq          wrq;
624
625   memset((char *) info, 0, sizeof(struct wireless_config));
626
627   /* Get wireless name */
628   if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
629     /* If no wireless name : no wireless extensions */
630     return(-1);
631   else
632     {
633       strncpy(info->name, wrq.u.name, IFNAMSIZ);
634       info->name[IFNAMSIZ] = '\0';
635     }
636
637   /* Get network ID */
638   if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0)
639     {
640       info->has_nwid = 1;
641       memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
642     }
643
644   /* Get frequency / channel */
645   if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
646     {
647       info->has_freq = 1;
648       info->freq = iw_freq2float(&(wrq.u.freq));
649       info->freq_flags = wrq.u.freq.flags;
650     }
651
652   /* Get encryption information */
653   wrq.u.data.pointer = (caddr_t) info->key;
654   wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
655   wrq.u.data.flags = 0;
656   if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
657     {
658       info->has_key = 1;
659       info->key_size = wrq.u.data.length;
660       info->key_flags = wrq.u.data.flags;
661     }
662
663   /* Get ESSID */
664   wrq.u.essid.pointer = (caddr_t) info->essid;
665   wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
666   wrq.u.essid.flags = 0;
667   if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0)
668     {
669       info->has_essid = 1;
670       info->essid_on = wrq.u.data.flags;
671     }
672
673   /* Get operation mode */
674   if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
675     {
676       info->mode = wrq.u.mode;
677       if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
678         info->has_mode = 1;
679     }
680
681   return(0);
682 }
683
684 /*------------------------------------------------------------------*/
685 /*
686  * Set essential wireless config in the device driver
687  * We will call all the classical wireless ioctl on the driver through
688  * the socket to know what is supported and to set the settings...
689  * We support only the restricted set as above...
690  */
691 int
692 iw_set_basic_config(int                 skfd,
693                     const char *        ifname,
694                     wireless_config *   info)
695 {
696   struct iwreq          wrq;
697   int                   ret = 0;
698
699   /* Get wireless name (check if interface is valid) */
700   if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
701     /* If no wireless name : no wireless extensions */
702     return(-2);
703
704   /* Set the current mode of operation
705    * Mode need to be first : some settings apply only in a specific mode
706    * (such as frequency).
707    */
708   if(info->has_mode)
709     {
710       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
711       wrq.u.mode = info->mode;
712
713       if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
714         {
715           fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
716           ret = -1;
717         }
718     }
719
720   /* Set frequency / channel */
721   if(info->has_freq)
722     {
723       iw_float2freq(info->freq, &(wrq.u.freq));
724
725       if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
726         {
727           fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
728           ret = -1;
729         }
730     }
731
732   /* Set encryption information */
733   if(info->has_key)
734     {
735       int               flags = info->key_flags;
736
737       /* Check if there is a key index */
738       if((flags & IW_ENCODE_INDEX) > 0)
739         {
740           /* Set the index */
741           wrq.u.data.pointer = (caddr_t) NULL;
742           wrq.u.data.flags = (flags & (IW_ENCODE_INDEX)) | IW_ENCODE_NOKEY;
743           wrq.u.data.length = 0;
744
745           if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
746             {
747               fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
748                       errno, strerror(errno));
749               ret = -1;
750             }
751         }
752
753       /* Mask out index to minimise probability of reject when setting key */
754       flags = flags & (~IW_ENCODE_INDEX);
755
756       /* Set the key itself (set current key in this case) */
757       wrq.u.data.pointer = (caddr_t) info->key;
758       wrq.u.data.length = info->key_size;
759       wrq.u.data.flags = flags;
760
761       /* Compatibility with WE<13 */
762       if(flags & IW_ENCODE_NOKEY)
763         wrq.u.data.pointer = NULL;
764
765       if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
766         {
767           fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
768                   errno, strerror(errno));
769           ret = -1;
770         }
771     }
772
773   /* Set Network ID, if available (this is for non-802.11 cards) */
774   if(info->has_nwid)
775     {
776       memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam));
777       wrq.u.nwid.fixed = 1;     /* Hum... When in Rome... */
778
779       if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
780         {
781           fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
782           ret = -1;
783         }
784     }
785
786   /* Set ESSID (extended network), if available.
787    * ESSID need to be last : most device re-perform the scanning/discovery
788    * when this is set, and things like encryption keys are better be
789    * defined if we want to discover the right set of APs/nodes.
790    */
791   if(info->has_essid)
792     {
793       wrq.u.essid.pointer = (caddr_t) info->essid;
794       wrq.u.essid.length = strlen(info->essid) + 1;
795       wrq.u.data.flags = info->essid_on;
796
797       if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
798         {
799           fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
800           ret = -1;
801         }
802     }
803
804   return(ret);
805 }
806
807 /*********************** PROTOCOL SUBROUTINES ***********************/
808 /*
809  * Fun stuff with protocol identifiers (SIOCGIWNAME).
810  * We assume that drivers are returning sensible values in there,
811  * which is not always the case :-(
812  */
813
814 /*------------------------------------------------------------------*/
815 /*
816  * Compare protocol identifiers.
817  * We don't want to know if the two protocols are the exactly same,
818  * but if they interoperate at some level, and also if they accept the
819  * same type of config (ESSID vs NWID, freq...).
820  * This is supposed to work around the alphabet soup.
821  * Return 1 if protocols are compatible, 0 otherwise
822  */
823 int
824 iw_protocol_compare(const char *        protocol1,
825                     const char *        protocol2)
826 {
827   const char *  dot11 = "IEEE 802.11";
828   const char *  dot11_ds = "Dbg";
829   const char *  dot11_5g = "a";
830
831   /* If the strings are the same -> easy */
832   if(!strncmp(protocol1, protocol2, IFNAMSIZ))
833     return(1);
834
835   /* Are we dealing with one of the 802.11 variant ? */
836   if( (!strncmp(protocol1, dot11, strlen(dot11))) &&
837       (!strncmp(protocol2, dot11, strlen(dot11))) )
838     {
839       const char *      sub1 = protocol1 + strlen(dot11);
840       const char *      sub2 = protocol2 + strlen(dot11);
841       unsigned int      i;
842       int               isds1 = 0;
843       int               isds2 = 0;
844       int               is5g1 = 0;
845       int               is5g2 = 0;
846
847       /* Check if we find the magic letters telling it's DS compatible */
848       for(i = 0; i < strlen(dot11_ds); i++)
849         {
850           if(strchr(sub1, dot11_ds[i]) != NULL)
851             isds1 = 1;
852           if(strchr(sub2, dot11_ds[i]) != NULL)
853             isds2 = 1;
854         }
855       if(isds1 && isds2)
856         return(1);
857
858       /* Check if we find the magic letters telling it's 5GHz compatible */
859       for(i = 0; i < strlen(dot11_5g); i++)
860         {
861           if(strchr(sub1, dot11_5g[i]) != NULL)
862             is5g1 = 1;
863           if(strchr(sub2, dot11_5g[i]) != NULL)
864             is5g2 = 1;
865         }
866       if(is5g1 && is5g2)
867         return(1);
868     }
869   /* Not compatible */
870   return(0);
871 }
872
873 /********************** FREQUENCY SUBROUTINES ***********************/
874 /*
875  * Note : the two functions below are the cause of troubles on
876  * various embeeded platforms, as they are the reason we require
877  * libm (math library).
878  * In this case, please use enable BUILD_NOLIBM in the makefile
879  *
880  * FIXME : check negative mantissa and exponent
881  */
882
883 /*------------------------------------------------------------------*/
884 /*
885  * Convert a floating point the our internal representation of
886  * frequencies.
887  * The kernel doesn't want to hear about floating point, so we use
888  * this custom format instead.
889  */
890 void
891 iw_float2freq(double    in,
892               iwfreq *  out)
893 {
894 #ifdef WE_NOLIBM
895   /* Version without libm : slower */
896   out->e = 0;
897   while(in > 1e9)
898     {
899       in /= 10;
900       out->e++;
901     }
902   out->m = (long) in;
903 #else   /* WE_NOLIBM */
904   /* Version with libm : faster */
905   out->e = (short) (floor(log10(in)));
906   if(out->e > 8)
907     {
908       out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100;
909       out->e -= 8;
910     }
911   else
912     {
913       out->m = (long) in;
914       out->e = 0;
915     }
916 #endif  /* WE_NOLIBM */
917 }
918
919 /*------------------------------------------------------------------*/
920 /*
921  * Convert our internal representation of frequencies to a floating point.
922  */
923 double
924 iw_freq2float(const iwfreq *    in)
925 {
926 #ifdef WE_NOLIBM
927   /* Version without libm : slower */
928   int           i;
929   double        res = (double) in->m;
930   for(i = 0; i < in->e; i++)
931     res *= 10;
932   return(res);
933 #else   /* WE_NOLIBM */
934   /* Version with libm : faster */
935   return ((double) in->m) * pow(10,in->e);
936 #endif  /* WE_NOLIBM */
937 }
938
939 /*------------------------------------------------------------------*/
940 /*
941  * Output a frequency with proper scaling
942  */
943 void
944 iw_print_freq_value(char *      buffer,
945                     int         buflen,
946                     double      freq)
947 {
948   if(freq < KILO)
949     snprintf(buffer, buflen, "%g", freq);
950   else
951     {
952       char      scale;
953       int       divisor;
954
955       if(freq >= GIGA)
956         {
957           scale = 'G';
958           divisor = GIGA;
959         }
960       else
961         {
962           if(freq >= MEGA)
963             {
964               scale = 'M';
965               divisor = MEGA;
966             }
967           else
968             {
969               scale = 'k';
970               divisor = KILO;
971             }
972         }
973       snprintf(buffer, buflen, "%g %cHz", freq / divisor, scale);
974     }
975 }
976
977 /*------------------------------------------------------------------*/
978 /*
979  * Output a frequency with proper scaling
980  */
981 void
982 iw_print_freq(char *    buffer,
983               int       buflen,
984               double    freq,
985               int       channel,
986               int       freq_flags)
987 {
988   char  sep = ((freq_flags & IW_FREQ_FIXED) ? '=' : ':');
989   char  vbuf[16];
990
991   /* Print the frequency/channel value */
992   iw_print_freq_value(vbuf, sizeof(vbuf), freq);
993
994   /* Check if channel only */
995   if(freq < KILO)
996     snprintf(buffer, buflen, "Channel%c%s", sep, vbuf);
997   else
998     {
999       /* Frequency. Check if we have a channel as well */
1000       if(channel >= 0)
1001         snprintf(buffer, buflen, "Frequency%c%s (Channel %d)",
1002                  sep, vbuf, channel);
1003       else
1004         snprintf(buffer, buflen, "Frequency%c%s", sep, vbuf);
1005     }
1006 }
1007
1008 /*------------------------------------------------------------------*/
1009 /*
1010  * Convert a frequency to a channel (negative -> error)
1011  */
1012 int
1013 iw_freq_to_channel(double                       freq,
1014                    const struct iw_range *      range)
1015 {
1016   double        ref_freq;
1017   int           k;
1018
1019   /* Check if it's a frequency or not already a channel */
1020   if(freq < KILO)
1021     return(-1);
1022
1023   /* We compare the frequencies as double to ignore differences
1024    * in encoding. Slower, but safer... */
1025   for(k = 0; k < range->num_frequency; k++)
1026     {
1027       ref_freq = iw_freq2float(&(range->freq[k]));
1028       if(freq == ref_freq)
1029         return(range->freq[k].i);
1030     }
1031   /* Not found */
1032   return(-2);
1033 }
1034
1035 /*------------------------------------------------------------------*/
1036 /*
1037  * Convert a channel to a frequency (negative -> error)
1038  * Return the channel on success
1039  */
1040 int
1041 iw_channel_to_freq(int                          channel,
1042                    double *                     pfreq,
1043                    const struct iw_range *      range)
1044 {
1045   int           has_freq = 0;
1046   int           k;
1047
1048   /* Check if the driver support only channels or if it has frequencies */
1049   for(k = 0; k < range->num_frequency; k++)
1050     {
1051       if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO))
1052         has_freq = 1;
1053     }
1054   if(!has_freq)
1055     return(-1);
1056
1057   /* Find the correct frequency in the list */
1058   for(k = 0; k < range->num_frequency; k++)
1059     {
1060       if(range->freq[k].i == channel)
1061         {
1062           *pfreq = iw_freq2float(&(range->freq[k]));
1063           return(channel);
1064         }
1065     }
1066   /* Not found */
1067   return(-2);
1068 }
1069
1070 /*********************** BITRATE SUBROUTINES ***********************/
1071
1072 /*------------------------------------------------------------------*/
1073 /*
1074  * Output a bitrate with proper scaling
1075  */
1076 void
1077 iw_print_bitrate(char * buffer,
1078                  int    buflen,
1079                  int    bitrate)
1080 {
1081   double        rate = bitrate;
1082   char          scale;
1083   int           divisor;
1084
1085   if(rate >= GIGA)
1086     {
1087       scale = 'G';
1088       divisor = GIGA;
1089     }
1090   else
1091     {
1092       if(rate >= MEGA)
1093         {
1094           scale = 'M';
1095           divisor = MEGA;
1096         }
1097       else
1098         {
1099           scale = 'k';
1100           divisor = KILO;
1101         }
1102     }
1103   snprintf(buffer, buflen, "%g %cb/s", rate / divisor, scale);
1104 }
1105
1106 /************************ POWER SUBROUTINES *************************/
1107
1108 /*------------------------------------------------------------------*/
1109 /*
1110  * Convert a value in dBm to a value in milliWatt.
1111  */
1112 int
1113 iw_dbm2mwatt(int        in)
1114 {
1115 #ifdef WE_NOLIBM
1116   /* Version without libm : slower */
1117   int           ip = in / 10;
1118   int           fp = in % 10;
1119   int           k;
1120   double        res = 1.0;
1121
1122   /* Split integral and floating part to avoid accumulating rounding errors */
1123   for(k = 0; k < ip; k++)
1124     res *= 10;
1125   for(k = 0; k < fp; k++)
1126     res *= LOG10_MAGIC;
1127   return((int) res);
1128 #else   /* WE_NOLIBM */
1129   /* Version with libm : faster */
1130   return((int) (floor(pow(10.0, (((double) in) / 10.0)))));
1131 #endif  /* WE_NOLIBM */
1132 }
1133
1134 /*------------------------------------------------------------------*/
1135 /*
1136  * Convert a value in milliWatt to a value in dBm.
1137  */
1138 int
1139 iw_mwatt2dbm(int        in)
1140 {
1141 #ifdef WE_NOLIBM
1142   /* Version without libm : slower */
1143   double        fin = (double) in;
1144   int           res = 0;
1145
1146   /* Split integral and floating part to avoid accumulating rounding errors */
1147   while(fin > 10.0)
1148     {
1149       res += 10;
1150       fin /= 10.0;
1151     }
1152   while(fin > 1.000001) /* Eliminate rounding errors, take ceil */
1153     {
1154       res += 1;
1155       fin /= LOG10_MAGIC;
1156     }
1157   return(res);
1158 #else   /* WE_NOLIBM */
1159   /* Version with libm : faster */
1160   return((int) (ceil(10.0 * log10((double) in))));
1161 #endif  /* WE_NOLIBM */
1162 }
1163
1164 /*------------------------------------------------------------------*/
1165 /*
1166  * Output a txpower with proper conversion
1167  */
1168 void
1169 iw_print_txpower(char *                 buffer,
1170                  int                    buflen,
1171                  struct iw_param *      txpower)
1172 {
1173   int           dbm;
1174
1175   /* Check if disabled */
1176   if(txpower->disabled)
1177     {
1178       snprintf(buffer, buflen, "off");
1179     }
1180   else
1181     {
1182       /* Check for relative values */
1183       if(txpower->flags & IW_TXPOW_RELATIVE)
1184         {
1185           snprintf(buffer, buflen, "%d", txpower->value);
1186         }
1187       else
1188         {
1189           /* Convert everything to dBm */
1190           if(txpower->flags & IW_TXPOW_MWATT)
1191             dbm = iw_mwatt2dbm(txpower->value);
1192           else
1193             dbm = txpower->value;
1194
1195           /* Display */
1196           snprintf(buffer, buflen, "%d dBm", dbm);
1197         }
1198     }
1199 }
1200
1201 /********************** STATISTICS SUBROUTINES **********************/
1202
1203 /*------------------------------------------------------------------*/
1204 /*
1205  * Read /proc/net/wireless to get the latest statistics
1206  */
1207 int
1208 iw_get_stats(int                skfd,
1209              const char *       ifname,
1210              iwstats *          stats,
1211              const iwrange *    range,
1212              int                has_range)
1213 {
1214   /* Fortunately, we can always detect this condition properly */
1215   if((has_range) && (range->we_version_compiled > 11))
1216     {
1217       struct iwreq              wrq;
1218       wrq.u.data.pointer = (caddr_t) stats;
1219       wrq.u.data.length = sizeof(struct iw_statistics);
1220       wrq.u.data.flags = 1;             /* Clear updated flag */
1221       strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
1222       if(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0)
1223         return(-1);
1224
1225       /* Format has not changed since WE-12, no conversion */
1226       return(0);
1227     }
1228   else
1229     {
1230       FILE *    f = fopen(PROC_NET_WIRELESS, "r");
1231       char      buf[256];
1232       char *    bp;
1233       int       t;
1234
1235       if(f==NULL)
1236         return -1;
1237       /* Loop on all devices */
1238       while(fgets(buf,255,f))
1239         {
1240           bp=buf;
1241           while(*bp&&isspace(*bp))
1242             bp++;
1243           /* Is it the good device ? */
1244           if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
1245             {
1246               /* Skip ethX: */
1247               bp=strchr(bp,':');
1248               bp++;
1249               /* -- status -- */
1250               bp = strtok(bp, " ");
1251               sscanf(bp, "%X", &t);
1252               stats->status = (unsigned short) t;
1253               /* -- link quality -- */
1254               bp = strtok(NULL, " ");
1255               if(strchr(bp,'.') != NULL)
1256                 stats->qual.updated |= 1;
1257               sscanf(bp, "%d", &t);
1258               stats->qual.qual = (unsigned char) t;
1259               /* -- signal level -- */
1260               bp = strtok(NULL, " ");
1261               if(strchr(bp,'.') != NULL)
1262                 stats->qual.updated |= 2;
1263               sscanf(bp, "%d", &t);
1264               stats->qual.level = (unsigned char) t;
1265               /* -- noise level -- */
1266               bp = strtok(NULL, " ");
1267               if(strchr(bp,'.') != NULL)
1268                 stats->qual.updated += 4;
1269               sscanf(bp, "%d", &t);
1270               stats->qual.noise = (unsigned char) t;
1271               /* -- discarded packets -- */
1272               bp = strtok(NULL, " ");
1273               sscanf(bp, "%d", &stats->discard.nwid);
1274               bp = strtok(NULL, " ");
1275               sscanf(bp, "%d", &stats->discard.code);
1276               bp = strtok(NULL, " ");
1277               sscanf(bp, "%d", &stats->discard.misc);
1278               fclose(f);
1279               /* No conversion needed */
1280               return 0;
1281             }
1282         }
1283       fclose(f);
1284       return -1;
1285     }
1286 }
1287
1288 /*------------------------------------------------------------------*/
1289 /*
1290  * Output the link statistics, taking care of formating
1291  */
1292 void
1293 iw_print_stats(char *           buffer,
1294                int              buflen,
1295                const iwqual *   qual,
1296                const iwrange *  range,
1297                int              has_range)
1298 {
1299   int           len;
1300
1301   /* People are very often confused by the 8 bit arithmetic happening
1302    * here.
1303    * All the values here are encoded in a 8 bit integer. 8 bit integers
1304    * are either unsigned [0 ; 255], signed [-128 ; +127] or
1305    * negative [-255 ; 0].
1306    * Further, on 8 bits, 0x100 == 256 == 0.
1307    *
1308    * Relative/percent values are always encoded unsigned, between 0 and 255.
1309    * Absolute/dBm values are always encoded negative, between -255 and 0.
1310    *
1311    * How do we separate relative from absolute values ? We use the
1312    * range to do that. The range allow to specify the real min/max
1313    * of the value. As the range struct only specify one bound of the
1314    * value, we assume that the other bound is 0 (zero).
1315    * For relative values, range is [0 ; range->max].
1316    * For absolute values, range is [range->max ; 0].
1317    *
1318    * Let's take two example :
1319    * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100
1320    * 2) value is -54dBm. noise floor of the radio is -104dBm.
1321    *    qual->value = -54 = 202 ; range->max_qual.value = -104 = 152
1322    *
1323    * Jean II
1324    */
1325
1326   /* Just do it */
1327   if(has_range && (qual->level != 0))
1328     {
1329       /* Deal with quality : always a relative value */
1330       if(!(qual->updated & IW_QUAL_QUAL_INVALID))
1331         {
1332           len = snprintf(buffer, buflen, "Quality%c%d/%d  ",
1333                          qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':',
1334                          qual->qual, range->max_qual.qual);
1335           buffer += len;
1336           buflen -= len;
1337         }
1338
1339       /* If the statistics are in dBm or relative */
1340       if(qual->level > range->max_qual.level)
1341         {
1342           /* Deal with signal level in dBm  (absolute power measurement) */
1343           if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1344             {
1345               len = snprintf(buffer, buflen, "Signal level%c%d dBm  ",
1346                              qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1347                              qual->level - 0x100);
1348               buffer += len;
1349               buflen -= len;
1350             }
1351
1352           /* Deal with noise level in dBm (absolute power measurement) */
1353           if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1354             {
1355               len = snprintf(buffer, buflen, "Noise level%c%d dBm",
1356                              qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1357                              qual->noise - 0x100);
1358             }
1359         }
1360       else
1361         {
1362           /* Deal with signal level as relative value (0 -> max) */
1363           if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1364             {
1365               len = snprintf(buffer, buflen, "Signal level%c%d/%d  ",
1366                              qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1367                              qual->level, range->max_qual.level);
1368               buffer += len;
1369               buflen -= len;
1370             }
1371
1372           /* Deal with noise level as relative value (0 -> max) */
1373           if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1374             {
1375               len = snprintf(buffer, buflen, "Noise level%c%d/%d",
1376                              qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1377                              qual->noise, range->max_qual.noise);
1378             }
1379         }
1380     }
1381   else
1382     {
1383       /* We can't read the range, so we don't know... */
1384       snprintf(buffer, buflen,
1385                "Quality:%d  Signal level:%d  Noise level:%d",
1386                qual->qual, qual->level, qual->noise);
1387     }
1388 }
1389
1390 /*********************** ENCODING SUBROUTINES ***********************/
1391
1392 /*------------------------------------------------------------------*/
1393 /*
1394  * Output the encoding key, with a nice formating
1395  */
1396 void
1397 iw_print_key(char *                     buffer,
1398              int                        buflen,
1399              const unsigned char *      key,            /* Must be unsigned */
1400              int                        key_size,
1401              int                        key_flags)
1402 {
1403   int   i;
1404
1405   /* Check buffer size -> 1 bytes => 2 digits + 1/2 separator */
1406   if((key_size * 3) > buflen)
1407     {
1408       snprintf(buffer, buflen, "<too big>");
1409       return;
1410     }
1411
1412   /* Is the key present ??? */
1413   if(key_flags & IW_ENCODE_NOKEY)
1414     {
1415       /* Nope : print on or dummy */
1416       if(key_size <= 0)
1417         strcpy(buffer, "on");                   /* Size checked */
1418       else
1419         {
1420           strcpy(buffer, "**");                 /* Size checked */
1421           buffer +=2;
1422           for(i = 1; i < key_size; i++)
1423             {
1424               if((i & 0x1) == 0)
1425                 strcpy(buffer++, "-");          /* Size checked */
1426               strcpy(buffer, "**");             /* Size checked */
1427               buffer +=2;
1428             }
1429         }
1430     }
1431   else
1432     {
1433       /* Yes : print the key */
1434       sprintf(buffer, "%.2X", key[0]);          /* Size checked */
1435       buffer +=2;
1436       for(i = 1; i < key_size; i++)
1437         {
1438           if((i & 0x1) == 0)
1439             strcpy(buffer++, "-");              /* Size checked */
1440           sprintf(buffer, "%.2X", key[i]);      /* Size checked */
1441           buffer +=2;
1442         }
1443     }
1444 }
1445
1446 /*------------------------------------------------------------------*/
1447 /*
1448  * Convert a passphrase into a key
1449  * ### NOT IMPLEMENTED ###
1450  * Return size of the key, or 0 (no key) or -1 (error)
1451  */
1452 static int
1453 iw_pass_key(const char *        input,
1454             unsigned char *     key)
1455 {
1456   input = input; key = key;
1457   fprintf(stderr, "Error: Passphrase not implemented\n");
1458   return(-1);
1459 }
1460
1461 /*------------------------------------------------------------------*/
1462 /*
1463  * Parse a key from the command line.
1464  * Return size of the key, or 0 (no key) or -1 (error)
1465  */
1466 int
1467 iw_in_key(const char *          input,
1468           unsigned char *       key)
1469 {
1470   int           keylen = 0;
1471
1472   /* Check the type of key */
1473   if(!strncmp(input, "s:", 2))
1474     {
1475       /* First case : as an ASCII string (Lucent/Agere cards) */
1476       keylen = strlen(input + 2);               /* skip "s:" */
1477       if(keylen > IW_ENCODING_TOKEN_MAX)
1478         keylen = IW_ENCODING_TOKEN_MAX;
1479       strncpy(key, input + 2, keylen);
1480     }
1481   else
1482     if(!strncmp(input, "p:", 2))
1483       {
1484         /* Second case : as a passphrase (PrismII cards) */
1485         return(iw_pass_key(input + 2, key));            /* skip "p:" */
1486       }
1487     else
1488       {
1489         char *  buff;
1490         char *  hex;
1491         char *  out;
1492         char *  p;
1493
1494         /* Third case : as hexadecimal digits */
1495         buff = malloc(IW_ENCODING_TOKEN_MAX + strlen(input) + 1);
1496         if(buff == NULL)
1497           {
1498             fprintf(stderr, "Malloc failed (string too long ?)\n");
1499             return(-1);
1500           }
1501         /* Preserve original buffers (both in & out) */
1502         hex = buff + IW_ENCODING_TOKEN_MAX;
1503         strcpy(hex, input);                             /* Size checked */
1504         out = buff;
1505
1506         /* Parse */
1507         p = strtok(hex, "-:;.,");
1508         while((p != (char *) NULL) && (keylen < IW_ENCODING_TOKEN_MAX))
1509           {
1510             int temph;
1511             int templ;
1512             int count;
1513             int len;
1514             /* Get each char separatly (and not by two) so that we don't
1515              * get confused by 'enc' (=> '0E'+'0C') and similar */
1516             count = sscanf(p, "%1X%1X", &temph, &templ);
1517             if(count < 1)
1518               return(-1);               /* Error -> non-hex char */
1519             /* Fixup odd strings such as '123' is '01'+'23' and not '12'+'03'*/
1520             len = strlen(p);
1521             if(len % 2)
1522               count = 1;
1523             /* Put back two chars as one byte */
1524             if(count == 2)
1525               templ |= temph << 4;
1526             else
1527               templ = temph;
1528             out[keylen++] = (unsigned char) (templ & 0xFF);
1529             /* Check where to get next char from */
1530             if(len > count)     /* Token not finished yet */
1531               p += count;
1532             else
1533               p = strtok((char *) NULL, "-:;.,");
1534           }
1535         memcpy(key, out, keylen);
1536         free(buff);
1537       }
1538
1539   return(keylen);
1540 }
1541
1542 /*------------------------------------------------------------------*/
1543 /*
1544  * Parse a key from the command line.
1545  * Return size of the key, or 0 (no key) or -1 (error)
1546  */
1547 int
1548 iw_in_key_full(int              skfd,
1549                const char *     ifname,
1550                const char *     input,
1551                unsigned char *  key,
1552                __u16 *          flags)
1553 {
1554   int           keylen = 0;
1555   char *        p;
1556
1557   if(!strncmp(input, "l:", 2))
1558     {
1559       struct iw_range   range;
1560
1561       /* Extra case : as a login (user:passwd - Cisco LEAP) */
1562       keylen = strlen(input + 2) + 1;           /* skip "l:", add '\0' */
1563       /* Most user/password is 8 char, so 18 char total, < 32 */
1564       if(keylen > IW_ENCODING_TOKEN_MAX)
1565         keylen = IW_ENCODING_TOKEN_MAX;
1566       memcpy(key, input + 2, keylen);
1567
1568       /* Separate the two strings */
1569       p = strchr(key, ':');
1570       if(p == NULL)
1571         {
1572           fprintf(stderr, "Error: Invalid login format\n");
1573           return(-1);
1574         }
1575       *p = '\0';
1576
1577       /* Extract range info */
1578       if(iw_get_range_info(skfd, ifname, &range) < 0)
1579         /* Hum... Maybe we should return an error ??? */
1580         memset(&range, 0, sizeof(range));
1581
1582       if(range.we_version_compiled > 15)
1583         {
1584
1585           printf("flags = %X, index = %X\n",
1586                  *flags, range.encoding_login_index);
1587           if((*flags & IW_ENCODE_INDEX) == 0)
1588             {
1589               /* Extract range info */
1590               if(iw_get_range_info(skfd, ifname, &range) < 0)
1591                 memset(&range, 0, sizeof(range));
1592               printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
1593               /* Set the index the driver expects */
1594               *flags |= range.encoding_login_index & IW_ENCODE_INDEX;
1595             }
1596           printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
1597         }
1598     }
1599   else
1600     /* Simpler routine above */
1601     keylen = iw_in_key(input, key);
1602
1603   return(keylen);
1604 }
1605
1606 /******************* POWER MANAGEMENT SUBROUTINES *******************/
1607
1608 /*------------------------------------------------------------------*/
1609 /*
1610  * Output a power management value with all attributes...
1611  */
1612 void
1613 iw_print_pm_value(char *        buffer,
1614                   int           buflen,
1615                   int           value,
1616                   int           flags)
1617 {
1618   /* Check size */
1619   if(buflen < 25)
1620     {
1621       snprintf(buffer, buflen, "<too big>");
1622       return;
1623     }
1624   buflen -= 25;
1625
1626   /* Modifiers */
1627   if(flags & IW_POWER_MIN)
1628     {
1629       strcpy(buffer, " min");                           /* Size checked */
1630       buffer += 4;
1631     }
1632   if(flags & IW_POWER_MAX)
1633     {
1634       strcpy(buffer, " max");                           /* Size checked */
1635       buffer += 4;
1636     }
1637
1638   /* Type */
1639   if(flags & IW_POWER_TIMEOUT)
1640     {
1641       strcpy(buffer, " timeout:");                      /* Size checked */
1642       buffer += 9;
1643     }
1644   else
1645     {
1646       strcpy(buffer, " period:");                       /* Size checked */
1647       buffer += 8;
1648     }
1649
1650   /* Display value without units */
1651   if(flags & IW_POWER_RELATIVE)
1652     snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
1653   else
1654     {
1655       /* Display value with units */
1656       if(value >= (int) MEGA)
1657         snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
1658       else
1659         if(value >= (int) KILO)
1660           snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
1661         else
1662           snprintf(buffer, buflen, "%dus", value);
1663     }
1664 }
1665
1666 /*------------------------------------------------------------------*/
1667 /*
1668  * Output a power management mode
1669  */
1670 void
1671 iw_print_pm_mode(char * buffer,
1672                  int    buflen,
1673                  int    flags)
1674 {
1675   /* Check size */
1676   if(buflen < 28)
1677     {
1678       snprintf(buffer, buflen, "<too big>");
1679       return;
1680     }
1681
1682   /* Print the proper mode... */
1683   switch(flags & IW_POWER_MODE)
1684     {
1685     case IW_POWER_UNICAST_R:
1686       strcpy(buffer, "mode:Unicast only received");     /* Size checked */
1687       break;
1688     case IW_POWER_MULTICAST_R:
1689       strcpy(buffer, "mode:Multicast only received");   /* Size checked */
1690       break;
1691     case IW_POWER_ALL_R:
1692       strcpy(buffer, "mode:All packets received");      /* Size checked */
1693       break;
1694     case IW_POWER_FORCE_S:
1695       strcpy(buffer, "mode:Force sending");             /* Size checked */
1696       break;
1697     case IW_POWER_REPEATER:
1698       strcpy(buffer, "mode:Repeat multicasts");         /* Size checked */
1699       break;
1700     default:
1701       strcpy(buffer, "");                               /* Size checked */
1702       break;
1703     }
1704 }
1705
1706 /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/
1707
1708 /*------------------------------------------------------------------*/
1709 /*
1710  * Output a retry value with all attributes...
1711  */
1712 void
1713 iw_print_retry_value(char *     buffer,
1714                      int        buflen,
1715                      int        value,
1716                      int        flags)
1717 {
1718   /* Check buffer size */
1719   if(buflen < 18)
1720     {
1721       snprintf(buffer, buflen, "<too big>");
1722       return;
1723     }
1724   buflen -= 18;
1725
1726   /* Modifiers */
1727   if(flags & IW_RETRY_MIN)
1728     {
1729       strcpy(buffer, " min");                           /* Size checked */
1730       buffer += 4;
1731     }
1732   if(flags & IW_RETRY_MAX)
1733     {
1734       strcpy(buffer, " max");                           /* Size checked */
1735       buffer += 4;
1736     }
1737
1738   /* Type lifetime of limit */
1739   if(flags & IW_RETRY_LIFETIME)
1740     {
1741       strcpy(buffer, " lifetime:");                     /* Size checked */
1742       buffer += 10;
1743
1744       /* Display value without units */
1745       if(flags & IW_POWER_RELATIVE)
1746         snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
1747       else
1748         {
1749           /* Display value with units */
1750           if(value >= (int) MEGA)
1751             snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
1752           else
1753             if(value >= (int) KILO)
1754               snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
1755             else
1756               snprintf(buffer, buflen, "%dus", value);
1757         }
1758     }
1759   else
1760     snprintf(buffer, buflen, " limit:%d", value);
1761 }
1762
1763 /************************* TIME SUBROUTINES *************************/
1764
1765 /*------------------------------------------------------------------*/
1766 /*
1767  * Print timestamps
1768  * Inspired from irdadump...
1769  */
1770 void
1771 iw_print_timeval(char *                 buffer,
1772                  int                    buflen,
1773                  const struct timeval * time)
1774 {
1775         int s;
1776
1777         s = (time->tv_sec) % 86400;
1778         snprintf(buffer, buflen, "%02d:%02d:%02d.%06u ", 
1779                 s / 3600, (s % 3600) / 60, 
1780                 s % 60, (u_int32_t) time->tv_usec);
1781 }
1782
1783 /*********************** ADDRESS SUBROUTINES ************************/
1784 /*
1785  * This section is mostly a cut & past from net-tools-1.2.0
1786  * (Well... This has evolved over the years)
1787  * manage address display and input...
1788  */
1789
1790 /*------------------------------------------------------------------*/
1791 /*
1792  * Check if interface support the right MAC address type...
1793  */
1794 int
1795 iw_check_mac_addr_type(int              skfd,
1796                        char *           ifname)
1797 {
1798   struct ifreq          ifr;
1799
1800   /* Get the type of hardware address */
1801   strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1802   if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) ||
1803      (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER))
1804     {
1805       /* Deep trouble... */
1806       fprintf(stderr, "Interface %s doesn't support MAC addresses\n",
1807              ifname);
1808       return(-1);
1809     }
1810
1811 #ifdef DEBUG
1812   printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family,
1813          iw_ether_ntoa((struct ether_addr *) ifr.ifr_hwaddr.sa_data));
1814 #endif
1815
1816   return(0);
1817 }
1818
1819
1820 /*------------------------------------------------------------------*/
1821 /*
1822  * Check if interface support the right interface address type...
1823  */
1824 int
1825 iw_check_if_addr_type(int               skfd,
1826                       char *            ifname)
1827 {
1828   struct ifreq          ifr;
1829
1830   /* Get the type of interface address */
1831   strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1832   if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) ||
1833      (ifr.ifr_addr.sa_family !=  AF_INET))
1834     {
1835       /* Deep trouble... */
1836       fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname);
1837       return(-1);
1838     }
1839
1840 #ifdef DEBUG
1841   printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family,
1842          *((unsigned long *) ifr.ifr_addr.sa_data));
1843 #endif
1844
1845   return(0);
1846 }
1847
1848 #if 0
1849 /*------------------------------------------------------------------*/
1850 /*
1851  * Check if interface support the right address types...
1852  */
1853 int
1854 iw_check_addr_type(int          skfd,
1855                    char *       ifname)
1856 {
1857   /* Check the interface address type */
1858   if(iw_check_if_addr_type(skfd, ifname) < 0)
1859     return(-1);
1860
1861   /* Check the interface address type */
1862   if(iw_check_mac_addr_type(skfd, ifname) < 0)
1863     return(-1);
1864
1865   return(0);
1866 }
1867 #endif
1868
1869 /*------------------------------------------------------------------*/
1870 /*
1871  * Ask the kernel for the MAC address of an interface.
1872  */
1873 int
1874 iw_get_mac_addr(int                     skfd,
1875                 const char *            ifname,
1876                 struct ether_addr *     eth,
1877                 unsigned short *        ptype)
1878 {
1879   struct ifreq  ifr;
1880   int           ret;
1881
1882   /* Prepare request */
1883   bzero(&ifr, sizeof(struct ifreq));
1884   strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1885
1886   /* Do it */
1887   ret = ioctl(skfd, SIOCGIFHWADDR, &ifr);
1888
1889   memcpy(eth->ether_addr_octet, ifr.ifr_hwaddr.sa_data, 6); 
1890   *ptype = ifr.ifr_hwaddr.sa_family;
1891   return(ret);
1892 }
1893
1894 /*------------------------------------------------------------------*/
1895 /*
1896  * Display an Ethernet address in readable format.
1897  */
1898 void
1899 iw_ether_ntop(const struct ether_addr* eth, char* buf)
1900 {
1901   sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
1902           eth->ether_addr_octet[0], eth->ether_addr_octet[1],
1903           eth->ether_addr_octet[2], eth->ether_addr_octet[3],
1904           eth->ether_addr_octet[4], eth->ether_addr_octet[5]);
1905 }
1906
1907 /*------------------------------------------------------------------*/
1908 /*
1909  * Display an Ethernet address in readable format.
1910  * Same with a static buffer
1911  */
1912 char *
1913 iw_ether_ntoa(const struct ether_addr* eth)
1914 {
1915   static char buf[20];
1916   iw_ether_ntop(eth, buf);
1917   return buf;
1918 }
1919
1920 /*------------------------------------------------------------------*/
1921 /*
1922  * Input an Ethernet address and convert to binary.
1923  */
1924 int
1925 iw_ether_aton(const char *orig, struct ether_addr *eth)
1926 {
1927   const char *bufp;
1928   int i;
1929
1930   i = 0;
1931   for(bufp = orig; *bufp != '\0'; ++bufp) {
1932         unsigned int val;
1933         unsigned char c = *bufp++;
1934         if (isdigit(c)) val = c - '0';
1935         else if (c >= 'a' && c <= 'f') val = c - 'a' + 10;
1936         else if (c >= 'A' && c <= 'F') val = c - 'A' + 10;
1937         else break;
1938
1939         val <<= 4;
1940         c = *bufp++;
1941         if (isdigit(c)) val |= c - '0';
1942         else if (c >= 'a' && c <= 'f') val |= c - 'a' + 10;
1943         else if (c >= 'A' && c <= 'F') val |= c - 'A' + 10;
1944         else break;
1945
1946         eth->ether_addr_octet[i] = (unsigned char) (val & 0377);
1947         if(++i == ETH_ALEN) {
1948                 /* That's it.  Any trailing junk? */
1949                 if (*bufp != '\0') {
1950 #ifdef DEBUG
1951                         fprintf(stderr, "iw_ether_aton(%s): trailing junk!\n", orig);
1952                         errno = EINVAL;
1953                         return(0);
1954 #endif
1955                 }
1956 #ifdef DEBUG
1957                 fprintf(stderr, "iw_ether_aton(%s): %s\n",
1958                         orig, ether_ntoa(eth));
1959 #endif
1960                 return(1);
1961         }
1962         if (*bufp != ':')
1963                 break;
1964   }
1965
1966 #ifdef DEBUG
1967   fprintf(stderr, "iw_ether_aton(%s): invalid ether address!\n", orig);
1968 #endif
1969   errno = EINVAL;
1970   return(0);
1971 }
1972
1973
1974 /*------------------------------------------------------------------*/
1975 /*
1976  * Input an Internet address and convert to binary.
1977  */
1978 int
1979 iw_in_inet(char *name, struct sockaddr *sap)
1980 {
1981   struct hostent *hp;
1982   struct netent *np;
1983   struct sockaddr_in *sain = (struct sockaddr_in *) sap;
1984
1985   /* Grmpf. -FvK */
1986   sain->sin_family = AF_INET;
1987   sain->sin_port = 0;
1988
1989   /* Default is special, meaning 0.0.0.0. */
1990   if (!strcmp(name, "default")) {
1991         sain->sin_addr.s_addr = INADDR_ANY;
1992         return(1);
1993   }
1994
1995   /* Try the NETWORKS database to see if this is a known network. */
1996   if ((np = getnetbyname(name)) != (struct netent *)NULL) {
1997         sain->sin_addr.s_addr = htonl(np->n_net);
1998         strcpy(name, np->n_name);
1999         return(1);
2000   }
2001
2002   /* Always use the resolver (DNS name + IP addresses) */
2003   if ((hp = gethostbyname(name)) == (struct hostent *)NULL) {
2004         errno = h_errno;
2005         return(-1);
2006   }
2007   memcpy((char *) &sain->sin_addr, (char *) hp->h_addr_list[0], hp->h_length);
2008   strcpy(name, hp->h_name);
2009   return(0);
2010 }
2011
2012 /*------------------------------------------------------------------*/
2013 /*
2014  * Input an address and convert to binary.
2015  */
2016 int
2017 iw_in_addr(int          skfd,
2018            char *       ifname,
2019            char *       bufp,
2020            struct sockaddr *sap)
2021 {
2022   /* Check if it is a hardware or IP address */
2023   if(index(bufp, ':') == NULL)
2024     {
2025       struct sockaddr   if_address;
2026       struct arpreq     arp_query;
2027
2028       /* Check if we have valid interface address type */
2029       if(iw_check_if_addr_type(skfd, ifname) < 0)
2030         {
2031           fprintf(stderr, "%-8.16s  Interface doesn't support IP addresses\n", ifname);
2032           return(-1);
2033         }
2034
2035       /* Read interface address */
2036       if(iw_in_inet(bufp, &if_address) < 0)
2037         {
2038           fprintf(stderr, "Invalid interface address %s\n", bufp);
2039           return(-1);
2040         }
2041
2042       /* Translate IP addresses to MAC addresses */
2043       memcpy((char *) &(arp_query.arp_pa),
2044              (char *) &if_address,
2045              sizeof(struct sockaddr));
2046       arp_query.arp_ha.sa_family = 0;
2047       arp_query.arp_flags = 0;
2048       /* The following restrict the search to the interface only */
2049       /* For old kernels which complain, just comment it... */
2050       strncpy(arp_query.arp_dev, ifname, IFNAMSIZ);
2051       if((ioctl(skfd, SIOCGARP, &arp_query) < 0) ||
2052          !(arp_query.arp_flags & ATF_COM))
2053         {
2054           fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n",
2055                   bufp, ifname, errno);
2056           return(-1);
2057         }
2058
2059       /* Store new MAC address */
2060       memcpy((char *) sap,
2061              (char *) &(arp_query.arp_ha),
2062              sizeof(struct sockaddr));
2063
2064 #ifdef DEBUG
2065       printf("IP Address %s => Hw Address = %s\n",
2066              bufp, iw_ether_ntoa((struct ether_addr *) sap->sa_data));
2067 #endif
2068     }
2069   else  /* If it's an hardware address */
2070     {
2071       /* Check if we have valid mac address type */
2072       if(iw_check_mac_addr_type(skfd, ifname) < 0)
2073         {
2074           fprintf(stderr, "%-8.16s  Interface doesn't support MAC addresses\n", ifname);
2075           return(-1);
2076         }
2077
2078       /* Get the hardware address */
2079       if(iw_in_ether(bufp, sap) < 0)
2080         {
2081           fprintf(stderr, "Invalid hardware address %s\n", bufp);
2082           return(-1);
2083         }
2084     }
2085
2086 #ifdef DEBUG
2087   printf("Hw Address = %s\n", iw_ether_ntoa((struct ether_addr *) sap->sa_data));
2088 #endif
2089
2090   return(0);
2091 }
2092
2093 /************************* MISC SUBROUTINES **************************/
2094
2095 /* Size (in bytes) of various events */
2096 static const int priv_type_size[] = {
2097         0,                              /* IW_PRIV_TYPE_NONE */
2098         1,                              /* IW_PRIV_TYPE_BYTE */
2099         1,                              /* IW_PRIV_TYPE_CHAR */
2100         0,                              /* Not defined */
2101         sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
2102         sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
2103         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
2104         0,                              /* Not defined */
2105 };
2106
2107 /*------------------------------------------------------------------*/
2108 /*
2109  * Max size in bytes of an private argument.
2110  */
2111 int
2112 iw_get_priv_size(int    args)
2113 {
2114   int   num = args & IW_PRIV_SIZE_MASK;
2115   int   type = (args & IW_PRIV_TYPE_MASK) >> 12;
2116
2117   return(num * priv_type_size[type]);
2118 }
2119
2120 /************************ EVENT SUBROUTINES ************************/
2121 /*
2122  * The Wireless Extension API 14 and greater define Wireless Events,
2123  * that are used for various events and scanning.
2124  * Those functions help the decoding of events, so are needed only in
2125  * this case.
2126  */
2127
2128 /* Type of headers we know about (basically union iwreq_data) */
2129 #define IW_HEADER_TYPE_NULL     0       /* Not available */
2130 #define IW_HEADER_TYPE_CHAR     2       /* char [IFNAMSIZ] */
2131 #define IW_HEADER_TYPE_UINT     4       /* __u32 */
2132 #define IW_HEADER_TYPE_FREQ     5       /* struct iw_freq */
2133 #define IW_HEADER_TYPE_ADDR     6       /* struct sockaddr */
2134 #define IW_HEADER_TYPE_POINT    8       /* struct iw_point */
2135 #define IW_HEADER_TYPE_PARAM    9       /* struct iw_param */
2136 #define IW_HEADER_TYPE_QUAL     10      /* struct iw_quality */
2137
2138 /* Headers for the various requests */
2139 static const char standard_ioctl_hdr[] = {
2140         IW_HEADER_TYPE_NULL,    /* SIOCSIWCOMMIT */
2141         IW_HEADER_TYPE_CHAR,    /* SIOCGIWNAME */
2142         IW_HEADER_TYPE_PARAM,   /* SIOCSIWNWID */
2143         IW_HEADER_TYPE_PARAM,   /* SIOCGIWNWID */
2144         IW_HEADER_TYPE_FREQ,    /* SIOCSIWFREQ */
2145         IW_HEADER_TYPE_FREQ,    /* SIOCGIWFREQ */
2146         IW_HEADER_TYPE_UINT,    /* SIOCSIWMODE */
2147         IW_HEADER_TYPE_UINT,    /* SIOCGIWMODE */
2148         IW_HEADER_TYPE_PARAM,   /* SIOCSIWSENS */
2149         IW_HEADER_TYPE_PARAM,   /* SIOCGIWSENS */
2150         IW_HEADER_TYPE_NULL,    /* SIOCSIWRANGE */
2151         IW_HEADER_TYPE_POINT,   /* SIOCGIWRANGE */
2152         IW_HEADER_TYPE_NULL,    /* SIOCSIWPRIV */
2153         IW_HEADER_TYPE_POINT,   /* SIOCGIWPRIV */
2154         IW_HEADER_TYPE_NULL,    /* SIOCSIWSTATS */
2155         IW_HEADER_TYPE_POINT,   /* SIOCGIWSTATS */
2156         IW_HEADER_TYPE_POINT,   /* SIOCSIWSPY */
2157         IW_HEADER_TYPE_POINT,   /* SIOCGIWSPY */
2158         IW_HEADER_TYPE_POINT,   /* SIOCSIWTHRSPY */
2159         IW_HEADER_TYPE_POINT,   /* SIOCGIWTHRSPY */
2160         IW_HEADER_TYPE_ADDR,    /* SIOCSIWAP */
2161         IW_HEADER_TYPE_ADDR,    /* SIOCGIWAP */
2162         IW_HEADER_TYPE_NULL,    /* -- hole -- */
2163         IW_HEADER_TYPE_POINT,   /* SIOCGIWAPLIST */
2164         IW_HEADER_TYPE_PARAM,   /* SIOCSIWSCAN */
2165         IW_HEADER_TYPE_POINT,   /* SIOCGIWSCAN */
2166         IW_HEADER_TYPE_POINT,   /* SIOCSIWESSID */
2167         IW_HEADER_TYPE_POINT,   /* SIOCGIWESSID */
2168         IW_HEADER_TYPE_POINT,   /* SIOCSIWNICKN */
2169         IW_HEADER_TYPE_POINT,   /* SIOCGIWNICKN */
2170         IW_HEADER_TYPE_NULL,    /* -- hole -- */
2171         IW_HEADER_TYPE_NULL,    /* -- hole -- */
2172         IW_HEADER_TYPE_PARAM,   /* SIOCSIWRATE */
2173         IW_HEADER_TYPE_PARAM,   /* SIOCGIWRATE */
2174         IW_HEADER_TYPE_PARAM,   /* SIOCSIWRTS */
2175         IW_HEADER_TYPE_PARAM,   /* SIOCGIWRTS */
2176         IW_HEADER_TYPE_PARAM,   /* SIOCSIWFRAG */
2177         IW_HEADER_TYPE_PARAM,   /* SIOCGIWFRAG */
2178         IW_HEADER_TYPE_PARAM,   /* SIOCSIWTXPOW */
2179         IW_HEADER_TYPE_PARAM,   /* SIOCGIWTXPOW */
2180         IW_HEADER_TYPE_PARAM,   /* SIOCSIWRETRY */
2181         IW_HEADER_TYPE_PARAM,   /* SIOCGIWRETRY */
2182         IW_HEADER_TYPE_POINT,   /* SIOCSIWENCODE */
2183         IW_HEADER_TYPE_POINT,   /* SIOCGIWENCODE */
2184         IW_HEADER_TYPE_PARAM,   /* SIOCSIWPOWER */
2185         IW_HEADER_TYPE_PARAM,   /* SIOCGIWPOWER */
2186 };
2187 static const unsigned int standard_ioctl_num = sizeof(standard_ioctl_hdr);
2188
2189 /*
2190  * Meta-data about all the additional standard Wireless Extension events
2191  * we know about.
2192  */
2193 static const char       standard_event_hdr[] = {
2194         IW_HEADER_TYPE_ADDR,    /* IWEVTXDROP */
2195         IW_HEADER_TYPE_QUAL,    /* IWEVQUAL */
2196         IW_HEADER_TYPE_POINT,   /* IWEVCUSTOM */
2197         IW_HEADER_TYPE_ADDR,    /* IWEVREGISTERED */
2198         IW_HEADER_TYPE_ADDR,    /* IWEVEXPIRED */
2199 };
2200 static const unsigned int standard_event_num = sizeof(standard_event_hdr);
2201
2202 /* Size (in bytes) of various events */
2203 static const int event_type_size[] = {
2204         IW_EV_LCP_LEN,          /* IW_HEADER_TYPE_NULL */
2205         0,
2206         IW_EV_CHAR_LEN,         /* IW_HEADER_TYPE_CHAR */
2207         0,
2208         IW_EV_UINT_LEN,         /* IW_HEADER_TYPE_UINT */
2209         IW_EV_FREQ_LEN,         /* IW_HEADER_TYPE_FREQ */
2210         IW_EV_ADDR_LEN,         /* IW_HEADER_TYPE_ADDR */
2211         0,
2212         IW_EV_POINT_LEN,        /* Without variable payload */
2213         IW_EV_PARAM_LEN,        /* IW_HEADER_TYPE_PARAM */
2214         IW_EV_QUAL_LEN,         /* IW_HEADER_TYPE_QUAL */
2215 };
2216
2217 /* Forward compatibility with WE-19 */
2218 #define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
2219                           (char *) NULL)
2220
2221 /*------------------------------------------------------------------*/
2222 /*
2223  * Initialise the struct stream_descr so that we can extract
2224  * individual events from the event stream.
2225  */
2226 void
2227 iw_init_event_stream(struct stream_descr *      stream, /* Stream of events */
2228                      char *                     data,
2229                      int                        len)
2230 {
2231   /* Cleanup */
2232   memset((char *) stream, '\0', sizeof(struct stream_descr));
2233
2234   /* Set things up */
2235   stream->current = data;
2236   stream->end = data + len;
2237 }
2238
2239 /*------------------------------------------------------------------*/
2240 /*
2241  * Extract the next event from the event stream.
2242  */
2243 int
2244 iw_extract_event_stream(struct stream_descr *   stream, /* Stream of events */
2245                         struct iw_event *       iwe,    /* Extracted event */
2246                         int                     we_version)
2247 {
2248   int           event_type = 0;
2249   unsigned int  event_len = 1;          /* Invalid */
2250   char *        pointer;
2251   /* Don't "optimise" the following variable, it will crash */
2252   unsigned      cmd_index;              /* *MUST* be unsigned */
2253
2254   /* Unused for now. Will be later on... */
2255   we_version = we_version;
2256
2257   /* Check for end of stream */
2258   if((stream->current + IW_EV_LCP_LEN) > stream->end)
2259     return(0);
2260
2261 #if 0
2262   printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n",
2263          stream->current, stream->value, stream->end);
2264 #endif
2265
2266   /* Extract the event header (to get the event id).
2267    * Note : the event may be unaligned, therefore copy... */
2268   memcpy((char *) iwe, stream->current, IW_EV_LCP_LEN);
2269
2270 #if 0
2271   printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n",
2272          iwe->cmd, iwe->len);
2273 #endif
2274
2275   /* Check invalid events */
2276   if(iwe->len <= IW_EV_LCP_LEN)
2277     return(-1);
2278
2279   /* Get the type and length of that event */
2280   if(iwe->cmd <= SIOCIWLAST)
2281     {
2282       cmd_index = iwe->cmd - SIOCIWFIRST;
2283       if(cmd_index < standard_ioctl_num)
2284         event_type = standard_ioctl_hdr[cmd_index];
2285     }
2286   else
2287     {
2288       cmd_index = iwe->cmd - IWEVFIRST;
2289       if(cmd_index < standard_event_num)
2290         event_type = standard_event_hdr[cmd_index];
2291     }
2292   /* Unknown events -> event_type=0 => IW_EV_LCP_LEN */
2293   event_len = event_type_size[event_type];
2294   /* Fixup for later version of WE */
2295   if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))
2296     event_len -= IW_EV_POINT_OFF;
2297
2298   /* Check if we know about this event */
2299   if(event_len <= IW_EV_LCP_LEN)
2300     {
2301       /* Skip to next event */
2302       stream->current += iwe->len;
2303       return(2);
2304     }
2305   event_len -= IW_EV_LCP_LEN;
2306
2307   /* Set pointer on data */
2308   if(stream->value != NULL)
2309     pointer = stream->value;                    /* Next value in event */
2310   else
2311     pointer = stream->current + IW_EV_LCP_LEN;  /* First value in event */
2312
2313 #if 0
2314   printf("DBG - event_type = %d, event_len = %d, pointer = %p\n",
2315          event_type, event_len, pointer);
2316 #endif
2317
2318   /* Copy the rest of the event (at least, fixed part) */
2319   if((pointer + event_len) > stream->end)
2320     {
2321       /* Go to next event */
2322       stream->current += iwe->len;
2323       return(-2);
2324     }
2325   /* Fixup for later version of WE */
2326   if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))
2327     memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
2328            pointer, event_len);
2329   else
2330     memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
2331
2332   /* Skip event in the stream */
2333   pointer += event_len;
2334
2335   /* Special processing for iw_point events */
2336   if(event_type == IW_HEADER_TYPE_POINT)
2337     {
2338       /* Check the length of the payload */
2339       if((iwe->len - (event_len + IW_EV_LCP_LEN)) > 0)
2340         /* Set pointer on variable part (warning : non aligned) */
2341         iwe->u.data.pointer = pointer;
2342       else
2343         /* No data */
2344         iwe->u.data.pointer = NULL;
2345
2346       /* Go to next event */
2347       stream->current += iwe->len;
2348     }
2349   else
2350     {
2351       /* Is there more value in the event ? */
2352       if((pointer + event_len) <= (stream->current + iwe->len))
2353         /* Go to next value */
2354         stream->value = pointer;
2355       else
2356         {
2357           /* Go to next event */
2358           stream->value = NULL;
2359           stream->current += iwe->len;
2360         }
2361     }
2362   return(1);
2363 }
2364
2365 /*********************** SCANNING SUBROUTINES ***********************/
2366 /*
2367  * The Wireless Extension API 14 and greater define Wireless Scanning.
2368  * The normal API is complex, this is an easy API that return
2369  * a subset of the scanning results. This should be enough for most
2370  * applications that want to use Scanning.
2371  * If you want to have use the full/normal API, check iwlist.c...
2372  *
2373  * Precaution when using scanning :
2374  * The scanning operation disable normal network traffic, and therefore
2375  * you should not abuse of scan.
2376  * The scan need to check the presence of network on other frequencies.
2377  * While you are checking those other frequencies, you can *NOT* be on
2378  * your normal frequency to listen to normal traffic in the cell.
2379  * You need typically in the order of one second to actively probe all
2380  * 802.11b channels (do the maths). Some cards may do that in background,
2381  * to reply to scan commands faster, but they still have to do it.
2382  * Leaving the cell for such an extended period of time is pretty bad.
2383  * Any kind of streaming/low latency traffic will be impacted, and the
2384  * user will perceive it (easily checked with telnet). People trying to
2385  * send traffic to you will retry packets and waste bandwidth. Some
2386  * applications may be sensitive to those packet losses in weird ways,
2387  * and tracing those weird behavior back to scanning may take time.
2388  * If you are in ad-hoc mode, if two nodes scan approx at the same
2389  * time, they won't see each other, which may create associations issues.
2390  * For those reasons, the scanning activity should be limited to
2391  * what's really needed, and continuous scanning is a bad idea.
2392  * Jean II
2393  */
2394
2395 /*------------------------------------------------------------------*/
2396 /*
2397  * Process/store one element from the scanning results in wireless_scan
2398  */
2399 static inline struct wireless_scan *
2400 iw_process_scanning_token(struct iw_event *             event,
2401                           struct wireless_scan *        wscan)
2402 {
2403   struct wireless_scan *        oldwscan;
2404
2405   /* Now, let's decode the event */
2406   switch(event->cmd)
2407     {
2408     case SIOCGIWAP:
2409       /* New cell description. Allocate new cell descriptor, zero it. */
2410       oldwscan = wscan;
2411       wscan = (struct wireless_scan *) malloc(sizeof(struct wireless_scan));
2412       if(wscan == NULL)
2413         return(wscan);
2414       /* Link at the end of the list */
2415       if(oldwscan != NULL)
2416         oldwscan->next = wscan;
2417
2418       /* Reset it */
2419       bzero(wscan, sizeof(struct wireless_scan));
2420
2421       /* Save cell identifier */
2422       wscan->has_ap_addr = 1;
2423       memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof (sockaddr));
2424       break;
2425     case SIOCGIWNWID:
2426       wscan->b.has_nwid = 1;
2427       memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam));
2428       break;
2429     case SIOCGIWFREQ:
2430       wscan->b.has_freq = 1;
2431       wscan->b.freq = iw_freq2float(&(event->u.freq));
2432       wscan->b.freq_flags = event->u.freq.flags;
2433       break;
2434     case SIOCGIWMODE:
2435       wscan->b.mode = event->u.mode;
2436       if((wscan->b.mode < IW_NUM_OPER_MODE) && (wscan->b.mode >= 0))
2437         wscan->b.has_mode = 1;
2438       break;
2439     case SIOCGIWESSID:
2440       wscan->b.has_essid = 1;
2441       wscan->b.essid_on = event->u.data.flags;
2442       if((event->u.essid.pointer) && (event->u.essid.length))
2443         memcpy(wscan->b.essid, event->u.essid.pointer, event->u.essid.length);
2444       wscan->b.essid[event->u.essid.length] = '\0';
2445       break;
2446     case SIOCGIWENCODE:
2447       wscan->b.has_key = 1;
2448       wscan->b.key_size = event->u.data.length;
2449       wscan->b.key_flags = event->u.data.flags;
2450       if(event->u.data.pointer)
2451         memcpy(wscan->b.key, event->u.essid.pointer, event->u.data.length);
2452       else
2453         wscan->b.key_flags |= IW_ENCODE_NOKEY;
2454       break;
2455     case IWEVQUAL:
2456       /* We don't get complete stats, only qual */
2457       wscan->has_stats = 1;
2458       memcpy(&wscan->stats.qual, &event->u.qual, sizeof(iwstats));
2459       break;
2460     case SIOCGIWRATE:
2461       /* Scan may return a list of bitrates. Should we really bother with
2462        * an array of bitrates ? Or only the maximum bitrate ? Jean II */
2463     case IWEVCUSTOM:
2464       /* How can we deal with those sanely ? Jean II */
2465     default:
2466       break;
2467    }    /* switch(event->cmd) */
2468
2469   return(wscan);
2470 }
2471
2472 /*------------------------------------------------------------------*/
2473 /*
2474  * Initiate the scan procedure, and process results.
2475  * This is a non-blocking procedure and it will return each time
2476  * it would block, returning the amount of time the caller should wait
2477  * before calling again.
2478  * Return -1 for error, delay to wait for (in ms), or 0 for success.
2479  * Error code is in errno
2480  */
2481 int
2482 iw_process_scan(int                     skfd,
2483                 char *                  ifname,
2484                 int                     we_version,
2485                 wireless_scan_head *    context)
2486 {
2487   struct iwreq          wrq;
2488   unsigned char *       buffer = NULL;          /* Results */
2489   int                   buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
2490   unsigned char *       newbuf;
2491
2492   /* Don't waste too much time on interfaces (50 * 100 = 5s) */
2493   context->retry++;
2494   if(context->retry > 50)
2495     {
2496       errno = ETIME;
2497       return(-1);
2498     }
2499
2500   /* If we have not yet initiated scanning on the interface */
2501   if(context->retry == 1)
2502     {
2503       /* Initiate Scan */
2504       wrq.u.data.pointer = NULL;                /* Later */
2505       wrq.u.data.flags = 0;
2506       wrq.u.data.length = 0;
2507       if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
2508         return(-1);
2509       /* Success : now, just wait for event or results */
2510       return(250);      /* Wait 250 ms */
2511     }
2512
2513  realloc:
2514   /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
2515   newbuf = realloc(buffer, buflen);
2516   if(newbuf == NULL)
2517     {
2518       /* man says : If realloc() fails the original block is left untouched */
2519       if(buffer)
2520         free(buffer);
2521       errno = ENOMEM;
2522       return(-1);
2523     }
2524   buffer = newbuf;
2525
2526   /* Try to read the results */
2527   wrq.u.data.pointer = buffer;
2528   wrq.u.data.flags = 0;
2529   wrq.u.data.length = buflen;
2530   if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
2531     {
2532       /* Check if buffer was too small (WE-17 only) */
2533       if((errno == E2BIG) && (we_version > 16))
2534         {
2535           /* Some driver may return very large scan results, either
2536            * because there are many cells, or because they have many
2537            * large elements in cells (like IWEVCUSTOM). Most will
2538            * only need the regular sized buffer. We now use a dynamic
2539            * allocation of the buffer to satisfy everybody. Of course,
2540            * as we don't know in advance the size of the array, we try
2541            * various increasing sizes. Jean II */
2542
2543           /* Check if the driver gave us any hints. */
2544           if(wrq.u.data.length > buflen)
2545             buflen = wrq.u.data.length;
2546           else
2547             buflen *= 2;
2548
2549           /* Try again */
2550           goto realloc;
2551         }
2552
2553       /* Check if results not available yet */
2554       if(errno == EAGAIN)
2555         {
2556           free(buffer);
2557           /* Wait for only 100ms from now on */
2558           return(100);  /* Wait 100 ms */
2559         }
2560
2561       free(buffer);
2562       /* Bad error, please don't come back... */
2563       return(-1);
2564     }
2565
2566   /* We have the results, process them */
2567   if(wrq.u.data.length)
2568     {
2569       struct iw_event           iwe;
2570       struct stream_descr       stream;
2571       struct wireless_scan *    wscan = NULL;
2572       int                       ret;
2573 #if 0
2574       /* Debugging code. In theory useless, because it's debugged ;-) */
2575       int       i;
2576       printf("Scan result [%02X", buffer[0]);
2577       for(i = 1; i < wrq.u.data.length; i++)
2578         printf(":%02X", buffer[i]);
2579       printf("]\n");
2580 #endif
2581
2582       /* Init */
2583       iw_init_event_stream(&stream, buffer, wrq.u.data.length);
2584       /* This is dangerous, we may leak user data... */
2585       context->result = NULL;
2586
2587       /* Look every token */
2588       do
2589         {
2590           /* Extract an event and print it */
2591           ret = iw_extract_event_stream(&stream, &iwe, we_version);
2592           if(ret > 0)
2593             {
2594               /* Convert to wireless_scan struct */
2595               wscan = iw_process_scanning_token(&iwe, wscan);
2596               /* Check problems */
2597               if(wscan == NULL)
2598                 {
2599                   free(buffer);
2600                   errno = ENOMEM;
2601                   return(-1);
2602                 }
2603               /* Save head of list */
2604               if(context->result == NULL)
2605                 context->result = wscan;
2606             }
2607         }
2608       while(ret > 0);
2609     }
2610
2611   /* Done with this interface - return success */
2612   free(buffer);
2613   return(0);
2614 }
2615
2616 /*------------------------------------------------------------------*/
2617 /*
2618  * Perform a wireless scan on the specified interface.
2619  * This is a blocking procedure and it will when the scan is completed
2620  * or when an error occur.
2621  *
2622  * The scan results are given in a linked list of wireless_scan objects.
2623  * The caller *must* free the result himself (by walking the list).
2624  * If there is an error, -1 is returned and the error code is available
2625  * in errno.
2626  *
2627  * The parameter we_version can be extracted from the range structure
2628  * (range.we_version_compiled - see iw_get_range_info()), or using
2629  * iw_get_kernel_we_version(). For performance reason, you should
2630  * cache this parameter when possible rather than querying it every time.
2631  *
2632  * Return -1 for error and 0 for success.
2633  */
2634 int
2635 iw_scan(int                     skfd,
2636         char *                  ifname,
2637         int                     we_version,
2638         wireless_scan_head *    context)
2639 {
2640   int           delay;          /* in ms */
2641
2642   /* Clean up context. Potential memory leak if(context.result != NULL) */
2643   context->result = NULL;
2644   context->retry = 0;
2645
2646   /* Wait until we get results or error */
2647   while(1)
2648     {
2649       /* Try to get scan results */
2650       delay = iw_process_scan(skfd, ifname, we_version, context);
2651
2652       /* Check termination */
2653       if(delay <= 0)
2654         break;
2655
2656       /* Wait a bit */
2657       usleep(delay * 1000);
2658     }
2659
2660   /* End - return -1 or 0 */
2661   return(delay);
2662 }