iwlist

iwlist主要用来显示无线网卡的一些附加信息。
iwlist的用法:

useage: iwlist [interface] options
scanning 扫描一定范围内的无线接入点和Ad-Hoc单元信息,包括ESSID,信号质量,频段以及无线模式等
frequency 频率
channel显示设备支持的频道及当前所在的频道
rate/bitrate 设备支持的速率
encryption 加密
key 密钥
power 电源
txpower 发送功率
retry 重传机制
ap 本地无线接入点及信号质量
peers 直连
event 设备支持的无线事件
auth 当前设置的WPA认证参数
wpa 罗列设备上设置的所有WPA加密密钥
modu 罗列设备支持的调制模式及当前开启的调制模式

iwlist中的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 < 2)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((iwcmd->max_count >= 0) && (count > iwcmd->max_count)){fprintf(stderr, "iwlist: command `%s' needs fewer arguments (max %d)\n",iwcmd->cmd, iwcmd->max_count);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);elseiw_enum_devices(skfd, iwcmd->fn, args, count);/* Close the socket. */iw_sockets_close(skfd);return 0;
}

iw_sockets_open函数,该函数创建了iwlist命令使用的套接字。
iw_enum_devices函数,该函数和iwconfig中的一样,也是在缺少参数的情况下打印出无线设备接口的配置信息。
iwlist_cmd是定义的iwlist_entry结构体数组,定义内容如下:

static const struct iwlist_entry iwlist_cmds[] = {{ "scanning",     print_scanning_info,    -1, "[essid NNN] [last]" },{ "frequency",    print_freq_info,    0, NULL },{ "channel",      print_freq_info,    0, NULL },{ "bitrate",      print_bitrate_info, 0, NULL },{ "rate",     print_bitrate_info, 0, NULL },{ "encryption",   print_keys_info,    0, NULL },{ "keys",     print_keys_info,    0, NULL },{ "power",        print_pm_info,      0, NULL },
#ifndef WE_ESSENTIAL{ "txpower",      print_txpower_info, 0, NULL },{ "retry",        print_retry_info,   0, NULL },{ "ap",       print_ap_info,      0, NULL },{ "accesspoints", print_ap_info,      0, NULL },{ "peers",        print_ap_info,      0, NULL },{ "event",        print_event_capa_info,  0, NULL },{ "auth",     print_auth_info,    0, NULL },{ "wpakeys",      print_wpakeys_info, 0, NULL },{ "genie",        print_gen_ie_info,  0, NULL },{ "modulation",   print_modul_info,   0, NULL },
#endif  /* WE_ESSENTIAL */{ NULL, NULL, 0, 0 },
};

iwlist_entry结构体定义了命令行参数条目,和调用了iw_enum_handler函数。其中scanning调用的print_scanning_info函数,内容如下:


