Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android wpa_supplcant 啟動之--網絡接口初始化

Android wpa_supplcant 啟動之--網絡接口初始化

編輯:關於Android編程

wpa_supplicant結構體與網絡接口

在手機adb中運行 netcfg或者ifconfig可以看到相關的網絡接口的ip,掩碼,mac地址等信息

這裡寫圖片描述
Wpa_supplicant為每個網絡接口都分配了一個struct wpa_supplicant, 該結構體存儲了一些必要信息例如 struct dl_list bss(掃描結果); struct wpa_config *conf(配置文件)等等。
每一個網絡接口的掃描,連接等操作都是通過struct wpa_supplicant中定義的相關函數和數據來實現的。下面是結構體中一些重要的元素介紹

struct wpa_supplicant{
    //接口的名字和mac地址
    unsigned char own_addr[ETH_ALEN];
    char ifname[100];

    /**************************************/    

    //外部控制wpa_s的socket
    struct ctrl_iface_priv *ctrl_iface;

    //網絡接口當前的狀態,斷開/關聯/連接的bssid ssid等
    enum wpa_states wpa_state;
    u8 bssid[ETH_ALEN];
    u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this
                     * field contains the target BSSID. */
    int reassociate; /* reassociation requested */
    int disconnected; /* all connections disabled; i.e., do no reassociate
               * before this has been cleared */
    struct wpa_ssid *current_ssid;
    struct wpa_bss *current_bss;
    int ap_ies_from_associnfo;
    unsigned int assoc_freq;

    //是否支持2.4G/5G
    enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband;

    /**************************************/

    //配置文件
    struct wpa_config *conf;
    //配置文件中的ESS網絡的信息
    /* Selected configuration (based on Beacon/ProbeResp WPA IE) */
    int pairwise_cipher;
    int group_cipher;
    int key_mgmt;
    int wpa_proto;
    int mgmt_group_cipher;

    /**************************************/

    //掃描結果的處理,每次掃描後的結果都會做相應的更新
    void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
                 struct wpa_scan_results *scan_res);
    struct dl_list bss; /* struct wpa_bss::list */
    struct dl_list bss_id; /* struct wpa_bss::list_id */
    size_t num_bss;
    unsigned int bss_update_idx;
    unsigned int bss_next_id;
    //黑名單
    struct wpa_blacklist *blacklist;

    /**************************************/

    //底層相關,驅動的操作函數
    struct wpa_driver_ops *driver;
    int interface_removed; /* whether the network interface has been removed */
    void *drv_priv; /* private data used by driver_ops */
    void *global_drv_priv;

    //用來處理密鑰相關netlink socket和處理方法
    struct l2_packet_data *l2;
    struct l2_packet_data *l2_br;

    /**************************************/

    //掃描相關的一些信息
    struct wpa_radio_work *scan_work;
    int scanning;
    int sched_scanning;
    struct os_reltime scan_trigger_time, scan_start_time;
    int scan_runs; /* number of scan runs since WPS was started */
    int *next_scan_freqs;
    int scan_interval; /* time in sec between scans to find suitable AP */
    int normal_scans; /* normal scans run before sched_scan */
    int scan_for_connection; /* whether the scan request was triggered for
                  * finding a connection */

    //sched_scan
    struct wpa_ssid *prev_sched_ssid; /* last SSID used in sched scan */
    int sched_scan_timeout;
    int sched_scan_interval;
    int first_sched_scan;
    int sched_scan_timed_out;

    //pno掃描
    int pno;
    int pno_sched_pending;
}
初始化網絡接口配置

在wpa_s的main()函數中,進行完全局初始化後,會調用 wpa_supplicant_add_iface(),為wpa_s運行時傳入的每個網絡接口分配wpa_supplicant結構體,並進行相應的初始化

struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
                         struct wpa_interface *iface)
{
    struct wpa_supplicant *wpa_s = wpa_supplicant_alloc();
    wpa_s->global = global;

