1. 接口定义实现wpa_drivers
wpa_drivers的定义如下:
1 struct wpa_driver_ops *wpa_drivers[] = 2 { 3 #ifdef CONFIG_DRIVER_WEXT 4 &wpa_driver_wext_ops, // 我的系统使用的这个老的接口 5 #endif /* CONFIG_DRIVER_WEXT */ 6 #ifdef CONFIG_DRIVER_NL80211 // 现在流行的NL80211接口 7 &wpa_driver_nl80211_ops, 8 #endif /* CONFIG_DRIVER_NL80211 */ 9 #ifdef CONFIG_DRIVER_HOSTAP 10 &wpa_driver_hostap_ops, 11 #endif /* CONFIG_DRIVER_HOSTAP */ 12 #ifdef CONFIG_DRIVER_MADWIFI 13 &wpa_driver_madwifi_ops, 14 #endif /* CONFIG_DRIVER_MADWIFI */ 15 #ifdef CONFIG_DRIVER_BROADCOM 16 &wpa_driver_broadcom_ops, 17 #endif /* CONFIG_DRIVER_BROADCOM */ 18 #ifdef CONFIG_DRIVER_BSD 19 &wpa_driver_bsd_ops, 20 #endif /* CONFIG_DRIVER_BSD */ 21 #ifdef CONFIG_DRIVER_NDIS 22 &wpa_driver_ndis_ops, 23 #endif /* CONFIG_DRIVER_NDIS */ 24 #ifdef CONFIG_DRIVER_WIRED 25 &wpa_driver_wired_ops, 26 #endif /* CONFIG_DRIVER_WIRED */ 27 #ifdef CONFIG_DRIVER_TEST 28 &wpa_driver_test_ops, 29 #endif /* CONFIG_DRIVER_TEST */ 30 #ifdef CONFIG_DRIVER_RALINK 31 &wpa_driver_ralink_ops, 32 #endif /* CONFIG_DRIVER_RALINK */ 33 #ifdef CONFIG_DRIVER_OSX 34 &wpa_driver_osx_ops, 35 #endif /* CONFIG_DRIVER_OSX */ 36 #ifdef CONFIG_DRIVER_IPHONE 37 &wpa_driver_iphone_ops, 38 #endif /* CONFIG_DRIVER_IPHONE */ 39 #ifdef CONFIG_DRIVER_ROBOSWITCH 40 &wpa_driver_roboswitch_ops, 41 #endif /* CONFIG_DRIVER_ROBOSWITCH */ 42 #ifdef CONFIG_DRIVER_ATHEROS 43 &wpa_driver_atheros_ops, 44 #endif /* CONFIG_DRIVER_ATHEROS */ 45 #ifdef CONFIG_DRIVER_NONE 46 &wpa_driver_none_ops, 47 #endif /* CONFIG_DRIVER_NONE */ 48 NULL 49 };
具体选择哪一个driver,由wpa_supplicant的命令参数决定,如我的如下:
在init.myboard.rc中定义:
1 service wpa_supplicant /system/bin/wpa_supplicant \ 2 -Dwext -iwlan0 -c/data/misc/wifi/wpa_supplicant.conf 3 #-Dnl80211 -iwlan0 -puse_p2p_group_interface=1 -e/data/misc/wifi/entropy.bin 4 # we will start as root and wpa_supplicant will switch to user wifi 5 # after setting up the capabilities required for WEXT 6 # user wifi 7 # group wifi inet keystore 8 class main 9 socket wpa_wlan0 dgram 660 wifi wifi 10 disabled 11 oneshot
由上可见,我的选择是wext, 即选择了:wpa_driver_wext_ops。具体选择在以下函数中实现,并最后保存在wpa_supplicant->driver中,以供在wpa_drv_scan中使用。
1 static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, 2 const char *name) 3 { 4 int i; 5 size_t len; 6 const char *pos, *driver = name; 7 8 if (wpa_s == NULL) 9 return -1; 10 11 wpa_msg(wpa_s,MSG_ERROR,"***MY_WIFI:%s,name=%s\n",__FUNCTION__,name); 12 13 if (wpa_drivers[0] == NULL) { 14 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into " 15 "wpa_supplicant"); 16 return -1; 17 } 18 19 if (name == NULL) { 20 /* default to first driver in the list */ 21 wpa_s->driver = wpa_drivers[0]; 22 wpa_s->global_drv_priv = wpa_s->global->drv_priv[0]; 23 return 0; 24 } 25 26 do { 27 pos = os_strchr(driver, ','); 28 if (pos) 29 len = pos - driver; 30 else 31 len = os_strlen(driver); 32 33 for (i = 0; wpa_drivers[i]; i++) { 34 if (os_strlen(wpa_drivers[i]->name) == len && 35 os_strncmp(driver, wpa_drivers[i]->name, len) == 36 0) { 37 wpa_s->driver = wpa_drivers[i]; // 根据name进行匹配,并最后保存到wpa_supplicant->dirver中 38 wpa_s->global_drv_priv = 39 wpa_s->global->drv_priv[i]; 40 return 0; 41 } 42 } 43 44 driver = pos + 1; 45 } while (pos); 46 47 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name); 48 return -1; 49 }
2. 接口操作函数实现
2.1 用户态实现
用户态实现的操作函数如下:
实现代码见:/external/wpa_supplicant_8/wpa_supplicant/src/drivers/driver_wext.c
1 const struct wpa_driver_ops wpa_driver_wext_ops = { 2 .name = "wext", 3 .desc = "Linux wireless extensions (generic)", 4 .get_bssid = wpa_driver_wext_get_bssid, 5 .get_ssid = wpa_driver_wext_get_ssid, 6 #ifdef WAPI 7 .set_wapi = wpa_driver_wext_set_wapi, 8 #endif 9 .set_key = wpa_driver_wext_set_key, 10 .set_countermeasures = wpa_driver_wext_set_countermeasures, 11 .scan2 = wpa_driver_wext_scan, 12 .get_scan_results2 = wpa_driver_wext_get_scan_results, 13 .deauthenticate = wpa_driver_wext_deauthenticate, 14 .disassociate = wpa_driver_wext_disassociate, 15 .associate = wpa_driver_wext_associate, 16 .init = wpa_driver_wext_init, // 初始ioctl socket, netlink socket 17 .deinit = wpa_driver_wext_deinit, 18 .add_pmkid = wpa_driver_wext_add_pmkid, 19 .remove_pmkid = wpa_driver_wext_remove_pmkid, 20 .flush_pmkid = wpa_driver_wext_flush_pmkid, 21 .get_capa = wpa_driver_wext_get_capa, 22 .set_operstate = wpa_driver_wext_set_operstate, 23 .get_radio_name = wext_get_radio_name, 24 #ifdef ANDROID 25 .signal_poll = wpa_driver_signal_poll, 26 .driver_cmd = wpa_driver_wext_driver_cmd, // 对应驱动中的 cfg80211_wext_setpriv 27 #endif 28 };
.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
执行流程如下所示:
wpa_supplicant_ctrl_iface_process-> (根据命令字符串调用对应的函数)
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态实现
Kernel态实现的操作函数如下:
实现代码见:net/wireless/wext_compat.c
1 static const iw_handler cfg80211_handlers[] = { 2 [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, 3 [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, 4 [IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq, 5 [IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode, 6 [IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode, 7 [IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange, 8 [IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap, 9 [IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap, 10 [IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme, 11 [IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan, 12 [IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan, 13 [IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid, 14 [IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid, 15 [IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate, 16 [IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate, 17 [IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts, 18 [IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts, 19 [IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag, 20 [IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag, 21 [IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower, 22 [IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower, 23 [IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry, 24 [IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry, 25 [IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode, 26 [IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode, 27 [IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower, 28 [IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower, 29 [IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie, 30 [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, 31 [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, 32 [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, 33 [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa, 34 [IW_IOCTL_IDX(SIOCSIWPRIV)] = (iw_handler)cfg80211_wext_setpriv 35 }; 36 37 const struct iw_handler_def cfg80211_wext_handler = { 38 .num_standard = ARRAY_SIZE(cfg80211_handlers), 39 .standard = cfg80211_handlers, 40 .get_wireless_stats = cfg80211_wireless_stats, 41 };
2.3 用户态与Kernel态的交互
用户态向Kernel态发送请求时,通过ioctl来实现。
Kernel态向用户态发送事件通知,通过netlink来实现。
其交互的初始化在wpa_driver_wext_init中实现,其代码如下:
1 /** 2 * wpa_driver_wext_init - Initialize WE driver interface 3 * @ctx: context to be used when calling wpa_supplicant functions, 4 * e.g., wpa_supplicant_event() 5 * @ifname: interface name, e.g., wlan0 6 * Returns: Pointer to private data, %NULL on failure 7 */ 8 void * wpa_driver_wext_init(void *ctx, const char *ifname) // 我的ifname为wlan0 9 { 10 struct wpa_driver_wext_data *drv; 11 struct netlink_config *cfg; 12 struct rfkill_config *rcfg; 13 char path[128]; 14 struct stat buf; 15 16 wpa_printf(MSG_ERROR,"***MY_WIFI:%s,ifname=%s\n",__FUNCTION__,ifname); 17 18 drv = os_zalloc(sizeof(*drv)); 19 if (drv == NULL) 20 return NULL; 21 drv->ctx = ctx; 22 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 23 24 os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname); 25 if (stat(path, &buf) == 0) { 26 wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected"); 27 drv->cfg80211 = 1; 28 wext_get_phy_name(drv); 29 } 30 31 drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); // 此drv->ioctl_sock用作为ioctl命令的fd 32 if (drv->ioctl_sock < 0) { 33 perror("socket(PF_INET,SOCK_DGRAM)"); 34 goto err1; 35 } 36 37 cfg = os_zalloc(sizeof(*cfg)); 38 if (cfg == NULL) 39 goto err1; 40 cfg->ctx = drv; 41 cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink; 42 cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink; 43 drv->netlink = netlink_init(cfg); // 初始化netlink,并注册事件接收函数 44 if (drv->netlink == NULL) { 45 os_free(cfg); 46 goto err2; 47 } 48 49 rcfg = os_zalloc(sizeof(*rcfg)); 50 if (rcfg == NULL) 51 goto err3; 52 rcfg->ctx = drv; 53 os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname)); 54 rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked; 55 rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked; 56 drv->rfkill = rfkill_init(rcfg); 57 if (drv->rfkill == NULL) { 58 wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available"); 59 os_free(rcfg); 60 } 61 62 drv->mlme_sock = -1; 63 #ifdef ANDROID 64 drv->errors = 0; 65 drv->driver_is_started = TRUE; 66 drv->skip_disconnect = 0; 67 drv->bgscan_enabled = 0; 68 #endif 69 70 if (wpa_driver_wext_finish_drv_init(drv) < 0) 71 goto err3; 72 73 wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1); 74 75 return drv; 76 77 err3: 78 rfkill_deinit(drv->rfkill); 79 netlink_deinit(drv->netlink); 80 err2: 81 close(drv->ioctl_sock); 82 err1: 83 os_free(drv); 84 return NULL; 85 }
其中参数ifname在/data/misc/wifi/wpa_supplicant.conf中被定义,如我的如下:
1 update_config=1 2 ctrl_interface=wlan0 3 eapol_version=1 4 ap_scan=1 5 fast_reauth=1
2.3.1 ioctl实现方案
在用户态可简单执行一个ioctl(fd,cmd,...)命令即可。
在Kernel态则是通过唯一的cmd (SIOCIWFIRST--SIOCIWLAST) 来进行区分,从而执行cfg80211_handlers中对应的函数。
socket文件操作如下:
1 /* 2 * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear 3 * in the operation structures but are done directly via the socketcall() multiplexor. 4 */ 5 6 static const struct file_operations socket_file_ops = { 7 .owner = THIS_MODULE, 8 .llseek = no_llseek, 9 .aio_read = sock_aio_read, 10 .aio_write = sock_aio_write, 11 .poll = sock_poll, 12 .unlocked_ioctl = sock_ioctl, // 这个就是被执行的ioctl 13 #ifdef CONFIG_COMPAT 14 .compat_ioctl = compat_sock_ioctl, 15 #endif 16 .mmap = sock_mmap, 17 .open = sock_no_open, /* special open code to disallow open via /proc */ 18 .release = sock_close, 19 .fasync = sock_fasync, 20 .sendpage = sock_sendpage, 21 .splice_write = generic_splice_sendpage, 22 .splice_read = sock_splice_read, 23 };
从sock_ioctl到iw_handler的执行注程如下所示:
sock_ioctl->
dev_ioctl->
wext_handle_ioctl-> (把执行结果从kernel态copy到用户态)
wext_ioctl_dispatch->
wireless_process_ioctl->
1) get_handler
2) ioctl_standard_call (执行cmd指定的iw_handler<cfg80211_handlers中定义的>,并返回结果)
1 static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) 2 { 3 struct socket *sock; 4 struct sock *sk; 5 void __user *argp = (void __user *)arg; 6 int pid, err; 7 struct net *net; 8 9 sock = file->private_data; 10 sk = sock->sk; 11 net = sock_net(sk); 12 if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { 13 err = dev_ioctl(net, cmd, argp); 14 } else 15 #ifdef CONFIG_WEXT_CORE 16 if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { 17 err = dev_ioctl(net, cmd, argp); //执行dev_ioctl 18 } else 19 #endif 20 ... 21 } 22 return err; 23 }
1 int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) 2 { 3 struct ifreq ifr; 4 int ret; 5 char *colon; 6 7 8 /* 9 * See which interface the caller is talking about. 10 */ 11 12 switch (cmd) { 13 14 /* 15 * Unknown or private ioctl. 16 */ 17 default: 18 /* Take care of Wireless Extensions */ 19 if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) 20 return wext_handle_ioctl(net, &ifr, cmd, arg); // 执行wext_handle_ioctl 21 return -ENOTTY; 22 } 23 }
1 int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, 2 void __user *arg) 3 { 4 struct iw_request_info info = { .cmd = cmd, .flags = 0 }; 5 int ret; 6 7 ret = wext_ioctl_dispatch(net, ifr, cmd, &info, // 执行wext_ioctl_dispatch 8 ioctl_standard_call, 9 ioctl_private_call); 10 if (ret >= 0 && 11 IW_IS_GET(cmd) && 12 copy_to_user(arg, ifr, sizeof(struct iwreq))) // 把执行结果copy到用户空间 13 return -EFAULT; 14 15 return ret; 16 }
1 /* entry point from dev ioctl */ 2 static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, 3 unsigned int cmd, struct iw_request_info *info, 4 wext_ioctl_func standard, 5 wext_ioctl_func private) 6 { 7 int ret = wext_permission_check(cmd); 8 9 if (ret) 10 return ret; 11 12 dev_load(net, ifr->ifr_name); 13 rtnl_lock(); 14 ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private); //执行wireless_process_ioctl 15 16 rtnl_unlock(); 17 18 return ret; 19 }
1 static iw_handler get_handler(struct net_device *dev, unsigned int cmd) 2 { 3 /* Don't "optimise" the following variable, it will crash */ 4 unsigned int index; /* *MUST* be unsigned */ 5 const struct iw_handler_def *handlers = NULL; 6 //printk("***IDONG_WIFI:%s,cmd=0x%x\n",__FUNCTION__,cmd); 7 #ifdef CONFIG_CFG80211_WEXT 8 if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy) 9 handlers = dev->ieee80211_ptr->wiphy->wext; 10 #endif 11 #ifdef CONFIG_WIRELESS_EXT 12 if (dev->wireless_handlers) 13 handlers = dev->wireless_handlers; 14 #endif 15 16 if (!handlers) 17 return NULL; 18 19 /* Try as a standard command */ 20 index = IW_IOCTL_IDX(cmd); 21 if (index < handlers->num_standard) 22 return handlers->standard[index]; 23 24 #ifdef CONFIG_WEXT_PRIV 25 /* Try as a private command */ 26 index = cmd - SIOCIWFIRSTPRIV; 27 if (index < handlers->num_private) 28 return handlers->private[index]; 29 #endif 30 31 /* Not found */ 32 return NULL; 33 }
1 static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, 2 unsigned int cmd, 3 struct iw_request_info *info, 4 wext_ioctl_func standard, 5 wext_ioctl_func private) 6 { 7 struct iwreq *iwr = (struct iwreq *) ifr; 8 struct net_device *dev; 9 iw_handler handler; 10 11 /* Permissions are already checked in dev_ioctl() before calling us. 12 * The copy_to/from_user() of ifr is also dealt with in there */ 13 14 /* Make sure the device exist */ 15 if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL) 16 return -ENODEV; 17 18 /* A bunch of special cases, then the generic case... 19 * Note that 'cmd' is already filtered in dev_ioctl() with 20 * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ 21 if (cmd == SIOCGIWSTATS) 22 return standard(dev, iwr, cmd, info, 23 &iw_handler_get_iwstats); 24 25 #ifdef CONFIG_WEXT_PRIV 26 if (cmd == SIOCGIWPRIV && dev->wireless_handlers) 27 return standard(dev, iwr, cmd, info, 28 iw_handler_get_private); 29 #endif 30 31 /* Basic check */ 32 if (!netif_device_present(dev)) 33 return -ENODEV; 34 35 /* New driver API : try to find the handler */ 36 handler = get_handler(dev, cmd); 37 if (handler) { 38 /* Standard and private are not the same */ 39 if (cmd < SIOCIWFIRSTPRIV) 40 return standard(dev, iwr, cmd, info, handler); // 去执行对应的iw_handler 41 else if (private) 42 return private(dev, iwr, cmd, info, handler); 43 } 44 /* Old driver API : call driver ioctl handler */ 45 if (dev->netdev_ops->ndo_do_ioctl) 46 return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); 47 return -EOPNOTSUPP; 48 }
2.3.2 用户态初始化netlink
1 struct netlink_data * netlink_init(struct netlink_config *cfg) 2 { 3 struct netlink_data *netlink; 4 struct sockaddr_nl local; 5 6 netlink = os_zalloc(sizeof(*netlink)); 7 if (netlink == NULL) 8 return NULL; 9 10 netlink->cfg = cfg; 11 12 netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 13 if (netlink->sock < 0) { 14 wpa_printf(MSG_ERROR, "netlink: Failed to open netlink " 15 "socket: %s", strerror(errno)); 16 netlink_deinit(netlink); 17 return NULL; 18 } 19 20 os_memset(&local, 0, sizeof(local)); 21 local.nl_family = AF_NETLINK; 22 local.nl_groups = RTMGRP_LINK; 23 if (bind(netlink->sock, (struct sockaddr *) &local, sizeof(local)) < 0) 24 { 25 wpa_printf(MSG_ERROR, "netlink: Failed to bind netlink " 26 "socket: %s", strerror(errno)); 27 netlink_deinit(netlink); 28 return NULL; 29 } 30 31 eloop_register_read_sock(netlink->sock, netlink_receive, netlink, 32 NULL); 33 34 return netlink; 35 }
2.3.3 用户态netlink事件接收函数netlink_receive
1 static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx) 2 { 3 struct netlink_data *netlink = eloop_ctx; 4 char buf[8192]; 5 int left; 6 struct sockaddr_nl from; 7 socklen_t fromlen; 8 struct nlmsghdr *h; 9 int max_events = 10; 10 11 try_again: 12 fromlen = sizeof(from); 13 left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, //从netlink读取事件 14 (struct sockaddr *) &from, &fromlen); 15 if (left < 0) { 16 if (errno != EINTR && errno != EAGAIN) 17 wpa_printf(MSG_INFO, "netlink: recvfrom failed: %s", 18 strerror(errno)); 19 return; 20 } 21 22 h = (struct nlmsghdr *) buf; 23 while (NLMSG_OK(h, left)) { 24 switch (h->nlmsg_type) { 25 case RTM_NEWLINK: 26 netlink_receive_link(netlink, netlink->cfg->newlink_cb, 27 h); 28 break; 29 case RTM_DELLINK: 30 netlink_receive_link(netlink, netlink->cfg->dellink_cb, 31 h); 32 break; 33 } 34 35 h = NLMSG_NEXT(h, left); 36 } 37 38 if (left > 0) { 39 wpa_printf(MSG_DEBUG, "netlink: %d extra bytes in the end of " 40 "netlink message", left); 41 } 42 43 if (--max_events > 0) { 44 /* 45 * Try to receive all events in one eloop call in order to 46 * limit race condition on cases where AssocInfo event, Assoc 47 * event, and EAPOL frames are received more or less at the 48 * same time. We want to process the event messages first 49 * before starting EAPOL processing. 50 */ 51 goto try_again; 52 } 53 }
3. SCAN流程
wpa_supplicant_ctrl_iface_process-> ( buf 内容为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-> (根据local当前状态进行下一步工作,直到工作完成)
__ieee80211_scan_completed-> (所有扫描的工作完成之后,调用此函数)
drv_sw_scan_complete->
local->ops->sw_scan_complete( ieee80211_ops ath9k_htc_ops->sw_scan_complete)
ath9k_htc_sw_scan_complete
• ieee80211_scan_work函数详细代码如下:
1 void ieee80211_scan_work(struct work_struct *work) 2 { 3 struct ieee80211_local *local = 4 container_of(work, struct ieee80211_local, scan_work.work); 5 struct ieee80211_sub_if_data *sdata; 6 unsigned long next_delay = 0; 7 bool aborted, hw_scan; 8 9 mutex_lock(&local->mtx); 10 11 sdata = local->scan_sdata; 12 13 if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { 14 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); 15 goto out_complete; 16 } 17 18 if (!sdata || !local->scan_req) 19 goto out; 20 21 if (local->scan_req && !local->scanning) { 22 struct cfg80211_scan_request *req = local->scan_req; 23 int rc; 24 25 local->scan_req = NULL; 26 local->scan_sdata = NULL; 27 28 rc = __ieee80211_start_scan(sdata, req); 29 if (rc) { 30 /* need to complete scan in cfg80211 */ 31 local->scan_req = req; 32 aborted = true; 33 goto out_complete; 34 } else 35 goto out; 36 } 37 38 /* 39 * Avoid re-scheduling when the sdata is going away. 40 */ 41 if (!ieee80211_sdata_running(sdata)) { 42 aborted = true; 43 goto out_complete; 44 } 45 46 /* 47 * as long as no delay is required advance immediately 48 * without scheduling a new work 49 */ 50 do { 51 if (!ieee80211_sdata_running(sdata)) { 52 aborted = true; 53 goto out_complete; 54 } 55 56 switch (local->next_scan_state) { 57 case SCAN_DECISION: 58 /* if no more bands/channels left, complete scan */ 59 if (local->scan_channel_idx >= local->scan_req->n_channels) { 60 aborted = false; 61 goto out_complete; 62 } 63 ieee80211_scan_state_decision(local, &next_delay); 64 break; 65 case SCAN_SET_CHANNEL: 66 ieee80211_scan_state_set_channel(local, &next_delay); 67 break; 68 case SCAN_SEND_PROBE: 69 ieee80211_scan_state_send_probe(local, &next_delay); 70 break; 71 case SCAN_LEAVE_OPER_CHANNEL: 72 ieee80211_scan_state_leave_oper_channel(local, &next_delay); 73 break; 74 case SCAN_ENTER_OPER_CHANNEL: 75 ieee80211_scan_state_enter_oper_channel(local, &next_delay); 76 break; 77 } 78 } while (next_delay == 0); 79 80 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); 81 goto out; 82 83 out_complete: 84 hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); 85 __ieee80211_scan_completed(&local->hw, aborted, hw_scan); 86 out: 87 mutex_unlock(&local->mtx); 88 }