代碼地址:git clone https://w1.fi/hostap.git
我目前學的的版本是 wpa_supplicant 2.12-devel-hostap_2_11-857-g54930b62b+
五月份左右的提交,是較新的代碼
想做白盒測試。最近開始學習 wpa_supplicant 這個工具。
自學了一個多月吧。 整理了一些代碼跳轉,歡迎指正交流 長期更新
commit b01c4843bb7b785db5a4201f0dc0f30b2047a04d (origin/pending, origin/main, origin/HEAD, main) Author: Shivani Baranwal <quic_shivbara@quicinc.com> Date: Tue May 20 15:06:56 2025 +0530
整理的代碼跳轉
main.c :: main→ c=getopt(argc,argv,"b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); // 解析參數→ global = wpa_supplicant_init(¶ms); // 初始化全局 wpa_supplicant context→ driver_ndis_init_ops();// 初始話NDIS驅動→ ret = eap_register_methods();// 注冊EAP 方法→ eloop_init // 初始化事件循環→ eloop.epollfd = epoll_create1(0);// 創建epoll 實例→ eloop.kqueuefd = kqueue();// 創建kqueue實例→ eloop.readers.type = EVENT_TYPE_READ;// 讀事件類型→ eloop.writers.type = EVENT_TYPE_WRITE;// 寫事件類型→ eloop.exceptions.type = EVENT_TYPE_EXCEPTION;// 異常事件類型→ global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);→ wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL); // 注冊添加 接口 比如 wlan0→ wpa_s = wpa_supplicant_alloc(parent); // 分配新的wpa 結構體→ wpa_s->scan_req = INITIAL_SCAN_REQ; // 設置 初次掃描→ wpa_s->global = global; // 設置全局上下文→ if (wpa_supplicant_init_iface(wpa_s, &t_iface)) // 初始化新接口→ wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false); // 讀取并解析配置文件→ tail = head = config->ssid; // 初始化網絡配置鏈表指針→ cred_tail = cred_head = config->cred; // 初始化憑證鏈表指針→ identity_tail = identity_head = config->identity; // 初始化身份鏈表指針→ while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {→ ssid = wpa_config_read_network(f, &line, id++); // 讀取網絡配置塊→ if (wpa_config_add_prio_network(config, ssid)) { // 將網絡配置添加到優先級列表→ config->ssid = head; // 更新主配置結構體中的鏈表指針 → wpas_init_driver(wpa_s, iface) // 初始化驅動→ if (wpa_supplicant_set_driver(wpa_s, driver) < 0) // 設置驅動類型→ if (select_driver(wpa_s, i) == 0)→ wpa_drivers[i]->global_init && global->drv_priv[i] == NULL // 運行 driver 的 global_init => nl80211_global_init→ nl80211_global_init→ if (wpa_driver_nl80211_init_nl_global(global) < 0)→ global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); → nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_global_event, global); // 配置libnl回調 在執行nl_recvmsgs 會調用 process_global_event→ process_global_event→ do_process_drv_event(bss, gnlh->cmd, tb); // 調用實際處理函數處理事件 !!!! 函數中會在處理完netlink 中 響應的 觸發wpa_supplicane_event 以外面wpa 狀態機的狀態→ nl80211_register_eloop_read(&global->nl_event, // 將 wpa_driver_nl80211_event_receive 注冊為 Netlink socket (global->nl_event) 的可讀事件回調函數。wpa_driver_nl80211_event_receive, // !!!! 注冊 netlink 接收事件 用于接受驅動返回的數據global->nl_cb, 0);→ wpa_driver_nl80211_event_receive→ res = nl_recvmsgs(handle, cb); // 接收netlink 消息,并觸發回調→ wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname); // 初始化驅動接口→ wpa_s->driver->init2// 執行driver的init2→ wpa_s->driver->init2 :: wpa_driver_nl80211_init→ wpa_driver_nl80211_drv_init→ if (nl80211_init_bss(bss)) // 初始化 BSS 層資源→ if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params,p2p_mode))→ if (wpa_driver_nl80211_capa(drv)) // 獲取并設置驅動能力→ nl80211_set_param(bss, driver_params // // 設置驅動參數→ eloop_register_read_sock // 注冊socket 讀事件回調→ wpa_driver_nl80211_handle_eapol_tx_status→ wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);→ if (wpa_supplicant_init_wpa(wpa_s) < 0) // 初始化WPA 狀態機→ wpa_supplicant_req_scan(wpa_s, interface_count % 3,100000); // 觸發掃描→ eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL); // 注冊 新定時器→ wpa_supplicant_scan→ ret = wpa_supplicant_trigger_scan(wpa_s, scan_params, false, false); // 構造參數并下發到驅動→ radio_add_work(wpa_s, 0, "scan", next, wpas_trigger_scan_cb,ctx) // 將wpas_trigger_scan_cb添加到工作隊列→ ret = wpa_drv_scan(wpa_s, params);→ wpa_s->driver->scan2 // 調用驅動 執行scan-> wpa_driver_nl80211_scan // !!!! start scan 通過netlink 下發 異步等待netlink回復→ msg = nl80211_scan_common( // 構造 NL80211_CMD_TRIGGER_SCAN 消息,設置基本掃描參數bss, NL80211_CMD_TRIGGER_SCAN, params); → ret = send_and_recv_cmd(drv, msg); /// 發送Netlink消息并接收響應→ wpa_sm_set_param // 設置wpa相關參數 → if (wpa_supplicant_init_eapol(wpa_s) < 0) // 初始化 EAPOL→ exitcode = wpa_supplicant_run(global); // 啟動循環事件→ wpa_supplicant_daemon(global->params.pid_file // 設置守護進程→ eloop_register_signal_terminate(wpa_supplicant_terminate, global); // 注冊終止信號處理函數→ eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); // 注冊重新配置信號處理函數→ eloop_run() // 運行主事件循環→ wpa_supplicant_deinit // 事件循環退出,清理資源// cfg80211 反饋接收事件 處理
→ do_process_drv_event # 驅動標記 scan 已經開始→ case NL80211_CMD_TRIGGER_SCAN:→ drv->scan_state = SCAN_STARTED→ wpa_supplicant_event(bss->ctx, EVENT_SCAN_STARTED, NULL);# 驅動完成 scan 結果處理 → case NL80211_CMD_NEW_SCAN_RESULTS→ drv->scan_complete_events = 1;→ send_scan_event(bss, 0, tb, external_scan_event); // 上報掃描完成→ wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, &event); // 發送掃描結果事件到 wpa_supplicant// wpas 事件處理
→ wpa_supplicant_event → case EVENT_SCAN_RESULTS:→ if (wpa_supplicant_event_scan_results(wpa_s, data))→ res = _wpa_supplicant_event_scan_results(wpa_s, data, 1, 0);→ scan_res = wpa_supplicant_get_scan_results(wpa_s, // 獲取掃描結果data ? &data->scan_info :NULL, 1, NULL);→ wpas_select_network_from_last_scan(wpa_s, 1, own_request, // 從上次掃描結果中選擇網絡trigger_6ghz_scan, data);→ selected = wpa_supplicant_pick_network(wpa_s, &ssid); // 選擇合適網絡→ if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0) // 嘗試連接到選中網絡→ wpa_supplicant_associate(wpa_s, selected, ssid); // 發起關聯→ wpa_s->own_scan_running = 0; // 更新掃描狀態