P2P: Report dev_found event (if not yet done) from GO Neg Req RX
[mech_eap.git] / src / p2p / p2p_go_neg.c
index 8a86c54..a32cfac 100644 (file)
@@ -49,8 +49,7 @@ int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own,
        os_memcpy(dev->country, pos, 3);
        wpa_hexdump_ascii(MSG_DEBUG, "P2P: Peer country", pos, 3);
        if (pos[2] != 0x04 && os_memcmp(pos, p2p->cfg->country, 2) != 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
-                       "P2P: Mismatching country (ours=%c%c peer's=%c%c)",
+               p2p_info(p2p, "Mismatching country (ours=%c%c peer's=%c%c)",
                        p2p->cfg->country[0], p2p->cfg->country[1],
                        pos[0], pos[1]);
                return -1;
@@ -61,8 +60,7 @@ int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own,
                struct p2p_reg_class *cl = &ch->reg_class[ch->reg_classes];
                cl->reg_class = *pos++;
                if (pos + 1 + pos[0] > end) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
-                               "P2P: Invalid peer Channel List");
+                       p2p_info(p2p, "Invalid peer Channel List");
                        return -1;
                }
                channels = *pos++;
@@ -76,14 +74,12 @@ int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own,
        }
 
        p2p_channels_intersect(own, &dev->channels, &intersection);
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own reg_classes %d "
-               "peer reg_classes %d intersection reg_classes %d",
+       p2p_dbg(p2p, "Own reg_classes %d peer reg_classes %d intersection reg_classes %d",
                (int) own->reg_classes,
                (int) dev->channels.reg_classes,
                (int) intersection.reg_classes);
        if (intersection.reg_classes == 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_INFO,
-                       "P2P: No common channels found");
+               p2p_info(p2p, "No common channels found");
                return -1;
        }
        return 0;
@@ -107,6 +103,8 @@ u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method)
                return DEV_PW_USER_SPECIFIED;
        case WPS_PBC:
                return DEV_PW_PUSHBUTTON;
+       case WPS_NFC:
+               return DEV_PW_NFC_CONNECTION_HANDOVER;
        default:
                return DEV_PW_DEFAULT;
        }
@@ -122,6 +120,8 @@ static const char * p2p_wps_method_str(enum p2p_wps_method wps_method)
                return "Keypad";
        case WPS_PBC:
                return "PBC";
+       case WPS_NFC:
+               return "NFC";
        default:
                return "??";
        }
@@ -135,6 +135,7 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
        u8 *len;
        u8 group_capab;
        size_t extra = 0;
+       u16 pw_id;
 
 #ifdef CONFIG_WIFI_DISPLAY
        if (p2p->wfd_ie_go_neg)
@@ -176,7 +177,14 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
        p2p_buf_update_ie_hdr(buf, len);
 
        /* WPS IE with Device Password ID attribute */
-       p2p_build_wps_ie(p2p, buf, p2p_wps_method_pw_id(peer->wps_method), 0);
+       pw_id = p2p_wps_method_pw_id(peer->wps_method);
+       if (peer->oob_pw_id)
+               pw_id = peer->oob_pw_id;
+       if (p2p_build_wps_ie(p2p, buf, pw_id, 0) < 0) {
+               p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Request");
+               wpabuf_free(buf);
+               return NULL;
+       }
 
 #ifdef CONFIG_WIFI_DISPLAY
        if (p2p->wfd_ie_go_neg)
@@ -194,8 +202,7 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
 
        if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
                u16 config_method;
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Use PD-before-GO-Neg workaround for " MACSTR,
+               p2p_dbg(p2p, "Use PD-before-GO-Neg workaround for " MACSTR,
                        MAC2STR(dev->info.p2p_device_addr));
                if (dev->wps_method == WPS_PIN_DISPLAY)
                        config_method = WPS_CONFIG_KEYPAD;
@@ -210,10 +217,11 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
        }
 
        freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
+       if (dev->oob_go_neg_freq > 0)
+               freq = dev->oob_go_neg_freq;
        if (freq <= 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Listen/Operating frequency known for the "
-                       "peer " MACSTR " to send GO Negotiation Request",
+               p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
+                       MACSTR " to send GO Negotiation Request",
                        MAC2STR(dev->info.p2p_device_addr));
                return -1;
        }
@@ -221,8 +229,7 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
        req = p2p_build_go_neg_req(p2p, dev);
        if (req == NULL)
                return -1;
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: Sending GO Negotiation Request");
+       p2p_dbg(p2p, "Sending GO Negotiation Request");
        p2p_set_state(p2p, P2P_CONNECT);
        p2p->pending_action_state = P2P_PENDING_GO_NEG_REQUEST;
        p2p->go_neg_peer = dev;
@@ -231,8 +238,7 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
        if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
                            p2p->cfg->dev_addr, dev->info.p2p_device_addr,
                            wpabuf_head(req), wpabuf_len(req), 500) < 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Failed to send Action frame");
+               p2p_dbg(p2p, "Failed to send Action frame");
                /* Use P2P find to recover and retry */
                p2p_set_timeout(p2p, 0, 0);
        } else
@@ -253,9 +259,9 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
        u8 *len;
        u8 group_capab;
        size_t extra = 0;
