zoukankan      html  css  js  c++  java
  • wpa_supplicant下行接口浅析

    wpa_supplicant通过socket通信机制实现下行接口,与内核进行通信,获取信息或下发命令。

    以下摘自http://blog.csdn.net/fxfzz/article/details/6176414 ,该文章应该主要是分析wpa_supplicant_6的,和wpa_supplicant_8确实存在一些差别!!!以下还是根据6来分析。

    wpa_supplicant提供的下行接口主要用于和kernel(driver)进行通信,下发命令和获取信息。

    wpa_supplicant下行接口主要包括三种重要的接口:

    1.PF_INET socket接口,主要用于向kernel 发送ioctl命令,控制并获取相应信息。
    2.PF_NETLINK socket接口,主要用于接收kernel发送上来的event 事件。
    3.PF_PACKET socket接口,主要用于向driver传递802.1X报文。

    主要涉及到的文件包括:driver.h,drivers.c,driver_wext.h,driver_wext.c,l2_packet.h和l2_packet_linux.c。其中,

    driver.h,drivers.c,driver_wext.h和driver_wext.c实现PF_INET socket接口和PF_NETLINK socket接口;
    l2_packet.h和l2_packet_linux.c实现PF_PACKET socket接口。

    (1) driver.h/drivers.c:主要用于封装底层差异,对外显示一个相同的wpa_driver_ops接口。wpa_supplicant可支持atmel, Broadcom, ipw, madwifi, ndis, nl80211, wext等多种驱动。

    其中一个最主要的数据结构为wpa_driver_ops, 其定义了driver相关的各种操作接口。

     

    (2) driver_wext.h/driver_wext.c实现了wext形式的wpa_driver_ops,并创建了PF_INET socket接口和PF_NETLINK socket接口(wpa_supplicant_8中没有创建PF_NETLINK socket接口),然后通过这两个接口完成与kernel的信息交互。

     

    wext提供的一个主要数据结构为:

    struct wpa_driver_wext_data {
           void *ctx;
           int event_sock;  //PF_NETLINK socket接口
           int ioctl_sock;   //PF_INET socket接口
           int mlme_sock;
           char ifname[IFNAMSIZ + 1];
           int ifindex;
           int ifindex2;
           int if_removed;
           u8 *assoc_req_ies;
           size_t assoc_req_ies_len;
           u8 *assoc_resp_ies;
           size_t assoc_resp_ies_len;
           struct wpa_driver_capa capa;
           int has_capability;
           int we_version_compiled;
     
           /* for set_auth_alg fallback */
           int use_crypt;
           int auth_alg_fallback;
     
           int operstate;
     
           char mlmedev[IFNAMSIZ + 1];
     
           int scan_complete_events;
    };

    其中event_sock 为PF_NETLINK socket接口,ioctl_sock为PF_INET socket接口。

    driver_wext.c实现了大量底层处理函数用于实现wpa_driver_ops操作参数,其中比较重要的有:

    /* 初始化wpa_driver_wext_data 数据结构,并创建PF_NETLINK socket和 PF_INET socket 接口 */
    void * wpa_driver_wext_init(void *ctx, const char *ifname);
     
    /* 销毁wpa_driver_wext_data 数据结构,PF_NETLINK socket和 PF_INET socket 接口 */
    void wpa_driver_wext_deinit(void *priv);
     
    //下面这个方法在wpa_supplicant_6上,wpa_supplicant_8中没有....
    static void wpa_driver_wext_event_receive(int sock, void *eloop_ctx,
                                         void *sock_ctx);
    /* 处理kernel主动发送的event事件的 callback 函数 */

    最后,将实现的操作函数映射到一个全局的wpa_driver_ops类型数据结构 wpa_driver_wext_ops中。

    const struct wpa_driver_ops wpa_driver_wext_ops = {
           .name = "wext",
           .desc = "Linux wireless extensions (generic)",
           .get_bssid = wpa_driver_wext_get_bssid,
           .get_ssid = wpa_driver_wext_get_ssid,
           .set_wpa = wpa_driver_wext_set_wpa,
           .set_key = wpa_driver_wext_set_key,
           .set_countermeasures = wpa_driver_wext_set_countermeasures,
           .set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted,
           .scan = wpa_driver_wext_scan,
           .get_scan_results2 = wpa_driver_wext_get_scan_results,
           .deauthenticate = wpa_driver_wext_deauthenticate,
           .disassociate = wpa_driver_wext_disassociate,
           .set_mode = wpa_driver_wext_set_mode,
           .associate = wpa_driver_wext_associate,
           .set_auth_alg = wpa_driver_wext_set_auth_alg,
           .init = wpa_driver_wext_init,
           .deinit = wpa_driver_wext_deinit,
           .add_pmkid = wpa_driver_wext_add_pmkid,
           .remove_pmkid = wpa_driver_wext_remove_pmkid,
           .flush_pmkid = wpa_driver_wext_flush_pmkid,
           .get_capa = wpa_driver_wext_get_capa,
           .set_operstate = wpa_driver_wext_set_operstate,
    };

    (3) l2_packet.h/l2_packet_linux.c主要用于实现PF_PACKET socket接口,通过该接口,wpa_supplicant可以直接将802.1X packet发送到L2层,而不经过TCP/IP协议栈。

    其中主要的功能函数为:

    /* 创建并初始化PF_PACKET socket接口,其中rx_callback 为从L2接收到的packet 处理callback函数 */
    struct l2_packet_data * l2_packet_init(
           const char *ifname, const u8 *own_addr, unsigned short protocol,
           void (*rx_callback)(void *ctx, const u8 *src_addr,
                             const u8 *buf, size_t len),
           void *rx_callback_ctx, int l2_hdr);

    ps:l2_packet_init方法中有代码:

    eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);

    即注册了与socket关联的回调方法为l2_packet_receive。

     

    /* 销毁 PF_PACKET socket接口 */
    void l2_packet_deinit(struct l2_packet_data *l2);
     
    /* L2层packet发送函数,wpa_supplicant用此发送L2层 802.1X packet  */
    int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
                     const u8 *buf, size_t len);
     
    /*  L2层packet接收函数,接收来自L2层数据后,将其发送到上层  */
    static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx);

    最后,附图说明wpa_supplicant与驱动交互的过程。从该图看,因为应用层部分还有WifiLayer类,说明android源码应该是2.1的,比较老了。不过分析了下wpa_supplicant,感觉变动不大,还是可以参考一下底层这一部分的。

  • 相关阅读:
    pyCharm专业版下载以及永久破解2099年过期
    win10安装最新的python3解释器
    Ubuntu软件源更换
    Ubuntu安装软件命令
    Target runtime Apache Tomcat 6.0 is not defined
    ajaxFileUpload 报这错jQuery.handleError is not a function
    怎样编写高质量的Java代码
    java 内存监控工具 jstat jmap
    jquery中attr和prop的区别
    javax.mail.MessagingException: 501 Syntax: HELO hostname
  • 原文地址:https://www.cnblogs.com/chenbin7/p/3266032.html
Copyright © 2011-2022 走看看