OSDN Git Service

v27
[android-x86/external-wireless-tools.git] / wireless_tools / iwconfig.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPLB 97->99 - HPL 99->04
5  *
6  * Main code for "iwconfig". This is the generic tool for most
7  * manipulations...
8  * You need to link this code against "iwlib.c" and "-lm".
9  *
10  * This file is released under the GPL license.
11  *     Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
12  */
13
14 #include "iwlib.h"              /* Header */
15
16 /************************* MISC SUBROUTINES **************************/
17
18 /*------------------------------------------------------------------*/
19 /*
20  * Print usage string
21  */
22 static void
23 iw_usage(void)
24 {
25   fprintf(stderr, "Usage: iwconfig interface [essid {NN|on|off}]\n");
26   fprintf(stderr, "                          [nwid {NN|on|off}]\n");
27   fprintf(stderr, "                          [mode {managed|ad-hoc|...}\n");
28   fprintf(stderr, "                          [freq N.NNNN[k|M|G]]\n");
29   fprintf(stderr, "                          [channel N]\n");
30   fprintf(stderr, "                          [ap {N|off|auto}]\n");
31   fprintf(stderr, "                          [sens N]\n");
32   fprintf(stderr, "                          [nick N]\n");
33   fprintf(stderr, "                          [rate {N|auto|fixed}]\n");
34   fprintf(stderr, "                          [rts {N|auto|fixed|off}]\n");
35   fprintf(stderr, "                          [frag {N|auto|fixed|off}]\n");
36   fprintf(stderr, "                          [enc {NNNN-NNNN|off}]\n");
37   fprintf(stderr, "                          [power {period N|timeout N}]\n");
38   fprintf(stderr, "                          [txpower N {mW|dBm}]\n");
39   fprintf(stderr, "                          [commit]\n");
40   fprintf(stderr, "       Check man pages for more details.\n\n");
41 }
42
43
44 /************************* DISPLAY ROUTINES **************************/
45
46 /*------------------------------------------------------------------*/
47 /*
48  * Get wireless informations & config from the device driver
49  * We will call all the classical wireless ioctl on the driver through
50  * the socket to know what is supported and to get the settings...
51  */
52 static int
53 get_info(int                    skfd,
54          char *                 ifname,
55          struct wireless_info * info)
56 {
57   struct iwreq          wrq;
58
59   memset((char *) info, 0, sizeof(struct wireless_info));
60
61   /* Get basic information */
62   if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0)
63     {
64       /* If no wireless name : no wireless extensions */
65       /* But let's check if the interface exists at all */
66       struct ifreq ifr;
67
68       strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
69       if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
70         return(-ENODEV);
71       else
72         return(-ENOTSUP);
73     }
74
75   /* Get ranges */
76   if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0)
77     info->has_range = 1;
78
79   /* Get sensitivity */
80   if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
81     {
82       info->has_sens = 1;
83       memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam));
84     }
85
86   /* Get AP address */
87   if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0)
88     {
89       info->has_ap_addr = 1;
90       memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
91     }
92
93   /* Get NickName */
94   wrq.u.essid.pointer = (caddr_t) info->nickname;
95   wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
96   wrq.u.essid.flags = 0;
97   if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0)
98     if(wrq.u.data.length > 1)
99       info->has_nickname = 1;
100
101   /* Get bit rate */
102   if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0)
103     {
104       info->has_bitrate = 1;
105       memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
106     }
107
108   /* Get RTS threshold */
109   if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
110     {
111       info->has_rts = 1;
112       memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam));
113     }
114
115   /* Get fragmentation threshold */
116   if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0)
117     {
118       info->has_frag = 1;
119       memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
120     }
121
122   /* Get Power Management settings */
123   wrq.u.power.flags = 0;
124   if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0)
125     {
126       info->has_power = 1;
127       memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam));
128     }
129
130   if((info->has_range) && (info->range.we_version_compiled > 9))
131     {
132       /* Get Transmit Power */
133       if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
134         {
135           info->has_txpower = 1;
136           memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
137         }
138     }
139
140   if((info->has_range) && (info->range.we_version_compiled > 10))
141     {
142       /* Get retry limit/lifetime */
143       if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0)
144         {
145           info->has_retry = 1;
146           memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
147         }
148     }
149
150   /* Get stats */
151   if(iw_get_stats(skfd, ifname, &(info->stats),
152                   &info->range, info->has_range) >= 0)
153     {
154       info->has_stats = 1;
155     }
156
157   return(0);
158 }
159
160 /*------------------------------------------------------------------*/
161 /*
162  * Print on the screen in a neat fashion all the info we have collected
163  * on a device.
164  */
165 static void
166 display_info(struct wireless_info *     info,
167              char *                     ifname)
168 {
169   char          buffer[128];    /* Temporary buffer */
170
171   /* One token is more of less 5 characters, 14 tokens per line */
172   int   tokens = 3;     /* For name */
173
174   /* Display device name and wireless name (name of the protocol used) */
175   printf("%-8.16s  %s  ", ifname, info->b.name);
176
177   /* Display ESSID (extended network), if any */
178   if(info->b.has_essid)
179     {
180       if(info->b.essid_on)
181         {
182           /* Does it have an ESSID index ? */
183           if((info->b.essid_on & IW_ENCODE_INDEX) > 1)
184             printf("ESSID:\"%s\" [%d]  ", info->b.essid,
185                    (info->b.essid_on & IW_ENCODE_INDEX));
186           else
187             printf("ESSID:\"%s\"  ", info->b.essid);
188         }
189       else
190         printf("ESSID:off/any  ");
191     }
192
193   /* Display NickName (station name), if any */
194   if(info->has_nickname)
195     printf("Nickname:\"%s\"", info->nickname);
196
197   /* Formatting */
198   if(info->b.has_essid || info->has_nickname)
199     {
200       printf("\n          ");
201       tokens = 0;
202     }
203
204   /* Display Network ID */
205   if(info->b.has_nwid)
206     {
207       /* Note : should display proper number of digit according to info
208        * in range structure */
209       if(info->b.nwid.disabled)
210         printf("NWID:off/any  ");
211       else
212         printf("NWID:%X  ", info->b.nwid.value);
213       tokens +=2;
214     }
215
216   /* Display the current mode of operation */
217   if(info->b.has_mode)
218     {
219       printf("Mode:%s  ", iw_operation_mode[info->b.mode]);
220       tokens +=3;
221     }
222
223   /* Display frequency / channel */
224   if(info->b.has_freq)
225     {
226       double            freq = info->b.freq;    /* Frequency/channel */
227       int               channel = -1;           /* Converted to channel */
228       /* Some driver insist of returning channel instead of frequency.
229        * This fixes them up. Note that, driver should still return
230        * frequency, because other tools depend on it. */
231       if(info->has_range && (freq < KILO))
232         channel = iw_channel_to_freq((int) freq, &freq, &info->range);
233       /* Display */
234       iw_print_freq(buffer, sizeof(buffer), freq, -1, info->b.freq_flags);
235       printf("%s  ", buffer);
236       tokens +=4;
237     }
238
239   /* Display the address of the current Access Point */
240   if(info->has_ap_addr)
241     {
242       /* A bit of clever formatting */
243       if(tokens > 8)
244         {
245           printf("\n          ");
246           tokens = 0;
247         }
248       tokens +=6;
249
250       /* Oups ! No Access Point in Ad-Hoc mode */
251       if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC))
252         printf("Cell:");
253       else
254         printf("Access Point:");
255       printf(" %s   ", iw_pr_ether(buffer, info->ap_addr.sa_data));
256     }
257
258   /* Display the currently used/set bit-rate */
259   if(info->has_bitrate)
260     {
261       /* A bit of clever formatting */
262       if(tokens > 11)
263         {
264           printf("\n          ");
265           tokens = 0;
266         }
267       tokens +=3;
268
269       /* Display it */
270       iw_print_bitrate(buffer, sizeof(buffer), info->bitrate.value);
271       printf("Bit Rate%c%s   ", (info->bitrate.fixed ? '=' : ':'), buffer);
272     }
273
274   /* Display the Transmit Power */
275   if(info->has_txpower)
276     {
277       /* A bit of clever formatting */
278       if(tokens > 11)
279         {
280           printf("\n          ");
281           tokens = 0;
282         }
283       tokens +=3;
284
285       /* Display it */
286       iw_print_txpower(buffer, sizeof(buffer), &info->txpower);
287       printf("Tx-Power%c%s   ", (info->txpower.fixed ? '=' : ':'), buffer);
288     }
289
290   /* Display sensitivity */
291   if(info->has_sens)
292     {
293       /* A bit of clever formatting */
294       if(tokens > 10)
295         {
296           printf("\n          ");
297           tokens = 0;
298         }
299       tokens +=4;
300
301       /* Fixed ? */
302       if(info->sens.fixed)
303         printf("Sensitivity=");
304       else
305         printf("Sensitivity:");
306
307       if(info->has_range)
308         /* Display in dBm ? */
309         if(info->sens.value < 0)
310           printf("%d dBm  ", info->sens.value);
311         else
312           printf("%d/%d  ", info->sens.value, info->range.sensitivity);
313       else
314         printf("%d  ", info->sens.value);
315     }
316
317   printf("\n          ");
318   tokens = 0;
319
320   /* Display retry limit/lifetime information */
321   if(info->has_retry)
322     { 
323       printf("Retry");
324       /* Disabled ? */
325       if(info->retry.disabled)
326         printf(":off");
327       else
328         {
329           /* Let's check the value and its type */
330           if(info->retry.flags & IW_RETRY_TYPE)
331             {
332               iw_print_retry_value(buffer, sizeof(buffer),
333                                    info->retry.value, info->retry.flags);
334               printf("%s", buffer);
335             }
336
337           /* Let's check if nothing (simply on) */
338           if(info->retry.flags == IW_RETRY_ON)
339             printf(":on");
340         }
341       printf("   ");
342       tokens += 5;      /* Between 3 and 5, depend on flags */
343     }
344
345   /* Display the RTS threshold */
346   if(info->has_rts)
347     {
348       /* Disabled ? */
349       if(info->rts.disabled)
350         printf("RTS thr:off   ");
351       else
352         {
353           /* Fixed ? */
354           if(info->rts.fixed)
355             printf("RTS thr=");
356           else
357             printf("RTS thr:");
358
359           printf("%d B   ", info->rts.value);
360         }
361       tokens += 3;
362     }
363
364   /* Display the fragmentation threshold */
365   if(info->has_frag)
366     {
367       /* A bit of clever formatting */
368       if(tokens > 10)
369         {
370           printf("\n          ");
371           tokens = 0;
372         }
373       tokens +=4;
374
375       /* Disabled ? */
376       if(info->frag.disabled)
377         printf("Fragment thr:off");
378       else
379         {
380           /* Fixed ? */
381           if(info->frag.fixed)
382             printf("Fragment thr=");
383           else
384             printf("Fragment thr:");
385
386           printf("%d B   ", info->frag.value);
387         }
388     }
389
390   /* Formating */
391   if(tokens > 0)
392     printf("\n          ");
393
394   /* Display encryption information */
395   /* Note : we display only the "current" key, use iwlist to list all keys */
396   if(info->b.has_key)
397     {
398       printf("Encryption key:");
399       if((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0))
400         printf("off\n          ");
401       else
402         {
403           /* Display the key */
404           iw_print_key(buffer, sizeof(buffer),
405                        info->b.key, info->b.key_size, info->b.key_flags);
406           printf("%s", buffer);
407
408           /* Other info... */
409           if((info->b.key_flags & IW_ENCODE_INDEX) > 1)
410             printf(" [%d]", info->b.key_flags & IW_ENCODE_INDEX);
411           if(info->b.key_flags & IW_ENCODE_RESTRICTED)
412             printf("   Security mode:restricted");
413           if(info->b.key_flags & IW_ENCODE_OPEN)
414             printf("   Security mode:open");
415           printf("\n          ");
416         }
417     }
418
419   /* Display Power Management information */
420   /* Note : we display only one parameter, period or timeout. If a device
421    * (such as HiperLan) has both, the user need to use iwlist... */
422   if(info->has_power)   /* I hope the device has power ;-) */
423     { 
424       printf("Power Management");
425       /* Disabled ? */
426       if(info->power.disabled)
427         printf(":off\n          ");
428       else
429         {
430           /* Let's check the value and its type */
431           if(info->power.flags & IW_POWER_TYPE)
432             {
433               iw_print_pm_value(buffer, sizeof(buffer),
434                                 info->power.value, info->power.flags);
435               printf("%s  ", buffer);
436             }
437
438           /* Let's check the mode */
439           iw_print_pm_mode(buffer, sizeof(buffer), info->power.flags);
440           printf("%s", buffer);
441
442           /* Let's check if nothing (simply on) */
443           if(info->power.flags == IW_POWER_ON)
444             printf(":on");
445           printf("\n          ");
446         }
447     }
448
449   /* Display statistics */
450   if(info->has_stats)
451     {
452       iw_print_stats(buffer, sizeof(buffer),
453                      &info->stats.qual, &info->range, info->has_range);
454       printf("Link %s\n", buffer);
455
456       if(info->range.we_version_compiled > 11)
457         printf("          Rx invalid nwid:%d  Rx invalid crypt:%d  Rx invalid frag:%d\n          Tx excessive retries:%d  Invalid misc:%d   Missed beacon:%d\n",
458                info->stats.discard.nwid,
459                info->stats.discard.code,
460                info->stats.discard.fragment,
461                info->stats.discard.retries,
462                info->stats.discard.misc,
463                info->stats.miss.beacon);
464       else
465         printf("          Rx invalid nwid:%d  invalid crypt:%d  invalid misc:%d\n",
466                info->stats.discard.nwid,
467                info->stats.discard.code,
468                info->stats.discard.misc);
469     }
470
471   printf("\n");
472 }
473
474 /*------------------------------------------------------------------*/
475 /*
476  * Print on the screen in a neat fashion all the info we have collected
477  * on a device.
478  */
479 static int
480 print_info(int          skfd,
481            char *       ifname,
482            char *       args[],
483            int          count)
484 {
485   struct wireless_info  info;
486   int                   rc;
487
488   /* Avoid "Unused parameter" warning */
489   args = args; count = count;
490
491   rc = get_info(skfd, ifname, &info);
492   switch(rc)
493     {
494     case 0:     /* Success */
495       /* Display it ! */
496       display_info(&info, ifname);
497       break;
498
499     case -ENOTSUP:
500       fprintf(stderr, "%-8.16s  no wireless extensions.\n\n",
501               ifname);
502       break;
503
504     default:
505       fprintf(stderr, "%-8.16s  %s\n\n", ifname, strerror(-rc));
506     }
507   return(rc);
508 }
509
510 /************************* SETTING ROUTINES **************************/
511
512 /*------------------------------------------------------------------*/
513 /*
514  * Macro to handle errors when setting WE
515  * Print a nice error message and exit...
516  * We define them as macro so that "return" do the right thing.
517  * The "do {...} while(0)" is a standard trick
518  */
519 #define ERR_SET_EXT(rname, request) \
520         fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", \
521                 rname, request)
522
523 #define ABORT_ARG_NUM(rname, request) \
524         do { \
525                 ERR_SET_EXT(rname, request); \
526                 fprintf(stderr, "    too few arguments.\n"); \
527                 return(-1); \
528         } while(0)
529
530 #define ABORT_ARG_TYPE(rname, request, arg) \
531         do { \
532                 ERR_SET_EXT(rname, request); \
533                 fprintf(stderr, "    invalid argument \"%s\".\n", arg); \
534                 return(-2); \
535         } while(0)
536
537 #define ABORT_ARG_SIZE(rname, request, max) \
538         do { \
539                 ERR_SET_EXT(rname, request); \
540                 fprintf(stderr, "    argument too big (max %d)\n", max); \
541                 return(-3); \
542         } while(0)
543
544 /*------------------------------------------------------------------*/
545 /*
546  * Wrapper to push some Wireless Parameter in the driver
547  * Use standard wrapper and add pretty error message if fail...
548  */
549 #define IW_SET_EXT_ERR(skfd, ifname, request, wrq, rname) \
550         do { \
551         if(iw_set_ext(skfd, ifname, request, wrq) < 0) { \
552                 ERR_SET_EXT(rname, request); \
553                 fprintf(stderr, "    SET failed on device %-1.16s ; %s.\n", \
554                         ifname, strerror(errno)); \
555                 return(-5); \
556         } } while(0)
557
558 /*------------------------------------------------------------------*/
559 /*
560  * Wrapper to extract some Wireless Parameter out of the driver
561  * Use standard wrapper and add pretty error message if fail...
562  */
563 #define IW_GET_EXT_ERR(skfd, ifname, request, wrq, rname) \
564         do { \
565         if(iw_get_ext(skfd, ifname, request, wrq) < 0) { \
566                 ERR_SET_EXT(rname, request); \
567                 fprintf(stderr, "    GET failed on device %-1.16s ; %s.\n", \
568                         ifname, strerror(errno)); \
569                 return(-6); \
570         } } while(0)
571
572 /*------------------------------------------------------------------*/
573 /*
574  * Set the wireless options requested on command line
575  * This function is too long and probably should be split,
576  * because it look like the perfect definition of spaghetti code,
577  * but I'm way to lazy
578  */
579 static int
580 set_info(int            skfd,           /* The socket */
581          char *         args[],         /* Command line args */
582          int            count,          /* Args count */
583          char *         ifname)         /* Dev name */
584 {
585   struct iwreq          wrq;
586   int                   i;
587
588   /* if nothing after the device name - will never happen */
589   if(count < 1)
590     {
591       fprintf(stderr, "Error : too few arguments.\n");
592       return(-1);
593     }
594
595   /* The other args on the line specify options to be set... */
596   for(i = 0; i < count; i++)
597     {
598       /* ---------- Commit changes to driver ---------- */
599       if(!strncmp(args[i], "commit", 6))
600         {
601           /* No args */
602           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWCOMMIT, &wrq,
603                          "Commit changes");
604           continue;
605         }
606
607       /* ---------- Set network ID ---------- */
608       if((!strcasecmp(args[i], "nwid")) ||
609          (!strcasecmp(args[i], "domain")))
610         {
611           i++;
612           if(i >= count)
613             ABORT_ARG_NUM("Set NWID", SIOCSIWNWID);
614           if((!strcasecmp(args[i], "off")) ||
615              (!strcasecmp(args[i], "any")))
616             wrq.u.nwid.disabled = 1;
617           else
618             if(!strcasecmp(args[i], "on"))
619               {
620                 /* Get old nwid */
621                 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWNWID, &wrq,
622                                "Set NWID");
623                 wrq.u.nwid.disabled = 0;
624               }
625             else
626               if(sscanf(args[i], "%lX", (unsigned long *) &(wrq.u.nwid.value))
627                  != 1)
628                 ABORT_ARG_TYPE("Set NWID", SIOCSIWNWID, args[i]);
629               else
630                 wrq.u.nwid.disabled = 0;
631           wrq.u.nwid.fixed = 1;
632
633           /* Set new nwid */
634           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNWID, &wrq,
635                          "Set NWID");
636           continue;
637         }
638
639       /* ---------- Set frequency / channel ---------- */
640       if((!strncmp(args[i], "freq", 4)) ||
641          (!strcmp(args[i], "channel")))
642         {
643           double                freq;
644
645           if(++i >= count)
646             ABORT_ARG_NUM("Set Frequency", SIOCSIWFREQ);
647           if(!strcasecmp(args[i], "auto"))
648             {
649               wrq.u.freq.m = -1;
650               wrq.u.freq.e = 0;
651               wrq.u.freq.flags = 0;
652             }
653           else
654             {
655               if(!strcasecmp(args[i], "fixed"))
656                 {
657                   /* Get old bitrate */
658                   IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFREQ, &wrq,
659                                  "Set Bit Rate");
660                   wrq.u.freq.flags = IW_FREQ_FIXED;
661                 }
662               else                      /* Should be a numeric value */
663                 {
664                   if(sscanf(args[i], "%lg", &(freq)) != 1)
665                     ABORT_ARG_TYPE("Set Frequency", SIOCSIWFREQ, args[i]);
666                   if(index(args[i], 'G')) freq *= GIGA;
667                   if(index(args[i], 'M')) freq *= MEGA;
668                   if(index(args[i], 'k')) freq *= KILO;
669
670                   iw_float2freq(freq, &(wrq.u.freq));
671
672                   wrq.u.freq.flags = IW_FREQ_FIXED;
673
674                   /* Check for an additional argument */
675                   if(((i+1) < count) &&
676                      (!strcasecmp(args[i+1], "auto")))
677                     {
678                       wrq.u.freq.flags = 0;
679                       ++i;
680                     }
681                   if(((i+1) < count) &&
682                      (!strcasecmp(args[i+1], "fixed")))
683                     {
684                       wrq.u.freq.flags = IW_FREQ_FIXED;
685                       ++i;
686                     }
687                 }
688             }
689
690           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFREQ, &wrq,
691                          "Set Frequency");
692           continue;
693         }
694
695       /* ---------- Set sensitivity ---------- */
696       if(!strncmp(args[i], "sens", 4))
697         {
698           if(++i >= count)
699             ABORT_ARG_NUM("Set Sensitivity", SIOCSIWSENS);
700           if(sscanf(args[i], "%i", &(wrq.u.sens.value)) != 1)
701             ABORT_ARG_TYPE("Set Sensitivity", SIOCSIWSENS, args[i]);
702
703           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWSENS, &wrq,
704                          "Set Sensitivity");
705           continue;
706         }
707
708       /* ---------- Set encryption stuff ---------- */
709       if((!strncmp(args[i], "enc", 3)) ||
710          (!strcmp(args[i], "key")))
711         {
712           unsigned char key[IW_ENCODING_TOKEN_MAX];
713
714           if(++i >= count)
715             ABORT_ARG_NUM("Set Encode", SIOCSIWENCODE);
716
717           if(!strcasecmp(args[i], "on"))
718             {
719               /* Get old encryption information */
720               wrq.u.data.pointer = (caddr_t) key;
721               wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
722               wrq.u.data.flags = 0;
723               IW_GET_EXT_ERR(skfd, ifname, SIOCGIWENCODE, &wrq,
724                              "Set Encode");
725               wrq.u.data.flags &= ~IW_ENCODE_DISABLED;  /* Enable */
726             }
727           else
728             {
729               int       gotone = 0;
730               int       oldone;
731               int       keylen;
732               int       temp;
733
734               wrq.u.data.pointer = (caddr_t) NULL;
735               wrq.u.data.flags = 0;
736               wrq.u.data.length = 0;
737
738               /* Allow arguments in any order (it's safe) */
739               do
740                 {
741                   oldone = gotone;
742
743                   /* -- Check for the key -- */
744                   if(i < count)
745                     {
746                       keylen = iw_in_key_full(skfd, ifname,
747                                               args[i], key, &wrq.u.data.flags);
748                       if(keylen > 0)
749                         {
750                           wrq.u.data.length = keylen;
751                           wrq.u.data.pointer = (caddr_t) key;
752                           ++i;
753                           gotone++;
754                         }
755                     }
756
757                   /* -- Check for token index -- */
758                   if((i < count) &&
759                      (sscanf(args[i], "[%i]", &temp) == 1) &&
760                      (temp > 0) && (temp < IW_ENCODE_INDEX))
761                     {
762                       wrq.u.encoding.flags |= temp;
763                       ++i;
764                       gotone++;
765                     }
766
767                   /* -- Check the various flags -- */
768                   if((i < count) && (!strcasecmp(args[i], "off")))
769                     {
770                       wrq.u.data.flags |= IW_ENCODE_DISABLED;
771                       ++i;
772                       gotone++;
773                     }
774                   if((i < count) && (!strcasecmp(args[i], "open")))
775                     {
776                       wrq.u.data.flags |= IW_ENCODE_OPEN;
777                       ++i;
778                       gotone++;
779                     }
780                   if((i < count) && (!strncasecmp(args[i], "restricted", 5)))
781                     {
782                       wrq.u.data.flags |= IW_ENCODE_RESTRICTED;
783                       ++i;
784                       gotone++;
785                     }
786                   if((i < count) && (!strncasecmp(args[i], "temporary", 4)))
787                     {
788                       wrq.u.data.flags |= IW_ENCODE_TEMP;
789                       ++i;
790                       gotone++;
791                     }
792                 }
793               while(gotone != oldone);
794
795               /* Pointer is absent in new API */
796               if(wrq.u.data.pointer == NULL)
797                 wrq.u.data.flags |= IW_ENCODE_NOKEY;
798
799               /* Check if we have any invalid argument */
800               if(!gotone)
801                 ABORT_ARG_TYPE("Set Encode", SIOCSIWENCODE, args[i]);
802               /* Get back to last processed argument */
803               --i;
804             }
805
806           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWENCODE, &wrq,
807                          "Set Encode");
808           continue;
809         }
810
811       /* ---------- Set ESSID ---------- */
812       if(!strcasecmp(args[i], "essid"))
813         {
814           char          essid[IW_ESSID_MAX_SIZE + 1];
815
816           i++;
817           if(i >= count)
818             ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
819           if((!strcasecmp(args[i], "off")) ||
820              (!strcasecmp(args[i], "any")))
821             {
822               wrq.u.essid.flags = 0;
823               essid[0] = '\0';
824             }
825           else
826             if(!strcasecmp(args[i], "on"))
827               {
828                 /* Get old essid */
829                 wrq.u.essid.pointer = (caddr_t) essid;
830                 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
831                 wrq.u.essid.flags = 0;
832                 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWESSID, &wrq,
833                                "Set ESSID");
834                 wrq.u.essid.flags = 1;
835               }
836             else
837               {
838                 /* '-' allow to escape the ESSID string, allowing
839                  * to set it to the string "any" or "off".
840                  * This is a big ugly, but it will do for now */
841                 if(!strcmp(args[i], "-"))
842                   {
843                     i++;
844                     if(i >= count)
845                       ABORT_ARG_NUM("Set ESSID", SIOCSIWESSID);
846                   }
847
848                 /* Check the size of what the user passed us to avoid
849                  * buffer overflows */
850                 if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
851                   ABORT_ARG_SIZE("Set ESSID", SIOCSIWESSID, IW_ESSID_MAX_SIZE);
852                 else
853                   {
854                     int         temp;
855
856                     wrq.u.essid.flags = 1;
857                     strcpy(essid, args[i]);     /* Size checked, all clear */
858
859                     /* Check for ESSID index */
860                     if(((i+1) < count) &&
861                        (sscanf(args[i+1], "[%i]", &temp) == 1) &&
862                        (temp > 0) && (temp < IW_ENCODE_INDEX))
863                       {
864                         wrq.u.essid.flags = temp;
865                         ++i;
866                       }
867                   }
868               }
869
870           wrq.u.essid.pointer = (caddr_t) essid;
871           wrq.u.essid.length = strlen(essid) + 1;
872           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWESSID, &wrq,
873                          "Set ESSID");
874           continue;
875         }
876
877       /* ---------- Set AP address ---------- */
878       if(!strcasecmp(args[i], "ap"))
879         {
880           if(++i >= count)
881             ABORT_ARG_NUM("Set AP Address", SIOCSIWAP);
882
883           if((!strcasecmp(args[i], "auto")) ||
884              (!strcasecmp(args[i], "any")))
885             {
886               /* Send a broadcast address */
887               iw_broad_ether(&(wrq.u.ap_addr));
888             }
889           else
890             {
891               if(!strcasecmp(args[i], "off"))
892                 {
893                   /* Send a NULL address */
894                   iw_null_ether(&(wrq.u.ap_addr));
895                 }
896               else
897                 {
898                   /* Get the address and check if the interface supports it */
899                   if(iw_in_addr(skfd, ifname, args[i++], &(wrq.u.ap_addr)) < 0)
900                     ABORT_ARG_TYPE("Set AP Address", SIOCSIWAP, args[i-1]);
901                 }
902             }
903
904           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWAP, &wrq,
905                          "Set AP Address");
906           continue;
907         }
908
909       /* ---------- Set NickName ---------- */
910       if(!strncmp(args[i], "nick", 4))
911         {
912           i++;
913           if(i >= count)
914             ABORT_ARG_NUM("Set Nickname", SIOCSIWNICKN);
915           if(strlen(args[i]) > IW_ESSID_MAX_SIZE)
916             ABORT_ARG_SIZE("Set Nickname", SIOCSIWNICKN, IW_ESSID_MAX_SIZE);
917
918           wrq.u.essid.pointer = (caddr_t) args[i];
919           wrq.u.essid.length = strlen(args[i]) + 1;
920           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWNICKN, &wrq,
921                          "Set Nickname");
922           continue;
923         }
924
925       /* ---------- Set Bit-Rate ---------- */
926       if((!strncmp(args[i], "bit", 3)) ||
927          (!strcmp(args[i], "rate")))
928         {
929           if(++i >= count)
930             ABORT_ARG_NUM("Set Bit Rate", SIOCSIWRATE);
931           if(!strcasecmp(args[i], "auto"))
932             {
933               wrq.u.bitrate.value = -1;
934               wrq.u.bitrate.fixed = 0;
935             }
936           else
937             {
938               if(!strcasecmp(args[i], "fixed"))
939                 {
940                   /* Get old bitrate */
941                   IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRATE, &wrq,
942                                  "Set Bit Rate");
943                   wrq.u.bitrate.fixed = 1;
944                 }
945               else                      /* Should be a numeric value */
946                 {
947                   double                brate;
948
949                   if(sscanf(args[i], "%lg", &(brate)) != 1)
950                     ABORT_ARG_TYPE("Set Bit Rate", SIOCSIWRATE, args[i]);
951                   if(index(args[i], 'G')) brate *= GIGA;
952                   if(index(args[i], 'M')) brate *= MEGA;
953                   if(index(args[i], 'k')) brate *= KILO;
954                   wrq.u.bitrate.value = (long) brate;
955                   wrq.u.bitrate.fixed = 1;
956
957                   /* Check for an additional argument */
958                   if(((i+1) < count) &&
959                      (!strcasecmp(args[i+1], "auto")))
960                     {
961                       wrq.u.bitrate.fixed = 0;
962                       ++i;
963                     }
964                   if(((i+1) < count) &&
965                      (!strcasecmp(args[i+1], "fixed")))
966                     {
967                       wrq.u.bitrate.fixed = 1;
968                       ++i;
969                     }
970                 }
971             }
972
973           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRATE, &wrq,
974                          "Set Bit Rate");
975           continue;
976         }
977
978       /* ---------- Set RTS threshold ---------- */
979       if(!strncasecmp(args[i], "rts", 3))
980         {
981           i++;
982           if(i >= count)
983             ABORT_ARG_NUM("Set RTS Threshold", SIOCSIWRTS);
984           wrq.u.rts.value = -1;
985           wrq.u.rts.fixed = 1;
986           wrq.u.rts.disabled = 0;
987           if(!strcasecmp(args[i], "off"))
988             wrq.u.rts.disabled = 1;     /* i.e. max size */
989           else
990             if(!strcasecmp(args[i], "auto"))
991               wrq.u.rts.fixed = 0;
992             else
993               {
994                 if(!strcasecmp(args[i], "fixed"))
995                   {
996                     /* Get old RTS threshold */
997                     IW_GET_EXT_ERR(skfd, ifname, SIOCGIWRTS, &wrq,
998                                    "Set RTS Threshold");
999                     wrq.u.rts.fixed = 1;
1000                   }
1001                 else                    /* Should be a numeric value */
1002                   if(sscanf(args[i], "%li", (unsigned long *) &(wrq.u.rts.value))
1003                      != 1)
1004                     ABORT_ARG_TYPE("Set RTS Threshold", SIOCSIWRTS, args[i]);
1005             }
1006
1007           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRTS, &wrq,
1008                          "Set RTS Threshold");
1009           continue;
1010         }
1011
1012       /* ---------- Set fragmentation threshold ---------- */
1013       if(!strncmp(args[i], "frag", 4))
1014         {
1015           i++;
1016           if(i >= count)
1017             ABORT_ARG_NUM("Set Fragmentation Threshold", SIOCSIWFRAG);
1018           wrq.u.frag.value = -1;
1019           wrq.u.frag.fixed = 1;
1020           wrq.u.frag.disabled = 0;
1021           if(!strcasecmp(args[i], "off"))
1022             wrq.u.frag.disabled = 1;    /* i.e. max size */
1023           else
1024             if(!strcasecmp(args[i], "auto"))
1025               wrq.u.frag.fixed = 0;
1026             else
1027               {
1028                 if(!strcasecmp(args[i], "fixed"))
1029                   {
1030                     /* Get old fragmentation threshold */
1031                     IW_GET_EXT_ERR(skfd, ifname, SIOCGIWFRAG, &wrq,
1032                                    "Set Fragmentation Threshold");
1033                     wrq.u.frag.fixed = 1;
1034                   }
1035                 else                    /* Should be a numeric value */
1036                   if(sscanf(args[i], "%li",
1037                             (unsigned long *) &(wrq.u.frag.value))
1038                      != 1)
1039                     ABORT_ARG_TYPE("Set Fragmentation Threshold", SIOCSIWFRAG,
1040                                    args[i]);
1041             }
1042
1043           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWFRAG, &wrq,
1044                          "Set Fragmentation Threshold");
1045           continue;
1046         }
1047
1048       /* ---------- Set operation mode ---------- */
1049       if(!strcmp(args[i], "mode"))
1050         {
1051           int   k;
1052
1053           i++;
1054           if(i >= count)
1055             ABORT_ARG_NUM("Set Mode", SIOCSIWMODE);
1056
1057           if(sscanf(args[i], "%i", &k) != 1)
1058             {
1059               k = 0;
1060               while((k < IW_NUM_OPER_MODE) &&
1061                     strncasecmp(args[i], iw_operation_mode[k], 3))
1062                 k++;
1063             }
1064           if((k >= IW_NUM_OPER_MODE) || (k < 0))
1065             ABORT_ARG_TYPE("Set Mode", SIOCSIWMODE, args[i]);
1066
1067           wrq.u.mode = k;
1068           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWMODE, &wrq,
1069                          "Set Mode");
1070           continue;
1071         }
1072
1073       /* ---------- Set Power Management ---------- */
1074       if(!strncmp(args[i], "power", 3))
1075         {
1076           if(++i >= count)
1077             ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1078
1079           if(!strcasecmp(args[i], "off"))
1080             wrq.u.power.disabled = 1;   /* i.e. max size */
1081           else
1082             if(!strcasecmp(args[i], "on"))
1083               {
1084                 /* Get old Power info */
1085                 IW_GET_EXT_ERR(skfd, ifname, SIOCGIWPOWER, &wrq,
1086                                "Set Power Management");
1087                 wrq.u.power.disabled = 0;
1088               }
1089             else
1090               {
1091                 double          temp;
1092                 int             gotone = 0;
1093                 /* Default - nope */
1094                 wrq.u.power.flags = IW_POWER_ON;
1095                 wrq.u.power.disabled = 0;
1096
1097                 /* Check value modifier */
1098                 if(!strcasecmp(args[i], "min"))
1099                   {
1100                     wrq.u.power.flags |= IW_POWER_MIN;
1101                     if(++i >= count)
1102                       ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1103                   }
1104                 else
1105                   if(!strcasecmp(args[i], "max"))
1106                     {
1107                       wrq.u.power.flags |= IW_POWER_MAX;
1108                       if(++i >= count)
1109                         ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1110                     }
1111
1112                 /* Check value type */
1113                 if(!strcasecmp(args[i], "period"))
1114                   {
1115                     wrq.u.power.flags |= IW_POWER_PERIOD;
1116                     if(++i >= count)
1117                       ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1118                   }
1119                 else
1120                   if(!strcasecmp(args[i], "timeout"))
1121                     {
1122                       wrq.u.power.flags |= IW_POWER_TIMEOUT;
1123                       if(++i >= count)
1124                         ABORT_ARG_NUM("Set Power Management", SIOCSIWPOWER);
1125                     }
1126
1127                 /* Is there any value to grab ? */
1128                 if(sscanf(args[i], "%lg", &(temp)) == 1)
1129                   {
1130                     temp *= MEGA;       /* default = s */
1131                     if(index(args[i], 'u')) temp /= MEGA;
1132                     if(index(args[i], 'm')) temp /= KILO;
1133                     wrq.u.power.value = (long) temp;
1134                     if((wrq.u.power.flags & IW_POWER_TYPE) == 0)
1135                       wrq.u.power.flags |= IW_POWER_PERIOD;
1136                     ++i;
1137                     gotone = 1;
1138                   }
1139
1140                 /* Now, check the mode */
1141                 if(i < count)
1142                   {
1143                     if(!strcasecmp(args[i], "all"))
1144                       wrq.u.power.flags |= IW_POWER_ALL_R;
1145                     if(!strncasecmp(args[i], "unicast", 4))
1146                       wrq.u.power.flags |= IW_POWER_UNICAST_R;
1147                     if(!strncasecmp(args[i], "multicast", 5))
1148                       wrq.u.power.flags |= IW_POWER_MULTICAST_R;
1149                     if(!strncasecmp(args[i], "force", 5))
1150                       wrq.u.power.flags |= IW_POWER_FORCE_S;
1151                     if(!strcasecmp(args[i], "repeat"))
1152                       wrq.u.power.flags |= IW_POWER_REPEATER;
1153                     if(wrq.u.power.flags & IW_POWER_MODE)
1154                       {
1155                         ++i;
1156                         gotone = 1;
1157                       }
1158                   }
1159                 if(!gotone)
1160                   ABORT_ARG_TYPE("Set Power Management", SIOCSIWPOWER,
1161                                  args[i]);
1162                 --i;
1163               }
1164
1165           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWPOWER, &wrq,
1166                        "Set Power Management");
1167           continue;
1168         }
1169
1170       /* ---------- Set Transmit-Power ---------- */
1171       if(!strncmp(args[i], "txpower", 3))
1172         {
1173           struct iw_range       range;
1174
1175           if(++i >= count)
1176             ABORT_ARG_NUM("Set Tx Power", SIOCSIWTXPOW);
1177
1178           /* Extract range info */
1179           if(iw_get_range_info(skfd, ifname, &range) < 0)
1180             memset(&range, 0, sizeof(range));
1181
1182           /* Prepare the request */
1183           wrq.u.txpower.value = -1;
1184           wrq.u.txpower.fixed = 1;
1185           wrq.u.txpower.disabled = 0;
1186           wrq.u.txpower.flags = IW_TXPOW_DBM;
1187           if(!strcasecmp(args[i], "off"))
1188             wrq.u.txpower.disabled = 1; /* i.e. turn radio off */
1189           else
1190             if(!strcasecmp(args[i], "auto"))
1191               wrq.u.txpower.fixed = 0;  /* i.e. use power control */
1192             else
1193               {
1194                 if(!strcasecmp(args[i], "on"))
1195                   {
1196                     /* Get old tx-power */
1197                     IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1198                                    "Set Tx Power");
1199                     wrq.u.txpower.disabled = 0;
1200                   }
1201                 else
1202                   {
1203                     if(!strcasecmp(args[i], "fixed"))
1204                       {
1205                         /* Get old tx-power */
1206                         IW_GET_EXT_ERR(skfd, ifname, SIOCGIWTXPOW, &wrq,
1207                                        "Set Tx Power");
1208                         wrq.u.txpower.fixed = 1;
1209                         wrq.u.txpower.disabled = 0;
1210                       }
1211                     else                        /* Should be a numeric value */
1212                       {
1213                         int             power;
1214                         int             ismwatt = 0;
1215
1216                         /* Get the value */
1217                         if(sscanf(args[i], "%i", &(power)) != 1)
1218                           ABORT_ARG_TYPE("Set Tx Power", SIOCSIWTXPOW,
1219                                          args[i]);
1220
1221                         /* Check if milliwatt */
1222                         ismwatt = (index(args[i], 'm') != NULL);
1223
1224                         /* Convert */
1225                         if(range.txpower_capa & IW_TXPOW_RELATIVE)
1226                           {
1227                             /* Can't convert */
1228                             if(ismwatt)
1229                               ABORT_ARG_TYPE("Set Tx Power",
1230                                              SIOCSIWTXPOW,
1231                                              args[i]);
1232                           }
1233                         else
1234                           if(range.txpower_capa & IW_TXPOW_MWATT)
1235                             {
1236                               if(!ismwatt)
1237                                 power = iw_dbm2mwatt(power);
1238                               wrq.u.txpower.flags = IW_TXPOW_MWATT;
1239                             }
1240                           else
1241                             {
1242                               if(ismwatt)
1243                                 power = iw_mwatt2dbm(power);
1244                               wrq.u.txpower.flags = IW_TXPOW_DBM;
1245                             }
1246                         wrq.u.txpower.value = power;
1247
1248                         /* Check for an additional argument */
1249                         if(((i+1) < count) &&
1250                            (!strcasecmp(args[i+1], "auto")))
1251                           {
1252                             wrq.u.txpower.fixed = 0;
1253                             ++i;
1254                           }
1255                         if(((i+1) < count) &&
1256                            (!strcasecmp(args[i+1], "fixed")))
1257                           {
1258                             wrq.u.txpower.fixed = 1;
1259                             ++i;
1260                           }
1261                       }
1262                   }
1263               }
1264
1265           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWTXPOW, &wrq,
1266                          "Set Tx Power");
1267           continue;
1268         }
1269
1270       /* ---------- Set Retry limit ---------- */
1271       if(!strncmp(args[i], "retry", 3))
1272         {
1273           double                temp;
1274           int           gotone = 0;
1275
1276           if(++i >= count)
1277             ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1278
1279           /* Default - nope */
1280           wrq.u.retry.flags = IW_RETRY_LIMIT;
1281           wrq.u.retry.disabled = 0;
1282
1283           /* Check value modifier */
1284           if(!strcasecmp(args[i], "min"))
1285             {
1286               wrq.u.retry.flags |= IW_RETRY_MIN;
1287               if(++i >= count)
1288                 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1289             }
1290           else
1291             if(!strcasecmp(args[i], "max"))
1292               {
1293                 wrq.u.retry.flags |= IW_RETRY_MAX;
1294                 if(++i >= count)
1295                   ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1296               }
1297
1298           /* Check value type */
1299           if(!strcasecmp(args[i], "limit"))
1300             {
1301               wrq.u.retry.flags |= IW_RETRY_LIMIT;
1302               if(++i >= count)
1303                 ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1304             }
1305           else
1306             if(!strncasecmp(args[i], "lifetime", 4))
1307               {
1308                 wrq.u.retry.flags &= ~IW_RETRY_LIMIT;
1309                 wrq.u.retry.flags |= IW_RETRY_LIFETIME;
1310                 if(++i >= count)
1311                   ABORT_ARG_NUM("Set Retry Limit", SIOCSIWRETRY);
1312               }
1313
1314           /* Is there any value to grab ? */
1315           if(sscanf(args[i], "%lg", &(temp)) == 1)
1316             {
1317               /* Limit is absolute, on the other hand lifetime is seconds */
1318               if(!(wrq.u.retry.flags & IW_RETRY_LIMIT))
1319                 {
1320                   /* Normalise lifetime */
1321                   temp *= MEGA; /* default = s */
1322                   if(index(args[i], 'u')) temp /= MEGA;
1323                   if(index(args[i], 'm')) temp /= KILO;
1324                 }
1325               wrq.u.retry.value = (long) temp;
1326               ++i;
1327               gotone = 1;
1328             }
1329
1330           if(!gotone)
1331             ABORT_ARG_TYPE("Set Retry Limit", SIOCSIWRETRY, args[i]);
1332           --i;
1333
1334           IW_SET_EXT_ERR(skfd, ifname, SIOCSIWRETRY, &wrq,
1335                          "Set Retry Limit");
1336           continue;
1337         }
1338
1339       /* ---------- Other ---------- */
1340       /* Here we have an unrecognised arg... */
1341       fprintf(stderr, "Error : unrecognised wireless request \"%s\"\n",
1342               args[i]);
1343       return(-1);
1344     }           /* for(index ... */
1345   return(0);
1346 }
1347
1348 /******************************* MAIN ********************************/
1349
1350 /*------------------------------------------------------------------*/
1351 /*
1352  * The main !
1353  */
1354 int
1355 main(int        argc,
1356      char **    argv)
1357 {
1358   int skfd;             /* generic raw socket desc.     */
1359   int goterr = 0;
1360
1361   /* Create a channel to the NET kernel. */
1362   if((skfd = iw_sockets_open()) < 0)
1363     {
1364       perror("socket");
1365       exit(-1);
1366     }
1367
1368   /* No argument : show the list of all device + info */
1369   if(argc == 1)
1370     iw_enum_devices(skfd, &print_info, NULL, 0);
1371   else
1372     /* Special case for help... */
1373     if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
1374       iw_usage();
1375     else
1376       /* Special case for version... */
1377       if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
1378         goterr = iw_print_version_info("iwconfig");
1379       else
1380         /* The device name must be the first argument */
1381         if(argc == 2)
1382           print_info(skfd, argv[1], NULL, 0);
1383         else
1384           /* The other args on the line specify options to be set... */
1385           goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
1386
1387   /* Close the socket. */
1388   iw_sockets_close(skfd);
1389
1390   return(goterr);
1391 }