天天看點

wpa_supplicant 驅動分析

1. 接口定義實作wpa_drivers

    wpa_drivers的定義如下:

[cpp]  view plain copy

  1. struct wpa_driver_ops *wpa_drivers[] =  
  2. {  
  3. #ifdef CONFIG_DRIVER_WEXT  
  4.     &wpa_driver_wext_ops,  // 我的系統使用的這個老的接口  
  5. #endif   
  6. #ifdef CONFIG_DRIVER_NL80211   // 現在流行的NL80211接口  
  7.     &wpa_driver_nl80211_ops,  
  8. #endif   
  9. #ifdef CONFIG_DRIVER_HOSTAP  
  10.     &wpa_driver_hostap_ops,  
  11. #endif   
  12. #ifdef CONFIG_DRIVER_MADWIFI  
  13.     &wpa_driver_madwifi_ops,  
  14. #endif   
  15. #ifdef CONFIG_DRIVER_BROADCOM  
  16.     &wpa_driver_broadcom_ops,  
  17. #endif   
  18. #ifdef CONFIG_DRIVER_BSD  
  19.     &wpa_driver_bsd_ops,  
  20. #endif   
  21. #ifdef CONFIG_DRIVER_NDIS  
  22.     &wpa_driver_ndis_ops,  
  23. #endif   
  24. #ifdef CONFIG_DRIVER_WIRED  
  25.     &wpa_driver_wired_ops,  
  26. #endif   
  27. #ifdef CONFIG_DRIVER_TEST  
  28.     &wpa_driver_test_ops,  
  29. #endif   
  30. #ifdef CONFIG_DRIVER_RALINK  
  31.     &wpa_driver_ralink_ops,  
  32. #endif   
  33. #ifdef CONFIG_DRIVER_OSX  
  34.     &wpa_driver_osx_ops,  
  35. #endif   
  36. #ifdef CONFIG_DRIVER_IPHONE  
  37.     &wpa_driver_iphone_ops,  
  38. #endif   
  39. #ifdef CONFIG_DRIVER_ROBOSWITCH  
  40.     &wpa_driver_roboswitch_ops,  
  41. #endif   
  42. #ifdef CONFIG_DRIVER_ATHEROS  
  43.     &wpa_driver_atheros_ops,  
  44. #endif   
  45. #ifdef CONFIG_DRIVER_NONE  
  46.     &wpa_driver_none_ops,  
  47. #endif   
  48.     NULL  
  49. };  

     具體選擇哪一個driver,由wpa_supplicant的指令參數決定,如我的如下:

     在init.myboard.rc中定義:

[cpp]  view plain copy

  1. service wpa_supplicant /system/bin/wpa_supplicant \  
  2.     -Dwext -iwlan0 -c/data/misc/wifi/wpa_supplicant.conf  
  3.     #-Dnl80211 -iwlan0 -puse_p2p_group_interpreprocessor">    #   we will start as root and wpa_supplicant will switch to user wifi  
  4.     #   after setting up the capabilities required for WEXT  
  5.     #   user wifi  
  6.     #   group wifi inet keystore  
  7.     class main  
  8.     socket wpa_wlan0 dgram 660 wifi wifi  
  9.     disabled  
  10.     oneshot  

     由上可見,我的選擇是wext, 即選擇了:wpa_driver_wext_ops。具體選擇在以下函數中實作,并最後儲存在wpa_supplicant->driver中,以供在wpa_drv_scan中使用。

