]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Fetch information on supported AKMs from the driver
authorVeerendranath Jakkam <vjakkam@codeaurora.org>
Fri, 24 Apr 2020 17:19:25 +0000 (22:49 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 12 May 2020 13:57:17 +0000 (16:57 +0300)
The driver can advertise supported AKMs per wiphy and/or per interface.
Populate per interface supported AKMs based on the driver advertisement
in the following order of preference:
1. AKM suites advertised by NL80211_ATTR_IFTYPE_AKM_SUITES
2. AKM suites advertised by NL80211_ATTR_AKM_SUITES
If neither of these is available:
3. AKMs support is assumed as per legacy behavior.

In addition, extend other driver interface wrappers to set the
per-interface values based on the global capability indication.

Signed-off-by: Veerendranath Jakkam <vjakkam@codeaurora.org>
src/drivers/driver.h
src/drivers/driver_bsd.c
src/drivers/driver_ndis.c
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_capa.c
src/drivers/driver_wext.c

index e3b13bc251978f03fe6d757d1cfdf77cbc8115da..b0713249f49dd8fafb24d04986e7b4fea3ab6143 100644 (file)
@@ -1658,6 +1658,73 @@ struct wpa_driver_set_key_params {
        enum key_flag key_flag;
 };
 
+enum wpa_driver_if_type {
+       /**
+        * WPA_IF_STATION - Station mode interface
+        */
+       WPA_IF_STATION,
+
+       /**
+        * WPA_IF_AP_VLAN - AP mode VLAN interface
+        *
+        * This interface shares its address and Beacon frame with the main
+        * BSS.
+        */
+       WPA_IF_AP_VLAN,
+
+       /**
+        * WPA_IF_AP_BSS - AP mode BSS interface
+        *
+        * This interface has its own address and Beacon frame.
+        */
+       WPA_IF_AP_BSS,
+
+       /**
+        * WPA_IF_P2P_GO - P2P Group Owner
+        */
+       WPA_IF_P2P_GO,
+
+       /**
+        * WPA_IF_P2P_CLIENT - P2P Client
+        */
+       WPA_IF_P2P_CLIENT,
+
+       /**
+        * WPA_IF_P2P_GROUP - P2P Group interface (will become either
+        * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known)
+        */
+       WPA_IF_P2P_GROUP,
+
+       /**
+        * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the
+        * abstracted P2P Device function in the driver
+        */
+       WPA_IF_P2P_DEVICE,
+
+       /*
+        * WPA_IF_MESH - Mesh interface
+        */
+       WPA_IF_MESH,
+
+       /*
+        * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only)
+        */
+       WPA_IF_TDLS,
+
+       /*
+        * WPA_IF_IBSS - IBSS interface (used for pref freq only)
+        */
+       WPA_IF_IBSS,
+
+       /*
+        * WPA_IF_NAN - NAN Device
+        */
+       WPA_IF_NAN,
+
+       /* keep last */
+       WPA_IF_MAX
+};
+
 /**
  * struct wpa_driver_capa - Driver capability information
  */
@@ -1681,6 +1748,7 @@ struct wpa_driver_capa {
 #define WPA_DRIVER_CAPA_KEY_MGMT_SAE           0x00010000
        /** Bitfield of supported key management suites */
        unsigned int key_mgmt;
+       unsigned int key_mgmt_iftype[WPA_IF_MAX];
 
 #define WPA_DRIVER_CAPA_ENC_WEP40      0x00000001
 #define WPA_DRIVER_CAPA_ENC_WEP104     0x00000002
@@ -2045,65 +2113,6 @@ struct hostapd_acl_params {
        struct mac_address mac_acl[0];
 };
 
-enum wpa_driver_if_type {
-       /**
-        * WPA_IF_STATION - Station mode interface
-        */
-       WPA_IF_STATION,
-
-       /**
-        * WPA_IF_AP_VLAN - AP mode VLAN interface
-        *
-        * This interface shares its address and Beacon frame with the main
-        * BSS.
-        */
-       WPA_IF_AP_VLAN,
-
-       /**
-        * WPA_IF_AP_BSS - AP mode BSS interface
-        *
-        * This interface has its own address and Beacon frame.
-        */
-       WPA_IF_AP_BSS,
-
-       /**
-        * WPA_IF_P2P_GO - P2P Group Owner
-        */
-       WPA_IF_P2P_GO,
-
-       /**
-        * WPA_IF_P2P_CLIENT - P2P Client
-        */
-       WPA_IF_P2P_CLIENT,
-
-       /**
-        * WPA_IF_P2P_GROUP - P2P Group interface (will become either
-        * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known)
-        */
-       WPA_IF_P2P_GROUP,
-
-       /**
-        * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the
-        * abstracted P2P Device function in the driver
-        */
-       WPA_IF_P2P_DEVICE,
-
-       /*
-        * WPA_IF_MESH - Mesh interface
-        */
-       WPA_IF_MESH,
-
-       /*
-        * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only)
-        */
-       WPA_IF_TDLS,
-
-       /*
-        * WPA_IF_IBSS - IBSS interface (used for pref freq only)
-        */
-       WPA_IF_IBSS,
-};
-
 struct wpa_init_params {
        void *global_priv;
        const u8 *bssid;
index b4400d7bf57dca925e4a932b72b5ac07245dc052..5adee13a266d550507cd44171a665dcccc448d4f 100644 (file)
@@ -1451,6 +1451,7 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv)
 #define        GETPARAM(drv, param, v) \
        (((v) = get80211param(drv, param)) != -1)
        struct bsd_driver_data *drv;
+       int i;
 
        drv = os_zalloc(sizeof(*drv));
        if (drv == NULL)
@@ -1486,6 +1487,10 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv)
        if (wpa_driver_bsd_capa(drv))
                goto fail;
 
+       /* Update per interface supported AKMs */
+       for (i = 0; i < WPA_IF_MAX; i++)
+               drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+
        /* Down interface during setup. */
        if (bsd_get_iface_flags(drv) < 0)
                goto fail;
index 529fc3bc69193c99b27bf1aa4251d7da92eac78d..b5fff483e78ba786fb1692ff72674b30b13c5f9d 100644 (file)
@@ -2809,6 +2809,7 @@ static void * wpa_driver_ndis_init(void *ctx, const char *ifname)
 {
        struct wpa_driver_ndis_data *drv;
        u32 mode;
+       int i;
 
        drv = os_zalloc(sizeof(*drv));
        if (drv == NULL)
@@ -2855,6 +2856,11 @@ static void * wpa_driver_ndis_init(void *ctx, const char *ifname)
        }
        wpa_driver_ndis_get_capability(drv);
 
+       /* Update per interface supported AKMs */
+       for (i = 0; i < WPA_IF_MAX; i++)
+               drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+
+
        /* Make sure that the driver does not have any obsolete PMKID entries.
         */
        wpa_driver_ndis_flush_pmkid(drv);
index d48f8cb7653ddf9784f417f65b345ed6381c47c3..9c72341f9a8b331b97f6ef6451335c87cb58e5f2 100644 (file)
@@ -2328,10 +2328,19 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
        /* FT Action frames */
        if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
                ret = -1;
-       else
+       else if (!drv->has_driver_key_mgmt) {
+               int i;
+
+               /* Update supported AKMs only if the driver doesn't advertize
+                * any AKM capabilities. */
                drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
                        WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
 
+               /* Update per interface supported AKMs */
+               for (i = 0; i < WPA_IF_MAX; i++)
+                       drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+       }
+
        /* WNM - BSS Transition Management Request */
        if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
                ret = -1;
@@ -5056,6 +5065,10 @@ const char * nl80211_iftype_str(enum nl80211_iftype mode)
                return "P2P_GO";
        case NL80211_IFTYPE_P2P_DEVICE:
                return "P2P_DEVICE";
+       case NL80211_IFTYPE_OCB:
+               return "OCB";
+       case NL80211_IFTYPE_NAN:
+               return "NAN";
        default:
                return "unknown";
        }