+       u16 pw_id;
 
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: Building GO Negotiation Response");
+       p2p_dbg(p2p, "Building GO Negotiation Response");
 
 #ifdef CONFIG_WIFI_DISPLAY
        if (p2p->wfd_ie_go_neg)
@@ -289,8 +295,7 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
        p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker);
        p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout);
        if (peer && peer->go_state == REMOTE_GO) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Omit Operating "
-                       "Channel attribute");
+               p2p_dbg(p2p, "Omit Operating Channel attribute");
        } else {
                p2p_buf_add_operating_channel(buf, p2p->cfg->country,
                                              p2p->op_reg_class,
@@ -317,9 +322,14 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
        p2p_buf_update_ie_hdr(buf, len);
 
        /* WPS IE with Device Password ID attribute */
-       p2p_build_wps_ie(p2p, buf,
-                        p2p_wps_method_pw_id(peer ? peer->wps_method :
-                                             WPS_NOT_READY), 0);
+       pw_id = p2p_wps_method_pw_id(peer ? peer->wps_method : WPS_NOT_READY);
+       if (peer && peer->oob_pw_id)
+               pw_id = peer->oob_pw_id;
+       if (p2p_build_wps_ie(p2p, buf, pw_id, 0) < 0) {
+               p2p_dbg(p2p, "Failed to build WPS IE for GO Negotiation Response");
+               wpabuf_free(buf);
+               return NULL;
+       }
 
 #ifdef CONFIG_WIFI_DISPLAY
        if (p2p->wfd_ie_go_neg)
@@ -349,13 +359,26 @@ void p2p_reselect_channel(struct p2p_data *p2p,
        int freq;
        u8 op_reg_class, op_channel;
        unsigned int i;
+       const int op_classes_5ghz[] = { 124, 115, 0 };
+       const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
+       const int op_classes_vht[] = { 128, 0 };
+
+       if (p2p->own_freq_preference > 0 &&
+           p2p_freq_to_channel(p2p->own_freq_preference,
+                               &op_reg_class, &op_channel) == 0 &&
+           p2p_channels_includes(intersection, op_reg_class, op_channel)) {
+               p2p_dbg(p2p, "Pick own channel preference (reg_class %u channel %u) from intersection",
+                       op_reg_class, op_channel);
+               p2p->op_reg_class = op_reg_class;
+               p2p->op_channel = op_channel;
+               return;
+       }
 
        if (p2p->best_freq_overall > 0 &&
-           p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
+           p2p_freq_to_channel(p2p->best_freq_overall,
                                &op_reg_class, &op_channel) == 0 &&
            p2p_channels_includes(intersection, op_reg_class, op_channel)) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best overall "
-                       "channel (reg_class %u channel %u) from intersection",
+               p2p_dbg(p2p, "Pick best overall channel (reg_class %u channel %u) from intersection",
                        op_reg_class, op_channel);
                p2p->op_reg_class = op_reg_class;
                p2p->op_channel = op_channel;
@@ -363,16 +386,14 @@ void p2p_reselect_channel(struct p2p_data *p2p,
        }
 
        /* First, try to pick the best channel from another band */
-       freq = p2p_channel_to_freq(p2p->cfg->country, p2p->op_reg_class,
-                                  p2p->op_channel);
+       freq = p2p_channel_to_freq(p2p->op_reg_class, p2p->op_channel);
        if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 &&
            !p2p_channels_includes(intersection, p2p->op_reg_class,
                                   p2p->op_channel) &&
-           p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
+           p2p_freq_to_channel(p2p->best_freq_5,
                                &op_reg_class, &op_channel) == 0 &&
            p2p_channels_includes(intersection, op_reg_class, op_channel)) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 5 GHz "
-                       "channel (reg_class %u channel %u) from intersection",
+               p2p_dbg(p2p, "Pick best 5 GHz channel (reg_class %u channel %u) from intersection",
                        op_reg_class, op_channel);
                p2p->op_reg_class = op_reg_class;
                p2p->op_channel = op_channel;
@@ -382,11 +403,10 @@ void p2p_reselect_channel(struct p2p_data *p2p,
        if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 &&
            !p2p_channels_includes(intersection, p2p->op_reg_class,
                                   p2p->op_channel) &&
-           p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
+           p2p_freq_to_channel(p2p->best_freq_24,
                                &op_reg_class, &op_channel) == 0 &&
            p2p_channels_includes(intersection, op_reg_class, op_channel)) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 2.4 GHz "
-                       "channel (reg_class %u channel %u) from intersection",
+               p2p_dbg(p2p, "Pick best 2.4 GHz channel (reg_class %u channel %u) from intersection",
                        op_reg_class, op_channel);
                p2p->op_reg_class = op_reg_class;
                p2p->op_channel = op_channel;
@@ -400,27 +420,34 @@ void p2p_reselect_channel(struct p2p_data *p2p,
                                          p2p->cfg->pref_chan[i].chan)) {
                        p2p->op_reg_class = p2p->cfg->pref_chan[i].op_class;
                        p2p->op_channel = p2p->cfg->pref_chan[i].chan;
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick "
-                               "highest preferred chnnel (op_class %u "
-                               "channel %u) from intersection",
+                       p2p_dbg(p2p, "Pick highest preferred channel (op_class %u channel %u) from intersection",
                                p2p->op_reg_class, p2p->op_channel);
                        return;
                }
        }
 