[cpp]  view plain copy

  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.     if (wpa_s == NULL)  
  8.         return -1;  
  9.        wpa_msg(wpa_s,MSG_ERROR,"***MY_WIFI:%s,name=%s\n",__FUNCTION__,name);  
  10.     if (wpa_drivers[0] == NULL) {  
  11.         wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "  
  12.             "wpa_supplicant");  
  13.         return -1;  
  14.     }  
  15.     if (name == NULL) {  
  16.         wpa_s->driver = wpa_drivers[0];  
  17.         wpa_s->global_drv_priv = wpa_s->global->drv_priv[0];  
  18.         return 0;  
  19.     }  
  20.     do {  
  21.         pos = os_strchr(driver, ',');  
  22.         if (pos)  
  23.             len = pos - driver;  
  24.         else  
  25.             len = os_strlen(driver);  
  26.         for (i = 0; wpa_drivers[i]; i++) {  
  27.             if (os_strlen(wpa_drivers[i]->name) == len &&  
  28.                 os_strncmp(driver, wpa_drivers[i]->name, len) ==  
  29.                 0) {  
  30.                 wpa_s->driver = wpa_drivers[i];  // 根據name進行比對,并最後儲存到wpa_supplicant->dirver中  
  31.                 wpa_s->global_drv_priv =  
  32.                     wpa_s->global->drv_priv[i];  
  33.                 return 0;  
  34.             }  
  35.         }  
  36.         driver = pos + 1;  
  37.     } while (pos);  
  38.     wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);  
  39.     return -1;  
  40. }  

2. 接口操作函數實作

2.1 使用者态實作

    使用者态實作的操作函數如下:

    實作代碼見:/external/wpa_supplicant_8/wpa_supplicant/src/drivers/driver_wext.c

[cpp]  view plain copy

  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

[cpp]  view plain copy

  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. const struct iw_handler_def cfg80211_wext_handler = {  
  37.     .num_standard       = ARRAY_SIZE(cfg80211_handlers),  
  38.     .standard       = cfg80211_handlers,  
  39.     .get_wireless_stats = cfg80211_wireless_stats,  
  40. };  

2.3 使用者态與Kernel态的互動

      使用者态向Kernel态發送請求時,通過ioctl來實作。

      Kernel态向使用者态發送事件通知,通過netlink來實作。

     其互動的初始化在wpa_driver_wext_init中實作,其代碼如下:

[cpp]  view plain copy

  1. void * wpa_driver_wext_init(void *ctx, const char *ifname) // 我的ifname為wlan0  
  2. {  
  3.     struct wpa_driver_wext_data *drv;  
  4.     struct netlink_config *cfg;  
  5.     struct rfkill_config *rcfg;  
  6.     char path[128];  
  7.     struct stat buf;  
  8.         wpa_printf(MSG_ERROR,"***MY_WIFI:%s,ifname=%s\n",__FUNCTION__,ifname);  
  9.     drv = os_zalloc(sizeof(*drv));  
  10.     if (drv == NULL)  
  11.         return NULL;  
  12.     drv->ctx = ctx;  
  13.     os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));  
  14.     os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname);  
  15.     if (stat(path, &buf) == 0) {  
  16.         wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected");  
  17.         drv->cfg80211 = 1;  
  18.         wext_get_phy_name(drv);  
  19.     }  
  20.     drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);  // 此drv->ioctl_sock用作為ioctl指令的fd  
  21.     if (drv->ioctl_sock < 0) {  
  22.         perror("socket(PF_INET,SOCK_DGRAM)");  
  23.         goto err1;  
  24.     }  
  25.     cfg = os_zalloc(sizeof(*cfg));  
  26.     if (cfg == NULL)  
  27.         goto err1;  
  28.     cfg->ctx = drv;  
  29.     cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink;  
  30.     cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink;  
  31.     drv->netlink = netlink_init(cfg);  // 初始化netlink,并注冊事件接收函數  
  32.     if (drv->netlink == NULL) {  
  33.         os_free(cfg);  
  34.         goto err2;  
  35.     }  
  36.     rcfg = os_zalloc(sizeof(*rcfg));  
  37.     if (rcfg == NULL)  
  38.         goto err3;  
  39.     rcfg->ctx = drv;  
  40.     os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));  
  41.     rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked;  
  42.     rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked;  
  43.     drv->rfkill = rfkill_init(rcfg);  
  44.     if (drv->rfkill == NULL) {  
  45.         wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available");  
  46.         os_free(rcfg);  
  47.     }  
  48.     drv->mlme_sock = -1;  
  49. #ifdef ANDROID  
  50.     drv->errors = 0;  
  51.     drv->driver_is_started = TRUE;  
  52.     drv->skip_disconnect = 0;  
  53.     drv->bgscan_enabled = 0;  
  54. #endif  
  55.     if (wpa_driver_wext_finish_drv_init(drv) < 0)  
  56.         goto err3;  
  57.     wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1);  
  58.     return drv;  
  59. err3:  
  60.     rfkill_deinit(drv->rfkill);  
  61.     netlink_deinit(drv->netlink);  
  62. err2:  
  63.     close(drv->ioctl_sock);  
  64. err1:  
  65.     os_free(drv);  
  66.     return NULL;  
  67. }  