index c3ad88a398b38c58e814598e330a1aa900dd31c3..660f49879bf4da8f775833bd02f702522ca056a1 100644 (file)
@@ -111,6 +111,7 @@ struct wpa_driver_nl80211_data {
        unsigned int num_iface_ext_capa;
 
        int has_capability;
+       int has_driver_key_mgmt;
 
        int operstate;
 
index 34ad0c694243d92e52283373b9e744c64ac9f74d..a3341a088930f7b9034391289c9158b8e72c8082 100644 (file)
@@ -79,6 +79,8 @@ struct wiphy_info_data {
        unsigned int mac_addr_rand_scan_supported:1;
        unsigned int mac_addr_rand_sched_scan_supported:1;
        unsigned int update_ft_ies_supported:1;
+       unsigned int has_key_mgmt:1;
+       unsigned int has_key_mgmt_iftype:1;
 };
 
 
@@ -252,6 +254,158 @@ static void wiphy_info_supp_cmds(struct wiphy_info_data *info,
 }
 
 
+static unsigned int get_akm_suites_info(struct nlattr *tb)
+{
+       int i, num;
+       unsigned int key_mgmt = 0;
+       u32 *akms;
+
+       if (!tb)
+               return 0;
+
+       num = nla_len(tb) / sizeof(u32);
+       akms = nla_data(tb);
+       for (i = 0; i < num; i++) {
+               switch (akms[i]) {
+               case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
+                       break;
+               case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FT_802_1X:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FT_PSK:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
+                       break;
+               case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B;
+                       break;
+               case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
+                       break;
+               case RSN_AUTH_KEY_MGMT_OWE:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OWE;
+                       break;
+               case RSN_AUTH_KEY_MGMT_DPP:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_DPP;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FILS_SHA256:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FILS_SHA384:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256;
+                       break;
+               case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384;
+                       break;
+               case RSN_AUTH_KEY_MGMT_SAE:
+                       key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SAE;
+                       break;
+               }
+       }
+
+       return key_mgmt;
+}
+
+
+static void get_iface_akm_suites_info(struct wiphy_info_data *info,
+                                       struct nlattr *nl_akms)
+{
+       struct nlattr *tb[NL80211_IFTYPE_AKM_ATTR_MAX + 1];
+       struct nlattr *nl_iftype;
+       unsigned int key_mgmt;
+       int i;
+
+       if (!nl_akms)
+               return;
+
+       nla_parse(tb, NL80211_IFTYPE_AKM_ATTR_MAX,
+                 nla_data(nl_akms), nla_len(nl_akms), NULL);
+
+       if (!tb[NL80211_IFTYPE_AKM_ATTR_IFTYPES] ||
+           !tb[NL80211_IFTYPE_AKM_ATTR_SUITES])
+               return;
+
+       info->has_key_mgmt_iftype = 1;
+       key_mgmt = get_akm_suites_info(tb[NL80211_IFTYPE_AKM_ATTR_SUITES]);
+
+       nla_for_each_nested(nl_iftype, tb[NL80211_IFTYPE_AKM_ATTR_IFTYPES], i) {
+               switch (nla_type(nl_iftype)) {
+               case NL80211_IFTYPE_ADHOC:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_IBSS] = key_mgmt;
+                       break;
+               case NL80211_IFTYPE_STATION:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_STATION] =
+                               key_mgmt;
+                       break;
+               case NL80211_IFTYPE_AP:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_AP_BSS] =
+                               key_mgmt;
+                       break;
+               case NL80211_IFTYPE_AP_VLAN:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_AP_VLAN] =
+                               key_mgmt;
+                       break;
+               case NL80211_IFTYPE_MESH_POINT:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_MESH] = key_mgmt;
+                       break;
+               case NL80211_IFTYPE_P2P_CLIENT:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_CLIENT] =
+                               key_mgmt;
+                       break;
+               case NL80211_IFTYPE_P2P_GO:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_GO] =
+                               key_mgmt;
+                       break;
+               case NL80211_IFTYPE_P2P_DEVICE:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_DEVICE] =
+                               key_mgmt;
+                       break;
+               case NL80211_IFTYPE_NAN:
+                       info->drv->capa.key_mgmt_iftype[WPA_IF_NAN] = key_mgmt;
+                       break;
+               }
+               wpa_printf(MSG_DEBUG, "nl80211: %s supported key_mgmt 0x%x",
+                          nl80211_iftype_str(nla_type(nl_iftype)),
+                          key_mgmt);
+       }
+}
+
+
+static void wiphy_info_iftype_akm_suites(struct wiphy_info_data *info,
+                                        struct nlattr *tb)
+{
+       struct nlattr *nl_if;
+       int rem_if;
+
+       if (!tb)
+               return;
+
+       nla_for_each_nested(nl_if, tb, rem_if)
+               get_iface_akm_suites_info(info, nl_if);
+}
+
+
+static void wiphy_info_akm_suites(struct wiphy_info_data *info,
+                                 struct nlattr *tb)
+{
+       if (!tb)
+               return;
+
+       info->has_key_mgmt = 1;
+       info->capa->key_mgmt = get_akm_suites_info(tb);
+       wpa_printf(MSG_DEBUG, "nl80211: wiphy supported key_mgmt 0x%x",
+                  info->capa->key_mgmt);
+}
+
+
 static void wiphy_info_cipher_suites(struct wiphy_info_data *info,
                                     struct nlattr *tb)
 {
@@ -696,6 +850,8 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
        wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
        wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
        wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]);
