Android wpa_supplicant源码分析–连接AP过程
来源:互联网 发布:乐视超级电视销售数据 编辑:程序博客网 时间:2024/06/07 05:19
连接网络过程
STA连接AP的过程可以参考该文章,http://support.huawei.com/ecommunity/bbs/10232527.html
STA需要认证后才可以接入AP,认证过程分为链路认证(associate)和接入认证(authentication),根据AP的加密方式 associate 和 authentication采用的认证方式不同。
上述网页中列出了各种加密方式的认证方式。
下面以wpa-psk加密方式为例,讲解wpa_supplicant连接AP的过程
1、链路认证(associate)过程
LOG:wpa_supplicant: wlan0: State: SCANNING -> ASSOCIATINGwpa_supplicant: wlan0: State: ASSOCIATING -> ASSOCIATED
wpa_supplicant接收到上层命令由扫描过程变为关联过程,向指定的AP发送 ASSOC 帧,由于此处的认证方式为open,AP在接收到STA的帧后,直接回复STA关联成功。
1.1 添加associate的radio_work
//选择网络(已经在conf中保存), 通过id选取,也可以传入 “any” 后续还可以加入频率的设置" freq="os_strncmp(buf, "SELECT_NETWORK ", 15)static int wpa_supplicant_ctrl_iface_select_network(struct wpa_supplicant *wpa_s, char *cmd){ //从conf中选取ssid网络 struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id); //选择网络 wpa_supplicant_select_network(wpa_s, ssid); { //太狠了,把conf文件中的其他ssid全部设置disable=1 for (other_ssid = wpa_s->conf->ssid; other_ssid; other_ssid = other_ssid->next) other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0; wpa_s->current_ssid = ssid; wpa_s->reassociate = 1; //快速连接,select 的ssid 已经设置为 wpa_s->current_ssid wpa_supplicant_fast_associate(wpa_s) //直接调用,从扫描结果中选取要连接的bss网络 wpas_select_network_from_last_scan(wpa_s, 0, 1) { //返回要连接的bss网络(scan), ssid返回conf中的ssid struct wpa_bss *selected = wpa_supplicant_pick_network(wpa_s,struct wpa_ssid &ssid(null)); { //根据priority的优先级匹配bss, 不合适的conf中的ssid网络已经被disable,不会选取 //返回的select 就是要 连接的bss 网络 for (prio = 0; prio < wpa_s->conf->num_prio; prio++) selected = wpa_supplicant_select_bss(wpa_s, wpa_s->conf->pssid[prio], selected_ssid, 0); } //连接选取的网络 关联所需的网络, //selected-----要连接的bss网络, ssid----conf中保存的ssid if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0) //打了句log就调用关联函数了,“Request association with ” 这句log挺常见的 wpa_supplicant_associate(wpa_s, selected, ssid); { //一个ssid有5中模式,手机连接某个网络时,mode为 * 0 = infrastructure (Managed) mode, i.e., associate with an AP. * 1 = IBSS (ad-hoc, peer-to-peer) * 2 = AP (access point) * 3 = P2P Group Owner (can be set in the configuration file) * 4 = P2P Group Formation (used internally; not in configuration //将wpas_start_assoc_cb 添加到 radio work中 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1, wpas_start_assoc_cb, cwork) < 0) } } }}
1.2 通过驱动发出associate 帧
//真正的连接过程static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit){ //认证方法 int algs = WPA_AUTH_ALG_OPEN; //关联的参数 struct wpa_driver_associate_params params; //关联所需要的ie域 u8 wpa_ie[200]; size_t wpa_ie_len; //关联所需要的ie域,先清除一下 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); //根据key_mgmt中规定的认证方式,设置参数 //在conf文件中的key_mgmt在wpa_config_parse_key_mgmt()中会解析成相应的值 //判断bss是是够支持wpa if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { //设置相关的wpa_ie if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_ie, &wpa_ie_len)) } //判断bss是否支持 8021x else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)){} //判断bss是否支持WPS else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS){} //判断bss是够为open的网络 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA){} //设置wpa_s的状态为 正在关联 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); //填充关联参数 params.wpa_ie = wpa_ie; 。。。 params.key_mgmt_suite = wpa_s->key_mgmt; //以wpa-psk的加密方式为例,psk密码最高为32位 params.key_mgmt_suite == WPA_KEY_MGMT_PSK || params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) { params.passphrase = ssid->passphrase; if (ssid->psk_set) params.psk = ssid->psk; } //调用驱动的关联方法,传入之前设置好的参数params ret = wpa_drv_associate(wpa_s, ¶ms); //关联的超时处理,如果超时后还没有关联,那就会调用wpa_supplicant_timeout方法,例如将该bss加入 blacklist wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);}//驱动的关联函数wpa_s->driver->associate(wpa_s->drv_priv, params)static int wpa_driver_nl80211_associate(void *priv, struct wpa_driver_associate_params *params){ //进入判断,直接调用链接的函数 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)){ return wpa_driver_nl80211_connect(drv, params); { //调用发送关联帧的函数 int ret = wpa_driver_nl80211_try_connect(drv, params); { //想组合好的帧发送到驱动中 ret = send_and_recv_msgs(drv, msg, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully"); } } }}
1.3 关联成功
//接收到驱动上传的ASSOC的event
mlme_event_connect(drv, cmd, tb[NL80211_ATTR_STATUS_CODE], tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_REQ_IE], tb[NL80211_ATTR_RESP_IE]);{ //调用event处理函数 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event); { wpa_supplicant_event_assoc(wpa_s, data); { //设置wpa_s的状态 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); /*设置超时10s,等待AP发送 EAPOL包 Timeout for receiving the first EAPOL packet */ wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); } }}
2、接入认证(authentication)(WPA-PSK为例)
采用PSK认证时,需要与AP交换4次信息,生成需要的密钥,俗称4次握手
https://en.wikipedia.org/wiki/IEEE_802.11i-2004#The_Four-Way_Handshake
wiki图片:
对用的相应的log为
wpa_supplicant: wlan0: State: ASSOCIATED -> 4WAY_HANDSHAKEwpa_supplicant: wlan0: State: 4WAY_HANDSHAKE -> 4WAY_HANDSHAKEwpa_supplicant: wlan0: State: 4WAY_HANDSHAKE -> GROUP_HANDSHAKEwpa_supplicant: wlan0: State: GROUP_HANDSHAKE -> COMPLETED
4次握手的第一帧是由AP发起的,wpa_supplicant在收到后,会根据帧中的信息,判定需要的加密方式,并采用相应的处理函数。
wpa_supplicant支持的加密方式如下图
图片:
L2_packet的4次握手过程:
//处理接收到 L2 EAPOL FRAME 用作auth过程wpa_supplicant_rx_eapol(){ //打印一些log wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr)); //做一些判断,然后通过 eapol_sm_rx_eapol 处理接收到 frame(8021x认证的会通过此路径) if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) && eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0) //wpa加密方式的通过此路径 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); { //这个应该会设置 wap的状态,具体还不他清楚。。 eapol_sm_notify_lower_layer_success(sm->eapol, 0); //依次调用握手处理函数 共4次,第一次 /* 1/4 4-Way Handshake */ wpa_supplicant_process_1_of_4(sm, src_addr, key, ver, key_data, key_data_len); { //发送第二次握手信息到AP wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, kde, kde_len, ptk)) } //再次受到L2 packet 处理/* 3/4 4-Way Handshake */ wpa_supplicant_process_3_of_4(sm, key, ver, key_data, key_data_len); { //发送第四次握手 wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,&sm->ptk)) //设置wpa_s状态 wlan0: State: 4WAY_HANDSHAKE -> GROUP_HANDSHAKE wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); //这一部分的代码变化还是挺大的,4.4的和6.0就不一样 //这里会设置状态为 complete wpa_supplicant_key_neg_complete(sm, sm->bssid, key_info & WPA_KEY_INFO_SECURE); //设置rekey的offload,具体由驱动还是芯片处理,需要继续看 wpa_sm_set_rekey_offload(sm); //至此整个连接过程完毕 } }}
3 流程图
0 0
- Android wpa_supplicant源码分析–连接AP过程
- Android wpa_supplicant连接ap
- Android wpa_supplicant源码分析–扫描scan过程
- wpa_supplicant--连接过程分析
- wpa_supplicant连接ap
- Android wpa_supplicant源码分析--conf配置文件
- Android wpa_supplicant源码分析--bss扫描结果
- Android wpa_supplicant源码分析--运行方式
- Android wpa_supplicant源码分析--conf配置文件
- Android wpa_supplicant源码分析--conf配置文件
- Android GATT 连接过程源码分析
- wpa_supplicant 源码分析
- wpa_supplicant源码分析整理
- wpa_supplicant源码分析
- Android wpa_supplicant源码分析--启动之全局初始化
- Android wpa_supplicant源码分析--启动之网络接口初始化
- Android wpa_supplicant源码分析---内核通信Netlink简介
- Android wpa_supplicant源码分析---nl80211内核通信Generic Netlink
- makefile的本质
- JSON在线编辑器V2.0
- String为什么尽量少用+ stringbuildd的原因
- 用mongo-connector同步生成的EelasticSearch索引如何添加中文分词ik
- [知其然不知其所以然-30] hibernation pages save/restore
- Android wpa_supplicant源码分析–连接AP过程
- ListView添加headerview实现连动滑动
- 抽象工厂模式(Abstract Factory)
- C语言控制语句
- py2exe找不到Python的解决方法
- 再不编程我们就毕业了
- 省市级联菜单
- 单/多处理器调度知识结构
- CSS权威指南-id选择器