/*------------------------------------------------------------------*/
/** Perform a scanning on one device*/
static int
print_scanning_info(int     skfd,char *  ifname,char *  args[],     /* Command line args */int     count)      /* Args count */
{struct iwreq      wrq;struct iw_scan_req    scanopt;        /* Options for 'set' */int           scanflags = 0;      /* Flags for scan */unsigned char *   buffer = NULL;      /* Results */int           buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */struct iw_range   range;int           has_range;struct timeval    tv;             /* Select timeout */int           timeout = 15000000;     /* 15s *//* Avoid "Unused parameter" warning */args = args; count = count;/* Debugging stuff */if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN)){fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n");fprintf(stderr, "*** and the following line :\n");fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n",IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN);}/* Get range stuff */has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);/* Check if the interface could support scanning. */if((!has_range) || (range.we_version_compiled < 14)){fprintf(stderr, "%-8.16s  Interface doesn't support scanning.\n\n",ifname);
      return(-1);}/* Init timeout value -> 250ms between set and first get */tv.tv_sec = 0;tv.tv_usec = 250000;/* Clean up set args */memset(&scanopt, 0, sizeof(scanopt));/* Parse command line arguments and extract options.* Note : when we have enough options, we should use the parser* from iwconfig... */while(count > 0){/* One arg is consumed (the option name) */count--;/** Check for Active Scan (scan with specific essid)*/if(!strncmp(args[0], "essid", 5)){if(count < 1){fprintf(stderr, "Too few arguments for scanning option [%s]\n",args[0]);
          return(-1);}args++;count--;/* Store the ESSID in the scan options */scanopt.essid_len = strlen(args[0]);memcpy(scanopt.essid, args[0], scanopt.essid_len);/* Initialise BSSID as needed */if(scanopt.bssid.sa_family == 0){scanopt.bssid.sa_family = ARPHRD_ETHER;memset(scanopt.bssid.sa_data, 0xff, ETH_ALEN);}/* Scan only this ESSID */scanflags |= IW_SCAN_THIS_ESSID;}else/* Check for last scan result (do not trigger scan) */if(!strncmp(args[0], "last", 4)){/* Hack */scanflags |= IW_SCAN_HACK;}else{fprintf(stderr, "Invalid scanning option [%s]\n", args[0]);
        return(-1);}/* Next arg */args++;}/* Check if we have scan options */if(scanflags){wrq.u.data.pointer = (caddr_t) &scanopt;wrq.u.data.length = sizeof(scanopt);wrq.u.data.flags = scanflags;}else{wrq.u.data.pointer = NULL;wrq.u.data.flags = 0;wrq.u.data.length = 0;}/* If only 'last' was specified on command line, don't trigger a scan */if(scanflags == IW_SCAN_HACK){/* Skip waiting */tv.tv_usec = 0;}else{/* Initiate Scanning */if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0){if((errno != EPERM) || (scanflags != 0)){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);
#endiftv.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;elsebuflen *= 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;#ifdef DEBUG/* 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");
#endifprintf("%-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");}elseprintf("%-8.16s  No scan results\n\n", ifname);free(buffer);
  return(0);
}

iw_get_range_info函数,将获取的驱动信息放入结构体iwrange中。
iw_set_extiw_get_ext函数,和iwconfig中的使用相同,都是进行了ioctl操作。

其中扫描请求结构体定义iw_scan_req


/**  Optional data for scan request**  Note: these optional parameters are controlling parameters for the*  scanning behavior, these do not apply to getting scan results*  (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and*  provide a merged results with all BSSes even if the previous scan*  request limited scanning to a subset, e.g., by specifying an SSID.*  Especially, scan results are required to include an entry for the*  current BSS if the driver is in Managed mode and associated with an AP.*/
struct  iw_scan_req
{__u8        scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */__u8        essid_len;__u8        num_channels; /* num entries in channel_list;* 0 = scan all allowed channels */__u8        flags; /* reserved as padding; use zero, this may* be used in the future for adding flags* to request different scan behavior */struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or* individual address of a specific BSS *//** Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using* the current ESSID. This allows scan requests for specific ESSID* without having to change the current ESSID and potentially breaking* the current association.*/__u8        essid[IW_ESSID_MAX_SIZE];/** Optional parameters for changing the default scanning behavior.* These are based on the MLME-SCAN.request from IEEE Std 802.11.* TU is 1.024 ms. If these are set to 0, driver is expected to use* reasonable default values. min_channel_time defines the time that* will be used to wait for the first reply on each channel. If no* replies are received, next channel will be scanned after this. If* replies are received, total time waited on the channel is defined by* max_channel_time.*/__u32       min_channel_time; /* in TU */__u32       max_channel_time; /* in TU */struct iw_freq  channel_list[IW_MAX_FREQUENCIES];
};

iw_range结构体定义如下:


