【转载】wpa_supplicant与kernel的接口

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 }

 

posted @ 2018-08-09 20:41  葫芦baby  阅读(877)  评论(0编辑  收藏  举报