    //網絡接口的初始化,與底層通信的socket,密鑰數據包的socket,wpa_s的初始狀態等 
    if (wpa_supplicant_init_iface(wpa_s, &t_iface)) 
    {


        //讀取兩個conf配置文件
        //wpa_s允許提供兩個配置文件,一個是原始的一個overlay,在overlay中的文件可以重新一些參數的值
        wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
        wpa_config_read(wpa_s->confanother, wpa_s->conf);

        //初始化驅動接口,並注冊接收驅動event的函數 nl80211
        if (wpas_init_driver(wpa_s, iface) < 0)
        {
            //根據傳進來的-inl80211選定對應的wpa_driver_ops(driver_nl80211.c),裡面定義了驅動的操作方法,同時調用對應的global_init()進行初始化
            if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
            ...
列表內容

驅動初始化
下一步是初始化相關驅動的操作參數和與驅動通信的socket
wpa_supplicant支持多種架構的驅動,Android中多使用的是nl80211架構,相關操作函數在文件drivers_ml80211.c中

//根據名稱選擇網絡ops,創建於driver通信的socket
select_driver(wpa_s, i)
{
    //調用對應的global_init(),void * nl80211_global_init(void)
    global->drv_priv[i] = wpa_drivers[i]->global_init();
    {
        //初始化netlink socket,設置兩個消息處理函數,netlink_receive中使用
        cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
        cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
        //創建一個接收kernel中 route 子系統的消息socket
        global->netlink = netlink_init(cfg);
        {
            //*****該socket用於接收 kernel中
            netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
            bind(netlink->sock, (struct sockaddr *) &local, sizeof(local));
            //注冊內核消息接收函數, 根據接收到的消息type選擇以下兩個處理函數
            eloop_register_read_sock(netlink->sock, netlink_receive, netlink, NULL);
            static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx)
            {
                char buf[8192]; //接收消息的字節數, 
                left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen);
                //buf中是一個netlink消息,符合netlink規范,根據消息type選在相應的處理函數 newlink 和 dellink          
            }
        }

        //創建 global結構體中的 nl_cb(接收消息處理)和nl(發送消息)
        if (wpa_driver_nl80211_init_nl_global(global) < 0)
        {
            //創建連接到 GENERIC_NETLINK 的socket
            global->nl = nl_create_handle(global->nl_cb, "nl");
            //將nl連接到 內核中的nl80211模塊
            global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");

            //創建接收消息的event socket, 並分別加入到組播組scan mlme regulatory vendor 中
            global->nl_event = nl_create_handle(global->nl_cb, "event");
            ret = nl_get_multicast_id(global, "nl80211", "scan");
            ret = nl_socket_add_membership(global->nl_event, ret);

            //設置nl_cb的回調函數 process_global_event(), 該函數又會調用 wpa_supplicant_event() 做進一步處理
            nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_global_event, global);
            //為nl_event注冊接收函數, 通過nl_recvmsgs()調用 process_global_event()
            nl80211_register_eloop_read(&global->nl_event, wpa_driver_nl80211_event_receive, global->nl_cb);
        }

        //創建一個 ioctl_sock, 還不知道干啥用,該sock用於通過ioctl方式向底層發送命令
        global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
    }
}
網絡接口初始配置

例如up對應的接口

//調用對應的初始化函數wpa_driver_nl80211_drv_init(),傳入的ifname名稱為 wlan0
wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, void *global_priv, int hostapd, const u8 *set_addr)
{
    //挺重要的一個結構體
    struct wpa_driver_nl80211_data *drv;

    //添加了回調函數drv->nl_cb process_drv_event(),最終會調用 wpa_supplicant_event()
    if (wpa_driver_nl80211_init_nl(drv))
    //添加bss回調函數bss->nl_cb,看著沒啥用,最終處理 wpa_supplicant_event(),這兩個回調函數沒有和socket綁定,目前不清楚調用地方
    if (nl80211_init_bss(bss))

    //RF射頻省電相關,讀取節點“/dev/rfkill”只是接受消息打印log,不做任何操作
    rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
    rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
    drv->rfkill = rfkill_init(rcfg);

    //檢查當前接口是否為UP狀態
    linux_iface_up(drv->global->ioctl_sock, ifname)

    //主要為操作網卡wlan0
    wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1)
    {
        //得知網卡地址和設置網口為UP
        if (set_addr && (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) || linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, set_addr)))
        //獲取網口能力,具體能力請查閱struct wpa_driver_capa
        if (wpa_driver_nl80211_capa(drv))
        //設置網口信息 IF_OPER_DORMANT
        netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 1, IF_OPER_DORMANT);
        //獲取網口地址
        if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, bss->addr))
    }

    //創建一個socket,並注冊接收函數wpa_driver_nl80211_handle_eapol_tx_status
    drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
    eloop_register_read_sock(drv->eapol_tx_sock, wpa_driver_nl80211_handle_eapol_tx_status, drv, NULL);
}

5 密鑰處理數據包收發socekt
由netlink創建

//初始化驅動,主要完成了l2_paket回掉函數的初始化,與4次握手相關
if (wpa_supplicant_driver_init(wpa_s) < 0)
{
    //主要函數,該函數會初始化l2_packet,並注冊回掉函數,與4次握手相關
    if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
    {
        //wpa_supplicant_rx_eapol()就是4次握手的處理函數了
        wpa_s->l2 = l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_EAPOL,  wpa_supplicant_rx_eapol, wpa_s, 0);
        {
            //新建socket 
            struct l2_packet_data *l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, htons(protocol));
            //bind
            if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0)
            //將socket與回掉函數l2_packet_receive相關聯,內部實際會調用 wpa_supplicant_rx_eapol()
            eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
            {   
                //相關步驟請看eloop_data結構體,所有的回掉函數和回掉所用的數據都在保存在該結構體中
                res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll, &fromlen);
                l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
            }
        }
    }
}
wap_cli控制socket

在linux中可以通過wpa_supplicant提供的wpa_cli工具控制wpa_supplicant,在android中也可以通過wpa_cli在沒有framework的情況下實現掃描連接工作
下述代碼就是創建需要的socket和接收發送函數。
在android手機中打開wifi後再 /data/misc/wifi/sockets下的wlan0 和p2p0 就是該段代碼生成的

wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
{
    //分配空間,然後執行真正的初始化工作
    struct ctrl_iface_priv *priv;
    if (wpas_ctrl_iface_open_sock(wpa_s, priv) < 0)
    {
        //android上運行不會執行以下兩行代碼
        //os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", wpa_s->conf->ctrl_interface);
        //priv->sock = android_get_control_socket(addr.sun_path);

        //新建sock
        priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
        //bind,地址為,/data/misc/wifi/sockets/wlan0,這個地址是新生成的                
        bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr))
        //注冊接收socket的函數wpa_supplicant_ctrl_iface_receive, 其核心調用函數是 wpa_supplicant_ctrl_iface_process
        eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv);
        //向socket上傳event的函數
        wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
    }
}

通過wpa_cli工具使用連接網絡的步驟:

添加接口過程中的全部代碼
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
                         struct wpa_interface *iface)
{
    struct wpa_supplicant *wpa_s;
    struct wpa_interface t_iface;
    struct wpa_ssid *ssid;


    struct wpa_supplicant *wpa_s = wpa_supplicant_alloc();
    wpa_s->global = global;