/* -------------------------- IOCTL DATA -------------------------- */
/**  For those ioctl which want to exchange mode data that what could*  fit in the above structure...*//**  Range of parameters*/struct  iw_range
{/* Informative stuff (to choose between different interface) */__u32       throughput; /* To give an idea... *//* In theory this value should be the maximum benchmarked* TCP/IP throughput, because with most of these devices the* bit rate is meaningless (overhead an co) to estimate how* fast the connection will go and pick the fastest one.* I suggest people to play with Netperf or any benchmark...*//* NWID (or domain id) */__u32       min_nwid;   /* Minimal NWID we are able to set */__u32       max_nwid;   /* Maximal NWID we are able to set *//* Old Frequency (backward compat - moved lower ) */__u16       old_num_channels;__u8        old_num_frequency;/* Wireless event capability bitmasks */__u32       event_capa[6];/* signal level threshold range */__s32       sensitivity;/* Quality of link & SNR stuff *//* Quality range (link, level, noise)* If the quality is absolute, it will be in the range [0 ; max_qual],* if the quality is dBm, it will be in the range [max_qual ; 0].* Don't forget that we use 8 bit arithmetics... */struct iw_quality   max_qual;   /* Quality of the link *//* This should contain the average/typical values of the quality* indicator. This should be the threshold between a "good" and* a "bad" link (example : monitor going from green to orange).* Currently, user space apps like quality monitors don't have any* way to calibrate the measurement. With this, they can split* the range between 0 and max_qual in different quality level* (using a geometric subdivision centered on the average).* I expect that people doing the user space apps will feedback* us on which value we need to put in each driver... */struct iw_quality   avg_qual;   /* Quality of the link *//* Rates */__u8        num_bitrates;   /* Number of entries in the list */__s32       bitrate[IW_MAX_BITRATES];   /* list, in bps *//* RTS threshold */__s32       min_rts;    /* Minimal RTS threshold */__s32       max_rts;    /* Maximal RTS threshold *//* Frag threshold */__s32       min_frag;   /* Minimal frag threshold */__s32       max_frag;   /* Maximal frag threshold *//* Power Management duration & timeout */__s32       min_pmp;    /* Minimal PM period */__s32       max_pmp;    /* Maximal PM period */__s32       min_pmt;    /* Minimal PM timeout */__s32       max_pmt;    /* Maximal PM timeout */__u16       pmp_flags;  /* How to decode max/min PM period */__u16       pmt_flags;  /* How to decode max/min PM timeout */__u16       pm_capa;    /* What PM options are supported *//* Encoder stuff */__u16   encoding_size[IW_MAX_ENCODING_SIZES];   /* Different token sizes */__u8    num_encoding_sizes; /* Number of entry in the list */__u8    max_encoding_tokens;    /* Max number of tokens *//* For drivers that need a "login/passwd" form */__u8    encoding_login_index;   /* token index for login token *//* Transmit power */__u16       txpower_capa;   /* What options are supported */__u8        num_txpower;    /* Number of entries in the list */__s32       txpower[IW_MAX_TXPOWER];    /* list, in bps *//* Wireless Extension version info */__u8        we_version_compiled;    /* Must be WIRELESS_EXT */__u8        we_version_source;  /* Last update of source *//* Retry limits and lifetime */__u16       retry_capa; /* What retry options are supported */__u16       retry_flags;    /* How to decode max/min retry limit */__u16       r_time_flags;   /* How to decode max/min retry life */__s32       min_retry;  /* Minimal number of retries */__s32       max_retry;  /* Maximal number of retries */__s32       min_r_time; /* Minimal retry lifetime */__s32       max_r_time; /* Maximal retry lifetime *//* Frequency */__u16       num_channels;   /* Number of channels [0; num - 1] */__u8        num_frequency;  /* Number of entry in the list */struct iw_freq  freq[IW_MAX_FREQUENCIES];   /* list *//* Note : this frequency list doesn't need to fit channel numbers,* because each entry contain its channel index */__u32       enc_capa;   /* IW_ENC_CAPA_* bit field *//* More power management stuff */__s32       min_pms;    /* Minimal PM saving */__s32       max_pms;    /* Maximal PM saving */__u16       pms_flags;  /* How to decode max/min PM saving *//* All available modulations for driver (hw may support less) */__s32       modul_capa; /* IW_MODUL_* bit field *//* More bitrate stuff */__u32       bitrate_capa;   /* Types of bitrates supported */
};

