• 【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_ 前缀

  • 相关阅读:
    每日一题·729.我的日程安排表
    软考复习(二):操作系统
    div中包含checkbox 点击事件重复问题
    11、JavaWeb启程——会话跟踪技术Cookie&Session
    Linux系统下的硬盘分区与挂载
    智慧安防/视频分析云平台EasyCVR不显示告警图片该如何解决?
    2022数学建模国赛降至,整理了一些很不错的在线网站分享一下
    虚拟DOM与diff算法
    软件考试:计算机组成原理:程序的运行过程
    【Python】模拟windows文件名排序
  • 原文地址:https://blog.csdn.net/AngryDog1024/article/details/125463074