+       /* Try a channel where we might be able to use VHT */
+       if (p2p_channel_select(intersection, op_classes_vht,
+                              &p2p->op_reg_class, &p2p->op_channel) == 0) {
+               p2p_dbg(p2p, "Pick possible VHT channel (op_class %u channel %u) from intersection",
+                       p2p->op_reg_class, p2p->op_channel);
+               return;
+       }
+
        /* Try a channel where we might be able to use HT40 */
-       for (i = 0; i < intersection->reg_classes; i++) {
-               struct p2p_reg_class *c = &intersection->reg_class[i];
-               if (c->reg_class == 116 || c->reg_class == 117 ||
-                   c->reg_class == 126 || c->reg_class == 127) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Pick possible HT40 channel (reg_class "
-                               "%u channel %u) from intersection",
-                               c->reg_class, c->channel[0]);
-                       p2p->op_reg_class = c->reg_class;
-                       p2p->op_channel = c->channel[0];
-                       return;
-               }
+       if (p2p_channel_select(intersection, op_classes_ht40,
+                              &p2p->op_reg_class, &p2p->op_channel) == 0) {
+               p2p_dbg(p2p, "Pick possible HT40 channel (op_class %u channel %u) from intersection",
+                       p2p->op_reg_class, p2p->op_channel);
+               return;
+       }
+
+       /* Prefer a 5 GHz channel */
+       if (p2p_channel_select(intersection, op_classes_5ghz,
+                              &p2p->op_reg_class, &p2p->op_channel) == 0) {
+               p2p_dbg(p2p, "Pick possible 5 GHz channel (op_class %u channel %u) from intersection",
+                       p2p->op_reg_class, p2p->op_channel);
+               return;
        }
 
        /*
@@ -430,9 +457,7 @@ void p2p_reselect_channel(struct p2p_data *p2p,
         */
        if (p2p_channels_includes(intersection, p2p->op_reg_class,
                                  p2p->op_channel)) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Using original operating class and channel "
-                       "(op_class %u channel %u) from intersection",
+               p2p_dbg(p2p, "Using original operating class and channel (op_class %u channel %u) from intersection",
                        p2p->op_reg_class, p2p->op_channel);
                return;
        }
@@ -442,8 +467,7 @@ void p2p_reselect_channel(struct p2p_data *p2p,
         * no better options seems to be available.
         */
        cl = &intersection->reg_class[0];
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick another channel "
-               "(reg_class %u channel %u) from intersection",
+       p2p_dbg(p2p, "Pick another channel (reg_class %u channel %u) from intersection",
                cl->reg_class, cl->channel[0]);
        p2p->op_reg_class = cl->reg_class;
        p2p->op_channel = cl->channel[0];
@@ -453,44 +477,38 @@ void p2p_reselect_channel(struct p2p_data *p2p,
 static int p2p_go_select_channel(struct p2p_data *p2p, struct p2p_device *dev,
                                 u8 *status)
 {
-       struct p2p_channels intersection;
-       size_t i;
-
-       p2p_channels_intersect(&p2p->channels, &dev->channels, &intersection);
+       struct p2p_channels tmp, intersection;
+
+       p2p_channels_dump(p2p, "own channels", &p2p->channels);
+       p2p_channels_dump(p2p, "peer channels", &dev->channels);
+       p2p_channels_intersect(&p2p->channels, &dev->channels, &tmp);
+       p2p_channels_dump(p2p, "intersection", &tmp);
+       p2p_channels_remove_freqs(&tmp, &p2p->no_go_freq);
+       p2p_channels_dump(p2p, "intersection after no-GO removal", &tmp);
+       p2p_channels_intersect(&tmp, &p2p->cfg->channels, &intersection);
+       p2p_channels_dump(p2p, "intersection with local channel list",
+                         &intersection);
        if (intersection.reg_classes == 0 ||
            intersection.reg_class[0].channels == 0) {
                *status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No common channels found");
+               p2p_dbg(p2p, "No common channels found");
                return -1;
        }
 
-       for (i = 0; i < intersection.reg_classes; i++) {
-               struct p2p_reg_class *c;
-               c = &intersection.reg_class[i];
-               wpa_printf(MSG_DEBUG, "P2P: reg_class %u", c->reg_class);
-               wpa_hexdump(MSG_DEBUG, "P2P: channels",
-                           c->channel, c->channels);
-       }
-
        if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
                                   p2p->op_channel)) {
                if (dev->flags & P2P_DEV_FORCE_FREQ) {
                        *status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer does "
-                               "not support the forced channel");
+                       p2p_dbg(p2p, "Peer does not support the forced channel");
                        return -1;
                }
 
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
-                       "channel (op_class %u channel %u) not acceptable to "
-                       "the peer", p2p->op_reg_class, p2p->op_channel);
+               p2p_dbg(p2p, "Selected operating channel (op_class %u channel %u) not acceptable to the peer",
+                       p2p->op_reg_class, p2p->op_channel);
                p2p_reselect_channel(p2p, &intersection);
        } else if (!(dev->flags & P2P_DEV_FORCE_FREQ) &&
                   !p2p->cfg->cfg_op_channel) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Try to optimize "
