From 3146ad01141fe944d15c5dac159ffc691beb66b4 Mon Sep 17 00:00:00 2001 From: wudan Date: Wed, 23 Nov 2022 10:38:35 +0800 Subject: [PATCH] add-wifi6/6+ and get-5g-freq --- debian/changelog | 7 + wpa_supplicant/bss.c | 190 +++++++++++++++++++++++- wpa_supplicant/bss.h | 17 +++ wpa_supplicant/dbus/dbus_new.c | 12 ++ wpa_supplicant/dbus/dbus_new_handlers.c | 101 +++++++++++++ wpa_supplicant/dbus/dbus_new_handlers.h | 3 + 6 files changed, 327 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 14e4446..1911b86 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +wpa (2:2.9-ok3) yangtze; urgency=medium + + * add-wifi6/6+ + * add-get-5g-freq + + -- wudan Wed, 16 Nov 2022 16:38:27 +0800 + wpa (2:2.9-ok2) yangtze; urgency=medium * update version info diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 441529c..be9250a 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -309,7 +309,162 @@ static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src, calculate_update_time(fetch_time, src->age, &dst->last_update); } +static u8 wpa_bss_get_160m_support_capability(struct wpa_bss *bss) +{ + const u8 *ie; + unsigned int channelWidth = 0; + unsigned int channelCenterSegment0 = 0; + unsigned int channelCenterSegment1 = 0; + /*find the VHT operation information */ + ie = wpa_bss_get_ie(bss, WLAN_EID_VHT_OPERATION); + if (ie == NULL || (ie[1] <= WIFI6WIFI6PLUS_VHT_CHANNEL_CENTER_SEGMENT1_INDEX)) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: NOT found VHT tag for SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_NOT_SUPPORTED; + } + + /*if the channel width equals 160MHZ, this AP has wifi6+ capability.*/ + channelWidth = ie[WIFI6WIFI6PLUS_HT_PRIMARY_CHANNEL_INDEX + 2]; + if (channelWidth == CHANWIDTH_160MHZ) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: 160MHZ supported(160MHZ) for SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_SUPPORTED; + } + + /*if Not, */ + channelCenterSegment0 = ie[WIFI6WIFI6PLUS_VHT_CHANNEL_CENTER_SEGMENT0_INDEX + 2]; + channelCenterSegment1 = ie[WIFI6WIFI6PLUS_VHT_CHANNEL_CENTER_SEGMENT1_INDEX + 2]; + wpa_printf(MSG_DEBUG, "wifi6wifi6+: SSID %s channelCenterSegment0:%d channelCenterSegment1:%d "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), channelCenterSegment0, channelCenterSegment1, MAC2STR(bss->bssid)); + if ((channelWidth == CHANWIDTH_80MHZ ) && channelCenterSegment0 && channelCenterSegment1 + && abs(channelCenterSegment1 - channelCenterSegment0) == 8) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: 160MHZ supported for SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_SUPPORTED; + } + + wpa_printf(MSG_DEBUG, "wifi6wifi6+: 160MHZ NOT supported for SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_NOT_SUPPORTED; +} +static u8 wpa_bss_get_narrowband_capability(struct wpa_bss *bss) +{ + const u8 *ie; + u8 index; + u8 bcc_id_header[9] = {0, 0xE0, 0xFC, 0x40, 0, 0, 0, 0x01, 0}; + unsigned int len = 0; + + /*To fetch vendor specific IE*/ + ie = wpa_bss_get_vendor_ie_content(bss, HW_IE_VENDOR_TYPE); + if (ie == NULL || (ie[1] <= sizeof(bcc_id_header))) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: vendor specific IE error1 for SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_NOT_SUPPORTED; + } + + /*To match the BCC ID head.*/ + for (index = 0; index < sizeof(bcc_id_header); index++) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: SSID %s ie[%d]:%d bcc_id_header:%d "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), index+2,ie[index+2],bcc_id_header[index], MAC2STR(bss->bssid)); + if ( ie[index + 2] != bcc_id_header[index]) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: bcc_id_header not match error SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_NOT_SUPPORTED; + } + } + + /*To find the narrowband sub ie entry, if successful, then to find the narrowband capability field and check its value.*/ + index = WIFI6WIFI6PLUS_TYPE_NARROWBAND_SUBIE_INDEX; + while (ie[1] > ie[index + 1] ) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: to match NB SUBIE for SSID %s ie[%d]:%d "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), index, ie[index], MAC2STR(bss->bssid)); + if (ie[index] == WIFI6WIFI6PLUS_TYPE_NARROWBAND_SUBIE) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: NB SUBIE FOUND SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + len = ie[index + 1]; + index += len - WIFI6WIFI6PLUS_NARROWBAND_OFFSET; + if (index >= ie[1] ) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: Index ERROR SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_NOT_SUPPORTED; + } + + if (WIFI6WIFI6PLUS_NARROWBAND_CAPABILITY == (ie[index] & WIFI6WIFI6PLUS_NARROWBAND_CAPABILITY)) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: narrowband supported for SSID %s "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_SUPPORTED; + } + } + len = ie[index + 1]; + index += len + 2; + } + + wpa_printf(MSG_DEBUG, "wifi6wifi6+: NB SUBIE NOT FOUND SSID %s ie[%d]:%d "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), index, ie[index], MAC2STR(bss->bssid)); + return WIFI6WIFI6PLUS_NOT_SUPPORTED; +} +static u8 wpa_bss_get_wifi6_capability(struct wpa_bss *bss) +{ + const u8 *ie; + + /*Whether this ap has wifi6 capability or not*/ + ie = get_ie_ext((u8 *) (bss + 1), bss->ie_len, WLAN_EID_EXT_HE_CAPABILITIES); + if (ie) { + return WIFI6WIFI6PLUS_SUPPORTED; + } + return WIFI6WIFI6PLUS_NOT_SUPPORTED; +} + +static void wpa_bss_get_wifi_category(struct wpa_bss *bss) +{ + u8 isWifi6Supported = 0; + u8 is160mBandSupported = 0; + u8 isNarrowbandSupported = 0; + + wpa_printf(MSG_DEBUG, "\r\n--------wifi6wifi6+ detect starting for SSID %s--------"MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + /*Whether this ap has wifi6 capability or not*/ + isWifi6Supported = wpa_bss_get_wifi6_capability(bss); + if (!isWifi6Supported){ + wpa_printf(MSG_DEBUG, "wifi6wifi6+: Wifi6 Not Supported %d SSID %s "MACSTR, + isWifi6Supported, wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + bss->category = WIFI6WIFI6PLUS_WIFI_CAPABILITY_DEFAULT; + wpa_printf(MSG_DEBUG, "--------wifi6wifi6+ detect finished for SSID %s--------"MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return; + } + + /*Whether this ap has wifi6 configure capability or not*/ + is160mBandSupported = wpa_bss_get_160m_support_capability(bss); + + if (is160mBandSupported){ + wpa_printf(MSG_DEBUG, "wifi6wifi6+: Wifi6 + Supported %d SSID %s "MACSTR, + is160mBandSupported, wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + bss->category = WIFI6WIFI6PLUS_WIFI_CATEGORY_WIFI6_PLUS; + wpa_printf(MSG_DEBUG, "--------wifi6wifi6+ detect finished for SSID %s--------"MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return; + } + + /*Whether this ap has narrowband capability or not*/ + isNarrowbandSupported = wpa_bss_get_narrowband_capability(bss); + + /*at last updating category result to bss entry according to the above results.*/ + if (isNarrowbandSupported) { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: Wifi6 + Supported %d SSID %s "MACSTR, + isNarrowbandSupported, wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + bss->category = WIFI6WIFI6PLUS_WIFI_CATEGORY_WIFI6_PLUS; + } + else { + wpa_printf(MSG_DEBUG, "wifi6wifi6+: Wifi6 Supported %d SSID %s "MACSTR, + isWifi6Supported, wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + bss->category = WIFI6WIFI6PLUS_WIFI_CATEGORY_WIFI6; + } + wpa_printf(MSG_DEBUG, "--------wifi6wifi6+ detect finished for SSID %s-------- "MACSTR, + wpa_ssid_txt(bss->ssid, bss->ssid_len), MAC2STR(bss->bssid)); + return; +} static int wpa_bss_is_wps_candidate(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { @@ -445,7 +600,8 @@ static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s, bss->beacon_ie_len = res->beacon_ie_len; os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); wpa_bss_set_hessid(bss); - + /*get the highest category of this ap and update into bss added by zwx955772 on 20210320*/ + wpa_bss_get_wifi_category(bss); if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count && wpa_bss_remove_oldest(wpa_s) != 0) { wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d " @@ -463,9 +619,9 @@ static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s, else extra[0] = '\0'; wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR - " SSID '%s' freq %d%s", + " SSID '%s' freq %d category %d %s", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len), - bss->freq, extra); + bss->freq, bss->category, extra); wpas_notify_bss_added(wpa_s, bss->bssid, bss->id); return bss; } @@ -1142,6 +1298,34 @@ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) return NULL; } +/** + * wpa_bss_get_vendor_ie_content - Fetch a vendor information element from a BSS entry (for wifi6/6+) + * @bss: BSS table entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the BSS + * entry. + */ +const u8 * wpa_bss_get_vendor_ie_content(const struct wpa_bss *bss, u32 vendor_type) +{ + const u8 *end, *pos; + + pos = (const u8 *) (bss + 1); + end = pos + bss->ie_len; + + while (end - pos > 1) { + if (2 + pos[1] > end - pos) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && pos[9] == 0x01 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + /** * wpa_bss_get_vendor_ie_beacon - Fetch a vendor information from a BSS entry diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 3ce8cd3..5454ad5 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -19,6 +19,20 @@ struct wpa_scan_res; #define WPA_BSS_ASSOCIATED BIT(5) #define WPA_BSS_ANQP_FETCH_TRIED BIT(6) +#define WIFI6WIFI6PLUS_NARROWBAND_CAPABILITY 0x20 +#define WIFI6WIFI6PLUS_HT_PRIMARY_CHANNEL_INDEX 0 +#define WIFI6WIFI6PLUS_VHT_CHANNEL_CENTER_SEGMENT0_INDEX 1 +#define WIFI6WIFI6PLUS_VHT_CHANNEL_CENTER_SEGMENT1_INDEX 2 +#define WIFI6WIFI6PLUS_WIFI_CAPABILITY_DEFAULT 0 +#define WIFI6WIFI6PLUS_WIFI_CATEGORY_WIFI6 1 +#define WIFI6WIFI6PLUS_WIFI_CATEGORY_WIFI6_PLUS 2 +#define WIFI6WIFI6PLUS_SUPPORTED 1 +#define WIFI6WIFI6PLUS_NOT_SUPPORTED 0 +#define WIFI6WIFI6PLUS_NARROWBAND_OFFSET 1 +#define WIFI6WIFI6PLUS_TYPE_NARROWBAND_SUBIE 0xFD +#define WIFI6WIFI6PLUS_TYPE_NARROWBAND_SUBIE_INDEX 0x0B +#define HW_IE_VENDOR_TYPE 0x00E0FC40 + struct wpa_bss_anqp_elem { struct dl_list list; u16 infoid; @@ -102,6 +116,8 @@ struct wpa_bss { unsigned int est_throughput; /** Signal-to-noise ratio in dB */ int snr; + /*indicating wifi category(0 means common ap, 1 means wifi6, 2 means wifi6+ )*/ + int category; /** ANQP data */ struct wpa_bss_anqp *anqp; /** Length of the following IE field in octets (from Probe Response) */ @@ -137,6 +153,7 @@ struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, unsigned int idf, unsigned int idl); const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); +const u8 * wpa_bss_get_vendor_ie_content(const struct wpa_bss *bss, u32 vendor_type); const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, u32 vendor_type); struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index fc2fc2e..285cbb5 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -2820,6 +2820,11 @@ static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = { NULL, NULL }, + { "Category", WPAS_DBUS_NEW_IFACE_BSS, "q", + wpas_dbus_getter_bss_category, + NULL, + NULL + }, { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q", wpas_dbus_getter_bss_frequency, NULL, @@ -3490,6 +3495,13 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { END_ARGS } }, + { "GetChannelFreq", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_get_channel_freq, + { + { "freq", "s", ARG_OUT }, + END_ARGS + } + }, #ifdef CONFIG_AUTOSCAN { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE, (WPADBusMethodHandler) wpas_dbus_handler_autoscan, diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 6c36d91..b647594 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -4433,6 +4433,22 @@ dbus_bool_t wpas_dbus_getter_bss_frequency( &freq, error); } +dbus_bool_t wpas_dbus_getter_bss_category( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct bss_handler_args *args = user_data; + struct wpa_bss *res; + u16 category; + + res = get_bss_helper(args, error, __func__); + if (!res) + return FALSE; + + category = (u16) res->category; + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, + &category, error); +} static int cmp_u8s_desc(const void *a, const void *b) { @@ -5323,3 +5339,88 @@ dbus_bool_t wpas_dbus_getter_mesh_group( } #endif /* CONFIG_MESH */ +static const char * modestr(enum hostapd_hw_mode mode) +{ + switch (mode) { + case HOSTAPD_MODE_IEEE80211B: + return "802.11b"; + case HOSTAPD_MODE_IEEE80211G: + return "802.11g"; + case HOSTAPD_MODE_IEEE80211A: + return "802.11a"; + case HOSTAPD_MODE_IEEE80211AD: + return "802.11ad"; + default: + return "?"; + } +} +DBusMessage *wpas_dbus_handler_get_channel_freq(DBusMessage *message, + struct wpa_supplicant *wpa_s, DBusError *error) +{ +#ifdef CONFIG_AP + DBusMessage *reply = NULL; + DBusMessageIter iter, subArrayIter; + dbus_message_iter_init(message, &iter); + char *freq = NULL; + int i; + char *hmode; + char str[200]; + if (wpa_s->hw.modes) + { + for (i = 0; i < wpa_s->hw.num_modes; i++) + { + struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i]; + char *mode_str = modestr(wpa_s->hw.modes[i].mode); + char *pos = str; + char *end = pos + sizeof(str); + int j, res; + + for (j = 0; j < mode->num_channels; j++) + { + if (strcmp(modestr(mode->mode), "802.11a") == 0) + { + struct hostapd_channel_data *chan = &mode->channels[j]; + + res = os_snprintf(pos, end - pos, " %d%s%s%s", + chan->freq, + (chan->flag & HOSTAPD_CHAN_DISABLED) ? "[DISABLED]" : "", + (chan->flag & HOSTAPD_CHAN_NO_IR) ? "[NO_IR]" : "", + (chan->flag & HOSTAPD_CHAN_RADAR) ? "[RADAR]" : ""); + if (os_snprintf_error(end - pos, res)) + break; + pos += res; + *pos = '\0'; + wpa_printf(MSG_DEBUG, "nl80211: Mode IEEE %s:%s", + modestr(mode->mode), str); + } + } + } + } + freq = os_calloc(1204, sizeof(char *)); + reply = dbus_message_new_method_return(message); + if (!reply) + return wpas_dbus_error_no_memory(message); + + dbus_message_iter_init_append(reply, &iter); + + if (!freq) + { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + return NULL; + } + strcpy(freq, str); + if (!dbus_message_iter_append_basic(&iter, + DBUS_TYPE_STRING, + &freq)) + { + dbus_message_unref(reply); + return NULL; + } + os_free(freq); + + return reply; +#else /* CONFIG_AP */ + wpa_printf(MSG_ERROR, "no sport mode"); + return FALSE; +#endif /* CONFIG_AP */ +} diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index d922ce1..adc231f 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -190,6 +190,7 @@ DECLARE_ACCESSOR(wpas_dbus_getter_bss_privacy); DECLARE_ACCESSOR(wpas_dbus_getter_bss_mode); DECLARE_ACCESSOR(wpas_dbus_getter_bss_signal); DECLARE_ACCESSOR(wpas_dbus_getter_bss_frequency); +DECLARE_ACCESSOR(wpas_dbus_getter_bss_category); DECLARE_ACCESSOR(wpas_dbus_getter_bss_rates); DECLARE_ACCESSOR(wpas_dbus_getter_bss_wpa); DECLARE_ACCESSOR(wpas_dbus_getter_bss_rsn); @@ -262,5 +263,7 @@ DBusMessage * wpas_dbus_handler_subscribe_preq( DBusMessage *message, struct wpa_supplicant *wpa_s); DBusMessage * wpas_dbus_handler_unsubscribe_preq( DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage *wpas_dbus_handler_get_channel_freq(DBusMessage *message, + struct wpa_supplicant *wpa_s,DBusError *error); #endif /* CTRL_IFACE_DBUS_HANDLERS_NEW_H */