123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- /*
- * Wireless Tools
- *
- * Jean II - HPL '01
- *
- * Just print the ESSID or NWID...
- *
- * This file is released under the GPL license.
- * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
- */
- #include "iwlib.h" /* Header */
- #include <getopt.h>
- /*
- * Note on Pcmcia Schemes :
- * ----------------------
- * The purpose of this tool is to use the ESSID discovery mechanism
- * to select the appropriate Pcmcia Scheme. The card tell us which
- * ESSID it has found, and we can then select the appropriate Pcmcia
- * Scheme for this ESSID (Wireless config (encrypt keys) and IP config).
- * The way to do it is as follows :
- * cardctl scheme "essidany"
- * delay 100
- * $scheme = iwgetid --scheme
- * cardctl scheme $scheme
- * Of course, you need to add a scheme called "essidany" with the
- * following setting :
- * essidany,*,*,*)
- * ESSID="any"
- * IPADDR="10.0.0.1"
- *
- * This can also be integrated int he Pcmcia scripts.
- * Some drivers don't activate the card up to "ifconfig up".
- * Therefore, they wont scan ESSID up to this point, so we can't
- * read it reliably in Pcmcia scripts.
- * I guess the proper way to write the network script is as follows :
- * if($scheme == "iwgetid") {
- * iwconfig $name essid any
- * iwconfig $name nwid any
- * ifconfig $name up
- * delay 100
- * $scheme = iwgetid $name --scheme
- * ifconfig $name down
- * }
- *
- * This is pseudo code, but you get an idea...
- * The "ifconfig up" activate the card.
- * The "delay" is necessary to let time for the card scan the
- * frequencies and associate with the AP.
- * The "ifconfig down" is necessary to allow the driver to optimise
- * the wireless parameters setting (minimise number of card resets).
- *
- * Another cute idea is to have a list of Pcmcia Schemes to try
- * and to keep the first one that associate (AP address != 0). This
- * would be necessary for closed networks and cards that can't
- * discover essid...
- *
- * Jean II - 29/3/01
- */
- /**************************** CONSTANTS ****************************/
- #define FORMAT_DEFAULT 0 /* Nice looking display for the user */
- #define FORMAT_SCHEME 1 /* To be used as a Pcmcia Scheme */
- #define FORMAT_RAW 2 /* Raw value, for shell scripts */
- #define WTYPE_ESSID 0 /* Display ESSID or NWID */
- #define WTYPE_AP 1 /* Display AP/Cell Address */
- #define WTYPE_FREQ 2 /* Display frequency/channel */
- #define WTYPE_CHANNEL 3 /* Display channel (converted from freq) */
- #define WTYPE_MODE 4 /* Display mode */
- #define WTYPE_PROTO 5 /* Display protocol name */
- /************************ DISPLAY ESSID/NWID ************************/
- /*------------------------------------------------------------------*/
- /*
- * Display the ESSID if possible
- */
- static int
- print_essid(int skfd,
- const char * ifname,
- int format)
- {
- struct iwreq wrq;
- char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID */
- char pessid[IW_ESSID_MAX_SIZE + 1]; /* Pcmcia format */
- unsigned int i;
- unsigned int j;
- /* Make sure ESSID is always NULL terminated */
- memset(essid, 0, sizeof(essid));
- /* Get ESSID */
- wrq.u.essid.pointer = (caddr_t) essid;
- wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
- wrq.u.essid.flags = 0;
- if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0)
- return(-1);
- switch(format)
- {
- case FORMAT_SCHEME:
- /* Strip all white space and stuff */
- j = 0;
- for(i = 0; i < strlen(essid); i++)
- if(isalnum(essid[i]))
- pessid[j++] = essid[i];
- pessid[j] = '\0';
- if((j == 0) || (j > 32))
- return(-2);
- printf("%s\n", pessid);
- break;
- case FORMAT_RAW:
- printf("%s\n", essid);
- break;
- default:
- printf("%-8.16s ESSID:\"%s\"\n", ifname, essid);
- break;
- }
- return(0);
- }
- /*------------------------------------------------------------------*/
- /*
- * Display the NWID if possible
- */
- static int
- print_nwid(int skfd,
- const char * ifname,
- int format)
- {
- struct iwreq wrq;
- /* Get network ID */
- if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0)
- return(-1);
- switch(format)
- {
- case FORMAT_SCHEME:
- /* Prefix with nwid to avoid name space collisions */
- printf("nwid%X\n", wrq.u.nwid.value);
- break;
- case FORMAT_RAW:
- printf("%X\n", wrq.u.nwid.value);
- break;
- default:
- printf("%-8.16s NWID:%X\n", ifname, wrq.u.nwid.value);
- break;
- }
- return(0);
- }
- /**************************** AP ADDRESS ****************************/
- /*------------------------------------------------------------------*/
- /*
- * Display the AP Address if possible
- */
- static int
- print_ap(int skfd,
- const char * ifname,
- int format)
- {
- struct iwreq wrq;
- char buffer[64];
- /* Get AP Address */
- if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) < 0)
- return(-1);
- /* Print */
- iw_ether_ntop((const struct ether_addr *) wrq.u.ap_addr.sa_data, buffer);
- switch(format)
- {
- case FORMAT_SCHEME:
- /* I think ':' are not problematic, because Pcmcia scripts
- * seem to handle them properly... */
- case FORMAT_RAW:
- printf("%s\n", buffer);
- break;
- default:
- printf("%-8.16s Access Point/Cell: %s\n", ifname, buffer);
- break;
- }
- return(0);
- }
- /****************************** OTHER ******************************/
- /*------------------------------------------------------------------*/
- /*
- * Display the frequency (or channel) if possible
- */
- static int
- print_freq(int skfd,
- const char * ifname,
- int format)
- {
- struct iwreq wrq;
- double freq;
- char buffer[64];
- /* Get frequency / channel */
- if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
- return(-1);
- /* Print */
- freq = iw_freq2float(&(wrq.u.freq));
- switch(format)
- {
- case FORMAT_SCHEME:
- /* Prefix with freq to avoid name space collisions */
- printf("freq%g\n", freq);
- break;
- case FORMAT_RAW:
- printf("%g\n", freq);
- break;
- default:
- iw_print_freq(buffer, sizeof(buffer), freq, -1, wrq.u.freq.flags);
- printf("%-8.16s %s\n", ifname, buffer);
- break;
- }
- return(0);
- }
- /*------------------------------------------------------------------*/
- /*
- * Display the channel (converted from frequency) if possible
- */
- static int
- print_channel(int skfd,
- const char * ifname,
- int format)
- {
- struct iwreq wrq;
- struct iw_range range;
- double freq;
- int channel;
- /* Get frequency / channel */
- if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0)
- return(-1);
- /* Convert to channel */
- if(iw_get_range_info(skfd, ifname, &range) < 0)
- return(-2);
- freq = iw_freq2float(&(wrq.u.freq));
- if(freq < KILO)
- channel = (int) freq;
- else
- {
- channel = iw_freq_to_channel(freq, &range);
- if(channel < 0)
- return(-3);
- }
- /* Print */
- switch(format)
- {
- case FORMAT_SCHEME:
- /* Prefix with freq to avoid name space collisions */
- printf("channel%d\n", channel);
- break;
- case FORMAT_RAW:
- printf("%d\n", channel);
- break;
- default:
- printf("%-8.16s Channel:%d\n", ifname, channel);
- break;
- }
- return(0);
- }
- /*------------------------------------------------------------------*/
- /*
- * Display the mode if possible
- */
- static int
- print_mode(int skfd,
- const char * ifname,
- int format)
- {
- struct iwreq wrq;
- /* Get frequency / channel */
- if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) < 0)
- return(-1);
- if(wrq.u.mode >= IW_NUM_OPER_MODE)
- return(-2);
- /* Print */
- switch(format)
- {
- case FORMAT_SCHEME:
- /* Strip all white space and stuff */
- if(wrq.u.mode == IW_MODE_ADHOC)
- printf("AdHoc\n");
- else
- printf("%s\n", iw_operation_mode[wrq.u.mode]);
- break;
- case FORMAT_RAW:
- printf("%d\n", wrq.u.mode);
- break;
- default:
- printf("%-8.16s Mode:%s\n", ifname, iw_operation_mode[wrq.u.mode]);
- break;
- }
- return(0);
- }
- /*------------------------------------------------------------------*/
- /*
- * Display the ESSID if possible
- */
- static int
- print_protocol(int skfd,
- const char * ifname,
- int format)
- {
- struct iwreq wrq;
- char proto[IFNAMSIZ + 1]; /* Protocol */
- char pproto[IFNAMSIZ + 1]; /* Pcmcia format */
- unsigned int i;
- unsigned int j;
- /* Get Protocol name */
- if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
- return(-1);
- strncpy(proto, wrq.u.name, IFNAMSIZ);
- proto[IFNAMSIZ] = '\0';
- switch(format)
- {
- case FORMAT_SCHEME:
- /* Strip all white space and stuff */
- j = 0;
- for(i = 0; i < strlen(proto); i++)
- if(isalnum(proto[i]))
- pproto[j++] = proto[i];
- pproto[j] = '\0';
- if((j == 0) || (j > 32))
- return(-2);
- printf("%s\n", pproto);
- break;
- case FORMAT_RAW:
- printf("%s\n", proto);
- break;
- default:
- printf("%-8.16s Protocol Name:\"%s\"\n", ifname, proto);
- break;
- }
- return(0);
- }
- /******************************* MAIN ********************************/
- /*------------------------------------------------------------------*/
- /*
- * Check options and call the proper handler
- */
- static int
- print_one_device(int skfd,
- int format,
- int wtype,
- const char* ifname)
- {
- int ret;
- /* Check wtype */
- switch(wtype)
- {
- case WTYPE_AP:
- /* Try to print an AP */
- ret = print_ap(skfd, ifname, format);
- break;
- case WTYPE_CHANNEL:
- /* Try to print channel */
- ret = print_channel(skfd, ifname, format);
- break;
- case WTYPE_FREQ:
- /* Try to print frequency */
- ret = print_freq(skfd, ifname, format);
- break;
- case WTYPE_MODE:
- /* Try to print the mode */
- ret = print_mode(skfd, ifname, format);
- break;
- case WTYPE_PROTO:
- /* Try to print the protocol */
- ret = print_protocol(skfd, ifname, format);
- break;
- default:
- /* Try to print an ESSID */
- ret = print_essid(skfd, ifname, format);
- if(ret < 0)
- {
- /* Try to print a nwid */
- ret = print_nwid(skfd, ifname, format);
- }
- }
- return(ret);
- }
- /*------------------------------------------------------------------*/
- /*
- * Try the various devices until one return something we can use
- *
- * Note : we can't use iw_enum_devices() because we want a different
- * behaviour :
- * 1) Stop at the first valid wireless device
- * 2) Only go through active devices
- */
- static int
- scan_devices(int skfd,
- int format,
- int wtype)
- {
- char buff[1024];
- struct ifconf ifc;
- struct ifreq *ifr;
- int i;
- /* Get list of active devices */
- ifc.ifc_len = sizeof(buff);
- ifc.ifc_buf = buff;
- if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
- {
- perror("SIOCGIFCONF");
- return(-1);
- }
- ifr = ifc.ifc_req;
- /* Print the first match */
- for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
- {
- if(print_one_device(skfd, format, wtype, ifr->ifr_name) >= 0)
- return 0;
- }
- return(-1);
- }
- /*------------------------------------------------------------------*/
- /*
- * helper
- */
- static void
- iw_usage(int status)
- {
- fputs("Usage iwgetid [OPTIONS] [ifname]\n"
- " Options are:\n"
- " -a,--ap Print the access point address\n"
- " -c,--channel Print the current channel\n"
- " -f,--freq Print the current frequency\n"
- " -m,--mode Print the current mode\n"
- " -p,--protocol Print the protocol name\n"
- " -r,--raw Format the output as raw value for shell scripts\n"
- " -s,--scheme Format the output as a PCMCIA scheme identifier\n"
- " -h,--help Print this message\n",
- status ? stderr : stdout);
- exit(status);
- }
- static const struct option long_opts[] = {
- { "ap", no_argument, NULL, 'a' },
- { "channel", no_argument, NULL, 'c' },
- { "freq", no_argument, NULL, 'f' },
- { "mode", no_argument, NULL, 'm' },
- { "protocol", no_argument, NULL, 'p' },
- { "help", no_argument, NULL, 'h' },
- { "raw", no_argument, NULL, 'r' },
- { "scheme", no_argument, NULL, 's' },
- { NULL, 0, NULL, 0 }
- };
- /*------------------------------------------------------------------*/
- /*
- * The main !
- */
- int
- main(int argc,
- char ** argv)
- {
- int skfd; /* generic raw socket desc. */
- int format = FORMAT_DEFAULT;
- int wtype = WTYPE_ESSID;
- int opt;
- int ret = -1;
- /* Check command line arguments */
- while((opt = getopt_long(argc, argv, "acfhmprs", long_opts, NULL)) > 0)
- {
- switch(opt)
- {
- case 'a':
- /* User wants AP/Cell Address */
- wtype = WTYPE_AP;
- break;
- case 'c':
- /* User wants channel only */
- wtype = WTYPE_CHANNEL;
- break;
- case 'f':
- /* User wants frequency/channel */
- wtype = WTYPE_FREQ;
- break;
- case 'm':
- /* User wants the mode */
- wtype = WTYPE_MODE;
- break;
- case 'p':
- /* User wants the protocol */
- wtype = WTYPE_PROTO;
- break;
- case 'h':
- iw_usage(0);
- break;
- case 'r':
- /* User wants a Raw format */
- format = FORMAT_RAW;
- break;
- case 's':
- /* User wants a Scheme format */
- format = FORMAT_SCHEME;
- break;
- default:
- iw_usage(1);
- break;
- }
- }
- if(optind + 1 < argc) {
- fputs("Too many arguments.\n", stderr);
- iw_usage(1);
- }
- /* Create a channel to the NET kernel. */
- if((skfd = iw_sockets_open()) < 0)
- {
- perror("socket");
- return(-1);
- }
- /* Check if first argument is a device name */
- if(optind < argc)
- {
- /* Yes : query only this device */
- ret = print_one_device(skfd, format, wtype, argv[optind]);
- }
- else
- {
- /* No : query all devices and print first found */
- ret = scan_devices(skfd, format, wtype);
- }
- fflush(stdout);
- iw_sockets_close(skfd);
- return(ret);
- }
|