nl80211: Split wiphy_info_handler() into smaller helper functions
[mech_eap.git] / src / drivers / driver_nl80211.c
index 7cd3df2..90985bf 100644 (file)
@@ -2546,12 +2546,42 @@ static unsigned int probe_resp_offload_support(int supp_protocols)
 }
 
 
-static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+static void wiphy_info_supported_iftypes(struct wiphy_info_data *info,
+                                        struct nlattr *tb)
 {
-       struct nlattr *tb[NL80211_ATTR_MAX + 1];
-       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-       struct wiphy_info_data *info = arg;
-       struct wpa_driver_capa *capa = info->capa;
+       struct nlattr *nl_mode;
+       int i;
+
+       if (tb == NULL)
+               return;
+
+       nla_for_each_nested(nl_mode, tb, i) {
+               switch (nla_type(nl_mode)) {
+               case NL80211_IFTYPE_AP:
+                       info->capa->flags |= WPA_DRIVER_FLAGS_AP;
+                       break;
+               case NL80211_IFTYPE_P2P_GO:
+                       info->p2p_go_supported = 1;
+                       break;
+               case NL80211_IFTYPE_P2P_CLIENT:
+                       info->p2p_client_supported = 1;
+                       break;
+               case NL80211_IFTYPE_MONITOR:
+                       info->monitor_supported = 1;
+                       break;
+               }
+       }
+}
+
+
+static int wiphy_info_iface_comb_process(struct wiphy_info_data *info,
+                                        struct nlattr *nl_combi)
+{
+       struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+       struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+       struct nlattr *nl_limit, *nl_mode;
+       int err, rem_limit, rem_mode;
+       int combination_has_p2p = 0, combination_has_mgd = 0;
        static struct nla_policy
        iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
                [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
@@ -2564,6 +2594,164 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
                [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
        };
 
+       err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
+                              nl_combi, iface_combination_policy);
+       if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
+           !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
+           !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
+               return 0; /* broken combination */
+
+       nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS],
+                           rem_limit) {
+               err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
+                                      nl_limit, iface_limit_policy);
+               if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES])
+                       return 0; /* broken combination */
+
+               nla_for_each_nested(nl_mode,
+                                   tb_limit[NL80211_IFACE_LIMIT_TYPES],
+                                   rem_mode) {
+                       int ift = nla_type(nl_mode);
+                       if (ift == NL80211_IFTYPE_P2P_GO ||
+                           ift == NL80211_IFTYPE_P2P_CLIENT)
+                               combination_has_p2p = 1;
+                       if (ift == NL80211_IFTYPE_STATION)
+                               combination_has_mgd = 1;
+               }
+               if (combination_has_p2p && combination_has_mgd)
+                       break;
+       }
+
+       if (combination_has_p2p && combination_has_mgd) {
+               info->p2p_concurrent = 1;
+               if (nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) > 1)
+                       info->p2p_multichan_concurrent = 1;
+               return 1;
+       }
+
+       return 0;
+}
+
+
+static void wiphy_info_iface_comb(struct wiphy_info_data *info,
+                                 struct nlattr *tb)
+{
+       struct nlattr *nl_combi;
+       int rem_combi;
+
+       if (tb == NULL)
+               return;
+
+       nla_for_each_nested(nl_combi, tb, rem_combi) {
+               if (wiphy_info_iface_comb_process(info, nl_combi) > 0)
+                       break;
+       }
+}
+
+
+static void wiphy_info_supp_cmds(struct wiphy_info_data *info,
+                                struct nlattr *tb)
+{
+       struct nlattr *nl_cmd;
+       int i;
+
+       if (tb == NULL)
+               return;
+
+       nla_for_each_nested(nl_cmd, tb, i) {
+               switch (nla_get_u32(nl_cmd)) {
+               case NL80211_CMD_AUTHENTICATE:
+                       info->auth_supported = 1;
+                       break;
+               case NL80211_CMD_CONNECT:
+                       info->connect_supported = 1;
+                       break;
+               case NL80211_CMD_START_SCHED_SCAN:
+                       info->capa->sched_scan_supported = 1;
+                       break;
+               case NL80211_CMD_PROBE_CLIENT:
+                       info->poll_command_supported = 1;
+                       break;
+               }
+       }
+}
+
+
+static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
+                              struct nlattr *tb)
+{
+       /* default to 5000 since early versions of mac80211 don't set it */
+       capa->max_remain_on_chan = 5000;
+
+       if (tb)
+               capa->max_remain_on_chan = nla_get_u32(tb);
+}
+
+
+static void wiphy_info_tdls(struct wpa_driver_capa *capa, struct nlattr *tdls,
+                           struct nlattr *ext_setup)
+{
+       if (tdls == NULL)
+               return;
+
+       wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
+       capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
+
+       if (ext_setup) {
+               wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
+               capa->flags |= WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
+       }
+}
+
+
+static void wiphy_info_feature_flags(struct wiphy_info_data *info,
+                                    struct nlattr *tb)
+{
+       u32 flags;
+       struct wpa_driver_capa *capa = info->capa;
+
+       if (tb == NULL)
+               return;
+
+       flags = nla_get_u32(tb);
+
+       if (flags & NL80211_FEATURE_SK_TX_STATUS)
+               info->data_tx_status = 1;
+
+       if (flags & NL80211_FEATURE_INACTIVITY_TIMER)
+               capa->flags |= WPA_DRIVER_FLAGS_INACTIVITY_TIMER;
+
+       if (flags & NL80211_FEATURE_SAE)
+               capa->flags |= WPA_DRIVER_FLAGS_SAE;
+
+       if (flags & NL80211_FEATURE_NEED_OBSS_SCAN)
+               capa->flags |= WPA_DRIVER_FLAGS_OBSS_SCAN;
+}
+
+
+static void wiphy_info_probe_resp_offload(struct wpa_driver_capa *capa,
+                                         struct nlattr *tb)
+{
+       u32 protocols;
+
+       if (tb == NULL)
+               return;
+
+       protocols = nla_get_u32(tb);
+       wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response offload in AP "
+                  "mode");
+       capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
+       capa->probe_resp_offloads = probe_resp_offload_support(protocols);
+}
+
+
+static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+{
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct wiphy_info_data *info = arg;
+       struct wpa_driver_capa *capa = info->capa;
+
        nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
                  genlmsg_attrlen(gnlh, 0), NULL);
 