经过select非阻塞获取扫描数据信息,然后iw_init_event_stream函数,将数据流放入stream_descr结构体中,再经过iw_extract_event_stream函数,提取数据流中的事件,放入一个iw_event结构体,iw_extract_event_stream函数内容如下:


/*------------------------------------------------------------------*/
/** Extract the next event from the event stream.*/
int
iw_extract_event_stream(struct stream_descr *   stream, /* Stream of events */struct iw_event *   iwe,    /* Extracted event */int         we_version)
{const struct iw_ioctl_description *   descr = NULL;int       event_type = 0;unsigned int  event_len = 1;      /* Invalid */char *    pointer;/* Don't "optimise" the following variable, it will crash */unsigned  cmd_index;      /* *MUST* be unsigned *//* Check for end of stream */if((stream->current + IW_EV_LCP_PK_LEN) > stream->end)
    return(0);#ifdef DEBUGprintf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n",stream->current, stream->value, stream->end);
#endif/* Extract the event header (to get the event id).* Note : the event may be unaligned, therefore copy... */memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN);#ifdef DEBUGprintf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n",iwe->cmd, iwe->len);
#endif/* Check invalid events */if(iwe->len <= IW_EV_LCP_PK_LEN)
    return(-1);/* Get the type and length of that event */if(iwe->cmd <= SIOCIWLAST){cmd_index = iwe->cmd - SIOCIWFIRST;if(cmd_index < standard_ioctl_num)descr = &(standard_ioctl_descr[cmd_index]);}else{cmd_index = iwe->cmd - IWEVFIRST;if(cmd_index < standard_event_num)descr = &(standard_event_descr[cmd_index]);}if(descr != NULL)event_type = descr->header_type;/* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */event_len = event_type_size[event_type];/* Fixup for earlier version of WE */if((we_version <= 18) && (event_type == IW_HEADER_TYPE_POINT))event_len += IW_EV_POINT_OFF;/* Check if we know about this event */if(event_len <= IW_EV_LCP_PK_LEN){/* Skip to next event */stream->current += iwe->len;
      return(2);}event_len -= IW_EV_LCP_PK_LEN;/* Set pointer on data */if(stream->value != NULL)pointer = stream->value;            /* Next value in event */elsepointer = stream->current + IW_EV_LCP_PK_LEN;   /* First value in event */#ifdef DEBUGprintf("DBG - event_type = %d, event_len = %d, pointer = %p\n",event_type, event_len, pointer);
#endif/* Copy the rest of the event (at least, fixed part) */if((pointer + event_len) > stream->end){/* Go to next event */stream->current += iwe->len;
      return(-2);}/* Fixup for WE-19 and later : pointer no longer in the stream *//* Beware of alignement. Dest has local alignement, not packed */if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,pointer, event_len);elsememcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);/* Skip event in the stream */pointer += event_len;/* Special processing for iw_point events */if(event_type == IW_HEADER_TYPE_POINT){/* Check the length of the payload */unsigned int  extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN);if(extra_len > 0){/* Set pointer on variable part (warning : non aligned) */iwe->u.data.pointer = pointer;/* Check that we have a descriptor for the command */if(descr == NULL)/* Can't check payload -> unsafe... */iwe->u.data.pointer = NULL; /* Discard paylod */else{/* Those checks are actually pretty hard to trigger,* because of the checks done in the kernel... */unsigned int  token_len = iwe->u.data.length * descr->token_size;/* Ugly fixup for alignement issues.* If the kernel is 64 bits and userspace 32 bits,* we have an extra 4+4 bytes.* Fixing that in the kernel would break 64 bits userspace. */if((token_len != extra_len) && (extra_len >= 4)){__u16     alt_dlen = *((__u16 *) pointer);unsigned int  alt_token_len = alt_dlen * descr->token_size;if((alt_token_len + 8) == extra_len){
#ifdef DEBUGprintf("DBG - alt_token_len = %d\n", alt_token_len);
#endif/* Ok, let's redo everything */pointer -= event_len;pointer += 4;/* Dest has local alignement, not packed */memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,pointer, event_len);pointer += event_len + 4;iwe->u.data.pointer = pointer;token_len = alt_token_len;}}/* Discard bogus events which advertise more tokens than* what they carry... */if(token_len > extra_len)iwe->u.data.pointer = NULL; /* Discard paylod *//* Check that the advertised token size is not going to* produce buffer overflow to our caller... */if((iwe->u.data.length > descr->max_tokens)&& !(descr->flags & IW_DESCR_FLAG_NOMAX))iwe->u.data.pointer = NULL; /* Discard paylod *//* Same for underflows... */if(iwe->u.data.length < descr->min_tokens)iwe->u.data.pointer = NULL; /* Discard paylod */
#ifdef DEBUGprintf("DBG - extra_len = %d, token_len = %d, token = %d, max = %d, min = %d\n",extra_len, token_len, iwe->u.data.length, descr->max_tokens, descr->min_tokens);
#endif}}else/* No data */iwe->u.data.pointer = NULL;/* Go to next event */stream->current += iwe->len;}else{/* Ugly fixup for alignement issues.* If the kernel is 64 bits and userspace 32 bits,* we have an extra 4 bytes.* Fixing that in the kernel would break 64 bits userspace. */if((stream->value == NULL)&& ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4)|| ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) ||(event_type == IW_HEADER_TYPE_QUAL))) )){
#ifdef DEBUGprintf("DBG - alt iwe->len = %d\n", iwe->len - 4);
#endifpointer -= event_len;pointer += 4;/* Beware of alignement. Dest has local alignement, not packed */memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);pointer += event_len;}/* Is there more value in the event ? */if((pointer + event_len) <= (stream->current + iwe->len))/* Go to next value */stream->value = pointer;else{/* Go to next event */stream->value = NULL;stream->current += iwe->len;}}
  return(1);
}

最后通过while循环,使用print_scanning_token函数将扫描的信息分类打印出来,print_scanning_token函数内容如下:


/***************************** SCANNING *****************************/
/** This one behave quite differently from the others** Note that we don't use the scanning capability of iwlib (functions* iw_process_scan() and iw_scan()). The main reason is that* iw_process_scan() return only a subset of the scan data to the caller,* for example custom elements and bitrates are ommited. Here, we* do the complete job...*//*------------------------------------------------------------------*/
/** Print one element from the scanning results*/
static inline void
print_scanning_token(struct stream_descr *  stream, /* Stream of events */struct iw_event *      event,  /* Extracted token */struct iwscan_state *  state,struct iw_range *  iw_range,   /* Range info */int        has_range)
{char      buffer[128];    /* Temporary buffer *//* Now, let's decode the event */switch(event->cmd){case SIOCGIWAP:printf("          Cell %02d - Address: %s\n", state->ap_num,iw_saether_ntop(&event->u.ap_addr, buffer));state->ap_num++;break;case SIOCGIWNWID:if(event->u.nwid.disabled)printf("                    NWID:off/any\n");elseprintf("                    NWID:%X\n", event->u.nwid.value);break;case SIOCGIWFREQ:{double      freq;           /* Frequency/channel */int     channel = -1;       /* Converted to channel */freq = iw_freq2float(&(event->u.freq));/* Convert to channel if possible */if(has_range)channel = iw_freq_to_channel(freq, iw_range);iw_print_freq(buffer, sizeof(buffer),freq, channel, event->u.freq.flags);printf("                    %s\n", buffer);}break;case SIOCGIWMODE:/* Note : event->u.mode is unsigned, no need to check <= 0 */if(event->u.mode >= IW_NUM_OPER_MODE)event->u.mode = IW_NUM_OPER_MODE;printf("                    Mode:%s\n",iw_operation_mode[event->u.mode]);break;case SIOCGIWNAME:printf("                    Protocol:%-1.16s\n", event->u.name);break;case SIOCGIWESSID:{char essid[IW_ESSID_MAX_SIZE+1];memset(essid, '\0', sizeof(essid));if((event->u.essid.pointer) && (event->u.essid.length))memcpy(essid, event->u.essid.pointer, event->u.essid.length);if(event->u.essid.flags){/* Does it have an ESSID index ? */if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)printf("                    ESSID:\"%s\" [%d]\n", essid,(event->u.essid.flags & IW_ENCODE_INDEX));elseprintf("                    ESSID:\"%s\"\n", essid);}elseprintf("                    ESSID:off/any/hidden\n");}break;case SIOCGIWENCODE:{unsigned char   key[IW_ENCODING_TOKEN_MAX];if(event->u.data.pointer)memcpy(key, event->u.data.pointer, event->u.data.length);elseevent->u.data.flags |= IW_ENCODE_NOKEY;printf("                    Encryption key:");if(event->u.data.flags & IW_ENCODE_DISABLED)printf("off\n");else{/* Display the key */iw_print_key(buffer, sizeof(buffer), key, event->u.data.length,event->u.data.flags);printf("%s", buffer);/* Other info... */if((event->u.data.flags & IW_ENCODE_INDEX) > 1)printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX);if(event->u.data.flags & IW_ENCODE_RESTRICTED)printf("   Security mode:restricted");if(event->u.data.flags & IW_ENCODE_OPEN)printf("   Security mode:open");printf("\n");}}break;case SIOCGIWRATE:if(state->val_index == 0)printf("                    Bit Rates:");elseif((state->val_index % 5) == 0)printf("\n                              ");elseprintf("; ");iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);printf("%s", buffer);/* Check for termination */if(stream->value == NULL){printf("\n");state->val_index = 0;}elsestate->val_index++;break;case SIOCGIWMODUL:{unsigned int    modul = event->u.param.value;int     i;int     n = 0;printf("                    Modulations :");for(i = 0; i < IW_SIZE_MODUL_LIST; i++){if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask){if((n++ % 8) == 7)printf("\n                        ");elseprintf(" ; ");printf("%s", iw_modul_list[i].cmd);}}printf("\n");}break;case IWEVQUAL:iw_print_stats(buffer, sizeof(buffer),&event->u.qual, iw_range, has_range);printf("                    %s\n", buffer);break;
#ifndef WE_ESSENTIALcase IWEVGENIE:/* Informations Elements are complex, let's do only some of them */iw_print_gen_ie(event->u.data.pointer, event->u.data.length);break;
#endif  /* WE_ESSENTIAL */case IWEVCUSTOM:{char custom[IW_CUSTOM_MAX+1];if((event->u.data.pointer) && (event->u.data.length))memcpy(custom, event->u.data.pointer, event->u.data.length);custom[event->u.data.length] = '\0';printf("                    Extra:%s\n", custom);}break;default:printf("                    (Unknown Wireless Token 0x%04X)\n",event->cmd);}    /* switch(event->cmd) */
}

可以看到分类打印,存在的则变换格式后直接打印,其它则信息分别调用了下列函数。

iw_saether_ntop //获取ethernet的mac地址
iw_print_freq  //获取频率
iw_print_key  //获取加密key
iw_print_bitrate //获取bit速率
iw_print_stats  //获取无线状态

wireless-tools源码分析-iwlist相关推荐

  1. Spring Developer Tools 源码分析:二、类路径监控

    在 Spring Developer Tools 源码分析一中介绍了 devtools 提供的文件监控实现,在第二部分中,我们将会使用第一部分提供的目录监控功能,实现对开发环境中 classpath ...

  2. kazoo源码分析:Zookeeper客户端start概述

    kazoo源码分析 kazoo-2.6.1 kazoo客户端 kazoo是一个由Python编写的zookeeper客户端,实现了zookeeper协议,从而提供了Python与zookeeper服务 ...

  3. kubeadm源码分析(内含kubernetes离线包,三步安装)

    k8s离线安装包 三步安装,简单到难以置信 kubeadm源码分析 说句实在话,kubeadm的代码写的真心一般,质量不是很高. 几个关键点来先说一下kubeadm干的几个核心的事: kubeadm ...

  4. 《深入理解Spark:核心思想与源码分析》——1.2节Spark初体验

    本节书摘来自华章社区<深入理解Spark:核心思想与源码分析>一书中的第1章,第1.2节Spark初体验,作者耿嘉安,更多章节内容可以访问云栖社区"华章社区"公众号查看 ...

  5. soundtouch源码分析__based on csdn :

    1. soundtouch介绍和相关资源 The SoundTouch Library Copyright © Olli Parviainen 2001-2014 SoundTouch is an o ...

  6. linux nDPI 协议检测 源码分析

    关于nDPI的基本功能就不在这介绍了,有兴趣了解的读者可以阅读官方的快速入门指南:https://github.com/ntop/nDPI/blob/dev/doc/nDPI_QuickStartGu ...

  7. java 源码分析_Java 源代码编译成 Class 文件的过程分析

    原标题:Java 源代码编译成 Class 文件的过程分析 在上篇文章< Java三种编译方式:前端编译 JIT编译 AOT编译 >中了解到了它们各有什么优点和缺点,以及前端编译+JIT编 ...

  8. 【Android 插件化】VirtualApp 源码分析 ( 添加应用源码分析 | LaunchpadAdapter 适配器 | 适配器添加元素 | PackageAppData 元素 )

    文章目录 一.添加应用源码分析 1.LaunchpadAdapter 适配器 2.适配器添加元素 3.PackageAppData 元素 一.添加应用源码分析 1.LaunchpadAdapter 适 ...

  9. zg手册 之 python2.7.7源码分析(1)-- python中的对象

    为什么80%的码农都做不了架构师?>>>    源代码主要目录结构 Demo: python 的示例程序 Doc: 文档 Grammar: 用BNF的语法定义了Python的全部语法 ...

  10. PostgreSQL源码分析

    PostgreSQL源码结构 PostgreSQL的使用形态 PostgreSQL采用C/S(客户机/服务器)模式结构.应用层通过INET或者Unix Socket利用既定的协议与数据库服务器进行通信 ...

