本文为《深入理解Android Wi-Fi、NFC和GPS卷》读书笔记,Android源码为Android 5.1

android-5.1/external/wpa_supplicant_8/wpa_supplicant/wpa_supplicant.c

static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,struct wpa_interface *iface)
{struct wpa_driver_capa capa;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 */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);/** Override ctrl_interface and driver_param if set on command* line.*/if (iface->ctrl_interface) {os_free(wpa_s->conf->ctrl_interface);wpa_s->conf->ctrl_interface =os_strdup(iface->ctrl_interface);}if (iface->driver_param) {os_free(wpa_s->conf->driver_param);wpa_s->conf->driver_param =os_strdup(iface->driver_param);}if (iface->p2p_mgmt && !iface->ctrl_interface) {os_free(wpa_s->conf->ctrl_interface);wpa_s->conf->ctrl_interface = NULL;}} elsewpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,iface->driver_param);if (wpa_s->conf == NULL) {wpa_printf(MSG_ERROR, "\nNo configuration found.");return -1;}if (iface->ifname == NULL) {wpa_printf(MSG_ERROR, "\nInterface name is required.");return -1;}if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",iface->ifname);return -1;}//将 wpa_interface 中的 ifname 复制到 wpa_supplicant 的 ifname 变量中os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));if (iface->bridge_ifname) {if (os_strlen(iface->bridge_ifname) >=sizeof(wpa_s->bridge_ifname)) {wpa_printf(MSG_ERROR, "\nToo long bridge interface ""name '%s'.", iface->bridge_ifname);return -1;}os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,sizeof(wpa_s->bridge_ifname));}/* RSNA Supplicant Key Management - INITIALIZE *///下面这两个函数和 EAPOL 状态机相关eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);eapol_sm_notify_portValid(wpa_s->eapol, FALSE);/* Initialize driver interface and register driver event handler before* L2 receive handler so that association events are processed before* EAPOL-Key packets if both become available for the same select()* call. *///初始化driverif (wpas_init_driver(wpa_s, iface) < 0)return -1;//初始化 wpa 上下文信息if (wpa_supplicant_init_wpa(wpa_s) < 0)return -1;//设置 wpa_s->wpa 指向一个 wpa_sm 对象,下面这两个函数用于设置 wpa_sm 中的一些成员变量wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :NULL);wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);//如果配置文件 wpa_supplicant.conf 设置了变量dot11RSNAConfigPMKLifetime、dot11RSNAConfigPMKReauthThreshold和dot11RSNAConfigSATimeout ,则使用配置文件中的值来替换 wpa_sm 中的默认值。if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,wpa_s->conf->dot11RSNAConfigPMKLifetime)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigPMKLifetime");return -1;}if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigPMKReauthThreshold");return -1;}if (wpa_s->conf->dot11RSNAConfigSATimeout &&wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,wpa_s->conf->dot11RSNAConfigSATimeout)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigSATimeout");return -1;}//处理 Wi-Fi 设备的 hardware 特性wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,&wpa_s->hw.num_modes,&wpa_s->hw.flags);if (wpa_drv_get_capa(wpa_s, &capa) == 0) {wpa_s->drv_capa_known = 1;wpa_s->drv_flags = capa.flags;wpa_s->drv_enc = capa.enc;wpa_s->probe_resp_offloads = capa.probe_resp_offloads;wpa_s->max_scan_ssids = capa.max_scan_ssids;wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;wpa_s->sched_scan_supported = capa.sched_scan_supported;wpa_s->max_match_sets = capa.max_match_sets;wpa_s->max_remain_on_chan = capa.max_remain_on_chan;wpa_s->max_stations = capa.max_stations;wpa_s->extended_capa = capa.extended_capa;wpa_s->extended_capa_mask = capa.extended_capa_mask;wpa_s->extended_capa_len = capa.extended_capa_len;wpa_s->num_multichan_concurrent =capa.num_multichan_concurrent;}if (wpa_s->max_remain_on_chan == 0)wpa_s->max_remain_on_chan = 1000;/** Only take p2p_mgmt parameters when P2P Device is supported.* Doing it here as it determines whether l2_packet_init() will be done* during wpa_supplicant_driver_init().*/if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)wpa_s->p2p_mgmt = iface->p2p_mgmt;elseiface->p2p_mgmt = 1;if (wpa_s->num_multichan_concurrent == 0)wpa_s->num_multichan_concurrent = 1;if (wpa_supplicant_driver_init(wpa_s) < 0)return -1;#ifdef CONFIG_TDLSif ((!iface->p2p_mgmt ||!(wpa_s->drv_flags &WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&wpa_tdls_init(wpa_s->wpa))return -1;
#endif /* CONFIG_TDLS */if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");return -1;}//初始化 WPS 相关模块if (wpas_wps_init(wpa_s))return -1;//初始化 EAPOL 模块if (wpa_supplicant_init_eapol(wpa_s) < 0)return -1;wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);//初始化 ctrl i/f 模块wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);if (wpa_s->ctrl_iface == NULL) {wpa_printf(MSG_ERROR,"Failed to initialize control interface '%s'.\n""You may have another wpa_supplicant process ""already running or the file was\n""left by an unclean termination of wpa_supplicant ""in which case you will need\n""to manually remove this file before starting ""wpa_supplicant again.\n",wpa_s->conf->ctrl_interface);return -1;}wpa_s->gas = gas_query_init(wpa_s);  //GAS 相关     if (wpa_s->gas == NULL) {wpa_printf(MSG_ERROR, "Failed to initialize GAS query");return -1;}//P2P 模块初始化if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");return -1;}if (wpa_bss_init(wpa_s) < 0)return -1;/** Set Wake-on-WLAN triggers, if configured.* Note: We don't restore/remove the triggers on shutdown (it doesn't* have effect anyway when the interface is down).*/if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)return -1;#ifdef CONFIG_EAP_PROXY
{size_t len;wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,&len);if (wpa_s->mnc_len > 0) {wpa_s->imsi[len] = '\0';wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",wpa_s->imsi, wpa_s->mnc_len);} else {wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");}
}
#endif /* CONFIG_EAP_PROXY */if (pcsc_reader_init(wpa_s) < 0)return -1;if (wpas_init_ext_pw(wpa_s) < 0)return -1;return 0;
}
static int wpas_init_driver(struct wpa_supplicant *wpa_s,struct wpa_interface *iface)
{const char *ifname, *driver, *rn;driver = iface->driver;
next_driver://wpa_supplicant_set_driver将根据driver wrapper 名找到 wpa_drivers 数组中 nl80211 指定的 driver wrapper 对象 wpa_driver_nl80211_ops, 然后调用 global_init 函数。if (wpa_supplicant_set_driver(wpa_s, driver) < 0)return -1;wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);if (wpa_s->drv_priv == NULL) {const char *pos;pos = driver ? os_strchr(driver, ',') : NULL;if (pos) {wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize ""driver interface - try next driver wrapper");driver = pos + 1;goto next_driver;}wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver ""interface");return -1;}//设置 driver 参数if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected ""driver_param '%s'", wpa_s->conf->driver_param);return -1;}//从 driver 中获取网卡名ifname = wpa_drv_get_ifname(wpa_s);if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced ""interface name with '%s'", ifname);//如果不一致则替换配置文件中设置的网卡设备名os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));}rn = wpa_driver_get_radio_name(wpa_s);if (rn && rn[0] == '\0')rn = NULL;wpa_s->radio = radio_add_interface(wpa_s, rn);if (wpa_s->radio == NULL)return -1;return 0;
}

