九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
android wpa_supplicant 流程分析

android wpa_supplicant 流程分析

370人閱讀 評論(1) 收藏 舉報

以下分析基于 wpa_supplicant 0.5.11 版本

1、wpa_supplicant簡介

    wpa_supplicant is an implementation of the WPA Supplicant component,
i.e., the part that runs in the client stations. It implements WPA key
negotiation with a WPA Authenticator and EAP authentication with
Authentication Server. In addition, it controls the roaming and IEEE
802.11 authentication/association of the wlan driver.
    wpa_supplicant is designed to be a "daemon" program that runs in the
background and acts as the backend component controlling the wireless
connection. wpa_supplicant supports separate frontend programs and an
example text-based frontend, wpa_cli, is included with wpa_supplicant.
    Following steps are used when associating with an AP using WPA:
      - wpa_supplicant requests the kernel driver to scan neighboring BSSes
      - wpa_supplicant selects a BSS based on its configuration
      - wpa_supplicant requests the kernel driver to associate with the chosen BSS
      - If WPA-EAP: integrated IEEE 802.1X Supplicant completes EAP
  authentication with the authentication server (proxied by theAuthenticator in the AP)
      - If WPA-EAP: master key is received from the IEEE 802.1X Supplicant
      - If WPA-PSK: wpa_supplicant uses PSK as the master session key
      - wpa_supplicant completes WPA 4-Way Handshake and Group Key Handshake
  with the Authenticator (AP)
      - wpa_supplicant configures encryption keys for unicast and broadcast
      - normal data packets can be transmitted and received

2、啟動命令

    You will need to make a configuration file, e.g.,
/etc/wpa_supplicant.conf, with network configuration for the networks
you are going to use. Configuration file section below includes
explanation fo the configuration file format and includes various
examples. Once the configuration is ready, you can test whether the
configuration work by first running wpa_supplicant with following
command to start it on foreground with debugging enabled:
      wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d


    Assuming everything goes fine, you can start using following command
to start wpa_supplicant on background without debugging:
      wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B


    Please note that if you included more than one driver interface in the
build time configuration (.config), you may need to specify which
interface to use by including -D<driver name> option on the command??
line. See following section for more details on command line options
for wpa_supplicant.

    Command line options
--------------------
usage:
  wpa_supplicant [-BddfhKLqqtuvwW] [-P<pid file>] [-g<global ctrl>] \
        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
        [-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
        [-p<driver_param>] [-b<br_ifname>] ...]

options:
  -b = optional bridge interface name
  -B = run daemon in the background
  -c = Configuration file
  -C = ctrl_interface parameter (only used if -c is not)
  -i = interface name
  -d = increase debugging verbosity (-dd even more)
  -D = driver name
  -f = Log output to default log location (normally /tmp)
  -g = global ctrl_interface
  -K = include keys (passwords, etc.) in debug output
  -t = include timestamp in debug messages
  -h = show this help text
  -L = show license (GPL and BSD)
  -p = driver parameters
  -P = PID file
  -q = decrease debugging verbosity (-qq even less)
  -v = show version
  -w = wait for interface to be added, if needed
  -W = wait for a control interface monitor before starting
  -N = start describing new interface

drivers:
  hostap = Host AP driver (Intersil Prism2/2.5/3) [default]
(this can also be used with Linuxant DriverLoader)
  hermes = Agere Systems Inc. driver (Hermes-I/Hermes-II)
  madwifi = MADWIFI 802.11 support (Atheros, etc.)
  atmel = ATMEL AT76C5XXx (USB, PCMCIA)
  wext = Linux wireless extensions (generic)
  ndiswrapper = Linux ndiswrapper
  broadcom = Broadcom wl.o driver
  ipw = Intel ipw2100/2200 driver (old; use wext with Linux 2.6.13 or newer)
  wired = wpa_supplicant wired Ethernet driver
  bsd = BSD 802.11 support (Atheros, etc.)
  ndis = Windows NDIS driver

In most common cases, wpa_supplicant is started with

wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -iwlan0


    This makes the process fork into background and wait for the wlan0
interface if it is not available at startup time.
    The easiest way to debug problems, and to get debug log for bug