最新文章

  1. python isinstance函数判断object的类型
  2. Android之ASD组件(一)
  3. 解决Eclipse中文乱码的方法
  4. android 再按一次退出程序
  5. python 读取excel表数据获取坐标_python读取并定位excel数据坐标系详解
  6. java对象与c网络语言通信,JAVA与C语言的网络通信代码案例.pdf
  7. Membership学习(二)membership入门[xgluxv]
  8. flask+apache2+ubuntu
  9. php 获取域名前缀,PHP获取域名方法
  10. MT666数字程序测试
  11. 守望先锋为何如此火爆
  12. Asp.net学习过程分解(学习路线)
  13. word-wrap和word-break
  14. Google搜索又变聪明了 Baidu你还能HOLD住吗
  15. VC++公安指纹识别系统
  16. 产品目标拆解:结构化思维
  17. 汽车软件合作开发中的分工、知识产权及质量责任
  18. Redis大Key优化
  19. 元宇宙的隐私保护:技术与监管
  20. 4.加载FeatureLayer

热门文章

  1. VC6-VC2008转移到VC2015问题记录
  2. 关于mac的open命令
  3. linux系统国产制图软件,国产操作系统也能用的国产图表绘制软件,替代Visio就用它了...
  4. 计算机体系结构与组成的区别
  5. android 模拟器 安装,夜神安卓模拟器安装环境
  6. 警方耗时19天抓捕了摄像头破解软件黑产,但你还要知道这些才能放心
  7. 无代码编程的兴起:借助无代码平台,无需编写任何基础代码即可开发软件
  8. 【问题和解决《NLTK PYTHON》自然语言处理中文翻译版中的一处代码错误
  9. java执行Sql脚本
  10. Linux常用命令,Linux常用基本命令大全