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