@@ -2579,109 +2767,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
                capa->max_match_sets =
                        nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
 
-       if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) {
-               struct nlattr *nl_mode;
-               int i;
-               nla_for_each_nested(nl_mode,
-                                   tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {
-                       switch (nla_type(nl_mode)) {
-                       case NL80211_IFTYPE_AP:
-                               capa->flags |= WPA_DRIVER_FLAGS_AP;
-                               break;
-                       case NL80211_IFTYPE_P2P_GO:
-                               info->p2p_go_supported = 1;
-                               break;
-                       case NL80211_IFTYPE_P2P_CLIENT:
-                               info->p2p_client_supported = 1;
-                               break;
-                       case NL80211_IFTYPE_MONITOR:
-                               info->monitor_supported = 1;
-                               break;
-                       }
-               }
-       }
-
-       if (tb[NL80211_ATTR_INTERFACE_COMBINATIONS]) {
-               struct nlattr *nl_combi;
-               int rem_combi;
-
-               nla_for_each_nested(nl_combi,
-                                   tb[NL80211_ATTR_INTERFACE_COMBINATIONS],
-                                   rem_combi) {
-                       struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
-                       struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
-                       struct nlattr *nl_limit, *nl_mode;
-                       int err, rem_limit, rem_mode;
-                       int combination_has_p2p = 0, combination_has_mgd = 0;
-
-                       err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
-                                              nl_combi,
-                                              iface_combination_policy);
-                       if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
-                           !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
-                           !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
-                               goto broken_combination;
-
-                       nla_for_each_nested(nl_limit,
-                                           tb_comb[NL80211_IFACE_COMB_LIMITS],
-                                           rem_limit) {
-                               err = nla_parse_nested(tb_limit,
-                                                      MAX_NL80211_IFACE_LIMIT,
-                                                      nl_limit,
-                                                      iface_limit_policy);
-                               if (err ||
-                                   !tb_limit[NL80211_IFACE_LIMIT_TYPES])
-                                       goto broken_combination;
-
-                               nla_for_each_nested(
-                                       nl_mode,
-                                       tb_limit[NL80211_IFACE_LIMIT_TYPES],
-                                       rem_mode) {
-                                       int ift = nla_type(nl_mode);
-                                       if (ift == NL80211_IFTYPE_P2P_GO ||
-                                           ift == NL80211_IFTYPE_P2P_CLIENT)
-                                               combination_has_p2p = 1;
-                                       if (ift == NL80211_IFTYPE_STATION)
-                                               combination_has_mgd = 1;
-                               }
-                               if (combination_has_p2p && combination_has_mgd)
-                                       break;
-                       }
-
-                       if (combination_has_p2p && combination_has_mgd) {
-                               info->p2p_concurrent = 1;
-                               if (nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) > 1)
-                                       info->p2p_multichan_concurrent = 1;
-                               break;
-                       }
-
-broken_combination:
-                       ;
-               }
-       }
-
-       if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {
-               struct nlattr *nl_cmd;
-               int i;
-
-               nla_for_each_nested(nl_cmd,
-                                   tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) {
-                       switch (nla_get_u32(nl_cmd)) {
-                       case NL80211_CMD_AUTHENTICATE:
-                               info->auth_supported = 1;
-                               break;
-                       case NL80211_CMD_CONNECT:
-                               info->connect_supported = 1;
-                               break;
-                       case NL80211_CMD_START_SCHED_SCAN:
-                               capa->sched_scan_supported = 1;
-                               break;
-                       case NL80211_CMD_PROBE_CLIENT:
-                               info->poll_command_supported = 1;
-                               break;
-                       }
-               }
-       }
+       wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
+       wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
+       wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
 
        if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
                wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