android-5.1/external/wpa_supplicant_8/src/drivers/driver_nl80211.c

static void * nl80211_global_init(void)
{struct nl80211_global *global;struct netlink_config *cfg;global = os_zalloc(sizeof(*global));if (global == NULL)return NULL;global->ioctl_sock = -1;dl_list_init(&global->interfaces);global->if_add_ifindex = -1;cfg = os_zalloc(sizeof(*cfg));if (cfg == NULL)goto err;cfg->ctx = global;//下面这三条语句用于创建 netlink socket 来接收来自内核的网卡状态变化事件(如 UP、DORMANT、REMOVED),然后通过 eloop_register_read_sock 注册一个 netlink_recv 函数用于处理接收到的 socke 消息。//netlink_recv 函数内部将根据消息的类别来调用 netlink_cb 和 dellink_cb 以处理网卡状态变化事件。 cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;global->netlink = netlink_init(cfg);if (global->netlink == NULL) {os_free(cfg);goto err;}//nl80211 利用 netlink 机制和 wlan driver 交互if (wpa_driver_nl80211_init_nl_global(global) < 0)goto err;global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);if (global->ioctl_sock < 0) {wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",strerror(errno));goto err;}return global;err:nl80211_global_deinit(global);return NULL;
}

nl80211_global 代表 nl80211 driver wrapper 全局上下文信息

android-5.1/external/wpa_supplicant_8/src/drivers/driver_nl80211.c

struct nl80211_global {struct dl_list interfaces;    //该链接包含 wpa_driver_nl80211_data 对象int if_add_ifindex;u64 if_add_wdevid;int if_add_wdevid_set;struct netlink_data *netlink;struct nl_cb *nl_cb;  //netlink 回调对象struct nl_handle *nl; //nl_handle 的真实类型就是 libnl 定义的 nl_socket 。 nl成员变量用于发送 netlink eventint nl80211_id;   //nl80211 模块的 netlink family 值int ioctl_sock; /* socket for ioctl() use 用于 ioctl 函数的 socket 句柄*/struct nl_handle *nl_event; //用于接收 netlink event
};
#define nl_handle nl_sock

android-5.1/external/wpa_supplicant_8/src/drivers/driver_nl80211.c

