记录wpa_supplicant启动过程
ini脚本:service wpa_supplicant /vendor/bin/hw/wpa_supplicant \ -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \ -I/vendor/etc/wifi/p2p_supplicant_overlay.conf -N \ -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ -I/vendor/etc/wifi/wpa_supplicant_overlay.conf \ -O/data/misc/wifi/sockets -puse_p2p_group_interface=1 -dd \ -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0# we will start as root and wpa_supplicant will switch to user wifi # after setting up the capabilities required for WEXT # user wifi # group wifi inet keystore class main socket wpa_wlan0 dgram 660 wifi wifi disabled oneshotexternal\wpa_supplicant_8\wpa_supplicant\main.cint main(int argc, char *argv[]){ int c, i; struct wpa_interface *ifaces, *iface; int iface_count, exitcode = -1; struct wpa_params params; struct wpa_global *global; if (os_program_init()) return -1; os_memset(¶ms, 0, sizeof(params)); params.wpa_debug_level = MSG_INFO; // 日志等级 iface = ifaces = os_zalloc(sizeof(struct wpa_interface)); if (ifaces == NULL) return -1; iface_count = 1; wpa_supplicant_fd_workaround(1); for (;;) { c = getopt(argc, argv, "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsS:TtuvW"); if (c < 0) break; switch (c) { case 'b': iface->bridge_ifname = optarg; break; case 'B': params.daemonize++; break; case 'c': // 配置文件 /data/misc/wifi/wpa_supplicant.conf iface->confname = optarg; break; case 'C': iface->ctrl_interface = optarg; break; case 'D': // 驱动 nl80211 iface->driver = optarg; break; case 'd':#ifdef CONFIG_NO_STDOUT_DEBUG printf("Debugging disabled with " "CONFIG_NO_STDOUT_DEBUG=y build time " "option.\n"); goto out;#else /* CONFIG_NO_STDOUT_DEBUG */ params.wpa_debug_level--; break;#endif /* CONFIG_NO_STDOUT_DEBUG */ case 'e': // 加密文件 /data/misc/wifi/entropy.bin params.entropy_file = optarg; break;#ifdef CONFIG_DEBUG_FILE case 'f': params.wpa_debug_file_path = optarg; break;#endif /* CONFIG_DEBUG_FILE */ case 'g': // 接口 @android:wpa_wlan0 params.ctrl_interface = optarg; break; case 'G': params.ctrl_interface_group = optarg; break; case 'h': usage(); exitcode = 0; goto out; case 'i': // 接口名称 wlan0 iface->ifname = optarg; break; ...... default: usage(); exitcode = 0; goto out; } } exitcode = 0; global = wpa_supplicant_init(¶ms); // if (global == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant"); exitcode = -1; goto out; } else { wpa_printf(MSG_INFO, "Successfully initialized " "wpa_supplicant"); } if (fst_global_init()) { wpa_printf(MSG_ERROR, "Failed to initialize FST"); exitcode = -1; goto out; }#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE) if (!fst_global_add_ctrl(fst_ctrl_cli)) wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");#endif for (i = 0; exitcode == 0 && i < iface_count; i++) { struct wpa_supplicant *wpa_s; if ((ifaces[i].confname == NULL && ifaces[i].ctrl_interface == NULL) || ifaces[i].ifname == NULL) { if (iface_count == 1 && (params.ctrl_interface ||#ifdef CONFIG_MATCH_IFACE params.match_iface_count ||#endif /* CONFIG_MATCH_IFACE */ params.dbus_ctrl_interface)) break; usage(); exitcode = -1; break; } wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL); // 添加接口 if (wpa_s == NULL) { exitcode = -1; break; } }#ifdef CONFIG_MATCH_IFACE if (exitcode == 0) exitcode = wpa_supplicant_init_match(global);#endif /* CONFIG_MATCH_IFACE */ if (exitcode == 0) exitcode = wpa_supplicant_run(global); // 启动eloop,监听wpa的事件 wpa_supplicant_deinit(global); fst_global_deinit();out: wpa_supplicant_fd_workaround(0); os_free(ifaces);#ifdef CONFIG_MATCH_IFACE os_free(params.match_ifaces);#endif /* CONFIG_MATCH_IFACE */ os_free(params.pid_file); os_program_deinit(); return exitcode;}external\wpa_supplicant_8\wpa_supplicant\wpa_supplicant.cstruct wpa_global * wpa_supplicant_init(struct wpa_params *params){ struct wpa_global *global; int ret, i; if (params == NULL) return NULL;#ifdef CONFIG_DRIVER_NDIS { void driver_ndis_init_ops(void); driver_ndis_init_ops(); }#endif /* CONFIG_DRIVER_NDIS */#ifndef CONFIG_NO_WPA_MSG wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);#endif /* CONFIG_NO_WPA_MSG */ // 如果没有设置debug文件,将日志写道stdout if (params->wpa_debug_file_path) wpa_debug_open_file(params->wpa_debug_file_path); else wpa_debug_setup_stdout(); if (params->wpa_debug_syslog) wpa_debug_open_syslog(); if (params->wpa_debug_tracing) { ret = wpa_debug_open_linux_tracing(); if (ret) { wpa_printf(MSG_ERROR, "Failed to enable trace logging"); return NULL; } } // 注册eap方法,是一个链表,将支持的eap方法添加到链表中 ret = eap_register_methods(); // 注册eap方法 if (ret) { wpa_printf(MSG_ERROR, "Failed to register EAP methods"); if (ret == -2) wpa_printf(MSG_ERROR, "Two or more EAP methods used " "the same EAP type."); return NULL; } global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; dl_list_init(&global->p2p_srv_bonjour); dl_list_init(&global->p2p_srv_upnp); /// 将启动参数添加到global->params中 global->params.daemonize = params->daemonize; global->params.wait_for_monitor = params->wait_for_monitor; global->params.dbus_ctrl_interface = params->dbus_ctrl_interface; if (params->pid_file) global->params.pid_file = os_strdup(params->pid_file); if (params->ctrl_interface) global->params.ctrl_interface = os_strdup(params->ctrl_interface); if (params->ctrl_interface_group) global->params.ctrl_interface_group = os_strdup(params->ctrl_interface_group); if (params->override_driver) global->params.override_driver = os_strdup(params->override_driver); if (params->override_ctrl_interface) global->params.override_ctrl_interface = os_strdup(params->override_ctrl_interface);#ifdef CONFIG_MATCH_IFACE global->params.match_iface_count = params->match_iface_count; if (params->match_iface_count) { global->params.match_ifaces = os_calloc(params->match_iface_count, sizeof(struct wpa_interface)); os_memcpy(global->params.match_ifaces, params->match_ifaces, params->match_iface_count * sizeof(struct wpa_interface)); }#endif /* CONFIG_MATCH_IFACE */#ifdef CONFIG_P2P if (params->conf_p2p_dev) global->params.conf_p2p_dev = os_strdup(params->conf_p2p_dev);#endif /* CONFIG_P2P */ wpa_debug_level = global->params.wpa_debug_level = params->wpa_debug_level; wpa_debug_show_keys = global->params.wpa_debug_show_keys = params->wpa_debug_show_keys; wpa_debug_timestamp = global->params.wpa_debug_timestamp = params->wpa_debug_timestamp;#ifdef CONFIG_HIDL if (params->hidl_service_name) global->params.hidl_service_name = os_strdup(params->hidl_service_name);#endif /* CONFIG_HIDL */ wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR); if (eloop_init()) { wpa_printf(MSG_ERROR, "Failed to initialize event loop"); wpa_supplicant_deinit(global); return NULL; } // 随机数 random_init(params->entropy_file); global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global); if (global->ctrl_iface == NULL) { wpa_supplicant_deinit(global); return NULL; } if (wpas_notify_supplicant_initialized(global)) { wpa_supplicant_deinit(global); return NULL; } // wpa_drivers记录了不同接口的操作方法。 for (i = 0; wpa_drivers[i]; i++) global->drv_count++; if (global->drv_count == 0) { wpa_printf(MSG_ERROR, "No drivers enabled"); wpa_supplicant_deinit(global); return NULL; } global->drv_priv = os_zalloc(global->drv_count * sizeof(void *)); if (global->drv_priv == NULL) { wpa_supplicant_deinit(global); return NULL; }#ifdef CONFIG_WIFI_DISPLAY if (wifi_display_init(global) < 0) { wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display"); wpa_supplicant_deinit(global); return NULL; }#endif /* CONFIG_WIFI_DISPLAY */ eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0, wpas_periodic, global, NULL);#ifdef CONFIG_WAPI if (wapi_asue_init()) { wpa_printf(MSG_ERROR, "wapi: wapi_asue_init fail\n"); return NULL; }#endif return global;}external\wpa_supplicant_8\src\drivers\drivers.cconst struct wpa_driver_ops *const wpa_drivers[] ={#ifdef CONFIG_DRIVER_NL80211 &wpa_driver_nl80211_ops,#endif /* CONFIG_DRIVER_NL80211 */#ifdef CONFIG_DRIVER_WEXT &wpa_driver_wext_ops,#endif /* CONFIG_DRIVER_WEXT */#ifdef CONFIG_DRIVER_HOSTAP &wpa_driver_hostap_ops,#endif /* CONFIG_DRIVER_HOSTAP */#ifdef CONFIG_DRIVER_BSD &wpa_driver_bsd_ops,#endif /* CONFIG_DRIVER_BSD */#ifdef CONFIG_DRIVER_OPENBSD &wpa_driver_openbsd_ops,#endif /* CONFIG_DRIVER_OPENBSD */#ifdef CONFIG_DRIVER_NDIS &wpa_driver_ndis_ops,#endif /* CONFIG_DRIVER_NDIS */#ifdef CONFIG_DRIVER_WIRED &wpa_driver_wired_ops,#endif /* CONFIG_DRIVER_WIRED */#ifdef CONFIG_DRIVER_MACSEC_LINUX &wpa_driver_macsec_linux_ops,#endif /* CONFIG_DRIVER_MACSEC_LINUX */#ifdef CONFIG_DRIVER_MACSEC_QCA &wpa_driver_macsec_qca_ops,#endif /* CONFIG_DRIVER_MACSEC_QCA */#ifdef CONFIG_DRIVER_ROBOSWITCH &wpa_driver_roboswitch_ops,#endif /* CONFIG_DRIVER_ROBOSWITCH */#ifdef CONFIG_DRIVER_ATHEROS &wpa_driver_atheros_ops,#endif /* CONFIG_DRIVER_ATHEROS */#ifdef CONFIG_DRIVER_NONE &wpa_driver_none_ops,#endif /* CONFIG_DRIVER_NONE */ NULL};对应驱动函数external\wpa_supplicant_8\src\drivers\driver_nl80211.cconst 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_results2 = 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, .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol, .sta_set_flags = wpa_driver_nl80211_sta_set_flags, .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,...}struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, struct wpa_interface *iface, struct wpa_supplicant *parent){ struct wpa_supplicant *wpa_s; struct wpa_interface t_iface; struct wpa_ssid *ssid; if (global == NULL || iface == NULL) return NULL; wpa_s = wpa_supplicant_alloc(parent); if (wpa_s == NULL) return NULL; wpa_s->global = global; t_iface = *iface; if (global->params.override_driver) { wpa_printf(MSG_DEBUG, "Override interface parameter: driver " "('%s' -> '%s')", iface->driver, global->params.override_driver); t_iface.driver = global->params.override_driver; } if (global->params.override_ctrl_interface) { wpa_printf(MSG_DEBUG, "Override interface parameter: " "ctrl_interface ('%s' -> '%s')", iface->ctrl_interface, global->params.override_ctrl_interface); t_iface.ctrl_interface = global->params.override_ctrl_interface; } if (wpa_supplicant_init_iface(wpa_s, &t_iface)) { wpa_printf(MSG_DEBUG, "Failed to add interface %s", iface->ifname); wpa_supplicant_deinit_iface(wpa_s, 0, 0); return NULL; } /* Notify the control interfaces about new iface */ if (wpas_notify_iface_added(wpa_s)) { wpa_supplicant_deinit_iface(wpa_s, 1, 0); return NULL; } /* Notify the control interfaces about new networks for non p2p mgmt * ifaces. */ if (iface->p2p_mgmt == 0) { for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) wpas_notify_network_added(wpa_s, ssid); } wpa_s->next = global->ifaces; global->ifaces = wpa_s; wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);#ifdef CONFIG_P2P if (wpa_s->global->p2p == NULL && !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) && wpas_p2p_add_p2pdev_interface( wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) { wpa_printf(MSG_INFO, "P2P: Failed to enable P2P Device interface"); /* Try to continue without. P2P will be disabled. */ }#endif /* CONFIG_P2P */ return wpa_s;}static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, struct wpa_interface *iface){ struct wpa_driver_capa capa; int capa_res; u8 dfs_domain; wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname, iface->confname ? iface->confname : "N/A", iface->driver ? iface->driver : "default", iface->ctrl_interface ? iface->ctrl_interface : "N/A", iface->bridge_ifname ? iface->bridge_ifname : "N/A"); if (iface->confname) {#ifdef CONFIG_BACKEND_FILE wpa_s->confname = os_rel2abs_path(iface->confname); if (wpa_s->confname == NULL) { wpa_printf(MSG_ERROR, "Failed to get absolute path " "for configuration file '%s'.", iface->confname); return -1; } wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'", iface->confname, wpa_s->confname);#else /* CONFIG_BACKEND_FILE */ wpa_s->confname = os_strdup(iface->confname);#endif /* CONFIG_BACKEND_FILE */ // 读取conf文件 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL); if (wpa_s->conf == NULL) { wpa_printf(MSG_ERROR, "Failed to read or parse " "configuration '%s'.", wpa_s->confname); return -1; } // 为什么还有一个文件 wpa_s->confanother = os_rel2abs_path(iface->confanother); wpa_config_read(wpa_s->confanother, wpa_s->conf); }} external\wpa_supplicant_8\wpa_supplicant\wpa_supplicant.cint wpa_supplicant_run(struct wpa_global *global){ struct wpa_supplicant *wpa_s; if (global->params.daemonize && (wpa_supplicant_daemon(global->params.pid_file) || eloop_sock_requeue())) return -1;#ifdef CONFIG_MATCH_IFACE if (wpa_supplicant_match_existing(global)) return -1;#endif if (global->params.wait_for_monitor) { for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt) wpa_supplicant_ctrl_iface_wait( wpa_s->ctrl_iface); } eloop_register_signal_terminate(wpa_supplicant_terminate, global); eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); eloop_run(); return 0;}external\wpa_supplicant_8\wpa_supplicant\src\utils\eloop.cvoid eloop_run(void){#ifdef CONFIG_ELOOP_POLL int num_poll_fds; int timeout_ms = 0;#endif /* CONFIG_ELOOP_POLL */#ifdef CONFIG_ELOOP_SELECT fd_set *rfds, *wfds, *efds; struct timeval _tv;#endif /* CONFIG_ELOOP_SELECT */#ifdef CONFIG_ELOOP_EPOLL int timeout_ms = -1;#endif /* CONFIG_ELOOP_EPOLL */#ifdef CONFIG_ELOOP_KQUEUE struct timespec ts;#endif /* CONFIG_ELOOP_KQUEUE */ int res; struct os_reltime tv, now;#ifdef CONFIG_ELOOP_SELECT rfds = os_malloc(sizeof(*rfds)); wfds = os_malloc(sizeof(*wfds)); efds = os_malloc(sizeof(*efds)); if (rfds == NULL || wfds == NULL || efds == NULL) goto out;#endif /* CONFIG_ELOOP_SELECT */ while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0)) { struct eloop_timeout *timeout; if (eloop.pending_terminate) { /* * This may happen in some corner cases where a signal * is received during a blocking operation. We need to * process the pending signals and exit if requested to * avoid hitting the SIGALRM limit if the blocking * operation took more than two seconds. */ eloop_process_pending_signals(); if (eloop.terminate) break; } timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_reltime(&now); if (os_reltime_before(&now, &timeout->time)) os_reltime_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0;#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) timeout_ms = tv.sec * 1000 + tv.usec / 1000;#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */#ifdef CONFIG_ELOOP_SELECT _tv.tv_sec = tv.sec; _tv.tv_usec = tv.usec;#endif /* CONFIG_ELOOP_SELECT */#ifdef CONFIG_ELOOP_KQUEUE ts.tv_sec = tv.sec; ts.tv_nsec = tv.usec * 1000L;#endif /* CONFIG_ELOOP_KQUEUE */ }#ifdef CONFIG_ELOOP_POLL // 将事件添加到监听队列里面 num_poll_fds = eloop_sock_table_set_fds( &eloop.readers, &eloop.writers, &eloop.exceptions, eloop.pollfds, eloop.pollfds_map, eloop.max_pollfd_map); // 监听事件变化 res = poll(eloop.pollfds, num_poll_fds, timeout ? timeout_ms : -1);#endif /* CONFIG_ELOOP_POLL */#ifdef CONFIG_ELOOP_SELECT // 将事件添加到监听队列里面 eloop_sock_table_set_fds(&eloop.readers, rfds); eloop_sock_table_set_fds(&eloop.writers, wfds); eloop_sock_table_set_fds(&eloop.exceptions, efds); // 监听事件变化 res = select(eloop.max_sock + 1, rfds, wfds, efds, timeout ? &_tv : NULL);#endif /* CONFIG_ELOOP_SELECT */#ifdef CONFIG_ELOOP_EPOLL if (eloop.count == 0) { res = 0; } else { res = epoll_wait(eloop.epollfd, eloop.epoll_events, eloop.count, timeout_ms); }#endif /* CONFIG_ELOOP_EPOLL */#ifdef CONFIG_ELOOP_KQUEUE if (eloop.count == 0) { res = 0; } else { res = kevent(eloop.kqueuefd, NULL, 0, eloop.kqueue_events, eloop.kqueue_nevents, timeout ? &ts : NULL); }#endif /* CONFIG_ELOOP_KQUEUE */ if (res < 0 && errno != EINTR && errno != 0) { wpa_printf(MSG_ERROR, "eloop: %s: %s",#ifdef CONFIG_ELOOP_POLL "poll"#endif /* CONFIG_ELOOP_POLL */#ifdef CONFIG_ELOOP_SELECT "select"#endif /* CONFIG_ELOOP_SELECT */#ifdef CONFIG_ELOOP_EPOLL "epoll"#endif /* CONFIG_ELOOP_EPOLL */#ifdef CONFIG_ELOOP_KQUEUE "kqueue"#endif /* CONFIG_ELOOP_EKQUEUE */ , strerror(errno)); goto out; } eloop.readers.changed = 0; eloop.writers.changed = 0; eloop.exceptions.changed = 0; eloop_process_pending_signals();...... } eloop.terminate = 0;out:#ifdef CONFIG_ELOOP_SELECT os_free(rfds); os_free(wfds); os_free(efds);#endif /* CONFIG_ELOOP_SELECT */ return;}