reports, is to start wpa_supplicant on foreground with debugging
enabled:
      wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d

    wpa_supplicant can control multiple interfaces (radios) either by
running one process for each interface separately or by running just
one process and list of options at command line. Each interface is
separated with -N argument. As an example, following command would
start wpa_supplicant for two interfaces:
    wpa_supplicant \
    -c wpa1.conf -i wlan0 -D hostap -N \
    -c wpa2.conf -i ath0 -D madwifi


    If the interface is added in a Linux bridge (e.g., br0), the bridge
interface needs to be configured to wpa_supplicant in addition to the
main interface:
      wpa_supplicant -cw.conf -Dmadwifi -iath0 -bbr0

3、結(jié)構(gòu)體介紹

struct  wpa_interface      struct  wpa_params      struct  wpa_global

    struct wpa_interface - Parameters for wpa_supplicant_add_iface().

    struct wpa_global - Internal, global data for all %wpa_supplicant interfaces.
This structure is initialized by calling wpa_supplicant_init() when starting %wpa_supplicant.

    struct wpa_params - Parameters for wpa_supplicant_init().

    wpa_params主要記錄一些與網(wǎng)卡本身沒關的參數(shù)設置,而wpa_interface對應網(wǎng)絡接口,

因為wpa_supplicant支持多個網(wǎng)絡接口,所以可能有多個wpa_interface結(jié)構(gòu)體,可以通過命令行

指定不同的接口,wpa_supplicant在main函數(shù)開始的地方會進行遍歷!(參考代碼main.c)

struct wpa_global {
struct wpa_supplicant *ifaces;
struct wpa_params params;
struct ctrl_iface_global_priv *ctrl_iface;
struct ctrl_iface_dbus_priv *dbus_ctrl_iface;
};

struct wpa_supplicant - Internal data for wpa_supplicant interface.

每個網(wǎng)絡接口都有一個對應的wpa_supplicant數(shù)據(jù)結(jié)構(gòu),該指針指向最近加入的一個,在wpa_supplicant數(shù)據(jù)結(jié)構(gòu)中有指針指向next

struct ctrl_iface_global_priv - Global control interface

struct ctrl_iface_dbus_priv - DBUS control interface

4、理解main.c

在這個函數(shù)中,主要做了四件事。
    a. android平臺進程wpa_supplicant權(quán)限及結(jié)構(gòu)體初始化,解析命令行參數(shù)
    b. 調(diào)用wpa_supplicant_init()函數(shù),主要初始化struct wpa_global *global這個局部結(jié)構(gòu)體同時傳遞給static struct     eloop_data eloop這個全局結(jié)構(gòu)體并返回這個局部結(jié)構(gòu)體(詳解見下)
    c. for循環(huán)中調(diào)用wpa_supplicant_add_iface()函數(shù),注冊可能有的一個或多個網(wǎng)卡接口
    d. 調(diào)用wpa_supplicant_run()函數(shù),這其中如果失敗將會走到out或者是通過goto跳轉(zhuǎn)到out.

下面詳細介紹這四個過程:

4.1 初步初始化及解析命令行參數(shù)

    最開始調(diào)用了os_program_init函數(shù),來給wpa_supplicant進程分配權(quán)限,這里的進程一般是在init.rc中有個service,然后通過在wifi.c中的函數(shù)由UI settings設置通過jni調(diào)用下來從而會把service調(diào)用起來!跟蹤這個函數(shù)到達了os_unix.c,見到了我們熟悉的setuid函數(shù)給它設為AID_WIFI(user / group).

    然后下面初始化兩大結(jié)構(gòu)體wpa_params和wpa_interface,再然后就開始解析命令行的參數(shù)了,這里不再詳述了


4.2 wpa_supplicant_init(&params)

    我們先看下這個函數(shù)的說明:

/**
 * 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.
 */

    這個函數(shù)先分配了struct wpa_global *global這個局部指向結(jié)構(gòu)體指針的內(nèi)存空間,然后通過傳遞的params參數(shù)填充global指向的結(jié)構(gòu)體中內(nèi)嵌的struct wpa_params對象,緊接著把global這個指針傳遞給static struct eloop_data  eloop這個全局結(jié)構(gòu)體對象!

    下面分別調(diào)用global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global); /* ctrl_iface_unix.c */

    對于第一個接口的初始化,實際上通過socket進行了內(nèi)部進程間通信,如下