-                       "channel selection with peer information received; "
-                       "previously selected op_class %u channel %u",
+               p2p_dbg(p2p, "Try to optimize channel selection with peer information received; previously selected op_class %u channel %u",
                        p2p->op_reg_class, p2p->op_channel);
                p2p_reselect_channel(p2p, &intersection);
        }
@@ -514,17 +532,14 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
        int tie_breaker = 0;
        int freq;
 
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: Received GO Negotiation Request from " MACSTR
-               "(freq=%d)", MAC2STR(sa), rx_freq);
+       p2p_dbg(p2p, "Received GO Negotiation Request from " MACSTR "(freq=%d)",
+               MAC2STR(sa), rx_freq);
 
        if (p2p_parse(data, len, &msg))
                return;
 
        if (!msg.capability) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory Capability attribute missing from GO "
-                       "Negotiation Request");
+               p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Request");
 #ifdef CONFIG_P2P_STRICT
                goto fail;
 #endif /* CONFIG_P2P_STRICT */
@@ -533,53 +548,42 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
        if (msg.go_intent)
                tie_breaker = *msg.go_intent & 0x01;
        else {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory GO Intent attribute missing from GO "
-                       "Negotiation Request");
+               p2p_dbg(p2p, "Mandatory GO Intent attribute missing from GO Negotiation Request");
 #ifdef CONFIG_P2P_STRICT
                goto fail;
 #endif /* CONFIG_P2P_STRICT */
        }
 
        if (!msg.config_timeout) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory Configuration Timeout attribute "
-                       "missing from GO Negotiation Request");
+               p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Request");
 #ifdef CONFIG_P2P_STRICT
                goto fail;
 #endif /* CONFIG_P2P_STRICT */
        }
 
        if (!msg.listen_channel) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Listen Channel attribute received");
+               p2p_dbg(p2p, "No Listen Channel attribute received");
                goto fail;
        }
        if (!msg.operating_channel) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Operating Channel attribute received");
+               p2p_dbg(p2p, "No Operating Channel attribute received");
                goto fail;
        }
        if (!msg.channel_list) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Channel List attribute received");
+               p2p_dbg(p2p, "No Channel List attribute received");
                goto fail;
        }
        if (!msg.intended_addr) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Intended P2P Interface Address attribute "
-                       "received");
+               p2p_dbg(p2p, "No Intended P2P Interface Address attribute received");
                goto fail;
        }
        if (!msg.p2p_device_info) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No P2P Device Info attribute received");
+               p2p_dbg(p2p, "No P2P Device Info attribute received");
                goto fail;
        }
 
        if (os_memcmp(msg.p2p_device_addr, sa, ETH_ALEN) != 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Unexpected GO Negotiation Request SA=" MACSTR
+               p2p_dbg(p2p, "Unexpected GO Negotiation Request SA=" MACSTR
                        " != dev_addr=" MACSTR,
                        MAC2STR(sa), MAC2STR(msg.p2p_device_addr));
                goto fail;
@@ -588,133 +592,164 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
        dev = p2p_get_device(p2p, sa);
 
        if (msg.status && *msg.status) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Unexpected Status attribute (%d) in GO "
-                       "Negotiation Request", *msg.status);
+               p2p_dbg(p2p, "Unexpected Status attribute (%d) in GO Negotiation Request",
+                       *msg.status);
+               if (dev && p2p->go_neg_peer == dev &&
+                   *msg.status == P2P_SC_FAIL_REJECTED_BY_USER) {
+                       /*
+                        * This mechanism for using Status attribute in GO
+                        * Negotiation Request is not compliant with the P2P
+                        * specification, but some deployed devices use it to
+                        * indicate rejection of GO Negotiation in a case where
+                        * they have sent out GO Negotiation Response with
+                        * status 1. The P2P specification explicitly disallows
+                        * this. To avoid unnecessary interoperability issues
+                        * and extra frames, mark the pending negotiation as
+                        * failed and do not reply to this GO Negotiation
+                        * Request frame.
+                        */
+                       p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
+                       p2p_go_neg_failed(p2p, dev, *msg.status);
+                       p2p_parse_free(&msg);
+                       return;
+               }
                goto fail;
        }
 
        if (dev == NULL)
                dev = p2p_add_dev_from_go_neg_req(p2p, sa, &msg);
-       else if (dev->flags & P2P_DEV_PROBE_REQ_ONLY)
+       else if ((dev->flags & P2P_DEV_PROBE_REQ_ONLY) ||
+                 !(dev->flags & P2P_DEV_REPORTED))
                p2p_add_dev_info(p2p, sa, dev, &msg);
+       else if (!dev->listen_freq && !dev->oper_freq) {
+               /*
+                * This may happen if the peer entry was added based on PD
+                * Request and no Probe Request/Response frame has been received
+                * from this peer (or that information has timed out).
+                */
+               p2p_dbg(p2p, "Update peer " MACSTR
+                       " based on GO Neg Req since listen/oper freq not known",
+                       MAC2STR(dev->info.p2p_device_addr));
+               p2p_add_dev_info(p2p, sa, dev, &msg);
+       }
+
        if (dev && dev->flags & P2P_DEV_USER_REJECTED) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: User has rejected this peer");
