📄 iwlist.c
字号:
wrq.u.data.flags = 0;
wrq.u.data.length = 0;
/* Initiate Scanning */
if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
{
if(errno != EPERM)
{
fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n",
ifname, strerror(errno));
return(-1);
}
/* If we don't have the permission to initiate the scan, we may
* still have permission to read left-over results.
* But, don't wait !!! */
#if 0
/* Not cool, it display for non wireless interfaces... */
fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname);
#endif
tv.tv_usec = 0;
}
timeout -= tv.tv_usec;
/* Forever */
while(1)
{
fd_set rfds; /* File descriptors for select */
int last_fd; /* Last fd */
int ret;
/* Guess what ? We must re-generate rfds each time */
FD_ZERO(&rfds);
last_fd = -1;
/* In here, add the rtnetlink fd in the list */
/* Wait until something happens */
ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
/* Check if there was an error */
if(ret < 0)
{
if(errno == EAGAIN || errno == EINTR)
continue;
fprintf(stderr, "Unhandled signal - exiting...\n");
return(-1);
}
/* Check if there was a timeout */
if(ret == 0)
{
unsigned char * newbuf;
realloc:
/* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
newbuf = realloc(buffer, buflen);
if(newbuf == NULL)
{
if(buffer)
free(buffer);
fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
return(-1);
}
buffer = newbuf;
/* Try to read the results */
wrq.u.data.pointer = buffer;
wrq.u.data.flags = 0;
wrq.u.data.length = buflen;
if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
{
/* Check if buffer was too small (WE-17 only) */
if((errno == E2BIG) && (range.we_version_compiled > 16))
{
/* Some driver may return very large scan results, either
* because there are many cells, or because they have many
* large elements in cells (like IWEVCUSTOM). Most will
* only need the regular sized buffer. We now use a dynamic
* allocation of the buffer to satisfy everybody. Of course,
* as we don't know in advance the size of the array, we try
* various increasing sizes. Jean II */
/* Check if the driver gave us any hints. */
if(wrq.u.data.length > buflen)
buflen = wrq.u.data.length;
else
buflen *= 2;
/* Try again */
goto realloc;
}
/* Check if results not available yet */
if(errno == EAGAIN)
{
/* Restart timer for only 100ms*/
tv.tv_sec = 0;
tv.tv_usec = 100000;
timeout -= tv.tv_usec;
if(timeout > 0)
continue; /* Try again later */
}
/* Bad error */
free(buffer);
fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n",
ifname, strerror(errno));
return(-2);
}
else
/* We have the results, go to process them */
break;
}
/* In here, check if event and event type
* if scan event, read results. All errors bad & no reset timeout */
}
if(wrq.u.data.length)
{
struct iw_event iwe;
struct stream_descr stream;
struct iwscan_state state = { .ap_num = 1, .val_index = 0 };
int ret;
#if 0
/* Debugging code. In theory useless, because it's debugged ;-) */
int i;
printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]);
for(i = 1; i < wrq.u.data.length; i++)
printf(":%02X", buffer[i]);
printf("]\n");
#endif
printf("%-8.16s Scan completed :\n", ifname);
iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
do
{
/* Extract an event and print it */
ret = iw_extract_event_stream(&stream, &iwe,
range.we_version_compiled);
if(ret > 0)
print_scanning_token(&stream, &iwe, &state,
&range, has_range);
}
while(ret > 0);
printf("\n");
}
else
printf("%-8.16s No scan results\n", ifname);
free(buffer);
return(0);
}
/******************** WIRELESS EVENT CAPABILITY ********************/
static const char * event_capa_req[] =
{
[SIOCSIWNWID - SIOCIWFIRST] = "Set NWID (kernel generated)",
[SIOCSIWFREQ - SIOCIWFIRST] = "Set Frequency/Channel (kernel generated)",
[SIOCGIWFREQ - SIOCIWFIRST] = "New Frequency/Channel",
[SIOCSIWMODE - SIOCIWFIRST] = "Set Mode (kernel generated)",
[SIOCGIWTHRSPY - SIOCIWFIRST] = "Spy threshold crossed",
[SIOCGIWAP - SIOCIWFIRST] = "New Access Point/Cell address - roaming",
[SIOCGIWSCAN - SIOCIWFIRST] = "Scan request completed",
[SIOCSIWESSID - SIOCIWFIRST] = "Set ESSID (kernel generated)",
[SIOCGIWESSID - SIOCIWFIRST] = "New ESSID",
[SIOCGIWRATE - SIOCIWFIRST] = "New bit-rate",
[SIOCSIWENCODE - SIOCIWFIRST] = "Set Encoding (kernel generated)",
[SIOCGIWPOWER - SIOCIWFIRST] = NULL,
};
static const char * event_capa_evt[] =
{
[IWEVTXDROP - IWEVFIRST] = "Tx packet dropped - retry exceeded",
[IWEVCUSTOM - IWEVFIRST] = "Custom driver event",
[IWEVREGISTERED - IWEVFIRST] = "Registered node",
[IWEVEXPIRED - IWEVFIRST] = "Expired node",
};
/*------------------------------------------------------------------*/
/*
* Print the number of available transmit powers for the device
*/
static int
print_event_capa_info(int skfd,
char * ifname,
char * args[], /* Command line args */
int count) /* Args count */
{
struct iw_range range;
int cmd;
/* Avoid "Unused parameter" warning */
args = args; count = count;
/* Extract range info */
if((iw_get_range_info(skfd, ifname, &range) < 0) ||
(range.we_version_compiled < 10))
fprintf(stderr, "%-8.16s no wireless event capability information.\n\n",
ifname);
else
{
#if 0
/* Debugging ;-) */
for(cmd = 0x8B00; cmd < 0x8C0F; cmd++)
{
int idx = IW_EVENT_CAPA_INDEX(cmd);
int mask = IW_EVENT_CAPA_MASK(cmd);
printf("0x%X - %d - %X\n", cmd, idx, mask);
}
#endif
printf("%-8.16s Wireless Events supported :\n", ifname);
for(cmd = SIOCIWFIRST; cmd <= SIOCGIWPOWER; cmd++)
{
int idx = IW_EVENT_CAPA_INDEX(cmd);
int mask = IW_EVENT_CAPA_MASK(cmd);
if(range.event_capa[idx] & mask)
printf(" 0x%04X : %s\n",
cmd, event_capa_req[cmd - SIOCIWFIRST]);
}
for(cmd = IWEVFIRST; cmd <= IWEVEXPIRED; cmd++)
{
int idx = IW_EVENT_CAPA_INDEX(cmd);
int mask = IW_EVENT_CAPA_MASK(cmd);
if(range.event_capa[idx] & mask)
printf(" 0x%04X : %s\n",
cmd, event_capa_evt[cmd - IWEVFIRST]);
}
printf("\n");
}
return(0);
}
/************************* COMMON UTILITIES *************************/
/*
* This section was initially written by Michael Tokarev <mjt@tls.msk.ru>
* but heavily modified by me ;-)
*/
/*------------------------------------------------------------------*/
/*
* Map command line arguments to the proper procedure...
*/
typedef struct iwlist_entry {
const char *cmd;
iw_enum_handler fn;
int min_count;
int max_count;
} iwlist_cmd;
static const struct iwlist_entry iwlist_cmds[] = {
{ "scanning", print_scanning_info, 0, 5 },
{ "frequency", print_freq_info, 0, 0 },
{ "channel", print_freq_info, 0, 0 },
{ "bitrate", print_bitrate_info, 0, 0 },
{ "rate", print_bitrate_info, 0, 0 },
{ "encryption", print_keys_info, 0, 0 },
{ "key", print_keys_info, 0, 0 },
{ "power", print_pm_info, 0, 0 },
{ "txpower", print_txpower_info, 0, 0 },
{ "retry", print_retry_info, 0, 0 },
{ "ap", print_ap_info, 0, 0 },
{ "accesspoints", print_ap_info, 0, 0 },
{ "peers", print_ap_info, 0, 0 },
{ "event", print_event_capa_info, 0, 0 },
{ NULL, NULL, 0, 0 },
};
/*------------------------------------------------------------------*/
/*
* Find the most appropriate command matching the command line
*/
static inline const iwlist_cmd *
find_command(const char * cmd)
{
const iwlist_cmd * found = NULL;
int ambig = 0;
unsigned int len = strlen(cmd);
int i;
/* Go through all commands */
for(i = 0; iwlist_cmds[i].cmd != NULL; ++i)
{
/* No match -> next one */
if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0)
continue;
/* Exact match -> perfect */
if(len == strlen(iwlist_cmds[i].cmd))
return &iwlist_cmds[i];
/* Partial match */
if(found == NULL)
/* First time */
found = &iwlist_cmds[i];
else
/* Another time */
if (iwlist_cmds[i].fn != found->fn)
ambig = 1;
}
if(found == NULL)
{
fprintf(stderr, "iwlist: unknown command `%s'\n", cmd);
return NULL;
}
if(ambig)
{
fprintf(stderr, "iwlist: command `%s' is ambiguous\n", cmd);
return NULL;
}
return found;
}
/*------------------------------------------------------------------*/
/*
* Display help
*/
static void iw_usage(int status)
{
FILE* f = status ? stderr : stdout;
int i;
fprintf(f, "Usage: iwlist [interface] %s\n", iwlist_cmds[0].cmd);
for(i = 1; iwlist_cmds[i].cmd != NULL; ++i)
fprintf(f, " [interface] %s\n", iwlist_cmds[i].cmd);
exit(status);
}
/******************************* MAIN ********************************/
/*------------------------------------------------------------------*/
/*
* The main !
*/
int
main(int argc,
char ** argv)
{
int skfd; /* generic raw socket desc. */
char *dev; /* device name */
char *cmd; /* command */
char **args; /* Command arguments */
int count; /* Number of arguments */
const iwlist_cmd *iwcmd;
if(argc == 1 || argc > 3)
iw_usage(1);
/* Those don't apply to all interfaces */
if((argc == 2) && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))
iw_usage(0);
if((argc == 2) && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")))
return(iw_print_version_info("iwlist"));
if(argc == 2)
{
cmd = argv[1];
dev = NULL;
args = NULL;
count = 0;
}
else
{
cmd = argv[2];
dev = argv[1];
args = argv + 3;
count = argc - 3;
}
/* find a command */
iwcmd = find_command(cmd);
if(iwcmd == NULL)
return 1;
/* Check arg numbers */
if(count < iwcmd->min_count)
{
fprintf(stderr, "iwlist: command `%s' needs more arguments\n", cmd);
return 1;
}
if(count > iwcmd->max_count)
{
fprintf(stderr, "iwlist: command `%s' needs fewer arguments\n", cmd);
return 1;
}
/* Create a channel to the NET kernel. */
if((skfd = iw_sockets_open()) < 0)
{
perror("socket");
return -1;
}
/* do the actual work */
if (dev)
(*iwcmd->fn)(skfd, dev, args, count);
else
iw_enum_devices(skfd, iwcmd->fn, args, count);
/* Close the socket. */
iw_sockets_close(skfd);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -