libiw中的函数说明

打开电脑连接wifi是一件很平常的事情,但这些事情通常都是操作系统下的wifi管理程序替我们完成的,如何在程序中连接指定的wifi其实很少有资料介绍,在网络专栏的文章中,有两篇是关于wfi编程的文章,其中对无线网卡的操作都是通过ioctl()完成的,显得有些繁琐和晦涩,但其实WE(Wireless Extensions)有一个简单的库libiw,这个库的实现也是使用ioctl(),但是经过封装后,会使wifi编程变得容易一些,本文为一篇资料类的文章,主要描述libiw中API的调用方法。

1 前言

  • 在大多数以 Linux 内核为基础的操作系统中,都是包含 WE(Wireless Extensions) 的,WE 实际就是一组在用户空间操作无线网卡驱动程序的一组 API,库 libiw 是对 WE 的一个封装;

  • 尽管库 libiw 可以给 wifi 编程带来一定的便利,但其实这是一个已经过时的库,这个库的最后更新日期是 2009 年,尽管如此,现在的绝大多数无线网卡驱动程序仍然支持 WE,所以我们仍然可以使用 libiw 进行 wifi 编程;

  • 一些常用的 wifi 工具软件是使用 WE 实现的,比如:iwlist、iwconfig 等,由此也可以看出 WE 在 wifi 编程中仍然占有很重要的位置;

  • WE 的基本实现是使用 ioctl(),前面的两篇文章 《使用ioctl扫描wifi信号获取信号属性的实例(一)》《使用ioctl扫描wifi信号获取信号属性的实例(二)》 都是使用 ioctl() 实现的;

  • libiw 是对 WE 的一个封装,使编程者不必直接面对 ioctl() 中复杂的调用方法和返回数据,可以给编程带来一些便利;

  • 之所以要写这样一份资料类的文章,是因为完整的 libiw 中 API 调用方法的资料几乎没有,libiw API 的使用方法几乎只能通过阅读源码来学习,很不方便;

  • 本文是通过阅读 libiw 的源码 iwlib.ciwlib.h 以及一些 wifi 工具软件的源码总结而成;

  • 项目 Wireless Tools 中的 iwlib.ciwlib.h 组成了 libiw

  • 克隆项目:

    git clone https://github.com/HewlettPackard/wireless-tools
    
  • 编译静态库 libiw.so.29

    gcc -Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wpointer-arith -Wcast-qual -Winline -I. -MMD -fPIC -c -o iwlib.so iwlib.c
    gcc -shared -o libiw.so.29 -Wl,-soname,libiw.so.29  -lm -lc iwlib.so
    
  • 编译静态库 libiw.a

    rm -f libiw.a
    ar cru libiw.a iwlib.so
    ranlib libiw.a
    
  • 在 ubuntu 上,要使用 libiw 需要单独安装,安装方法非常容易:

    sudo apt update
    sudo apt install libiw-dev
    
  • 要说明的是,使用 apt 安装的 libiw,看到的动态链接库为 libiw.so.30,但是使用这个项目的开源版本编译出来的动态链接库为 libiw.so.29,版本略有不同,从 iwlib.h 看,libiw.so.30 更新于 2009 年,而开源项目的源代码更新于 2007 年,二者还是有一些差距的;

  • libiw.h 看,libiw.so.30 中包含了一些 libiw.so.29 中没有的函数,但总体看,区别不是很大。