static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
{int ret;//创建一个 netlink 回调对象global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);if (global->nl_cb == NULL) {wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink ""callbacks");return -1;}//nl_create_handle 返回值的类型为 nl_handle *//nl_create_handle 内部调用 genl_connect 连接到内核对应的模块。该函数最后的字符串参数("nl")仅用于输出调试信息global->nl = nl_create_handle(global->nl_cb, "nl");if (global->nl == NULL)goto err;//向 netlink 中的 "nl" 模块查询 "nl80211" 模块的编号。 genl_ctrl_resolve 函数本是由 libnl 定义,但在 driver_nl80211.c 中通过//#define genl_ctrl_resolve android_genl_ctrl_resolve//将其指向 android_genl_ctrl_resolve。该函数内部通过发送查询消息来获取 "nl80211" 模块的 family 值。global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");if (global->nl80211_id < 0) {wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not ""found");goto err;}//创建另一个 nl_handle 来接收 netlink 消息global->nl_event = nl_create_handle(global->nl_cb, "event");if (global->nl_event == NULL)goto err;//先从 nl80211 模块中获得对应的组播组编号,如"scan"、"mlme"以及"regulatory"组播组的编号。ret = nl_get_multicast_id(global, "nl80211", "scan");if (ret >= 0)//加入某个组播组。这样,当某个组播有消息发送时, nl_event 就能收到了ret = nl_socket_add_membership(global->nl_event, ret);if (ret < 0) {wpa_printf(MSG_ERROR, "nl80211: Could not add multicast ""membership for scan events: %d (%s)",ret, strerror(-ret));goto err;}ret = nl_get_multicast_id(global, "nl80211", "mlme");if (ret >= 0)ret = nl_socket_add_membership(global->nl_event, ret);if (ret < 0) {wpa_printf(MSG_ERROR, "nl80211: Could not add multicast ""membership for mlme events: %d (%s)",ret, strerror(-ret));goto err;}ret = nl_get_multicast_id(global, "nl80211", "regulatory");if (ret >= 0)ret = nl_socket_add_membership(global->nl_event, ret);if (ret < 0) {wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast ""membership for regulatory events: %d (%s)",ret, strerror(-ret));/* Continue without regulatory events */}ret = nl_get_multicast_id(global, "nl80211", "vendor");if (ret >= 0)ret = nl_socket_add_membership(global->nl_event, ret);if (ret < 0) {wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast ""membership for vendor events: %d (%s)",ret, strerror(-ret));/* Continue without vendor events */}nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,no_seq_check, NULL); //设置序列号检查函数为 no_seq_checknl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,process_global_event, global);   //设置 netlink 消息回调处理函数//将 nl_event 对应的 socket 注册到 eloop 中,回调函数为 wpa_driver_nl80211_event_receive ,该函数内部将调用 nl_recv_msg ,而 nl_recv_msg 又会调用 process_global_event 。nl80211_register_eloop_read(&global->nl_event,wpa_driver_nl80211_event_receive,global->nl_cb);return 0;err:nl_destroy_handles(&global->nl_event);nl_destroy_handles(&global->nl);nl_cb_put(global->nl_cb);global->nl_cb = NULL;return -1;
}
static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,void *global_priv)
{return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL);
}static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,void *global_priv, int hostapd,const u8 *set_addr)
{struct wpa_driver_nl80211_data *drv;struct rfkill_config *rcfg;struct i802_bss *bss;if (global_priv == NULL)return NULL;drv = os_zalloc(sizeof(*drv));if (drv == NULL)return NULL;drv->global = global_priv;drv->ctx = ctx;   //ctx 的真正类型是 wpa_supplicantdrv->hostapd = !!hostapd;drv->eapol_sock = -1;drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);drv->if_indices = drv->default_if_indices;drv->first_bss = os_zalloc(sizeof(*drv->first_bss));if (!drv->first_bss) {os_free(drv);return NULL;}bss = drv->first_bss;bss->drv = drv;bss->ctx = ctx;os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));drv->monitor_ifidx = -1;drv->monitor_sock = -1;drv->eapol_tx_sock = -1;drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;if (wpa_driver_nl80211_init_nl(drv)) {os_free(drv);return NULL;}if (nl80211_init_bss(bss))goto failed;rcfg = os_zalloc(sizeof(*rcfg));if (rcfg == NULL)goto failed;rcfg->ctx = drv;os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));//和 rfkill 相关rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;drv->rfkill = rfkill_init(rcfg);if (drv->rfkill == NULL) {wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");os_free(rcfg);}if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0)drv->start_iface_up = 1;if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1))goto failed;drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);if (drv->eapol_tx_sock < 0)goto failed;if (drv->data_tx_status) {int enabled = 1;if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,&enabled, sizeof(enabled)) < 0) {wpa_printf(MSG_DEBUG,"nl80211: wifi status sockopt failed\n");drv->data_tx_status = 0;if (!drv->use_monitor)drv->capa.flags &=~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;} else {eloop_register_read_sock(drv->eapol_tx_sock,wpa_driver_nl80211_handle_eapol_tx_status,drv, NULL);}}if (drv->global) {//把自己加入到 nl80211_global 中的 interfaces 链表中去dl_list_add(&drv->global->interfaces, &drv->list);drv->in_interface_list = 1;}return bss;failed:wpa_driver_nl80211_deinit(bss);return NULL;
}

rfkill: radio frequency connector kill switch support , 它是 Kernel 的一个子系统。功能是控制系统中射频设备的电源。这些设备驱动只有把自己注册到 rfkill 子系统后, rfkill 才能对它们起作用。 rfkill 对用户空间提供了相应的控制接口,主要是通过 /dev/rfkill 设备文件完成相关操作。
android-5.1/external/wpa_supplicant_8/src/drivers/rfkill.c

struct rfkill_data * rfkill_init(struct rfkill_config *cfg)
{struct rfkill_data *rfkill;struct rfkill_event event;ssize_t len;rfkill = os_zalloc(sizeof(*rfkill));if (rfkill == NULL)return NULL;rfkill->cfg = cfg;//O_RDONLY 标志表示 driver_nl80211 只读取 rfkill 事件,而不会去操作 rfkill 模块rfkill->fd = open("/dev/rfkill", O_RDONLY);if (rfkill->fd < 0) {wpa_printf(MSG_INFO, "rfkill: Cannot open RFKILL control ""device");goto fail;}//设置 I/O 操作为非阻塞式if (fcntl(rfkill->fd, F_SETFL, O_NONBLOCK) < 0) {wpa_printf(MSG_ERROR, "rfkill: Cannot set non-blocking mode: ""%s", strerror(errno));goto fail2;}for (;;) {//读取 /dev/rfkill 中已有的事件信息。 rfkill 事件信息保存在 rfkill_event 结构体中len = read(rfkill->fd, &event, sizeof(event));if (len < 0) {if (errno == EAGAIN)break; /* No more entries 无数据可读,则跳出循环*/wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s",strerror(errno));break;//其他错误也跳出循环}if (len != RFKILL_EVENT_SIZE_V1) {wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size ""%d (expected %d)",(int) len, RFKILL_EVENT_SIZE_V1);continue;}wpa_printf(MSG_DEBUG, "rfkill: initial event: idx=%u type=%d ""op=%u soft=%u hard=%u",event.idx, event.type, event.op, event.soft,event.hard);//op变量代表 rfkill 事件的类型,目前可取值由 RFKILL_OP_ADD、 RFKILL_OP_DEL 等//type 代表该 rfkill 事件所对应设备的类型:如 RFKILL_TYPE_WLAN/ RFKILL_TYPE_BLUETOOTH等。if (event.op != RFKILL_OP_ADD ||event.type != RFKILL_TYPE_WLAN)continue;if (event.hard) {//是否为hard block, 指不能通过软件来重启的 RF 设备wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");rfkill->blocked = 1;} else if (event.soft) {//用软件来重启 RF 设备wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked");rfkill->blocked = 1;}}//为 eloop 注册一个读事件,一旦 rfkill 有新的事件到来, 则 eloop 会触发 rfkill_receive 函数被调用eloop_register_read_sock(rfkill->fd, rfkill_receive, rfkill, NULL);return rfkill;fail2:close(rfkill->fd);
fail:os_free(rfkill);return NULL;
}

WPAS 只监控 rfkill 设备以获取发生在其上的 rfkill_event,而并不操作 rfkill 以关闭或启用无线设备。

struct rfkill_data {struct rfkill_config *cfg;int fd;int blocked;
};

rfkill_event 代表 rfkill 事件

struct rfkill_event {u32 idx;//代表设备类型u8 type;//op变量代表 rfkill 事件的类型,目前可取值由 RFKILL_OP_ADD、 RFKILL_OP_DEL 等u8 op;u8 soft;u8 hard;
} STRUCT_PACKED;
static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
{drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);if (!drv->nl_cb) {wpa_printf(MSG_ERROR, "nl80211: Failed to alloc cb struct");return -1;}nl_cb_set(drv->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);nl_cb_set(drv->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_drv_event, drv);return 0;
}
static int nl80211_init_bss(struct i802_bss *bss)
{bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);if (!bss->nl_cb)return -1;nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_bss_event, bss);return 0;
}

这两个函数都创建了回调对象,不过未创建 nl_handle,即没有创建 nl socket,没有和socket绑定。

static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
{struct wpa_driver_nl80211_data *drv = bss->drv;if (bss->nl_mgmt) {wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting ""already on! (nl_mgmt=%p)", bss->nl_mgmt);return -1;}bss->nl_mgmt = nl_create_handle(drv->nl_cb, "mgmt");    //drv->nl_cb对应的回调对象是 process_drv_eventif (bss->nl_mgmt == NULL)return -1;return 0;
}static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,void *handle)
{struct nl_cb *cb = eloop_ctx;int res;wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");res = nl_recvmsgs(handle, cb);    //cb 是 bss->nl_cbif (res < 0) {wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",__func__, res);}
}
static int
wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,const u8 *set_addr, int first)
{struct i802_bss *bss = drv->first_bss;int send_rfkill_event = 0;enum nl80211_iftype nlmode;drv->ifindex = if_nametoindex(bss->ifname); //获取网卡设备的索引,属于 netdevice 编程范畴bss->ifindex = drv->ifindex;bss->wdev_id = drv->global->if_add_wdevid;bss->wdev_id_set = drv->global->if_add_wdevid_set;bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;drv->global->if_add_wdevid_set = 0;if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)bss->static_ap = 1;//获取 Wi-Fi 设备的 capabilityif (wpa_driver_nl80211_capa(drv))return -1;wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",bss->ifname, drv->phyname);//linux_set_iface_flags 通过 ioctl 方式启动 ifname 对应的网卡设备,该函数使用了 netdevice APIif (set_addr &&(linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) ||linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,set_addr)))return -1;if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)drv->start_mode_ap = 1;if (drv->hostapd || bss->static_ap)nlmode = NL80211_IFTYPE_AP;else if (bss->if_dynamic)nlmode = nl80211_get_ifmode(bss);elsenlmode = NL80211_IFTYPE_STATION;//设置接口类型; 该函数会调用到上一节提到的 nl80211_alloc_mgmt_handleif (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");return -1;}if (nlmode == NL80211_IFTYPE_P2P_DEVICE)nl80211_get_macaddr(bss);//启动设备失败时,要判断是不是 rfkill 禁止了该设备if (!rfkill_is_blocked(drv->rfkill)) {int ret = i802_set_iface_flags(bss, 1);if (ret) {wpa_printf(MSG_ERROR, "nl80211: Could not set ""interface '%s' UP", bss->ifname);return ret;}if (nlmode == NL80211_IFTYPE_P2P_DEVICE)return ret;} else {wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable ""interface '%s' due to rfkill", bss->ifname);if (nlmode == NL80211_IFTYPE_P2P_DEVICE)return 0;//如果是因为 rfkill 原因导致设备被禁止,则需要通知 wpa_supplicantdrv->if_disabled = 1;   //该设备被 rfkill 禁止了send_rfkill_event = 1;    //该值表示需要设置 WPAS 的状态}if (!drv->hostapd)//设置 Wi-Fi 设备的工作状态为 IF_OPER_DORMANTnetlink_send_oper_ifla(drv->global->netlink, drv->ifindex,1, IF_OPER_DORMANT);//通过 ioctl 方式获取指定网卡的MAC地址if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,bss->addr))return -1;os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);if (send_rfkill_event) {//添加一个超时任务,超时时间为 0 秒。超时处理函数为 wpa_driver_nl80211_send_rfkill, 该函数内部将设置 wpa_states 为 WPA_INTERFACE_DISABLEDeloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,drv, drv->ctx);}return 0;
}

Virtual Interface 类型
android-5.1/external/wpa_supplicant_8/src/drivers/nl80211_copy.h

enum nl80211_iftype {NL80211_IFTYPE_UNSPECIFIED,NL80211_IFTYPE_ADHOC,    //IBSS 类型NL80211_IFTYPE_STATION,    //基础结构型网络中的STANL80211_IFTYPE_AP,        //基础结构型网络中的APNL80211_IFTYPE_AP_VLAN,    //VLAN 相关NL80211_IFTYPE_WDS,        //无线桥接NL80211_IFTYPE_MONITOR,   //可接收无线网络所有的数据包,它提供类似 AirPcap 这样的功能NL80211_IFTYPE_MESH_POINT,    //Mesh 网络节点NL80211_IFTYPE_P2P_CLIENT,   //P2P ClientNL80211_IFTYPE_P2P_GO,      //P2P group ownerNL80211_IFTYPE_P2P_DEVICE,/* keep last */NUM_NL80211_IFTYPES,NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
};

android-5.1\prebuilts\ndk\9\platforms\android-21\arch-arm64\usr\include\linux\if.h

enum {IF_OPER_UNKNOWN,IF_OPER_NOTPRESENT,IF_OPER_DOWN,   //接口不能工作IF_OPER_LOWERLAYERDOWN, //相比 DOWN, 该状态指出了接口设备不能工作的原因是其所依赖的更低一层的设备不能正常工作IF_OPER_TESTING,  //接口处于测试状态IF_OPER_DORMANT,  //休眠或暂停状态,表示接口设备在等待某个事情的发生IF_OPER_UP,    //接口可工作
};

获取无线网络设备的 capability

static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
{struct wiphy_info_data info;//发送 netlink 命令 NL80211_CMD_GET_WIPHY 来获取 Wi-Fi 设备的信息if (wpa_driver_nl80211_get_info(drv, &info))return -1;if (info.error)return -1;drv->has_capability = 1;//drv->capa 变量的类型是 wpa_driver_capa , 用于表示设备的 capability ,这些 capa 如下:drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;drv->capa.auth = WPA_DRIVER_AUTH_OPEN |WPA_DRIVER_AUTH_SHARED |WPA_DRIVER_AUTH_LEAP;//WPA_DRIVER_FLAGS_SANE_ERROR_CODES 主要针对 associate 操作。当关联操作失败后,如果driver 支持该选项,则表明 driver 能处理失败之后的各种收尾工作; 否则,WPAS 需要自己处理这些事情drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;//WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE 表明 association 成功后, Kernel driver 需要设置 WEP key。drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;//WPA_DRIVER_FLAGS_EAPOL_TX_STATUS 表示 Kernel中的 driver 是否能反馈 EAPOL 数据帧发送情况以及 Deauthentiation/Disassociation 帧发送情况drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;/** As all cfg80211 drivers must support cases where the AP interface is* removed without the knowledge of wpa_supplicant/hostapd, e.g., in* case that the user space daemon has crashed, they must be able to* cleanup all stations and key entries in the AP tear down flow. Thus,* this flag can/should always be set for cfg80211 drivers.*/drv->capa.flags |= WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT;if (!info.device_ap_sme) {drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;/** No AP SME is currently assumed to also indicate no AP MLME* in the driver/firmware.*/drv->capa.flags |= WPA_DRIVER_FLAGS_AP_MLME;}//device_ap_sme 表示 AP 集成了 SME。drv->device_ap_sme = info.device_ap_sme;//poll_command_supported: hostapd 需要判断 STA 是否还活跃, 即心跳检测。检测方法是发送 null 数据帧,即不带任何数据的无线 MAC 数据帧, 如果 STA 还活跃的话,一定会回复 ACK 给 AP。发送 null 的工作可以由 Kernel driver 完成,也可以由 hostapd 来完成。如果 Kernel driver 支持 poll_command_supported, hostapd 只要发送 netlink 命令 NL80211_CMD_PROBE_CLIENT 给 Kernel 驱动,所有工作就由 Kernel 驱动完成。否则 hostapd 需要自己构造一个 null 数据帧,然后再发送出去drv->poll_command_supported = info.poll_command_supported;//和 WPA_DRIVER_FLAGS_EAPOL_TX_STATUS 有关。如果 wlan 驱动支持的话, EAPOL 帧 TX Report 将通知给用户空间的 driver wrapper,即此处的 driver_nl80211drv->data_tx_status = info.data_tx_status;if (info.set_qos_map_supported)drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;drv->have_low_prio_scan = info.have_low_prio_scan;/** If poll command and tx status are supported, mac80211 is new enough* to have everything we need to not need monitor interfaces.*///use_monitor 也和 AP 心跳检测 STA 有关。如果 Kernel driver 不支持 poll_command_supported 的话, hostapd 可通过创建一个 NL80211_IFTYPE_MONITOR 类型的接口设备用于监控 STA 的活跃情况drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;if (drv->device_ap_sme && drv->use_monitor) {/** Non-mac80211 drivers may not support monitor interface.* Make sure we do not get stuck with incorrect capability here* by explicitly testing this.*///monitor supported 表示 kernel driver 是否支持创建 NL80211_IFTYPE_MONITOR 类型的设备接口if (!info.monitor_supported) {wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor ""with device_ap_sme since no monitor mode ""support detected");drv->use_monitor = 0;}}/** If we aren't going to use monitor interfaces, but the* driver doesn't support data TX status, we won't get TX* status for EAPOL frames.*/if (!drv->use_monitor && !info.data_tx_status)drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;return 0;
}

android-5.1/external/wpa_supplicant_8/src/drivers/driver.h

