From 43a356b2687219b7a212df8ef21237b5ddf49f35 Mon Sep 17 00:00:00 2001 From: Purushottam Kushwaha Date: Tue, 9 May 2017 20:33:51 +0530 Subject: [PATCH] Provide option to configure BSSID hint for a network This exposes user configurable option to set bssid_hint for a network. bssid_hint indicates which BSS has been found a suitable candidate for initial association for drivers that use driver/firmware-based BSS selection. Unlike the bssid parameter, bssid_hint does not limit the driver from selecting other BSSs in the ESS. Signed-off-by: Jouni Malinen --- wpa_supplicant/config.c | 45 +++++++++++++++++++++++++++++++++ wpa_supplicant/config_file.c | 12 +++++++++ wpa_supplicant/config_ssid.h | 13 ++++++++++ wpa_supplicant/wpa_supplicant.c | 3 +++ 4 files changed, 73 insertions(+) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 8a88a8dff..0248d7981 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -397,6 +397,50 @@ static char * wpa_config_write_bssid(const struct parse_data *data, #endif /* NO_CONFIG_WRITE */ +static int wpa_config_parse_bssid_hint(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 || + os_strcmp(value, "any") == 0) { + ssid->bssid_hint_set = 0; + wpa_printf(MSG_MSGDUMP, "BSSID hint any"); + return 0; + } + if (hwaddr_aton(value, ssid->bssid_hint)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID hint '%s'.", + line, value); + return -1; + } + ssid->bssid_hint_set = 1; + wpa_hexdump(MSG_MSGDUMP, "BSSID hint", ssid->bssid_hint, ETH_ALEN); + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid_hint(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *value; + int res; + + if (!ssid->bssid_hint_set) + return NULL; + + value = os_malloc(20); + if (!value) + return NULL; + res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid_hint)); + if (os_snprintf_error(20, res)) { + os_free(value); + return NULL; + } + return value; +} +#endif /* NO_CONFIG_WRITE */ + + static int wpa_config_parse_bssid_blacklist(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) @@ -2028,6 +2072,7 @@ static const struct parse_data ssid_fields[] = { { STR_RANGE(ssid, 0, SSID_MAX_LEN) }, { INT_RANGE(scan_ssid, 0, 1) }, { FUNC(bssid) }, + { FUNC(bssid_hint) }, { FUNC(bssid_blacklist) }, { FUNC(bssid_whitelist) }, { FUNC_KEY(psk) }, diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 7069b1624..ceaf434bd 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -503,6 +503,17 @@ static void write_bssid(FILE *f, struct wpa_ssid *ssid) } +static void write_bssid_hint(FILE *f, struct wpa_ssid *ssid) +{ + char *value = wpa_config_get(ssid, "bssid_hint"); + + if (!value) + return; + fprintf(f, "\tbssid_hint=%s\n", value); + os_free(value); +} + + static void write_psk(FILE *f, struct wpa_ssid *ssid) { char *value; @@ -713,6 +724,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(ssid); INT(scan_ssid); write_bssid(f, ssid); + write_bssid_hint(f, ssid); write_str(f, "bssid_blacklist", ssid); write_str(f, "bssid_whitelist", ssid); write_psk(f, ssid); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 7153042f9..6c6c32ad1 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -146,6 +146,19 @@ struct wpa_ssid { */ int bssid_set; + /** + * bssid_hint - BSSID hint + * + * If set, this is configured to the driver as a preferred initial BSSID + * while connecting to this network. + */ + u8 bssid_hint[ETH_ALEN]; + + /** + * bssid_hint_set - Whether BSSID hint is configured for this network + */ + int bssid_hint_set; + /** * go_p2p_dev_addr - GO's P2P Device Address or all zeros if not set */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 56cc35c56..b4680eae9 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2681,6 +2681,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.freq_hint = bss->freq; params.pbss = bss_is_pbss(bss); } else { + if (ssid->bssid_hint_set) + params.bssid_hint = ssid->bssid_hint; + params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;