2. 库函数列表(共计 52 个)

  • SOCKET SUBROUTINES(2 个)

    1. int iw_sockets_open(void);
    2. void iw_enum_devices(int skfd, iw_enum_handler fn, char *args[], int count);
  • WIRELESS SUBROUTINES(6个)

    1. int iw_get_kernel_we_version(void);
    2. int iw_print_version_info(const char *toolname);
    3. int iw_get_range_info(int skfd, const char *ifname, iwrange *range);
    4. int iw_get_priv_info(int skfd, const char *ifname, iwprivargs ** ppriv);
    5. int iw_get_basic_config(int skfd, const char *ifname, wireless_config *info);
    6. int iw_set_basic_config(int skfd, const char *ifname, wireless_config *info);
  • PROTOCOL SUBROUTINES(1个)

    1. int iw_protocol_compare(const char *protocol1, const char *protocol2);
  • ESSID SUBROUTINES(2个)

    1. void iw_essid_escape(char *dest, const char *src, const int slen);
    2. int iw_essid_unescape(char *dest, const char *src);
  • FREQUENCY SUBROUTINES(7个)

    1. void iw_float2freq(double in, iwfreq *out);
    2. double iw_freq2float(const iwfreq *in);
    3. void iw_print_freq_value(char *buffer, int buflen, double freq);
    4. void iw_print_freq(char *buffer, int buflen, double freq, int channel, int freq_flags);
    5. int iw_freq_to_channel(double freq, const struct iw_range *range);
    6. int iw_channel_to_freq(int channel, double *pfreq, const struct iw_range *range);
    7. void iw_print_bitrate(char *buffer, int buflen, int bitrate);
  • POWER SUBROUTINES(3个)

    1. int iw_dbm2mwatt(int in);
    2. int iw_mwatt2dbm(int in);
    3. void iw_print_txpower(char *buffer, int buflen, struct iw_param *txpower);
  • STATISTICS SUBROUTINES(2个)

    1. int iw_get_stats(int skfd, const char *ifname, iwstats *stats, const iwrange *range, int has_range);
    2. void iw_print_stats(char *buffer, int buflen, const iwqual *qual, const iwrange *range, int has_range);
  • ENCODING SUBROUTINES(3个)

    1. void iw_print_key(char *buffer, int buflen, const unsigned char *key, int key_size, int key_flags);
    2. int iw_in_key(const char *input, unsigned char *key);
    3. int iw_in_key_full(int skfd, const char *ifname, const char *input, unsigned char *key, __u16 *flags);
  • POWER MANAGEMENT SUBROUTINES(2个)

    1. void iw_print_pm_value(char *buffer, int buflen, int value, int flags, int we_version);
    2. void iw_print_pm_mode(char *buffer, int buflen, int flags);
  • RETRY LIMIT/LIFETIME SUBROUTINES(1个)

    1. void iw_print_retry_value(char *buffer, int buflen, int value, int flags, int we_version);
  • TIME SUBROUTINES(1个)

    1. void iw_print_timeval(char *buffer, int buflen, const struct timeval *time, const struct timezone *tz);
  • ADDRESS SUBROUTINES(9个)

    1. int iw_check_mac_addr_type(int skfd, const char *ifname);
    2. int iw_check_if_addr_type(int skfd, const char *ifname);
    3. char *iw_mac_ntop(const unsigned char *mac, int maclen, char *buf, int buflen);
    4. void iw_ether_ntop(const struct ether_addr *eth, char *buf);
    5. char *iw_sawap_ntop(const struct sockaddr *sap, char *buf);
    6. int iw_mac_aton(const char *orig, unsigned char *mac, int macmax);
    7. int iw_ether_aton(const char *bufp, struct ether_addr *eth);
    8. int iw_in_inet(char *bufp, struct sockaddr *sap);
    9. int iw_in_addr(int skfd, const char *ifname, char *bufp, struct sockaddr *sap);
  • MISC SUBROUTINES(1个)

    1. int iw_get_priv_size(int args);
  • EVENT SUBROUTINES(2个)

    1. void iw_init_event_stream(struct stream_descr *stream, char *data, int len);
    2. int iw_extract_event_stream(struct stream_descr *stream, struct iw_event *iwe, int we_version);
  • SCANNING SUBROUTINES(2个)

    1. int iw_process_scan(int skfd, char *ifname, int we_version, wireless_scan_head *context);
    2. int iw_scan(int skfd, char *ifname, int we_version, wireless_scan_head *context);
  • 内联函数(8个)

    1. static inline int iw_set_ext(int skfd, const char *ifname, int request, struct iwreq *pwrq);
    2. static inline int iw_get_ext(int skfd, const char *ifname, int request, struct iwreq *pwrq);
    3. static inline void iw_sockets_close(int skfd);
    4. static inline char *iw_saether_ntop(const struct sockaddr *sap, char* bufp);
    5. static inline int iw_saether_aton(const char *bufp, struct sockaddr *sap);
    6. static inline void iw_broad_ether(struct sockaddr *sap);
    7. static inline void iw_null_ether(struct sockaddr *sap);
    8. static inline int iw_ether_cmp(const struct ether_addr* eth1, const struct ether_addr* eth2);

3 SOCKET SUBROUTINES(2个函数)

  • int iw_sockets_open(void);
    • 功能:打开一个 socket
    • 返回:成功时,返回一个打开的 socket;失败时,返回 -1
    • 说明:按顺序尝试使用不同的协议族打开 socket,直至成功或全部失败,协议族顺序为:AF_INET、AF_IPX、AF_AX25、AF_APPLETALK;99% 的情况下可以使用 AF_INET 协议族打开 socket。
  • void iw_enum_devices(int skfd, iw_enum_handler fn, char *args[], int count);
    • 功能:枚举所有无线接口设备
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • fn 为一个函数的指针,每找到一个无线接口,都会调用 fn,iw_enum_handler 的定义如下:
        typedef int (*iw_enum_handler)(int skfd, char *ifname, char *args[], int count);
        

        由此可见 fn() 返回的是一个 int,其调用参数有 4 个,skfd 为一个打开的 socket,ifname 为接口名称,args[] 为传递给 fn() 的自定义参数,count 为 args[] 中的参数数量;

      • argc[] 和 count 为传递给 fn() 的自定义参数,count 表示 args[] 参数的数量;
    • 可以使用 fn() 打印接口信息等;
    • 说明:这个函数的实现是首先读取文件 /proc/net/wireless 获取无线网络接口名称,然后调用 *fn(),并将获得的设备接口名称自动填到 *fn() 第二个参数 ifname 上。