+               p2p_dbg(p2p, "User has rejected this peer");
                status = P2P_SC_FAIL_REJECTED_BY_USER;
-       } else if (dev == NULL || dev->wps_method == WPS_NOT_READY) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Not ready for GO negotiation with " MACSTR,
+       } else if (dev == NULL ||
+                  (dev->wps_method == WPS_NOT_READY &&
+                   (p2p->authorized_oob_dev_pw_id == 0 ||
+                    p2p->authorized_oob_dev_pw_id !=
+                    msg.dev_password_id))) {
+               p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
                        MAC2STR(sa));
                status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
-               if (dev)
-                       dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
                p2p->cfg->go_neg_req_rx(p2p->cfg->cb_ctx, sa,
                                        msg.dev_password_id);
        } else if (p2p->go_neg_peer && p2p->go_neg_peer != dev) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Already in Group Formation with another peer");
+               p2p_dbg(p2p, "Already in Group Formation with another peer");
                status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
        } else {
                int go;
 
                if (!p2p->go_neg_peer) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting "
-                               "GO Negotiation with previously authorized "
-                               "peer");
+                       p2p_dbg(p2p, "Starting GO Negotiation with previously authorized peer");
                        if (!(dev->flags & P2P_DEV_FORCE_FREQ)) {
-                               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                                       "P2P: Use default channel settings");
+                               p2p_dbg(p2p, "Use default channel settings");
                                p2p->op_reg_class = p2p->cfg->op_reg_class;
                                p2p->op_channel = p2p->cfg->op_channel;
                                os_memcpy(&p2p->channels, &p2p->cfg->channels,
                                          sizeof(struct p2p_channels));
                        } else {
-                               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                                       "P2P: Use previously configured "
-                                       "forced channel settings");
+                               p2p_dbg(p2p, "Use previously configured forced channel settings");
                        }
                }
 
                dev->flags &= ~P2P_DEV_NOT_YET_READY;
 
                if (!msg.go_intent) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: No GO Intent attribute received");
+                       p2p_dbg(p2p, "No GO Intent attribute received");
                        goto fail;
                }
                if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Invalid GO Intent value (%u) received",
+                       p2p_dbg(p2p, "Invalid GO Intent value (%u) received",
                                *msg.go_intent >> 1);
                        goto fail;
                }
 
                if (dev->go_neg_req_sent &&
                    os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Do not reply since peer has higher "
-                               "address and GO Neg Request already sent");
+                       p2p_dbg(p2p, "Do not reply since peer has higher address and GO Neg Request already sent");
                        p2p_parse_free(&msg);
                        return;
                }
 
                go = p2p_go_det(p2p->go_intent, *msg.go_intent);
                if (go < 0) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Incompatible GO Intent");
+                       p2p_dbg(p2p, "Incompatible GO Intent");
                        status = P2P_SC_FAIL_BOTH_GO_INTENT_15;
                        goto fail;
                }
 
                if (p2p_peer_channels(p2p, dev, msg.channel_list,
                                      msg.channel_list_len) < 0) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: No common channels found");
+                       p2p_dbg(p2p, "No common channels found");
                        status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
                        goto fail;
                }
 
                switch (msg.dev_password_id) {
                case DEV_PW_REGISTRAR_SPECIFIED:
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: PIN from peer Display");
+                       p2p_dbg(p2p, "PIN from peer Display");
                        if (dev->wps_method != WPS_PIN_KEYPAD) {
-                               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                                       "P2P: We have wps_method=%s -> "
-                                       "incompatible",
+                               p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
                                        p2p_wps_method_str(dev->wps_method));
                                status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
                                goto fail;
                        }
                        break;
                case DEV_PW_USER_SPECIFIED:
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Peer entered PIN on Keypad");
+                       p2p_dbg(p2p, "Peer entered PIN on Keypad");
                        if (dev->wps_method != WPS_PIN_DISPLAY) {
-                               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                                       "P2P: We have wps_method=%s -> "
-                                       "incompatible",
+                               p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
                                        p2p_wps_method_str(dev->wps_method));
                                status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
                                goto fail;
                        }
                        break;
                case DEV_PW_PUSHBUTTON:
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Peer using pushbutton");
+                       p2p_dbg(p2p, "Peer using pushbutton");
                        if (dev->wps_method != WPS_PBC) {
-                               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                                       "P2P: We have wps_method=%s -> "
-                                       "incompatible",
+                               p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
                                        p2p_wps_method_str(dev->wps_method));
                                status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
                                goto fail;
                        }
                        break;
                default:
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Unsupported Device Password ID %d",
+                       if (msg.dev_password_id &&
+                           msg.dev_password_id == dev->oob_pw_id) {
+                               p2p_dbg(p2p, "Peer using NFC");
+                               if (dev->wps_method != WPS_NFC) {
+                                       p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
+                                               p2p_wps_method_str(
+                                                       dev->wps_method));
+                                       status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
+                                       goto fail;
+                               }
+                               break;
+                       }
+#ifdef CONFIG_WPS_NFC
+                       if (p2p->authorized_oob_dev_pw_id &&
+                           msg.dev_password_id ==
+                           p2p->authorized_oob_dev_pw_id) {
+                               p2p_dbg(p2p, "Using static handover with our device password from NFC Tag");
+                               dev->wps_method = WPS_NFC;
+                               dev->oob_pw_id = p2p->authorized_oob_dev_pw_id;
+                               break;
+                       }
+#endif /* CONFIG_WPS_NFC */
+                       p2p_dbg(p2p, "Unsupported Device Password ID %d",
                                msg.dev_password_id);
                        status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
                        goto fail;
