wpa_supplicant与kernel的接口
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
1. 接口定義實(shí)現(xiàn)wpa_drivers
?
??wpa_drivers的定義如下:
[cpp]?view plaincopy
struct?wpa_driver_ops?*wpa_drivers[]?=??
{??
#ifdef?CONFIG_DRIVER_WEXT??
????&wpa_driver_wext_ops,??//?我的系統(tǒng)使用的這個(gè)老的接口??
#endif???
#ifdef?CONFIG_DRIVER_NL80211???//?現(xiàn)在流行的NL80211接口??
????&wpa_driver_nl80211_ops,??
#endif???
#ifdef?CONFIG_DRIVER_HOSTAP??
????&wpa_driver_hostap_ops,??
#endif???
#ifdef?CONFIG_DRIVER_MADWIFI??
????&wpa_driver_madwifi_ops,??
#endif???
#ifdef?CONFIG_DRIVER_BROADCOM??
????&wpa_driver_broadcom_ops,??
#endif???
#ifdef?CONFIG_DRIVER_BSD??
????&wpa_driver_bsd_ops,??
#endif???
#ifdef?CONFIG_DRIVER_NDIS??
????&wpa_driver_ndis_ops,??
#endif???
#ifdef?CONFIG_DRIVER_WIRED??
????&wpa_driver_wired_ops,??
#endif???
#ifdef?CONFIG_DRIVER_TEST??
????&wpa_driver_test_ops,??
#endif???
#ifdef?CONFIG_DRIVER_RALINK??
????&wpa_driver_ralink_ops,??
#endif???
#ifdef?CONFIG_DRIVER_OSX??
????&wpa_driver_osx_ops,??
#endif???
#ifdef?CONFIG_DRIVER_IPHONE??
????&wpa_driver_iphone_ops,??
#endif???
#ifdef?CONFIG_DRIVER_ROBOSWITCH??
????&wpa_driver_roboswitch_ops,??
#endif???
#ifdef?CONFIG_DRIVER_ATHEROS??
????&wpa_driver_atheros_ops,??
#endif???
#ifdef?CONFIG_DRIVER_NONE??
????&wpa_driver_none_ops,??
#endif???
????NULL??
}; ?
???具體選擇哪一個(gè)driver,由wpa_supplicant的命令參數(shù)決定,如我的如下:
???在init.myboard.rc中定義:
?
[cpp]?view plaincopy
service?wpa_supplicant?/system/bin/wpa_supplicant?\??
????-Dwext?-iwlan0?-c/data/misc/wifi/wpa_supplicant.conf??
????#-Dnl80211?-iwlan0?-puse_p2p_group_interface=1?-e/data/misc/wifi/entropy.bin??
????#???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??
????oneshot ?
???由上可見,我的選擇是wext, 即選擇了:wpa_driver_wext_ops。具體選擇在以下函數(shù)中實(shí)現(xiàn),并最后保存在wpa_supplicant->driver中,以供在wpa_drv_scan中使用。
? 首先需要講解一下,在android4.0之后,wifi的工作方式基本都采用的是比較標(biāo)準(zhǔn)的nl80211方式,以前的wext方式現(xiàn)在使用的已經(jīng)很少了,關(guān)于nl80211和wext的區(qū)別,小弟由于接觸的少,所以簡單的說兩句(有錯(cuò)誤的請(qǐng)各位大大指正啊,萬謝!)
???wext:supplicant通過wext直接給wifi driver下命令,即不通過kernel,所以一般以wext工作的driver是不需要load cfg80211.ko的,這個(gè)cfg80211.ko就是kernel里面的wireless部分,主要對(duì)接supplicant和driver的。
???nl80211:supplicant的命令以nl80211的方式下給kernel,經(jīng)過kernel再發(fā)送給driver,這樣子做的好處是 supplicant和driver之間的通訊方式更加標(biāo)準(zhǔn)話,是以后的主流方式,我后面講的driver都是以這種方式工作的。
[cpp]?view plaincopy
static?int?wpa_supplicant_set_driver(struct?wpa_supplicant?*wpa_s,??
?????????????????????const?char?*name)??
{??
????int?i;??
????size_t?len;??
????const?char?*pos,?*driver?=?name;??
??
????if?(wpa_s?==?NULL)??
????????return?-1;??
??
???????wpa_msg(wpa_s,MSG_ERROR,"***MY_WIFI:%s,name=%s\n",__FUNCTION__,name);??
??????
????if?(wpa_drivers[0]?==?NULL)?{??
????????wpa_msg(wpa_s,?MSG_ERROR,?"No?driver?interfaces?build?into?"??
????????????"wpa_supplicant");??
????????return?-1;??
????}??
??
????if?(name?==?NULL)?{??
??????????
????????wpa_s->driver?=?wpa_drivers[0];??
????????wpa_s->global_drv_priv?=?wpa_s->global->drv_priv[0];??
????????return?0;??
????}??
??
????do?{??
????????pos?=?os_strchr(driver,?',');??
????????if?(pos)??
????????????len?=?pos?-?driver;??
????????else??
????????????len?=?os_strlen(driver);??
??
????????for?(i?=?0;?wpa_drivers[i];?i++)?{??
????????????if?(os_strlen(wpa_drivers[i]->name)?==?len?&&??
????????????????os_strncmp(driver,?wpa_drivers[i]->name,?len)?==??
????????????????0)?{??
????????????????wpa_s->driver?=?wpa_drivers[i];??//?根據(jù)name進(jìn)行匹配,并最后保存到wpa_supplicant->dirver中??
????????????????wpa_s->global_drv_priv?=??
????????????????????wpa_s->global->drv_priv[i];??
????????????????return?0;??
????????????}??
????????}??
??
????????driver?=?pos?+?1;??
????}?while?(pos);??
??
????wpa_msg(wpa_s,?MSG_ERROR,?"Unsupported?driver?'%s'",?name);??
????return?-1;??
} ?
2. 接口操作函數(shù)實(shí)現(xiàn)
2.1 用戶態(tài)實(shí)現(xiàn)
??用戶態(tài)實(shí)現(xiàn)的操作函數(shù)如下:
??實(shí)現(xiàn)代碼見:/external/wpa_supplicant_8/wpa_supplicant/src/drivers/driver_wext.c
?
[cpp]?view plaincopy
const?struct?wpa_driver_ops?wpa_driver_wext_ops?=?{??
????.name?=?"wext",??
????.desc?=?"Linux?wireless?extensions?(generic)",??
????.get_bssid?=?wpa_driver_wext_get_bssid,??
????.get_ssid?=?wpa_driver_wext_get_ssid,??
#ifdef?WAPI??
????.set_wapi?=?wpa_driver_wext_set_wapi,??
#endif??
????.set_key?=?wpa_driver_wext_set_key,??
????.set_countermeasures?=?wpa_driver_wext_set_countermeasures,??
????.scan2?=?wpa_driver_wext_scan,??
????.get_scan_results2?=?wpa_driver_wext_get_scan_results,??
????.deauthenticate?=?wpa_driver_wext_deauthenticate,??
????.disassociate?=?wpa_driver_wext_disassociate,??
????.associate?=?wpa_driver_wext_associate,??
????.init?=?wpa_driver_wext_init,?//?初始ioctl?socket,?netlink?socket??
????.deinit?=?wpa_driver_wext_deinit,??
????.add_pmkid?=?wpa_driver_wext_add_pmkid,??
????.remove_pmkid?=?wpa_driver_wext_remove_pmkid,??
????.flush_pmkid?=?wpa_driver_wext_flush_pmkid,??
????.get_capa?=?wpa_driver_wext_get_capa,??
????.set_operstate?=?wpa_driver_wext_set_operstate,??
????.get_radio_name?=?wext_get_radio_name,??
#ifdef?ANDROID??
????.signal_poll?=?wpa_driver_signal_poll,??
????.driver_cmd?=?wpa_driver_wext_driver_cmd,?//?對(duì)應(yīng)驅(qū)動(dòng)中的?cfg80211_wext_setpriv??
#endif??
}; ?
.driver_cmd處理以DRIVER開始的命令,如:
???DRIVER MACADDR
???DRIVER BTCOEXSCAN-STOP
???DRIVER RXFILTER-ADD 3
???DRIVER RXFILTER-START
???DRIVER RXFILTER-STOP
???DRIVER RXFILTER-REMOVE 2
???DRIVER RXFILTER-START
??DRIVER SETBAND 0
???DRIVER SCAN-ACTIVE
???DRIVER SCAN-PASSIVE
??執(zhí)行流程如下所示:
???wpa_supplicant_ctrl_iface_process-> (根據(jù)命令字符串調(diào)用對(duì)應(yīng)的函數(shù))
????wpa_supplicant_driver_cmd->
?????wpa_drv_driver_cmd->
??????wpa_s->driver->driver_cmd->
???????wpa_driver_wext_driver_cmd-> (User)
??????...
???????cfg80211_wext_setpriv(Kernel)
2.2 Kernel態(tài)實(shí)現(xiàn) ???
???Kernel態(tài)實(shí)現(xiàn)的操作函數(shù)如下:
???實(shí)現(xiàn)代碼見:net/wireless/wext_compat.c
?
[cpp]?view plaincopy
static?const?iw_handler?cfg80211_handlers[]?=?{??
????[IW_IOCTL_IDX(SIOCGIWNAME)]?=?(iw_handler)?cfg80211_wext_giwname,??
????[IW_IOCTL_IDX(SIOCSIWFREQ)]?=?(iw_handler)?cfg80211_wext_siwfreq,??
????[IW_IOCTL_IDX(SIOCGIWFREQ)]?=?(iw_handler)?cfg80211_wext_giwfreq,??
????[IW_IOCTL_IDX(SIOCSIWMODE)]?=?(iw_handler)?cfg80211_wext_siwmode,??
????[IW_IOCTL_IDX(SIOCGIWMODE)]?=?(iw_handler)?cfg80211_wext_giwmode,??
????[IW_IOCTL_IDX(SIOCGIWRANGE)]????=?(iw_handler)?cfg80211_wext_giwrange,??
????[IW_IOCTL_IDX(SIOCSIWAP)]???=?(iw_handler)?cfg80211_wext_siwap,??
????[IW_IOCTL_IDX(SIOCGIWAP)]???=?(iw_handler)?cfg80211_wext_giwap,??
????[IW_IOCTL_IDX(SIOCSIWMLME)]?=?(iw_handler)?cfg80211_wext_siwmlme,??
????[IW_IOCTL_IDX(SIOCSIWSCAN)]?=?(iw_handler)?cfg80211_wext_siwscan,??
????[IW_IOCTL_IDX(SIOCGIWSCAN)]?=?(iw_handler)?cfg80211_wext_giwscan,??
????[IW_IOCTL_IDX(SIOCSIWESSID)]????=?(iw_handler)?cfg80211_wext_siwessid,??
????[IW_IOCTL_IDX(SIOCGIWESSID)]????=?(iw_handler)?cfg80211_wext_giwessid,??
????[IW_IOCTL_IDX(SIOCSIWRATE)]?=?(iw_handler)?cfg80211_wext_siwrate,??
????[IW_IOCTL_IDX(SIOCGIWRATE)]?=?(iw_handler)?cfg80211_wext_giwrate,??
????[IW_IOCTL_IDX(SIOCSIWRTS)]??=?(iw_handler)?cfg80211_wext_siwrts,??
????[IW_IOCTL_IDX(SIOCGIWRTS)]??=?(iw_handler)?cfg80211_wext_giwrts,??
????[IW_IOCTL_IDX(SIOCSIWFRAG)]?=?(iw_handler)?cfg80211_wext_siwfrag,??
????[IW_IOCTL_IDX(SIOCGIWFRAG)]?=?(iw_handler)?cfg80211_wext_giwfrag,??
????[IW_IOCTL_IDX(SIOCSIWTXPOW)]????=?(iw_handler)?cfg80211_wext_siwtxpower,??
????[IW_IOCTL_IDX(SIOCGIWTXPOW)]????=?(iw_handler)?cfg80211_wext_giwtxpower,??
????[IW_IOCTL_IDX(SIOCSIWRETRY)]????=?(iw_handler)?cfg80211_wext_siwretry,??
?..........................
??
const?struct?iw_handler_def?cfg80211_wext_handler?=?{??
????.num_standard???????=?ARRAY_SIZE(cfg80211_handlers),??
????.standard???????=?cfg80211_handlers,??
????.get_wireless_stats?=?cfg80211_wireless_stats,??
};??
2.3 用戶態(tài)與Kernel態(tài)的交互
????用戶態(tài)向Kernel態(tài)發(fā)送請(qǐng)求時(shí),通過ioctl來實(shí)現(xiàn)。
???Kernel態(tài)向用戶態(tài)發(fā)送事件通知,通過netlink來實(shí)現(xiàn)。
???其交互的初始化在wpa_driver_wext_init中實(shí)現(xiàn),其代碼如下:
?
[cpp]?view plaincopy
??
void?*?wpa_driver_wext_init(void?*ctx,?const?char?*ifname)?//?我的ifname為wlan0??
{??
????struct?wpa_driver_wext_data?*drv;??
????struct?netlink_config?*cfg;??
????struct?rfkill_config?*rcfg;??
????char?path[128];??
????struct?stat?buf;??
??
????????wpa_printf(MSG_ERROR,"***MY_WIFI:%s,ifname=%s\n",__FUNCTION__,ifname);??
??????
????drv?=?os_zalloc(sizeof(*drv));??
????if?(drv?==?NULL)??
????????return?NULL;??
????drv->ctx?=?ctx;??
????os_strlcpy(drv->ifname,?ifname,?sizeof(drv->ifname));??
??
????os_snprintf(path,?sizeof(path),?"/sys/class/net/%s/phy80211",?ifname);??
????if?(stat(path,?&buf)?==?0)?{??
????????wpa_printf(MSG_DEBUG,?"WEXT:?cfg80211-based?driver?detected");??
????????drv->cfg80211?=?1;??
????????wext_get_phy_name(drv);??
????}??
??
????drv->ioctl_sock?=?socket(PF_INET,?SOCK_DGRAM,?0);??//?此drv->ioctl_sock用作為ioctl命令的fd??
????if?(drv->ioctl_sock?<?0)?{??
????????perror("socket(PF_INET,SOCK_DGRAM)");??
????????goto?err1;??
????}??
??
????cfg?=?os_zalloc(sizeof(*cfg));??
????if?(cfg?==?NULL)??
????????goto?err1;??
????cfg->ctx?=?drv;??
????cfg->newlink_cb?=?wpa_driver_wext_event_rtm_newlink;??
????cfg->dellink_cb?=?wpa_driver_wext_event_rtm_dellink;??
????drv->netlink?=?netlink_init(cfg);??//?初始化netlink,并注冊(cè)事件接收函數(shù)??
????if?(drv->netlink?==?NULL)?{??
????????os_free(cfg);??
????????goto?err2;??
????}??
??
????rcfg?=?os_zalloc(sizeof(*rcfg));??
??
其中參數(shù)ifname在/data/misc/wifi/wpa_supplicant.conf中被定義,如我的如下:
[cpp]?view plaincopy
update_config=1??
ctrl_interface=wlan0??
eapol_version=1??
ap_scan=1??
fast_reauth=1 ?
2.3.1 ioctl實(shí)現(xiàn)方案
???在用戶態(tài)可簡單執(zhí)行一個(gè)ioctl(fd,cmd,...)命令即可。
???在Kernel態(tài)則是通過唯一的cmd (SIOCIWFIRST--SIOCIWLAST)?來進(jìn)行區(qū)分,從而執(zhí)行cfg80211_handlers中對(duì)應(yīng)的函數(shù)。
???socket文件操作如下:
?
[cpp]?view plaincopy
??
??
static?const?struct?file_operations?socket_file_ops?=?{??
????.owner?=????THIS_MODULE,??
????.llseek?=???no_llseek,??
????.aio_read?=?sock_aio_read,??
????.aio_write?=????sock_aio_write,??
????.poll?=?????sock_poll,??
????.unlocked_ioctl?=?sock_ioctl,?//?這個(gè)就是被執(zhí)行的ioctl??
#ifdef?CONFIG_COMPAT??
????.compat_ioctl?=?compat_sock_ioctl,??
#endif??
????.mmap?=?????sock_mmap,??
????.open?=?????sock_no_open,?????
????.release?=??sock_close,??
????.fasync?=???sock_fasync,??
????.sendpage?=?sock_sendpage,??
????.splice_write?=?generic_splice_sendpage,??
????.splice_read?=??sock_splice_read,??
}; ?
從sock_ioctl到iw_handler的執(zhí)行注程如下所示:
?sock_ioctl->
??dev_ioctl->
???wext_handle_ioctl-> (把執(zhí)行結(jié)果從kernel態(tài)copy到用戶態(tài))
????wext_ioctl_dispatch->
?????wireless_process_ioctl->
???????1)?get_handler
???????2) ioctl_standard_call (執(zhí)行cmd指定的iw_handler,并返回結(jié)果)?
?
2.3.2 用戶態(tài)初始化netlink
?
[cpp]?view plaincopy
struct?netlink_data?*?netlink_init(struct?netlink_config?*cfg)??
{??
????struct?netlink_data?*netlink;??
????struct?sockaddr_nl?local;??
??
????netlink?=?os_zalloc(sizeof(*netlink));??
????if?(netlink?==?NULL)??
????????return?NULL;??
??
????netlink->cfg?=?cfg;??
??
????netlink->sock?=?socket(PF_NETLINK,?SOCK_RAW,?NETLINK_ROUTE);??
????if?(netlink->sock?<?0)?{??
????????wpa_printf(MSG_ERROR,?"netlink:?Failed?to?open?netlink?"??
???????????????"socket:?%s",?strerror(errno));??
????????netlink_deinit(netlink);??
????????return?NULL;??
????}??
??
????os_memset(&local,?0,?sizeof(local));??
????local.nl_family?=?AF_NETLINK;??
????local.nl_groups?=?RTMGRP_LINK;??
????if?(bind(netlink->sock,?(struct?sockaddr?*)?&local,?sizeof(local))?<?0)??
????{??
????????wpa_printf(MSG_ERROR,?"netlink:?Failed?to?bind?netlink?"??
???????????????"socket:?%s",?strerror(errno));??
????????netlink_deinit(netlink);??
????????return?NULL;??
????}??
??
????eloop_register_read_sock(netlink->sock,?netlink_receive,?netlink,??
?????????????????NULL);??
??
????return?netlink;??
} ?
2.3.3 用戶態(tài)netlink事件接收函數(shù)netlink_receive
?
[cpp]?view plaincopy
static?void?netlink_receive(int?sock,?void?*eloop_ctx,?void?*sock_ctx)??
{??
????struct?netlink_data?*netlink?=?eloop_ctx;??
????char?buf[8192];??
????int?left;??
????struct?sockaddr_nl?from;??
????socklen_t?fromlen;??
????struct?nlmsghdr?*h;??
????int?max_events?=?10;??
??
try_again:??
????fromlen?=?sizeof(from);??
????left?=?recvfrom(sock,?buf,?sizeof(buf),?MSG_DONTWAIT,?//從netlink讀取事件??
????????????(struct?sockaddr?*)?&from,?&fromlen);??
????if?(left?<?0)?{??
????????if?(errno?!=?EINTR?&&?errno?!=?EAGAIN)??
????????????wpa_printf(MSG_INFO,?"netlink:?recvfrom?failed:?%s",??
???????????????????strerror(errno));??
????????return;??
????}??
??
????h?=
} ?
3. SCAN流程
wpa_supplicant_ctrl_iface_process-> ( buf 內(nèi)容為SCAN )
?wpa_supplicant_req_scan->wpa_supplicant_scan->wpa_supplicant_trigger_scan->wpa_drv_scan->wpa_s->driver->scan2->wpa_driver_wext_scan-> (Request the driver to initiate scan)wpa_driver_wext_combo_scan->ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)-> (User)...cfg80211_wext_setpriv (cmd=CSCAN S)->cfg80211_wext_siwscan->rdev->ops->scan (cfg80211_ops?mac80211_config_ops->scan)->ieee80211_scan->?ieee80211_request_scan->__ieee80211_start_scan->ieee80211_start_sw_scan-><1>?drv_sw_scan_start->local->ops->sw_scan_start(ieee80211_ops?ath9k_htc_ops->sw_scan_start)->ath9k_htc_sw_scan_start->?<2>?ieee80211_hw_config-> (set power level at maximum rate for scanning)drv_config->local->ops->config(?ieee80211_ops?ath9k_htc_ops->config)->?ath9k_htc_config->ath9k_htc_setpower(priv,ATH9K_PM_AWAKE)?<3> ?ieee80211_queue_delayed_work(&local->scan_work)->(注:INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work))?ieee80211_scan_work-> (根據(jù)local當(dāng)前狀態(tài)進(jìn)行下一步工作,直到工作完成)__ieee80211_scan_completed-> (所有掃描的工作完成之后,調(diào)用此函數(shù))drv_sw_scan_complete->local->ops->sw_scan_complete(?ieee80211_ops?ath9k_htc_ops->sw_scan_complete)ath9k_htc_sw_scan_complete
轉(zhuǎn)載于:https://my.oschina.net/u/994235/blog/323261
總結(jié)
以上是生活随笔為你收集整理的wpa_supplicant与kernel的接口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。