4 WIRELESS SUBROUTINES(6个函数)

  • int iw_get_kernel_we_version(void);
    • 功能:获取内核中 WE(Wireless Extension) 的版本号
    • 返回:版本号
    • 说明:这个函数的实现是从文件 /proc/net/wireless 中提取出 WE 的版本号。
  • int iw_print_version_info(const char *toolname);
    • 功能:打印 Wireless Tools 所使用的 WE 的版本号,Wireless Tools 的版本号,Wireless Tools 的版本号其实就是常数 WT_VERSION,以及接口支持的 WE 版本号
    • 参数:toolsname - Wireless Tools 名称,从源码看,这个参数可以是任意字符串,或者为 NULL
    • 返回:成功返回 0,如果打开 socket 失败则返回 -1
  • int iw_get_range_info(int skfd, const char *ifname, iwrange *range);
    • 功能:从驱动程序中获取 range 信息
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • iwrange 就是 struct iw_range,获取的信息将放在 range 指向的 struct iw_range 中,struct iw_range 定义在 wireless.h 中;
    • 返回:成功返回 0,range 中存放获取的信息,失败则返回 -1
    • 说明:该函数使用 ioctl() 的 SIOCGIWRANGE 命令获取 range 信息,struct iw_range 结构比较庞大,不同的驱动程序可以返回的信息也不同。
  • int iw_get_priv_info(int skfd, const char *ifname, iwprivargs **ppriv);
    • 功能:获取有关驱动程序支持哪些私有 ioctl 的信息
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • iwprivargs 就是 struct iw_priv_args,该结构定义在 wireless.h 中,如下:
        struct iw_priv_args {
            __u32       cmd;            /* Number of the ioctl to issue */
            __u16       set_args;       /* Type and number of args */
            __u16       get_args;       /* Type and number of args */
            char        name[IFNAMSIZ]; /* Name of the extension */
        };
        
      • ppriv 为一个数组指针,成功返回后将存放该接口支持的 ioctl
    • 返回:调用成功返回支持的 ioctl 的数量,失败返回 -1;
    • 说明:该函数会动态为 ppriv 参数申请内存,所以使用完毕一定要记得 free(),源码中提示,即便返回的数据长度为 0,仍然要调用 free(*ppriv)
  • int iw_get_basic_config(int skfd, const char *ifname, wireless_config *info);
    • 功能:从设备驱动程序获取必要的(基本的)无线配置
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • wireless_config 就是 struct wireless_config,定义如下:
        typedef struct wireless_config {
            char        name[IFNAMSIZ + 1];     /* Wireless/protocol name */
            int         has_nwid;
            iwparam     nwid;                   /* Network ID */
            int         has_freq;
            double      freq;                   /* Frequency/channel */
            int         freq_flags;
            int         has_key;
            unsigned char    key[IW_ENCODING_TOKEN_MAX];    /* Encoding key used */
            int         key_size;               /* Number of bytes */
            int         key_flags;              /* Various flags */
            int         has_essid;
            int         essid_on;
            char        essid[IW_ESSID_MAX_SIZE + 1];       /* ESSID (extended network) */
            int         has_mode;
            int         mode;                   /* Operation mode */
        } wireless_config;
        
      • info 是一个指向 struct wireless_config 的指针,调用成功将存放获得的无线配置
    • 返回:成功返回 0,info 中存放着获得的无线配置,失败返回 -1
    • 说明:该函数会调用 ioctl() 的如下命令已获得无线配置信息:SIOCGIWNAME、SIOCGIWNWID、SIOCGIWFREQ、SIOCGIWENCODE、SIOCGIWESSID、SIOCGIWMODE
  • int iw_set_basic_config(int skfd, const char *ifname, wireless_config *info);
    • 功能:在设备驱动程序中设置必要的(基本的)无线配置
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • info 说明同上,为一个 struct wireless_config 结构指针;
    • 返回:全部成功返回 0,有一项或多项失败返回 -1;
    • 说明:该函数会调用 ioctl() 的如下命令已设置无线配置信息:SIOCSGIWNAME、SIOCSIWMODE、SIOCSIWFREQ、SIOCSIWENCODE、SIOCSIWNWID、SIOCSIWESSID

5 PROTOCOL SUBROUTINES(1个函数)

  • int iw_protocol_compare(const char *protocol1, const char *protocol2);
    • 功能:比较协议标识符
    • 参数:
      • protocol1 为第一个协议(字符串)
      • protecol2 为第二个协议(字符串)
    • 返回:如果协议兼容则返回 1,否则返回 0
    • 说明:如果 protocol1 和 protocol2 完全一样,返回 1;如果 protocol1 和 protocol2 的起始字符串都是 “IEEE 802.11”,则 protocol1 和 protocol2 后面字符串中只要含有 “Dbg” 之中任一个字符(protocol1 和 protocol2 中可以不一样),则返回 1,或者 protocol1 和 protocol2 中均含有 “a”(5g),也将返回 1;其它情况返回 0。