其中參數ifname在/data/misc/wifi/wpa_supplicant.conf中被定義,如我的如下:

[cpp]  view plain copy

  1. update_config=1  
  2. ctrl_interalt"> eapol_version=1  
  3. ap_scan=1  
  4. fast_reauth=1  

2.3.1 ioctl實作方案

      在使用者态可簡單執行一個ioctl(fd,cmd,...)指令即可。

      在Kernel态則是通過唯一的cmd (SIOCIWFIRST--SIOCIWLAST) 來進行區分,進而執行cfg80211_handlers中對應的函數。

      socket檔案操作如下:

[cpp]  view plain copy

  1. static const struct file_operations socket_file_ops = {  
  2.     .owner =    THIS_MODULE,  
  3.     .llseek =   no_llseek,  
  4.     .aio_read = sock_aio_read,  
  5.     .aio_write =    sock_aio_write,  
  6.     .poll =     sock_poll,  
  7.     .unlocked_ioctl = sock_ioctl, // 這個就是被執行的ioctl  
  8. #ifdef CONFIG_COMPAT  
  9.     .compat_ioctl = compat_sock_ioctl,  
  10. #endif  
  11.     .mmap =     sock_mmap,  
  12.     .open =     sock_no_open,     
  13.     .release =  sock_close,  
  14.     .fasync =   sock_fasync,  
  15.     .sendpage = sock_sendpage,  
  16.     .splice_write = generic_splice_sendpage,  
  17.     .splice_read =  sock_splice_read,  
  18. };  

從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中定義的>,并傳回結果) 

[cpp]  view plain copy

  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.     sock = file->private_data;  
  9.     sk = sock->sk;  
  10.     net = sock_net(sk);  
  11.     if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {  
  12.         err = dev_ioctl(net, cmd, argp);  
  13.     } else  
  14. #ifdef CONFIG_WEXT_CORE  
  15.     if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {  
  16.         err = dev_ioctl(net, cmd, argp); //執行dev_ioctl  
  17.     } else  
  18. #endif  
  19.         ...  
  20.     }  
  21.     return err;  
  22. }  

[cpp]  view plain copy

  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.     switch (cmd) {  
  7.     default:  
  8.         if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)  
  9.             return wext_handle_ioctl(net, &ifr, cmd, arg); // 執行wext_handle_ioctl  
  10.         return -ENOTTY;  
  11.     }  
  12. }  

[cpp]  view plain copy

  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.     ret = wext_ioctl_dispatch(net, ifr, cmd, &info,  // 執行wext_ioctl_dispatch  
  7.                   ioctl_standard_call,  
  8.                   ioctl_private_call);  
  9.     if (ret >= 0 &&  
  10.         IW_IS_GET(cmd) &&  
  11.         copy_to_user(arg, ifr, sizeof(struct iwreq))) // 把執行結果copy到使用者空間  
  12.         return -EFAULT;  
  13.     return ret;  
  14. }  

[cpp]  view plain copy

  1. static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,  
  2.                    unsigned int cmd, struct iw_request_info *info,  
  3.                    wext_ioctl_func standard,  
  4.                    wext_ioctl_func private)  
  5. {  
  6.     int ret = wext_permission_check(cmd);  
  7.     if (ret)  
  8.         return ret;  
  9.     dev_load(net, ifr->ifr_name);  
  10.     rtnl_lock();  
  11.     ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private); //執行wireless_process_ioctl  
  12.     rtnl_unlock();  
  13.     return ret;  
  14. }  

