From b907491281b06b4dee9e0d0326e23c67ce486eb5 Mon Sep 17 00:00:00 2001 From: Lior David Date: Mon, 8 Feb 2016 12:30:04 +0200 Subject: [PATCH] wpa_supplicant: Basic support for PBSS/PCP PBSS (Personal Basic Service Set) is a new BSS type for DMG networks. It is similar to infrastructure BSS, having an AP-like entity called PCP (PBSS Control Point), but it has few differences. PBSS support is mandatory for IEEE 802.11ad devices. Add a new "pbss" argument to network block. The argument is used in the following scenarios: 1. When network has mode=2 (AP), when pbss flag is set will start as a PCP instead of an AP. 2. When network has mode=0 (station), when pbss flag is set will connect to PCP instead of AP. The function wpa_scan_res_match() was modified to match BSS according to the pbss flag in the network block (wpa_ssid structure). When pbss flag is set it will match only PCPs, and when it is clear it will match only APs. Signed-off-by: Lior David --- src/ap/ap_config.h | 2 ++ src/ap/beacon.c | 1 + wpa_supplicant/ap.c | 2 ++ wpa_supplicant/bss.h | 11 +++++++++++ wpa_supplicant/config.c | 1 + wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 9 +++++++++ wpa_supplicant/events.c | 10 ++++++++-- wpa_supplicant/p2p_supplicant.c | 2 ++ wpa_supplicant/wpa_cli.c | 2 +- wpa_supplicant/wpa_supplicant.c | 2 ++ wpa_supplicant/wpa_supplicant.conf | 7 +++++++ wpa_supplicant/wps_supplicant.c | 8 ++++++++ 13 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 44bcccc..e68ec28 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -570,6 +570,8 @@ struct hostapd_bss_config { char *no_probe_resp_if_seen_on; char *no_auth_if_seen_on; + + int pbss; }; diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 3276d12..560b19c 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1217,6 +1217,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, params->osen = 1; } #endif /* CONFIG_HS20 */ + params->pbss = hapd->conf->pbss; return 0; } diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 98b9596..03c3fab 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -453,6 +453,8 @@ no_wps: wpabuf_dup(wpa_s->conf->ap_vendor_elements); } + bss->pbss = ssid->pbss; + return 0; } diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 4a782af..f7f72f3 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -148,6 +148,17 @@ static inline int bss_is_dmg(const struct wpa_bss *bss) return bss->freq > 45000; } +/** + * Test whether a BSS is a PBSS. + * This checks whether a BSS is a DMG-band PBSS. PBSS is used for P2P DMG + * network. + */ +static inline int bss_is_pbss(struct wpa_bss *bss) +{ + return bss_is_dmg(bss) && + (bss->caps & IEEE80211_CAP_DMG_MASK) == IEEE80211_CAP_DMG_PBSS; +} + static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level) { if (bss != NULL && new_level < 0) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 85717e9..e345895 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1980,6 +1980,7 @@ static const struct parse_data ssid_fields[] = { { INT(update_identifier) }, #endif /* CONFIG_HS20 */ { INT_RANGE(mac_addr, 0, 2) }, + { INT_RANGE(pbss, 0, 1) }, }; #undef OFFSET diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index c9ba8b7..a1eb691 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -755,6 +755,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(peerkey); INT(mixed_cell); INT(max_oper_chwidth); + INT(pbss); #ifdef CONFIG_IEEE80211W write_int(f, "ieee80211w", ssid->ieee80211w, MGMT_FRAME_PROTECTION_DEFAULT); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index b296826..eb7b87b 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -360,6 +360,15 @@ struct wpa_ssid { } mode; /** + * pbss - Whether to use PBSS. Relevant to DMG networks only. + * Used together with mode configuration. When mode is AP, it + * means to start a PCP instead of a regular AP. When mode is INFRA it + * means connect to a PCP instead of AP. P2P_GO and P2P_GROUP_FORMATION + * modes must use PBSS in DMG network. + */ + int pbss; + + /** * disabled - Whether this network is currently disabled * * 0 = this network can be used (default). diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 2870e89..3264dc0 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -988,8 +988,14 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, continue; } - if (!bss_is_ess(bss)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - not ESS network"); + if (!bss_is_ess(bss) && !bss_is_pbss(bss)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - neither ESS nor PBSS network"); + continue; + } + + if (ssid->pbss != bss_is_pbss(bss)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - PBSS mismatch (ssid %d bss %d)", + ssid->pbss, bss_is_pbss(bss)); continue; } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 9b36b63..bf8f394 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1898,6 +1898,8 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, */ ssid->pairwise_cipher = WPA_CIPHER_GCMP; ssid->group_cipher = WPA_CIPHER_GCMP; + /* P2P GO in 60 GHz is always a PCP (PBSS) */ + ssid->pbss = 1; } if (os_strlen(params->passphrase) > 0) { ssid->passphrase = os_strdup(params->passphrase); diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 265f72c..2420602 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1612,7 +1612,7 @@ static const char *network_fields[] = { #ifdef CONFIG_HS20 "update_identifier", #endif /* CONFIG_HS20 */ - "mac_addr" + "mac_addr", "pbss" }; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index c3c1f14..f362638 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2345,9 +2345,11 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) } params.bssid_hint = bss->bssid; params.freq_hint = bss->freq; + params.pbss = bss_is_pbss(bss); } else { params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; + params.pbss = ssid->pbss; } if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set && diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index f3e913a..478cb82 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -702,6 +702,13 @@ fast_reauth=1 # an IBSS network with the configured SSID is already present, the frequency of # the network will be used instead of this configured value. # +# pbss: Whether to use PBSS. Relevant to IEEE 802.11ad networks only. +# Used together with mode configuration. When mode is AP, it means to start a +# PCP instead of a regular AP. When mode is infrastructure it means connect +# to a PCP instead of AP. P2P_GO and P2P_GROUP_FORMATION modes must use PBSS +# in IEEE 802.11ad network. +# For more details, see IEEE Std 802.11ad-2012. +# # scan_freq: List of frequencies to scan # Space-separated list of frequencies in MHz to scan when searching for this # BSS. If the subset of channels used by the network is known, this option can diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 5c674b2..a39897d 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1149,6 +1149,10 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, ssid->ssid_len = wpa_s->go_params->ssid_len; os_memcpy(ssid->ssid, wpa_s->go_params->ssid, ssid->ssid_len); + if (wpa_s->go_params->freq > 56160) { + /* P2P in 60 GHz uses PBSS */ + ssid->pbss = 1; + } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP " "SSID", ssid->ssid, ssid->ssid_len); } @@ -1216,6 +1220,10 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s, ssid->ssid_len = wpa_s->go_params->ssid_len; os_memcpy(ssid->ssid, wpa_s->go_params->ssid, ssid->ssid_len); + if (wpa_s->go_params->freq > 56160) { + /* P2P in 60 GHz uses PBSS */ + ssid->pbss = 1; + } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP " "SSID", ssid->ssid, ssid->ssid_len); } -- 2.1.4