6 ESSID SUBROUTINES(2个函数)

  • void iw_essid_escape(char *dest, const char *src, const int slen);
  • int iw_essid_unescape(char *dest, const char *src);
  • 上面两个函数在 libiw.so.29 中没有,仅存在在 libiw.so.30 中。

7 FREQUENCY SUBROUTINES(7个函数)

  • void iw_float2freq(double in, iwfreq *out);

    • 功能:将浮点数转换为频率,内核是不好处理浮点数的,所以需要将一个浮点数转换成一种内部格式(struct iw_freq)传递给内核
    • 参数:
      • in 为浮点数频率
      • iwfreq 就是 struct iw_freq,是一个内核可以接受的频率格式,定义如下:
        struct iw_freq {
            __s32 m;      /* Mantissa */
            __s16 e;      /* Exponent */
            __u8  i;      /* List index (when in range struct) */
            __u8  flags;  /* Flags (fixed/auto) */
        };
        
      • in = m x 10e
    • 返回:转换结果存放在 out 中;
  • double iw_freq2float(const iwfreq *in);

    • 功能:将内部格式(struct iw_freq)表示的频率转换为浮点数
    • 参数:
      • in 为使用 struct iw_freq 表示的频率
    • 返回:返回以浮点数表示的频率
  • void iw_print_freq_value(char *buffer, int buflen, double freq);

    • 功能:将频率值转换成适当单位(GHz、MHz、kHz)的字符串
    • 参数:
      • buffer 存放转换完成的字符串的缓冲区
      • buflen 为 buffer 的长度
      • freq 频率值
    • 返回:转换好的字符串存放在 buffer 中
  • void iw_print_freq(char *buffer, int buflen, double freq, int channel, int freq_flags);

    • 功能:将频率值转换成适当单位(GHz、MHz、kHz)的字符串,并分离出工作信道(channel)
    • 说明:当使用 ioctl() 获取工作频率时,如果返回值 < 1000 则该值为工作信道(channel),否则为工作频率;当 freq < 1000 时,该函数转换成类似 Channel:5 这样的字符串,否则,转换成类似 Frequency:5.265 GHz 这样的字符串;
    • 参数:
      • buffer 存放转换完成的字符串的缓冲区
      • buflen 为 buffer 的长度
      • freq 频率值
      • channel >= 0 时,转换的字符串类似 Frequency:5.265 GHz (Channel 3) 这样的字符串;
      • freq_flags = 1 时,转换出的字符串类似 Frequency=5.265 GHz,否则为 Frequency:5.265 GHz
    • 返回:转换好的字符串存放在 buffer 中
  • int iw_freq_to_channel(double freq, const struct iw_range *range);

    • 功能:得到工作频率对应的工作信道(channel)
    • 参数:
      • freq 为工作频率值
      • range 从接口驱动程序中获取的 range
    • 返回:>=0 时表示工作频率所在的工作信道,-2 表示在 range 中没有找到指定的频率 freq,-1 表示 freq < 1000
    • 说明:struct iw_range 定义在 wireless.h 中,其中有一个 struct iw_freq 的结构数组,该函数将从这个结构数组(struct iw_freq).freq)中查找与 freq 一致的频率,找到后返回 (struct iw_freq).i,否则返回 -2,当参数 freq < 1000 时,返回 -1
  • int iw_channel_to_freq(int channel, double *pfreq, const struct iw_range *range);

    • 功能:将工作信道转换成工作频率
    • 参数:
      • channel 为工作信道
      • pfreq 为存放频率的指针,转换好的频率将存放在这里
      • range 从接口驱动程序中获取的 range
    • 返回:转换成功返回 channel,否则返回 <0 的值
    • 说明:参考前面 struct iw_freq 的定义,struct iw_range 定义在 wireless.h 中,从 range 中的 struct iw_freq 结构数组中的 (struct iw_freq).i 中查找与 channel 一致的项,并将其对应的 (struct iw_freq).freq 存放到 pfreq 中;
  • void iw_print_bitrate(char *buffer, int buflen, int bitrate);

    • 功能:将传输速率(bitrate)以适当的单位(Gb/s、Mb/s、kb/s)表示的字符串
    • 参数:
      • buffer 为存放转换结果字符串的缓冲区
      • buflen 为 buffer 的长度
      • bitrate 为要转换的传输速率
    • 返回:转换好的字符串存放在 buffer 中
    • 说明:当速率 >109 时,单位为 Gb/s,当速率 >106 时,单位为 Mb/s,当速率 >1000 时,单位为 kb/s