priv->sock = android_get_control_socket(global->params.ctrl_interface);

 /* 此處通過getenv獲得了sockfd(android平臺),相當于如果本身有了fd的話,將直接跳轉(zhuǎn)到havesock,如果沒有的話,將創(chuàng)建連接,如下所示 */

priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); /* PF_UNIX 代表內(nèi)部進程間通信 */

下面bind或者connect,錯誤基本上也是goto到fail.到這里控制接口初始化結(jié)束.

    下面初始化第二個接口dbus

global->dbus_ctrl_iface = wpa_supplicant_dbus_ctrl_iface_init(global); / *初始化dbus控制接口ctrl_iface_dbus.c */

    再下面調(diào)用wpa_supplicant_daemon(global->params.pid_file)); 再調(diào)用os_daemonize函數(shù)寫pid(os_unix.c) ,最后返回局部變量global,到此初始化過程結(jié)束了!


4.3 wpa_supplicant_add_iface(global, &ifaces[i])

    還是先看下這個函數(shù)注釋:

/**
 * wpa_supplicant_add_iface - Add a new network interface
 * @global: Pointer to global data from wpa_supplicant_init()
 * @iface: Interface configuration options
 * Returns: Pointer to the created interface or %NULL on failure
 *
 * This function is used to add new network interfaces for %wpa_supplicant.
 * This can be called before wpa_supplicant_run() to add interfaces before the
 * main event loop has been started. In addition, new interfaces can be added
 * dynamically while %wpa_supplicant is already running. This could happen,
 * e.g., when a hotplug network adapter is inserted.
 */


a.分配struct wpa_supplicant *wpa_s局部指針空間

b.init iface and iface2

wpa_supplicant_init_iface(wpa_s, iface) || wpa_supplicant_init_iface2(wpa_s, global->params.wait_for_interface)

    這兩個函數(shù)很重要,將調(diào)用到驅(qū)動,下面我們分析下這兩個函數(shù)的調(diào)用過程

 b1) wpa_supplicant_init_iface

   b1.1)wpa_supplicant_set_driver(wpa_s, iface->driver)        

    此函數(shù)很重要,調(diào)用過程如下所示

      wpa_s->driver = wpa_supplicant_drivers[i]; /* wpa_supplicant.c */

后者在drivers.c中 struct wpa_driver_ops *wpa_supplicant_drivers[ ] = { &wpa_driver_wext_ops, NULL };

ops這個結(jié)構(gòu)體對象注冊了一系列wext(我們采用wext的驅(qū)動類型)相關的函數(shù)指針,從而提供了相應的驅(qū)動接口!同時android增加了

       #ifdef ANDROID
        .driver_cmd = wpa_driver_priv_driver_cmd,
        #endif

     b1.2) 讀配置文件
    讀取配置文件,并將其中的信息設置到wpa_supplicant數(shù)據(jù)結(jié)構(gòu)中的conf 指針指向的數(shù)據(jù)結(jié)構(gòu),它是一個wpa_config類型

    命令行設置的控制接口ctrl_interface和驅(qū)動參數(shù)driver_param覆蓋配置文件里設置,命令行中的優(yōu)先;

    對 于網(wǎng)絡配置塊有兩個鏈表描述它,一個是 config->ssid,它按照配置文件中的順序依次掛載在這個鏈表上,還有一個是pssid,它是一個二級指針,指向一個指針數(shù)組,該指針數(shù)組 按照優(yōu)先級從高到底的順序依次保存wpa_ssid指針,相同優(yōu)先級的在同一鏈表中掛載。

    wpa_s->conf = wpa_config_read(wpa_s->confname);  /* 此函數(shù)在wpa_supplicant.c中,而實現(xiàn)在conf_file.c中,這里內(nèi)容比較多,沒細看 */

     b1.3) 將函數(shù)傳遞的指向結(jié)構(gòu)體wpa_interface的指針中的相關的ifname傳遞給指向wpa_supplicant結(jié)構(gòu)體的指針,調(diào)用結(jié)束.


    b2) wpa_supplicant_init_iface2

      調(diào)用wpa_supplicant_init_eapol()函數(shù)來初始化eapol;(eapol 網(wǎng)上查了下意思是:局域網(wǎng)擴展協(xié)議,請高手指點下這個是做什么用的?)
      調(diào)用相應類型的driver的init()函數(shù),我們的是wext;(即.init = wpa_driver_wext_init,在driver_wext.c)

  1. /* RSNA Supplicant Key Management - INITIALIZE */  
  2. eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);  
  3. eapol_sm_notify_portValid(wpa_s->eapol, FALSE);  
  4.   
  5. /* Initialize driver interface and register driver event handler before 
  6.  * L2 receive handler so that association events are processed before 
  7.  * EAPOL-Key packets if both become available for the same select() 
  8.  * call. */  
  9. wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);  

