zoukankan      html  css  js  c++  java
  • Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续

    下面我们将接上一篇文章继续分析main中第二个关键函数wpa_supplicant_add_iface。

    wpa_supplicant_add_iface用于向wpa_supplicant添加接口设备。所谓的添加(add iface),其实就是初始化这些设备。

    [wpa_supplicant.c::wpa_supplicant_add_iface]

    1. struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,  
    2.                          struct wpa_interface *iface)  
    3. {  
    4.     struct wpa_supplicant *wpa_s;  
    5.     struct wpa_interface t_iface;  
    6.     struct wpa_ssid *ssid;  
    7.   
    8.     if (global == NULL || iface == NULL)  
    9.         return NULL;  
    10.   
    11.     wpa_s = wpa_supplicant_alloc();  
    12.     if (wpa_s == NULL)  
    13.         return NULL;  
    14.   
    15.     wpa_s->global = global;  
    16.   
    17.     t_iface = *iface;  
    18.     if (global->params.override_driver) {  
    19.         wpa_printf(MSG_DEBUG, "Override interface parameter: driver "  
    20.                "('%s' -> '%s')",  
    21.                iface->driver, global->params.override_driver);  
    22.         t_iface.driver = global->params.override_driver;  
    23.     }  
    24.     if (global->params.override_ctrl_interface) {  
    25.         wpa_printf(MSG_DEBUG, "Override interface parameter: "  
    26.                "ctrl_interface ('%s' -> '%s')",  
    27.                iface->ctrl_interface,  
    28.                global->params.override_ctrl_interface);  
    29.         t_iface.ctrl_interface =  
    30.             global->params.override_ctrl_interface;  
    31.     }  
    32.     if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {  
    33.         wpa_printf(MSG_DEBUG, "Failed to add interface %s",  
    34.                iface->ifname);  
    35.         wpa_supplicant_deinit_iface(wpa_s, 0, 0);  
    36.         return NULL;  
    37.     }  
    38.   
    39.     /* Notify the control interfaces about new iface */  
    40.     if (wpas_notify_iface_added(wpa_s)) {  
    41.         wpa_supplicant_deinit_iface(wpa_s, 1, 0);  
    42.         return NULL;  
    43.     }  
    44.   
    45.     for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)  
    46.         wpas_notify_network_added(wpa_s, ssid);  
    47.   
    48.     wpa_s->next = global->ifaces;  
    49.     global->ifaces = wpa_s;  
    50.   
    51.     wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);  
    52.     wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);  
    53.   
    54.     return wpa_s;  
    55. }  

    wpa_supplicant_add_iface的内容非常丰富,包括两个重要数据结构(wpa_supplicant和wpa_ssid)以及一个关键函数wpa_supplicant_init_iface.

    1、wpa_ssid结构体

    wpa_ssid用于存储某个无线网络的配置信息(如所支持的安全类型、优先级等)它其实是wpa_supplicant.conf中无线网络配置项在代码中的反映(conf文件中每一个network项都对应一个wpa_ssid对象)。它的一些主要数据成员如下所示:

    struct wpa_ssid
    +next:struct wpa_ssid*  //所有wpa_ssid对象都保存在一个链表中,头指针保存于另外一个结构体wpa_config的变量中
    +pnext:struct wpa_ssid*  //wpa_ssid还可按priority保存在另一个链表中,头指针为wpa_config的pssid变量
    +id:int  //每一个无线网络都有一个唯一的编号
    +priority:int  //该无线对应的priority值,默认为0
    +ssid:8*:此无线网络的ssid(即无线网络名)
    +ssid_len:size_t  //ssid变量的长度
    +bssid:u8数组  //用于保存bssid,数组长度为ETH_ALEN(值为6)
    +bssid_set:  //该无线网络是否设置了bssid变量
    +psk:u8数组  //数组长度为32,用于保存WPA中的Pre-Shared Key
    +psk_set: int  //是否设置了商数的psk参数
    +passphrase:char*  //为WPA设置了ASCII字符密码。
    +pairwise_cipher:int  //用于单播数据加密的密钥对类型
    +group_cipher: int  //用于组播数据加密的密钥对类型
    +key_mgmt:int   //密钥管理类型
    +proto:int  //该无线网络支持的安全保护类型
    +auth_alg:int  //该无线网络支持的身份验证类型
    +scan_ssid:int  //是否利用probe request帧扫描此ssid对应的无线网络
    +eapol_flags:int //EAPOL选项
    +eap:struct eap_peer_config  //eap peer端设置信息
    +proactive_key_caching:int  //
    +mode:enum wpas_mode  //
    +disabled:int  //
    wpa_ssid定义的wpas_mode枚举变量
    enum wpas_mode{
    WPAS_MODE_INFRA = 0,//代表基础结构网络的STA
    WPAS_MODE_IBSS = 1,//代表IBSS网络的模式
    WPAS_MODE_AP = 2,代表基础结构网络中的AP
    WPAS_MODE_P2P_GO = 3,//P2P相关
    WPAS_MODE_GROUP_FORMATION = 4,
    }mode;





















    上表格中一些数据成员非常重要,下面分别介绍:

    (1)安全相关成员变量

    1)passphrase:该变量只和WPA/WPA2-PSK模式有关,用于存储我们输入的字符串密码。

    2)pairwise_cipher和group_cipher:这两个变量和规范中的cipher suite定义有关。

    1. #define WPA_CIPHER_NONE BIT(0)<span style="white-space:pre">      </span>//不保护  
    2. #define WPA_CIPHER_WEP40 BIT(1)<span style="white-space:pre">     </span>//WEP40  
    3. #define WPA_CIPHER_WEP104 BIT(2)<span style="white-space:pre">    </span>//WEP104  
    4. #define WPA_CIPHER_TKIP BIT(3)<span style="white-space:pre">      </span>//TKIP  
    5. #define WPA_CIPHER_CCMP BIT(4)<span style="white-space:pre">      </span>//CCMP  
    1. #define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP)  
    2. #define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP |   
    3.                WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)  

    3)key_mgmt:该成员和802.11中的AKM(Authentication and Key Managment,身份验证和密钥管理)suite相关。

    1. #define WPA_KEY_MGMT_IEEE8021X BIT(0)  
    2. #define WPA_KEY_MGMT_PSK BIT(1)  
    3. #define WPA_KEY_MGMT_NONE BIT(2)  
    4. #define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)  
    5. #define WPA_KEY_MGMT_WPA_NONE BIT(4)  
    6. #define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)  
    7. #define WPA_KEY_MGMT_FT_PSK BIT(6)  
    8. #define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)  
    9. #define WPA_KEY_MGMT_PSK_SHA256 BIT(8)  
    10. #define WPA_KEY_MGMT_WPS BIT(9)  
    11. #define WPA_KEY_MGMT_SAE BIT(10)  
    12. #define WPA_KEY_MGMT_FT_SAE BIT(11)  
    13. #define WPA_KEY_MGMT_WAPI_PSK BIT(12)  
    14. #define WPA_KEY_MGMT_WAPI_CERT BIT(13)  
    15. #define WPA_KEY_MGMT_CCKM BIT(14)  
    1. #define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X)  

    4)proto:代表该无线网络支持的安全协议类型。

    1. #define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN)  
    1. #define WPA_PROTO_WPA BIT(0)  
    2. #define WPA_PROTO_RSN BIT(1)  
    3. #define WPA_PROTO_WAPI BIT(2)  

    5)auth_alg:表示该无线网络所支持的身份验证算法。其可取值如下:

    1. #define WPA_AUTH_ALG_OPEN BIT(0)<span style="white-space:pre">        </span>//open system,如果要使用WPA或RSN,必须选择它  
    2. #define WPA_AUTH_ALG_SHARED BIT(1)<span style="white-space:pre">      </span>//Shard Key算法  
    3. #define WPA_AUTH_ALG_LEAP BIT(2)<span style="white-space:pre">        </span>//LEAP算法,LEAP是思科公司提出的身份验证算法  
    4. #define WPA_AUTH_ALG_FT BIT(3)<span style="white-space:pre">          </span>//和FT有关  
    5. #define WPA_AUTH_ALG_SAE BIT(4)  

    6)eapol_flags:和动态WEP Key有关

    1. #define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0)  
    2. #define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1)  

    (2)其他成员变量

    1)proactive_key_caching:该变量和OPC(Opportunistic PMK Caching)技术相关。

    2)disable:该变量取值为0(代表该无线网络可用)、1(代表该无线网络被禁止使用,但可通过命令来启用它)、2(表示该无线网络和P2P有关)

    3)mode:wpa_ssid结构体内部还定义了一个枚举型变量
    2、wpa_supplicant结构体

    wpa_supplicant结构体定义的成员变量非常多。详细请参考wpa_supplicant_i.h文件。


    wpa_supplicant_init_iface函数分析

    1. static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,  
    2.                      struct wpa_interface *iface)  
    3. {  
    4.     const char *ifname, *driver;  
    5.     struct wpa_driver_capa capa;  
    6.   
    7.     wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "  
    8.            "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,  
    9.            iface->confname ? iface->confname : "N/A",  
    10.            iface->driver ? iface->driver : "default",  
    11.            iface->ctrl_interface ? iface->ctrl_interface : "N/A",  
    12.            iface->bridge_ifname ? iface->bridge_ifname : "N/A");  
    13.   
    14.     if (iface->confname) {  
    15. #ifdef CONFIG_BACKEND_FILE  
    16.         wpa_s->confname = os_rel2abs_path(iface->confname);  
    17.         if (wpa_s->confname == NULL) {  
    18.             wpa_printf(MSG_ERROR, "Failed to get absolute path "  
    19.                    "for configuration file '%s'.",  
    20.                    iface->confname);  
    21.             return -1;  
    22.         }  
    23.         wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",  
    24.                iface->confname, wpa_s->confname);  
    25. #else /* CONFIG_BACKEND_FILE */  
    26.         wpa_s->confname = os_strdup(iface->confname);  
    27. #endif /* CONFIG_BACKEND_FILE */  
    28.         wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);  
    29.         if (wpa_s->conf == NULL) {  
    30.             wpa_printf(MSG_ERROR, "Failed to read or parse "  
    31.                    "configuration '%s'.", wpa_s->confname);  
    32.             return -1;  
    33.         }  
    34.         wpa_s->confanother = os_rel2abs_path(iface->confanother);  
    35.         wpa_config_read(wpa_s->confanother, wpa_s->conf);  
    36.   
    37.         /* 
    38.          * Override ctrl_interface and driver_param if set on command 
    39.          * line. 
    40.          */  
    41.         if (iface->ctrl_interface) {  
    42.             os_free(wpa_s->conf->ctrl_interface);  
    43.             wpa_s->conf->ctrl_interface =  
    44.                 os_strdup(iface->ctrl_interface);  
    45.         }  
    46.   
    47.         if (iface->driver_param) {  
    48.             os_free(wpa_s->conf->driver_param);  
    49.             wpa_s->conf->driver_param =  
    50.                 os_strdup(iface->driver_param);  
    51.         }  
    52.   
    53.         if (iface->p2p_mgmt && !iface->ctrl_interface) {  
    54.             os_free(wpa_s->conf->ctrl_interface);  
    55.             wpa_s->conf->ctrl_interface = NULL;  
    56.         }  
    57.     } else  
    58.         wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,  
    59.                              iface->driver_param);  
    60.   
    61.     if (wpa_s->conf == NULL) {  
    62.         wpa_printf(MSG_ERROR, " No configuration found.");  
    63.         return -1;  
    64.     }  
    65.   
    66.     if (iface->ifname == NULL) {  
    67.         wpa_printf(MSG_ERROR, " Interface name is required.");  
    68.         return -1;  
    69.     }  
    70.     if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {  
    71.         wpa_printf(MSG_ERROR, " Too long interface name '%s'.",  
    72.                iface->ifname);  
    73.         return -1;  
    74.     }  
    75.     os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));  
    76.   
    77.     if (iface->bridge_ifname) {  
    78.         if (os_strlen(iface->bridge_ifname) >=  
    79.             sizeof(wpa_s->bridge_ifname)) {  
    80.             wpa_printf(MSG_ERROR, " Too long bridge interface "  
    81.                    "name '%s'.", iface->bridge_ifname);  
    82.             return -1;  
    83.         }  
    84.         os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,  
    85.                sizeof(wpa_s->bridge_ifname));  
    86.     }  
    87.   
    88.     /* RSNA Supplicant Key Management - INITIALIZE */  
    89.     eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);  
    90.     eapol_sm_notify_portValid(wpa_s->eapol, FALSE);  
    91.   
    92.     /* Initialize driver interface and register driver event handler before 
    93.      * L2 receive handler so that association events are processed before 
    94.      * EAPOL-Key packets if both become available for the same select() 
    95.      * call. */  
    96.     driver = iface->driver;  
    97. next_driver:  
    98.     if (wpa_supplicant_set_driver(wpa_s, driver) < 0)  
    99.         return -1;  
    100.   
    101.     wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);  
    102.     if (wpa_s->drv_priv == NULL) {  
    103.         const char *pos;  
    104.         pos = driver ? os_strchr(driver, ',') : NULL;  
    105.         if (pos) {  
    106.             wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "  
    107.                 "driver interface - try next driver wrapper");  
    108.             driver = pos + 1;  
    109.             goto next_driver;  
    110.         }  
    111.         wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "  
    112.             "interface");  
    113.         return -1;  
    114.     }  
    115.     if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {  
    116.         wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "  
    117.             "driver_param '%s'", wpa_s->conf->driver_param);  
    118.         return -1;  
    119.     }  
    120.   
    121.     ifname = wpa_drv_get_ifname(wpa_s);  
    122.     if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {  
    123.         wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "  
    124.             "interface name with '%s'", ifname);  
    125.         os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));  
    126.     }  
    127.   
    128.     if (wpa_supplicant_init_wpa(wpa_s) < 0)  
    129.         return -1;  
    130.   
    131.     wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,  
    132.               wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :  
    133.               NULL);  
    134.     wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);  
    135.   
    136.     if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&  
    137.         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,  
    138.                  wpa_s->conf->dot11RSNAConfigPMKLifetime)) {  
    139.         wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "  
    140.             "dot11RSNAConfigPMKLifetime");  
    141.         return -1;  
    142.     }  
    143.   
    144.     if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&  
    145.         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,  
    146.                  wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {  
    147.         wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "  
    148.             "dot11RSNAConfigPMKReauthThreshold");  
    149.         return -1;  
    150.     }  
    151.   
    152.     if (wpa_s->conf->dot11RSNAConfigSATimeout &&  
    153.         wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,  
    154.                  wpa_s->conf->dot11RSNAConfigSATimeout)) {  
    155.         wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "  
    156.             "dot11RSNAConfigSATimeout");  
    157.         return -1;  
    158.     }  
    159.   
    160.     wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,  
    161.                               &wpa_s->hw.num_modes,  
    162.                               &wpa_s->hw.flags);  
    163.   
    164.     if (wpa_drv_get_capa(wpa_s, &capa) == 0) {  
    165.         wpa_s->drv_capa_known = 1;  
    166.         wpa_s->drv_flags = capa.flags;  
    167.         wpa_s->drv_enc = capa.enc;  
    168.         wpa_s->probe_resp_offloads = capa.probe_resp_offloads;  
    169.         wpa_s->max_scan_ssids = capa.max_scan_ssids;  
    170.         wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;  
    171.         wpa_s->sched_scan_supported = capa.sched_scan_supported;  
    172.         wpa_s->max_match_sets = capa.max_match_sets;  
    173.         wpa_s->max_remain_on_chan = capa.max_remain_on_chan;  
    174.         wpa_s->max_stations = capa.max_stations;  
    175.         wpa_s->extended_capa = capa.extended_capa;  
    176.         wpa_s->extended_capa_mask = capa.extended_capa_mask;  
    177.         wpa_s->extended_capa_len = capa.extended_capa_len;  
    178.         wpa_s->num_multichan_concurrent =  
    179.             capa.num_multichan_concurrent;  
    180.     }  
    181.     if (wpa_s->max_remain_on_chan == 0)  
    182.         wpa_s->max_remain_on_chan = 1000;  
    183.   
    184.     /* 
    185.      * Only take p2p_mgmt parameters when P2P Device is supported. 
    186.      * Doing it here as it determines whether l2_packet_init() will be done 
    187.      * during wpa_supplicant_driver_init(). 
    188.      */  
    189.     if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)  
    190.         wpa_s->p2p_mgmt = iface->p2p_mgmt;  
    191.     else  
    192.         iface->p2p_mgmt = 1;  
    193.   
    194.     if (wpa_s->num_multichan_concurrent == 0)  
    195.         wpa_s->num_multichan_concurrent = 1;  
    196.   
    197.     if (wpa_supplicant_driver_init(wpa_s) < 0)  
    198.         return -1;  
    199.   
    200. #ifdef CONFIG_TDLS  
    201.     if ((!iface->p2p_mgmt ||  
    202.          !(wpa_s->drv_flags &  
    203.            WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&  
    204.         wpa_tdls_init(wpa_s->wpa))  
    205.         return -1;  
    206. #endif /* CONFIG_TDLS */  
    207.   
    208.     if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&  
    209.         wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {  
    210.         wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");  
    211.         return -1;  
    212.     }  
    213.   
    214.     if (wpas_wps_init(wpa_s))  
    215.         return -1;  
    216.   
    217.     if (wpa_supplicant_init_eapol(wpa_s) < 0)  
    218.         return -1;  
    219.     wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);  
    220.   
    221.     wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);  
    222.     if (wpa_s->ctrl_iface == NULL) {  
    223.         wpa_printf(MSG_ERROR,  
    224.                "Failed to initialize control interface '%s'. "  
    225.                "You may have another wpa_supplicant process "  
    226.                "already running or the file was "  
    227.                "left by an unclean termination of wpa_supplicant "  
    228.                "in which case you will need "  
    229.                "to manually remove this file before starting "  
    230.                "wpa_supplicant again. ",  
    231.                wpa_s->conf->ctrl_interface);  
    232.         return -1;  
    233.     }  
    234.   
    235.     wpa_s->gas = gas_query_init(wpa_s);  
    236.     if (wpa_s->gas == NULL) {  
    237.         wpa_printf(MSG_ERROR, "Failed to initialize GAS query");  
    238.         return -1;  
    239.     }  
    240.   
    241. #ifdef CONFIG_P2P  
    242.     if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {  
    243.         wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");  
    244.         return -1;  
    245.     }  
    246. #endif /* CONFIG_P2P */  
    247.   
    248.     if (wpa_bss_init(wpa_s) < 0)  
    249.         return -1;  
    250.   
    251. #ifdef CONFIG_EAP_PROXY  
    252. {  
    253.     size_t len;  
    254.     wpa_s->mnc_len = eap_proxy_get_imsi(wpa_s->imsi, &len);  
    255.     if (wpa_s->mnc_len > 0) {  
    256.         wpa_s->imsi[len] = '';  
    257.         wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",  
    258.                wpa_s->imsi, wpa_s->mnc_len);  
    259.     } else {  
    260.         wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");  
    261.     }  
    262. }  
    263. #endif /* CONFIG_EAP_PROXY */  
    264.   
    265.     if (pcsc_reader_init(wpa_s) < 0)  
    266.         return -1;  
    267.   
    268.     if (wpas_init_ext_pw(wpa_s) < 0)  
    269.         return -1;  
    270.   
    271.     return 0;  
    272. }  

    1、init_iface初始化的第一个工作是解析运行时配置文件。其中,wpa_s->confname的值为“/data/misc/wifi/wpa_supplicant.conf”,解析函数是wpa_config_read。

    1. struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)  
    2. {  
    3.     FILE *f;  
    4.     char buf[512], *pos;  
    5.     int errors = 0, line = 0;  
    6.     struct wpa_ssid *ssid, *tail = NULL, *head = NULL;  
    7.     struct wpa_cred *cred, *cred_tail = NULL, *cred_head = NULL;  
    8.     struct wpa_config *config;  
    9.     int id = 0;  
    10.     int cred_id = 0;  
    11.   
    12.     if (name == NULL)  
    13.         return NULL;  
    14.     if (cfgp)  
    15.         config = cfgp;  
    16.     else  
    17.         config = wpa_config_alloc_empty(NULL, NULL);  
    18.     if (config == NULL) {  
    19.         wpa_printf(MSG_ERROR, "Failed to allocate config file "  
    20.                "structure");  
    21.         return NULL;  
    22.     }  
    23.     head = config->ssid;  
    24.     cred_head = config->cred;  
    25.   
    26.     wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);  
    27.     f = fopen(name, "r");  
    28.     if (f == NULL) {  
    29.         wpa_printf(MSG_ERROR, "Failed to open config file '%s', "  
    30.                "error: %s", name, strerror(errno));  
    31.         os_free(config);  
    32.         return NULL;  
    33.     }  
    34.   
    35.     while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {  
    36.         if (os_strcmp(pos, "network={") == 0) {  
    37.             ssid = wpa_config_read_network(f, &line, id++);  
    38.             if (ssid == NULL) {  
    39.                 wpa_printf(MSG_ERROR, "Line %d: failed to "  
    40.                        "parse network block.", line);  
    41.                 errors++;  
    42.                 continue;  
    43.             }  
    44.             if (head == NULL) {  
    45.                 head = tail = ssid;  
    46.             } else {  
    47.                 tail->next = ssid;  
    48.                 tail = ssid;  
    49.             }  
    50.             if (wpa_config_add_prio_network(config, ssid)) {  
    51.                 wpa_printf(MSG_ERROR, "Line %d: failed to add "  
    52.                        "network block to priority list.",  
    53.                        line);  
    54.                 errors++;  
    55.                 continue;  
    56.             }  
    57.         } else if (os_strcmp(pos, "cred={") == 0) {  
    58.             cred = wpa_config_read_cred(f, &line, cred_id++);  
    59.             if (cred == NULL) {  
    60.                 wpa_printf(MSG_ERROR, "Line %d: failed to "  
    61.                        "parse cred block.", line);  
    62.                 errors++;  
    63.                 continue;  
    64.             }  
    65.             if (cred_head == NULL) {  
    66.                 cred_head = cred_tail = cred;  
    67.             } else {  
    68.                 cred_tail->next = cred;  
    69.                 cred_tail = cred;  
    70.             }  
    71. #ifndef CONFIG_NO_CONFIG_BLOBS  
    72.         } else if (os_strncmp(pos, "blob-base64-", 12) == 0) {  
    73.             if (wpa_config_process_blob(config, f, &line, pos + 12)  
    74.                 < 0) {  
    75.                 wpa_printf(MSG_ERROR, "Line %d: failed to "  
    76.                        "process blob.", line);  
    77.                 errors++;  
    78.                 continue;  
    79.             }  
    80. #endif /* CONFIG_NO_CONFIG_BLOBS */  
    81.         } else if (wpa_config_process_global(config, pos, line) < 0) {  
    82.             wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "  
    83.                    "line '%s'.", line, pos);  
    84.             errors++;  
    85.             continue;  
    86.         }  
    87.     }  
    88.   
    89.     fclose(f);  
    90.   
    91.     config->ssid = head;  
    92.     wpa_config_debug_dump_networks(config);  
    93.     config->cred = cred_head;  
    94.   
    95. #ifndef WPA_IGNORE_CONFIG_ERRORS  
    96.     if (errors) {  
    97.         wpa_config_free(config);  
    98.         config = NULL;  
    99.         head = NULL;  
    100.     }  
    101. #endif /* WPA_IGNORE_CONFIG_ERRORS */  
    102.   
    103.     return config;  
    104. }  

    wpa_config和wpa_ssid这两个数据结构都是配置文件中的信息在代码中的实现。
    2、wpa_supplicant_set_driver将根据nl80211找到wpa_driver数组中nl80211指定的driver对象wpa_driver_nl80211_ops,然后调用其global_init函数。

    global_init是wpa_driver_ops结构体重的一个类型为函数指针的成员变量。

    1. static void * nl80211_global_init(void)  
    2. {  
    3.     struct nl80211_global *global;  
    4.     struct netlink_config *cfg;  
    5.   
    6.     global = os_zalloc(sizeof(*global));  
    7.     if (global == NULL)  
    8.         return NULL;  
    9.     global->ioctl_sock = -1;  
    10.     dl_list_init(&global->interfaces);  
    11.     global->if_add_ifindex = -1;  
    12.   
    13.     cfg = os_zalloc(sizeof(*cfg));  
    14.     if (cfg == NULL)  
    15.         goto err;  
    16.   
    17.     cfg->ctx = global;  
    18.     cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;  
    19.     cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;  
    20.     global->netlink = netlink_init(cfg);  
    21.     if (global->netlink == NULL) {  
    22.         os_free(cfg);  
    23.         goto err;  
    24.     }  
    25.   
    26.     if (wpa_driver_nl80211_init_nl_global(global) < 0)  
    27.         goto err;  
    28.   
    29.     global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);  
    30.     if (global->ioctl_sock < 0) {  
    31.         perror("socket(PF_INET,SOCK_DGRAM)");  
    32.         goto err;  
    33.     }  
    34.   
    35.     return global;  
    36.   
    37. err:  
    38.     nl80211_global_deinit(global);  
    39.     return NULL;  
    40. }  
    1. static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)  
    2. {  
    3.     int ret;  
    4.   
    5.     global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);  
    6.     if (global->nl_cb == NULL) {  
    7.         wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "  
    8.                "callbacks");  
    9.         return -1;  
    10.     }  
    11.   
    12.     global->nl = nl_create_handle(global->nl_cb, "nl");  
    13.     if (global->nl == NULL)  
    14.         goto err;  
    15.   
    16.     global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");  
    17.     if (global->nl80211_id < 0) {  
    18.         wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "  
    19.                "found");  
    20.         goto err;  
    21.     }  
    22.   
    23.     global->nl_event = nl_create_handle(global->nl_cb, "event");  
    24.     if (global->nl_event == NULL)  
    25.         goto err;  
    26.   
    27.     ret = nl_get_multicast_id(global, "nl80211", "scan");  
    28.     if (ret >= 0)  
    29.         ret = nl_socket_add_membership(global->nl_event, ret);  
    30.     if (ret < 0) {  
    31.         wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "  
    32.                "membership for scan events: %d (%s)",  
    33.                ret, strerror(-ret));  
    34.         goto err;  
    35.     }  
    36.   
    37.     ret = nl_get_multicast_id(global, "nl80211", "mlme");  
    38.     if (ret >= 0)  
    39.         ret = nl_socket_add_membership(global->nl_event, ret);  
    40.     if (ret < 0) {  
    41.         wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "  
    42.                "membership for mlme events: %d (%s)",  
    43.                ret, strerror(-ret));  
    44.         goto err;  
    45.     }  
    46.   
    47.     ret = nl_get_multicast_id(global, "nl80211", "regulatory");  
    48.     if (ret >= 0)  
    49.         ret = nl_socket_add_membership(global->nl_event, ret);  
    50.     if (ret < 0) {  
    51.         wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "  
    52.                "membership for regulatory events: %d (%s)",  
    53.                ret, strerror(-ret));  
    54.         /* Continue without regulatory events */  
    55.     }  
    56.   
    57.     nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,  
    58.           no_seq_check, NULL);  
    59.     nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,  
    60.           process_global_event, global);  
    61.   
    62.     eloop_register_read_sock(nl_socket_get_fd(global->nl_event),  
    63.                  wpa_driver_nl80211_event_receive,  
    64.                  global->nl_cb, global->nl_event);  
    65.   
    66.     return 0;  
    67.   
    68. err:  
    69.     nl_destroy_handles(&global->nl_event);  
    70.     nl_destroy_handles(&global->nl);  
    71.     nl_cb_put(global->nl_cb);  
    72.     global->nl_cb = NULL;  
    73.     return -1;  
    74. }  

    3、wpa_drv_init函数处理单个driver。内部调用init2函数。

      1. static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,  
      2.                       void *global_priv)  
      3. {  
      4.     struct wpa_driver_nl80211_data *drv;  
      5.     struct rfkill_config *rcfg;  
      6.     struct i802_bss *bss;  
      7.   
      8.     if (global_priv == NULL)  
      9.         return NULL;  
      10.     drv = os_zalloc(sizeof(*drv));  
      11.     if (drv == NULL)  
      12.         return NULL;  
      13.     drv->global = global_priv;  
      14.     drv->ctx = ctx;  
      15.     bss = &drv->first_bss;  
      16.     bss->drv = drv;  
      17.     bss->ctx = ctx;  
      18.   
      19.     os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));  
      20.     drv->monitor_ifidx = -1;  
      21.     drv->monitor_sock = -1;  
      22.     drv->eapol_tx_sock = -1;  
      23.     drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;  
      24.   
      25.     if (wpa_driver_nl80211_init_nl(drv)) {  
      26.         os_free(drv);  
      27.         return NULL;  
      28.     }  
      29.   
      30.     if (nl80211_init_bss(bss))  
      31.         goto failed;  
      32.   
      33.     rcfg = os_zalloc(sizeof(*rcfg));  
      34.     if (rcfg == NULL)  
      35.         goto failed;  
      36.     rcfg->ctx = drv;  
      37.     os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));  
      38.     rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;  
      39.     rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;  
      40.     drv->rfkill = rfkill_init(rcfg);  
      41.     if (drv->rfkill == NULL) {  
      42.         wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");  
      43.         os_free(rcfg);  
      44.     }  
      45.   
      46.     if (wpa_driver_nl80211_finish_drv_init(drv))  
      47.         goto failed;  
      48.   
      49.     drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);  
      50.     if (drv->eapol_tx_sock < 0)  
      51.         goto failed;  
      52.   
      53.     if (drv->data_tx_status) {  
      54.         int enabled = 1;  
      55.   
      56.         if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,  
      57.                    &enabled, sizeof(enabled)) < 0) {  
      58.             wpa_printf(MSG_DEBUG,  
      59.                 "nl80211: wifi status sockopt failed ");  
      60.             drv->data_tx_status = 0;  
      61.             if (!drv->use_monitor)  
      62.                 drv->capa.flags &=  
      63.                     ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;  
      64.         } else {  
      65.             eloop_register_read_sock(drv->eapol_tx_sock,  
      66.                 wpa_driver_nl80211_handle_eapol_tx_status,  
      67.                 drv, NULL);  
      68.         }  
      69.     }  
      70.   
      71.     if (drv->global) {  
      72.         dl_list_add(&drv->global->interfaces, &drv->list);  
      73.         drv->in_interface_list = 1;  
      74.     }  
      75.   
      76.     return bss;  
      77.   
      78. failed:  
      79.     wpa_driver_nl80211_deinit(bss);  
      80.     return NULL;  
  • 相关阅读:
    van Emda Boas
    斐波那契堆
    NTT
    FFT
    KDTree
    扩展kmp
    kmp
    Dancing Links
    树的prufer编码
    有向图最小路径覆盖
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/7458639.html
Copyright © 2011-2022 走看看