当前位置: 首页 > article >正文

wpa_supplicant驱动初始化源码分析

这里面有非常多的成员,主要是关于 wifi 的一些功能



const struct wpa_driver_ops wpa_driver_nl80211_ops = {
	.name = "nl80211",
	.desc = "Linux nl80211/cfg80211",
	.get_bssid = wpa_driver_nl80211_get_bssid,
	.get_ssid = wpa_driver_nl80211_get_ssid,
	.set_key = driver_nl80211_set_key,
	.scan2 = driver_nl80211_scan2,
	.sched_scan = wpa_driver_nl80211_sched_scan,
	.stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
	.get_scan_results = wpa_driver_nl80211_get_scan_results,
	.abort_scan = wpa_driver_nl80211_abort_scan,
	.deauthenticate = driver_nl80211_deauthenticate,
	.authenticate = driver_nl80211_authenticate,
	.associate = wpa_driver_nl80211_associate,
	.global_init = nl80211_global_init,
	.global_deinit = nl80211_global_deinit,
	.init2 = wpa_driver_nl80211_init,
	.deinit = driver_nl80211_deinit,
	.get_capa = wpa_driver_nl80211_get_capa,
	.set_operstate = wpa_driver_nl80211_set_operstate,
	.set_supp_port = wpa_driver_nl80211_set_supp_port,
	.set_country = wpa_driver_nl80211_set_country,
	.get_country = wpa_driver_nl80211_get_country,
	.set_ap = wpa_driver_nl80211_set_ap,
	.set_acl = wpa_driver_nl80211_set_acl,
	.if_add = wpa_driver_nl80211_if_add,
	.if_remove = driver_nl80211_if_remove,
	.send_mlme = driver_nl80211_send_mlme,
	.get_hw_feature_data = nl80211_get_hw_feature_data,
	.sta_add = wpa_driver_nl80211_sta_add,
	.sta_remove = driver_nl80211_sta_remove,
	.tx_control_port = nl80211_tx_control_port,
	.hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
	.sta_set_flags = wpa_driver_nl80211_sta_set_flags,
	.sta_set_airtime_weight = driver_nl80211_sta_set_airtime_weight,
	.hapd_init = i802_init,
	.hapd_deinit = i802_deinit,
	.set_wds_sta = i802_set_wds_sta,
	.get_seqnum = i802_get_seqnum,
	.flush = i802_flush,
	.get_inact_sec = i802_get_inact_sec,
	.sta_clear_stats = i802_sta_clear_stats,
	.set_rts = i802_set_rts,
	.set_frag = i802_set_frag,
	.set_tx_queue_params = i802_set_tx_queue_params,
	.set_sta_vlan = driver_nl80211_set_sta_vlan,
	.sta_deauth = i802_sta_deauth,
	.sta_disassoc = i802_sta_disassoc,
	.read_sta_data = driver_nl80211_read_sta_data,
	.set_freq = i802_set_freq,
	.send_action = driver_nl80211_send_action,
	.send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
	.remain_on_channel = wpa_driver_nl80211_remain_on_channel,
	.cancel_remain_on_channel =
	wpa_driver_nl80211_cancel_remain_on_channel,
	.probe_req_report = driver_nl80211_probe_req_report,
	.deinit_ap = wpa_driver_nl80211_deinit_ap,
	.deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
	.resume = wpa_driver_nl80211_resume,
	.signal_monitor = nl80211_signal_monitor,
	.signal_poll = nl80211_signal_poll,
	.mlo_signal_poll = nl80211_mlo_signal_poll,
	.channel_info = nl80211_channel_info,
	.set_param = nl80211_set_param,
	.get_radio_name = nl80211_get_radio_name,
	.add_pmkid = nl80211_add_pmkid,
	.remove_pmkid = nl80211_remove_pmkid,
	.flush_pmkid = nl80211_flush_pmkid,
	.set_rekey_info = nl80211_set_rekey_info,
	.poll_client = nl80211_poll_client,
	.set_p2p_powersave = nl80211_set_p2p_powersave,
	.start_dfs_cac = nl80211_start_radar_detection,
	.stop_ap = wpa_driver_nl80211_stop_ap,
#ifdef CONFIG_TDLS
	.send_tdls_mgmt = nl80211_send_tdls_mgmt,
	.tdls_oper = nl80211_tdls_oper,
	.tdls_enable_channel_switch = nl80211_tdls_enable_channel_switch,
	.tdls_disable_channel_switch = nl80211_tdls_disable_channel_switch,
#endif /* CONFIG_TDLS */
	.update_ft_ies = wpa_driver_nl80211_update_ft_ies,
	.update_dh_ie = nl80211_update_dh_ie,
	.get_mac_addr = wpa_driver_nl80211_get_macaddr,
	.get_survey = wpa_driver_nl80211_get_survey,
	.status = wpa_driver_nl80211_status,
	.switch_channel = nl80211_switch_channel,
#ifdef CONFIG_IEEE80211AX
	.switch_color = nl80211_switch_color,
#endif /* CONFIG_IEEE80211AX */
#ifdef ANDROID_P2P
	.set_noa = wpa_driver_set_p2p_noa,
	.get_noa = wpa_driver_get_p2p_noa,
	.set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
#endif /* ANDROID_P2P */
#ifdef ANDROID
#ifndef ANDROID_LIB_STUB
	.driver_cmd = wpa_driver_nl80211_driver_cmd,
#endif /* !ANDROID_LIB_STUB */
#endif /* ANDROID */
	.vendor_cmd = nl80211_vendor_cmd,
	.set_qos_map = nl80211_set_qos_map,
	.get_wowlan = nl80211_get_wowlan,
	.set_wowlan = nl80211_set_wowlan,
	.set_mac_addr = nl80211_set_mac_addr,
#ifdef CONFIG_MESH
	.init_mesh = wpa_driver_nl80211_init_mesh,
	.join_mesh = wpa_driver_nl80211_join_mesh,
	.leave_mesh = wpa_driver_nl80211_leave_mesh,
	.probe_mesh_link = nl80211_probe_mesh_link,
#endif /* CONFIG_MESH */
	.br_add_ip_neigh = wpa_driver_br_add_ip_neigh,
	.br_delete_ip_neigh = wpa_driver_br_delete_ip_neigh,
	.br_port_set_attr = wpa_driver_br_port_set_attr,
	.br_set_net_param = wpa_driver_br_set_net_param,
	.add_tx_ts = nl80211_add_ts,
	.del_tx_ts = nl80211_del_ts,
	.get_ifindex = nl80211_get_ifindex,
#ifdef CONFIG_DRIVER_NL80211_QCA
	.roaming = nl80211_roaming,
	.disable_fils = nl80211_disable_fils,
	.set_band = nl80211_set_band,
	.get_pref_freq_list = nl80211_get_pref_freq_list,
	.set_prob_oper_freq = nl80211_set_prob_oper_freq,
	.p2p_lo_start = nl80211_p2p_lo_start,
	.p2p_lo_stop = nl80211_p2p_lo_stop,
	.set_default_scan_ies = nl80211_set_default_scan_ies,
	.set_tdls_mode = nl80211_set_tdls_mode,
#ifdef CONFIG_MBO
	.get_bss_transition_status = nl80211_get_bss_transition_status,
	.ignore_assoc_disallow = nl80211_ignore_assoc_disallow,
#endif /* CONFIG_MBO */
	.set_bssid_tmp_disallow = nl80211_set_bssid_tmp_disallow,
	.add_sta_node = nl80211_add_sta_node,
#ifdef CONFIG_PASN
	.send_pasn_resp = nl80211_send_pasn_resp,
	.set_secure_ranging_ctx = nl80211_set_secure_ranging_ctx,
#endif /* CONFIG_PASN */
#endif /* CONFIG_DRIVER_NL80211_QCA */
	.do_acs = nl80211_do_acs,
	.configure_data_frame_filters = nl80211_configure_data_frame_filters,
	.get_ext_capab = nl80211_get_ext_capab,
	.get_mld_capab = nl80211_get_mld_capab,
	.update_connect_params = nl80211_update_connection_params,
	.send_external_auth_status = nl80211_send_external_auth_status,
	.set_4addr_mode = nl80211_set_4addr_mode,
#ifdef CONFIG_DPP
	.dpp_listen = nl80211_dpp_listen,
#endif /* CONFIG_DPP */
	.get_sta_mlo_info = nl80211_get_sta_mlo_info,
	.link_add = nl80211_link_add,
#ifdef CONFIG_IEEE80211BE
	.link_remove = driver_nl80211_link_remove,
	.is_drv_shared = nl80211_is_drv_shared,
	.link_sta_remove = wpa_driver_nl80211_link_sta_remove,
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_TESTING_OPTIONS
	.register_frame = testing_nl80211_register_frame,
	.radio_disable = testing_nl80211_radio_disable,
#endif /* CONFIG_TESTING_OPTIONS */
};

在 wpa_supplicant 加载时会调用 select_driver 函数,这里会调用驱动的global_init,对应上面驱动 ops 结构体的 nl80211_global_init 函数

\wpa_supplicant\wpa_supplicant.c

\src\drivers\driver_nl80211.c

这里首先注册连接和断连回调,然后调用 netlink_init

\src\drivers\netlink.c

这里面初始化一个 socket 文件描述符,然后监听其读事件,这个 PF_NETLINK 是用于管理连接的

\src\drivers\driver_nl80211.c

wpa_driver_nl80211_init_nl_global 注册了全局事件处理回调和与内核通信的文件描述符

这个文件描述符用于监听内核事件

这里会设置缓冲区大小并将文件描述符设置为非阻塞

回到全局初始化函数

这里注册的 PF_INET socket 是用来向内核发送命令数据的

来看看wpa_driver_nl80211_init_nl_global 中注册的接收事件的回调

\src\drivers\driver_nl80211.c

收到来自内核的事件就会去调用这个函数

int process_global_event(struct nl_msg *msg, void *arg)
{
	struct nl80211_global *global = arg;
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *tb[NL80211_ATTR_MAX + 1];
	struct wpa_driver_nl80211_data *drv, *tmp;
	int ifidx = -1, wiphy_idx = -1, wiphy_idx_rx = -1;
	struct i802_bss *bss;
	u64 wdev_id = 0;
	int wdev_id_set = 0;
	int wiphy_idx_set = 0;
	bool processed = false;

	/* Event marker, all prior events have been processed */
	if (gnlh->cmd == NL80211_CMD_GET_PROTOCOL_FEATURES) {
		u32 seq = nlmsg_hdr(msg)->nlmsg_seq;

		dl_list_for_each_safe(drv, tmp, &global->interfaces,
				      struct wpa_driver_nl80211_data, list) {
			if (drv->ignore_next_local_deauth > 0 &&
			    drv->ignore_next_local_deauth <= seq) {
				wpa_printf(MSG_DEBUG,
					   "nl80211: No DEAUTHENTICATE event was ignored");
				drv->ignore_next_local_deauth = 0;
			}

			if (drv->ignore_next_local_disconnect > 0 &&
			    drv->ignore_next_local_disconnect <= seq) {
				wpa_printf(MSG_DEBUG,
					   "nl80211: No DISCONNECT event was ignored");
				drv->ignore_next_local_disconnect = 0;
			}
		}

		return NL_SKIP;
	}

	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	if (tb[NL80211_ATTR_IFINDEX])
		ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
	else if (tb[NL80211_ATTR_WDEV]) {
		wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
		wdev_id_set = 1;
	} else if (tb[NL80211_ATTR_WIPHY]) {
		wiphy_idx_rx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
		wiphy_idx_set = 1;
	}

	dl_list_for_each_safe(drv, tmp, &global->interfaces,
			      struct wpa_driver_nl80211_data, list) {
		for (bss = drv->first_bss; bss; bss = bss->next) {
			if (wiphy_idx_set)
				wiphy_idx = nl80211_get_wiphy_index(bss);
			if ((ifidx == -1 && !wiphy_idx_set && !wdev_id_set) ||
			    ifidx == bss->ifindex ||
			    (wiphy_idx_set && wiphy_idx == wiphy_idx_rx) ||
			    (wdev_id_set && bss->wdev_id_set &&
			     wdev_id == bss->wdev_id)) {
				processed = true;
				do_process_drv_event(bss, gnlh->cmd, tb);
				if (!wiphy_idx_set)
					return NL_SKIP;
				/* The driver instance could have been removed,
				 * e.g., due to NL80211_CMD_RADAR_DETECT event,
				 * so need to stop the loop if that has
				 * happened. */
				if (!nl80211_drv_in_list(global, drv))
					break;
			}
		}
	}

	if (processed)
		return NL_SKIP;

	wpa_printf(MSG_DEBUG,
		   "nl80211: Ignored event %d (%s) for foreign interface (ifindex %d wdev 0x%llx wiphy %d)",
		   gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
		   ifidx, (long long unsigned int) wdev_id, wiphy_idx_rx);

	return NL_SKIP;
}

这个函数会根据不同的驱动命令种类进行不同的处理,这些都是 wifi 的一些核心功能事件



static void do_process_drv_event(struct i802_bss *bss, int cmd,
				 struct nlattr **tb)
{
	struct wpa_driver_nl80211_data *drv = bss->drv;
	int external_scan_event = 0;
	struct nlattr *frame = tb[NL80211_ATTR_FRAME];

	wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
		   cmd, nl80211_command_to_string(cmd), bss->ifname);

#ifdef CONFIG_DRIVER_NL80211_QCA
	if (cmd == NL80211_CMD_ROAM &&
	    (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
		if (drv->pending_roam_data) {
			wpa_printf(MSG_DEBUG,
				   "nl80211: Process pending roam+auth vendor event");
			qca_nl80211_key_mgmt_auth(drv, drv->pending_roam_data,
						  drv->pending_roam_data_len);
			os_free(drv->pending_roam_data);
			drv->pending_roam_data = NULL;
			return;
		}
		/*
		 * Device will use roam+auth vendor event to indicate
		 * roaming, so ignore the regular roam event.
		 */
		drv->roam_indication_done = true;
		wpa_printf(MSG_DEBUG,
			   "nl80211: Ignore roam event (cmd=%d), device will use vendor event roam+auth",
			   cmd);
		return;
	}
#endif /* CONFIG_DRIVER_NL80211_QCA */

	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
	    (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
	     cmd == NL80211_CMD_SCAN_ABORTED))
		nl80211_restore_ap_mode(bss);

	switch (cmd) {
	case NL80211_CMD_TRIGGER_SCAN:
		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
		drv->scan_state = SCAN_STARTED;
		if (drv->scan_for_auth) {
			/*
			 * Cannot indicate EVENT_SCAN_STARTED here since we skip
			 * EVENT_SCAN_RESULTS in scan_for_auth case and the
			 * upper layer implementation could get confused about
			 * scanning state.
			 */
			wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
			break;
		}
		wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
		break;
	case NL80211_CMD_START_SCHED_SCAN:
		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
		drv->scan_state = SCHED_SCAN_STARTED;
		break;
	case NL80211_CMD_SCHED_SCAN_STOPPED:
		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
		drv->scan_state = SCHED_SCAN_STOPPED;
		wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
		break;
	case NL80211_CMD_NEW_SCAN_RESULTS:
		wpa_dbg(drv->ctx, MSG_DEBUG,
			"nl80211: New scan results available");
		if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
			drv->scan_state = SCAN_COMPLETED;
		drv->scan_complete_events = 1;
		if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
			eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
					     drv, drv->ctx);
			drv->last_scan_cmd = 0;
		} else {
			external_scan_event = 1;
		}
		send_scan_event(drv, 0, tb, external_scan_event);
		break;
	case NL80211_CMD_SCHED_SCAN_RESULTS:
		wpa_dbg(drv->ctx, MSG_DEBUG,
			"nl80211: New sched scan results available");
		drv->scan_state = SCHED_SCAN_RESULTS;
		send_scan_event(drv, 0, tb, 0);
		break;
	case NL80211_CMD_SCAN_ABORTED:
		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
		if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
			drv->scan_state = SCAN_ABORTED;
		if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
			/*
			 * Need to indicate that scan results are available in
			 * order not to make wpa_supplicant stop its scanning.
			 */
			eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
					     drv, drv->ctx);
			drv->last_scan_cmd = 0;
		} else {
			external_scan_event = 1;
		}
		send_scan_event(drv, 1, tb, external_scan_event);
		break;
	case NL80211_CMD_AUTHENTICATE:
	case NL80211_CMD_ASSOCIATE:
	case NL80211_CMD_DEAUTHENTICATE:
	case NL80211_CMD_DISASSOCIATE:
	case NL80211_CMD_FRAME:
	case NL80211_CMD_FRAME_TX_STATUS:
	case NL80211_CMD_UNPROT_DEAUTHENTICATE:
	case NL80211_CMD_UNPROT_DISASSOCIATE:
		mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
			   tb[NL80211_ATTR_COOKIE],
			   tb[NL80211_ATTR_RX_SIGNAL_DBM],
			   tb[NL80211_ATTR_STA_WME],
			   tb[NL80211_ATTR_REQ_IE],
			   tb[NL80211_ATTR_MLO_LINK_ID]);
		break;
	case NL80211_CMD_CONNECT:
	case NL80211_CMD_ROAM:
		mlme_event_connect(drv, cmd, false,
				   tb[NL80211_ATTR_STATUS_CODE],
				   tb[NL80211_ATTR_MAC],
				   tb[NL80211_ATTR_REQ_IE],
				   tb[NL80211_ATTR_RESP_IE],
				   tb[NL80211_ATTR_TIMED_OUT],
				   tb[NL80211_ATTR_TIMEOUT_REASON],
				   NULL, NULL, NULL,
				   tb[NL80211_ATTR_FILS_KEK],
				   NULL,
				   tb[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM],
				   tb[NL80211_ATTR_PMK],
				   tb[NL80211_ATTR_PMKID],
				   tb[NL80211_ATTR_MLO_LINKS]);
		break;
	case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY:
		mlme_event_ch_switch(drv,
				     tb[NL80211_ATTR_IFINDEX],
				     tb[NL80211_ATTR_MLO_LINK_ID],
				     tb[NL80211_ATTR_WIPHY_FREQ],
				     tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
				     tb[NL80211_ATTR_CHANNEL_WIDTH],
				     tb[NL80211_ATTR_CENTER_FREQ1],
				     tb[NL80211_ATTR_CENTER_FREQ2],
				     tb[NL80211_ATTR_PUNCT_BITMAP],
				     0);
		break;
	case NL80211_CMD_CH_SWITCH_NOTIFY:
		mlme_event_ch_switch(drv,
				     tb[NL80211_ATTR_IFINDEX],
				     tb[NL80211_ATTR_MLO_LINK_ID],
				     tb[NL80211_ATTR_WIPHY_FREQ],
				     tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
				     tb[NL80211_ATTR_CHANNEL_WIDTH],
				     tb[NL80211_ATTR_CENTER_FREQ1],
				     tb[NL80211_ATTR_CENTER_FREQ2],
				     tb[NL80211_ATTR_PUNCT_BITMAP],
				     1);
		break;
	case NL80211_CMD_DISCONNECT:
		mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
				      tb[NL80211_ATTR_MAC],
				      tb[NL80211_ATTR_DISCONNECTED_BY_AP]);
		break;
	case NL80211_CMD_MICHAEL_MIC_FAILURE:
		mlme_event_michael_mic_failure(bss, tb);
		break;
	case NL80211_CMD_JOIN_IBSS:
		mlme_event_join_ibss(drv, tb);
		break;
	case NL80211_CMD_REMAIN_ON_CHANNEL:
		mlme_event_remain_on_channel(drv, 0, tb);
		break;
	case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:
		mlme_event_remain_on_channel(drv, 1, tb);
		break;
	case NL80211_CMD_NOTIFY_CQM:
		nl80211_cqm_event(drv, tb);
		break;
	case NL80211_CMD_REG_CHANGE:
	case NL80211_CMD_WIPHY_REG_CHANGE:
		nl80211_reg_change_event(drv, tb);
		break;
	case NL80211_CMD_REG_BEACON_HINT:
		nl80211_reg_beacon_hint_event(drv, tb);
		break;
	case NL80211_CMD_NEW_STATION:
		nl80211_new_station_event(drv, bss, tb);
		break;
	case NL80211_CMD_DEL_STATION:
		nl80211_del_station_event(drv, bss, tb);
		break;
	case NL80211_CMD_SET_REKEY_OFFLOAD:
		nl80211_rekey_offload_event(drv, tb);
		break;
	case NL80211_CMD_PMKSA_CANDIDATE:
		nl80211_pmksa_candidate_event(drv, tb);
		break;
	case NL80211_CMD_PROBE_CLIENT:
		nl80211_client_probe_event(drv, tb);
		break;
	case NL80211_CMD_TDLS_OPER:
		nl80211_tdls_oper_event(drv, tb);
		break;
	case NL80211_CMD_CONN_FAILED:
		nl80211_connect_failed_event(drv, tb);
		break;
	case NL80211_CMD_FT_EVENT:
		mlme_event_ft_event(drv, tb);
		break;
	case NL80211_CMD_RADAR_DETECT:
		nl80211_radar_event(drv, tb);
		break;
	case NL80211_CMD_STOP_AP:
		nl80211_stop_ap(drv, tb);
		break;
	case NL80211_CMD_VENDOR:
		nl80211_vendor_event(drv, tb);
		break;
	case NL80211_CMD_NEW_PEER_CANDIDATE:
		nl80211_new_peer_candidate(drv, tb);
		break;
	case NL80211_CMD_PORT_AUTHORIZED:
		nl80211_port_authorized(drv, tb);
		break;
	case NL80211_CMD_STA_OPMODE_CHANGED:
		nl80211_sta_opmode_change_event(drv, tb);
		break;
	case NL80211_CMD_UPDATE_OWE_INFO:
		mlme_event_dh_event(drv, bss, tb);
		break;
	case NL80211_CMD_UNPROT_BEACON:
		if (frame)
			mlme_event_unprot_beacon(drv, nla_data(frame),
						 nla_len(frame));
		break;
	case NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS:
		if (!frame)
			break;
		nl80211_control_port_frame_tx_status(bss,
						     nla_data(frame),
						     nla_len(frame),
						     tb[NL80211_ATTR_ACK],
						     tb[NL80211_ATTR_COOKIE]);
		break;
	case NL80211_CMD_FRAME_WAIT_CANCEL:
		nl80211_frame_wait_cancel(drv, tb[NL80211_ATTR_COOKIE]);
		break;
	case NL80211_CMD_ASSOC_COMEBACK:
		nl80211_assoc_comeback(drv, tb[NL80211_ATTR_MAC],
				       tb[NL80211_ATTR_TIMEOUT]);
		break;
#ifdef CONFIG_IEEE80211AX
	case NL80211_CMD_OBSS_COLOR_COLLISION:
	case NL80211_CMD_COLOR_CHANGE_STARTED:
	case NL80211_CMD_COLOR_CHANGE_ABORTED:
	case NL80211_CMD_COLOR_CHANGE_COMPLETED:
		nl80211_obss_color_event(bss, cmd, tb);
		break;
#endif /* CONFIG_IEEE80211AX */
	case NL80211_CMD_LINKS_REMOVED:
		wpa_supplicant_event(drv->ctx, EVENT_LINK_RECONFIG, NULL);
		break;
	default:
		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
			"(cmd=%d)", cmd);
		break;
	}
}

wpa_supplicant 加载时还会调用 wpas_init_driver

\wpa_supplicant\wpa_supplicant.c

这里会调用驱动的 init2 函数(前面提到的 ops 结构体)

\src\drivers\driver_nl80211.c

初始化 bss,这里主要是创建 bss 相关的与内核通信的文件描述符,在发起关联请求的时候就会用到这该文件描述符,并且会使用 precess_bss_event 这个回调来处理内核发来的 bss 相关事件

这里面做了 rfkill 相关的初始化

这里初始化 eapol 的 socket


http://www.kler.cn/a/593890.html

相关文章:

  • 当Anaconda的安装路径与我想创建的conda虚拟环境路径不一致时,应该怎么操作?
  • Docker Compose部署MantisBT
  • java学习笔记5
  • 智能AI流式输出的前端展现过程
  • 实现一个函数,将驼峰命名法的字符串转换为下划线命名法。
  • 剑指 Offer II 112. 最长递增路径
  • Java的表达式自动类型提升
  • Java操作RabbitMQ
  • 基于ArcGIS和ETOPO-2022 DEM数据分层绘制全球海陆分布
  • VLLM专题(三十一)—架构概述
  • 蓝桥杯十四届C++B组真题题解
  • 计算机网络基础:网络配置与管理
  • springboot实现文件上传到服务器上,并通过url访问
  • 批量将 PPT 转换为PDF/XPS/JPG图片等其它格式
  • 谈谈 CSS 中z - index属性的作用及在什么情况下会失效。
  • LVGL和其他图形库区别于联系
  • 1.环境搭建VUE+Spring boot
  • 「清华大学、北京大学」DeepSeek 课件PPT专栏
  • 小型状态机实现
  • Kubeasz工具快速部署K8Sv1.27版本集群(二进制方式)