位置: 编程技术 - 正文

Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续

编辑:rootadmin

推荐整理分享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]

[cpp] view plaincopystruct 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数组 //数组长度为,用于保存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,//代表基础结构网络的STAWPAS_MODE_IBSS = 1,//代表IBSS网络的模式WPAS_MODE_AP = 2,代表基础结构网络中的APWPAS_MODE_P2P_GO = 3,//P2P相关WPAS_MODE_GROUP_FORMATION = 4,}mode;

Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续

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

(1)安全相关成员变量

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

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

[cpp] view plaincopy#define WPA_CIPHER_NONE BIT(0)<span style="white-space:pre"> </span>//不保护 #define WPA_CIPHER_WEP BIT(1)<span style="white-space:pre"> </span>//WEP #define WPA_CIPHER_WEP BIT(2)<span style="white-space:pre"> </span>//WEP #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 plaincopy#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) #define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP | WPA_CIPHER_WEP) 3)key_mgmt:该成员和.中的AKM(Authentication and Key Managment,身份验证和密钥管理)suite相关。[cpp] view plaincopy#define WPA_KEY_MGMT_IEEEX BIT(0) #define WPA_KEY_MGMT_PSK BIT(1) #define WPA_KEY_MGMT_NONE BIT(2) #define WPA_KEY_MGMT_IEEEX_NO_WPA BIT(3) #define WPA_KEY_MGMT_WPA_NONE BIT(4) #define WPA_KEY_MGMT_FT_IEEEX BIT(5) #define WPA_KEY_MGMT_FT_PSK BIT(6) #define WPA_KEY_MGMT_IEEEX_SHA BIT(7) #define WPA_KEY_MGMT_PSK_SHA BIT(8) #define WPA_KEY_MGMT_WPS BIT(9) #define WPA_KEY_MGMT_SAE BIT() #define WPA_KEY_MGMT_FT_SAE BIT() #define WPA_KEY_MGMT_WAPI_PSK BIT() #define WPA_KEY_MGMT_WAPI_CERT BIT() #define WPA_KEY_MGMT_CCKM BIT() [cpp] view plaincopy#define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEEX) 4)proto:代表该无线网络支持的安全协议类型。[cpp] view plaincopy#define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN) [cpp] view plaincopy#define WPA_PROTO_WPA BIT(0) #define WPA_PROTO_RSN BIT(1) #define WPA_PROTO_WAPI BIT(2)

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

[cpp] view plaincopy#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 plaincopy#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 plaincopystatic 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->dotRSNAConfigPMKLifetime && wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, wpa_s->conf->dotRSNAConfigPMKLifetime)) { wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " "dotRSNAConfigPMKLifetime"); return -1; } if (wpa_s->conf->dotRSNAConfigPMKReauthThreshold && wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, wpa_s->conf->dotRSNAConfigPMKReauthThreshold)) { wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " "dotRSNAConfigPMKReauthThreshold"); return -1; } if (wpa_s->conf->dotRSNAConfigSATimeout && wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, wpa_s->conf->dotRSNAConfigSATimeout)) { wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " "dotRSNAConfigSATimeout"); 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 = ; /* * 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 wasn" "left by an unclean termination of wpa_supplicant " "in which case you will needn" "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] = ''; 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 plaincopystruct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp) { FILE *f; char buf[], *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-base-", ) == 0) { if (wpa_config_process_blob(config, f, &line, pos &#; ) < 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将根据nl找到wpa_driver数组中nl指定的driver对象wpa_driver_nl_ops,然后调用其global_init函数。

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

[cpp] view plaincopystatic void * nl_global_init(void) { struct nl_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_nl_event_rtm_newlink; cfg->dellink_cb = wpa_driver_nl_event_rtm_dellink; global->netlink = netlink_init(cfg); if (global->netlink == NULL) { os_free(cfg); goto err; } if (wpa_driver_nl_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: nl_global_deinit(global); return NULL; } [cpp] view plaincopystatic int wpa_driver_nl_init_nl_global(struct nl_global *global) { int ret; global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); if (global->nl_cb == NULL) { wpa_printf(MSG_ERROR, "nl: Failed to allocate netlink " "callbacks"); return -1; } global->nl = nl_create_handle(global->nl_cb, "nl"); if (global->nl == NULL) goto err; global->nl_id = genl_ctrl_resolve(global->nl, "nl"); if (global->nl_id < 0) { wpa_printf(MSG_ERROR, "nl: 'nl' 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, "nl", "scan"); if (ret >= 0) ret = nl_socket_add_membership(global->nl_event, ret); if (ret < 0) { wpa_printf(MSG_ERROR, "nl: Could not add multicast " "membership for scan events: %d (%s)", ret, strerror(-ret)); goto err; } ret = nl_get_multicast_id(global, "nl", "mlme"); if (ret >= 0) ret = nl_socket_add_membership(global->nl_event, ret); if (ret < 0) { wpa_printf(MSG_ERROR, "nl: Could not add multicast " "membership for mlme events: %d (%s)", ret, strerror(-ret)); goto err; } ret = nl_get_multicast_id(global, "nl", "regulatory"); if (ret >= 0) ret = nl_socket_add_membership(global->nl_event, ret); if (ret < 0) { wpa_printf(MSG_DEBUG, "nl: 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_nl_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 plaincopystatic void * wpa_driver_nl_init(void *ctx, const char *ifname, void *global_priv) { struct wpa_driver_nl_data *drv; struct rfkill_config *rcfg; struct i_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 = NL_IFTYPE_UNSPECIFIED; if (wpa_driver_nl_init_nl(drv)) { os_free(drv); return NULL; } if (nl_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_nl_rfkill_blocked; rcfg->unblocked_cb = wpa_driver_nl_rfkill_unblocked; drv->rfkill = rfkill_init(rcfg); if (drv->rfkill == NULL) { wpa_printf(MSG_DEBUG, "nl: RFKILL status not available"); os_free(rcfg); } if (wpa_driver_nl_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, "nl: wifi status sockopt failedn"); 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_nl_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_nl_deinit(bss); return NULL; }

android AsyncTask介绍 AsyncTask和Handler对比1)AsyncTask实现的原理,和适用的优缺点AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反

[置顶] [Android Studio 权威教程]Android Studio 三种添加插件的方式 前几篇blog我们介绍了如何安装和配置AndroidStudio,这篇Blog我们来聊聊如何给AndroidStudio添加插件,添加插件的路径有三种,我把他们分类如下:点击设置小

Java和android及iOS对接RSA加密经验 1.网上找的java生成RSA密钥对的例子,产生的字附串实际上是hax后和密钥串你可以将他们当成静态字附串存在java代码里2.android和java可以代码复用,IOS对接比

标签: Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续

本文链接地址:https://www.jiuchutong.com/biancheng/384213.html 转载请保留说明!

上一篇:俩个时间戳相减(时间戳的差值)

下一篇:android AsyncTask介绍(android synchronized)

  • 免税外汇商品
  • 企业取得非货币性收入
  • 企业转让土地需要交土地增值税吗
  • 办理外汇账户开户手续
  • 现金长短款的一般处理
  • 其他业务收入记账凭证怎么写
  • 给了钱不给发票可以报警吗
  • 所得税汇算清缴后发现有误怎么办
  • 企业怎么办税
  • 同一套房
  • 有开发票就要交印花税吗?
  • 增值税专票给客户的是第几联
  • 个体户哪种税率最低
  • 在企业走账扣的税点钱如何做账?
  • 进项税额异常补税怎么算
  • 红冲的普通发票要给对方吗
  • coms恢复默认设置
  • 普通发票的进项票怎么做分录
  • 路由器网速慢怎么设置
  • vue做移动端适配最佳解决方案,亲测有效
  • 一般纳税人辅导期管理办法
  • PHP:zip_entry_close()的用法_Zip函数
  • 微信小程序前端源码
  • PHP:date_sunrise()的用法_Date Time函数
  • 支付航天信息服务费怎么入账
  • 进项税大于销项税,不用缴纳增值税
  • php利用switch语句判断学生成绩处于哪个区间
  • php cookie session
  • 微信小程序商城创建
  • 滚动条基本样式有哪些
  • 销售货款无法收到怎么办
  • wordpress页面设置
  • 股东之间股权转让需要股东会决议吗
  • 合同发票收款付款管理系统源码
  • 小型微利企业符合条件的有
  • css中字符间距怎么设置
  • 一般纳税人申请条件
  • 银行日记账怎么做账
  • 科技型中小微企业贷款贴息贴保项目入库
  • 无形资产一般包括哪些权利
  • 施工企业会计核算实验报告
  • 月底留抵税额需要结转吗
  • 购买软件多少钱进无形资产
  • 2021个税新规工资表公式
  • 税费损失
  • 电梯安装发票税收分类
  • 单位收到社保补贴会计怎样处理
  • 投资性房地产改造期间计提折旧吗
  • 赔偿款从货款扣除怎么做账
  • 小规模结转增值税会计科目有哪些
  • 营业外支出科目核算内容
  • 递延收益的主要形式有
  • 记账凭证可以先做贷方吗
  • 货拉拉平台运费没有结打不通电话怎么办
  • 修筑公路的流程视频
  • 纳税申报利润总额计算公式
  • 计税价格里含税吗
  • sql语句数量
  • centos强制关闭程序
  • 0x80070718配额不足
  • u盘安装ubuntu找不到硬盘
  • windows10推送
  • linux安装与基本命令
  • win8更新设置
  • Linux下查看某一个程序所使用的内存方法
  • win7 64位旗舰版系统网页字体大小如何修改变动
  • 游戏引擎官方平台
  • Androidannotation使用之@Rest获取资源及用户登录验证(一)
  • jquery教程w3school
  • ie6怎么设置兼容性
  • js设置select
  • ajax multipart/form-data
  • shell中大括号
  • javascript+css3 实现动态按钮菜单特效
  • 江西国税局电子税务局
  • 网上交医保几点上班
  • 遵从和尊重
  • 增值税发票勾选操作流程
  • 02112366电子税务局
  • 广东省电子税务局app下载官网
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设