X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fdrivers%2Fdriver_nl80211_capa.c;h=1134886adb07646157879b393e93669399a467d5;hb=a6f5b1937ad45ced659d87b1eb5a665c8d137d34;hp=1b5752fbba58ffa8b239915716cfced3baa7bc25;hpb=bee5d8e067a743986c0a5c19b09dc61178436d27;p=mech_eap.git diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 1b5752f..1134886 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -352,13 +352,20 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, struct nlattr *tb) { struct wpa_driver_capa *capa = info->capa; + u8 *ext_features; + int len; if (tb == NULL) return; - if (ext_feature_isset(nla_data(tb), nla_len(tb), - NL80211_EXT_FEATURE_VHT_IBSS)) + ext_features = nla_data(tb); + len = nla_len(tb); + + if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_VHT_IBSS)) capa->flags |= WPA_DRIVER_FLAGS_VHT_IBSS; + + if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_RRM)) + capa->rrm_flags |= WPA_DRIVER_FLAGS_SUPPORT_RRM; } @@ -428,6 +435,9 @@ static void wiphy_info_feature_flags(struct wiphy_info_data *info, if (flags & NL80211_FEATURE_HT_IBSS) capa->flags |= WPA_DRIVER_FLAGS_HT_IBSS; + + if (flags & NL80211_FEATURE_FULL_AP_CLIENT_STATE) + capa->flags |= WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE; } @@ -476,6 +486,74 @@ static void wiphy_info_wowlan_triggers(struct wpa_driver_capa *capa, } +static void wiphy_info_extended_capab(struct wpa_driver_nl80211_data *drv, + struct nlattr *tb) +{ + int rem = 0, i; + struct nlattr *tb1[NL80211_ATTR_MAX + 1], *attr; + + if (!tb || drv->num_iface_ext_capa == NL80211_IFTYPE_MAX) + return; + + nla_for_each_nested(attr, tb, rem) { + unsigned int len; + struct drv_nl80211_ext_capa *capa; + + nla_parse(tb1, NL80211_ATTR_MAX, nla_data(attr), + nla_len(attr), NULL); + + if (!tb1[NL80211_ATTR_IFTYPE] || + !tb1[NL80211_ATTR_EXT_CAPA] || + !tb1[NL80211_ATTR_EXT_CAPA_MASK]) + continue; + + capa = &drv->iface_ext_capa[drv->num_iface_ext_capa]; + capa->iftype = nla_get_u32(tb1[NL80211_ATTR_IFTYPE]); + wpa_printf(MSG_DEBUG, + "nl80211: Driver-advertised extended capabilities for interface type %s", + nl80211_iftype_str(capa->iftype)); + + len = nla_len(tb1[NL80211_ATTR_EXT_CAPA]); + capa->ext_capa = os_malloc(len); + if (!capa->ext_capa) + goto err; + + os_memcpy(capa->ext_capa, nla_data(tb1[NL80211_ATTR_EXT_CAPA]), + len); + capa->ext_capa_len = len; + wpa_hexdump(MSG_DEBUG, "nl80211: Extended capabilities", + capa->ext_capa, capa->ext_capa_len); + + len = nla_len(tb1[NL80211_ATTR_EXT_CAPA_MASK]); + capa->ext_capa_mask = os_malloc(len); + if (!capa->ext_capa_mask) + goto err; + + os_memcpy(capa->ext_capa_mask, + nla_data(tb1[NL80211_ATTR_EXT_CAPA_MASK]), len); + wpa_hexdump(MSG_DEBUG, "nl80211: Extended capabilities mask", + capa->ext_capa_mask, capa->ext_capa_len); + + drv->num_iface_ext_capa++; + if (drv->num_iface_ext_capa == NL80211_IFTYPE_MAX) + break; + } + + return; + +err: + /* Cleanup allocated memory on error */ + for (i = 0; i < NL80211_IFTYPE_MAX; i++) { + os_free(drv->iface_ext_capa[i].ext_capa); + drv->iface_ext_capa[i].ext_capa = NULL; + os_free(drv->iface_ext_capa[i].ext_capa_mask); + drv->iface_ext_capa[i].ext_capa_mask = NULL; + drv->iface_ext_capa[i].ext_capa_len = 0; + } + drv->num_iface_ext_capa = 0; +} + + static int wiphy_info_handler(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; @@ -487,6 +565,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); + if (tb[NL80211_ATTR_WIPHY]) + drv->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]); + if (tb[NL80211_ATTR_WIPHY_NAME]) os_strlcpy(drv->phyname, nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]), @@ -499,6 +580,19 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) capa->max_sched_scan_ssids = nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]); + if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS] && + tb[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL] && + tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]) { + capa->max_sched_scan_plans = + nla_get_u32(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS]); + + capa->max_sched_scan_plan_interval = + nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL]); + + capa->max_sched_scan_plan_iterations = + nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]); + } + if (tb[NL80211_ATTR_MAX_MATCH_SETS]) capa->max_match_sets = nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]); @@ -550,6 +644,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) nla_len(tb[NL80211_ATTR_EXT_CAPA])); drv->extended_capa_len = nla_len(tb[NL80211_ATTR_EXT_CAPA]); + wpa_hexdump(MSG_DEBUG, + "nl80211: Driver-advertised extended capabilities (default)", + drv->extended_capa, drv->extended_capa_len); } drv->extended_capa_mask = os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA_MASK])); @@ -557,6 +654,10 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) os_memcpy(drv->extended_capa_mask, nla_data(tb[NL80211_ATTR_EXT_CAPA_MASK]), nla_len(tb[NL80211_ATTR_EXT_CAPA_MASK])); + wpa_hexdump(MSG_DEBUG, + "nl80211: Driver-advertised extended capabilities mask (default)", + drv->extended_capa_mask, + drv->extended_capa_len); } else { os_free(drv->extended_capa); drv->extended_capa = NULL; @@ -564,6 +665,8 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) } } + wiphy_info_extended_capab(drv, tb[NL80211_ATTR_IFTYPE_EXT_CAPA]); + if (tb[NL80211_ATTR_VENDOR_DATA]) { struct nlattr *nl; int rem; @@ -711,6 +814,12 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv, drv->capa.max_csa_counters = 1; } + if (!drv->capa.max_sched_scan_plans) { + drv->capa.max_sched_scan_plans = 1; + drv->capa.max_sched_scan_plan_interval = UINT32_MAX; + drv->capa.max_sched_scan_plan_iterations = 0; + } + return 0; } @@ -795,8 +904,12 @@ static int features_info_handler(struct nl_msg *msg, void *arg) attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS]; if (attr) { - info->flags = nla_data(attr); - info->flags_len = nla_len(attr); + int len = nla_len(attr); + info->flags = os_malloc(len); + if (info->flags != NULL) { + os_memcpy(info->flags, nla_data(attr), len); + info->flags_len = len; + } } attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA]; if (attr) @@ -859,6 +972,9 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv) if (check_feature(QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS, &info)) drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS; + if (check_feature(QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD, &info)) + drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD; + os_free(info.flags); } #endif /* CONFIG_DRIVER_NL80211_QCA */