Android4.4 wpa

    xiaoxiao2021-04-14  73

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

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

    [wpa_supplicant.c::wpa_supplicant_add_iface]

    [cpp]  view plain  copy   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;          if (global == NULL || iface == NULL)           return NULL;          wpa_s = wpa_supplicant_alloc();       if (wpa_s == NULL)           return NULL;          wpa_s->global = global;          t_iface = *iface;       if (global->params.override_driver) {           wpa_printf(MSG_DEBUG, "Override interface parameter: driver "                  "('%s' -> '%s')",                  iface->driver, global->params.override_driver);           t_iface.driver = global->params.override_driver;       }       if (global->params.override_ctrl_interface) {           wpa_printf(MSG_DEBUG, "Override interface parameter: "                  "ctrl_interface ('%s' -> '%s')",                  iface->ctrl_interface,                  global->params.override_ctrl_interface);           t_iface.ctrl_interface =               global->params.override_ctrl_interface;       }       if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {           wpa_printf(MSG_DEBUG, "Failed to add interface %s",                  iface->ifname);           wpa_supplicant_deinit_iface(wpa_s, 0, 0);           return NULL;       }          /* 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);          wpa_s->next = global->ifaces;       global->ifaces = wpa_s;          wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);       wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);          return wpa_s;   }  

    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定义有关。

    [cpp]  view plain  copy   #define WPA_CIPHER_NONE BIT(0)<span style="white-space:pre">      </span>//不保护   #define WPA_CIPHER_WEP40 BIT(1)<span style="white-space:pre">     </span>//WEP40   #define WPA_CIPHER_WEP104 BIT(2)<span style="white-space:pre">    </span>//WEP104   #define WPA_CIPHER_TKIP BIT(3)<span style="white-space:pre">      </span>//TKIP   #define WPA_CIPHER_CCMP BIT(4)<span style="white-space:pre">      </span>//CCMP   [cpp]  view plain  copy   #define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP)   #define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | \                  WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)   3)key_mgmt:该成员和802.11中的AKM(Authentication and Key Managment,身份验证和密钥管理)suite相关。 [cpp]  view plain  copy   #define WPA_KEY_MGMT_IEEE8021X BIT(0)   #define WPA_KEY_MGMT_PSK BIT(1)   #define WPA_KEY_MGMT_NONE BIT(2)   #define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)   #define WPA_KEY_MGMT_WPA_NONE BIT(4)   #define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)   #define WPA_KEY_MGMT_FT_PSK BIT(6)   #define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)   #define WPA_KEY_MGMT_PSK_SHA256 BIT(8)   #define WPA_KEY_MGMT_WPS BIT(9)   #define WPA_KEY_MGMT_SAE BIT(10)   #define WPA_KEY_MGMT_FT_SAE BIT(11)   #define WPA_KEY_MGMT_WAPI_PSK BIT(12)   #define WPA_KEY_MGMT_WAPI_CERT BIT(13)   #define WPA_KEY_MGMT_CCKM BIT(14)   [cpp]  view plain  copy   #define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X)   4)proto:代表该无线网络支持的安全协议类型。 [cpp]  view plain  copy   #define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN)   [cpp]  view plain  copy   #define WPA_PROTO_WPA BIT(0)   #define WPA_PROTO_RSN BIT(1)   #define WPA_PROTO_WAPI BIT(2)  

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

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

    [cpp]  view plain  copy   #define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0)   #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函数分析

    [cpp]  view plain  copy   static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,                        struct wpa_interface *iface)   {       const char *ifname, *driver;       struct wpa_driver_capa capa;          wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "              "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,              iface->confname ? iface->confname : "N/A",              iface->driver ? iface->driver : "default",              iface->ctrl_interface ? iface->ctrl_interface : "N/A",              iface->bridge_ifname ? iface->bridge_ifname : "N/A");          if (iface->confname) {   #ifdef CONFIG_BACKEND_FILE           wpa_s->confname = os_rel2abs_path(iface->confname);           if (wpa_s->confname == NULL) {               wpa_printf(MSG_ERROR, "Failed to get absolute path "                      "for configuration file '%s'.",                      iface->confname);               return -1;           }           wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",                  iface->confname, wpa_s->confname);   #else /* CONFIG_BACKEND_FILE */           wpa_s->confname = os_strdup(iface->confname);   #endif /* CONFIG_BACKEND_FILE */           wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);           if (wpa_s->conf == NULL) {               wpa_printf(MSG_ERROR, "Failed to read or parse "                      "configuration '%s'.", wpa_s->confname);               return -1;           }           wpa_s->confanother = os_rel2abs_path(iface->confanother);           wpa_config_read(wpa_s->confanother, wpa_s->conf);              /*           * Override ctrl_interface and driver_param if set on command           * line.           */           if (iface->ctrl_interface) {               os_free(wpa_s->conf->ctrl_interface);               wpa_s->conf->ctrl_interface =                   os_strdup(iface->ctrl_interface);           }              if (iface->driver_param) {               os_free(wpa_s->conf->driver_param);               wpa_s->conf->driver_param =                   os_strdup(iface->driver_param);           }              if (iface->p2p_mgmt && !iface->ctrl_interface) {               os_free(wpa_s->conf->ctrl_interface);               wpa_s->conf->ctrl_interface = NULL;           }       } else           wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,                                iface->driver_param);          if (wpa_s->conf == NULL) {           wpa_printf(MSG_ERROR, "\nNo configuration found.");           return -1;       }          if (iface->ifname == NULL) {           wpa_printf(MSG_ERROR, "\nInterface name is required.");           return -1;       }       if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {           wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",                  iface->ifname);           return -1;       }       os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));          if (iface->bridge_ifname) {           if (os_strlen(iface->bridge_ifname) >=               sizeof(wpa_s->bridge_ifname)) {               wpa_printf(MSG_ERROR, "\nToo long bridge interface "                      "name '%s'.", iface->bridge_ifname);               return -1;           }           os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,                  sizeof(wpa_s->bridge_ifname));       }          /* RSNA Supplicant Key Management - INITIALIZE */       eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);       eapol_sm_notify_portValid(wpa_s->eapol, FALSE);          /* Initialize driver interface and register driver event handler before       * L2 receive handler so that association events are processed before       * EAPOL-Key packets if both become available for the same select()       * call. */       driver = iface->driver;   next_driver:       if (wpa_supplicant_set_driver(wpa_s, driver) < 0)           return -1;          wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);       if (wpa_s->drv_priv == NULL) {           const char *pos;           pos = driver ? os_strchr(driver, ',') : NULL;           if (pos) {               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "                   "driver interface - try next driver wrapper");               driver = pos + 1;               goto next_driver;           }           wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "               "interface");           return -1;       }       if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {           wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "               "driver_param '%s'", wpa_s->conf->driver_param);           return -1;       }          ifname = wpa_drv_get_ifname(wpa_s);       if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {           wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "               "interface name with '%s'", ifname);           os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));       }          if (wpa_supplicant_init_wpa(wpa_s) < 0)           return -1;          wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,                 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :                 NULL);       wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);          if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&           wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,                    wpa_s->conf->dot11RSNAConfigPMKLifetime)) {           wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "               "dot11RSNAConfigPMKLifetime");           return -1;       }          if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&           wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,                    wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {           wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "               "dot11RSNAConfigPMKReauthThreshold");           return -1;       }          if (wpa_s->conf->dot11RSNAConfigSATimeout &&           wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,                    wpa_s->conf->dot11RSNAConfigSATimeout)) {           wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "               "dot11RSNAConfigSATimeout");           return -1;       }          wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,                                 &wpa_s->hw.num_modes,                                 &wpa_s->hw.flags);          if (wpa_drv_get_capa(wpa_s, &capa) == 0) {           wpa_s->drv_capa_known = 1;           wpa_s->drv_flags = capa.flags;           wpa_s->drv_enc = capa.enc;           wpa_s->probe_resp_offloads = capa.probe_resp_offloads;           wpa_s->max_scan_ssids = capa.max_scan_ssids;           wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;           wpa_s->sched_scan_supported = capa.sched_scan_supported;           wpa_s->max_match_sets = capa.max_match_sets;           wpa_s->max_remain_on_chan = capa.max_remain_on_chan;           wpa_s->max_stations = capa.max_stations;           wpa_s->extended_capa = capa.extended_capa;           wpa_s->extended_capa_mask = capa.extended_capa_mask;           wpa_s->extended_capa_len = capa.extended_capa_len;           wpa_s->num_multichan_concurrent =               capa.num_multichan_concurrent;       }       if (wpa_s->max_remain_on_chan == 0)           wpa_s->max_remain_on_chan = 1000;          /*       * Only take p2p_mgmt parameters when P2P Device is supported.       * Doing it here as it determines whether l2_packet_init() will be done       * during wpa_supplicant_driver_init().       */       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)           wpa_s->p2p_mgmt = iface->p2p_mgmt;       else           iface->p2p_mgmt = 1;          if (wpa_s->num_multichan_concurrent == 0)           wpa_s->num_multichan_concurrent = 1;          if (wpa_supplicant_driver_init(wpa_s) < 0)           return -1;      #ifdef CONFIG_TDLS       if ((!iface->p2p_mgmt ||            !(wpa_s->drv_flags &              WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&           wpa_tdls_init(wpa_s->wpa))           return -1;   #endif /* CONFIG_TDLS */          if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&           wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {           wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");           return -1;       }          if (wpas_wps_init(wpa_s))           return -1;          if (wpa_supplicant_init_eapol(wpa_s) < 0)           return -1;       wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);          wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);       if (wpa_s->ctrl_iface == NULL) {           wpa_printf(MSG_ERROR,                  "Failed to initialize control interface '%s'.\n"                  "You may have another wpa_supplicant process "                  "already running or the file was\n"                  "left by an unclean termination of wpa_supplicant "                  "in which case you will need\n"                  "to manually remove this file before starting "                  "wpa_supplicant again.\n",                  wpa_s->conf->ctrl_interface);           return -1;       }          wpa_s->gas = gas_query_init(wpa_s);       if (wpa_s->gas == NULL) {           wpa_printf(MSG_ERROR, "Failed to initialize GAS query");           return -1;       }      #ifdef CONFIG_P2P       if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {           wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");           return -1;       }   #endif /* CONFIG_P2P */          if (wpa_bss_init(wpa_s) < 0)           return -1;      #ifdef CONFIG_EAP_PROXY   {       size_t len;       wpa_s->mnc_len = eap_proxy_get_imsi(wpa_s->imsi, &len);       if (wpa_s->mnc_len > 0) {           wpa_s->imsi[len] = '\0';           wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",                  wpa_s->imsi, wpa_s->mnc_len);       } else {           wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");       }   }   #endif /* CONFIG_EAP_PROXY */          if (pcsc_reader_init(wpa_s) < 0)           return -1;          if (wpas_init_ext_pw(wpa_s) < 0)           return -1;          return 0;   }   1、init_iface初始化的第一个工作是解析运行时配置文件。其中,wpa_s->confname的值为“/data/misc/wifi/wpa_supplicant.conf”,解析函数是wpa_config_read。

    [cpp]  view plain  copy   struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)   {       FILE *f;       char buf[512], *pos;       int errors = 0, line = 0;       struct wpa_ssid *ssid, *tail = NULL, *head = NULL;       struct wpa_cred *cred, *cred_tail = NULL, *cred_head = NULL;       struct wpa_config *config;       int id = 0;       int cred_id = 0;          if (name == NULL)           return NULL;       if (cfgp)           config = cfgp;       else           config = wpa_config_alloc_empty(NULL, NULL);       if (config == NULL) {           wpa_printf(MSG_ERROR, "Failed to allocate config file "                  "structure");           return NULL;       }       head = config->ssid;       cred_head = config->cred;          wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);       f = fopen(name, "r");       if (f == NULL) {           wpa_printf(MSG_ERROR, "Failed to open config file '%s', "                  "error: %s", name, strerror(errno));           os_free(config);           return NULL;       }          while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {           if (os_strcmp(pos, "network={") == 0) {               ssid = wpa_config_read_network(f, &line, id++);               if (ssid == NULL) {                   wpa_printf(MSG_ERROR, "Line %d: failed to "                          "parse network block.", line);                   errors++;                   continue;               }               if (head == NULL) {                   head = tail = ssid;               } else {                   tail->next = ssid;                   tail = ssid;               }               if (wpa_config_add_prio_network(config, ssid)) {                   wpa_printf(MSG_ERROR, "Line %d: failed to add "                          "network block to priority list.",                          line);                   errors++;                   continue;               }           } else if (os_strcmp(pos, "cred={") == 0) {               cred = wpa_config_read_cred(f, &line, cred_id++);               if (cred == NULL) {                   wpa_printf(MSG_ERROR, "Line %d: failed to "                          "parse cred block.", line);                   errors++;                   continue;               }               if (cred_head == NULL) {                   cred_head = cred_tail = cred;               } else {                   cred_tail->next = cred;                   cred_tail = cred;               }   #ifndef CONFIG_NO_CONFIG_BLOBS           } else if (os_strncmp(pos, "blob-base64-", 12) == 0) {               if (wpa_config_process_blob(config, f, &line, pos + 12)                   < 0) {                   wpa_printf(MSG_ERROR, "Line %d: failed to "                          "process blob.", line);                   errors++;                   continue;               }   #endif /* CONFIG_NO_CONFIG_BLOBS */           } else if (wpa_config_process_global(config, pos, line) < 0) {               wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "                      "line '%s'.", line, pos);               errors++;               continue;           }       }          fclose(f);          config->ssid = head;       wpa_config_debug_dump_networks(config);       config->cred = cred_head;      #ifndef WPA_IGNORE_CONFIG_ERRORS       if (errors) {           wpa_config_free(config);           config = NULL;           head = NULL;       }   #endif /* WPA_IGNORE_CONFIG_ERRORS */          return config;   }   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结构体重的一个类型为函数指针的成员变量。

    [cpp]  view plain  copy   static void * nl80211_global_init(void)   {       struct nl80211_global *global;       struct netlink_config *cfg;          global = os_zalloc(sizeof(*global));       if (global == NULL)           return NULL;       global->ioctl_sock = -1;       dl_list_init(&global->interfaces);       global->if_add_ifindex = -1;          cfg = os_zalloc(sizeof(*cfg));       if (cfg == NULL)           goto err;          cfg->ctx = global;       cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;       cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;       global->netlink = netlink_init(cfg);       if (global->netlink == NULL) {           os_free(cfg);           goto err;       }          if (wpa_driver_nl80211_init_nl_global(global) < 0)           goto err;          global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);       if (global->ioctl_sock < 0) {           perror("socket(PF_INET,SOCK_DGRAM)");           goto err;       }          return global;      err:       nl80211_global_deinit(global);       return NULL;   }   [cpp]  view plain  copy   static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)   {       int ret;          global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);       if (global->nl_cb == NULL) {           wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "                  "callbacks");           return -1;       }          global->nl = nl_create_handle(global->nl_cb, "nl");       if (global->nl == NULL)           goto err;          global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");       if (global->nl80211_id < 0) {           wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "                  "found");           goto err;       }          global->nl_event = nl_create_handle(global->nl_cb, "event");       if (global->nl_event == NULL)           goto err;          ret = nl_get_multicast_id(global, "nl80211""scan");       if (ret >= 0)           ret = nl_socket_add_membership(global->nl_event, ret);       if (ret < 0) {           wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "                  "membership for scan events: %d (%s)",                  ret, strerror(-ret));           goto err;       }          ret = nl_get_multicast_id(global, "nl80211""mlme");       if (ret >= 0)           ret = nl_socket_add_membership(global->nl_event, ret);       if (ret < 0) {           wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "                  "membership for mlme events: %d (%s)",                  ret, strerror(-ret));           goto err;       }          ret = nl_get_multicast_id(global, "nl80211""regulatory");       if (ret >= 0)           ret = nl_socket_add_membership(global->nl_event, ret);       if (ret < 0) {           wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "                  "membership for regulatory events: %d (%s)",                  ret, strerror(-ret));           /* Continue without regulatory events */       }          nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,             no_seq_check, NULL);       nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,             process_global_event, global);          eloop_register_read_sock(nl_socket_get_fd(global->nl_event),                    wpa_driver_nl80211_event_receive,                    global->nl_cb, global->nl_event);          return 0;      err:       nl_destroy_handles(&global->nl_event);       nl_destroy_handles(&global->nl);       nl_cb_put(global->nl_cb);       global->nl_cb = NULL;       return -1;   }   3、wpa_drv_init函数处理单个driver。内部调用init2函数。 [cpp]  view plain  copy   static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,                         void *global_priv)   {       struct wpa_driver_nl80211_data *drv;       struct rfkill_config *rcfg;       struct i802_bss *bss;          if (global_priv == NULL)           return NULL;       drv = os_zalloc(sizeof(*drv));       if (drv == NULL)           return NULL;       drv->global = global_priv;       drv->ctx = ctx;       bss = &drv->first_bss;       bss->drv = drv;       bss->ctx = ctx;          os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));       drv->monitor_ifidx = -1;       drv->monitor_sock = -1;       drv->eapol_tx_sock = -1;       drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;          if (wpa_driver_nl80211_init_nl(drv)) {           os_free(drv);           return NULL;       }          if (nl80211_init_bss(bss))           goto failed;          rcfg = os_zalloc(sizeof(*rcfg));       if (rcfg == NULL)           goto failed;       rcfg->ctx = drv;       os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));       rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;       rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;       drv->rfkill = rfkill_init(rcfg);       if (drv->rfkill == NULL) {           wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");           os_free(rcfg);       }          if (wpa_driver_nl80211_finish_drv_init(drv))           goto failed;          drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);       if (drv->eapol_tx_sock < 0)           goto failed;          if (drv->data_tx_status) {           int enabled = 1;              if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,                      &enabled, sizeof(enabled)) < 0) {               wpa_printf(MSG_DEBUG,                   "nl80211: wifi status sockopt failed\n");               drv->data_tx_status = 0;               if (!drv->use_monitor)                   drv->capa.flags &=                       ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;           } else {               eloop_register_read_sock(drv->eapol_tx_sock,                   wpa_driver_nl80211_handle_eapol_tx_status,                   drv, NULL);           }       }          if (drv->global) {           dl_list_add(&drv->global->interfaces, &drv->list);           drv->in_interface_list = 1;       }          return bss;      failed:       wpa_driver_nl80211_deinit(bss);       return NULL;   }  
    转载请注明原文地址: https://ju.6miu.com/read-670730.html

    最新回复(0)