4 * Jean II - HPLB 97->99 - HPL 99->04
6 * Common subroutines to all the wireless tools...
8 * This file is released under the GPL license.
9 * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
12 /***************************** INCLUDES *****************************/
14 #include "iwlib.h" /* Header */
16 /************************ CONSTANTS & MACROS ************************/
19 * Constants fof WE-9->15
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
28 /****************************** TYPES ******************************/
31 * Struct iw_range up to WE-15
40 struct iw_freq freq[IW15_MAX_FREQUENCIES];
42 struct iw_quality max_qual;
44 __s32 bitrate[IW15_MAX_BITRATES];
56 __u16 encoding_size[IW15_MAX_ENCODING_SIZES];
57 __u8 num_encoding_sizes;
58 __u8 max_encoding_tokens;
61 __s32 txpower[IW15_MAX_TXPOWER];
62 __u8 we_version_compiled;
63 __u8 we_version_source;
71 struct iw_quality avg_qual;
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.
81 struct iw15_range range15; /* WE 9->15 */
82 struct iw_range range; /* WE 16->current */
86 * Offsets in iw_range struct
88 #define iwr15_off(f) ( ((char *) &(((struct iw15_range *) NULL)->f)) - \
90 #define iwr_off(f) ( ((char *) &(((struct iw_range *) NULL)->f)) - \
93 /**************************** VARIABLES ****************************/
95 /* Modes as human readable strings */
96 const char * const iw_operation_mode[] = { "Auto",
104 /* Disable runtime version warning in iw_get_range_info() */
105 int iw_ignore_version = 0;
107 /************************ SOCKET SUBROUTINES *************************/
109 /*------------------------------------------------------------------*/
112 * Depending on the protocol present, open the right socket. The socket
113 * will allow us to talk to the driver.
116 iw_sockets_open(void)
118 static const int families[] = {
119 AF_INET, AF_IPX, AF_AX25, AF_APPLETALK
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...
133 /* Try all families we support */
134 for(i = 0; i < sizeof(families)/sizeof(int); ++i)
136 /* Try to open the socket, if success returns it */
137 sock = socket(families[i], SOCK_DGRAM, 0);
145 /*------------------------------------------------------------------*/
147 * Extract the interface name out of /proc/net/wireless or /proc/net/dev.
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 */
156 /* Skip leading spaces */
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, ':');
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, ": ");
172 /* Not found ??? To big ??? */
173 if((end == NULL) || (((end - buf) + 1) > nsize))
177 memcpy(name, buf, (end - buf));
178 name[end - buf] = '\0';
180 /* Return value currently unused, just make sure it's non-NULL */
184 /*------------------------------------------------------------------*/
186 * Enumerate devices and call specified routine
187 * The new way just use /proc/net/wireless, so get all wireless interfaces,
188 * whether configured or not. This is the default if available.
189 * The old way use SIOCGIFCONF, so get only configured interfaces (wireless
193 iw_enum_devices(int skfd,
204 #ifndef IW_RESTRIC_ENUM
205 /* Check if /proc/net/dev is available */
206 fh = fopen(PROC_NET_DEV, "r");
208 /* Check if /proc/net/wireless is available */
209 fh = fopen(PROC_NET_WIRELESS, "r");
214 /* Success : use data from /proc/net/wireless */
216 /* Eat 2 lines of header */
217 fgets(buff, sizeof(buff), fh);
218 fgets(buff, sizeof(buff), fh);
220 /* Read each device line */
221 while(fgets(buff, sizeof(buff), fh))
223 char name[IFNAMSIZ + 1];
226 /* Skip empty or almost empty lines. It seems that in some
227 * cases fgets return a line with only a newline. */
228 if((buff[0] == '\0') || (buff[1] == '\0'))
231 /* Extract interface name */
232 s = iw_get_ifname(name, sizeof(name), buff);
236 /* Failed to parse, complain and continue */
237 #ifndef IW_RESTRIC_ENUM
238 fprintf(stderr, "Cannot parse " PROC_NET_DEV "\n");
240 fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
244 /* Got it, print info about this interface */
245 (*fn)(skfd, name, args, count);
252 /* Get list of configured devices using "traditional" way */
253 ifc.ifc_len = sizeof(buff);
255 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
257 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
263 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
264 (*fn)(skfd, ifr->ifr_name, args, count);
268 /*********************** WIRELESS SUBROUTINES ************************/
270 /*------------------------------------------------------------------*/
272 * Extract WE version number from /proc/net/wireless
273 * In most cases, you really want to get version information from
274 * the range info (range->we_version_compiled), see below...
276 * If we have WE-16 and later, the WE version is available at the
277 * end of the header line of the file.
278 * For version prior to that, we can only detect the change from
279 * v11 to v12, so we do an approximate job. Fortunately, v12 to v15
280 * are highly binary compatible (on the struct level).
283 iw_get_kernel_we_version(void)
290 /* Check if /proc/net/wireless is available */
291 fh = fopen(PROC_NET_WIRELESS, "r");
295 fprintf(stderr, "Cannot read " PROC_NET_WIRELESS "\n");
299 /* Read the first line of buffer */
300 fgets(buff, sizeof(buff), fh);
302 if(strstr(buff, "| WE") == NULL)
304 /* Prior to WE16, so explicit version not present */
307 if(strstr(buff, "| Missed") == NULL)
315 /* Read the second line of buffer */
316 fgets(buff, sizeof(buff), fh);
318 /* Get to the last separator, to get the version */
319 p = strrchr(buff, '|');
320 if((p == NULL) || (sscanf(p + 1, "%d", &v) != 1))
322 fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
331 /*------------------------------------------------------------------*/
333 * Print the WE versions of the interface.
336 print_iface_version_info(int skfd,
338 char * args[], /* Command line args */
339 int count) /* Args count */
342 char buffer[sizeof(iwrange) * 2]; /* Large enough */
343 struct iw_range * range;
345 /* Avoid "Unused parameter" warning */
346 args = args; count = count;
348 /* If no wireless name : no wireless extensions.
349 * This enable us to treat the SIOCGIWRANGE failure below properly. */
350 if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
354 memset(buffer, 0, sizeof(buffer));
356 wrq.u.data.pointer = (caddr_t) buffer;
357 wrq.u.data.length = sizeof(buffer);
358 wrq.u.data.flags = 0;
359 if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
361 /* Interface support WE (see above), but not IWRANGE */
362 fprintf(stderr, "%-8.16s Driver has no Wireless Extension version information.\n\n", ifname);
366 /* Copy stuff at the right place, ignore extra */
367 range = (struct iw_range *) buffer;
369 /* For new versions, we can check the version directly, for old versions
370 * we use magic. 300 bytes is a also magic number, don't touch... */
371 if(wrq.u.data.length >= 300)
373 /* Version is always at the same offset, so it's ok */
374 printf("%-8.16s Recommend Wireless Extension v%d or later,\n",
375 ifname, range->we_version_source);
376 printf(" Currently compiled with Wireless Extension v%d.\n\n",
377 range->we_version_compiled);
381 fprintf(stderr, "%-8.16s Wireless Extension version too old.\n\n",
389 /*------------------------------------------------------------------*/
391 * Print the WE versions of the tools.
394 iw_print_version_info(const char * toolname)
396 int skfd; /* generic raw socket desc. */
397 int we_kernel_version;
399 /* Create a channel to the NET kernel. */
400 if((skfd = iw_sockets_open()) < 0)
406 /* Information about the tools themselves */
408 printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION);
409 printf(" Compatible with Wireless Extension v11 to v%d.\n\n",
412 /* Get version from kernel */
413 we_kernel_version = iw_get_kernel_we_version();
414 /* Only version >= 16 can be verified, other are guessed */
415 if(we_kernel_version > 15)
416 printf("Kernel Currently compiled with Wireless Extension v%d.\n\n",
419 /* Version for each device */
420 iw_enum_devices(skfd, &print_iface_version_info, NULL, 0);
422 iw_sockets_close(skfd);
427 /*------------------------------------------------------------------*/
429 * Get the range information out of the driver
432 iw_get_range_info(int skfd,
437 char buffer[sizeof(iwrange) * 2]; /* Large enough */
438 union iw_range_raw * range_raw;
441 bzero(buffer, sizeof(buffer));
443 wrq.u.data.pointer = (caddr_t) buffer;
444 wrq.u.data.length = sizeof(buffer);
445 wrq.u.data.flags = 0;
446 if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
449 /* Point to the buffer */
450 range_raw = (union iw_range_raw *) buffer;
452 /* For new versions, we can check the version directly, for old versions
453 * we use magic. 300 bytes is a also magic number, don't touch... */
454 if(wrq.u.data.length < 300)
456 /* That's v10 or earlier. Ouch ! Let's make a guess...*/
457 range_raw->range.we_version_compiled = 9;
460 /* Check how it needs to be processed */
461 if(range_raw->range.we_version_compiled > 15)
463 /* This is our native format, that's easy... */
464 /* Copy stuff at the right place, ignore extra */
465 memcpy((char *) range, buffer, sizeof(iwrange));
469 /* Zero unknown fields */
470 bzero((char *) range, sizeof(struct iw_range));
472 /* Initial part unmoved */
473 memcpy((char *) range,
475 iwr15_off(num_channels));
476 /* Frequencies pushed futher down towards the end */
477 memcpy((char *) range + iwr_off(num_channels),
478 buffer + iwr15_off(num_channels),
479 iwr15_off(sensitivity) - iwr15_off(num_channels));
480 /* This one moved up */
481 memcpy((char *) range + iwr_off(sensitivity),
482 buffer + iwr15_off(sensitivity),
483 iwr15_off(num_bitrates) - iwr15_off(sensitivity));
484 /* This one goes after avg_qual */
485 memcpy((char *) range + iwr_off(num_bitrates),
486 buffer + iwr15_off(num_bitrates),
487 iwr15_off(min_rts) - iwr15_off(num_bitrates));
488 /* Number of bitrates has changed, put it after */
489 memcpy((char *) range + iwr_off(min_rts),
490 buffer + iwr15_off(min_rts),
491 iwr15_off(txpower_capa) - iwr15_off(min_rts));
492 /* Added encoding_login_index, put it after */
493 memcpy((char *) range + iwr_off(txpower_capa),
494 buffer + iwr15_off(txpower_capa),
495 iwr15_off(txpower) - iwr15_off(txpower_capa));
496 /* Hum... That's an unexpected glitch. Bummer. */
497 memcpy((char *) range + iwr_off(txpower),
498 buffer + iwr15_off(txpower),
499 iwr15_off(avg_qual) - iwr15_off(txpower));
500 /* Avg qual moved up next to max_qual */
501 memcpy((char *) range + iwr_off(avg_qual),
502 buffer + iwr15_off(avg_qual),
503 sizeof(struct iw_quality));
506 /* We are now checking much less than we used to do, because we can
507 * accomodate more WE version. But, there are still cases where things
509 if(!iw_ignore_version)
511 /* We don't like very old version (unfortunately kernel 2.2.X) */
512 if(range->we_version_compiled <= 10)
514 fprintf(stderr, "Warning: Driver for device %s has been compiled with an ancient version\n", ifname);
515 fprintf(stderr, "of Wireless Extension, while this program support version 11 and later.\n");
516 fprintf(stderr, "Some things may be broken...\n\n");
519 /* We don't like future versions of WE, because we can't cope with
521 if(range->we_version_compiled > WE_MAX_VERSION)
523 fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled);
524 fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_VERSION);
525 fprintf(stderr, "Some things may be broken...\n\n");
528 /* Driver version verification */
529 if((range->we_version_compiled > 10) &&
530 (range->we_version_compiled < range->we_version_source))
532 fprintf(stderr, "Warning: Driver for device %s recommend version %d of Wireless Extension,\n", ifname, range->we_version_source);
533 fprintf(stderr, "but has been compiled with version %d, therefore some driver features\n", range->we_version_compiled);
534 fprintf(stderr, "may not be available...\n\n");
536 /* Note : we are only trying to catch compile difference, not source.
537 * If the driver source has not been updated to the latest, it doesn't
538 * matter because the new fields are set to zero */
541 /* Don't complain twice.
542 * In theory, the test apply to each individual driver, but usually
543 * all drivers are compiled from the same kernel. */
544 iw_ignore_version = 1;
549 /*------------------------------------------------------------------*/
551 * Get information about what private ioctls are supported by the driver
553 * Note : there is one danger using this function. If it return 0, you
554 * still need to free() the buffer. Beware.
557 iw_get_priv_info(int skfd,
562 iwprivargs * priv = NULL; /* Not allocated yet */
563 int maxpriv = 16; /* Minimum for compatibility WE<13 */
564 iwprivargs * newpriv;
566 /* Some driver may return a very large number of ioctls. Some
567 * others a very small number. We now use a dynamic allocation
568 * of the array to satisfy everybody. Of course, as we don't know
569 * in advance the size of the array, we try various increasing
573 /* (Re)allocate the buffer */
574 newpriv = realloc(priv, maxpriv * sizeof(priv[0]));
577 fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
582 /* Ask the driver if it's large enough */
583 wrq.u.data.pointer = (caddr_t) priv;
584 wrq.u.data.length = maxpriv;
585 wrq.u.data.flags = 0;
586 if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) >= 0)
588 /* Success. Pass the buffer by pointer */
590 /* Return the number of ioctls */
591 return(wrq.u.data.length);
594 /* Only E2BIG means the buffer was too small, abort on other errors */
597 /* Most likely "not supported". Don't barf. */
601 /* Failed. We probably need a bigger buffer. Check if the kernel
602 * gave us any hints. */
603 if(wrq.u.data.length > maxpriv)
604 maxpriv = wrq.u.data.length;
608 while(maxpriv < 1000);
618 /*------------------------------------------------------------------*/
620 * Get essential wireless config from the device driver
621 * We will call all the classical wireless ioctl on the driver through
622 * the socket to know what is supported and to get the settings...
623 * Note : compare to the version in iwconfig, we extract only
624 * what's *really* needed to configure a device...
627 iw_get_basic_config(int skfd,
629 wireless_config * info)
633 memset((char *) info, 0, sizeof(struct wireless_config));
635 /* Get wireless name */
636 if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
637 /* If no wireless name : no wireless extensions */
641 strncpy(info->name, wrq.u.name, IFNAMSIZ);
642 info->name[IFNAMSIZ] = '\0';
646 if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0)
649 memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
652 /* Get frequency / channel */
653 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
656 info->freq = iw_freq2float(&(wrq.u.freq));
657 info->freq_flags = wrq.u.freq.flags;
660 /* Get encryption information */
661 wrq.u.data.pointer = (caddr_t) info->key;
662 wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
663 wrq.u.data.flags = 0;
664 if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
667 info->key_size = wrq.u.data.length;
668 info->key_flags = wrq.u.data.flags;
672 wrq.u.essid.pointer = (caddr_t) info->essid;
673 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
674 wrq.u.essid.flags = 0;
675 if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0)
678 info->essid_on = wrq.u.data.flags;
681 /* Get operation mode */
682 if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
684 info->mode = wrq.u.mode;
685 if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
692 /*------------------------------------------------------------------*/
694 * Set essential wireless config in the device driver
695 * We will call all the classical wireless ioctl on the driver through
696 * the socket to know what is supported and to set the settings...
697 * We support only the restricted set as above...
700 iw_set_basic_config(int skfd,
702 wireless_config * info)
707 /* Get wireless name (check if interface is valid) */
708 if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
709 /* If no wireless name : no wireless extensions */
712 /* Set the current mode of operation
713 * Mode need to be first : some settings apply only in a specific mode
714 * (such as frequency).
718 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
719 wrq.u.mode = info->mode;
721 if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
723 fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
728 /* Set frequency / channel */
731 iw_float2freq(info->freq, &(wrq.u.freq));
733 if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
735 fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
740 /* Set encryption information */
743 int flags = info->key_flags;
745 /* Check if there is a key index */
746 if((flags & IW_ENCODE_INDEX) > 0)
749 wrq.u.data.pointer = (caddr_t) NULL;
750 wrq.u.data.flags = (flags & (IW_ENCODE_INDEX)) | IW_ENCODE_NOKEY;
751 wrq.u.data.length = 0;
753 if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
755 fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
756 errno, strerror(errno));
761 /* Mask out index to minimise probability of reject when setting key */
762 flags = flags & (~IW_ENCODE_INDEX);
764 /* Set the key itself (set current key in this case) */
765 wrq.u.data.pointer = (caddr_t) info->key;
766 wrq.u.data.length = info->key_size;
767 wrq.u.data.flags = flags;
769 /* Compatibility with WE<13 */
770 if(flags & IW_ENCODE_NOKEY)
771 wrq.u.data.pointer = NULL;
773 if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
775 fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
776 errno, strerror(errno));
781 /* Set Network ID, if available (this is for non-802.11 cards) */
784 memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam));
785 wrq.u.nwid.fixed = 1; /* Hum... When in Rome... */
787 if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
789 fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
794 /* Set ESSID (extended network), if available.
795 * ESSID need to be last : most device re-perform the scanning/discovery
796 * when this is set, and things like encryption keys are better be
797 * defined if we want to discover the right set of APs/nodes.
801 int we_kernel_version;
802 we_kernel_version = iw_get_kernel_we_version();
804 wrq.u.essid.pointer = (caddr_t) info->essid;
805 wrq.u.essid.length = strlen(info->essid) + 1;
806 wrq.u.data.flags = info->essid_on;
807 if(we_kernel_version > 20)
808 wrq.u.essid.length--;
810 if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
812 fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
820 /*********************** PROTOCOL SUBROUTINES ***********************/
822 * Fun stuff with protocol identifiers (SIOCGIWNAME).
823 * We assume that drivers are returning sensible values in there,
824 * which is not always the case :-(
827 /*------------------------------------------------------------------*/
829 * Compare protocol identifiers.
830 * We don't want to know if the two protocols are the exactly same,
831 * but if they interoperate at some level, and also if they accept the
832 * same type of config (ESSID vs NWID, freq...).
833 * This is supposed to work around the alphabet soup.
834 * Return 1 if protocols are compatible, 0 otherwise
837 iw_protocol_compare(const char * protocol1,
838 const char * protocol2)
840 const char * dot11 = "IEEE 802.11";
841 const char * dot11_ds = "Dbg";
842 const char * dot11_5g = "a";
844 /* If the strings are the same -> easy */
845 if(!strncmp(protocol1, protocol2, IFNAMSIZ))
848 /* Are we dealing with one of the 802.11 variant ? */
849 if( (!strncmp(protocol1, dot11, strlen(dot11))) &&
850 (!strncmp(protocol2, dot11, strlen(dot11))) )
852 const char * sub1 = protocol1 + strlen(dot11);
853 const char * sub2 = protocol2 + strlen(dot11);
860 /* Check if we find the magic letters telling it's DS compatible */
861 for(i = 0; i < strlen(dot11_ds); i++)
863 if(strchr(sub1, dot11_ds[i]) != NULL)
865 if(strchr(sub2, dot11_ds[i]) != NULL)
871 /* Check if we find the magic letters telling it's 5GHz compatible */
872 for(i = 0; i < strlen(dot11_5g); i++)
874 if(strchr(sub1, dot11_5g[i]) != NULL)
876 if(strchr(sub2, dot11_5g[i]) != NULL)
886 /********************** FREQUENCY SUBROUTINES ***********************/
888 * Note : the two functions below are the cause of troubles on
889 * various embeeded platforms, as they are the reason we require
890 * libm (math library).
891 * In this case, please use enable BUILD_NOLIBM in the makefile
893 * FIXME : check negative mantissa and exponent
896 /*------------------------------------------------------------------*/
898 * Convert a floating point the our internal representation of
900 * The kernel doesn't want to hear about floating point, so we use
901 * this custom format instead.
904 iw_float2freq(double in,
908 /* Version without libm : slower */
916 #else /* WE_NOLIBM */
917 /* Version with libm : faster */
918 out->e = (short) (floor(log10(in)));
921 out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100;
929 #endif /* WE_NOLIBM */
932 /*------------------------------------------------------------------*/
934 * Convert our internal representation of frequencies to a floating point.
937 iw_freq2float(const iwfreq * in)
940 /* Version without libm : slower */
942 double res = (double) in->m;
943 for(i = 0; i < in->e; i++)
946 #else /* WE_NOLIBM */
947 /* Version with libm : faster */
948 return ((double) in->m) * pow(10,in->e);
949 #endif /* WE_NOLIBM */
952 /*------------------------------------------------------------------*/
954 * Output a frequency with proper scaling
957 iw_print_freq_value(char * buffer,
962 snprintf(buffer, buflen, "%g", freq);
986 snprintf(buffer, buflen, "%g %cHz", freq / divisor, scale);
990 /*------------------------------------------------------------------*/
992 * Output a frequency with proper scaling
995 iw_print_freq(char * buffer,
1001 char sep = ((freq_flags & IW_FREQ_FIXED) ? '=' : ':');
1004 /* Print the frequency/channel value */
1005 iw_print_freq_value(vbuf, sizeof(vbuf), freq);
1007 /* Check if channel only */
1009 snprintf(buffer, buflen, "Channel%c%s", sep, vbuf);
1012 /* Frequency. Check if we have a channel as well */
1014 snprintf(buffer, buflen, "Frequency%c%s (Channel %d)",
1015 sep, vbuf, channel);
1017 snprintf(buffer, buflen, "Frequency%c%s", sep, vbuf);
1021 /*------------------------------------------------------------------*/
1023 * Convert a frequency to a channel (negative -> error)
1026 iw_freq_to_channel(double freq,
1027 const struct iw_range * range)
1032 /* Check if it's a frequency or not already a channel */
1036 /* We compare the frequencies as double to ignore differences
1037 * in encoding. Slower, but safer... */
1038 for(k = 0; k < range->num_frequency; k++)
1040 ref_freq = iw_freq2float(&(range->freq[k]));
1041 if(freq == ref_freq)
1042 return(range->freq[k].i);
1048 /*------------------------------------------------------------------*/
1050 * Convert a channel to a frequency (negative -> error)
1051 * Return the channel on success
1054 iw_channel_to_freq(int channel,
1056 const struct iw_range * range)
1061 /* Check if the driver support only channels or if it has frequencies */
1062 for(k = 0; k < range->num_frequency; k++)
1064 if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO))
1070 /* Find the correct frequency in the list */
1071 for(k = 0; k < range->num_frequency; k++)
1073 if(range->freq[k].i == channel)
1075 *pfreq = iw_freq2float(&(range->freq[k]));
1083 /*********************** BITRATE SUBROUTINES ***********************/
1085 /*------------------------------------------------------------------*/
1087 * Output a bitrate with proper scaling
1090 iw_print_bitrate(char * buffer,
1094 double rate = bitrate;
1116 snprintf(buffer, buflen, "%g %cb/s", rate / divisor, scale);
1119 /************************ POWER SUBROUTINES *************************/
1121 /*------------------------------------------------------------------*/
1123 * Convert a value in dBm to a value in milliWatt.
1126 iw_dbm2mwatt(int in)
1129 /* Version without libm : slower */
1135 /* Split integral and floating part to avoid accumulating rounding errors */
1136 for(k = 0; k < ip; k++)
1138 for(k = 0; k < fp; k++)
1141 #else /* WE_NOLIBM */
1142 /* Version with libm : faster */
1143 return((int) (floor(pow(10.0, (((double) in) / 10.0)))));
1144 #endif /* WE_NOLIBM */
1147 /*------------------------------------------------------------------*/
1149 * Convert a value in milliWatt to a value in dBm.
1152 iw_mwatt2dbm(int in)
1155 /* Version without libm : slower */
1156 double fin = (double) in;
1159 /* Split integral and floating part to avoid accumulating rounding errors */
1165 while(fin > 1.000001) /* Eliminate rounding errors, take ceil */
1171 #else /* WE_NOLIBM */
1172 /* Version with libm : faster */
1173 return((int) (ceil(10.0 * log10((double) in))));
1174 #endif /* WE_NOLIBM */
1177 /*------------------------------------------------------------------*/
1179 * Output a txpower with proper conversion
1182 iw_print_txpower(char * buffer,
1184 struct iw_param * txpower)
1188 /* Check if disabled */
1189 if(txpower->disabled)
1191 snprintf(buffer, buflen, "off");
1195 /* Check for relative values */
1196 if(txpower->flags & IW_TXPOW_RELATIVE)
1198 snprintf(buffer, buflen, "%d", txpower->value);
1202 /* Convert everything to dBm */
1203 if(txpower->flags & IW_TXPOW_MWATT)
1204 dbm = iw_mwatt2dbm(txpower->value);
1206 dbm = txpower->value;
1209 snprintf(buffer, buflen, "%d dBm", dbm);
1214 /********************** STATISTICS SUBROUTINES **********************/
1216 /*------------------------------------------------------------------*/
1218 * Read /proc/net/wireless to get the latest statistics
1219 * Note : strtok not thread safe, not used in WE-12 and later.
1222 iw_get_stats(int skfd,
1223 const char * ifname,
1225 const iwrange * range,
1228 /* Fortunately, we can always detect this condition properly */
1229 if((has_range) && (range->we_version_compiled > 11))
1232 wrq.u.data.pointer = (caddr_t) stats;
1233 wrq.u.data.length = sizeof(struct iw_statistics);
1234 wrq.u.data.flags = 1; /* Clear updated flag */
1235 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
1236 if(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0)
1239 /* Format has not changed since WE-12, no conversion */
1244 FILE * f = fopen(PROC_NET_WIRELESS, "r");
1251 /* Loop on all devices */
1252 while(fgets(buf,255,f))
1255 while(*bp&&isspace(*bp))
1257 /* Is it the good device ? */
1258 if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
1264 bp = strtok(bp, " ");
1265 sscanf(bp, "%X", &t);
1266 stats->status = (unsigned short) t;
1267 /* -- link quality -- */
1268 bp = strtok(NULL, " ");
1269 if(strchr(bp,'.') != NULL)
1270 stats->qual.updated |= 1;
1271 sscanf(bp, "%d", &t);
1272 stats->qual.qual = (unsigned char) t;
1273 /* -- signal level -- */
1274 bp = strtok(NULL, " ");
1275 if(strchr(bp,'.') != NULL)
1276 stats->qual.updated |= 2;
1277 sscanf(bp, "%d", &t);
1278 stats->qual.level = (unsigned char) t;
1279 /* -- noise level -- */
1280 bp = strtok(NULL, " ");
1281 if(strchr(bp,'.') != NULL)
1282 stats->qual.updated += 4;
1283 sscanf(bp, "%d", &t);
1284 stats->qual.noise = (unsigned char) t;
1285 /* -- discarded packets -- */
1286 bp = strtok(NULL, " ");
1287 sscanf(bp, "%d", &stats->discard.nwid);
1288 bp = strtok(NULL, " ");
1289 sscanf(bp, "%d", &stats->discard.code);
1290 bp = strtok(NULL, " ");
1291 sscanf(bp, "%d", &stats->discard.misc);
1293 /* No conversion needed */
1302 /*------------------------------------------------------------------*/
1304 * Output the link statistics, taking care of formating
1307 iw_print_stats(char * buffer,
1309 const iwqual * qual,
1310 const iwrange * range,
1315 /* People are very often confused by the 8 bit arithmetic happening
1317 * All the values here are encoded in a 8 bit integer. 8 bit integers
1318 * are either unsigned [0 ; 255], signed [-128 ; +127] or
1319 * negative [-255 ; 0].
1320 * Further, on 8 bits, 0x100 == 256 == 0.
1322 * Relative/percent values are always encoded unsigned, between 0 and 255.
1323 * Absolute/dBm values are always encoded negative, between -255 and 0.
1325 * How do we separate relative from absolute values ?
1326 * The old way is to use the range to do that. As of WE-19, we have
1327 * an explicit IW_QUAL_DBM flag in updated...
1328 * The range allow to specify the real min/max of the value. As the
1329 * range struct only specify one bound of the value, we assume that
1330 * the other bound is 0 (zero).
1331 * For relative values, range is [0 ; range->max].
1332 * For absolute values, range is [range->max ; 0].
1334 * Let's take two example :
1335 * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100
1336 * 2) value is -54dBm. noise floor of the radio is -104dBm.
1337 * qual->value = -54 = 202 ; range->max_qual.value = -104 = 152
1343 * The old way to detect dBm require both the range and a non-null
1344 * level (which confuse the test). The new way can deal with level of 0
1345 * because it does an explicit test on the flag. */
1346 if(has_range && ((qual->level != 0) || (qual->updated & IW_QUAL_DBM)))
1348 /* Deal with quality : always a relative value */
1349 if(!(qual->updated & IW_QUAL_QUAL_INVALID))
1351 len = snprintf(buffer, buflen, "Quality%c%d/%d ",
1352 qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':',
1353 qual->qual, range->max_qual.qual);
1358 /* Check if the statistics are in dBm or relative */
1359 if((qual->updated & IW_QUAL_DBM)
1360 || (qual->level > range->max_qual.level))
1362 /* Deal with signal level in dBm (absolute power measurement) */
1363 if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1365 len = snprintf(buffer, buflen, "Signal level%c%d dBm ",
1366 qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1367 qual->level - 0x100);
1372 /* Deal with noise level in dBm (absolute power measurement) */
1373 if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1375 len = snprintf(buffer, buflen, "Noise level%c%d dBm",
1376 qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1377 qual->noise - 0x100);
1382 /* Deal with signal level as relative value (0 -> max) */
1383 if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1385 len = snprintf(buffer, buflen, "Signal level%c%d/%d ",
1386 qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1387 qual->level, range->max_qual.level);
1392 /* Deal with noise level as relative value (0 -> max) */
1393 if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1395 len = snprintf(buffer, buflen, "Noise level%c%d/%d",
1396 qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1397 qual->noise, range->max_qual.noise);
1403 /* We can't read the range, so we don't know... */
1404 snprintf(buffer, buflen,
1405 "Quality:%d Signal level:%d Noise level:%d",
1406 qual->qual, qual->level, qual->noise);
1410 /*********************** ENCODING SUBROUTINES ***********************/
1412 /*------------------------------------------------------------------*/
1414 * Output the encoding key, with a nice formating
1417 iw_print_key(char * buffer,
1419 const unsigned char * key, /* Must be unsigned */
1425 /* Check buffer size -> 1 bytes => 2 digits + 1/2 separator */
1426 if((key_size * 3) > buflen)
1428 snprintf(buffer, buflen, "<too big>");
1432 /* Is the key present ??? */
1433 if(key_flags & IW_ENCODE_NOKEY)
1435 /* Nope : print on or dummy */
1437 strcpy(buffer, "on"); /* Size checked */
1440 strcpy(buffer, "**"); /* Size checked */
1442 for(i = 1; i < key_size; i++)
1445 strcpy(buffer++, "-"); /* Size checked */
1446 strcpy(buffer, "**"); /* Size checked */
1453 /* Yes : print the key */
1454 sprintf(buffer, "%.2X", key[0]); /* Size checked */
1456 for(i = 1; i < key_size; i++)
1459 strcpy(buffer++, "-"); /* Size checked */
1460 sprintf(buffer, "%.2X", key[i]); /* Size checked */
1466 /*------------------------------------------------------------------*/
1468 * Convert a passphrase into a key
1469 * ### NOT IMPLEMENTED ###
1470 * Return size of the key, or 0 (no key) or -1 (error)
1473 iw_pass_key(const char * input,
1474 unsigned char * key)
1476 input = input; key = key;
1477 fprintf(stderr, "Error: Passphrase not implemented\n");
1481 /*------------------------------------------------------------------*/
1483 * Parse a key from the command line.
1484 * Return size of the key, or 0 (no key) or -1 (error)
1485 * If the key is too long, it's simply truncated...
1488 iw_in_key(const char * input,
1489 unsigned char * key)
1493 /* Check the type of key */
1494 if(!strncmp(input, "s:", 2))
1496 /* First case : as an ASCII string (Lucent/Agere cards) */
1497 keylen = strlen(input + 2); /* skip "s:" */
1498 if(keylen > IW_ENCODING_TOKEN_MAX)
1499 keylen = IW_ENCODING_TOKEN_MAX;
1500 memcpy(key, input + 2, keylen);
1503 if(!strncmp(input, "p:", 2))
1505 /* Second case : as a passphrase (PrismII cards) */
1506 return(iw_pass_key(input + 2, key)); /* skip "p:" */
1511 int dlen; /* Digits sequence length */
1512 unsigned char out[IW_ENCODING_TOKEN_MAX];
1514 /* Third case : as hexadecimal digits */
1518 /* Loop until we run out of chars in input or overflow the output */
1524 /* No more chars in this sequence */
1527 /* Skip separator */
1530 /* Calculate num of char to next separator */
1531 dlen = strcspn(p, "-:;.,");
1533 /* Get each char separatly (and not by two) so that we don't
1534 * get confused by 'enc' (=> '0E'+'0C') and similar */
1535 count = sscanf(p, "%1X%1X", &temph, &templ);
1537 return(-1); /* Error -> non-hex char */
1538 /* Fixup odd strings such as '123' is '01'+'23' and not '12'+'03'*/
1541 /* Put back two chars as one byte and output */
1543 templ |= temph << 4;
1546 out[keylen++] = (unsigned char) (templ & 0xFF);
1547 /* Check overflow in output */
1548 if(keylen >= IW_ENCODING_TOKEN_MAX)
1550 /* Move on to next chars */
1554 /* We use a temporary output buffer 'out' so that if there is
1555 * an error, we don't overwrite the original key buffer.
1556 * Because of the way iwconfig loop on multiple key/enc arguments
1557 * until it finds an error in here, this is necessary to avoid
1558 * silently corrupting the encryption key... */
1559 memcpy(key, out, keylen);
1564 char buf[IW_ENCODING_TOKEN_MAX * 3];
1565 iw_print_key(buf, sizeof(buf), key, keylen, 0);
1566 printf("Got key : %d [%s]\n", keylen, buf);
1573 /*------------------------------------------------------------------*/
1575 * Parse a key from the command line.
1576 * Return size of the key, or 0 (no key) or -1 (error)
1579 iw_in_key_full(int skfd,
1580 const char * ifname,
1582 unsigned char * key,
1588 if(!strncmp(input, "l:", 2))
1590 struct iw_range range;
1592 /* Extra case : as a login (user:passwd - Cisco LEAP) */
1593 keylen = strlen(input + 2) + 1; /* skip "l:", add '\0' */
1594 /* Most user/password is 8 char, so 18 char total, < 32 */
1595 if(keylen > IW_ENCODING_TOKEN_MAX)
1596 keylen = IW_ENCODING_TOKEN_MAX;
1597 memcpy(key, input + 2, keylen);
1599 /* Separate the two strings */
1600 p = strchr((char *) key, ':');
1603 fprintf(stderr, "Error: Invalid login format\n");
1608 /* Extract range info */
1609 if(iw_get_range_info(skfd, ifname, &range) < 0)
1610 /* Hum... Maybe we should return an error ??? */
1611 memset(&range, 0, sizeof(range));
1613 if(range.we_version_compiled > 15)
1616 printf("flags = %X, index = %X\n",
1617 *flags, range.encoding_login_index);
1618 if((*flags & IW_ENCODE_INDEX) == 0)
1620 /* Extract range info */
1621 if(iw_get_range_info(skfd, ifname, &range) < 0)
1622 memset(&range, 0, sizeof(range));
1623 printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
1624 /* Set the index the driver expects */
1625 *flags |= range.encoding_login_index & IW_ENCODE_INDEX;
1627 printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
1631 /* Simpler routine above */
1632 keylen = iw_in_key(input, key);
1637 /******************* POWER MANAGEMENT SUBROUTINES *******************/
1639 /*------------------------------------------------------------------*/
1641 * Output a power management value with all attributes...
1644 iw_print_pm_value(char * buffer,
1652 snprintf(buffer, buflen, "<too big>");
1658 if(flags & IW_POWER_MIN)
1660 strcpy(buffer, " min"); /* Size checked */
1663 if(flags & IW_POWER_MAX)
1665 strcpy(buffer, " max"); /* Size checked */
1670 if(flags & IW_POWER_TIMEOUT)
1672 strcpy(buffer, " timeout:"); /* Size checked */
1677 strcpy(buffer, " period:"); /* Size checked */
1681 /* Display value without units */
1682 if(flags & IW_POWER_RELATIVE)
1683 snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
1686 /* Display value with units */
1687 if(value >= (int) MEGA)
1688 snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
1690 if(value >= (int) KILO)
1691 snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
1693 snprintf(buffer, buflen, "%dus", value);
1697 /*------------------------------------------------------------------*/
1699 * Output a power management mode
1702 iw_print_pm_mode(char * buffer,
1709 snprintf(buffer, buflen, "<too big>");
1713 /* Print the proper mode... */
1714 switch(flags & IW_POWER_MODE)
1716 case IW_POWER_UNICAST_R:
1717 strcpy(buffer, "mode:Unicast only received"); /* Size checked */
1719 case IW_POWER_MULTICAST_R:
1720 strcpy(buffer, "mode:Multicast only received"); /* Size checked */
1722 case IW_POWER_ALL_R:
1723 strcpy(buffer, "mode:All packets received"); /* Size checked */
1725 case IW_POWER_FORCE_S:
1726 strcpy(buffer, "mode:Force sending"); /* Size checked */
1728 case IW_POWER_REPEATER:
1729 strcpy(buffer, "mode:Repeat multicasts"); /* Size checked */
1732 strcpy(buffer, ""); /* Size checked */
1737 /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/
1739 /*------------------------------------------------------------------*/
1741 * Output a retry value with all attributes...
1744 iw_print_retry_value(char * buffer,
1749 /* Check buffer size */
1752 snprintf(buffer, buflen, "<too big>");
1758 if(flags & IW_RETRY_MIN)
1760 strcpy(buffer, " min"); /* Size checked */
1763 if(flags & IW_RETRY_MAX)
1765 strcpy(buffer, " max"); /* Size checked */
1769 /* Type lifetime of limit */
1770 if(flags & IW_RETRY_LIFETIME)
1772 strcpy(buffer, " lifetime:"); /* Size checked */
1775 /* Display value without units */
1776 if(flags & IW_POWER_RELATIVE)
1777 snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
1780 /* Display value with units */
1781 if(value >= (int) MEGA)
1782 snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
1784 if(value >= (int) KILO)
1785 snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
1787 snprintf(buffer, buflen, "%dus", value);
1791 snprintf(buffer, buflen, " limit:%d", value);
1794 /************************* TIME SUBROUTINES *************************/
1796 /*------------------------------------------------------------------*/
1799 * Inspired from irdadump...
1802 iw_print_timeval(char * buffer,
1804 const struct timeval * timev,
1805 const struct timezone * tz)
1809 s = (timev->tv_sec - tz->tz_minuteswest * 60) % 86400;
1810 snprintf(buffer, buflen, "%02d:%02d:%02d.%06u",
1811 s / 3600, (s % 3600) / 60,
1812 s % 60, (u_int32_t) timev->tv_usec);
1815 /*********************** ADDRESS SUBROUTINES ************************/
1817 * This section is mostly a cut & past from net-tools-1.2.0
1818 * (Well... This has evolved over the years)
1819 * manage address display and input...
1822 /*------------------------------------------------------------------*/
1824 * Check if interface support the right MAC address type...
1827 iw_check_mac_addr_type(int skfd,
1828 const char * ifname)
1832 /* Get the type of hardware address */
1833 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1834 if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) ||
1835 ((ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
1836 && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211)))
1838 /* Deep trouble... */
1839 fprintf(stderr, "Interface %s doesn't support MAC addresses\n",
1847 printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family,
1848 iw_saether_ntop(&ifr.ifr_hwaddr, buf));
1856 /*------------------------------------------------------------------*/
1858 * Check if interface support the right interface address type...
1861 iw_check_if_addr_type(int skfd,
1862 const char * ifname)
1866 /* Get the type of interface address */
1867 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1868 if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) ||
1869 (ifr.ifr_addr.sa_family != AF_INET))
1871 /* Deep trouble... */
1872 fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname);
1877 printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family,
1878 *((unsigned long *) ifr.ifr_addr.sa_data));
1885 /*------------------------------------------------------------------*/
1887 * Check if interface support the right address types...
1890 iw_check_addr_type(int skfd,
1893 /* Check the interface address type */
1894 if(iw_check_if_addr_type(skfd, ifname) < 0)
1897 /* Check the interface address type */
1898 if(iw_check_mac_addr_type(skfd, ifname) < 0)
1906 /*------------------------------------------------------------------*/
1908 * Ask the kernel for the MAC address of an interface.
1911 iw_get_mac_addr(int skfd,
1912 const char * ifname,
1913 struct ether_addr * eth,
1914 unsigned short * ptype)
1919 /* Prepare request */
1920 bzero(&ifr, sizeof(struct ifreq));
1921 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1924 ret = ioctl(skfd, SIOCGIFHWADDR, &ifr);
1926 memcpy(eth->ether_addr_octet, ifr.ifr_hwaddr.sa_data, 6);
1927 *ptype = ifr.ifr_hwaddr.sa_family;
1932 /*------------------------------------------------------------------*/
1934 * Display an arbitrary length MAC address in readable format.
1937 iw_mac_ntop(const unsigned char * mac,
1944 /* Overflow check (don't forget '\0') */
1945 if(buflen < (maclen * 3 - 1 + 1))
1949 sprintf(buf, "%02X", mac[0]);
1952 for(i = 1; i < maclen; i++)
1953 sprintf(buf + (i * 3) - 1, ":%02X", mac[i]);
1957 /*------------------------------------------------------------------*/
1959 * Display an Ethernet address in readable format.
1962 iw_ether_ntop(const struct ether_addr * eth,
1965 sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
1966 eth->ether_addr_octet[0], eth->ether_addr_octet[1],
1967 eth->ether_addr_octet[2], eth->ether_addr_octet[3],
1968 eth->ether_addr_octet[4], eth->ether_addr_octet[5]);
1971 /*------------------------------------------------------------------*/
1973 * Display an Wireless Access Point Socket Address in readable format.
1974 * Note : 0x44 is an accident of history, that's what the Orinoco/PrismII
1975 * chipset report, and the driver doesn't filter it.
1978 iw_sawap_ntop(const struct sockaddr * sap,
1981 const struct ether_addr ether_zero = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
1982 const struct ether_addr ether_bcast = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
1983 const struct ether_addr ether_hack = {{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }};
1984 const struct ether_addr * ether_wap = (const struct ether_addr *) sap->sa_data;
1986 if(!iw_ether_cmp(ether_wap, ðer_zero))
1987 sprintf(buf, "Not-Associated");
1989 if(!iw_ether_cmp(ether_wap, ðer_bcast))
1990 sprintf(buf, "Invalid");
1992 if(!iw_ether_cmp(ether_wap, ðer_hack))
1993 sprintf(buf, "None");
1995 iw_ether_ntop(ether_wap, buf);
1999 /*------------------------------------------------------------------*/
2001 * Input an arbitrary length MAC address and convert to binary.
2002 * Return address size.
2005 iw_mac_aton(const char * orig,
2006 unsigned char * mac,
2009 const char * p = orig;
2012 /* Loop on all bytes of the string */
2018 /* Extract one byte as two chars */
2019 count = sscanf(p, "%1X%1X", &temph, &templ);
2021 break; /* Error -> non-hex chars */
2022 /* Output two chars as one byte */
2023 templ |= temph << 4;
2024 mac[maclen++] = (unsigned char) (templ & 0xFF);
2026 /* Check end of string */
2032 iw_ether_ntop((const struct ether_addr *) mac, buf);
2033 fprintf(stderr, "iw_mac_aton(%s): %s\n", orig, buf);
2035 return(maclen); /* Normal exit */
2038 /* Check overflow */
2039 if(maclen >= macmax)
2042 fprintf(stderr, "iw_mac_aton(%s): trailing junk!\n", orig);
2045 return(0); /* Error -> overflow */
2048 /* Check separator */
2056 fprintf(stderr, "iw_mac_aton(%s): invalid ether address!\n", orig);
2062 /*------------------------------------------------------------------*/
2064 * Input an Ethernet address and convert to binary.
2067 iw_ether_aton(const char *orig, struct ether_addr *eth)
2070 maclen = iw_mac_aton(orig, (unsigned char *) eth, ETH_ALEN);
2071 if((maclen > 0) && (maclen < ETH_ALEN))
2079 /*------------------------------------------------------------------*/
2081 * Input an Internet address and convert to binary.
2084 iw_in_inet(char *name, struct sockaddr *sap)
2088 struct sockaddr_in *sain = (struct sockaddr_in *) sap;
2091 sain->sin_family = AF_INET;
2094 /* Default is special, meaning 0.0.0.0. */
2095 if (!strcmp(name, "default")) {
2096 sain->sin_addr.s_addr = INADDR_ANY;
2100 /* Try the NETWORKS database to see if this is a known network. */
2101 if ((np = getnetbyname(name)) != (struct netent *)NULL) {
2102 sain->sin_addr.s_addr = htonl(np->n_net);
2103 strcpy(name, np->n_name);
2107 /* Always use the resolver (DNS name + IP addresses) */
2108 if ((hp = gethostbyname(name)) == (struct hostent *)NULL) {
2112 memcpy((char *) &sain->sin_addr, (char *) hp->h_addr_list[0], hp->h_length);
2113 strcpy(name, hp->h_name);
2117 /*------------------------------------------------------------------*/
2119 * Input an address and convert to binary.
2122 iw_in_addr(int skfd,
2123 const char * ifname,
2125 struct sockaddr *sap)
2127 /* Check if it is a hardware or IP address */
2128 if(index(bufp, ':') == NULL)
2130 struct sockaddr if_address;
2131 struct arpreq arp_query;
2133 /* Check if we have valid interface address type */
2134 if(iw_check_if_addr_type(skfd, ifname) < 0)
2136 fprintf(stderr, "%-8.16s Interface doesn't support IP addresses\n", ifname);
2140 /* Read interface address */
2141 if(iw_in_inet(bufp, &if_address) < 0)
2143 fprintf(stderr, "Invalid interface address %s\n", bufp);
2147 /* Translate IP addresses to MAC addresses */
2148 memcpy((char *) &(arp_query.arp_pa),
2149 (char *) &if_address,
2150 sizeof(struct sockaddr));
2151 arp_query.arp_ha.sa_family = 0;
2152 arp_query.arp_flags = 0;
2153 /* The following restrict the search to the interface only */
2154 /* For old kernels which complain, just comment it... */
2155 strncpy(arp_query.arp_dev, ifname, IFNAMSIZ);
2156 if((ioctl(skfd, SIOCGARP, &arp_query) < 0) ||
2157 !(arp_query.arp_flags & ATF_COM))
2159 fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n",
2160 bufp, ifname, errno);
2164 /* Store new MAC address */
2165 memcpy((char *) sap,
2166 (char *) &(arp_query.arp_ha),
2167 sizeof(struct sockaddr));
2172 printf("IP Address %s => Hw Address = %s\n",
2173 bufp, iw_saether_ntop(sap, buf));
2177 else /* If it's an hardware address */
2179 /* Check if we have valid mac address type */
2180 if(iw_check_mac_addr_type(skfd, ifname) < 0)
2182 fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname);
2186 /* Get the hardware address */
2187 if(iw_saether_aton(bufp, sap) == 0)
2189 fprintf(stderr, "Invalid hardware address %s\n", bufp);
2197 printf("Hw Address = %s\n", iw_saether_ntop(sap, buf));
2204 /************************* MISC SUBROUTINES **************************/
2206 /* Size (in bytes) of various events */
2207 static const int priv_type_size[] = {
2208 0, /* IW_PRIV_TYPE_NONE */
2209 1, /* IW_PRIV_TYPE_BYTE */
2210 1, /* IW_PRIV_TYPE_CHAR */
2211 0, /* Not defined */
2212 sizeof(__u32), /* IW_PRIV_TYPE_INT */
2213 sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */
2214 sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */
2215 0, /* Not defined */
2218 /*------------------------------------------------------------------*/
2220 * Max size in bytes of an private argument.
2223 iw_get_priv_size(int args)
2225 int num = args & IW_PRIV_SIZE_MASK;
2226 int type = (args & IW_PRIV_TYPE_MASK) >> 12;
2228 return(num * priv_type_size[type]);
2231 /************************ EVENT SUBROUTINES ************************/
2233 * The Wireless Extension API 14 and greater define Wireless Events,
2234 * that are used for various events and scanning.
2235 * Those functions help the decoding of events, so are needed only in
2239 /* -------------------------- CONSTANTS -------------------------- */
2241 /* Type of headers we know about (basically union iwreq_data) */
2242 #define IW_HEADER_TYPE_NULL 0 /* Not available */
2243 #define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
2244 #define IW_HEADER_TYPE_UINT 4 /* __u32 */
2245 #define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
2246 #define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */
2247 #define IW_HEADER_TYPE_POINT 8 /* struct iw_point */
2248 #define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */
2249 #define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */
2251 /* Handling flags */
2252 /* Most are not implemented. I just use them as a reminder of some
2253 * cool features we might need one day ;-) */
2254 #define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
2255 /* Wrapper level flags */
2256 #define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
2257 #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
2258 #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
2259 /* SET : Omit payload from generated iwevent */
2260 #define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
2261 /* Driver level flags */
2262 #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
2264 /* ---------------------------- TYPES ---------------------------- */
2267 * Describe how a standard IOCTL looks like.
2269 struct iw_ioctl_description
2271 __u8 header_type; /* NULL, iw_point or other */
2272 __u8 token_type; /* Future */
2273 __u16 token_size; /* Granularity of payload */
2274 __u16 min_tokens; /* Min acceptable token number */
2275 __u16 max_tokens; /* Max acceptable token number */
2276 __u32 flags; /* Special handling of the request */
2279 /* -------------------------- VARIABLES -------------------------- */
2282 * Meta-data about all the standard Wireless Extension request we
2285 static const struct iw_ioctl_description standard_ioctl_descr[] = {
2286 [SIOCSIWCOMMIT - SIOCIWFIRST] = {
2287 .header_type = IW_HEADER_TYPE_NULL,
2289 [SIOCGIWNAME - SIOCIWFIRST] = {
2290 .header_type = IW_HEADER_TYPE_CHAR,
2291 .flags = IW_DESCR_FLAG_DUMP,
2293 [SIOCSIWNWID - SIOCIWFIRST] = {
2294 .header_type = IW_HEADER_TYPE_PARAM,
2295 .flags = IW_DESCR_FLAG_EVENT,
2297 [SIOCGIWNWID - SIOCIWFIRST] = {
2298 .header_type = IW_HEADER_TYPE_PARAM,
2299 .flags = IW_DESCR_FLAG_DUMP,
2301 [SIOCSIWFREQ - SIOCIWFIRST] = {
2302 .header_type = IW_HEADER_TYPE_FREQ,
2303 .flags = IW_DESCR_FLAG_EVENT,
2305 [SIOCGIWFREQ - SIOCIWFIRST] = {
2306 .header_type = IW_HEADER_TYPE_FREQ,
2307 .flags = IW_DESCR_FLAG_DUMP,
2309 [SIOCSIWMODE - SIOCIWFIRST] = {
2310 .header_type = IW_HEADER_TYPE_UINT,
2311 .flags = IW_DESCR_FLAG_EVENT,
2313 [SIOCGIWMODE - SIOCIWFIRST] = {
2314 .header_type = IW_HEADER_TYPE_UINT,
2315 .flags = IW_DESCR_FLAG_DUMP,
2317 [SIOCSIWSENS - SIOCIWFIRST] = {
2318 .header_type = IW_HEADER_TYPE_PARAM,
2320 [SIOCGIWSENS - SIOCIWFIRST] = {
2321 .header_type = IW_HEADER_TYPE_PARAM,
2323 [SIOCSIWRANGE - SIOCIWFIRST] = {
2324 .header_type = IW_HEADER_TYPE_NULL,
2326 [SIOCGIWRANGE - SIOCIWFIRST] = {
2327 .header_type = IW_HEADER_TYPE_POINT,
2329 .max_tokens = sizeof(struct iw_range),
2330 .flags = IW_DESCR_FLAG_DUMP,
2332 [SIOCSIWPRIV - SIOCIWFIRST] = {
2333 .header_type = IW_HEADER_TYPE_NULL,
2335 [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */
2336 .header_type = IW_HEADER_TYPE_NULL,
2338 [SIOCSIWSTATS - SIOCIWFIRST] = {
2339 .header_type = IW_HEADER_TYPE_NULL,
2341 [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */
2342 .header_type = IW_HEADER_TYPE_NULL,
2343 .flags = IW_DESCR_FLAG_DUMP,
2345 [SIOCSIWSPY - SIOCIWFIRST] = {
2346 .header_type = IW_HEADER_TYPE_POINT,
2347 .token_size = sizeof(struct sockaddr),
2348 .max_tokens = IW_MAX_SPY,
2350 [SIOCGIWSPY - SIOCIWFIRST] = {
2351 .header_type = IW_HEADER_TYPE_POINT,
2352 .token_size = sizeof(struct sockaddr) +
2353 sizeof(struct iw_quality),
2354 .max_tokens = IW_MAX_SPY,
2356 [SIOCSIWTHRSPY - SIOCIWFIRST] = {
2357 .header_type = IW_HEADER_TYPE_POINT,
2358 .token_size = sizeof(struct iw_thrspy),
2362 [SIOCGIWTHRSPY - SIOCIWFIRST] = {
2363 .header_type = IW_HEADER_TYPE_POINT,
2364 .token_size = sizeof(struct iw_thrspy),
2368 [SIOCSIWAP - SIOCIWFIRST] = {
2369 .header_type = IW_HEADER_TYPE_ADDR,
2371 [SIOCGIWAP - SIOCIWFIRST] = {
2372 .header_type = IW_HEADER_TYPE_ADDR,
2373 .flags = IW_DESCR_FLAG_DUMP,
2375 [SIOCSIWMLME - SIOCIWFIRST] = {
2376 .header_type = IW_HEADER_TYPE_POINT,
2378 .min_tokens = sizeof(struct iw_mlme),
2379 .max_tokens = sizeof(struct iw_mlme),
2381 [SIOCGIWAPLIST - SIOCIWFIRST] = {
2382 .header_type = IW_HEADER_TYPE_POINT,
2383 .token_size = sizeof(struct sockaddr) +
2384 sizeof(struct iw_quality),
2385 .max_tokens = IW_MAX_AP,
2386 .flags = IW_DESCR_FLAG_NOMAX,
2388 [SIOCSIWSCAN - SIOCIWFIRST] = {
2389 .header_type = IW_HEADER_TYPE_POINT,
2392 .max_tokens = sizeof(struct iw_scan_req),
2394 [SIOCGIWSCAN - SIOCIWFIRST] = {
2395 .header_type = IW_HEADER_TYPE_POINT,
2397 .max_tokens = IW_SCAN_MAX_DATA,
2398 .flags = IW_DESCR_FLAG_NOMAX,
2400 [SIOCSIWESSID - SIOCIWFIRST] = {
2401 .header_type = IW_HEADER_TYPE_POINT,
2403 .max_tokens = IW_ESSID_MAX_SIZE + 1,
2404 .flags = IW_DESCR_FLAG_EVENT,
2406 [SIOCGIWESSID - SIOCIWFIRST] = {
2407 .header_type = IW_HEADER_TYPE_POINT,
2409 .max_tokens = IW_ESSID_MAX_SIZE + 1,
2410 .flags = IW_DESCR_FLAG_DUMP,
2412 [SIOCSIWNICKN - SIOCIWFIRST] = {
2413 .header_type = IW_HEADER_TYPE_POINT,
2415 .max_tokens = IW_ESSID_MAX_SIZE + 1,
2417 [SIOCGIWNICKN - SIOCIWFIRST] = {
2418 .header_type = IW_HEADER_TYPE_POINT,
2420 .max_tokens = IW_ESSID_MAX_SIZE + 1,
2422 [SIOCSIWRATE - SIOCIWFIRST] = {
2423 .header_type = IW_HEADER_TYPE_PARAM,
2425 [SIOCGIWRATE - SIOCIWFIRST] = {
2426 .header_type = IW_HEADER_TYPE_PARAM,
2428 [SIOCSIWRTS - SIOCIWFIRST] = {
2429 .header_type = IW_HEADER_TYPE_PARAM,
2431 [SIOCGIWRTS - SIOCIWFIRST] = {
2432 .header_type = IW_HEADER_TYPE_PARAM,
2434 [SIOCSIWFRAG - SIOCIWFIRST] = {
2435 .header_type = IW_HEADER_TYPE_PARAM,
2437 [SIOCGIWFRAG - SIOCIWFIRST] = {
2438 .header_type = IW_HEADER_TYPE_PARAM,
2440 [SIOCSIWTXPOW - SIOCIWFIRST] = {
2441 .header_type = IW_HEADER_TYPE_PARAM,
2443 [SIOCGIWTXPOW - SIOCIWFIRST] = {
2444 .header_type = IW_HEADER_TYPE_PARAM,
2446 [SIOCSIWRETRY - SIOCIWFIRST] = {
2447 .header_type = IW_HEADER_TYPE_PARAM,
2449 [SIOCGIWRETRY - SIOCIWFIRST] = {
2450 .header_type = IW_HEADER_TYPE_PARAM,
2452 [SIOCSIWENCODE - SIOCIWFIRST] = {
2453 .header_type = IW_HEADER_TYPE_POINT,
2455 .max_tokens = IW_ENCODING_TOKEN_MAX,
2456 .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
2458 [SIOCGIWENCODE - SIOCIWFIRST] = {
2459 .header_type = IW_HEADER_TYPE_POINT,
2461 .max_tokens = IW_ENCODING_TOKEN_MAX,
2462 .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
2464 [SIOCSIWPOWER - SIOCIWFIRST] = {
2465 .header_type = IW_HEADER_TYPE_PARAM,
2467 [SIOCGIWPOWER - SIOCIWFIRST] = {
2468 .header_type = IW_HEADER_TYPE_PARAM,
2470 [SIOCSIWGENIE - SIOCIWFIRST] = {
2471 .header_type = IW_HEADER_TYPE_POINT,
2473 .max_tokens = IW_GENERIC_IE_MAX,
2475 [SIOCGIWGENIE - SIOCIWFIRST] = {
2476 .header_type = IW_HEADER_TYPE_POINT,
2478 .max_tokens = IW_GENERIC_IE_MAX,
2480 [SIOCSIWAUTH - SIOCIWFIRST] = {
2481 .header_type = IW_HEADER_TYPE_PARAM,
2483 [SIOCGIWAUTH - SIOCIWFIRST] = {
2484 .header_type = IW_HEADER_TYPE_PARAM,
2486 [SIOCSIWENCODEEXT - SIOCIWFIRST] = {
2487 .header_type = IW_HEADER_TYPE_POINT,
2489 .min_tokens = sizeof(struct iw_encode_ext),
2490 .max_tokens = sizeof(struct iw_encode_ext) +
2491 IW_ENCODING_TOKEN_MAX,
2493 [SIOCGIWENCODEEXT - SIOCIWFIRST] = {
2494 .header_type = IW_HEADER_TYPE_POINT,
2496 .min_tokens = sizeof(struct iw_encode_ext),
2497 .max_tokens = sizeof(struct iw_encode_ext) +
2498 IW_ENCODING_TOKEN_MAX,
2500 [SIOCSIWPMKSA - SIOCIWFIRST] = {
2501 .header_type = IW_HEADER_TYPE_POINT,
2503 .min_tokens = sizeof(struct iw_pmksa),
2504 .max_tokens = sizeof(struct iw_pmksa),
2507 static const unsigned int standard_ioctl_num = (sizeof(standard_ioctl_descr) /
2508 sizeof(struct iw_ioctl_description));
2511 * Meta-data about all the additional standard Wireless Extension events
2514 static const struct iw_ioctl_description standard_event_descr[] = {
2515 [IWEVTXDROP - IWEVFIRST] = {
2516 .header_type = IW_HEADER_TYPE_ADDR,
2518 [IWEVQUAL - IWEVFIRST] = {
2519 .header_type = IW_HEADER_TYPE_QUAL,
2521 [IWEVCUSTOM - IWEVFIRST] = {
2522 .header_type = IW_HEADER_TYPE_POINT,
2524 .max_tokens = IW_CUSTOM_MAX,
2526 [IWEVREGISTERED - IWEVFIRST] = {
2527 .header_type = IW_HEADER_TYPE_ADDR,
2529 [IWEVEXPIRED - IWEVFIRST] = {
2530 .header_type = IW_HEADER_TYPE_ADDR,
2532 [IWEVGENIE - IWEVFIRST] = {
2533 .header_type = IW_HEADER_TYPE_POINT,
2535 .max_tokens = IW_GENERIC_IE_MAX,
2537 [IWEVMICHAELMICFAILURE - IWEVFIRST] = {
2538 .header_type = IW_HEADER_TYPE_POINT,
2540 .max_tokens = sizeof(struct iw_michaelmicfailure),
2542 [IWEVASSOCREQIE - IWEVFIRST] = {
2543 .header_type = IW_HEADER_TYPE_POINT,
2545 .max_tokens = IW_GENERIC_IE_MAX,
2547 [IWEVASSOCRESPIE - IWEVFIRST] = {
2548 .header_type = IW_HEADER_TYPE_POINT,
2550 .max_tokens = IW_GENERIC_IE_MAX,
2552 [IWEVPMKIDCAND - IWEVFIRST] = {
2553 .header_type = IW_HEADER_TYPE_POINT,
2555 .max_tokens = sizeof(struct iw_pmkid_cand),
2558 static const unsigned int standard_event_num = (sizeof(standard_event_descr) /
2559 sizeof(struct iw_ioctl_description));
2561 /* Size (in bytes) of various events */
2562 static const int event_type_size[] = {
2563 IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */
2565 IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
2567 IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */
2568 IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */
2569 IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */
2571 IW_EV_POINT_LEN, /* Without variable payload */
2572 IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */
2573 IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
2576 /*------------------------------------------------------------------*/
2578 * Initialise the struct stream_descr so that we can extract
2579 * individual events from the event stream.
2582 iw_init_event_stream(struct stream_descr * stream, /* Stream of events */
2587 memset((char *) stream, '\0', sizeof(struct stream_descr));
2590 stream->current = data;
2591 stream->end = data + len;
2594 /*------------------------------------------------------------------*/
2596 * Extract the next event from the event stream.
2599 iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
2600 struct iw_event * iwe, /* Extracted event */
2603 const struct iw_ioctl_description * descr = NULL;
2605 unsigned int event_len = 1; /* Invalid */
2607 /* Don't "optimise" the following variable, it will crash */
2608 unsigned cmd_index; /* *MUST* be unsigned */
2610 /* Unused for now. Will be later on... */
2611 we_version = we_version;
2613 /* Check for end of stream */
2614 if((stream->current + IW_EV_LCP_LEN) > stream->end)
2618 printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n",
2619 stream->current, stream->value, stream->end);
2622 /* Extract the event header (to get the event id).
2623 * Note : the event may be unaligned, therefore copy... */
2624 memcpy((char *) iwe, stream->current, IW_EV_LCP_LEN);
2627 printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n",
2628 iwe->cmd, iwe->len);
2631 /* Check invalid events */
2632 if(iwe->len <= IW_EV_LCP_LEN)
2635 /* Get the type and length of that event */
2636 if(iwe->cmd <= SIOCIWLAST)
2638 cmd_index = iwe->cmd - SIOCIWFIRST;
2639 if(cmd_index < standard_ioctl_num)
2640 descr = &(standard_ioctl_descr[cmd_index]);
2644 cmd_index = iwe->cmd - IWEVFIRST;
2645 if(cmd_index < standard_event_num)
2646 descr = &(standard_event_descr[cmd_index]);
2649 event_type = descr->header_type;
2650 /* Unknown events -> event_type=0 => IW_EV_LCP_LEN */
2651 event_len = event_type_size[event_type];
2652 /* Fixup for earlier version of WE */
2653 if((we_version <= 18) && (event_type == IW_HEADER_TYPE_POINT))
2654 event_len += IW_EV_POINT_OFF;
2656 /* Check if we know about this event */
2657 if(event_len <= IW_EV_LCP_LEN)
2659 /* Skip to next event */
2660 stream->current += iwe->len;
2663 event_len -= IW_EV_LCP_LEN;
2665 /* Set pointer on data */
2666 if(stream->value != NULL)
2667 pointer = stream->value; /* Next value in event */
2669 pointer = stream->current + IW_EV_LCP_LEN; /* First value in event */
2672 printf("DBG - event_type = %d, event_len = %d, pointer = %p\n",
2673 event_type, event_len, pointer);
2676 /* Copy the rest of the event (at least, fixed part) */
2677 if((pointer + event_len) > stream->end)
2679 /* Go to next event */
2680 stream->current += iwe->len;
2683 /* Fixup for WE-19 and later : pointer no longer in the stream */
2684 if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))
2685 memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
2686 pointer, event_len);
2688 memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
2690 /* Skip event in the stream */
2691 pointer += event_len;
2693 /* Special processing for iw_point events */
2694 if(event_type == IW_HEADER_TYPE_POINT)
2696 /* Check the length of the payload */
2697 unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_LEN);
2700 /* Set pointer on variable part (warning : non aligned) */
2701 iwe->u.data.pointer = pointer;
2703 /* Check that we have a descriptor for the command */
2705 /* Can't check payload -> unsafe... */
2706 iwe->u.data.pointer = NULL; /* Discard paylod */
2709 /* Those checks are actually pretty hard to trigger,
2710 * because of the checks done in the kernel... */
2712 /* Discard bogus events which advertise more tokens than
2713 * what they carry... */
2714 unsigned int token_len = iwe->u.data.length * descr->token_size;
2715 if(token_len > extra_len)
2716 iwe->u.data.pointer = NULL; /* Discard paylod */
2717 /* Check that the advertised token size is not going to
2718 * produce buffer overflow to our caller... */
2719 if((iwe->u.data.length > descr->max_tokens)
2720 && !(descr->flags & IW_DESCR_FLAG_NOMAX))
2721 iwe->u.data.pointer = NULL; /* Discard paylod */
2722 /* Same for underflows... */
2723 if(iwe->u.data.length < descr->min_tokens)
2724 iwe->u.data.pointer = NULL; /* Discard paylod */
2726 printf("DBG - extra_len = %d, token_len = %d, token = %d, max = %d, min = %d\n",
2727 extra_len, token_len, iwe->u.data.length, descr->max_tokens, descr->min_tokens);
2733 iwe->u.data.pointer = NULL;
2735 /* Go to next event */
2736 stream->current += iwe->len;
2740 /* Is there more value in the event ? */
2741 if((pointer + event_len) <= (stream->current + iwe->len))
2742 /* Go to next value */
2743 stream->value = pointer;
2746 /* Go to next event */
2747 stream->value = NULL;
2748 stream->current += iwe->len;
2754 /*********************** SCANNING SUBROUTINES ***********************/
2756 * The Wireless Extension API 14 and greater define Wireless Scanning.
2757 * The normal API is complex, this is an easy API that return
2758 * a subset of the scanning results. This should be enough for most
2759 * applications that want to use Scanning.
2760 * If you want to have use the full/normal API, check iwlist.c...
2762 * Precaution when using scanning :
2763 * The scanning operation disable normal network traffic, and therefore
2764 * you should not abuse of scan.
2765 * The scan need to check the presence of network on other frequencies.
2766 * While you are checking those other frequencies, you can *NOT* be on
2767 * your normal frequency to listen to normal traffic in the cell.
2768 * You need typically in the order of one second to actively probe all
2769 * 802.11b channels (do the maths). Some cards may do that in background,
2770 * to reply to scan commands faster, but they still have to do it.
2771 * Leaving the cell for such an extended period of time is pretty bad.
2772 * Any kind of streaming/low latency traffic will be impacted, and the
2773 * user will perceive it (easily checked with telnet). People trying to
2774 * send traffic to you will retry packets and waste bandwidth. Some
2775 * applications may be sensitive to those packet losses in weird ways,
2776 * and tracing those weird behavior back to scanning may take time.
2777 * If you are in ad-hoc mode, if two nodes scan approx at the same
2778 * time, they won't see each other, which may create associations issues.
2779 * For those reasons, the scanning activity should be limited to
2780 * what's really needed, and continuous scanning is a bad idea.
2784 /*------------------------------------------------------------------*/
2786 * Process/store one element from the scanning results in wireless_scan
2788 static inline struct wireless_scan *
2789 iw_process_scanning_token(struct iw_event * event,
2790 struct wireless_scan * wscan)
2792 struct wireless_scan * oldwscan;
2794 /* Now, let's decode the event */
2798 /* New cell description. Allocate new cell descriptor, zero it. */
2800 wscan = (struct wireless_scan *) malloc(sizeof(struct wireless_scan));
2803 /* Link at the end of the list */
2804 if(oldwscan != NULL)
2805 oldwscan->next = wscan;
2808 bzero(wscan, sizeof(struct wireless_scan));
2810 /* Save cell identifier */
2811 wscan->has_ap_addr = 1;
2812 memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof (sockaddr));
2815 wscan->b.has_nwid = 1;
2816 memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam));
2819 wscan->b.has_freq = 1;
2820 wscan->b.freq = iw_freq2float(&(event->u.freq));
2821 wscan->b.freq_flags = event->u.freq.flags;
2824 wscan->b.mode = event->u.mode;
2825 if((wscan->b.mode < IW_NUM_OPER_MODE) && (wscan->b.mode >= 0))
2826 wscan->b.has_mode = 1;
2829 wscan->b.has_essid = 1;
2830 wscan->b.essid_on = event->u.data.flags;
2831 memset(wscan->b.essid, '\0', IW_ESSID_MAX_SIZE+1);
2832 if((event->u.essid.pointer) && (event->u.essid.length))
2833 memcpy(wscan->b.essid, event->u.essid.pointer, event->u.essid.length);
2836 wscan->b.has_key = 1;
2837 wscan->b.key_size = event->u.data.length;
2838 wscan->b.key_flags = event->u.data.flags;
2839 if(event->u.data.pointer)
2840 memcpy(wscan->b.key, event->u.essid.pointer, event->u.data.length);
2842 wscan->b.key_flags |= IW_ENCODE_NOKEY;
2845 /* We don't get complete stats, only qual */
2846 wscan->has_stats = 1;
2847 memcpy(&wscan->stats.qual, &event->u.qual, sizeof(struct iw_quality));
2850 /* Scan may return a list of bitrates. Should we really bother with
2851 * an array of bitrates ? Or only the maximum bitrate ? Jean II */
2853 /* How can we deal with those sanely ? Jean II */
2856 } /* switch(event->cmd) */
2861 /*------------------------------------------------------------------*/
2863 * Initiate the scan procedure, and process results.
2864 * This is a non-blocking procedure and it will return each time
2865 * it would block, returning the amount of time the caller should wait
2866 * before calling again.
2867 * Return -1 for error, delay to wait for (in ms), or 0 for success.
2868 * Error code is in errno
2871 iw_process_scan(int skfd,
2874 wireless_scan_head * context)
2877 unsigned char * buffer = NULL; /* Results */
2878 int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
2879 unsigned char * newbuf;
2881 /* Don't waste too much time on interfaces (150 * 100 = 15s) */
2883 if(context->retry > 150)
2889 /* If we have not yet initiated scanning on the interface */
2890 if(context->retry == 1)
2893 wrq.u.data.pointer = NULL; /* Later */
2894 wrq.u.data.flags = 0;
2895 wrq.u.data.length = 0;
2896 if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
2898 /* Success : now, just wait for event or results */
2899 return(250); /* Wait 250 ms */
2903 /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
2904 newbuf = realloc(buffer, buflen);
2907 /* man says : If realloc() fails the original block is left untouched */
2915 /* Try to read the results */
2916 wrq.u.data.pointer = buffer;
2917 wrq.u.data.flags = 0;
2918 wrq.u.data.length = buflen;
2919 if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
2921 /* Check if buffer was too small (WE-17 only) */
2922 if((errno == E2BIG) && (we_version > 16))
2924 /* Some driver may return very large scan results, either
2925 * because there are many cells, or because they have many
2926 * large elements in cells (like IWEVCUSTOM). Most will
2927 * only need the regular sized buffer. We now use a dynamic
2928 * allocation of the buffer to satisfy everybody. Of course,
2929 * as we don't know in advance the size of the array, we try
2930 * various increasing sizes. Jean II */
2932 /* Check if the driver gave us any hints. */
2933 if(wrq.u.data.length > buflen)
2934 buflen = wrq.u.data.length;
2942 /* Check if results not available yet */
2946 /* Wait for only 100ms from now on */
2947 return(100); /* Wait 100 ms */
2951 /* Bad error, please don't come back... */
2955 /* We have the results, process them */
2956 if(wrq.u.data.length)
2958 struct iw_event iwe;
2959 struct stream_descr stream;
2960 struct wireless_scan * wscan = NULL;
2963 /* Debugging code. In theory useless, because it's debugged ;-) */
2965 printf("Scan result [%02X", buffer[0]);
2966 for(i = 1; i < wrq.u.data.length; i++)
2967 printf(":%02X", buffer[i]);
2972 iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
2973 /* This is dangerous, we may leak user data... */
2974 context->result = NULL;
2976 /* Look every token */
2979 /* Extract an event and print it */
2980 ret = iw_extract_event_stream(&stream, &iwe, we_version);
2983 /* Convert to wireless_scan struct */
2984 wscan = iw_process_scanning_token(&iwe, wscan);
2985 /* Check problems */
2992 /* Save head of list */
2993 if(context->result == NULL)
2994 context->result = wscan;
3000 /* Done with this interface - return success */
3005 /*------------------------------------------------------------------*/
3007 * Perform a wireless scan on the specified interface.
3008 * This is a blocking procedure and it will when the scan is completed
3009 * or when an error occur.
3011 * The scan results are given in a linked list of wireless_scan objects.
3012 * The caller *must* free the result himself (by walking the list).
3013 * If there is an error, -1 is returned and the error code is available
3016 * The parameter we_version can be extracted from the range structure
3017 * (range.we_version_compiled - see iw_get_range_info()), or using
3018 * iw_get_kernel_we_version(). For performance reason, you should
3019 * cache this parameter when possible rather than querying it every time.
3021 * Return -1 for error and 0 for success.
3027 wireless_scan_head * context)
3029 int delay; /* in ms */
3031 /* Clean up context. Potential memory leak if(context.result != NULL) */
3032 context->result = NULL;
3035 /* Wait until we get results or error */
3038 /* Try to get scan results */
3039 delay = iw_process_scan(skfd, ifname, we_version, context);
3041 /* Check termination */
3046 usleep(delay * 1000);
3049 /* End - return -1 or 0 */