OSDN Git Service

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