@@ -724,20 +759,17 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
                        goto fail;
 
                dev->go_state = go ? LOCAL_GO : REMOTE_GO;
-               dev->oper_freq = p2p_channel_to_freq((const char *)
-                                                    msg.operating_channel,
-                                                    msg.operating_channel[3],
+               dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
                                                     msg.operating_channel[4]);
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
-                       "channel preference: %d MHz", dev->oper_freq);
+               p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
+                       dev->oper_freq);
 
                if (msg.config_timeout) {
                        dev->go_timeout = msg.config_timeout[0];
                        dev->client_timeout = msg.config_timeout[1];
                }
 
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: GO Negotiation with " MACSTR, MAC2STR(sa));
+               p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa));
                if (p2p->state != P2P_IDLE)
                        p2p_stop_find_for_freq(p2p, rx_freq);
                p2p_set_state(p2p, P2P_GO_NEG);
@@ -756,17 +788,14 @@ fail:
        p2p_parse_free(&msg);
        if (resp == NULL)
                return;
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: Sending GO Negotiation Response");
+       p2p_dbg(p2p, "Sending GO Negotiation Response");
        if (rx_freq > 0)
                freq = rx_freq;
        else
-               freq = p2p_channel_to_freq(p2p->cfg->country,
-                                          p2p->cfg->reg_class,
+               freq = p2p_channel_to_freq(p2p->cfg->reg_class,
                                           p2p->cfg->channel);
        if (freq < 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Unknown regulatory class/channel");
+               p2p_dbg(p2p, "Unknown regulatory class/channel");
                wpabuf_free(resp);
                return;
        }
@@ -790,8 +819,7 @@ fail:
        if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
                            p2p->cfg->dev_addr,
                            wpabuf_head(resp), wpabuf_len(resp), 500) < 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Failed to send Action frame");
+               p2p_dbg(p2p, "Failed to send Action frame");
        }
 
        wpabuf_free(resp);
@@ -809,8 +837,7 @@ static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p,
        u8 group_capab;
        size_t extra = 0;
 
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: Building GO Negotiation Confirm");
+       p2p_dbg(p2p, "Building GO Negotiation Confirm");
 
 #ifdef CONFIG_WIFI_DISPLAY
        if (p2p->wfd_ie_go_neg)
@@ -875,14 +902,12 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
        u8 status = P2P_SC_SUCCESS;
        int freq;
 
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: Received GO Negotiation Response from " MACSTR
+       p2p_dbg(p2p, "Received GO Negotiation Response from " MACSTR
                " (freq=%d)", MAC2STR(sa), rx_freq);
        dev = p2p_get_device(p2p, sa);
        if (dev == NULL || dev->wps_method == WPS_NOT_READY ||
            dev != p2p->go_neg_peer) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Not ready for GO negotiation with " MACSTR,
+               p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
                        MAC2STR(sa));
                return;
        }
@@ -891,44 +916,35 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
                return;
 
        if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE)) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Was not expecting GO Negotiation Response - "
-                       "ignore");
+               p2p_dbg(p2p, "Was not expecting GO Negotiation Response - ignore");
                p2p_parse_free(&msg);
                return;
        }
        dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
 
        if (msg.dialog_token != dev->dialog_token) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Unexpected Dialog Token %u (expected %u)",
+               p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
                        msg.dialog_token, dev->dialog_token);
                p2p_parse_free(&msg);
                return;
        }
 
        if (!msg.status) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Status attribute received");
+               p2p_dbg(p2p, "No Status attribute received");
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
        }
        if (*msg.status) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: GO Negotiation rejected: status %d",
-                       *msg.status);
+               p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status);
                dev->go_neg_req_sent = 0;
                if (*msg.status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Wait for the peer to become ready for "
-                               "GO Negotiation");
+                       p2p_dbg(p2p, "Wait for the peer to become ready for GO Negotiation");
                        dev->flags |= P2P_DEV_NOT_YET_READY;
                        dev->wait_count = 0;
                        p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
                        p2p_set_timeout(p2p, 0, 0);
                } else {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: Stop GO Negotiation attempt");
+                       p2p_dbg(p2p, "Stop GO Negotiation attempt");
                        p2p_go_neg_failed(p2p, dev, *msg.status);
                }
                p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
@@ -937,9 +953,7 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
        }
 
        if (!msg.capability) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory Capability attribute missing from GO "
-                       "Negotiation Response");
+               p2p_dbg(p2p, "Mandatory Capability attribute missing from GO Negotiation Response");
 #ifdef CONFIG_P2P_STRICT
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
@@ -947,9 +961,7 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
        }
 
        if (!msg.p2p_device_info) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory P2P Device Info attribute missing "