+       wiphy_info_akm_suites(info, tb[NL80211_ATTR_AKM_SUITES]);
+       wiphy_info_iftype_akm_suites(info, tb[NL80211_ATTR_IFTYPE_AKM_SUITES]);
 
        if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
                wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
@@ -1098,6 +1254,8 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
 int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
 {
        struct wiphy_info_data info;
+       int i;
+
        if (wpa_driver_nl80211_get_info(drv, &info))
                return -1;
 
@@ -1105,27 +1263,62 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
                return -1;
 
        drv->has_capability = 1;
-       drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
-               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
-               WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
-               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
-               WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
-               WPA_DRIVER_CAPA_KEY_MGMT_OWE |
-               WPA_DRIVER_CAPA_KEY_MGMT_DPP;
-
-       if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 |
-                            WPA_DRIVER_CAPA_ENC_GCMP_256))
-               drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
-
-       if (drv->capa.flags & WPA_DRIVER_FLAGS_SME)
-               drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
-                       WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
-                       WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
-                       WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
-                       WPA_DRIVER_CAPA_KEY_MGMT_SAE;
-       else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
-               drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
-                       WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
+       drv->has_driver_key_mgmt = info.has_key_mgmt | info.has_key_mgmt_iftype;
+
+       /* Fallback to hardcoded defaults if the driver does nott advertize any
+        * AKM capabilities. */
+       if (!drv->has_driver_key_mgmt) {
+               drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+                       WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+                       WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
+                       WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
+                       WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
+                       WPA_DRIVER_CAPA_KEY_MGMT_OWE |
+                       WPA_DRIVER_CAPA_KEY_MGMT_DPP;
+
+               if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 |
+                                    WPA_DRIVER_CAPA_ENC_GCMP_256))
+                       drv->capa.key_mgmt |=
+                               WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
+
+               if (drv->capa.flags & WPA_DRIVER_FLAGS_SME)
+                       drv->capa.key_mgmt |=
+                               WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
+                               WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
+                               WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
+                               WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
+                               WPA_DRIVER_CAPA_KEY_MGMT_SAE;
+               else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
+                       drv->capa.key_mgmt |=
+                               WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
+                               WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
+       }
+
+       if (!info.has_key_mgmt_iftype) {
+               /* If the driver does not advertize per interface AKM
+                * capabilities, consider all interfaces to support default AKMs
+                * in key_mgmt. */
+               for (i = 0; i < WPA_IF_MAX; i++)
+                       drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+       } else if (info.has_key_mgmt_iftype && !info.has_key_mgmt) {
+               /* If the driver advertizes only per interface supported AKMs
+                * but does not advertize per wiphy AKM capabilities, consider
+                * the default key_mgmt as a mask of per interface supported
+                * AKMs. */
+               drv->capa.key_mgmt = 0;
+               for (i = 0; i < WPA_IF_MAX; i++)
+                       drv->capa.key_mgmt |= drv->capa.key_mgmt_iftype[i];
+       } else if (info.has_key_mgmt_iftype && info.has_key_mgmt) {
+               /* If the driver advertizes AKM capabilities both per wiphy and
+                * per interface, consider the interfaces for which per
+                * interface AKM capabilities were not received to support the
+                * default key_mgmt capabilities.
+                */
+               for (i = 0; i < WPA_IF_MAX; i++)
+                       if (!drv->capa.key_mgmt_iftype[i])
+                               drv->capa.key_mgmt_iftype[i] =
+                                       drv->capa.key_mgmt;
+       }
 
        drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
                WPA_DRIVER_AUTH_SHARED |
index 978e1cf438b727eccbe7b7b3287410ae99385576..8a3adee05241178f49fe623b659c0da3b9abfad5 100644 (file)
@@ -968,6 +968,7 @@ static void wext_check_hostap(struct wpa_driver_wext_data *drv)
 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
 {
        int send_rfkill_event = 0;
+       int i;
 
        if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {
                if (rfkill_is_blocked(drv->rfkill)) {
@@ -996,6 +997,10 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
 
        wpa_driver_wext_get_range(drv);
 
+       /* Update per interface supported AKMs */
+       for (i = 0; i < WPA_IF_MAX; i++)
+               drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+
        /*
         * Unlock the driver's BSSID and force to a random SSID to clear any
         * previous association the driver might have when the supplicant