@@ -2694,55 +2782,21 @@ broken_combination:
                capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
        }
 
-       /* default to 5000 since early versions of mac80211 don't set it */
-       capa->max_remain_on_chan = 5000;
+       wiphy_info_max_roc(capa,
+                          tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
 
        if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
                capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
 
-       if (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION])
-               capa->max_remain_on_chan =
-                       nla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
-
-       if (tb[NL80211_ATTR_TDLS_SUPPORT]) {
-               wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
-               capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
-
-               if (tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]) {
-                       wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
-                       capa->flags |=
-                               WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
-               }
-       }
+       wiphy_info_tdls(capa, tb[NL80211_ATTR_TDLS_SUPPORT],
+                       tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]);
 
        if (tb[NL80211_ATTR_DEVICE_AP_SME])
                info->device_ap_sme = 1;
 
-       if (tb[NL80211_ATTR_FEATURE_FLAGS]) {
-               u32 flags = nla_get_u32(tb[NL80211_ATTR_FEATURE_FLAGS]);
-
-               if (flags & NL80211_FEATURE_SK_TX_STATUS)
-                       info->data_tx_status = 1;
-
-               if (flags & NL80211_FEATURE_INACTIVITY_TIMER)
-                       capa->flags |= WPA_DRIVER_FLAGS_INACTIVITY_TIMER;
-
-               if (flags & NL80211_FEATURE_SAE)
-                       capa->flags |= WPA_DRIVER_FLAGS_SAE;
-
-               if (flags & NL80211_FEATURE_NEED_OBSS_SCAN)
-                       capa->flags |= WPA_DRIVER_FLAGS_OBSS_SCAN;
-       }
-
-       if (tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]) {
-               int protocols =
-                       nla_get_u32(tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
-               wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response "
-                          "offload in AP mode");
-               capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
-               capa->probe_resp_offloads =
-                       probe_resp_offload_support(protocols);
-       }
+       wiphy_info_feature_flags(info, tb[NL80211_ATTR_FEATURE_FLAGS]);
+       wiphy_info_probe_resp_offload(capa,
+                                     tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
 
        return NL_SKIP;
 }
@@ -5069,7 +5123,8 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
                        idx = phy_info->last_chan_idx;
 
                        nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
-                               nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
+                               nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
+                                         nla_data(nl_freq),
                                          nla_len(nl_freq), freq_policy);
                                if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
                                        continue;