struct wpa_driver_capa {
#define WPA_DRIVER_CAPA_KEY_MGMT_WPA        0x00000001
#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2       0x00000002
#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK    0x00000004
#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK   0x00000008
#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE   0x00000010
#define WPA_DRIVER_CAPA_KEY_MGMT_FT     0x00000020
#define WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK     0x00000040
#define WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK   0x00000080unsigned int key_mgmt;    //该设备支持的密钥管理类型。默认支持 WPA 、 WPA-PSK 、WPA2 和 WPA2-PSK#define WPA_DRIVER_CAPA_ENC_WEP40 0x00000001
#define WPA_DRIVER_CAPA_ENC_WEP104  0x00000002
#define WPA_DRIVER_CAPA_ENC_TKIP    0x00000004
#define WPA_DRIVER_CAPA_ENC_CCMP    0x00000008
#define WPA_DRIVER_CAPA_ENC_WEP128  0x00000010
#define WPA_DRIVER_CAPA_ENC_GCMP    0x00000020
#define WPA_DRIVER_CAPA_ENC_GCMP_256    0x00000040
#define WPA_DRIVER_CAPA_ENC_CCMP_256    0x00000080
#define WPA_DRIVER_CAPA_ENC_BIP     0x00000100
#define WPA_DRIVER_CAPA_ENC_BIP_GMAC_128    0x00000200
#define WPA_DRIVER_CAPA_ENC_BIP_GMAC_256    0x00000400
#define WPA_DRIVER_CAPA_ENC_BIP_CMAC_256    0x00000800
#define WPA_DRIVER_CAPA_ENC_GTK_NOT_USED    0x00001000unsigned int enc; //支持的加密算法类型。默认支持 WEP40 、 WEP104 、 TKIP 和 CCMP #define WPA_DRIVER_AUTH_OPEN      0x00000001
#define WPA_DRIVER_AUTH_SHARED      0x00000002
#define WPA_DRIVER_AUTH_LEAP        0x00000004unsigned int auth;    //支持的身份验证类型:默认支持 Open System、 Shared 和 LEAP/* Driver generated WPA/RSN IE */
#define WPA_DRIVER_FLAGS_DRIVER_IE  0x00000001
/* Driver needs static WEP key setup after association command */
#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002
/* Driver takes care of all DFS operations */
#define WPA_DRIVER_FLAGS_DFS_OFFLOAD            0x00000004
/* Driver takes care of RSN 4-way handshake internally; PMK is configured with* struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */
#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008
#define WPA_DRIVER_FLAGS_WIRED      0x00000010
/* Driver provides separate commands for authentication and association (SME in* wpa_supplicant). */
#define WPA_DRIVER_FLAGS_SME        0x00000020
/* Driver supports AP mode */
#define WPA_DRIVER_FLAGS_AP     0x00000040
/* Driver needs static WEP key setup after association has been completed */
#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE  0x00000080
/* Driver supports dynamic HT 20/40 MHz channel changes during BSS lifetime */
#define WPA_DRIVER_FLAGS_HT_2040_COEX           0x00000100
/* Driver supports concurrent P2P operations */
#define WPA_DRIVER_FLAGS_P2P_CONCURRENT 0x00000200
/** Driver uses the initial interface as a dedicated management interface, i.e.,* it cannot be used for P2P group operations or non-P2P purposes.*/
#define WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE    0x00000400
/* This interface is P2P capable (P2P GO or P2P Client) */
#define WPA_DRIVER_FLAGS_P2P_CAPABLE    0x00000800
/* Driver supports station and key removal when stopping an AP */
#define WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT        0x00001000
/** Driver uses the initial interface for P2P management interface and non-P2P* purposes (e.g., connect to infra AP), but this interface cannot be used for* P2P group operations.*/
#define WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P       0x00002000
/** Driver is known to use sane error codes, i.e., when it indicates that* something (e.g., association) fails, there was indeed a failure and the* operation does not end up getting completed successfully later.*/
#define WPA_DRIVER_FLAGS_SANE_ERROR_CODES       0x00004000
/* Driver supports off-channel TX */
#define WPA_DRIVER_FLAGS_OFFCHANNEL_TX          0x00008000
/* Driver indicates TX status events for EAPOL Data frames */
#define WPA_DRIVER_FLAGS_EAPOL_TX_STATUS        0x00010000
/* Driver indicates TX status events for Deauth/Disassoc frames */
#define WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS       0x00020000
/* Driver supports roaming (BSS selection) in firmware */
#define WPA_DRIVER_FLAGS_BSS_SELECTION          0x00040000
/* Driver supports operating as a TDLS peer */
#define WPA_DRIVER_FLAGS_TDLS_SUPPORT           0x00080000
/* Driver requires external TDLS setup/teardown/discovery */
#define WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP        0x00100000
/* Driver indicates support for Probe Response offloading in AP mode */
#define WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD     0x00200000
/* Driver supports U-APSD in AP mode */
#define WPA_DRIVER_FLAGS_AP_UAPSD           0x00400000
/* Driver supports inactivity timer in AP mode */
#define WPA_DRIVER_FLAGS_INACTIVITY_TIMER       0x00800000
/* Driver expects user space implementation of MLME in AP mode */
#define WPA_DRIVER_FLAGS_AP_MLME            0x01000000
/* Driver supports SAE with user space SME */
#define WPA_DRIVER_FLAGS_SAE                0x02000000
/* Driver makes use of OBSS scan mechanism in wpa_supplicant */
#define WPA_DRIVER_FLAGS_OBSS_SCAN          0x04000000
/* Driver supports IBSS (Ad-hoc) mode */
#define WPA_DRIVER_FLAGS_IBSS               0x08000000
/* Driver supports radar detection */
#define WPA_DRIVER_FLAGS_RADAR              0x10000000
/* Driver supports a dedicated interface for P2P Device */
#define WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE       0x20000000
/* Driver supports QoS Mapping */
#define WPA_DRIVER_FLAGS_QOS_MAPPING            0x40000000
/* Driver supports CSA in AP mode */
#define WPA_DRIVER_FLAGS_AP_CSA             0x80000000unsigned int flags;int max_scan_ssids;int max_sched_scan_ssids;int sched_scan_supported;int max_match_sets;/*** max_remain_on_chan - Maximum remain-on-channel duration in msec*/unsigned int max_remain_on_chan;/*** max_stations - Maximum number of associated stations the driver* supports in AP mode*/unsigned int max_stations;/*** probe_resp_offloads - Bitmap of supported protocols by the driver* for Probe Response offloading.*/
/* Driver Probe Response offloading support for WPS ver. 1 */
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS       0x00000001
/* Driver Probe Response offloading support for WPS ver. 2 */
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2      0x00000002
/* Driver Probe Response offloading support for P2P */
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P       0x00000004
/* Driver Probe Response offloading support for IEEE 802.11u (Interworking) */
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING  0x00000008unsigned int probe_resp_offloads;unsigned int max_acl_mac_addrs;/*** Number of supported concurrent channels*/unsigned int num_multichan_concurrent;/*** extended_capa - extended capabilities in driver/device** Must be allocated and freed by driver and the pointers must be* valid for the lifetime of the driver, i.e., freed in deinit()*/const u8 *extended_capa, *extended_capa_mask;unsigned int extended_capa_len;struct wowlan_triggers wowlan_triggers;
};
static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,struct wiphy_info_data *info)
{u32 feat;struct nl_msg *msg;os_memset(info, 0, sizeof(*info));info->capa = &drv->capa;info->drv = drv;msg = nlmsg_alloc();if (!msg)return -1;feat = get_nl80211_protocol_features(drv);if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)//构造一个 NL80211_CMD_GET_WIPHY 命令以获取设备信息nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_WIPHY);elsenl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);if (nl80211_set_iface_id(msg, drv->first_bss) < 0)goto nla_put_failure;//发送命令并等待回复,回复消息将由 wiphy_info_handler 函数处理if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info))return -1;if (info->auth_supported)drv->capa.flags |= WPA_DRIVER_FLAGS_SME;else if (!info->connect_supported) {wpa_printf(MSG_INFO, "nl80211: Driver does not support ""authentication/association or connect commands");info->error = 1;}if (info->p2p_go_supported && info->p2p_client_supported)drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;if (info->p2p_concurrent) {wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group ""interface (driver advertised support)");drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;}if (info->num_multichan_concurrent > 1) {wpa_printf(MSG_DEBUG, "nl80211: Enable multi-channel ""concurrent (driver advertised support)");drv->capa.num_multichan_concurrent =info->num_multichan_concurrent;}/* default to 5000 since early versions of mac80211 don't set it */if (!drv->capa.max_remain_on_chan)drv->capa.max_remain_on_chan = 5000;if (info->channel_switch_supported)drv->capa.flags |= WPA_DRIVER_FLAGS_AP_CSA;return 0;
nla_put_failure:nlmsg_free(msg);return -1;
}
struct wpa_driver_nl80211_data {struct nl80211_global *global;   //指向 nl80211_global 对象struct dl_list list;struct dl_list wiphy_list;char phyname[32];u8 perm_addr[ETH_ALEN];void *ctx;  //指向一个 wpa_supplicant 对象int ifindex;    //对应网卡设备的索引int if_removed;int if_disabled;int ignore_if_down_event;struct rfkill_data *rfkill;  //rfkill 相关的上下文信息struct wpa_driver_capa capa;   //代表 kernel 中 wifi 驱动的 capabilityu8 *extended_capa, *extended_capa_mask;unsigned int extended_capa_len;int has_capability;int operstate;    //IfOperStatus 相关int scan_complete_events;enum scan_states {NO_SCAN, SCAN_REQUESTED, SCAN_STARTED, SCAN_COMPLETED,SCAN_ABORTED, SCHED_SCAN_STARTED, SCHED_SCAN_STOPPED,SCHED_SCAN_RESULTS} scan_state;struct nl_cb *nl_cb;  //libnl 回调对象u8 auth_bssid[ETH_ALEN];u8 auth_attempt_bssid[ETH_ALEN];u8 bssid[ETH_ALEN];u8 prev_bssid[ETH_ALEN];int associated;u8 ssid[32];size_t ssid_len;enum nl80211_iftype nlmode;enum nl80211_iftype ap_scan_as_station;    //接口类型unsigned int assoc_freq;int monitor_sock;int monitor_ifidx;int monitor_refcount;unsigned int disabled_11b_rates:1;unsigned int pending_remain_on_chan:1;unsigned int in_interface_list:1;unsigned int device_ap_sme:1;unsigned int poll_command_supported:1;unsigned int data_tx_status:1;unsigned int scan_for_auth:1;unsigned int retry_auth:1;unsigned int use_monitor:1;unsigned int ignore_next_local_disconnect:1;unsigned int ignore_next_local_deauth:1;unsigned int allow_p2p_device:1;unsigned int hostapd:1;unsigned int start_mode_ap:1;unsigned int start_iface_up:1;unsigned int test_use_roc_tx:1;unsigned int ignore_deauth_event:1;unsigned int roaming_vendor_cmd_avail:1;unsigned int dfs_vendor_cmd_avail:1;unsigned int have_low_prio_scan:1;unsigned int force_connect_cmd:1;unsigned int addr_changed:1;u64 remain_on_chan_cookie;u64 send_action_cookie;unsigned int last_mgmt_freq;struct wpa_driver_scan_filter *filter_ssids;size_t num_filter_ssids;struct i802_bss *first_bss;   //指向一个 i802_bss 结构体int eapol_tx_sock;int eapol_sock; /* socket for EAPOL frames */struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */int default_if_indices[16];int *if_indices;int num_if_indices;/* From failed authentication command */int auth_freq;u8 auth_bssid_[ETH_ALEN];u8 auth_ssid[32];size_t auth_ssid_len;int auth_alg;u8 *auth_ie;size_t auth_ie_len;u8 auth_wep_key[4][16];size_t auth_wep_key_len[4];int auth_wep_tx_keyidx;int auth_local_state_change;int auth_p2p;
};
struct i802_bss {struct wpa_driver_nl80211_data *drv;struct i802_bss *next;  //指向下一个 i802_bssint ifindex;    //网络设备编号u64 wdev_id;char ifname[IFNAMSIZ + 1];char brname[IFNAMSIZ];unsigned int beacon_set:1;unsigned int added_if_into_bridge:1;unsigned int added_bridge:1;unsigned int in_deinit:1;unsigned int wdev_id_set:1;unsigned int added_if:1;unsigned int static_ap:1;u8 addr[ETH_ALEN];  //用于存储 MAC 地址int freq;int bandwidth;int if_dynamic;void *ctx;struct nl_handle *nl_preq, *nl_mgmt;   //用于接收 MLME 相关的 netlink 消息struct nl_cb *nl_cb;//netlink 回调对象struct nl80211_wiphy_data *wiphy_data;struct dl_list wiphy_list;
};

android-5.1/external/wpa_supplicant_8/wpa_supplicant/wpas_glue.c

int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
{
#ifndef CONFIG_NO_WPAstruct wpa_sm_ctx *ctx;ctx = os_zalloc(sizeof(*ctx));if (ctx == NULL) {wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");return -1;}ctx->ctx = wpa_s;ctx->msg_ctx = wpa_s;ctx->set_state = _wpa_supplicant_set_state;ctx->get_state = _wpa_supplicant_get_state;ctx->deauthenticate = _wpa_supplicant_deauthenticate;ctx->set_key = wpa_supplicant_set_key;ctx->get_network_ctx = wpa_supplicant_get_network_ctx;ctx->get_bssid = wpa_supplicant_get_bssid;ctx->ether_send = _wpa_ether_send;ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;ctx->alloc_eapol = _wpa_alloc_eapol;ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;ctx->add_pmkid = wpa_supplicant_add_pmkid;ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
#ifndef CONFIG_NO_CONFIG_BLOBSctx->set_config_blob = wpa_supplicant_set_config_blob;ctx->get_config_blob = wpa_supplicant_get_config_blob;
#endif /* CONFIG_NO_CONFIG_BLOBS */ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
#ifdef CONFIG_IEEE80211Rctx->update_ft_ies = wpa_supplicant_update_ft_ies;ctx->send_ft_action = wpa_supplicant_send_ft_action;ctx->mark_authenticated = wpa_supplicant_mark_authenticated;
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_TDLSctx->tdls_get_capa = wpa_supplicant_tdls_get_capa;ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt;ctx->tdls_oper = wpa_supplicant_tdls_oper;ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset;
#endif /* CONFIG_TDLS */ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;wpa_s->wpa = wpa_sm_init(ctx);if (wpa_s->wpa == NULL) {wpa_printf(MSG_ERROR, "Failed to initialize WPA state ""machine");return -1;}
#endif /* CONFIG_NO_WPA */return 0;
}