-                       "from GO Negotiation Response");
+               p2p_dbg(p2p, "Mandatory P2P Device Info attribute missing from GO Negotiation Response");
 #ifdef CONFIG_P2P_STRICT
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
@@ -957,22 +969,18 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
        }
 
        if (!msg.intended_addr) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Intended P2P Interface Address attribute "
-                       "received");
+               p2p_dbg(p2p, "No Intended P2P Interface Address attribute received");
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
        }
 
        if (!msg.go_intent) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No GO Intent attribute received");
+               p2p_dbg(p2p, "No GO Intent attribute received");
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
        }
        if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Invalid GO Intent value (%u) received",
+               p2p_dbg(p2p, "Invalid GO Intent value (%u) received",
                        *msg.go_intent >> 1);
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
@@ -980,8 +988,7 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
 
        go = p2p_go_det(p2p->go_intent, *msg.go_intent);
        if (go < 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Incompatible GO Intent");
+               p2p_dbg(p2p, "Incompatible GO Intent");
                status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
                goto fail;
        }
@@ -991,18 +998,14 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
                p2p->ssid_len = msg.group_id_len - ETH_ALEN;
                os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len);
        } else if (!go) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory P2P Group ID attribute missing from "
-                       "GO Negotiation Response");
+               p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Response");
                p2p->ssid_len = 0;
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
        }
 
        if (!msg.config_timeout) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory Configuration Timeout attribute "
-                       "missing from GO Negotiation Response");
+               p2p_dbg(p2p, "Mandatory Configuration Timeout attribute missing from GO Negotiation Response");
 #ifdef CONFIG_P2P_STRICT
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
@@ -1017,76 +1020,72 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
                 * Note: P2P Client may omit Operating Channel attribute to
                 * indicate it does not have a preference.
                 */
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Operating Channel attribute received");
+               p2p_dbg(p2p, "No Operating Channel attribute received");
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
        }
        if (!msg.channel_list) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Channel List attribute received");
+               p2p_dbg(p2p, "No Channel List attribute received");
                status = P2P_SC_FAIL_INVALID_PARAMS;
                goto fail;
        }
 
        if (p2p_peer_channels(p2p, dev, msg.channel_list,
                              msg.channel_list_len) < 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No common channels found");
+               p2p_dbg(p2p, "No common channels found");
                status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
                goto fail;
        }
 
        if (msg.operating_channel) {
-               dev->oper_freq = p2p_channel_to_freq((const char *)
-                                                    msg.operating_channel,
-                                                    msg.operating_channel[3],
+               dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
                                                     msg.operating_channel[4]);
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
-                       "channel preference: %d MHz", dev->oper_freq);
+               p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
+                       dev->oper_freq);
        } else
                dev->oper_freq = 0;
 
        switch (msg.dev_password_id) {
        case DEV_PW_REGISTRAR_SPECIFIED:
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: PIN from peer Display");
+               p2p_dbg(p2p, "PIN from peer Display");
                if (dev->wps_method != WPS_PIN_KEYPAD) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: We have wps_method=%s -> "
-                               "incompatible",
+                       p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
                                p2p_wps_method_str(dev->wps_method));
                        status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
                        goto fail;
                }
                break;
        case DEV_PW_USER_SPECIFIED:
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Peer entered PIN on Keypad");
+               p2p_dbg(p2p, "Peer entered PIN on Keypad");
                if (dev->wps_method != WPS_PIN_DISPLAY) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: We have wps_method=%s -> "
-                               "incompatible",
+                       p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
                                p2p_wps_method_str(dev->wps_method));
                        status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
                        goto fail;
                }
                break;
        case DEV_PW_PUSHBUTTON:
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Peer using pushbutton");
+               p2p_dbg(p2p, "Peer using pushbutton");
                if (dev->wps_method != WPS_PBC) {
-                       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                               "P2P: We have wps_method=%s -> "
-                               "incompatible",
+                       p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
                                p2p_wps_method_str(dev->wps_method));
                        status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
                        goto fail;
                }
                break;
        default:
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Unsupported Device Password ID %d",
+               if (msg.dev_password_id &&
+                   msg.dev_password_id == dev->oob_pw_id) {
+                       p2p_dbg(p2p, "Peer using NFC");
+                       if (dev->wps_method != WPS_NFC) {
+                               p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
+                                       p2p_wps_method_str(dev->wps_method));
+                               status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
+                               goto fail;
+                       }
+                       break;
+               }
+               p2p_dbg(p2p, "Unsupported Device Password ID %d",
                        msg.dev_password_id);
                status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
                goto fail;
@@ -1098,8 +1097,7 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
        p2p_set_state(p2p, P2P_GO_NEG);
        p2p_clear_timeout(p2p);
 
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: GO Negotiation with " MACSTR, MAC2STR(sa));
+       p2p_dbg(p2p, "GO Negotiation with " MACSTR, MAC2STR(sa));
        os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN);
 
 fail:
@@ -1108,8 +1106,7 @@ fail:
        p2p_parse_free(&msg);
        if (conf == NULL)
                return;
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: Sending GO Negotiation Confirm");
+       p2p_dbg(p2p, "Sending GO Negotiation Confirm");
        if (status == P2P_SC_SUCCESS) {
                p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM;
                dev->go_state = go ? LOCAL_GO : REMOTE_GO;
@@ -1120,15 +1117,14 @@ fail:
        else
                freq = dev->listen_freq;
        if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa,
-                           wpabuf_head(conf), wpabuf_len(conf), 0) < 0) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Failed to send Action frame");
+                           wpabuf_head(conf), wpabuf_len(conf), 200) < 0) {
+               p2p_dbg(p2p, "Failed to send Action frame");
                p2p_go_neg_failed(p2p, dev, -1);
+               p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
        }
        wpabuf_free(conf);
        if (status != P2P_SC_SUCCESS) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: GO Negotiation failed");
+               p2p_dbg(p2p, "GO Negotiation failed");
                p2p_go_neg_failed(p2p, dev, status);
        }
 }
@@ -1140,22 +1136,18 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
        struct p2p_device *dev;
        struct p2p_message msg;
 
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-               "P2P: Received GO Negotiation Confirm from " MACSTR,
+       p2p_dbg(p2p, "Received GO Negotiation Confirm from " MACSTR,
                MAC2STR(sa));
        dev = p2p_get_device(p2p, sa);
        if (dev == NULL || dev->wps_method == WPS_NOT_READY ||
            dev != p2p->go_neg_peer) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Not ready for GO negotiation with " MACSTR,
+               p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
                        MAC2STR(sa));
                return;
        }
 
        if (p2p->pending_action_state == P2P_PENDING_GO_NEG_RESPONSE) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopped waiting "
-                       "for TX status on GO Negotiation Response since we "
-                       "already received Confirmation");
+               p2p_dbg(p2p, "Stopped waiting for TX status on GO Negotiation Response since we already received Confirmation");
                p2p->pending_action_state = P2P_NO_PENDING_ACTION;
        }
 
@@ -1163,31 +1155,27 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
                return;
 
        if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Was not expecting GO Negotiation Confirm - "
-                       "ignore");
+               p2p_dbg(p2p, "Was not expecting GO Negotiation Confirm - ignore");
+               p2p_parse_free(&msg);
                return;
        }
        dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
+       p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
 
        if (msg.dialog_token != dev->dialog_token) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Unexpected Dialog Token %u (expected %u)",
+               p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
                        msg.dialog_token, dev->dialog_token);
                p2p_parse_free(&msg);
                return;
        }
 
        if (!msg.status) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: No Status attribute received");
+               p2p_dbg(p2p, "No Status attribute received");
                p2p_parse_free(&msg);
                return;
        }
        if (*msg.status) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: GO Negotiation rejected: status %d",
-                       *msg.status);
+               p2p_dbg(p2p, "GO Negotiation rejected: status %d", *msg.status);
                p2p_go_neg_failed(p2p, dev, *msg.status);
                p2p_parse_free(&msg);
                return;
@@ -1198,9 +1186,7 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
                p2p->ssid_len = msg.group_id_len - ETH_ALEN;
                os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len);
        } else if (dev->go_state == REMOTE_GO) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory P2P Group ID attribute missing from "
-                       "GO Negotiation Confirmation");
+               p2p_dbg(p2p, "Mandatory P2P Group ID attribute missing from GO Negotiation Confirmation");
                p2p->ssid_len = 0;
                p2p_go_neg_failed(p2p, dev, P2P_SC_FAIL_INVALID_PARAMS);
                p2p_parse_free(&msg);
@@ -1208,19 +1194,23 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
        }
 
        if (!msg.operating_channel) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory Operating Channel attribute missing "
-                       "from GO Negotiation Confirmation");
+               p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation");
 #ifdef CONFIG_P2P_STRICT
                p2p_parse_free(&msg);
                return;
 #endif /* CONFIG_P2P_STRICT */
+       } else if (dev->go_state == REMOTE_GO) {
+               int oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
+                                                   msg.operating_channel[4]);
+               if (oper_freq != dev->oper_freq) {
+                       p2p_dbg(p2p, "Updated peer (GO) operating channel preference from %d MHz to %d MHz",
+                               dev->oper_freq, oper_freq);
+                       dev->oper_freq = oper_freq;
+               }
        }
 
        if (!msg.channel_list) {
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Mandatory Operating Channel attribute missing "
-                       "from GO Negotiation Confirmation");
+               p2p_dbg(p2p, "Mandatory Operating Channel attribute missing from GO Negotiation Confirmation");
 #ifdef CONFIG_P2P_STRICT
                p2p_parse_free(&msg);
                return;
@@ -1234,9 +1224,7 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
                 * This should not happen since GO negotiation has already
                 * been completed.
                 */
-               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
-                       "P2P: Unexpected GO Neg state - do not know which end "
-                       "becomes GO");
+               p2p_dbg(p2p, "Unexpected GO Neg state - do not know which end becomes GO");
                return;
        }
 
@@ -1248,8 +1236,7 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
         * the group so that we will remain on the current channel to
         * acknowledge any possible retransmission from the peer.
         */
-       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: 20 ms wait on current "
-               "channel before starting group");
+       p2p_dbg(p2p, "20 ms wait on current channel before starting group");
        os_sleep(0, 20000);
 
        p2p_go_complete(p2p, dev);