/* driver_ops 調(diào)用方式都和下面的類似 */

  1. static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,  
  2.  const char *ifname)  
  3. {  
  4.     if (wpa_s->driver->init) {  
  5.         return wpa_s->driver->init(wpa_s, ifname);  
  6.     }  
  7.     return NULL;  
  8. }  
      設置driver的param參數(shù);(即.set_param = wpa_driver_wext_set_param)
      調(diào)用wpa_drv_get_ifname()函數(shù)獲得網(wǎng)絡接口的名稱,對于wext類型的driver,沒有這個接口函數(shù)(忽略它);
      調(diào)用wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)函數(shù)來初始化struct wpa_sm *wpa,并做相應的初始化工作;

  1. static int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)  
  2. {  
  3. #ifndef CONFIG_NO_WPA   
  4.     struct wpa_sm_ctx *ctx;  
  5.     ctx = os_zalloc(sizeof(*ctx));  
  6.     if (ctx == NULL) {  
  7.         wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");  
  8.         return -1;  
  9.     }  
  10.   
  11.     ctx->ctx = wpa_s;  
  12.     ctx->set_state = _wpa_supplicant_set_state;  
  13.     ctx->get_state = _wpa_supplicant_get_state;  
  14.     ctx->deauthenticate = _wpa_supplicant_deauthenticate;  
  15.     ctx->disassociate = _wpa_supplicant_disassociate;  
  16.     ctx->set_key = wpa_supplicant_set_key;  
  17.     ctx->scan = wpa_supplicant_scan;  
  18.     ctx->get_ssid = _wpa_supplicant_get_ssid;  
  19.     ctx->get_bssid = wpa_supplicant_get_bssid;  
  20.     ctx->ether_send = _wpa_ether_send;  
  21.     ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;  
  22.     ctx->alloc_eapol = _wpa_alloc_eapol;  
  23.     ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;  
  24.     ctx->add_pmkid = wpa_supplicant_add_pmkid;  
  25.     ctx->remove_pmkid = wpa_supplicant_remove_pmkid;  
  26.     ctx->set_config_blob = wpa_supplicant_set_config_blob;  
  27.     ctx->get_config_blob = wpa_supplicant_get_config_blob;  
  28.     ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;  
  29.   
  30.     wpa_s->wpa = wpa_sm_init(ctx);  
  31.     if (wpa_s->wpa == NULL) {  
  32.         wpa_printf(MSG_ERROR, "Failed to initialize WPA state "  
  33.                "machine");  
  34.         return -1;  
  35.     }  
  36. #endif /* CONFIG_NO_WPA */   
  37.   
  38.     return 0;  
  39. }  

上面這些函數(shù)指針,目前還不太理解,希望高手可以補充?

      調(diào)用wpa_supplicant_driver_init()函數(shù),來初始化driver接口參數(shù),如下所示:

  1. /* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) 
  2.  * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the 
  3.  * parameter that is being set/get to; value will be read/written to 
  4.  * struct iw_param value field) */  
  5. #define IW_AUTH_WPA_VERSION     0   
  6. #define IW_AUTH_CIPHER_PAIRWISE     1   
  7. #define IW_AUTH_CIPHER_GROUP        2   
  8. #define IW_AUTH_KEY_MGMT        3   
  9. #define IW_AUTH_TKIP_COUNTERMEASURES    4   
  10. #define IW_AUTH_DROP_UNENCRYPTED    5   
  11. #define IW_AUTH_80211_AUTH_ALG      6   
  12. #define IW_AUTH_WPA_ENABLED     7   
  13. #define IW_AUTH_RX_UNENCRYPTED_EAPOL    8   
  14. #define IW_AUTH_ROAMING_CONTROL     9   
  15. #define IW_AUTH_PRIVACY_INVOKED     10  

  1. /** 
  2.  * wpa_supplicant_driver_init - Initialize driver interface parameters 
  3.  * @wpa_s: Pointer to wpa_supplicant data 
  4.  * @wait_for_interface: 0 = do not wait for the interface (reports a failure if 
  5.  * the interface is not present), 1 = wait until the interface is available 
  6.  * Returns: 0 on success, -1 on failure 
  7.  * 
  8.  * This function is called to initialize driver interface parameters. 
  9.  * wpa_drv_init() must have been called before this function to initialize the 
  10.  * driver interface. 
  11.  */  
  12. int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,  
  13.                    int wait_for_interface)  
  14. {  
  15.     static int interface_count = 0;  
  16.   
  17.     for (;;) {  
  18.         if (wpa_s->driver->send_eapol) {  
  19.             const u8 *addr = wpa_drv_get_mac_addr(wpa_s);  
  20.             if (addr)  
  21.                 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);  
  22.             break;  
  23.         }  
  24.         wpa_s->l2 = l2_packet_init(wpa_s->ifname,  
  25.                        wpa_drv_get_mac_addr(wpa_s),  
  26.                        ETH_P_EAPOL,  
  27.                        wpa_supplicant_rx_eapol, wpa_s, 0);  
  28.         if (wpa_s->l2)  
  29.             break;  
  30.         else if (!wait_for_interface)  
  31.             return -1;  
  32.         wpa_printf(MSG_DEBUG, "Waiting for interface..");  
  33.         os_sleep(5, 0);  
  34.     }  
  35.   
  36.     if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {  
  37.         wpa_printf(MSG_ERROR, "Failed to get own L2 address");  
  38.         return -1;  
  39.     }  
  40.   
  41.     wpa_printf(MSG_DEBUG, "Own MAC address: " MACSTR,  
  42.            MAC2STR(wpa_s->own_addr));  
  43.   
  44.     if (wpa_s->bridge_ifname[0]) {  
  45.         wpa_printf(MSG_DEBUG, "Receiving packets from bridge interface"  
  46.                " '%s'", wpa_s->bridge_ifname);  
  47.         wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,  
  48.                           wpa_s->own_addr,  
  49.                           ETH_P_EAPOL,  
  50.                           wpa_supplicant_rx_eapol, wpa_s,  
  51.                           0);  
  52.         if (wpa_s->l2_br == NULL) {  
  53.             wpa_printf(MSG_ERROR, "Failed to open l2_packet "  
  54.                    "connection for the bridge interface '%s'",  
  55.                    wpa_s->bridge_ifname);  
  56.             return -1;  
  57.         }  
  58.     }  
  59.   
  60.     /* Backwards compatibility call to set_wpa() handler. This is called 
  61.      * only just after init and just before deinit, so these handler can be 
  62.      * used to implement same functionality. */  
  63.     if (wpa_drv_set_wpa(wpa_s, 1) < 0) {  
  64.         struct wpa_driver_capa capa;  
  65.         if (wpa_drv_get_capa(wpa_s, &capa) < 0 ||  
  66.             !(capa.flags & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |  
  67.                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2))) {  
  68.             wpa_printf(MSG_DEBUG, "Driver does not support WPA.");  
  69.             /* Continue to allow non-WPA modes to be used. */  
  70.         } else {  
  71.             wpa_printf(MSG_ERROR, "Failed to enable WPA in the "  
  72.                 "driver.");  
  73.             return -1;  
  74.         }  
  75.     }  
  76.   
  77.     wpa_clear_keys(wpa_s, NULL);   
  1. <pre name="code" class="cpp">        // 幾個ioctl調(diào)用都是調(diào)用ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr)   
  2.         // #define SIOCSIWAUTH  0x8B32         
  3.         /* set authentication mode params */  
  4.         // 根據(jù)上面的宏通過iwr這個參數(shù)傳遞給內(nèi)核相應的get / set  
  1. </pre><pre name="code" class="cpp">  
  1.     /* Make sure that TKIP countermeasures are not left enabled (could 
  2.      * happen if wpa_supplicant is killed during countermeasures. */  
  3.     wpa_drv_set_countermeasures(wpa_s, 0);   
  4.   
  5.     wpa_drv_set_drop_unencrypted(wpa_s, 1);  
  6.   
  7.     wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;  
  8.     wpa_supplicant_req_scan(wpa_s, interface_count, 100000);  
  9.     interface_count++;  
  10.   
  11.     return 0;  
  12. }  

在該函數(shù)的最后會
      wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
      wpa_supplicant_req_scan(wpa_s, interface_count, 100000); 來主動發(fā)起scan,這個地方剛剛開始一直沒能理解清楚如何去scan,然后又是如何終止的,后來發(fā)現(xiàn)其實就是用了signal的方式來處理,下面是run scan的過程,代碼封裝的相當好,真正的執(zhí)行是在最后一個wpa_supplicant_run函數(shù)!

  1. /** 
  2.  * wpa_supplicant_req_scan - Schedule a scan for neighboring access points 
  3.  * @wpa_s: Pointer to wpa_supplicant data 
  4.  * @sec: Number of seconds after which to scan 
  5.  * @usec: Number of microseconds after which to scan 
  6.  * 
  7.  * This function is used to schedule a scan for neighboring access points after 
  8.  * the specified time. 
  9.  */  
  10. void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)  
  11. {  
  12.     wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",  
  13.         sec, usec);  
  14.     eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);  
  15.     eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);  
  16. }  

  1. /* check if some registered timeouts have occurred */  
  2. if (eloop.timeout) {  
  3.     struct eloop_timeout *tmp;  
  4.   
  5.     os_get_time(&now);  
  6.     if (!os_time_before(&now, &eloop.timeout->time)) {  
  7.         tmp = eloop.timeout;  
  8.         eloop.timeout = eloop.timeout->next;  
  9.         tmp->handler(tmp->eloop_data,  
  10.                  tmp->user_data);  
  11.         os_free(tmp);  
  12.     }  
  13.   
  14. }  

這樣這個wpa_supplicant_driver_init(wpa_s, wait_for_interface)函數(shù)就說完了!

 下面再調(diào)用wpa_supplicant_ctrl_iface_init()函數(shù),來初始化控制接口;對于UNIX SOCKET這種方式,其本地socket文件是由配置文件里的     ctrl_interface參數(shù)指定的路徑加上網(wǎng)絡接口名稱;

  1. wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);  
  2.   
  3. wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);  
  4. if (wpa_s->ctrl_iface == NULL) {  
  5.     wpa_printf(MSG_ERROR,  
  6.            "Failed to initialize control interface '%s'.\n"  
  7.            "You may have another wpa_supplicant process "  
  8.            "already running or the file was\n"  
  9.            "left by an unclean termination of wpa_supplicant "  
  10.            "in which case you will need\n"  
  11.            "to manually remove this file before starting "  
  12.            "wpa_supplicant again.\n",  
  13.            wpa_s->conf->ctrl_interface);  
  14.     return -1;  
  15. }  

這個函數(shù)的錯誤信息,我調(diào)試中有遇到過,確實是有多個進程的時候會報。

這樣就講完了這個牛逼函數(shù),下面就是注冊dbus,不再詳解了,看代碼:

  1. wpa_s->global = global;  
  2.   
  3. /* Register the interface with the dbus control interface */  
  4. if (wpas_dbus_register_iface(wpa_s)) {  
  5.     wpa_supplicant_deinit_iface(wpa_s);  
  6.     os_free(wpa_s);  
  7.     return NULL;  
  8. }  
  1. #ifdef ANDROID   
  2.     char scan_prop[PROPERTY_VALUE_MAX];  
  3.     char *endp;  
  4.     if (property_get("wifi.supplicant_scan_interval", scan_prop, "5") != 0) {  
  5.         wpa_s->scan_interval = (int)strtol(scan_prop, &endp, 0);  
  6.         if (endp == scan_prop) {  
  7.             wpa_s->scan_interval = 5;  
  8.         }  
  9.     }  
  10. #endif   
  11.     wpa_s->next = global->ifaces;  
  12.     global->ifaces = wpa_s;  
  13.   
  14.     wpa_printf(MSG_DEBUG, "Added interface %s", wpa_s->ifname);  
  15.   
  16.     return wpa_s;  