8 POWER SUBROUTINES(3个函数)

  • int iw_dbm2mwatt(int in);

    • 功能:将 dBm 值转换为毫瓦值
    • 参数:
      • in 为功率的 dBm 值
    • 返回:转换后的毫瓦值
  • int iw_mwatt2dbm(int in);

    • 功能:将毫瓦值转换为 dBm 值
    • 参数:
      • in 为以毫瓦表示的功率值
    • 返回:转换后的 dBm 值
  • void iw_print_txpower(char *buffer, int buflen, struct iw_param *txpower);

    • 功能:txpower 表示发射功率,本函数对 txpower 进行适当的转换,转换结果以字符串输出
    • 参数:
      • buffer 为存放转换结果字符串的缓冲区
      • buflen 为 buffer 的长度
      • struct iw_param 时 WE 下的一个通用结构,定义在 wireless.h 中,具体如下:
        struct iw_param {
            __s32       value;      /* The value of the parameter itself */
            __u8        fixed;      /* Hardware should not use auto select */
            __u8        disabled;   /* Disable the feature */
            __u16       flags;      /* Various specifc flags (if any) */
        };
        
      • txpower->value 为发射功率值,当 txpower->flags 的 bit 0 为 1 时,value 的单位为毫瓦(否则为 dBm),当 bit 1 为 1 时表示 value 中的值是一个相对值,没有具体单位
    • 返回:转换结果存放在 buffer 中

9 STATISTICS SUBROUTINES(2个函数)

  • int iw_get_stats(int skfd, const char *ifname, iwstats *stats, const iwrange *range, int has_range);

    • 功能:读取文件 /proc/net/wireless 获取最新的统计数据
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • iwstats 就是 struct iw_statistics,定义在 wireless.h 中,如下:
        struct iw_statistics {
            __u16               status;     /* Status - device dependent for now */
            struct iw_quality   qual;       /* Quality of the link (instant/mean/max) */
            struct iw_discarded discard;    /* Packet discarded counts */
            struct iw_missed    miss;       /* Packet missed counts */
        };
        
      • 其中:struct iw_qualitystruct iw_discardedstruct iw_missed 均定义在 wireless.h 中
      • 从文件 /proc/net/wireless 读出的统计信息存放在 stats 指向的 struct iw_statistics
      • has_range 为 1 表示 range 参数存在,range 参数仅用于比较 WE 的版本号,因为 WE version 11 以后才有 /proc/net/wireless 文件
    • 返回:调用成功返回 0,stats 中存放有统计数据,调用失败返回 -1
  • void iw_print_stats(char *buffer, int buflen, const iwqual *qual, const iwrange *range, int has_range);

    • 功能:获取连接统计数据,包括信号质量、信号强度和信号噪音,以字符串形式输出
    • 参数:
      • buffer 为存放转换结果字符串的缓冲区
      • buflen 为 buffer 的长度
      • iwqual 就是 struct iw_quality,定义在 wireless.h 中,如下:
        struct iw_quality {
            __u8    qual;       /* link quality (%retries, SNR, %missed beacons or better...) */
            __u8    level;      /* signal level (dBm) */
            __u8    noise;      /* noise level (dBm) */
            __u8    updated;    /* Flags to know if updated */
        };
        
      • 关于信号质量以及相关数据结构的说明,请参考文章《使用ioctl扫描wifi信号获取信号属性的实例(二)》
      • has_range 为 1 表示 range 参数存在,该函数中将使用 range->max_qual.qualrange->max_qual.levelrange->max_qual.noise
    • 返回:信号质量、信号强度和信号噪音,将转换成字符串存放在 buffer 中

10 ENCODING SUBROUTINES(3个函数)

  • void iw_print_key(char *buffer, int buflen, const unsigned char *key, int key_size, int key_flags);

    • 功能:按照一个特定的格式显示经过编码后的秘钥
    • 参数:
      • buffer 为存放转换结果字符串的缓冲区
      • buflen 为 buffer 的长度
      • key 为经过编码的秘钥
      • key_size 为 key 的长度
      • key_flags 为秘钥的标志,当 bit 8 为 1 时,表示没有秘钥
    • 返回:秘钥转换成特定格式的字符串存放在 buffer中
  • int iw_in_key(const char *input, unsigned char *key);

    • 功能:从命令行解析密钥
    • 参数:
      • input 为密码字符串
      • key 为转换为以 16 进制表示的秘钥
    • 返回:>0 时为秘钥的长度,=0 表示没有秘钥,
    • 说明:
      • input 为一个字符串,当没有任何标志时,应该是用字符串表达的 16 进制数,比如:“01:2A:0C:E3:…”,转换完存放在 key 中是一个 8 位无符号整数数组,比如:{0X01, 0X2A, 0X0C, 0XE3, ...}
      • 当 input 起始字符为 “s:” 时,表示 input 中为一个由 ASCII 字符组成的字符串,比如:“Abc123…”,转换完放在 key 中的 8 位无符号整数数组为:{0X41, 0X62, 0X63, 0X31, 0X32, 0X33, ...}
  • int iw_in_key_full(int skfd, const char *ifname, const char *input, unsigned char *key, __u16 *flags);

    • 功能:从命令行解析密钥,当 input 起始字符为 “l:” 时,被认为是登录的 username:password,否则调用 iw_in_key()
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • input 为密码字符串
      • key 为转换为以 16 进制表示的秘钥
      • flags
    • 说明:skfd 和 ifname 用于获取 range,然后根据 WE 的版本号及 range.encoding_login_index 设置 flags

