]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Allow peer to propose channel in invitation process
authorJouni Malinen <jouni@qca.qualcomm.com>
Mon, 24 Sep 2012 19:15:58 +0000 (22:15 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 24 Sep 2012 19:15:58 +0000 (22:15 +0300)
Make Invitation process for re-invoking a persistent group behave
similarly to GO Negotiation as far as channel negotiation is concerned.
The Operating Channel value (if present) is used as a starting point if
the local device does not have a forced operating channel (e.g., due to
concurrent use). Channel lists from devices are then compared to check
that the selected channel is in the intersection. If not, channel is
selected based on GO Negotiation channel rules (best channel preferences
etc.). Invitation Request is rejected if no common channel can be
selected.

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

src/p2p/p2p_go_neg.c
src/p2p/p2p_i.h
src/p2p/p2p_invitation.c
wpa_supplicant/p2p_supplicant.c

index 031b3a1f551fd06a754dd6a03c48e8b05ebf20a0..9137aebe950740631ab20fa95fb61fa8bda7c328 100644 (file)
@@ -336,8 +336,8 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
 }
 
 
-static void p2p_reselect_channel(struct p2p_data *p2p,
-                                struct p2p_channels *intersection)
+void p2p_reselect_channel(struct p2p_data *p2p,
+                         struct p2p_channels *intersection)
 {
        struct p2p_reg_class *cl;
        int freq;
index 860233323ff8256e354615fa9d056719c235ebc2..0f00c5402ff33f9832c16ad6436cbb044735fb6b 100644 (file)
@@ -642,6 +642,8 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
                             const u8 *data, size_t len);
 int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev);
 u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method);
+void p2p_reselect_channel(struct p2p_data *p2p,
+                         struct p2p_channels *intersection);
 
 /* p2p_pd.c */
 void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
index d26654b6619f8c815da20af7bf35f8779371dc28..e06ba12ca719d8ebacebc8d7ececca4d1520e950 100644 (file)
@@ -233,6 +233,8 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
        }
 
        if (op_freq) {
+               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Invitation "
+                       "processing forced frequency %d MHz", op_freq);
                if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
                                        &reg_class, &channel) < 0) {
                        wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
@@ -256,24 +258,89 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
                if (status == P2P_SC_SUCCESS)
                        channels = &intersection;
        } else {
+               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+                       "P2P: No forced channel from invitation processing - "
+                       "figure out best one to use");
+
+               p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
+                                      &intersection);
+               /* Default to own configuration as a starting point */
+               p2p->op_reg_class = p2p->cfg->op_reg_class;
+               p2p->op_channel = p2p->cfg->op_channel;
+               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own default "
+                       "op_class %d channel %d",
+                       p2p->op_reg_class, p2p->op_channel);
+
+               /* Use peer preference if specified and compatible */
+               if (msg.operating_channel) {
+                       int req_freq;
+                       req_freq = p2p_channel_to_freq(
+                               (const char *) msg.operating_channel,
+                               msg.operating_channel[3],
+                               msg.operating_channel[4]);
+                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer "
+                               "operating channel preference: %d MHz",
+                               req_freq);
+                       if (req_freq > 0 &&
+                           p2p_channels_includes(&intersection,
+                                                 msg.operating_channel[3],
+                                                 msg.operating_channel[4])) {
+                               p2p->op_reg_class = msg.operating_channel[3];
+                               p2p->op_channel = msg.operating_channel[4];
+                               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+                                       "P2P: Use peer preference op_class %d "
+                                       "channel %d",
+                                       p2p->op_reg_class, p2p->op_channel);
+                       } else {
+                               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+                                       "P2P: Cannot use peer channel "
+                                       "preference");
+                       }
+               }
+
+               if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
+                                          p2p->op_channel)) {
+                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+                               "P2P: Initially selected channel (op_class %d "
+                               "channel %d) not in channel intersection - try "
+                               "to reselect",
+                               p2p->op_reg_class, p2p->op_channel);
+                       p2p_reselect_channel(p2p, &intersection);
+                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+                               "P2P: Re-selection result: op_class %d "
+                               "channel %d",
+                               p2p->op_reg_class, p2p->op_channel);
+                       if (!p2p_channels_includes(&intersection,
+                                                  p2p->op_reg_class,
+                                                  p2p->op_channel)) {
+                               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+                                       "P2P: Peer does not support selected "
+                                       "operating channel (reg_class=%u "
+                                       "channel=%u)",
+                                       p2p->op_reg_class, p2p->op_channel);
+                               status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
+                               goto fail;
+                       }
+               }
+
                op_freq = p2p_channel_to_freq(p2p->cfg->country,
-                                             p2p->cfg->op_reg_class,
-                                             p2p->cfg->op_channel);
+                                             p2p->op_reg_class,
+                                             p2p->op_channel);
                if (op_freq < 0) {
                        wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
                                "P2P: Unknown operational channel "
                                "(country=%c%c reg_class=%u channel=%u)",
                                p2p->cfg->country[0], p2p->cfg->country[1],
-                               p2p->cfg->op_reg_class, p2p->cfg->op_channel);
+                               p2p->op_reg_class, p2p->op_channel);
                        status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
                        goto fail;
                }
+               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
+                       "channel - %d MHz", op_freq);
 
-               p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
-                                      &intersection);
                if (status == P2P_SC_SUCCESS) {
-                       reg_class = p2p->cfg->op_reg_class;
-                       channel = p2p->cfg->op_channel;
+                       reg_class = p2p->op_reg_class;
+                       channel = p2p->op_channel;
                        channels = &intersection;
                }
        }
index 883761a5020f264d1705992c657337aae4f60593..6abdd684b2545bd66b494b0f19e71e8b58aa99ea 100644 (file)
@@ -2249,8 +2249,9 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
                           " was accepted; op_freq=%d MHz",
                           MAC2STR(sa), op_freq);
                if (s) {
+                       int go = s->mode == WPAS_MODE_P2P_GO;
                        wpas_p2p_group_add_persistent(
-                               wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0, 0);
+                               wpa_s, s, go, go ? op_freq : 0, 0);
                } else if (bssid) {
                        wpas_p2p_join(wpa_s, bssid, go_dev_addr,
                                      wpa_s->p2p_wps_method, 0);