再下面就是把結(jié)果該傳遞的傳遞,該返回的返回,最后return,下面就到wpa_supplicant_run函數(shù)了!


4.4 wpa_supplicant_run()函數(shù)

初始化完成之后,讓wpa_supplicant的main event loop run起來。
在 wpa_supplicant中,有許多與外界通信的socket,它們都是需要注冊到eloop event模塊中的,具體地說,就是在eloop_sock_table中增加一項記錄,其中包括了sock_fd, handle, eloop_data, user_data。
eloop event模塊就是將這些socket組織起來,統(tǒng)一管理,然后在eloop_run中利用select機制來管理socket的通信。

  1. /** 
  2.  * wpa_supplicant_run - Run the %wpa_supplicant main event loop 
  3.  * @global: Pointer to global data from wpa_supplicant_init() 
  4.  * Returns: 0 after successful event loop run, -1 on failure 
  5.  * 
  6.  * This function starts the main event loop and continues running as long as 
  7.  * there are any remaining events. In most cases, this function is running as 
  8.  * long as the %wpa_supplicant process in still in use. 
  9.  */  
  10. int wpa_supplicant_run(struct wpa_global *global)  
  11. {  
  12.     struct wpa_supplicant *wpa_s;  
  13.   
  14.     if (!global->params.wait_for_interface && global->params.daemonize &&  
  15.         wpa_supplicant_daemon(global->params.pid_file))  
  16.         return -1;  
  17.   
  18.     if (global->params.wait_for_monitor) {  
  19.         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)  
  20.             if (wpa_s->ctrl_iface)  
  21.                 wpa_supplicant_ctrl_iface_wait(  
  22.                     wpa_s->ctrl_iface);  
  23.     }  
  24.   
  25.     eloop_register_signal_terminate(wpa_supplicant_terminate, NULL);  
  26.     eloop_register_signal_reconfig(wpa_supplicant_reconfig, NULL);  
  27.   
  28.     eloop_run();  
  29.   
  30.     return 0;  
  31. }  

這個地方的真正執(zhí)行過程還沒理解清楚,只能以后有時間再理解了!



wpa_supplicant 的對外接口分析

對于wpa_supplicant模塊的對外接口,主要有以下幾種:
5.1. global control interface: 用于配置(增加或刪除)網(wǎng)絡接口。
5.2. ctrl interface: 與其他外部模塊交互的控制接口。
例 如,在初始化時,android 平臺的wifi.c中的 wifi_connect_to_supplicant函數(shù)調(diào)用wpa_ctrl_open函數(shù)創(chuàng)建兩個socket,一個是ctrl interface,另一個就是monitor interface,monitor interface這個接口用于監(jiān)測從wpa_supplicant發(fā)出的event事件。
這兩個socket創(chuàng)建成功后,monitor interface 會發(fā)送ATTACH到wpa_supplicant模塊,wpa_supplicant模塊收到后,會將該客戶端的socket信息記錄下來,用于以后發(fā)送事件時用(由于用的是DGRAM的方式)。
5.3. socket for ioctl: 發(fā)送命令到kernel space。
5.4. socket (netlink) for interact between kernel and userspace(AF_NETLINK, NETLINK_ROUTE): 接受kernel發(fā)送上來的event。
5.5. socket for l2 packet(PF_PACKET): 處理802.1x報文。

本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
wpa_supplicant 初始化流程分析
Raspberry Pi樹莓派無線網(wǎng)卡配置[多重方法備選]
hotplug應用實例:自動連接無線網(wǎng)
Linux usb子系統(tǒng)(一):子系統(tǒng)架構(gòu)
linux usb初始化
Linux動態(tài)頻率調(diào)節(jié)系統(tǒng)CPUFreq之二:核心(core)架構(gòu)與API【轉(zhuǎn)】
更多類似文章 >>
生活服務
熱點新聞
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服