📄 iwgetid.c
字号:
/* * Wireless Tools * * Jean II - HPL '01 * * Just print the ESSID or NWID... * * This file is released under the GPL license. * Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com> */#include "iwlib.h" /* Header */#include <getopt.h>#define FORMAT_DEFAULT 0 /* Nice looking display for the user */#define FORMAT_SCHEME 1 /* To be used as a Pcmcia Scheme */#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_MODE 3 /* Display mode */#define WTYPE_PROTO 4 /* Display protocol name *//* * 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 *//*************************** SUBROUTINES ***************************//* * Just for the heck of it, let's try to not link with iwlib. * This will keep the binary small and tiny... * * Note : maybe it's time to admit that we have lost the battle * and we start using iwlib ? Maybe we should default to dynamic * lib first... *//*------------------------------------------------------------------*//* * Open a socket. * Depending on the protocol present, open the right socket. The socket * will allow us to talk to the driver. */intiw_sockets_open(void){ int ipx_sock = -1; /* IPX socket */ int ax25_sock = -1; /* AX.25 socket */ int inet_sock = -1; /* INET socket */ int ddp_sock = -1; /* Appletalk DDP socket */ /* * Now pick any (exisiting) useful socket family for generic queries * Note : don't open all the socket, only returns when one matches, * all protocols might not be valid. * Workaround by Jim Kaba <jkaba@sarnoff.com> * Note : in 99% of the case, we will just open the inet_sock. * The remaining 1% case are not fully correct... */ inet_sock=socket(AF_INET, SOCK_DGRAM, 0); if(inet_sock!=-1) return inet_sock; ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0); if(ipx_sock!=-1) return ipx_sock; ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0); if(ax25_sock!=-1) return ax25_sock; ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0); /* * If this is -1 we have no known network layers and its time to jump. */ return ddp_sock;}/*------------------------------------------------------------------*//* * Display an Ethernet address in readable format. */voidiw_ether_ntop(const struct ether_addr* eth, char* buf){ sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", eth->ether_addr_octet[0], eth->ether_addr_octet[1], eth->ether_addr_octet[2], eth->ether_addr_octet[3], eth->ether_addr_octet[4], eth->ether_addr_octet[5]);}/*------------------------------------------------------------------*//* * Convert our internal representation of frequencies to a floating point. */doubleiw_freq2float(iwfreq * in){#ifdef WE_NOLIBM /* Version without libm : slower */ int i; double res = (double) in->m; for(i = 0; i < in->e; i++) res *= 10; return(res);#else /* WE_NOLIBM */ /* Version with libm : faster */ return ((double) in->m) * pow(10,in->e);#endif /* WE_NOLIBM */}/*------------------------------------------------------------------*//* * Output a frequency with proper scaling */voidiw_print_freq(char * buffer, double freq){ if(freq < KILO) sprintf(buffer, "Channel:%g", freq); else { if(freq >= GIGA) sprintf(buffer, "Frequency:%gGHz", freq / GIGA); else { if(freq >= MEGA) sprintf(buffer, "Frequency:%gMHz", freq / MEGA); else sprintf(buffer, "Frequency:%gkHz", freq / KILO); } }}/*------------------------------------------------------------------*/const char * const iw_operation_mode[] = { "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Monitor" };/************************ DISPLAY ESSID/NWID ************************//*------------------------------------------------------------------*//* * Display the ESSID if possible */static intprint_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; /* Get ESSID */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; if(ioctl(skfd, 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; default: printf("%-8.8s ESSID:\"%s\"\n", ifname, essid); break; } return(0);}/*------------------------------------------------------------------*//* * Display the NWID if possible */static intprint_nwid(int skfd, const char * ifname, int format){ struct iwreq wrq; /* Get network ID */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, 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; default: printf("%-8.8s NWID:%X\n", ifname, wrq.u.nwid.value); break; } return(0);}/**************************** AP ADDRESS ****************************//*------------------------------------------------------------------*//* * Display the AP Address if possible */static intprint_ap(int skfd, const char * ifname, int format){ struct iwreq wrq; char buffer[64]; /* Get AP Address */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, 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... */ printf("%s\n", buffer); break; default: printf("%-8.8s Access Point/Cell: %s\n", ifname, buffer); break; } return(0);}/****************************** OTHER ******************************//*------------------------------------------------------------------*//* * Display the frequency (or channel) if possible */static intprint_freq(int skfd, const char * ifname, int format){ struct iwreq wrq; double freq; char buffer[64]; /* Get frequency / channel */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWFREQ, &wrq) < 0) return(-1); /* Print */ freq = iw_freq2float(&(wrq.u.freq)); switch(format) { case FORMAT_SCHEME: printf("%g\n", freq); break; default: iw_print_freq(buffer, freq); printf("%-8.8s %s\n", ifname, buffer); break; } return(0);}/*------------------------------------------------------------------*//* * Display the mode if possible */static intprint_mode(int skfd, const char * ifname, int format){ struct iwreq wrq; /* Get frequency / channel */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIWMODE, &wrq) < 0) return(-1); if(wrq.u.mode >= IW_NUM_OPER_MODE) return(-2); /* Print */ switch(format) { case FORMAT_SCHEME: printf("%d\n", wrq.u.mode); break; default: printf("%-8.8s Mode:%s\n", ifname, iw_operation_mode[wrq.u.mode]); break; } return(0);}/*------------------------------------------------------------------*//* * Display the ESSID if possible */static intprint_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 */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, 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; default: printf("%-8.8s Protocol Name:\"%s\"\n", ifname, proto); break; } return(0);}/******************************* MAIN ********************************//*------------------------------------------------------------------*//* * Check options and call the proper handler */static intprint_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_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 */static intscan_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 voidiw_usage(int status){ fputs("Usage iwgetid [OPTIONS] [ifname]\n" " Options are:\n" " -a,--ap Print the access point address\n" " -f,--freq Print the current frequency\n" " -m,--mode Print the current mode\n" " -p,--protocol Print the protocol name\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' }, { "freq", no_argument, NULL, 'f' }, { "mode", no_argument, NULL, 'm' }, { "protocol", no_argument, NULL, 'p' }, { "help", no_argument, NULL, 'h' }, { "scheme", no_argument, NULL, 's' }, { NULL, 0, NULL, 0 }};/*------------------------------------------------------------------*//* * The main ! */intmain(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, "afhmps", long_opts, NULL)) > 0) { switch(opt) { case 'a': /* User wants AP/Cell Address */ wtype = WTYPE_AP; 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 '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); close(skfd); return(ret);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -