Add freq_list network configuration parameter
authorJouni Malinen <j@w1.fi>
Sat, 27 Mar 2010 05:45:50 +0000 (22:45 -0700)
committerJouni Malinen <j@w1.fi>
Sat, 27 Mar 2010 05:45:50 +0000 (22:45 -0700)
This can be used to limit which frequencies are considered when
selecting a BSS. This is somewhat similar to scan_freq, but will
also affect any scan results regardless of which program triggered
the scan.

wpa_supplicant/config.c
wpa_supplicant/config_ssid.h
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.conf

index 6aa8e9b..7e2a5b4 100644 (file)
@@ -917,9 +917,9 @@ static char * wpa_config_write_auth_alg(const struct parse_data *data,
 #endif /* NO_CONFIG_WRITE */
 
 
-static int wpa_config_parse_scan_freq(const struct parse_data *data,
-                                     struct wpa_ssid *ssid, int line,
-                                     const char *value)
+static int * wpa_config_parse_freqs(const struct parse_data *data,
+                                   struct wpa_ssid *ssid, int line,
+                                   const char *value)
 {
        int *freqs;
        size_t used, len;
@@ -929,7 +929,7 @@ static int wpa_config_parse_scan_freq(const struct parse_data *data,
        len = 10;
        freqs = os_zalloc((len + 1) * sizeof(int));
        if (freqs == NULL)
-               return -1;
+               return NULL;
 
        pos = value;
        while (pos) {
@@ -941,7 +941,7 @@ static int wpa_config_parse_scan_freq(const struct parse_data *data,
                        n = os_realloc(freqs, (len * 2 + 1) * sizeof(int));
                        if (n == NULL) {
                                os_free(freqs);
-                               return -1;
+                               return NULL;
                        }
                        for (i = len; i <= len * 2; i++)
                                n[i] = 0;
@@ -956,6 +956,19 @@ static int wpa_config_parse_scan_freq(const struct parse_data *data,
                pos = os_strchr(pos + 1, ' ');
        }
 
+       return freqs;
+}
+
+
+static int wpa_config_parse_scan_freq(const struct parse_data *data,
+                                     struct wpa_ssid *ssid, int line,
+                                     const char *value)
+{
+       int *freqs;
+
+       freqs = wpa_config_parse_freqs(data, ssid, line, value);
+       if (freqs == NULL)
+               return -1;
        os_free(ssid->scan_freq);
        ssid->scan_freq = freqs;
 
@@ -963,19 +976,35 @@ static int wpa_config_parse_scan_freq(const struct parse_data *data,
 }
 
 
+static int wpa_config_parse_freq_list(const struct parse_data *data,
+                                     struct wpa_ssid *ssid, int line,
+                                     const char *value)
+{
+       int *freqs;
+
+       freqs = wpa_config_parse_freqs(data, ssid, line, value);
+       if (freqs == NULL)
+               return -1;
+       os_free(ssid->freq_list);
+       ssid->freq_list = freqs;
+
+       return 0;
+}
+
+
 #ifndef NO_CONFIG_WRITE
-static char * wpa_config_write_scan_freq(const struct parse_data *data,
-                                        struct wpa_ssid *ssid)
+static char * wpa_config_write_freqs(const struct parse_data *data,
+                                    const int *freqs)
 {
        char *buf, *pos, *end;
        int i, ret;
        size_t count;
 
-       if (ssid->scan_freq == NULL)
+       if (freqs == NULL)
                return NULL;
 
        count = 0;
-       for (i = 0; ssid->scan_freq[i]; i++)
+       for (i = 0; freqs[i]; i++)
                count++;
 
        pos = buf = os_zalloc(10 * count + 1);
@@ -983,9 +1012,9 @@ static char * wpa_config_write_scan_freq(const struct parse_data *data,
                return NULL;
        end = buf + 10 * count + 1;
 
-       for (i = 0; ssid->scan_freq[i]; i++) {
+       for (i = 0; freqs[i]; i++) {
                ret = os_snprintf(pos, end - pos, "%s%u",
-                                 i == 0 ? "" : " ", ssid->scan_freq[i]);
+                                 i == 0 ? "" : " ", freqs[i]);
                if (ret < 0 || ret >= end - pos) {
                        end[-1] = '\0';
                        return buf;
@@ -995,6 +1024,20 @@ static char * wpa_config_write_scan_freq(const struct parse_data *data,
 
        return buf;
 }
+
+
+static char * wpa_config_write_scan_freq(const struct parse_data *data,
+                                        struct wpa_ssid *ssid)
+{
+       return wpa_config_write_freqs(data, ssid->scan_freq);
+}
+
+
+static char * wpa_config_write_freq_list(const struct parse_data *data,
+                                        struct wpa_ssid *ssid)
+{
+       return wpa_config_write_freqs(data, ssid->freq_list);
+}
 #endif /* NO_CONFIG_WRITE */
 
 
@@ -1399,6 +1442,7 @@ static const struct parse_data ssid_fields[] = {
        { FUNC(group) },
        { FUNC(auth_alg) },
        { FUNC(scan_freq) },
+       { FUNC(freq_list) },
 #ifdef IEEE8021X_EAPOL
        { FUNC(eap) },
        { STR_LENe(identity) },
@@ -1624,6 +1668,7 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
 #endif /* IEEE8021X_EAPOL */
        os_free(ssid->id_str);
        os_free(ssid->scan_freq);
+       os_free(ssid->freq_list);
        os_free(ssid->bgscan);
        os_free(ssid);
 }
index 6056c9c..25e87aa 100644 (file)
@@ -363,6 +363,16 @@ struct wpa_ssid {
         * <bgscan module name>:<module parameters>
         */
        char *bgscan;
+
+       /**
+        * freq_list - Array of allowed frequencies or %NULL for all
+        *
+        * This is an optional zero-terminated array of frequencies in
+        * megahertz (MHz) to allow for selecting the BSS. If set, scan results
+        * that do not match any of the specified frequencies are not
+        * considered when selecting a BSS.
+        */
+       int *freq_list;
 };
 
 #endif /* CONFIG_SSID_H */
index 3604454..70dccac 100644 (file)
@@ -394,6 +394,20 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
 }
 
 
+static int freq_allowed(int *freqs, int freq)
+{
+       int i;
+
+       if (freqs == NULL)
+               return 1;
+
+       for (i = 0; freqs[i]; i++)
+               if (freqs[i] == freq)
+                       return 1;
+       return 0;
+}
+
+
 static struct wpa_bss *
 wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
                              struct wpa_scan_results *scan_res,
@@ -477,6 +491,12 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
                        if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss))
                                continue;
 
+                       if (!freq_allowed(ssid->freq_list, bss->freq)) {
+                               wpa_printf(MSG_DEBUG, "   skip - "
+                                          "frequency not allowed");
+                               continue;
+                       }
+
                        wpa_printf(MSG_DEBUG, "   selected WPA AP "
                                   MACSTR " ssid='%s'",
                                   MAC2STR(bss->bssid),
@@ -604,6 +624,12 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
                                continue;
                        }
 
+                       if (!freq_allowed(ssid->freq_list, bss->freq)) {
+                               wpa_printf(MSG_DEBUG, "   skip - "
+                                          "frequency not allowed");
+                               continue;
+                       }
+
                        wpa_printf(MSG_DEBUG, "   selected non-WPA AP "
                                   MACSTR " ssid='%s'",
                                   MAC2STR(bss->bssid),
index 39058d8..0cd5b02 100644 (file)
@@ -288,6 +288,11 @@ fast_reauth=1
 # be used to optimize scanning to not occur on channels that the network does
 # not use. Example: scan_freq=2412 2437 2462
 #
+# freq_list: Array of allowed frequencies
+# Space-separated list of frequencies in MHz to allow for selecting the BSS. If
+# set, scan results that do not match any of the specified frequencies are not
+# considered when selecting a BSS.
+#
 # proto: list of accepted protocols
 # WPA = WPA/IEEE 802.11i/D3.0
 # RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN)