代码地址: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; // 更新扫描状态