nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 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-2004 Jean Tourrilhes <jt@hpl.hp.com>
10 */
11  
12 #include "iwlib.h" /* Header */
13  
14 #include <getopt.h>
15  
16 /*
17 * Note on Pcmcia Schemes :
18 * ----------------------
19 * The purpose of this tool is to use the ESSID discovery mechanism
20 * to select the appropriate Pcmcia Scheme. The card tell us which
21 * ESSID it has found, and we can then select the appropriate Pcmcia
22 * Scheme for this ESSID (Wireless config (encrypt keys) and IP config).
23 * The way to do it is as follows :
24 * cardctl scheme "essidany"
25 * delay 100
26 * $scheme = iwgetid --scheme
27 * cardctl scheme $scheme
28 * Of course, you need to add a scheme called "essidany" with the
29 * following setting :
30 * essidany,*,*,*)
31 * ESSID="any"
32 * IPADDR="10.0.0.1"
33 *
34 * This can also be integrated int he Pcmcia scripts.
35 * Some drivers don't activate the card up to "ifconfig up".
36 * Therefore, they wont scan ESSID up to this point, so we can't
37 * read it reliably in Pcmcia scripts.
38 * I guess the proper way to write the network script is as follows :
39 * if($scheme == "iwgetid") {
40 * iwconfig $name essid any
41 * iwconfig $name nwid any
42 * ifconfig $name up
43 * delay 100
44 * $scheme = iwgetid $name --scheme
45 * ifconfig $name down
46 * }
47 *
48 * This is pseudo code, but you get an idea...
49 * The "ifconfig up" activate the card.
50 * The "delay" is necessary to let time for the card scan the
51 * frequencies and associate with the AP.
52 * The "ifconfig down" is necessary to allow the driver to optimise
53 * the wireless parameters setting (minimise number of card resets).
54 *
55 * Another cute idea is to have a list of Pcmcia Schemes to try
56 * and to keep the first one that associate (AP address != 0). This
57 * would be necessary for closed networks and cards that can't
58 * discover essid...
59 *
60 * Jean II - 29/3/01
61 */
62  
63 /**************************** CONSTANTS ****************************/
64  
65 #define FORMAT_DEFAULT 0 /* Nice looking display for the user */
66 #define FORMAT_SCHEME 1 /* To be used as a Pcmcia Scheme */
67 #define FORMAT_RAW 2 /* Raw value, for shell scripts */
68 #define WTYPE_ESSID 0 /* Display ESSID or NWID */
69 #define WTYPE_AP 1 /* Display AP/Cell Address */
70 #define WTYPE_FREQ 2 /* Display frequency/channel */
71 #define WTYPE_CHANNEL 3 /* Display channel (converted from freq) */
72 #define WTYPE_MODE 4 /* Display mode */
73 #define WTYPE_PROTO 5 /* Display protocol name */
74  
75 /************************ DISPLAY ESSID/NWID ************************/
76  
77 /*------------------------------------------------------------------*/
78 /*
79 * Display the ESSID if possible
80 */
81 static int
82 print_essid(int skfd,
83 const char * ifname,
84 int format)
85 {
86 struct iwreq wrq;
87 char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID */
88 char pessid[IW_ESSID_MAX_SIZE + 1]; /* Pcmcia format */
89 unsigned int i;
90 unsigned int j;
91  
92 /* Make sure ESSID is always NULL terminated */
93 memset(essid, 0, sizeof(essid));
94  
95 /* Get ESSID */
96 wrq.u.essid.pointer = (caddr_t) essid;
97 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
98 wrq.u.essid.flags = 0;
99 if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0)
100 return(-1);
101  
102 switch(format)
103 {
104 case FORMAT_SCHEME:
105 /* Strip all white space and stuff */
106 j = 0;
107 for(i = 0; i < strlen(essid); i++)
108 if(isalnum(essid[i]))
109 pessid[j++] = essid[i];
110 pessid[j] = '\0';
111 if((j == 0) || (j > 32))
112 return(-2);
113 printf("%s\n", pessid);
114 break;
115 case FORMAT_RAW:
116 printf("%s\n", essid);
117 break;
118 default:
119 printf("%-8.16s ESSID:\"%s\"\n", ifname, essid);
120 break;
121 }
122  
123 return(0);
124 }
125  
126 /*------------------------------------------------------------------*/
127 /*
128 * Display the NWID if possible
129 */
130 static int
131 print_nwid(int skfd,
132 const char * ifname,
133 int format)
134 {
135 struct iwreq wrq;
136  
137 /* Get network ID */
138 if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0)
139 return(-1);
140  
141 switch(format)
142 {
143 case FORMAT_SCHEME:
144 /* Prefix with nwid to avoid name space collisions */
145 printf("nwid%X\n", wrq.u.nwid.value);
146 break;
147 case FORMAT_RAW:
148 printf("%X\n", wrq.u.nwid.value);
149 break;
150 default:
151 printf("%-8.16s NWID:%X\n", ifname, wrq.u.nwid.value);
152 break;
153 }
154  
155 return(0);
156 }
157  
158 /**************************** AP ADDRESS ****************************/
159  
160 /*------------------------------------------------------------------*/
161 /*
162 * Display the AP Address if possible
163 */
164 static int
165 print_ap(int skfd,
166 const char * ifname,
167 int format)
168 {
169 struct iwreq wrq;
170 char buffer[64];
171  
172 /* Get AP Address */
173 if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) < 0)
174 return(-1);
175  
176 /* Print */
177 iw_ether_ntop((const struct ether_addr *) wrq.u.ap_addr.sa_data, buffer);
178 switch(format)
179 {
180 case FORMAT_SCHEME:
181 /* I think ':' are not problematic, because Pcmcia scripts
182 * seem to handle them properly... */
183 case FORMAT_RAW:
184 printf("%s\n", buffer);
185 break;
186 default:
187 printf("%-8.16s Access Point/Cell: %s\n", ifname, buffer);
188 break;
189 }
190  
191 return(0);
192 }
193  
194 /****************************** OTHER ******************************/
195  
196 /*------------------------------------------------------------------*/
197 /*
198 * Display the frequency (or channel) if possible
199 */
200 static int
201 print_freq(int skfd,
202 const char * ifname,
203 int format)
204 {
205 struct iwreq wrq;
206 double freq;
207 char buffer[64];
208  
209 /* Get frequency / channel */
210 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
211 return(-1);
212  
213 /* Print */
214 freq = iw_freq2float(&(wrq.u.freq));
215 switch(format)
216 {
217 case FORMAT_SCHEME:
218 /* Prefix with freq to avoid name space collisions */
219 printf("freq%g\n", freq);
220 break;
221 case FORMAT_RAW:
222 printf("%g\n", freq);
223 break;
224 default:
225 iw_print_freq(buffer, sizeof(buffer), freq, -1, wrq.u.freq.flags);
226 printf("%-8.16s %s\n", ifname, buffer);
227 break;
228 }
229  
230 return(0);
231 }
232  
233 /*------------------------------------------------------------------*/
234 /*
235 * Display the channel (converted from frequency) if possible
236 */
237 static int
238 print_channel(int skfd,
239 const char * ifname,
240 int format)
241 {
242 struct iwreq wrq;
243 struct iw_range range;
244 double freq;
245 int channel;
246  
247 /* Get frequency / channel */
248 if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
249 return(-1);
250  
251 /* Convert to channel */
252 if(iw_get_range_info(skfd, ifname, &range) < 0)
253 return(-2);
254 freq = iw_freq2float(&(wrq.u.freq));
255 if(freq < KILO)
256 channel = (int) freq;
257 else
258 {
259 channel = iw_freq_to_channel(freq, &range);
260 if(channel < 0)
261 return(-3);
262 }
263  
264 /* Print */
265 switch(format)
266 {
267 case FORMAT_SCHEME:
268 /* Prefix with freq to avoid name space collisions */
269 printf("channel%d\n", channel);
270 break;
271 case FORMAT_RAW:
272 printf("%d\n", channel);
273 break;
274 default:
275 printf("%-8.16s Channel:%d\n", ifname, channel);
276 break;
277 }
278  
279 return(0);
280 }
281  
282 /*------------------------------------------------------------------*/
283 /*
284 * Display the mode if possible
285 */
286 static int
287 print_mode(int skfd,
288 const char * ifname,
289 int format)
290 {
291 struct iwreq wrq;
292  
293 /* Get frequency / channel */
294 if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) < 0)
295 return(-1);
296 if(wrq.u.mode >= IW_NUM_OPER_MODE)
297 return(-2);
298  
299 /* Print */
300 switch(format)
301 {
302 case FORMAT_SCHEME:
303 /* Strip all white space and stuff */
304 if(wrq.u.mode == IW_MODE_ADHOC)
305 printf("AdHoc\n");
306 else
307 printf("%s\n", iw_operation_mode[wrq.u.mode]);
308 break;
309 case FORMAT_RAW:
310 printf("%d\n", wrq.u.mode);
311 break;
312 default:
313 printf("%-8.16s Mode:%s\n", ifname, iw_operation_mode[wrq.u.mode]);
314 break;
315 }
316  
317 return(0);
318 }
319  
320 /*------------------------------------------------------------------*/
321 /*
322 * Display the ESSID if possible
323 */
324 static int
325 print_protocol(int skfd,
326 const char * ifname,
327 int format)
328 {
329 struct iwreq wrq;
330 char proto[IFNAMSIZ + 1]; /* Protocol */
331 char pproto[IFNAMSIZ + 1]; /* Pcmcia format */
332 unsigned int i;
333 unsigned int j;
334  
335 /* Get Protocol name */
336 if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
337 return(-1);
338 strncpy(proto, wrq.u.name, IFNAMSIZ);
339 proto[IFNAMSIZ] = '\0';
340  
341 switch(format)
342 {
343 case FORMAT_SCHEME:
344 /* Strip all white space and stuff */
345 j = 0;
346 for(i = 0; i < strlen(proto); i++)
347 if(isalnum(proto[i]))
348 pproto[j++] = proto[i];
349 pproto[j] = '\0';
350 if((j == 0) || (j > 32))
351 return(-2);
352 printf("%s\n", pproto);
353 break;
354 case FORMAT_RAW:
355 printf("%s\n", proto);
356 break;
357 default:
358 printf("%-8.16s Protocol Name:\"%s\"\n", ifname, proto);
359 break;
360 }
361  
362 return(0);
363 }
364  
365 /******************************* MAIN ********************************/
366  
367 /*------------------------------------------------------------------*/
368 /*
369 * Check options and call the proper handler
370 */
371 static int
372 print_one_device(int skfd,
373 int format,
374 int wtype,
375 const char* ifname)
376 {
377 int ret;
378  
379 /* Check wtype */
380 switch(wtype)
381 {
382 case WTYPE_AP:
383 /* Try to print an AP */
384 ret = print_ap(skfd, ifname, format);
385 break;
386  
387 case WTYPE_CHANNEL:
388 /* Try to print channel */
389 ret = print_channel(skfd, ifname, format);
390 break;
391  
392 case WTYPE_FREQ:
393 /* Try to print frequency */
394 ret = print_freq(skfd, ifname, format);
395 break;
396  
397 case WTYPE_MODE:
398 /* Try to print the mode */
399 ret = print_mode(skfd, ifname, format);
400 break;
401  
402 case WTYPE_PROTO:
403 /* Try to print the protocol */
404 ret = print_protocol(skfd, ifname, format);
405 break;
406  
407 default:
408 /* Try to print an ESSID */
409 ret = print_essid(skfd, ifname, format);
410 if(ret < 0)
411 {
412 /* Try to print a nwid */
413 ret = print_nwid(skfd, ifname, format);
414 }
415 }
416  
417 return(ret);
418 }
419  
420 /*------------------------------------------------------------------*/
421 /*
422 * Try the various devices until one return something we can use
423 *
424 * Note : we can't use iw_enum_devices() because we want a different
425 * behaviour :
426 * 1) Stop at the first valid wireless device
427 * 2) Only go through active devices
428 */
429 static int
430 scan_devices(int skfd,
431 int format,
432 int wtype)
433 {
434 char buff[1024];
435 struct ifconf ifc;
436 struct ifreq *ifr;
437 int i;
438  
439 /* Get list of active devices */
440 ifc.ifc_len = sizeof(buff);
441 ifc.ifc_buf = buff;
442 if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
443 {
444 perror("SIOCGIFCONF");
445 return(-1);
446 }
447 ifr = ifc.ifc_req;
448  
449 /* Print the first match */
450 for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
451 {
452 if(print_one_device(skfd, format, wtype, ifr->ifr_name) >= 0)
453 return 0;
454 }
455 return(-1);
456 }
457  
458 /*------------------------------------------------------------------*/
459 /*
460 * helper
461 */
462 static void
463 iw_usage(int status)
464 {
465 fputs("Usage iwgetid [OPTIONS] [ifname]\n"
466 " Options are:\n"
467 " -a,--ap Print the access point address\n"
468 " -c,--channel Print the current channel\n"
469 " -f,--freq Print the current frequency\n"
470 " -m,--mode Print the current mode\n"
471 " -p,--protocol Print the protocol name\n"
472 " -r,--raw Format the output as raw value for shell scripts\n"
473 " -s,--scheme Format the output as a PCMCIA scheme identifier\n"
474 " -h,--help Print this message\n",
475 status ? stderr : stdout);
476 exit(status);
477 }
478  
479 static const struct option long_opts[] = {
480 { "ap", no_argument, NULL, 'a' },
481 { "channel", no_argument, NULL, 'c' },
482 { "freq", no_argument, NULL, 'f' },
483 { "mode", no_argument, NULL, 'm' },
484 { "protocol", no_argument, NULL, 'p' },
485 { "help", no_argument, NULL, 'h' },
486 { "raw", no_argument, NULL, 'r' },
487 { "scheme", no_argument, NULL, 's' },
488 { NULL, 0, NULL, 0 }
489 };
490  
491 /*------------------------------------------------------------------*/
492 /*
493 * The main !
494 */
495 int
496 main(int argc,
497 char ** argv)
498 {
499 int skfd; /* generic raw socket desc. */
500 int format = FORMAT_DEFAULT;
501 int wtype = WTYPE_ESSID;
502 int opt;
503 int ret = -1;
504  
505 /* Check command line arguments */
506 while((opt = getopt_long(argc, argv, "acfhmprs", long_opts, NULL)) > 0)
507 {
508 switch(opt)
509 {
510 case 'a':
511 /* User wants AP/Cell Address */
512 wtype = WTYPE_AP;
513 break;
514  
515 case 'c':
516 /* User wants channel only */
517 wtype = WTYPE_CHANNEL;
518 break;
519  
520 case 'f':
521 /* User wants frequency/channel */
522 wtype = WTYPE_FREQ;
523 break;
524  
525 case 'm':
526 /* User wants the mode */
527 wtype = WTYPE_MODE;
528 break;
529  
530 case 'p':
531 /* User wants the protocol */
532 wtype = WTYPE_PROTO;
533 break;
534  
535 case 'h':
536 iw_usage(0);
537 break;
538  
539 case 'r':
540 /* User wants a Raw format */
541 format = FORMAT_RAW;
542 break;
543  
544 case 's':
545 /* User wants a Scheme format */
546 format = FORMAT_SCHEME;
547 break;
548  
549 default:
550 iw_usage(1);
551 break;
552 }
553 }
554 if(optind + 1 < argc) {
555 fputs("Too many arguments.\n", stderr);
556 iw_usage(1);
557 }
558  
559 /* Create a channel to the NET kernel. */
560 if((skfd = iw_sockets_open()) < 0)
561 {
562 perror("socket");
563 return(-1);
564 }
565  
566 /* Check if first argument is a device name */
567 if(optind < argc)
568 {
569 /* Yes : query only this device */
570 ret = print_one_device(skfd, format, wtype, argv[optind]);
571 }
572 else
573 {
574 /* No : query all devices and print first found */
575 ret = scan_devices(skfd, format, wtype);
576 }
577  
578 fflush(stdout);
579 iw_sockets_close(skfd);
580 return(ret);
581 }