]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Allow channels to be removed from P2P use
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 17 Feb 2012 20:57:13 +0000 (22:57 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 17 Feb 2012 20:57:13 +0000 (22:57 +0200)
A list of disallowed frequencies for P2P channel list can now be
configured with P2P_SET disallow_freq. The frequencies (or frequency
pairs) are comma separated. For example:
wpa_cli p2p_set disallow_freq 2462,5000-6000

The allowed P2P channel list is constructed by removing explicitly
disallowed channels from the channel list received from the driver.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

wpa_supplicant/ctrl_iface.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 1bbdebe498f140e8cea27cac1d970d9ccf089a39..9d1afbe4b87b632a333f3bd7fa3fcdfc03b88937 100644 (file)
@@ -3287,6 +3287,56 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
 }
 
 
+static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
+                                 const char *param)
+{
+       struct wpa_freq_range *freq = NULL, *n;
+       unsigned int count = 0, i;
+       const char *pos, *pos2, *pos3;
+
+       if (wpa_s->global->p2p == NULL)
+               return -1;
+
+       /*
+        * param includes comma separated frequency range.
+        * For example: 2412-2432,2462,5000-6000
+        */
+       pos = param;
+       while (pos && pos[0]) {
+               n = os_realloc(freq,
+                              (count + 1) * sizeof(struct wpa_freq_range));
+               if (n == NULL) {
+                       os_free(freq);
+                       return -1;
+               }
+               freq = n;
+               freq[count].min = atoi(pos);
+               pos2 = os_strchr(pos, '-');
+               pos3 = os_strchr(pos, ',');
+               if (pos2 && (!pos3 || pos2 < pos3)) {
+                       pos2++;
+                       freq[count].max = atoi(pos2);
+               } else
+                       freq[count].max = freq[count].min;
+               pos = pos3;
+               if (pos)
+                       pos++;
+               count++;
+       }
+
+       for (i = 0; i < count; i++) {
+               wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
+                          freq[i].min, freq[i].max);
+       }
+
+       os_free(wpa_s->global->p2p_disallow_freq);
+       wpa_s->global->p2p_disallow_freq = freq;
+       wpa_s->global->num_p2p_disallow_freq = count;
+       wpas_p2p_update_channel_list(wpa_s);
+       return 0;
+}
+
+
 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
 {
        char *param;
@@ -3431,6 +3481,9 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
                return 0;
        }
 
+       if (os_strcmp(cmd, "disallow_freq") == 0)
+               return p2p_ctrl_disallow_freq(wpa_s, param);
+
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
                   cmd);
 
index e870e45fd589ec66b08bcfd01eab37d13393069f..015e6b41c45932952c68536bb11750507e562a04 100644 (file)
@@ -2030,6 +2030,31 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid)
 }
 
 
+static int wpas_p2p_disallowed_freq(struct wpa_global *global,
+                                   unsigned int freq)
+{
+       unsigned int i;
+
+       if (global->p2p_disallow_freq == NULL)
+               return 0;
+
+       for (i = 0; i < global->num_p2p_disallow_freq; i++) {
+               if (freq >= global->p2p_disallow_freq[i].min &&
+                   freq <= global->p2p_disallow_freq[i].max)
+                       return 1;
+       }
+
+       return 0;
+}
+
+
+static void wpas_p2p_add_chan(struct p2p_reg_class *reg, u8 chan)
+{
+       reg->channel[reg->channels] = chan;
+       reg->channels++;
+}
+
+
 static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
                                     struct p2p_channels *chan)
 {
@@ -2040,34 +2065,47 @@ static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
 
        /* Operating class 81 - 2.4 GHz band channels 1..13 */
        chan->reg_class[cla].reg_class = 81;
-       chan->reg_class[cla].channels = 11;
-       for (i = 0; i < 11; i++)
-               chan->reg_class[cla].channel[i] = i + 1;
-       cla++;
+       chan->reg_class[cla].channels = 0;
+       for (i = 0; i < 11; i++) {
+               if (!wpas_p2p_disallowed_freq(wpa_s->global, 2412 + i * 5))
+                       wpas_p2p_add_chan(&chan->reg_class[cla], i + 1);
+       }
+       if (chan->reg_class[cla].channels)
+               cla++;
 
        wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for lower 5 GHz "
                   "band");
 
        /* Operating class 115 - 5 GHz, channels 36-48 */
        chan->reg_class[cla].reg_class = 115;
-       chan->reg_class[cla].channels = 4;
-       chan->reg_class[cla].channel[0] = 36;
-       chan->reg_class[cla].channel[1] = 40;
-       chan->reg_class[cla].channel[2] = 44;
-       chan->reg_class[cla].channel[3] = 48;
-       cla++;
+       chan->reg_class[cla].channels = 0;
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 36 * 5))
+               wpas_p2p_add_chan(&chan->reg_class[cla], 36);
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 40 * 5))
+               wpas_p2p_add_chan(&chan->reg_class[cla], 40);
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 44 * 5))
+               wpas_p2p_add_chan(&chan->reg_class[cla], 44);
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 48 * 5))
+               wpas_p2p_add_chan(&chan->reg_class[cla], 48);
+       if (chan->reg_class[cla].channels)
+               cla++;
 
        wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for higher 5 GHz "
                   "band");
 
        /* Operating class 124 - 5 GHz, channels 149,153,157,161 */
        chan->reg_class[cla].reg_class = 124;
-       chan->reg_class[cla].channels = 4;
-       chan->reg_class[cla].channel[0] = 149;
-       chan->reg_class[cla].channel[1] = 153;
-       chan->reg_class[cla].channel[2] = 157;
-       chan->reg_class[cla].channel[3] = 161;
-       cla++;
+       chan->reg_class[cla].channels = 0;
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 149 * 5))
+               wpas_p2p_add_chan(&chan->reg_class[cla], 149);
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 153 * 5))
+               wpas_p2p_add_chan(&chan->reg_class[cla], 153);
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 156 * 5))
+               wpas_p2p_add_chan(&chan->reg_class[cla], 157);
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 161 * 5))
+               wpas_p2p_add_chan(&chan->reg_class[cla], 161);
+       if (chan->reg_class[cla].channels)
+               cla++;
 
        chan->reg_classes = cla;
        return 0;
@@ -2089,9 +2127,16 @@ static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
 }
 
 
-static int has_channel(struct hostapd_hw_modes *mode, u8 chan, int *flags)
+static int has_channel(struct wpa_global *global,
+                      struct hostapd_hw_modes *mode, u8 chan, int *flags)
 {
        int i;
+       unsigned int freq;
+
+       freq = (mode->mode == HOSTAPD_MODE_IEEE80211A ? 5000 : 2407) +
+               chan * 5;
+       if (wpas_p2p_disallowed_freq(global, freq))
+               return 0;
 
        for (i = 0; i < mode->num_channels; i++) {
                if (mode->channels[i].chan == chan) {
@@ -2158,15 +2203,15 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
                        continue;
                for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
                        int flag;
-                       if (!has_channel(mode, ch, &flag))
+                       if (!has_channel(wpa_s->global, mode, ch, &flag))
                                continue;
                        if (o->bw == BW40MINUS &&
                            (!(flag & HOSTAPD_CHAN_HT40MINUS) ||
-                            !has_channel(mode, ch - 4, NULL)))
+                            !has_channel(wpa_s->global, mode, ch - 4, NULL)))
                                continue;
                        if (o->bw == BW40PLUS &&
                            (!(flag & HOSTAPD_CHAN_HT40PLUS) ||
-                            !has_channel(mode, ch + 4, NULL)))
+                            !has_channel(wpa_s->global, mode, ch + 4, NULL)))
                                continue;
                        if (reg == NULL) {
                                wpa_printf(MSG_DEBUG, "P2P: Add operating "
@@ -3104,7 +3149,18 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
                wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
                           "channel %d MHz", params->freq);
        } else {
-               params->freq = 2412;
+               int chan;
+               for (chan = 0; chan < 11; chan++) {
+                       params->freq = 2412 + chan * 5;
+                       if (!wpas_p2p_disallowed_freq(wpa_s->global,
+                                                     params->freq))
+                               break;
+               }
+               if (chan == 11) {
+                       wpa_printf(MSG_DEBUG, "P2P: No 2.4 GHz channel "
+                                  "allowed");
+                       return -1;
+               }
                wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference "
                           "known)", params->freq);
        }
index caf90996d8ebec5233616aada83fd040774293a4..4c365dd45f5bcf53976d47b643784f740083a540 100644 (file)
@@ -2951,6 +2951,8 @@ void wpa_supplicant_deinit(struct wpa_global *global)
        os_free(global->params.override_driver);
        os_free(global->params.override_ctrl_interface);
 
+       os_free(global->p2p_disallow_freq);
+
        os_free(global);
        wpa_debug_close_syslog();
        wpa_debug_close_file();
index 671bca266057af27117b20a701953275f0282e33..91e5741865ca7986e95e6c2ecb5fab5ebcfb7745 100644 (file)
@@ -199,6 +199,12 @@ struct p2p_srv_upnp {
        char *service;
 };
 
+struct wpa_freq_range {
+       unsigned int min;
+       unsigned int max;
+};
+
+
 /**
  * struct wpa_global - Internal, global data for all %wpa_supplicant interfaces
  *
@@ -220,6 +226,8 @@ struct wpa_global {
        struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
        int p2p_disabled;
        int cross_connection;
+       struct wpa_freq_range *p2p_disallow_freq;
+       unsigned int num_p2p_disallow_freq;
 };