6 * Main code for "iwconfig". This is the generic tool for most
8 * You need to link this code against "iwcommon.c" and "-lm".
11 #include "iwcommon.h" /* Header */
13 /************************* MISC SUBROUTINES **************************/
15 /*------------------------------------------------------------------*/
22 fprintf(stderr, "Usage: iwconfig interface [essid {NN|on|off}]\n");
23 fprintf(stderr, " [nwid {NN|on|off}]\n");
24 fprintf(stderr, " [freq N.NNNN[k|M|G]]\n");
25 fprintf(stderr, " [channel N]\n");
26 fprintf(stderr, " [sens N]\n");
27 fprintf(stderr, " [nick N]\n");
28 fprintf(stderr, " [rate {N|auto|fixed}]\n");
29 fprintf(stderr, " [rts {N|auto|fixed|off}]\n");
30 fprintf(stderr, " [frag {N|auto|fixed|off}]\n");
31 fprintf(stderr, " [enc NNNN-NNNN]\n");
36 /************************* DISPLAY ROUTINES **************************/
38 /*------------------------------------------------------------------*/
40 * Read /proc/net/wireless to get the latest statistics
43 iw_getstats(char * ifname,
46 FILE *f=fopen("/proc/net/wireless","r");
51 while(fgets(buf,255,f))
54 while(*bp&&isspace(*bp))
56 if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
60 bp = strtok(bp, " .");
61 sscanf(bp, "%X", (unsigned int *)&stats->status);
62 bp = strtok(NULL, " .");
63 sscanf(bp, "%d", (unsigned int *)&stats->qual.qual);
64 bp = strtok(NULL, " .");
65 sscanf(bp, "%d", (unsigned int *)&stats->qual.level);
66 bp = strtok(NULL, " .");
67 sscanf(bp, "%d", (unsigned int *)&stats->qual.noise);
68 bp = strtok(NULL, " .");
69 sscanf(bp, "%d", &stats->discard.nwid);
70 bp = strtok(NULL, " .");
71 sscanf(bp, "%d", &stats->discard.code);
72 bp = strtok(NULL, " .");
73 sscanf(bp, "%d", &stats->discard.misc);
82 /*------------------------------------------------------------------*/
84 * Get wireless informations & config from the device driver
85 * We will call all the classical wireless ioctl on the driver through
86 * the socket to know what is supported and to get the settings...
91 struct wireless_info * info)
95 memset((char *) info, 0, sizeof(struct wireless_info));
97 /* Get wireless name */
98 strcpy(wrq.ifr_name, ifname);
99 if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
100 /* If no wireless name : no wireless extensions */
103 strcpy(info->name, wrq.u.name);
106 strcpy(wrq.ifr_name, ifname);
107 if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0)
110 info->nwid_on = wrq.u.nwid.on;
111 info->nwid = wrq.u.nwid.nwid;
114 /* Get frequency / channel */
115 strcpy(wrq.ifr_name, ifname);
116 if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0)
119 info->freq = freq2float(&(wrq.u.freq));
122 /* Get sensitivity */
123 strcpy(wrq.ifr_name, ifname);
124 if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0)
127 info->sens = wrq.u.sensitivity;
130 /* Get encryption information */
131 strcpy(wrq.ifr_name, ifname);
132 if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0)
135 info->enc_method = wrq.u.encoding.method;
136 info->enc_key = wrq.u.encoding.code;
141 strcpy(wrq.ifr_name, ifname);
142 wrq.u.data.pointer = (caddr_t) info->essid;
143 wrq.u.data.length = 0;
144 wrq.u.data.flags = 0;
145 if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0)
148 info->essid_on = wrq.u.data.flags;
152 strcpy(wrq.ifr_name, ifname);
153 if(ioctl(skfd, SIOCGIWAP, &wrq) >= 0)
155 info->has_ap_addr = 1;
156 memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
158 #endif /* WIRELESS_EXT > 5 */
162 strcpy(wrq.ifr_name, ifname);
163 wrq.u.data.pointer = (caddr_t) info->nickname;
164 wrq.u.data.length = 0;
165 wrq.u.data.flags = 0;
166 if(ioctl(skfd, SIOCGIWNICKN, &wrq) >= 0)
167 if(wrq.u.data.length > 1)
168 info->has_nickname = 1;
171 strcpy(wrq.ifr_name, ifname);
172 if(ioctl(skfd, SIOCGIWRATE, &wrq) >= 0)
174 info->has_bitrate = 1;
175 info->bitrate_fixed = wrq.u.bitrate.fixed;
176 info->bitrate = wrq.u.bitrate.value;
179 /* Get RTS threshold */
180 strcpy(wrq.ifr_name, ifname);
181 if(ioctl(skfd, SIOCGIWRTS, &wrq) >= 0)
184 info->rts_fixed = wrq.u.rts.fixed;
185 info->rts = wrq.u.rts.value;
188 /* Get fragmentation thershold */
189 strcpy(wrq.ifr_name, ifname);
190 if(ioctl(skfd, SIOCGIWFRAG, &wrq) >= 0)
193 info->frag_fixed = wrq.u.frag.fixed;
194 info->frag = wrq.u.frag.value;
196 #endif /* WIRELESS_EXT > 7 */
199 if(iw_getstats(ifname, &(info->stats)) == 0)
205 if(get_range_info(skfd, ifname, &(info->range)) >= 0)
211 /*------------------------------------------------------------------*/
213 * Print on the screen in a neat fashion all the info we have collected
217 display_info(struct wireless_info * info,
220 /* Display device name and wireless name (name of the protocol used) */
221 printf("%-8.8s %s ", ifname, info->name);
223 /* Display ESSID (extended network), if any */
227 printf("ESSID:\"%s\" ", info->essid);
229 printf("ESSID:off ");
232 /* Display NickName (station name), if any */
233 if(info->has_nickname)
234 printf("Nickname:\"%s\"", info->nickname);
237 if(info->has_essid || info->has_nickname)
240 /* Display Network ID */
243 /* Note : should display right number of digit according to info
244 * in range structure */
246 printf("NWID:%lX ", info->nwid);
248 printf("NWID:off/any ");
251 /* Display frequency / channel */
254 if(info->freq < KILO)
255 printf("Channel:%g ", info->freq);
258 if(info->freq >= GIGA)
259 printf("Frequency:%gGHz ", info->freq / GIGA);
262 if(info->freq >= MEGA)
263 printf("Frequency:%gMHz ", info->freq / MEGA);
265 printf("Frequency:%gkHz ", info->freq / KILO);
270 /* Display sensitivity */
274 /* Display in dBm ? */
276 printf("Sensitivity:%d dBm ", info->sens);
278 printf("Sensitivity:%d/%d ", info->sens, info->range.sensitivity);
280 printf("Sensitivity:%d ", info->sens);
283 /* Display the address of the current Access Point */
284 if(info->has_ap_addr)
286 /* A bit of clever formatting */
287 if((info->has_nwid + 2*info->has_freq + 2*info->has_sens
288 + !info->has_essid) > 3)
291 printf("Access Point: %s", pr_ether(info->ap_addr.sa_data));
296 /* Display the currently used/set bit-rate */
297 if(info->has_bitrate)
300 if(info->bitrate >= GIGA)
301 printf("%g Gb/s", info->bitrate / GIGA);
303 if(info->bitrate >= MEGA)
304 printf("%g Mb/s", info->bitrate / MEGA);
306 printf("%g kb/s", info->bitrate / KILO);
309 if(info->bitrate_fixed)
315 /* Display the RTS threshold */
318 printf("RTS thr:%ld B", info->rts);
327 /* Display the fragmentation threshold */
328 if(info->has_bitrate)
330 printf("Frag thr:%ld B", info->frag);
340 if((info->has_bitrate) || (info->has_rts) || (info->has_bitrate))
345 printf("Encryption key:");
350 long long key = info->enc_key;
352 for(i = 3; i >= 0; i--)
354 parts[i] = key & 0xFFFF;
359 while((parts[i] == 0) && (i < 3))
362 printf("%.4X-", parts[i]);
363 printf("%.4X", parts[3]);
365 if(info->enc_method > 1)
366 printf(" (%d)", info->enc_method);
375 if(info->has_range && (info->stats.qual.level != 0))
376 /* If the statistics are in dBm */
377 if(info->stats.qual.level > info->range.max_qual.level)
378 printf("Link quality:%d/%d Signal level:%d dBm Noise level:%d dBm\n",
379 info->stats.qual.qual, info->range.max_qual.qual,
380 info->stats.qual.level - 0x100,
381 info->stats.qual.noise - 0x100);
383 /* Statistics are relative values (0 -> max) */
384 printf("Link quality:%d/%d Signal level:%d/%d Noise level:%d/%d\n",
385 info->stats.qual.qual, info->range.max_qual.qual,
386 info->stats.qual.level, info->range.max_qual.level,
387 info->stats.qual.noise, info->range.max_qual.noise);
389 /* We can't read the range, so we don't know... */
390 printf("Link quality:%d Signal level:%d Noise level:%d\n",
391 info->stats.qual.qual,
392 info->stats.qual.level,
393 info->stats.qual.noise);
395 printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n",
396 info->stats.discard.nwid,
397 info->stats.discard.code,
398 info->stats.discard.misc);
404 /*------------------------------------------------------------------*/
406 * Print on the screen in a neat fashion all the info we have collected
413 struct wireless_info info;
415 if(get_info(skfd, ifname, &info) < 0)
417 fprintf(stderr, "%-8.8s no wireless extensions.\n\n",
423 display_info(&info, ifname);
426 /*------------------------------------------------------------------*/
428 * Get info on all devices and print it on the screen
431 print_devices(int skfd)
438 /* Get list of active devices */
439 ifc.ifc_len = sizeof(buff);
441 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
443 fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
449 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
450 print_info(skfd, ifr->ifr_name);
453 /************************* SETTING ROUTINES **************************/
455 /*------------------------------------------------------------------*/
457 * Set the wireless options requested on command line
458 * This function is too long and probably should be split,
459 * because it look like the perfect definition of spaghetti code,
460 * but I'm way to lazy
463 set_info(int skfd, /* The socket */
464 char * args[], /* Command line args */
465 int count, /* Args count */
466 char * ifname) /* Dev name */
472 strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
474 /* if nothing after the device name */
478 /* The other args on the line specify options to be set... */
479 for(i = 0; i < count; i++)
481 /* ---------- Set network ID ---------- */
482 if((!strcasecmp(args[i], "nwid")) ||
483 (!strcasecmp(args[i], "domain")))
488 if((!strcasecmp(args[i], "off")) ||
489 (!strcasecmp(args[i], "any")))
492 if(!strcasecmp(args[i], "on"))
495 if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0)
497 fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno));
500 strcpy(wrq.ifr_name, ifname);
504 if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.nwid))
510 if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0)
512 fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
518 /* ---------- Set frequency / channel ---------- */
519 if((!strncmp(args[i], "freq", 4)) ||
520 (!strcmp(args[i], "channel")))
526 if(sscanf(args[i], "%lg", &(freq)) != 1)
528 if(index(args[i], 'G')) freq *= GIGA;
529 if(index(args[i], 'M')) freq *= MEGA;
530 if(index(args[i], 'k')) freq *= KILO;
532 float2freq(freq, &(wrq.u.freq));
534 if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
536 fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
542 /* ---------- Set sensitivity ---------- */
543 if(!strncmp(args[i], "sens", 4))
547 if(sscanf(args[i], "%d", &(wrq.u.sensitivity)) != 1)
550 if(ioctl(skfd, SIOCSIWSENS, &wrq) < 0)
552 fprintf(stderr, "SIOCSIWSENS: %s\n", strerror(errno));
558 /* ---------- Set encryption stuff ---------- */
559 if(!strncmp(args[i], "enc", 3 ))
561 unsigned long long key = 0;
566 if(!strcasecmp(args[i], "off"))
567 wrq.u.encoding.method = 0;
570 if(!strcasecmp(args[i], "on"))
572 /* Get old encryption information */
573 if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0)
575 fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno));
578 strcpy(wrq.ifr_name, ifname);
586 p = buff = malloc(strlen(args[i] + 1));
587 strcpy(buff, args[i]);
589 p = strtok(buff, "-:;.,*#");
590 while(p != (char *) NULL)
593 if(sscanf(p, "%lX", &temp) != 1)
596 p = strtok((char *) NULL, "-:;.,*#");
600 wrq.u.encoding.code = key;
602 /* TODO : check for "(method)" in args list */
603 wrq.u.encoding.method = 1;
606 if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0)
608 fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
609 errno, strerror(errno));
616 /* ---------- Set ESSID ---------- */
617 if(!strcasecmp(args[i], "essid"))
619 char essid[IW_ESSID_MAX_SIZE + 1];
624 if((!strcasecmp(args[i], "off")) ||
625 (!strcasecmp(args[i], "any")))
627 wrq.u.data.flags = 0;
631 if(!strcasecmp(args[i], "on"))
634 wrq.u.data.pointer = (caddr_t) essid;
635 wrq.u.data.length = 0;
636 wrq.u.data.flags = 0;
637 if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0)
639 fprintf(stderr, "SIOCGIWESSID: %s\n", strerror(errno));
642 strcpy(wrq.ifr_name, ifname);
643 wrq.u.data.flags = 1;
646 if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
648 fprintf(stderr, "ESSID too long (max %d): ``%s''\n",
649 IW_ESSID_MAX_SIZE, args[i]);
654 wrq.u.data.flags = 1;
655 strcpy(essid, args[i]);
658 wrq.u.data.pointer = (caddr_t) essid;
659 wrq.u.data.length = strlen(essid) + 1;
660 if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0)
662 fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
668 /* ---------- Set AP address ---------- */
669 if(!strcasecmp(args[i], "ap"))
674 /* Check if we have valid address types */
675 if(check_addr_type(skfd, ifname) < 0)
677 fprintf(stderr, "%-8.8s Interface doesn't support MAC & IP addresses\n", ifname);
681 /* Get the address */
682 if(in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
685 if(ioctl(skfd, SIOCSIWAP, &wrq) < 0)
687 fprintf(stderr, "SIOCSIWAP: %s\n", strerror(errno));
692 #endif /* WIRELESS_EXT > 5 */
695 /* ---------- Set NickName ---------- */
696 if(!strncmp(args[i], "nick", 4))
701 if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
703 fprintf(stderr, "Name too long (max %d) : ``%s''\n",
704 IW_ESSID_MAX_SIZE, args[i]);
708 wrq.u.data.pointer = (caddr_t) args[i];
709 wrq.u.data.length = strlen(args[i]) + 1;
710 if(ioctl(skfd, SIOCSIWNICKN, &wrq) < 0)
712 fprintf(stderr, "SIOCSIWNICKN: %s\n", strerror(errno));
718 /* ---------- Set Bit-Rate ---------- */
719 if((!strncmp(args[i], "bit", 3)) ||
720 (!strcmp(args[i], "rate")))
725 if(!strcasecmp(args[i], "auto"))
727 wrq.u.bitrate.value = -1;
728 wrq.u.bitrate.fixed = 0;
732 if(!strcasecmp(args[i], "fixed"))
734 /* Get old bitrate */
735 if(ioctl(skfd, SIOCGIWRATE, &wrq) < 0)
737 fprintf(stderr, "SIOCGIWRATE: %s\n", strerror(errno));
740 strcpy(wrq.ifr_name, ifname);
742 else /* Should be a numeric value */
746 if(sscanf(args[i], "%lg", &(brate)) != 1)
748 if(index(args[i], 'G')) brate *= GIGA;
749 if(index(args[i], 'M')) brate *= MEGA;
750 if(index(args[i], 'k')) brate *= KILO;
751 wrq.u.bitrate.value = (long) brate;
753 wrq.u.bitrate.fixed = 1;
756 if(ioctl(skfd, SIOCSIWRATE, &wrq) < 0)
758 fprintf(stderr, "SIOCSIWRATE: %s\n", strerror(errno));
764 /* ---------- Set RTS threshold ---------- */
765 if(!strncmp(args[i], "rts", 3))
770 if(!strcasecmp(args[i], "auto"))
772 wrq.u.rts.value = -1;
777 if(!strcasecmp(args[i], "fixed"))
779 /* Get old RTS threshold */
780 if(ioctl(skfd, SIOCGIWRTS, &wrq) < 0)
782 fprintf(stderr, "SIOCGIWRTS: %s\n", strerror(errno));
785 strcpy(wrq.ifr_name, ifname);
788 if(!strcasecmp(args[i], "off"))
789 wrq.u.rts.value = -1; /* i.e. max size */
790 else /* Should be a numeric value */
791 if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.rts.value))
798 if(ioctl(skfd, SIOCSIWRTS, &wrq) < 0)
800 fprintf(stderr, "SIOCSIWRTS: %s\n", strerror(errno));
806 /* ---------- Set fragmentation threshold ---------- */
807 if(!strncmp(args[i], "frag", 4))
812 if(!strcasecmp(args[i], "auto"))
814 wrq.u.frag.value = -1;
815 wrq.u.frag.fixed = 0;
819 if(!strcasecmp(args[i], "fixed"))
821 /* Get old fragmentation threshold */
822 if(ioctl(skfd, SIOCGIWFRAG, &wrq) < 0)
824 fprintf(stderr, "SIOCGIWFRAG: %s\n", strerror(errno));
827 strcpy(wrq.ifr_name, ifname);
830 if(!strcasecmp(args[i], "off"))
831 wrq.u.frag.value = -1; /* i.e. max size */
832 else /* Should be a numeric value */
833 if(sscanf(args[i], "%ld", (unsigned long *) &(wrq.u.frag.value))
837 wrq.u.frag.fixed = 1;
840 if(ioctl(skfd, SIOCSIWFRAG, &wrq) < 0)
842 fprintf(stderr, "SIOCSIWFRAG: %s\n", strerror(errno));
847 #endif /* WIRELESS_EXT > 7 */
849 /* Here we have an unrecognised arg... */
850 fprintf(stderr, "Invalid argument : %s\n", args[i]);
853 } /* for(index ... */
857 /******************************* MAIN ********************************/
859 /*------------------------------------------------------------------*/
867 int skfd = -1; /* generic raw socket desc. */
870 /* Create a channel to the NET kernel. */
871 if((skfd = sockets_open()) < 0)
877 /* No argument : show the list of all device + info */
885 /* Special case for help... */
886 if((!strncmp(argv[1], "-h", 9)) ||
887 (!strcmp(argv[1], "--help")))
894 /* The device name must be the first argument */
897 print_info(skfd, argv[1]);
902 /* The other args on the line specify options to be set... */
903 goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
905 /* Close the socket. */