深入理解 wpa_supplicant(四)相关推荐

  1. (三)深入浅出TCPIP之再识TCP,理解TCP四次挥手(上)

    目录 1.TCP四次挥手过程 2.挥手连环发问 专栏其他文章: 理论篇: (一)深入浅出TCPIP之理解TCP报文格式和交互流程 (二)深入浅出TCPIP之再识TCP,理解TCP三次握手(上) (三) ...

  2. Android wpa_supplicant 四次握手 流程分析

    记录wpa_supplicant四次握手的过程. 相关log:https://www.cnblogs.com/helloworldtoyou/p/9633603.html 接收到第一次握手,会设置一个 ...

  3. 红黑树理解(四) 左旋

    红黑树理解 (一) 从2-3树到红黑树 红黑树理解(二)插入过程图解 红黑树理解(三)变色 红黑树理解(四)左旋 红黑树理解(五)右旋 左旋的目的是什么? 称以旋转节点为根节点的红黑树为T,左旋的目的 ...

  4. 深入理解wpa_supplicant

    转自:http://blog.csdn.net/innost/article/details/20862875 先感谢各位兄弟姐妹们的耐心等待.本书预计在3月中旬上市发售.从今天开始,我将在博客中连载 ...

  5. 本质安全设备标准(IEC60079-11)的理解(四)

    本质安全设备标准(IEC60079-11)的理解(四) 对于标准中"Separation"的理解 IEC60079-11使用了较长的篇幅来说明设计中需要考虑到的各种间距, 这也从一 ...

  6. 深入理解 wpa_supplicant(三)

    本文为<深入理解Android Wi-Fi.NFC和GPS卷>读书笔记,Android源码为Android 5.1 android-5.1/external/wpa_supplicant_ ...

  7. 深入理解 wpa_supplicant(二)

    本文为<深入理解Android Wi-Fi.NFC和GPS卷>读书笔记,Android源码为Android 5.1 struct wpa_global * wpa_supplicant_i ...

  8. 深入理解 wpa_supplicant(一)

    本文为<深入理解Android Wi-Fi.NFC和GPS卷>读书笔记,Android源码为Android 5.1 wpa_supplicant 是一个开源软件项目,它实现了 Statio ...

  9. mysql隔离级别底层实现_1、深入理解mysql四种隔离级别及底层实现原理(MVCC和锁)...

    一.ACID特性 持久性,我们就不讲了,易懂. 1.原子性 在同一个事务内部的一组操作必须全部执行成功(或者全部失败). 为了保证事务操作的原子性,必须实现基于日志的REDO/UNDO机制:将所有对数 ...

最新文章

  1. 涨姿势,Java中New一个对象是个怎么样的过程?
  2. tar.xz、tar.bz2 压缩包解压方式
  3. “芯痛”之下阿里苦心研发NPU AI芯片究竟哪款PU更厉害?
  4. matlab中的科学记数法变成小数形式
  5. 转载:EBS上用过的一些接口表整理信息
  6. Android自定义属性,format详解
  7. 广东金融学院java实验报告_《大学计算机Ⅰ》实验报告实验三
  8. Docker折腾手记-安装
  9. LeetCode 61. 旋转链表(python、c++)
  10. 神经网络画图-ConvNetDraw(简单实用)
  11. Selenium调用使用360浏览器,QQ浏览器,遨游浏览器,猎豹浏览器,Chromium
  12. IDEA中Python使用url时报错:Traceback (most recent call last)
  13. Jepg转DICOM
  14. top与free命令详解
  15. IOS UIVisualEffect 蒙版的View 高斯模糊实图
  16. StudentLife数据集介绍
  17. 如何将其他语言添加到Office 2010
  18. k8s学习-CKA真题-k8s升级(kubeadm、kubelet、kubectl等)
  19. markdown 里的上标以及下标写法
  20. 最全的OLT设备介绍

热门文章

  1. java.lang.NullPointerException: Attempt to invoke virtual method ‘boolean java.lang.String.equals(j
  2. JAVA中的接口和抽象类的区别
  3. Java:全局变量(成员变量)与局部变量
  4. [NOI 2015]荷马史诗
  5. Go 学习笔记(21)— 标准库 os 操作文件(新建、打开、写入、读取、删除、关闭文件)
  6. RabbitMQ 入门系列(9)— Python 的 pika 库常用函数及参数说明
  7. Pairs Forming LCM LightOJ - 1236
  8. try-catch-finally对返回值的影响
  9. hdu 1166 敌兵布阵(树状数组)
  10. 修改属性使按钮处于无验证状态