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';
183 /*------------------------------------------------------------------*/
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
192 iw_enum_devices(int skfd,
203 #ifndef IW_RESTRIC_ENUM
204 /* Check if /proc/net/wireless is available */
205 fh = fopen(PROC_NET_DEV, "r");
207 /* Check if /proc/net/wireless is available */
208 fh = fopen(PROC_NET_WIRELESS, "r");
213 /* Success : use data from /proc/net/wireless */
215 /* Eat 2 lines of header */
216 fgets(buff, sizeof(buff), fh);
217 fgets(buff, sizeof(buff), fh);
219 /* Read each device line */
220 while(fgets(buff, sizeof(buff), fh))
222 char name[IFNAMSIZ + 1];
225 /* Extract interface name */
226 s = iw_get_ifname(name, sizeof(name), buff);
229 /* Failed to parse, complain and continue */
230 #ifndef IW_RESTRIC_ENUM
231 fprintf(stderr, "Cannot parse " PROC_NET_DEV "\n");
233 fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
236 /* Got it, print info about this interface */
237 (*fn)(skfd, name, args, count);
244 /* Get list of configured devices using "traditional" way */
245 ifc.ifc_len = sizeof(buff);
247 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
249 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
255 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
256 (*fn)(skfd, ifr->ifr_name, args, count);
260 /*********************** WIRELESS SUBROUTINES ************************/
262 /*------------------------------------------------------------------*/
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...
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).
275 iw_get_kernel_we_version(void)
282 /* Check if /proc/net/wireless is available */
283 fh = fopen(PROC_NET_WIRELESS, "r");
287 fprintf(stderr, "Cannot read " PROC_NET_WIRELESS "\n");
291 /* Read the first line of buffer */
292 fgets(buff, sizeof(buff), fh);
294 if(strstr(buff, "| WE") == NULL)
296 /* Prior to WE16, so explicit version not present */
299 if(strstr(buff, "| Missed") == NULL)
307 /* Read the second line of buffer */
308 fgets(buff, sizeof(buff), fh);
310 /* Get to the last separator, to get the version */
311 p = strrchr(buff, '|');
312 if((p == NULL) || (sscanf(p + 1, "%d", &v) != 1))
314 fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
323 /*------------------------------------------------------------------*/
325 * Print the WE versions of the interface.
328 print_iface_version_info(int skfd,
330 char * args[], /* Command line args */
331 int count) /* Args count */
334 char buffer[sizeof(iwrange) * 2]; /* Large enough */
335 struct iw_range * range;
337 /* Avoid "Unused parameter" warning */
338 args = args; count = count;
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)
346 memset(buffer, 0, sizeof(buffer));
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)
353 /* Interface support WE (see above), but not IWRANGE */
354 fprintf(stderr, "%-8.16s Driver has no Wireless Extension version information.\n\n", ifname);
358 /* Copy stuff at the right place, ignore extra */
359 range = (struct iw_range *) buffer;
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)
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);
373 fprintf(stderr, "%-8.16s Wireless Extension version too old.\n\n",
381 /*------------------------------------------------------------------*/
383 * Print the WE versions of the tools.
386 iw_print_version_info(const char * toolname)
388 int skfd; /* generic raw socket desc. */
389 int we_kernel_version;
391 /* Create a channel to the NET kernel. */
392 if((skfd = iw_sockets_open()) < 0)
398 /* Information about the tools themselves */
400 printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION);
401 printf(" Compatible with Wireless Extension v11 to v%d.\n\n",
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",
411 /* Version for each device */
412 iw_enum_devices(skfd, &print_iface_version_info, NULL, 0);
414 iw_sockets_close(skfd);
419 /*------------------------------------------------------------------*/
421 * Get the range information out of the driver
424 iw_get_range_info(int skfd,
429 char buffer[sizeof(iwrange) * 2]; /* Large enough */
430 union iw_range_raw * range_raw;
433 bzero(buffer, sizeof(buffer));
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)
441 /* Point to the buffer */
442 range_raw = (union iw_range_raw *) buffer;
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)
448 /* That's v10 or earlier. Ouch ! Let's make a guess...*/
449 range_raw->range.we_version_compiled = 9;
452 /* Check how it needs to be processed */
453 if(range_raw->range.we_version_compiled > 15)
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));
461 /* Zero unknown fields */
462 bzero((char *) range, sizeof(struct iw_range));
464 /* Initial part unmoved */
465 memcpy((char *) range,
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));
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
501 if(!iw_ignore_version)
503 /* We don't like very old version (unfortunately kernel 2.2.X) */
504 if(range->we_version_compiled <= 10)
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");
511 /* We don't like future versions of WE, because we can't cope with
513 if(range->we_version_compiled > WE_VERSION)
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");
520 /* Driver version verification */
521 if((range->we_version_compiled > 10) &&
522 (range->we_version_compiled < range->we_version_source))
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");
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 */
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;
541 /*------------------------------------------------------------------*/
543 * Get information about what private ioctls are supported by the driver
545 * Note : there is one danger using this function. If it return 0, you
546 * still need to free() the buffer. Beware.
549 iw_get_priv_info(int skfd,
554 iwprivargs * priv = NULL; /* Not allocated yet */
555 int maxpriv = 16; /* Minimum for compatibility WE<13 */
556 iwprivargs * newpriv;
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
565 /* (Re)allocate the buffer */
566 newpriv = realloc(priv, maxpriv * sizeof(priv[0]));
569 fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
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)
580 /* Success. Pass the buffer by pointer */
582 /* Return the number of ioctls */
583 return(wrq.u.data.length);
586 /* Only E2BIG means the buffer was too small, abort on other errors */
589 /* Most likely "not supported". Don't barf. */
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;
600 while(maxpriv < 1000);
610 /*------------------------------------------------------------------*/
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...
619 iw_get_basic_config(int skfd,
621 wireless_config * info)
625 memset((char *) info, 0, sizeof(struct wireless_config));
627 /* Get wireless name */
628 if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
629 /* If no wireless name : no wireless extensions */
633 strncpy(info->name, wrq.u.name, IFNAMSIZ);
634 info->name[IFNAMSIZ] = '\0';
638 if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0)
641 memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
644 /* Get frequency / channel */
645 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
648 info->freq = iw_freq2float(&(wrq.u.freq));
649 info->freq_flags = wrq.u.freq.flags;
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)
659 info->key_size = wrq.u.data.length;
660 info->key_flags = wrq.u.data.flags;
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)
670 info->essid_on = wrq.u.data.flags;
673 /* Get operation mode */
674 if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
676 info->mode = wrq.u.mode;
677 if((info->mode < IW_NUM_OPER_MODE) && (info->mode >= 0))
684 /*------------------------------------------------------------------*/
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...
692 iw_set_basic_config(int skfd,
694 wireless_config * info)
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 */
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).
710 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
711 wrq.u.mode = info->mode;
713 if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
715 fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
720 /* Set frequency / channel */
723 iw_float2freq(info->freq, &(wrq.u.freq));
725 if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
727 fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
732 /* Set encryption information */
735 int flags = info->key_flags;
737 /* Check if there is a key index */
738 if((flags & IW_ENCODE_INDEX) > 0)
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;
745 if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
747 fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
748 errno, strerror(errno));
753 /* Mask out index to minimise probability of reject when setting key */
754 flags = flags & (~IW_ENCODE_INDEX);
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;
761 /* Compatibility with WE<13 */
762 if(flags & IW_ENCODE_NOKEY)
763 wrq.u.data.pointer = NULL;
765 if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
767 fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
768 errno, strerror(errno));
773 /* Set Network ID, if available (this is for non-802.11 cards) */
776 memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam));
777 wrq.u.nwid.fixed = 1; /* Hum... When in Rome... */
779 if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
781 fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
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.
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;
797 if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
799 fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
807 /*********************** PROTOCOL SUBROUTINES ***********************/
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 :-(
814 /*------------------------------------------------------------------*/
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
824 iw_protocol_compare(const char * protocol1,
825 const char * protocol2)
827 const char * dot11 = "IEEE 802.11";
828 const char * dot11_ds = "Dbg";
829 const char * dot11_5g = "a";
831 /* If the strings are the same -> easy */
832 if(!strncmp(protocol1, protocol2, IFNAMSIZ))
835 /* Are we dealing with one of the 802.11 variant ? */
836 if( (!strncmp(protocol1, dot11, strlen(dot11))) &&
837 (!strncmp(protocol2, dot11, strlen(dot11))) )
839 const char * sub1 = protocol1 + strlen(dot11);
840 const char * sub2 = protocol2 + strlen(dot11);
847 /* Check if we find the magic letters telling it's DS compatible */
848 for(i = 0; i < strlen(dot11_ds); i++)
850 if(strchr(sub1, dot11_ds[i]) != NULL)
852 if(strchr(sub2, dot11_ds[i]) != NULL)
858 /* Check if we find the magic letters telling it's 5GHz compatible */
859 for(i = 0; i < strlen(dot11_5g); i++)
861 if(strchr(sub1, dot11_5g[i]) != NULL)
863 if(strchr(sub2, dot11_5g[i]) != NULL)
873 /********************** FREQUENCY SUBROUTINES ***********************/
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
880 * FIXME : check negative mantissa and exponent
883 /*------------------------------------------------------------------*/
885 * Convert a floating point the our internal representation of
887 * The kernel doesn't want to hear about floating point, so we use
888 * this custom format instead.
891 iw_float2freq(double in,
895 /* Version without libm : slower */
903 #else /* WE_NOLIBM */
904 /* Version with libm : faster */
905 out->e = (short) (floor(log10(in)));
908 out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100;
916 #endif /* WE_NOLIBM */
919 /*------------------------------------------------------------------*/
921 * Convert our internal representation of frequencies to a floating point.
924 iw_freq2float(const iwfreq * in)
927 /* Version without libm : slower */
929 double res = (double) in->m;
930 for(i = 0; i < in->e; i++)
933 #else /* WE_NOLIBM */
934 /* Version with libm : faster */
935 return ((double) in->m) * pow(10,in->e);
936 #endif /* WE_NOLIBM */
939 /*------------------------------------------------------------------*/
941 * Output a frequency with proper scaling
944 iw_print_freq_value(char * buffer,
949 snprintf(buffer, buflen, "%g", freq);
973 snprintf(buffer, buflen, "%g %cHz", freq / divisor, scale);
977 /*------------------------------------------------------------------*/
979 * Output a frequency with proper scaling
982 iw_print_freq(char * buffer,
988 char sep = ((freq_flags & IW_FREQ_FIXED) ? '=' : ':');
991 /* Print the frequency/channel value */
992 iw_print_freq_value(vbuf, sizeof(vbuf), freq);
994 /* Check if channel only */
996 snprintf(buffer, buflen, "Channel%c%s", sep, vbuf);
999 /* Frequency. Check if we have a channel as well */
1001 snprintf(buffer, buflen, "Frequency%c%s (Channel %d)",
1002 sep, vbuf, channel);
1004 snprintf(buffer, buflen, "Frequency%c%s", sep, vbuf);
1008 /*------------------------------------------------------------------*/
1010 * Convert a frequency to a channel (negative -> error)
1013 iw_freq_to_channel(double freq,
1014 const struct iw_range * range)
1019 /* Check if it's a frequency or not already a channel */
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++)
1027 ref_freq = iw_freq2float(&(range->freq[k]));
1028 if(freq == ref_freq)
1029 return(range->freq[k].i);
1035 /*------------------------------------------------------------------*/
1037 * Convert a channel to a frequency (negative -> error)
1038 * Return the channel on success
1041 iw_channel_to_freq(int channel,
1043 const struct iw_range * range)
1048 /* Check if the driver support only channels or if it has frequencies */
1049 for(k = 0; k < range->num_frequency; k++)
1051 if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO))
1057 /* Find the correct frequency in the list */
1058 for(k = 0; k < range->num_frequency; k++)
1060 if(range->freq[k].i == channel)
1062 *pfreq = iw_freq2float(&(range->freq[k]));
1070 /*********************** BITRATE SUBROUTINES ***********************/
1072 /*------------------------------------------------------------------*/
1074 * Output a bitrate with proper scaling
1077 iw_print_bitrate(char * buffer,
1081 double rate = bitrate;
1103 snprintf(buffer, buflen, "%g %cb/s", rate / divisor, scale);
1106 /************************ POWER SUBROUTINES *************************/
1108 /*------------------------------------------------------------------*/
1110 * Convert a value in dBm to a value in milliWatt.
1113 iw_dbm2mwatt(int in)
1116 /* Version without libm : slower */
1122 /* Split integral and floating part to avoid accumulating rounding errors */
1123 for(k = 0; k < ip; k++)
1125 for(k = 0; k < fp; k++)
1128 #else /* WE_NOLIBM */
1129 /* Version with libm : faster */
1130 return((int) (floor(pow(10.0, (((double) in) / 10.0)))));
1131 #endif /* WE_NOLIBM */
1134 /*------------------------------------------------------------------*/
1136 * Convert a value in milliWatt to a value in dBm.
1139 iw_mwatt2dbm(int in)
1142 /* Version without libm : slower */
1143 double fin = (double) in;
1146 /* Split integral and floating part to avoid accumulating rounding errors */
1152 while(fin > 1.000001) /* Eliminate rounding errors, take ceil */
1158 #else /* WE_NOLIBM */
1159 /* Version with libm : faster */
1160 return((int) (ceil(10.0 * log10((double) in))));
1161 #endif /* WE_NOLIBM */
1164 /*------------------------------------------------------------------*/
1166 * Output a txpower with proper conversion
1169 iw_print_txpower(char * buffer,
1171 struct iw_param * txpower)
1175 /* Check if disabled */
1176 if(txpower->disabled)
1178 snprintf(buffer, buflen, "off");
1182 /* Check for relative values */
1183 if(txpower->flags & IW_TXPOW_RELATIVE)
1185 snprintf(buffer, buflen, "%d", txpower->value);
1189 /* Convert everything to dBm */
1190 if(txpower->flags & IW_TXPOW_MWATT)
1191 dbm = iw_mwatt2dbm(txpower->value);
1193 dbm = txpower->value;
1196 snprintf(buffer, buflen, "%d dBm", dbm);
1201 /********************** STATISTICS SUBROUTINES **********************/
1203 /*------------------------------------------------------------------*/
1205 * Read /proc/net/wireless to get the latest statistics
1208 iw_get_stats(int skfd,
1209 const char * ifname,
1211 const iwrange * range,
1214 /* Fortunately, we can always detect this condition properly */
1215 if((has_range) && (range->we_version_compiled > 11))
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)
1225 /* Format has not changed since WE-12, no conversion */
1230 FILE * f = fopen(PROC_NET_WIRELESS, "r");
1237 /* Loop on all devices */
1238 while(fgets(buf,255,f))
1241 while(*bp&&isspace(*bp))
1243 /* Is it the good device ? */
1244 if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
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);
1279 /* No conversion needed */
1288 /*------------------------------------------------------------------*/
1290 * Output the link statistics, taking care of formating
1293 iw_print_stats(char * buffer,
1295 const iwqual * qual,
1296 const iwrange * range,
1301 /* People are very often confused by the 8 bit arithmetic happening
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.
1308 * Relative/percent values are always encoded unsigned, between 0 and 255.
1309 * Absolute/dBm values are always encoded negative, between -255 and 0.
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].
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
1327 if(has_range && (qual->level != 0))
1329 /* Deal with quality : always a relative value */
1330 if(!(qual->updated & IW_QUAL_QUAL_INVALID))
1332 len = snprintf(buffer, buflen, "Quality%c%d/%d ",
1333 qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':',
1334 qual->qual, range->max_qual.qual);
1339 /* If the statistics are in dBm or relative */
1340 if(qual->level > range->max_qual.level)
1342 /* Deal with signal level in dBm (absolute power measurement) */
1343 if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1345 len = snprintf(buffer, buflen, "Signal level%c%d dBm ",
1346 qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1347 qual->level - 0x100);
1352 /* Deal with noise level in dBm (absolute power measurement) */
1353 if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1355 len = snprintf(buffer, buflen, "Noise level%c%d dBm",
1356 qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1357 qual->noise - 0x100);
1362 /* Deal with signal level as relative value (0 -> max) */
1363 if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
1365 len = snprintf(buffer, buflen, "Signal level%c%d/%d ",
1366 qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
1367 qual->level, range->max_qual.level);
1372 /* Deal with noise level as relative value (0 -> max) */
1373 if(!(qual->updated & IW_QUAL_NOISE_INVALID))
1375 len = snprintf(buffer, buflen, "Noise level%c%d/%d",
1376 qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
1377 qual->noise, range->max_qual.noise);
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);
1390 /*********************** ENCODING SUBROUTINES ***********************/
1392 /*------------------------------------------------------------------*/
1394 * Output the encoding key, with a nice formating
1397 iw_print_key(char * buffer,
1399 const unsigned char * key, /* Must be unsigned */
1405 /* Check buffer size -> 1 bytes => 2 digits + 1/2 separator */
1406 if((key_size * 3) > buflen)
1408 snprintf(buffer, buflen, "<too big>");
1412 /* Is the key present ??? */
1413 if(key_flags & IW_ENCODE_NOKEY)
1415 /* Nope : print on or dummy */
1417 strcpy(buffer, "on"); /* Size checked */
1420 strcpy(buffer, "**"); /* Size checked */
1422 for(i = 1; i < key_size; i++)
1425 strcpy(buffer++, "-"); /* Size checked */
1426 strcpy(buffer, "**"); /* Size checked */
1433 /* Yes : print the key */
1434 sprintf(buffer, "%.2X", key[0]); /* Size checked */
1436 for(i = 1; i < key_size; i++)
1439 strcpy(buffer++, "-"); /* Size checked */
1440 sprintf(buffer, "%.2X", key[i]); /* Size checked */
1446 /*------------------------------------------------------------------*/
1448 * Convert a passphrase into a key
1449 * ### NOT IMPLEMENTED ###
1450 * Return size of the key, or 0 (no key) or -1 (error)
1453 iw_pass_key(const char * input,
1454 unsigned char * key)
1456 input = input; key = key;
1457 fprintf(stderr, "Error: Passphrase not implemented\n");
1461 /*------------------------------------------------------------------*/
1463 * Parse a key from the command line.
1464 * Return size of the key, or 0 (no key) or -1 (error)
1467 iw_in_key(const char * input,
1468 unsigned char * key)
1472 /* Check the type of key */
1473 if(!strncmp(input, "s:", 2))
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);
1482 if(!strncmp(input, "p:", 2))
1484 /* Second case : as a passphrase (PrismII cards) */
1485 return(iw_pass_key(input + 2, key)); /* skip "p:" */
1494 /* Third case : as hexadecimal digits */
1495 buff = malloc(IW_ENCODING_TOKEN_MAX + strlen(input) + 1);
1498 fprintf(stderr, "Malloc failed (string too long ?)\n");
1501 /* Preserve original buffers (both in & out) */
1502 hex = buff + IW_ENCODING_TOKEN_MAX;
1503 strcpy(hex, input); /* Size checked */
1507 p = strtok(hex, "-:;.,");
1508 while((p != (char *) NULL) && (keylen < IW_ENCODING_TOKEN_MAX))
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);
1518 return(-1); /* Error -> non-hex char */
1519 /* Fixup odd strings such as '123' is '01'+'23' and not '12'+'03'*/
1523 /* Put back two chars as one byte */
1525 templ |= temph << 4;
1528 out[keylen++] = (unsigned char) (templ & 0xFF);
1529 /* Check where to get next char from */
1530 if(len > count) /* Token not finished yet */
1533 p = strtok((char *) NULL, "-:;.,");
1535 memcpy(key, out, keylen);
1542 /*------------------------------------------------------------------*/
1544 * Parse a key from the command line.
1545 * Return size of the key, or 0 (no key) or -1 (error)
1548 iw_in_key_full(int skfd,
1549 const char * ifname,
1551 unsigned char * key,
1557 if(!strncmp(input, "l:", 2))
1559 struct iw_range range;
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);
1568 /* Separate the two strings */
1569 p = strchr(key, ':');
1572 fprintf(stderr, "Error: Invalid login format\n");
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));
1582 if(range.we_version_compiled > 15)
1585 printf("flags = %X, index = %X\n",
1586 *flags, range.encoding_login_index);
1587 if((*flags & IW_ENCODE_INDEX) == 0)
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;
1596 printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
1600 /* Simpler routine above */
1601 keylen = iw_in_key(input, key);
1606 /******************* POWER MANAGEMENT SUBROUTINES *******************/
1608 /*------------------------------------------------------------------*/
1610 * Output a power management value with all attributes...
1613 iw_print_pm_value(char * buffer,
1621 snprintf(buffer, buflen, "<too big>");
1627 if(flags & IW_POWER_MIN)
1629 strcpy(buffer, " min"); /* Size checked */
1632 if(flags & IW_POWER_MAX)
1634 strcpy(buffer, " max"); /* Size checked */
1639 if(flags & IW_POWER_TIMEOUT)
1641 strcpy(buffer, " timeout:"); /* Size checked */
1646 strcpy(buffer, " period:"); /* Size checked */
1650 /* Display value without units */
1651 if(flags & IW_POWER_RELATIVE)
1652 snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
1655 /* Display value with units */
1656 if(value >= (int) MEGA)
1657 snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
1659 if(value >= (int) KILO)
1660 snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
1662 snprintf(buffer, buflen, "%dus", value);
1666 /*------------------------------------------------------------------*/
1668 * Output a power management mode
1671 iw_print_pm_mode(char * buffer,
1678 snprintf(buffer, buflen, "<too big>");
1682 /* Print the proper mode... */
1683 switch(flags & IW_POWER_MODE)
1685 case IW_POWER_UNICAST_R:
1686 strcpy(buffer, "mode:Unicast only received"); /* Size checked */
1688 case IW_POWER_MULTICAST_R:
1689 strcpy(buffer, "mode:Multicast only received"); /* Size checked */
1691 case IW_POWER_ALL_R:
1692 strcpy(buffer, "mode:All packets received"); /* Size checked */
1694 case IW_POWER_FORCE_S:
1695 strcpy(buffer, "mode:Force sending"); /* Size checked */
1697 case IW_POWER_REPEATER:
1698 strcpy(buffer, "mode:Repeat multicasts"); /* Size checked */
1701 strcpy(buffer, ""); /* Size checked */
1706 /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/
1708 /*------------------------------------------------------------------*/
1710 * Output a retry value with all attributes...
1713 iw_print_retry_value(char * buffer,
1718 /* Check buffer size */
1721 snprintf(buffer, buflen, "<too big>");
1727 if(flags & IW_RETRY_MIN)
1729 strcpy(buffer, " min"); /* Size checked */
1732 if(flags & IW_RETRY_MAX)
1734 strcpy(buffer, " max"); /* Size checked */
1738 /* Type lifetime of limit */
1739 if(flags & IW_RETRY_LIFETIME)
1741 strcpy(buffer, " lifetime:"); /* Size checked */
1744 /* Display value without units */
1745 if(flags & IW_POWER_RELATIVE)
1746 snprintf(buffer, buflen, "%g", ((double) value) / MEGA);
1749 /* Display value with units */
1750 if(value >= (int) MEGA)
1751 snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
1753 if(value >= (int) KILO)
1754 snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
1756 snprintf(buffer, buflen, "%dus", value);
1760 snprintf(buffer, buflen, " limit:%d", value);
1763 /************************* TIME SUBROUTINES *************************/
1765 /*------------------------------------------------------------------*/
1768 * Inspired from irdadump...
1771 iw_print_timeval(char * buffer,
1773 const struct timeval * time)
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);
1783 /*********************** ADDRESS SUBROUTINES ************************/
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...
1790 /*------------------------------------------------------------------*/
1792 * Check if interface support the right MAC address type...
1795 iw_check_mac_addr_type(int skfd,
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))
1805 /* Deep trouble... */
1806 fprintf(stderr, "Interface %s doesn't support MAC addresses\n",
1812 printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family,
1813 iw_ether_ntoa((struct ether_addr *) ifr.ifr_hwaddr.sa_data));
1820 /*------------------------------------------------------------------*/
1822 * Check if interface support the right interface address type...
1825 iw_check_if_addr_type(int skfd,
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))
1835 /* Deep trouble... */
1836 fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname);
1841 printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family,
1842 *((unsigned long *) ifr.ifr_addr.sa_data));
1849 /*------------------------------------------------------------------*/
1851 * Check if interface support the right address types...
1854 iw_check_addr_type(int skfd,
1857 /* Check the interface address type */
1858 if(iw_check_if_addr_type(skfd, ifname) < 0)
1861 /* Check the interface address type */
1862 if(iw_check_mac_addr_type(skfd, ifname) < 0)
1869 /*------------------------------------------------------------------*/
1871 * Ask the kernel for the MAC address of an interface.
1874 iw_get_mac_addr(int skfd,
1875 const char * ifname,
1876 struct ether_addr * eth,
1877 unsigned short * ptype)
1882 /* Prepare request */
1883 bzero(&ifr, sizeof(struct ifreq));
1884 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1887 ret = ioctl(skfd, SIOCGIFHWADDR, &ifr);
1889 memcpy(eth->ether_addr_octet, ifr.ifr_hwaddr.sa_data, 6);
1890 *ptype = ifr.ifr_hwaddr.sa_family;
1894 /*------------------------------------------------------------------*/
1896 * Display an Ethernet address in readable format.
1899 iw_ether_ntop(const struct ether_addr* eth, char* buf)
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]);
1907 /*------------------------------------------------------------------*/
1909 * Display an Ethernet address in readable format.
1910 * Same with a static buffer
1913 iw_ether_ntoa(const struct ether_addr* eth)
1915 static char buf[20];
1916 iw_ether_ntop(eth, buf);
1920 /*------------------------------------------------------------------*/
1922 * Input an Ethernet address and convert to binary.
1925 iw_ether_aton(const char *orig, struct ether_addr *eth)
1931 for(bufp = orig; *bufp != '\0'; ++bufp) {
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;
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;
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') {
1951 fprintf(stderr, "iw_ether_aton(%s): trailing junk!\n", orig);
1957 fprintf(stderr, "iw_ether_aton(%s): %s\n",
1958 orig, ether_ntoa(eth));
1967 fprintf(stderr, "iw_ether_aton(%s): invalid ether address!\n", orig);
1974 /*------------------------------------------------------------------*/
1976 * Input an Internet address and convert to binary.
1979 iw_in_inet(char *name, struct sockaddr *sap)
1983 struct sockaddr_in *sain = (struct sockaddr_in *) sap;
1986 sain->sin_family = AF_INET;
1989 /* Default is special, meaning 0.0.0.0. */
1990 if (!strcmp(name, "default")) {
1991 sain->sin_addr.s_addr = INADDR_ANY;
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);
2002 /* Always use the resolver (DNS name + IP addresses) */
2003 if ((hp = gethostbyname(name)) == (struct hostent *)NULL) {
2007 memcpy((char *) &sain->sin_addr, (char *) hp->h_addr_list[0], hp->h_length);
2008 strcpy(name, hp->h_name);
2012 /*------------------------------------------------------------------*/
2014 * Input an address and convert to binary.
2017 iw_in_addr(int skfd,
2020 struct sockaddr *sap)
2022 /* Check if it is a hardware or IP address */
2023 if(index(bufp, ':') == NULL)
2025 struct sockaddr if_address;
2026 struct arpreq arp_query;
2028 /* Check if we have valid interface address type */
2029 if(iw_check_if_addr_type(skfd, ifname) < 0)
2031 fprintf(stderr, "%-8.16s Interface doesn't support IP addresses\n", ifname);
2035 /* Read interface address */
2036 if(iw_in_inet(bufp, &if_address) < 0)
2038 fprintf(stderr, "Invalid interface address %s\n", bufp);
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))
2054 fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n",
2055 bufp, ifname, errno);
2059 /* Store new MAC address */
2060 memcpy((char *) sap,
2061 (char *) &(arp_query.arp_ha),
2062 sizeof(struct sockaddr));
2065 printf("IP Address %s => Hw Address = %s\n",
2066 bufp, iw_ether_ntoa((struct ether_addr *) sap->sa_data));
2069 else /* If it's an hardware address */
2071 /* Check if we have valid mac address type */
2072 if(iw_check_mac_addr_type(skfd, ifname) < 0)
2074 fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname);
2078 /* Get the hardware address */
2079 if(iw_in_ether(bufp, sap) < 0)
2081 fprintf(stderr, "Invalid hardware address %s\n", bufp);
2087 printf("Hw Address = %s\n", iw_ether_ntoa((struct ether_addr *) sap->sa_data));
2093 /************************* MISC SUBROUTINES **************************/
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 */
2107 /*------------------------------------------------------------------*/
2109 * Max size in bytes of an private argument.
2112 iw_get_priv_size(int args)
2114 int num = args & IW_PRIV_SIZE_MASK;
2115 int type = (args & IW_PRIV_TYPE_MASK) >> 12;
2117 return(num * priv_type_size[type]);
2120 /************************ EVENT SUBROUTINES ************************/
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
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 */
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 */
2187 static const unsigned int standard_ioctl_num = sizeof(standard_ioctl_hdr);
2190 * Meta-data about all the additional standard Wireless Extension events
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 */
2200 static const unsigned int standard_event_num = sizeof(standard_event_hdr);
2202 /* Size (in bytes) of various events */
2203 static const int event_type_size[] = {
2204 IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */
2206 IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
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 */
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 */
2217 /* Forward compatibility with WE-19 */
2218 #define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
2221 /*------------------------------------------------------------------*/
2223 * Initialise the struct stream_descr so that we can extract
2224 * individual events from the event stream.
2227 iw_init_event_stream(struct stream_descr * stream, /* Stream of events */
2232 memset((char *) stream, '\0', sizeof(struct stream_descr));
2235 stream->current = data;
2236 stream->end = data + len;
2239 /*------------------------------------------------------------------*/
2241 * Extract the next event from the event stream.
2244 iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
2245 struct iw_event * iwe, /* Extracted event */
2249 unsigned int event_len = 1; /* Invalid */
2251 /* Don't "optimise" the following variable, it will crash */
2252 unsigned cmd_index; /* *MUST* be unsigned */
2254 /* Unused for now. Will be later on... */
2255 we_version = we_version;
2257 /* Check for end of stream */
2258 if((stream->current + IW_EV_LCP_LEN) > stream->end)
2262 printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n",
2263 stream->current, stream->value, stream->end);
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);
2271 printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n",
2272 iwe->cmd, iwe->len);
2275 /* Check invalid events */
2276 if(iwe->len <= IW_EV_LCP_LEN)
2279 /* Get the type and length of that event */
2280 if(iwe->cmd <= SIOCIWLAST)
2282 cmd_index = iwe->cmd - SIOCIWFIRST;
2283 if(cmd_index < standard_ioctl_num)
2284 event_type = standard_ioctl_hdr[cmd_index];
2288 cmd_index = iwe->cmd - IWEVFIRST;
2289 if(cmd_index < standard_event_num)
2290 event_type = standard_event_hdr[cmd_index];
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;
2298 /* Check if we know about this event */
2299 if(event_len <= IW_EV_LCP_LEN)
2301 /* Skip to next event */
2302 stream->current += iwe->len;
2305 event_len -= IW_EV_LCP_LEN;
2307 /* Set pointer on data */
2308 if(stream->value != NULL)
2309 pointer = stream->value; /* Next value in event */
2311 pointer = stream->current + IW_EV_LCP_LEN; /* First value in event */
2314 printf("DBG - event_type = %d, event_len = %d, pointer = %p\n",
2315 event_type, event_len, pointer);
2318 /* Copy the rest of the event (at least, fixed part) */
2319 if((pointer + event_len) > stream->end)
2321 /* Go to next event */
2322 stream->current += iwe->len;
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);
2330 memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
2332 /* Skip event in the stream */
2333 pointer += event_len;
2335 /* Special processing for iw_point events */
2336 if(event_type == IW_HEADER_TYPE_POINT)
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;
2344 iwe->u.data.pointer = NULL;
2346 /* Go to next event */
2347 stream->current += iwe->len;
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;
2357 /* Go to next event */
2358 stream->value = NULL;
2359 stream->current += iwe->len;
2365 /*********************** SCANNING SUBROUTINES ***********************/
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...
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.
2395 /*------------------------------------------------------------------*/
2397 * Process/store one element from the scanning results in wireless_scan
2399 static inline struct wireless_scan *
2400 iw_process_scanning_token(struct iw_event * event,
2401 struct wireless_scan * wscan)
2403 struct wireless_scan * oldwscan;
2405 /* Now, let's decode the event */
2409 /* New cell description. Allocate new cell descriptor, zero it. */
2411 wscan = (struct wireless_scan *) malloc(sizeof(struct wireless_scan));
2414 /* Link at the end of the list */
2415 if(oldwscan != NULL)
2416 oldwscan->next = wscan;
2419 bzero(wscan, sizeof(struct wireless_scan));
2421 /* Save cell identifier */
2422 wscan->has_ap_addr = 1;
2423 memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof (sockaddr));
2426 wscan->b.has_nwid = 1;
2427 memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam));
2430 wscan->b.has_freq = 1;
2431 wscan->b.freq = iw_freq2float(&(event->u.freq));
2432 wscan->b.freq_flags = event->u.freq.flags;
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;
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';
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);
2453 wscan->b.key_flags |= IW_ENCODE_NOKEY;
2456 /* We don't get complete stats, only qual */
2457 wscan->has_stats = 1;
2458 memcpy(&wscan->stats.qual, &event->u.qual, sizeof(iwstats));
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 */
2464 /* How can we deal with those sanely ? Jean II */
2467 } /* switch(event->cmd) */
2472 /*------------------------------------------------------------------*/
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
2482 iw_process_scan(int skfd,
2485 wireless_scan_head * context)
2488 unsigned char * buffer = NULL; /* Results */
2489 int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
2490 unsigned char * newbuf;
2492 /* Don't waste too much time on interfaces (50 * 100 = 5s) */
2494 if(context->retry > 50)
2500 /* If we have not yet initiated scanning on the interface */
2501 if(context->retry == 1)
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)
2509 /* Success : now, just wait for event or results */
2510 return(250); /* Wait 250 ms */
2514 /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
2515 newbuf = realloc(buffer, buflen);
2518 /* man says : If realloc() fails the original block is left untouched */
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)
2532 /* Check if buffer was too small (WE-17 only) */
2533 if((errno == E2BIG) && (we_version > 16))
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 */
2543 /* Check if the driver gave us any hints. */
2544 if(wrq.u.data.length > buflen)
2545 buflen = wrq.u.data.length;
2553 /* Check if results not available yet */
2557 /* Wait for only 100ms from now on */
2558 return(100); /* Wait 100 ms */
2562 /* Bad error, please don't come back... */
2566 /* We have the results, process them */
2567 if(wrq.u.data.length)
2569 struct iw_event iwe;
2570 struct stream_descr stream;
2571 struct wireless_scan * wscan = NULL;
2574 /* Debugging code. In theory useless, because it's debugged ;-) */
2576 printf("Scan result [%02X", buffer[0]);
2577 for(i = 1; i < wrq.u.data.length; i++)
2578 printf(":%02X", buffer[i]);
2583 iw_init_event_stream(&stream, buffer, wrq.u.data.length);
2584 /* This is dangerous, we may leak user data... */
2585 context->result = NULL;
2587 /* Look every token */
2590 /* Extract an event and print it */
2591 ret = iw_extract_event_stream(&stream, &iwe, we_version);
2594 /* Convert to wireless_scan struct */
2595 wscan = iw_process_scanning_token(&iwe, wscan);
2596 /* Check problems */
2603 /* Save head of list */
2604 if(context->result == NULL)
2605 context->result = wscan;
2611 /* Done with this interface - return success */
2616 /*------------------------------------------------------------------*/
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.
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
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.
2632 * Return -1 for error and 0 for success.
2638 wireless_scan_head * context)
2640 int delay; /* in ms */
2642 /* Clean up context. Potential memory leak if(context.result != NULL) */
2643 context->result = NULL;
2646 /* Wait until we get results or error */
2649 /* Try to get scan results */
2650 delay = iw_process_scan(skfd, ifname, we_version, context);
2652 /* Check termination */
2657 usleep(delay * 1000);
2660 /* End - return -1 or 0 */