玩转「Wi-Fi」系列之wpa_supplicant - main分析(十)

这一章主要进行wpa_supplicant_init函数的分析

struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
{
    struct wpa_global *global;
    //设置全局回调函数
    wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
    //设置输出到文件或终端
    if (params->wpa_debug_file_path)
        wpa_debug_open_file(params->wpa_debug_file_path);
    else
        wpa_debug_setup_stdout();
    //注册EAP 
    ret = eap_register_methods();
    //创建一个global对象
    global = os_zalloc(sizeof(*global));
    dl_list_init(&global->p2p_srv_bonjour);
    dl_list_init(&global->p2p_srv_upnp);
    //事件循环机制初始化
    if (eloop_init()) {
        wpa_printf(MSG_ERROR, "Failed to initialize event loop");
        wpa_supplicant_deinit(global);
        return NULL;
    }
    // 随机数初始化
    random_init(params->entropy_file);
    //初始化全局控制接口对象
    global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
    if (global->ctrl_iface == NULL) {
        wpa_supplicant_deinit(global);
        return NULL;
    }
    //初始化通知机制相关资源,和dbug有关
    if (wpas_notify_supplicant_initialized(global)) {
        wpa_supplicant_deinit(global);
        return NULL;
    }
    for (i = 0; wpa_drivers[i]; i++)
        global->drv_count++;
    if (global->drv_count == 0) {
        wpa_printf(MSG_ERROR, "No drivers enabled");
        wpa_supplicant_deinit(global);
        return NULL;
    }
    //分配全局driver wrapper 上下文信息数组
    global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
    if (global->drv_priv == NULL) {
        wpa_supplicant_deinit(global);
        return NULL;
    }
    // 注册超时
    eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
                   wpas_periodic, global, NULL);
    return global;
}

分析函数可知wpa_supplicant_init函数的主要功能是初始化wpa_global以及相关资源,包括注册EAP,事件循环,回调函数处理

关键函数
1. eap_register_methods函数
int eap_register_methods(void)
{
    int ret = 0;

#ifdef EAP_MD5
    if (ret == 0)
        ret = eap_peer_md5_register();
#endif /* EAP_MD5 */

#ifdef EAP_TLS
    if (ret == 0)
        ret = eap_peer_tls_register();
#endif /* EAP_TLS */

#ifdef EAP_TLS
#ifdef CONFIG_HS20
    if (ret == 0)
        ret = eap_peer_wfa_unauth_tls_register();
#endif /* CONFIG_HS20 */
#endif /* EAP_TLS */
....
    return ret;
}

根据不同的编译选项来注册所需要的eap method。 例如 MD5身份验证对应的注册函数eap_peer_md5_register。该函数内部将填充一个eap_method的数据结构

2. eloop_init函数
int eloop_init(void)
{
    os_memset(&eloop, 0, sizeof(eloop));
    dl_list_init(&eloop.timeout);
    // epoll 创建
    eloop.epollfd = epoll_create1(0);
    // 队列 创建
    eloop.kqueuefd = kqueue();
    // 指定eloop 读写事件类型
    eloop.readers.type = EVENT_TYPE_READ;
    eloop.writers.type = EVENT_TYPE_WRITE;
    eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
    //信号捕获
    signal(SIGSEGV, eloop_sigsegv_handler);
    return 0;
}

函数采用epoll实现了I/O复用,并指定了一些事件类型

  • read type 读事件
  • write type 写事件
  • exceptions type 异常事件
  • timeout type 超时事件
  • signal type 信号事件
3. 数据结构 wpa_drivers 数组

wpa_drivers 是一个全局数据变量,定义在drivers.c中如下所示

const struct wpa_driver_ops *const wpa_drivers[] =
{
#ifdef CONFIG_DRIVER_NL80211
    &wpa_driver_nl80211_ops,
#endif /* CONFIG_DRIVER_NL80211 */
#ifdef CONFIG_DRIVER_WEXT
    &wpa_driver_wext_ops,
#endif /* CONFIG_DRIVER_WEXT */
  ... 其他driver接口
};

wpa_drivers定义

const struct wpa_driver_ops *const wpa_drivers[] = { NULL };

wpa_drivers 数组成员指向一个wpa_driver_ops类型对象,其中wpa_driver_ops是driver i/f 模块的核心数据结构,内部定义了很多函数指针,正是通过定义函数指针的方法wpa_supplicant能够隔离上层使用者和具体的drivers。

wpa_driver_ops原型定义如下

struct wpa_driver_ops {
    /** Name of the driver interface */
    const char *name;
    /** One line description of the driver interface */
    const char *desc;

    int (*get_bssid)(void *priv, u8 *bssid);

    int (*get_ssid)(void *priv, u8 *ssid);

    int (*set_key)(const char *ifname, void *priv, enum wpa_alg alg,
               const u8 *addr, int key_idx, int set_tx,
               const u8 *seq, size_t seq_len,
               const u8 *key, size_t key_len);


    void * (*init)(void *ctx, const char *ifname);
   .... //其它函数指针 
}

wpa_drivers 数据包含多个drivers wrapper对象是由编译选项来控制的,如代码中的CONFIG_DRIVER_NL80211,可在defconfig修改

wpa_driver_nl80211_ops的定义

const struct wpa_driver_ops wpa_driver_nl80211_ops = {
    //名称
    .name = "nl80211",              
    //描述信息   
    .desc = "Linux nl80211/cfg80211",
    //获取bssid 
    .get_bssid = wpa_driver_nl80211_get_bssid,
    //获取ssid
    .get_ssid = wpa_driver_nl80211_get_ssid,
    //扫描
    .scan2 = driver_nl80211_scan2,
    //获取扫描结果
    .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
    //触发deauthenticate操作
    .deauthenticate = driver_nl80211_deauthenticate,
    //触发authenticat操作
    .authenticate = driver_nl80211_authenticate,
    //触发associate操作
    .associate = wpa_driver_nl80211_associate,
    //全局初始化,返回值保存在wpa_global成员变量drv_pri数组中    
    .global_init = nl80211_global_init,
    .global_deinit = nl80211_global_deinit,
    .... 
    // 处理和具体驱动相关的命令
    .driver_cmd = wpa_driver_nl80211_driver_cmd,
};

本文介绍了main函数中一个关键函数wpa_supplicant_init。其中涉及重要的数据结构,如wpa_drivers_ops,eap_method等,由于这一节只是初步介绍了event的初始化,下一节重点介绍

event_loop的工作原理,这也是wpa_supplicant的事件核心点。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序手艺人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值