11 POWER MANAGEMENT SUBROUTINES(2个函数)

  • void iw_print_pm_value(char *buffer, int buflen, int value, int flags, int we_version);

    • 功能:将电源管理值 value 根据 flags 的提示转换成适当的字符串存入 buffer 中
    • 参数:
      • buffer 为转换后存放字符串的缓冲区
      • buflen 为 buffer 的长度
      • value 为电源管理值(power management value)
      • flags 一些标志电源管理值属性的标志,bit0-
      • we_version 为 WE 的版本号
    • 返回:buffer 中存放转换后的字符串
    • 说明:
  • void iw_print_pm_mode(char *buffer, int buflen, int flags);

    • 功能:将 flags 中的电源管理方式转换成字符串存放在 buffer 中
    • 参数:
      • buffer 为转换后存放字符串的缓冲区
      • buflen 为 buffer 的长度
      • flags 为电源管理方式标志,bit8-11 为电源管理方式,bit8-Unicast only received,bit9-Multicast only received,bit10-All packets received,bit11-Force sending,bit12-Repeat multicasts

12 RETRY LIMIT/LIFETIME SUBROUTINES(1个函数)

  • void iw_print_retry_value(char *buffer, int buflen, int value, int flags, int we_version);
    • 功能:将重试值 value 根据 flags 的提示转换成适当的字符串存入 buffer 中
    • 参数:
      • buffer 为转换后存放字符串的缓冲区
      • buflen 为 buffer 的长度
      • value 为重试值(retry value)
      • flags 一些属性的标志
      • we_version 为 WE 的版本号
    • 返回:buffer 中存放转换后的字符串

13 TIME SUBROUTINES(1个函数)

  • void iw_print_timeval(char *buffer, int buflen, const struct timeval *time, const struct timezone *tz);
    • 功能:将 time 中的时间戳转换成字符串存放在 buffer 中
    • 参数:
      • buffer 为转换后存放字符串的缓冲区
      • buflen 为 buffer 的长度
      • time 为时间戳
      • tz 为时间戳所在时区
    • 返回:buffer 中存放转换后的字符串

14 ADDRESS SUBROUTINES(9个函数)

  • int iw_check_mac_addr_type(int skfd, const char *ifname);

    • 功能:检查网络接口是否支持正确 MAC 地址类型
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
    • 返回:0 表示支持 MAC 地址,-1 表示不支持 MAC 地址
    • 说明:通过 ioctl() 的 SIOCGIFHWADDR 命令获取 HW 的地址类型,应该为 ARPHRD_ETHER 或者 ARPHRD_IEEE80211
  • int iw_check_if_addr_type(int skfd, const char *ifname);

    • 功能:检查网络接口是否支持正确的接口地址类型(INET)
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
    • 返回:0 表示支持接口地址类型,-1 表示不支持接口地址类型
    • 说明:通过 ioctl() 的 SIOCGIFADDR 命令获取接口地址类型,应该为 AF_INET
  • char *iw_mac_ntop(const unsigned char *mac, int maclen, char *buf, int buflen);

    • 功能:以可读格式显示任意长度的 MAC 地址
    • 参数:
      • mac 为 16 进制表示的 MAC 地址
      • maclen 为 mac 的长度
      • buf 为 MAC 地址转换为字符串后的存储区
      • buflen 为 buf 的有效长度
    • 返回:成功返回 buf 指针,失败返回 NULL
  • void iw_ether_ntop(const struct ether_addr *eth, char *buf);

    • 功能:以可读格式显示以太网地址(实际就是 MAC 地址)
    • 参数:
      • struct ether_addr 定义在 ethernet.h 中,如下:
        struct ether_addr {
            uint8_t ether_addr_octet[ETH_ALEN];
        } __attribute__ ((__packed__));
        
      • 其实就是一个 8 位无符号整数的数组,数组有 6 个(因为 ETH_ALEN 为 6)元素
      • buf 转换后以字符串表示的以太网地址存放在这里
    • 返回:buf 中存放着已经转换好的字符串
    • 说明:iw_mac_ntop() 把一个任意长度的 MAC 地址转换成字符串,其输入参数为一个 unsigned char 数组,iw_ether_ntop() 将一个长度为 6 个字符的 unsigned char 数组转换为字符串,输入参数为 struct ether_addr,两个函数本质上非常相似。
  • char *iw_sawap_ntop(const struct sockaddr *sap, char *buf);

    • 功能:以可读格式显示无线接入点 socket 地址
    • 参数:
      • struct sockaddr 定义在文件 socket.h 中,如下:
        struct sockaddr {
            sa_family_t sa_family;	/* Common data: address family and length.  */
            char sa_data[14];		/* Address data.  */
        };
        
      • buf 转换后以字符串表示的以太网地址存放在这里
    • 返回:返回 buf 指针,buf 中存储着转换结果
    • 说明:实际上就是使用 iw_ether_ntop() 将 socket.sa_data 中的 MAC 地址转换成字符串,这个函数仍然是把 MAC 地址转换为字符串,不过输入参数是 struct sockaddr 而已。

