wpa_supplicant初始化关键函数

1. wpa_supplicant_init()网络

初始化成功后,返回的wpa_global指针可用于添加删除接口,最后,deinit wpa_supplicant。数据结构

传入的参数为命令行输入的接口无关的参数wpa_params。dom

1、main() 
一、 wpa_supplicant的入口函数在external\wpa_supplicant\main.c里面,入口main()。 
 
二、 main()函数里申明的结构体中,socket

        wpa_global为最重要的结构体,是wpa_supplicant的全局数据结构;ide

        wpa_interface结构体是wpa_supplicant_add_iface()函数为wpa_supplicant增长网络接口时要用到的接口配置选项,该函数的具体功能在函数申明(external\wpa_supplicant\wpa_supplicant.c)时有具体的解释;函数

        wpa_params结构体是wpa_supplicant_init()函数为初始化wpa_supplicant时要使用的参数,该函数的具体功能在函数申明(external\wpa_supplicant\wpa_supplicant.c)时有具体的解释。oop

三、 main()函数主要作了四个工做: 
    a、根据命令行参数设置wpa_params结构体; 
    b、调用wpa_supplicant_init()函数初始化wpa_supplicant; 
    c、调用wpa_supplicant_add_iface()函数为wpa_supplicant增长网络接口;spa

    d、调用wpa_supplicant_run()让wpa_supplicant跑起来。命令行

2、wpa_supplicant_init () 
一、 该函数位于external\wpa_supplicant\wpa_supplicant.c文件下,用于初始化wpa_supplicant。 debug

二、 调用eap_peer_register_methods()注册eap方法,EAP(Extensible Authentication Protocol)是可扩展身份验证协议的简称。代码中的解释为:This function is called at program initialization to register all EAP peer methods that were linked in statically。 
三、 经过main()函数中传入的参数初始化global结构体。

四、 调用eloop_init()将初始化好的global结构体传给eloop结构体,该结构体是一个全局变量,存储了不少event loop循环须要使用的信息。

五、 调用wpa_supplicant_global_ctrl_iface_init()函数创建global控制接口,该函数创建一个socket,而后与初始化global结构体时给出的params.ctrl.interface参数进行链接,链接成功以后注册到eloop循环中,从而创建两个进程之间的通讯。这是wpa_supplicant与外部进程创建的第一个通讯通道,主要用于增长或删除网络接口。 
六、 调用wpa_supplicant_dbus_ctrl_iface_init()函数创建dbus进程间通信接口,该函数首先经过调用dbus_bus_get()函数得到系统总线引用,而后调用integrate_with_eloop()告诉dbus 设置eloop循环相关的处理函数(好比增长删除之类,dbus的socket也是在这些处理函数中创建的),以后调用dbus_connection_register_object_path()函数为dbus接口注册消息处理函数,最后调用dbus_bus_request_name()函数将该dbus注册为消息服务bus。函数在退出以前经过调用eloop_register_timeout()函数将处理函数添加进入eloop循环,注意这个注册是采用timeout的形式,缘由多是不想太早初始化这个dbus,由于这个时候eloop尚未启动,若是过早初始化,会致使别的进程使用,会出问题。这是wpa_supplicant与外部进程创建的第二个通讯通道,主要用于处理dbus通讯。

七、 调用wpa_supplicant_daemon()函数将该守护进程的pid写入pid_file中。

3、wpa_supplicant_add_iface() 
一、该函数为wpa_supplicant增长网络接口,而且支持热插拔。 
二、调用wpa_supplicant_init_iface()函数: 

    a、调用wpa_supplicant_set_driver()函数设置驱动函数;

    b、读取配置文件信息,保存到结构体wpa_s->confname中,再分析配置参数,将分析结果保存到wpa_s->conf中; 

    c、检查命令行参数中是否设置了wpa_s->conf,若是设置,就用命令行设置的参数覆盖以上b中用配置文件设置的参数;

    d、拷贝网络接口名称和桥接口名称到wpa_s结构体。 
三、调用wpa_supplicant_init_iface2()函数: 
    a、调用wpa_supplicant_init_eapol()函数初始化eapol,该认证采用状态机的风格,在eloop循环中,设置定时器来定时更新eapol的认证状态,实现接入网络的认证;

    b、调用wpa_drv_init()函数初始化网络驱动,该函数进一步调用在上述中由wpa_supplicant_set_driver()函数加载的驱动的.init函数,因为wpa_supplicant须要和内核进行socket通讯,这个socket的创建和注册到eloop循环就在这个地方;这是wpa_supplicant与外部进程创建的第三个通讯通道,主要用于与kernel交换数据; 

    c、调用wpa_drv_get_ifname()函数得到网络接口名称; 

    d、调用wpa_supplicant_init_wpa()函数初始化wpa;

    e、调用wpa_supplicant_driver_init()函数初始化驱动接口,该函数会调用l2_packet_init()函数创建与802.1x进行报文通信的socket,并注册到eloop循环中,这是wpa_supplicant与外部进程创建的第四个通讯通道,主要用于处理802.1x报文;最后调用wpa_supplicant_req_scan()函数在指定时间以后发起scan; 

    f、调用wpa_supplicant_ctrl_iface_init()函数初始化控制接口,该函数创建与HAL层通讯的socket,并注册到eloop循环,这是wpa_supplicant与外部进程创建的第五个通讯通道,主要用于接受WIFI HAL层的控制。  
4、wpa_supplicant_run() 
一、该函数主要功能是启动eloop循环;

二、注册结束函数和从新配置函数;

三、调用eloop_run()进入循环,该循环经过select()机制,检测socket信号量并处理,并处理定时事件。

/**
 * wpa_supplicant_init - Initialize %wpa_supplicant
 * @params: Parameters for %wpa_supplicant
 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
 *
 * This function is used to initialize %wpa_supplicant. After successful
 * initialization, the returned data pointer can be used to add and remove
 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
 */
struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
{
    struct wpa_global *global;
    int ret, i;
……
#ifndef CONFIG_NO_WPA_MSG
    wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);// 注册回调函数,获取当前ifname
#endif /* CONFIG_NO_WPA_MSG */

……
    ret = eap_register_methods();// 注册eap(Extensible Authentication Protocol)方法。
    
    global = os_zalloc(sizeof(*global));
    dl_list_init(&global->p2p_srv_bonjour);
    dl_list_init(&global->p2p_srv_upnp);
    global->params.daemonize = params->daemonize;
    global->params.wait_for_monitor = params->wait_for_monitor;
    global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
    global->params.pid_file = os_strdup(params->pid_file);
    global->params.ctrl_interface = os_strdup(params->ctrl_interface);
    global->params.override_driver = os_strdup(params->override_driver);
    global->params.override_ctrl_interface = os_strdup(params->override_ctrl_interface);
    wpa_debug_level = global->params.wpa_debug_level = params->wpa_debug_level;
    wpa_debug_show_keys = global->params.wpa_debug_show_keys = params->wpa_debug_show_keys;
    wpa_debug_timestamp = global->params.wpa_debug_timestamp = params->wpa_debug_timestamp;

    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;
    }

    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;
    }
    global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
    if (global->drv_priv == NULL) {
        wpa_supplicant_deinit(global);
        return NULL;
    }

#ifdef CONFIG_WIFI_DISPLAY
    if (wifi_display_init(global) < 0) {
        wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
        wpa_supplicant_deinit(global);
        return NULL;
    }
#endif /* CONFIG_WIFI_DISPLAY */

    return global;
}
相关文章
相关标签/搜索