[cpp]  view plain copy

  1. static iw_handler get_handler(struct net_device *dev, unsigned int cmd)  
  2. {  
  3.     unsigned int    index;        
  4.     const struct iw_handler_def *handlers = NULL;  
  5.     //printk("***IDONG_WIFI:%s,cmd=0x%x\n",__FUNCTION__,cmd);  
  6. #ifdef CONFIG_CFG80211_WEXT  
  7.     if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy)  
  8.         handlers = dev->ieee80211_ptr->wiphy->wext;  
  9. #endif  
  10. #ifdef CONFIG_WIRELESS_EXT  
  11.     if (dev->wireless_handlers)  
  12.         handlers = dev->wireless_handlers;  
  13. #endif  
  14.     if (!handlers)  
  15.         return NULL;  
  16.     index = IW_IOCTL_IDX(cmd);  
  17.     if (index < handlers->num_standard)  
  18.         return handlers->standard[index];  
  19. #ifdef CONFIG_WEXT_PRIV  
  20.     index = cmd - SIOCIWFIRSTPRIV;  
  21.     if (index < handlers->num_private)  
  22.         return handlers->private[index];  
  23. #endif  
  24.     return NULL;  
  25. }  

[cpp]  view plain copy

  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.     if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)  
  11.         return -ENODEV;  
  12.     if (cmd == SIOCGIWSTATS)  
  13.         return standard(dev, iwr, cmd, info,  
  14.                 &iw_handler_get_iwstats);  
  15. #ifdef CONFIG_WEXT_PRIV  
  16.     if (cmd == SIOCGIWPRIV && dev->wireless_handlers)  
  17.         return standard(dev, iwr, cmd, info,  
  18.                 iw_handler_get_private);  
  19. #endif  
  20.     if (!netif_device_present(dev))  
  21.         return -ENODEV;  
  22.     handler = get_handler(dev, cmd);  
  23.     if (handler) {  
  24.         if (cmd < SIOCIWFIRSTPRIV)  
  25.             return standard(dev, iwr, cmd, info, handler); // 去執行對應的iw_handler  
  26.         else if (private)  
  27.             return private(dev, iwr, cmd, info, handler);  
  28.     }  
  29.     if (dev->netdev_ops->ndo_do_ioctl)  
  30.         return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);  
  31.     return -EOPNOTSUPP;  
  32. }  

2.3.2 使用者态初始化netlink

[cpp]  view plain copy

  1. struct netlink_data * netlink_init(struct netlink_config *cfg)  
  2. {  
  3.     struct netlink_data *netlink;  
  4.     struct sockaddr_nl local;  
  5.     netlink = os_zalloc(sizeof(*netlink));  
  6.     if (netlink == NULL)  
  7.         return NULL;  
  8.     netlink->cfg = cfg;  
  9.     netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);  
  10.     if (netlink->sock < 0) {  
  11.         wpa_printf(MSG_ERROR, "netlink: Failed to open netlink "  
  12.                "socket: %s", strerror(errno));  
  13.         netlink_deinit(netlink);  
  14.         return NULL;  
  15.     }  
  16.     os_memset(&local, 0, sizeof(local));  
  17.     local.nl_family = AF_NETLINK;  
  18.     local.nl_groups = RTMGRP_LINK;  
  19.     if (bind(netlink->sock, (struct sockaddr *) &local, sizeof(local)) < 0)  
  20.     {  
  21.         wpa_printf(MSG_ERROR, "netlink: Failed to bind netlink "  
  22.                "socket: %s", strerror(errno));  
  23.         netlink_deinit(netlink);  
  24.         return NULL;  
  25.     }  
  26.     eloop_register_read_sock(netlink->sock, netlink_receive, netlink,  
  27.                  NULL);  
  28.     return netlink;  
  29. }  