iw_mac_ntop()iw_ether_ntop()iw_sawap_ntop() 都是把 MAC 地址转换成易读的字符串形式,但各自的输入参数不同,iw_mac_ntop() 的输入参数是一个任意长度的二进制数组;iw_ether_ntop() 的输入参数是 struct ether_addr;iw_sawap_ntop() 的输入参数是 struct sockaddr

  • int iw_mac_aton(const char *orig, unsigned char *mac, int macmax);

    • 功能:将任意长度的字符串表达的 MAC 地址,转换成二进制
    • 参数:
      • orig 为以字符串格式表达的一个 MAC 地址
      • mac 为 MAC 地址转换为二进制后存放在这里
      • macmax 为 mac 的最大长度
    • 返回:成功则返回转换后 MAC 地址长度,失败则返回 0
  • int iw_ether_aton(const char *orig, struct ether_addr *eth);

    • 功能:将一个以字符串形式表达的以太网地址转换成二进制
    • 参数:
      • orig 为以字符串格式表达的一个以太网地址
      • struct ether_addr 在前面有介绍,转换好的二进制以太网地址存放在 eth 中
    • 返回:成功则返回以太网地址的长度,失败返回 0
    • 说明:iw_mac_aton()iw_ether_aton() 都是把一个字符串表达的 MAC 地址转换成二进制形式,iw_mac_aton() 的输出参数是一个 unsigned char 数组,iw_ether_aton() 的输出参数是 struct ether_addriw_mac_aton() 是任意长度,iw_ether_aton() 是 6 个字符长度。

iw_mac_aton()、iw_ether_aton()、

  • int iw_in_inet(char *bufp, struct sockaddr *sap);

    • 功能:将一个以字符串表达的互联网地址(域名)转换成二进制(DNS 名称、IP 地址等)
    • 参数:
      • bufp 为一个以字符串表达的互联网地址,可以是域名、IP 地址
      • sap 存放转换结果的结构,bufp 中如果不是官方域名,将改为官方域名
    • 返回:成功返回 0,失败返回 -1
    • 说明:该函数会使用 gethostbyname() 将域名(主机名)进行解析
  • int iw_in_addr(int skfd, const char *ifname, char *bufp, struct sockaddr *sap);

    • 功能:将一个以字符串表达的地址转换成二进制
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • bufp 为一个用字符串格式表达的地址
      • sap 转换为二进制后存放在这个结构中
    • 返回:成功返回 0,失败返回 -1
    • 说明:bufp 中既可以是 MAC 地址,也可以是 IP 地址,该函数实际上就是用 MAC 地址生成一个 struct sockaddr

15 MISC SUBROUTINES(1个函数)

  • int iw_get_priv_size(int args);
    • 功能:返回私有参数以字节为单位的最大长度
    • 参数:args 私有参数的标志,bit0-10 表示参数的数量,bit12-14 表示参数的类型
    • 返回:返回私有参数以字节为单位的最大长度

16 EVENT SUBROUTINES(2个函数)

  • void iw_init_event_stream(struct stream_descr *stream, char *data, int len);

    • 功能:初始化结构体stream_descr,以便我们可以从事件流中提取单个事件
    • 参数:
      • struct stream_descr 定义在 iwlib.h 中,如下:
        struct stream_descr {
            char *end;          /* End of the stream */
            char *current;      /* Current event in stream of events */
            char *value;        /* Current value in event */
        } stream_descr;
        
      • stream 为需要初始化的结构指针
      • data 为事件流数据的起始指针
      • len 为事件流数据的长度
    • 返回:stream->current=data,stream->end=(data+len)
  • int iw_extract_event_stream(struct stream_descr *stream, struct iw_event *iwe, int we_version);

    • 功能:从事件流中提取下一个事件
    • 参数:
      • stream 为经过 iw_init_event_stream() 初始化的结构
      • struct iw_event 定义在 wireless.h 中,如下:
        struct iw_event {
            __u16   len;            /* Real lenght of this stuff */
            __u16   cmd;            /* Wireless IOCTL */
            union iwreq_data u;     /* IOCTL fixed payload */
        };
        
      • iwe 将用于存储当前要提取的事件
      • we_version 为 WE 的版本号
    • 返回:成功返回 1,此时 iwe 中为当前事件,失败返回 -1,返回 2 表示跳过了当前事件

7 SCANNING SUBROUTINES(2个函数)

  • int iw_process_scan(int skfd, char *ifname, int we_version, wireless_scan_head *context);

    • 功能:启动无线信号扫描程序并处理结果
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • we_version 为 WE 的版本号
      • wireless_scan_head 就是 struct wireless_scan_head,定义在 iwlib.h 中,如下:
        struct wireless_scan_head {
            wireless_scan *result;      /* Result of the scan */
            int            retry;       /* Retry level */
        } wireless_scan_head;
        
      • context 中将存储获取的扫描结果的首指针,以及获取扫描结果重试的次数
      • wireless_scan 就是 struct wireless_scan,定义在 iwlib.h 中,如下:
        struct wireless_scan
        {
            /* Linked list */
            struct wireless_scan *next;
        
            /* Cell identifiaction */
            int         has_ap_addr;
            sockaddr    ap_addr;        /* Access point address */
        
            /* Other information */
            struct  wireless_config	b;  /* Basic information */
            iwstats stats;              /* Signal strength */
            int     has_stats;
            iwparam maxbitrate;         /* Max bit rate in bps */
            int     has_maxbitrate;
        }
        
      • 扫描结果存放在 struct wireless_scan 中,并且以链表形式存储多个多个无线信号的扫描结果;
      • struct wireless_scan 中的 struct wireless_config 在前面有介绍;
    • 返回:成功则返回 0
  • int iw_scan(int skfd, char *ifname, int we_version, wireless_scan_head *context);

    • 功能:对指定接口执行无线信号扫描
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • we_version 为 WE 的版本号
      • context 中将存储获取的扫描结果的首指针,以及获取扫描结果重试的次数
    • 返回:成功则返回 0,失败返回 -1

8 内联函数(8个函数)

  • 这 8 个内联函数(inline)定义在 iwlib.h 中;
  • static inline int iw_set_ext(int skfd, const char *ifname, int request, struct iwreq *pwrq);
    • 功能:将无线网卡的参数通过调用 ioctl() 设置到驱动程序中
  • static inline int iw_get_ext(int skfd, const char *ifname, int request, struct iwreq *pwrq);
    • 功能:通过调用 ioctl() 从无线网卡驱动程序中获取无线参数
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
      • ifname 为网络接口名称
      • request 为调用 ioctl() 时的命令代码,定义在 wireless.h 中
      • pwrq 为一个 struct iwreq 的结构指针,不同的 request,其填写方法也不一样
    • 返回:返回 ioctl() 调用的返回值,0 表示调用成功,-1 表示出现错误,errno 中为错误代码

说明:上面这两个内联函数其实是一样的,都是调用指定的 ioctl(),WE 支持的 ioctl 调用方式为:int ioctl(int fd, unsigned long request, struct iwreq *pwrq),其 request 通常有两种,一种是 SIOCS*,另一种是 SIOCG*,均定义在 wireless.h 中,按照惯例,当 request 为 SIOCS* 时,使用 iw_set_ext(),当 request 为 SIOCG* 时,使用 iw_get_ext()。

  • static inline void iw_sockets_close(int skfd);

    • 功能:关闭一个打开的 socket
    • 参数:
      • skfd 为一个使用 iw_sockets_open() 打开的 socket
    • 返回:无
    • 说明:实际调用 close(skfd)
  • static inline char *iw_saether_ntop(const struct sockaddr *sap, char* bufp);

    • 功能:将 struct sockaddr 中的 MAC 地址转换成可读格式的字符串
    • 参数:
      • sap 是一个 struct sockaddr 的结构指针,这个结构在 socket 编程中常会用到
      • bufp 一个字符缓冲区指针,转换好的字符串存放在这里
    • 返回:转换完成的字符串指针,也就是 bufp
    • 说明:bufp 的长度务必大于等于 18个字符,否则会内存溢出,该函数实际是调用了 iw_ether_ntop()
  • static inline int iw_saether_aton(const char *bufp, struct sockaddr *sap);

    • 功能:将一个以字符串表示的 MAC 地址转换成二进制格式
    • 参数:
      • bufp 指向 MAC 地址字符串的指针
      • sap 指向结构 struct sockaddr 的指针,转换结果将放到该结构的 sa_data 字段中
    • 返回:成功则返回 MAC 地址的长度,失败则返回 0
    • 说明:该函数实际调用 iw_ether_aton() 函数
  • static inline void iw_broad_ether(struct sockaddr *sap);

    • 功能:创建一个以太网广播地址
    • 参数:
      • sap 指向结构 struct sockaddr 的指针
    • 返回:无,建立的广播地址放在 sap 的 sa_data 字段中
    • 说明:广播地址就是:FF:FF:FF:FF:FF:FF,该函数实际就是在 sap 的 sa_data 中填上 6 个 0xff
  • static inline void iw_null_ether(struct sockaddr *sap);

    • 功能:建立一个以太网空地址
    • 参数:
      • sap 指向结构 struct sockaddr 的指针
    • 返回:无,建立的广播地址放在 sap 的 sa_data 字段中
    • 说明:空地址就是:00:00:00:00:00:00,该函数实际就是在 sap 的 sa_data 中填上 6 个 0
  • static inline int iw_ether_cmp(const struct ether_addr* eth1, const struct ether_addr* eth2);

    • 功能:比较两个以太网地址
    • 参数:
      • eth1 指向结构 struct ether_addr 的指针
      • eth2 指向结构 struct ether_addr 的指针
    • 返回:eth1 < eth2 则小于 0,eth1 > eth2 则大于 0,否则等于 0
    • 说明:该函数使用 memcmp() 对两个以太网地址的二进制数据进行比较,其意义不甚清楚,其结果的意义似乎也不明确

欢迎订阅 『网络编程专栏』

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

whowin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值