• 【wpa_supplicant】driver如何告诉supplicant自己做的一些事情以及结果


    按之前计划的,这期我们来看 driver如何告诉supplicant自己(被要求)做的一些事情以及结果

    老样子,adb logcat -c /adb logcat -s wpa_supplicant
    会发现如下的类似打印

    06-24 11:58:41.768 31436 31436 D wpa_supplicant: nl80211: Drv Event 33 (NL80211_CMD_TRIGGER_SCAN) received for wlan0

    于是我们定位了 driver与supplicant通信的关键一环

    还记得之前 wpa_supplicant 初始化过程中调用的 nl80211_global_init 吗

    	nl80211_global_init           //上述的 global_init
    		global->netlink = netlink_init(cfg);
    		wpa_driver_nl80211_init_nl_global(global)
    			//这里涉及到 netlink 的使用,没必要深究
    			nl80211_register_eloop_read(&global->nl_event, wpa_driver_nl80211_event_receive, global->nl_cb, 0);
    				eloop_register_read_sock(nl_socket_get_fd(*handle), wpa_driver_nl80211_event_receive, global->nl_cb, *handle); // 所以我们知道通过netlink报过来的事件都由  wpa_driver_nl80211_event_receive 处理
    		global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里其实描述的有些错误
    在 nl80211_register_eloop_read 之前有一行

    nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_global_event, global);

    目前看不大懂,但大致能猜到这是设置 netlink80211 报上来事件时会调用的回调函数

    int process_global_event(struct nl_msg *msg, void *arg)
    	dl_list_for_each_safe(drv, tmp, &global->interfaces, struct wpa_driver_nl80211_data, list) {
    		for (bss = drv->first_bss; bss; bss = bss->next) {
    			do_process_drv_event(bss, gnlh->cmd, tb);
    			return NL_SKIP;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    遍历每个 interface 的每个bss,处理nl80211报上来的事件

    static void do_process_drv_event(struct i802_bss *bss, int cmd, struct nlattr **tb) {
    	wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s", cmd, nl80211_command_to_string(cmd), bss->ifname);
    	switch(cmd) {
    	 case NL80211_CMD_TRIGGER_SCAN:
    	 	wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
    	 	break;
    	 case ###:
    	 	mlme_event_###(###);
    	 	break;
    	 case ###:
    	 	nl80211_###(###);
    	 	break;
    	 default:
    	 	wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event (cmd=%d)", cmd);
    	 	break;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    对各种case的处理看起来有3类,实际最后的处理都是 wpa_supplicant
    wpa_supplicant_event 是一个800多行的函数,里面按 event_type 对各种事件做处理,事件相关的数据都放在wpa_event_data中传入
    do_process_drv_event 一定要做的事情就是 按事先沟通好的格式从 struct nlattr **tb 这个二维数组中取出数据,以便下一步处理

    以 NL80211_CMD_NEW_SCAN_RESULTS 为例我们看下 wpa_supplicant_event 的处理

    	case EVENT_SCAN_RESULTS:
    		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
    			wpa_s->scan_res_handler = NULL;
    			wpa_s->own_scan_running = 0;
    			wpa_s->radio->external_scan_req_interface = NULL;
    			wpa_s->last_scan_req = NORMAL_SCAN_REQ;
    			break;
    		}
    
    		if (!(data && data->scan_info.external_scan) &&
    		    os_reltime_initialized(&wpa_s->scan_start_time)) {
    			struct os_reltime now, diff;
    			os_get_reltime(&now);
    			os_reltime_sub(&now, &wpa_s->scan_start_time, &diff);
    			wpa_s->scan_start_time.sec = 0;
    			wpa_s->scan_start_time.usec = 0;
    			wpa_dbg(wpa_s, MSG_DEBUG, "Scan completed in %ld.%06ld seconds",
    				diff.sec, diff.usec);
    		}
    		if (wpa_supplicant_event_scan_results(wpa_s, data))
    			break; /* interface may have been removed */
    		if (!(data && data->scan_info.external_scan))
    			wpa_s->own_scan_running = 0;
    		if (data && data->scan_info.nl_scan_event)
    			wpa_s->radio->external_scan_req_interface = NULL;
    		radio_work_check_next(wpa_s);
    		break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    可以看出 wpa_supplicant_event 会根据事件类型调用 更多 wpa_supplicant_event_ 前缀的api

    就看到这里吧。
    有一点感悟是 supplicant 的架构设计很严苛,牢记每一层 api 的前缀可以帮助读者很快掌握每个函数应该做到的事情
    例如,supplicant通报fwk事件的api大部分都有 wpas_notify 前缀,再比如这期我们看到的 wpa_supplicant_event 则是supplicant自己内部的处理,nl80211的一些ops都是 nl80211_ 前缀

  • 相关阅读:
    眼内衍射透镜的设计与分析
    【Orangepi Zero2 全志H616】驱动串口实现Tik Tok—VUI(语音交互)
    基于JAVA中小企业人力资源管理系统计算机毕业设计源码+系统+数据库+lw文档+部署
    1413. Minimum Value to Get Positive Step by Step Sum
    前端小白是如何利用chatgt用一周时间从做一款微信小程序的
    idea自动添加作者、日期等信息
    Spring Boot框架的原理及应用详解(七)
    SpreadJS 15.1 CN 与 SpreadJS 15.1 EN
    【整理】HTTP相关版本对比
    企业级大数据平台智能运维好帮手——星环科技多模数据平台监控软件Aquila Insight
  • 原文地址:https://blog.csdn.net/AngryDog1024/article/details/125463074