    //網絡接口的初始化,與底層通信的socket,密鑰數據包的socket,wpa_s的初始狀態等 
    if (wpa_supplicant_init_iface(wpa_s, &t_iface)) 
    {
        //讀取兩個conf配置文件
        wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
        wpa_config_read(wpa_s->confanother, wpa_s->conf);

        //初始化驅動接口,並注冊接收驅動event的函數 nl80211
        if (wpas_init_driver(wpa_s, iface) < 0)
        {
            //根據傳進來的-inl80211選定對應的wpa_driver_ops(driver_nl80211.c),裡面定義了驅動的操作方法(),同時調用對應的global_init()進行初始化
            if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
            {
                //根據名稱選擇網絡ops
                select_driver(wpa_s, i)
                {
                    //調用對應的global_init(),void * nl80211_global_init(void)
                    global->drv_priv[i] = wpa_drivers[i]->global_init();
                    {
                        //初始化netlink socket,設置兩個消息處理函數,netlink_receive中使用
                        cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
                        cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
                        //創建一個接收kernel中 route 子系統的消息socket
                        global->netlink = netlink_init(cfg);
                        {
                            //*****該socket用於接收 kernel中
                            netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
                            bind(netlink->sock, (struct sockaddr *) &local, sizeof(local));
                            //注冊內核消息接收函數, 根據接收到的消息type選擇以下兩個處理函數
                            eloop_register_read_sock(netlink->sock, netlink_receive, netlink, NULL);
                            static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx)
                            {
                                char buf[8192]; //接收消息的字節數, 
                                left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen);
                                //buf中是一個netlink消息,符合netlink規范,根據消息type選在相應的處理函數 newlink 和 dellink          
                            }
                        }

                        //創建 global結構體中的 nl_cb(接收消息處理)和nl(發送消息)
                        if (wpa_driver_nl80211_init_nl_global(global) < 0)
                        {
                            //創建連接到 GENERIC_NETLINK 的socket
                            global->nl = nl_create_handle(global->nl_cb, "nl");
                            //將nl連接到 內核中的nl80211模塊
                            global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");

                            //創建接收消息的event socket, 並分別加入到組播組scan mlme regulatory vendor 中
                            global->nl_event = nl_create_handle(global->nl_cb, "event");
                            ret = nl_get_multicast_id(global, "nl80211", "scan");
                            ret = nl_socket_add_membership(global->nl_event, ret);

                            //設置nl_cb的回調函數 process_global_event(), 該函數又會調用 wpa_supplicant_event() 做進一步處理
                            nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_global_event, global);
                            //為nl_event注冊接收函數, 通過nl_recvmsgs()調用 process_global_event()
                            nl80211_register_eloop_read(&global->nl_event, wpa_driver_nl80211_event_receive, global->nl_cb);
                        }

                        //創建一個 ioctl_sock, 還不知道干啥用,該sock用於通過ioctl方式向底層發送命令
                        global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
                    }
                }               
            }

            //調用對應的初始化函數wpa_driver_nl80211_drv_init(),傳入的ifname名稱為 wlan0
            wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
                static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, void *global_priv, int hostapd, const u8 *set_addr)
                {
                    //挺重要的一個結構體
                    struct wpa_driver_nl80211_data *drv;

                    //添加了回調函數drv->nl_cb process_drv_event(),最終會調用 wpa_supplicant_event()
                    if (wpa_driver_nl80211_init_nl(drv))
                    //添加bss回調函數bss->nl_cb,看著沒啥用,最終處理 wpa_supplicant_event(),這兩個回調函數沒有和socket綁定,目前不清楚調用地方
                    if (nl80211_init_bss(bss))

                    //RF射頻省電相關,讀取節點“/dev/rfkill”只是接受消息打印log,不做任何操作
                    rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
                    rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
                    drv->rfkill = rfkill_init(rcfg);

                    //檢查當前接口是否為UP狀態
                    linux_iface_up(drv->global->ioctl_sock, ifname)

                    //主要為操作網卡wlan0
                    wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1)
                    {
                        //得知網卡地址和設置網口為UP
                        if (set_addr && (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) || linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, set_addr)))
                        //獲取網口能力,具體能力請查閱struct wpa_driver_capa
                        if (wpa_driver_nl80211_capa(drv))
                        //設置網口信息 IF_OPER_DORMANT
                        netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 1, IF_OPER_DORMANT);
                        //獲取網口地址
                        if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, bss->addr))
                    }

                    。。創建一個socket,並注冊接收函數wpa_driver_nl80211_handle_eapol_tx_status
                    drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
                    eloop_register_read_sock(drv->eapol_tx_sock, wpa_driver_nl80211_handle_eapol_tx_status, drv, NULL);
                }


        }

        //初始化wpa_s,主要設置 wpa 狀態機
        if (wpa_supplicant_init_wpa(wpa_s) < 0)
        {
            //設置一些操作函數,請查看結構體 struct wpa_sm_ctx
            。。。
            //
            struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
            {
                //主要是3個變量值
                sm->dot11RSNAConfigPMKLifetime = 43200; //PMK的生存時間(秒)(12小時),超時後要重新計算
                sm->dot11RSNAConfigPMKReauthThreshold = 70;  //PMK超時多少(70%)後,需要重新身份認證
                sm->dot11RSNAConfigSATimeout = 60;      //進行身份驗證的最長時間(秒)
            }
        }

        //初始化驅動,主要完成了l2_paket回掉函數的初始化,與4次握手相關
        if (wpa_supplicant_driver_init(wpa_s) < 0)
        {
            //主要函數,該函數會初始化l2_packet,並注冊回掉函數,與4次握手相關
            if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
            {
                //wpa_supplicant_rx_eapol()就是4次握手的處理函數了
                wpa_s->l2 = l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_EAPOL,  wpa_supplicant_rx_eapol, wpa_s, 0);
                {
                    //新建socket 
                    struct l2_packet_data *l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, htons(protocol));
                    //bind
                    if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0)
                    //將socket與回掉函數l2_packet_receive相關聯,內部實際會調用 wpa_supplicant_rx_eapol()
                    eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
                    {   
                        //相關步驟請看eloop_data結構體,所有的回掉函數和回掉所用的數據都在保存在該結構體中
                        res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll, &fromlen);
                        l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
                    }
                }
            }
        }

        //設置國家碼到驅動中
        wpa_drv_set_country(wpa_s, wpa_s->conf->country))

        //wpa_s中的 struct wps_context *wps 節點
        if (wpas_wps_init(wpa_s))
        {
            //wps_context *wps中定義了一些方法,具體請查看注釋,沒什麼邏輯處理的問題
        }

        //初始化 EAPOOL,參考eapol模塊信息
        wpa_supplicant_init_eapol(wpa_s)
        {
            //設置一些方法
            。。。
            ctx->eapol_send = wpa_supplicant_eapol_send;
            。。。
            //初始化eapol狀態機
            wpa_s->eapol = eapol_sm_init(ctx);
        }


        //初始化與FWKS的通信的socket???
        wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
        {
            //分配空間,然後執行真正的初始化工作
            struct ctrl_iface_priv *priv;
            if (wpas_ctrl_iface_open_sock(wpa_s, priv) < 0)
            {
                //參數通過啟動參數傳入wlan0的名稱,然後獲取init.rc中wpa_wlan0的socket
                //android上運行不會執行以下兩行代碼
                //os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", wpa_s->conf->ctrl_interface);
                //priv->sock = android_get_control_socket(addr.sun_path);

                //新建sock
                priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
                //bind,地址為,/data/misc/wifi/sockets/wlan0,這個地址是新生成的                
                bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr))
                //注冊接收socket 命令的函數wpa_supplicant_ctrl_iface_receive, 其核心調用函數是 wpa_supplicant_ctrl_iface_process
                eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv);
                //向socket上傳event的函數
                wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
            }
        }

        //初始化bss相關,主要是wpa_s中的兩個鏈表
        if (wpa_bss_init(wpa_s) < 0)
        {
            //初始化wpa_s中bss和bssid鏈表
            dl_list_init(&wpa_s->bss);
            dl_list_init(&wpa_s->bss_id);
            //注冊超時函數 ,每隔10秒刷新下bss,去掉無用的bss
            eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD=10, wpa_bss_timeout, wpa_s, NULL);
        }

        //sim卡 sd卡相關
        if (pcsc_reader_init(wpa_s) < 0)

        //不知道做什麼用的
        if (wpas_init_ext_pw(wpa_s) < 0)            
    }

    /* Notify the control interfaces about new iface */
    if (wpas_notify_iface_added(wpa_s)) {
        wpa_supplicant_deinit_iface(wpa_s, 1, 0);
        return NULL;
    }

    for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
        wpas_notify_network_added(wpa_s, ssid);

    //設置wpas狀態
    wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
    return wpa_s;
}
流程圖

其中虛線表示數據的傳遞,深棕色部分表示創建的socket以及收發函數
添加接口流程圖

下一篇為wpa_supplicant中的兩個重要的結構體bss和conf
bss中保存著掃描結果, conf中為wpa_s的參數和保存的網絡

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved