wpa_supplicant初始化关键函数

1. wpa_supplicant_init()

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

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

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

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

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

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

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

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

二、wpa_supplicant_init () 
1、 该函数位于externalwpa_supplicantwpa_supplicant.c文件下,用于初始化wpa_supplicant。

2、 调用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。 
3、 通过main()函数中传入的参数初始化global结构体。

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

5、 调用wpa_supplicant_global_ctrl_iface_init()函数建立global控制接口,该函数建立一个socket,然后与初始化global结构体时给出的params.ctrl.interface参数进行连接,连接成功之后注册到eloop循环中,从而建立两个进程之间的通信。这是wpa_supplicant与外部进程建立的第一个通信通道,主要用于增加或删除网络接口。 
6、 调用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通信。

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

三、wpa_supplicant_add_iface() 
1、该函数为wpa_supplicant增加网络接口,并且支持热插拔。 
2、调用wpa_supplicant_init_iface()函数: 

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

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

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

    d、拷贝网络接口名称和桥接口名称到wpa_s结构体。 
3、调用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层的控制。  
四、wpa_supplicant_run() 
1、该函数主要功能是启动eloop循环;

2、注册结束函数和重新配置函数;

3、调用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;
}
原文地址:https://www.cnblogs.com/leino11121/p/3874822.html