2.3.3 使用者态netlink事件接收函數netlink_receive

[cpp]  view plain copy

  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. try_again:  
  11.     fromlen = sizeof(from);  
  12.     left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, //從netlink讀取事件  
  13.             (struct sockaddr *) &from, &fromlen);  
  14.     if (left < 0) {  
  15.         if (errno != EINTR && errno != EAGAIN)  
  16.             wpa_printf(MSG_INFO, "netlink: recvfrom failed: %s",  
  17.                    strerror(errno));  
  18.         return;  
  19.     }  
  20.     h = (struct nlmsghdr *) buf;  
  21.     while (NLMSG_OK(h, left)) {  
  22.         switch (h->nlmsg_type) {  
  23.         case RTM_NEWLINK:  
  24.             netlink_receive_link(netlink, netlink->cfg->newlink_cb,  
  25.                          h);  
  26.             break;  
  27.         case RTM_DELLINK:  
  28.             netlink_receive_link(netlink, netlink->cfg->dellink_cb,  
  29.                          h);  
  30.             break;  
  31.         }  
  32.         h = NLMSG_NEXT(h, left);  
  33.     }  
  34.     if (left > 0) {  
  35.         wpa_printf(MSG_DEBUG, "netlink: %d extra bytes in the end of "  
  36.                "netlink message", left);  
  37.     }  
  38.     if (--max_events > 0) {  
  39.         goto try_again;  
  40.     }  
  41. }  

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函數詳細代碼如下:                                      

[cpp]  view plain copy

  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.     mutex_lock(&local->mtx);  
  9.     sdata = local->scan_sdata;  
  10.     if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {  
  11.         aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);  
  12.         goto out_complete;  
  13.     }  
  14.     if (!sdata || !local->scan_req)  
  15.         goto out;  
  16.     if (local->scan_req && !local->scanning) {  
  17.         struct cfg80211_scan_request *req = local->scan_req;  
  18.         int rc;  
  19.         local->scan_req = NULL;  
  20.         local->scan_sdata = NULL;  
  21.         rc = __ieee80211_start_scan(sdata, req);  
  22.         if (rc) {  
  23.             local->scan_req = req;  
  24.             aborted = true;  
  25.             goto out_complete;  
  26.         } else  
  27.             goto out;  
  28.     }  
  29.     if (!ieee80211_sdata_running(sdata)) {  
  30.         aborted = true;  
  31.         goto out_complete;  
  32.     }  
  33.     do {  
  34.         if (!ieee80211_sdata_running(sdata)) {  
  35.             aborted = true;  
  36.             goto out_complete;  
  37.         }  
  38.         switch (local->next_scan_state) {  
  39.         case SCAN_DECISION:  
  40.             if (local->scan_channel_idx >= local->scan_req->n_channels) {  
  41.                 aborted = false;  
  42.                 goto out_complete;  
  43.             }  
  44.             ieee80211_scan_state_decision(local, &next_delay);  
  45.             break;  
  46.         case SCAN_SET_CHANNEL:  
  47.             ieee80211_scan_state_set_channel(local, &next_delay);  
  48.             break;  
  49.         case SCAN_SEND_PROBE:  
  50.             ieee80211_scan_state_send_probe(local, &next_delay);  
  51.             break;  
  52.         case SCAN_LEAVE_OPER_CHANNEL:  
  53.             ieee80211_scan_state_leave_oper_channel(local, &next_delay);  
  54.             break;  
  55.         case SCAN_ENTER_OPER_CHANNEL:  
  56.             ieee80211_scan_state_enter_oper_channel(local, &next_delay);  
  57.             break;  
  58.         }  
  59.     } while (next_delay == 0);  
  60.     ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);  
  61.     goto out;  
  62. out_complete:  
  63.     hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);  
  64.     __ieee80211_scan_completed(&local->hw, aborted, hw_scan);  
  65. out:  
  66.     mutex_unlock(&local->mtx);  
  67. }  

繼續閱讀