• 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;
    }
  • 相关阅读:
    IE浏览器cookie存放在本地什么目录
    C# clickonce 部署自定义文件
    [C#.Net]C#连接Oracle数据库的方法
    Eclipse 插件一览
    登录名 '***' 拥有一个或多个数据库。在删除该登录名之前,请更改相应数据库的所有者。 (Microsoft SQL Server,错误: 15174)
    SqlServer_表结构查询_查询当前用户所有表名
    sqlserver怎么删除有外键关联的数据?
    springboot logback控制台中文输出乱码
    控制台运行JAVA的jar文件时乱码 / Gradle编译设置编码格式
    Python 算法之一
  • 原文地址:https://www.cnblogs.com/leino11121/p/3874822.html
Copyright © 2020-2023  润新知