OSDN Git Service

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