OSDN Git Service

v23
[android-x86/external-wireless-tools.git] / wireless_tools / iwgetid.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPL '01
5  *
6  * Just print the ESSID or NWID...
7  *
8  * This file is released under the GPL license.
9  *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
10  */
11
12 #include "iwlib.h"              /* Header */
13
14 #define FORMAT_DEFAULT  0       /* Nice looking display for the user */
15 #define FORMAT_SCHEME   1       /* To be used as a Pcmcia Scheme */
16
17 /*
18  * Note on Pcmcia Schemes :
19  * ----------------------
20  *      The purpose of this tool is to use the ESSID discovery mechanism
21  * to select the appropriate Pcmcia Scheme. The card tell us which
22  * ESSID it has found, and we can then select the appropriate Pcmcia
23  * Scheme for this ESSID (Wireless config (encrypt keys) and IP config).
24  *      The way to do it is as follows :
25  *                      cardctl scheme "essidany"
26  *                      delay 100
27  *                      $scheme = iwgetid --scheme
28  *                      cardctl scheme $scheme
29  *      Of course, you need to add a scheme called "essidany" with the
30  * following setting :
31  *                      essidany,*,*,*)
32  *                              ESSID="any"
33  *                              IPADDR="10.0.0.1"
34  *
35  *      This can also be integrated int he Pcmcia scripts.
36  *      Some drivers don't activate the card up to "ifconfig up".
37  * Therefore, they wont scan ESSID up to this point, so we can't
38  * read it reliably in Pcmcia scripts.
39  *      I guess the proper way to write the network script is as follows :
40  *                      if($scheme == "iwgetid") {
41  *                              iwconfig $name essid any
42  *                              iwconfig $name nwid any
43  *                              ifconfig $name up
44  *                              delay 100
45  *                              $scheme = iwgetid $name --scheme
46  *                              ifconfig $name down
47  *                      }
48  *
49  *      This is pseudo code, but you get an idea...
50  *      The "ifconfig up" activate the card.
51  *      The "delay" is necessary to let time for the card scan the
52  * frequencies and associate with the AP.
53  *      The "ifconfig down" is necessary to allow the driver to optimise
54  * the wireless parameters setting (minimise number of card resets).
55  *
56  *      Another cute idea is to have a list of Pcmcia Schemes to try
57  * and to keep the first one that associate (AP address != 0). This
58  * would be necessary for closed networks and cards that can't
59  * discover essid...
60  *
61  * Jean II - 29/3/01
62  */
63
64 /************************ DISPLAY ESSID/NWID ************************/
65
66 /*------------------------------------------------------------------*/
67 /*
68  * Display the ESSID if possible
69  */
70 static int
71 print_essid(int         skfd,
72             char *      ifname,
73             int         format)
74 {
75   struct iwreq          wrq;
76   char                  essid[IW_ESSID_MAX_SIZE + 1];   /* ESSID */
77   char                  pessid[IW_ESSID_MAX_SIZE + 1];  /* Pcmcia format */
78   int           i;
79   int           j;
80
81   /* Get ESSID */
82   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
83   wrq.u.essid.pointer = (caddr_t) essid;
84   wrq.u.essid.length = 0;
85   wrq.u.essid.flags = 0;
86   if(ioctl(skfd, SIOCGIWESSID, &wrq) < 0)
87     return(-1);
88
89   switch(format)
90     {
91     case FORMAT_SCHEME:
92       /* Stip all white space and stuff */
93       j = 0;
94       for(i = 0; i < strlen(essid); i++)
95         if(isalnum(essid[i]))
96           pessid[j++] = essid[i];
97       pessid[j] = '\0';
98       if((j == 0) || (j > 32))
99         return(-2);
100       printf("%s\n", pessid);
101       fflush(stdout);
102       break;
103     default:
104       printf("%-8.8s  ESSID:\"%s\"\n", ifname, essid);
105       break;
106     }
107
108   return(0);
109 }
110
111 /*------------------------------------------------------------------*/
112 /*
113  * Display the NWID if possible
114  */
115 static int
116 print_nwid(int          skfd,
117            char *       ifname,
118            int          format)
119 {
120   struct iwreq          wrq;
121
122   /* Get network ID */
123   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
124   if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0)
125     return(-1);
126
127   switch(format)
128     {
129     case FORMAT_SCHEME:
130       /* Prefix with nwid to avoid name space collisions */
131       printf("nwid%X\n", wrq.u.nwid.value);
132       fflush(stdout);
133       break;
134     default:
135       printf("%-8.8s  NWID:%X\n", ifname, wrq.u.nwid.value);
136       break;
137     }
138
139   return(0);
140 }
141
142 /*------------------------------------------------------------------*/
143 /*
144  * Try the various devices until one return something we can use
145  */
146 static int
147 scan_devices(int                skfd,
148              int                format)
149 {
150   char          buff[1024];
151   struct ifconf ifc;
152   struct ifreq *ifr;
153   int           i;
154   int           ret;
155
156   /* Get list of active devices */
157   ifc.ifc_len = sizeof(buff);
158   ifc.ifc_buf = buff;
159   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
160     {
161       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
162       return(-1);
163     }
164   ifr = ifc.ifc_req;
165
166   /* Print the first match */
167   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
168     {
169       /* Try to print an ESSID */
170       ret = print_essid(skfd, ifr->ifr_name, format);
171       if(ret == 0)
172         return(0);      /* Success */
173
174       /* Try to print a nwid */
175       ret = print_nwid(skfd, ifr->ifr_name, format);
176       if(ret == 0)
177         return(0);      /* Success */
178     }
179   return(-1);
180 }
181
182 /*************************** SUBROUTINES ***************************/
183
184 /*------------------------------------------------------------------*/
185 /*
186  * Display an Ethernet address in readable format.
187  */
188 char *
189 pr_ether(char *         buffer,
190          unsigned char *ptr)
191 {
192   sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X",
193           (ptr[0] & 0xFF), (ptr[1] & 0xFF), (ptr[2] & 0xFF),
194           (ptr[3] & 0xFF), (ptr[4] & 0xFF), (ptr[5] & 0xFF)
195   );
196   return(buffer);
197 }
198
199 /*------------------------------------------------------------------*/
200 /*
201  * Open a socket.
202  * Depending on the protocol present, open the right socket. The socket
203  * will allow us to talk to the driver.
204  */
205 int
206 sockets_open(void)
207 {
208         int ipx_sock = -1;              /* IPX socket                   */
209         int ax25_sock = -1;             /* AX.25 socket                 */
210         int inet_sock = -1;             /* INET socket                  */
211         int ddp_sock = -1;              /* Appletalk DDP socket         */
212
213         inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
214         ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
215         ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
216         ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
217         /*
218          * Now pick any (exisiting) useful socket family for generic queries
219          */
220         if(inet_sock!=-1)
221                 return inet_sock;
222         if(ipx_sock!=-1)
223                 return ipx_sock;
224         if(ax25_sock!=-1)
225                 return ax25_sock;
226         /*
227          * If this is -1 we have no known network layers and its time to jump.
228          */
229          
230         return ddp_sock;
231 }
232
233 /**************************** AP ADDRESS ****************************/
234
235 /*------------------------------------------------------------------*/
236 /*
237  * Display the NWID if possible
238  */
239 static int
240 print_ap(int            skfd,
241          char *         ifname,
242          int            format)
243 {
244   struct iwreq          wrq;
245   char                  buffer[64];
246
247   /* Get network ID */
248   strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
249   if(ioctl(skfd, SIOCGIWAP, &wrq) < 0)
250     return(-1);
251
252   /* Print */
253   printf("%-8.8s  Access Point: %s\n", ifname,
254          pr_ether(buffer, wrq.u.ap_addr.sa_data));
255
256   return(0);
257 }
258
259 /*------------------------------------------------------------------*/
260 /*
261  * Try the various devices until one return something we can use
262  */
263 static inline int
264 scan_ap(int             skfd,
265         int             format)
266 {
267   char          buff[1024];
268   struct ifconf ifc;
269   struct ifreq *ifr;
270   int           i;
271   int           ret;
272
273   /* Get list of active devices */
274   ifc.ifc_len = sizeof(buff);
275   ifc.ifc_buf = buff;
276   if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
277     {
278       fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
279       return(-1);
280     }
281   ifr = ifc.ifc_req;
282
283   /* Print the first match */
284   for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
285     {
286       /* Try to print an ESSID */
287       ret = print_ap(skfd, ifr->ifr_name, format);
288       if(ret == 0)
289         return(0);      /* Success */
290     }
291   return(-1);
292 }
293
294 /******************************* MAIN ********************************/
295
296 /*------------------------------------------------------------------*/
297 /*
298  * The main !
299  */
300 int
301 main(int        argc,
302      char **    argv)
303 {
304   int   skfd = -1;              /* generic raw socket desc.     */
305   int   format = FORMAT_DEFAULT;
306   int   ret = -1;
307
308   /* Create a channel to the NET kernel. */
309   if((skfd = sockets_open()) < 0)
310     {
311       perror("socket");
312       return(-1);
313     }
314
315   /* No argument */
316   if(argc == 1)
317     {
318       /* Look on all devices */
319       ret = scan_devices(skfd, format);
320       close(skfd);
321       return(ret);
322     }
323
324   /* Only ask for first AP address */
325   if((!strcmp(argv[1], "--ap")) || (!strcmp(argv[1], "-a")))
326     {
327       /* Look on all devices */
328       ret = scan_ap(skfd, format);
329       close(skfd);
330       return(ret);
331     }
332
333   /* Only the format, no interface name */
334   if((!strncmp(argv[1], "--scheme", 4)) || (!strcmp(argv[1], "-s")))
335     {
336       /* Look on all devices */
337       format = FORMAT_SCHEME;
338       ret = scan_devices(skfd, format);
339       close(skfd);
340       return(ret);
341     }
342
343   /* Help */
344   if((argc > 3) ||
345      (!strncmp(argv[1], "-h", 9)) || (!strcmp(argv[1], "--help")))
346     {
347       fprintf(stderr, "Usage: iwgetid [interface]\n");
348       fprintf(stderr, "               [interface] --scheme\n");
349       return(-1);
350     }
351
352   /* If at least a device name */
353   if(argc > 1)
354     {
355       /* Check extra format argument */
356       if(argc > 2)
357         {
358           /* Only ask for first AP address */
359           if((!strcmp(argv[2], "--ap")) || (!strcmp(argv[2], "-a")))
360             {
361               ret = print_ap(skfd, argv[1], format);
362               close(skfd);
363               return(ret);
364             }
365
366           /* Want scheme format */
367           if((!strncmp(argv[2], "--scheme", 4)) || (!strcmp(argv[2], "-s")))
368             format = FORMAT_SCHEME;
369         }
370
371       /* Try to print an ESSID */
372       ret = print_essid(skfd, argv[1], format);
373
374       if(ret == -1)
375         {
376           /* Try to print a nwid */
377           ret = print_nwid(skfd, argv[1], format);
378         }
379     }
380
381   /* Close the socket. */
382   close(skfd);
383
384   return(ret);
385 }