]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P NFC: Add processing of P2P client while NFC handover case
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 4 Apr 2013 13:18:46 +0000 (16:18 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 27 Jan 2014 19:44:30 +0000 (21:44 +0200)
Instead of automatically triggering a connection, provide an indication
of one of the devices being a P2P client to upper layers to allow user
to determine what to do next.

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

src/common/wpa_ctrl.h
src/p2p/p2p.c
src/p2p/p2p.h
wpa_supplicant/p2p_supplicant.c

index 5948ca7b151a2edbe78e33b3521eb98dd2a78004..759cee47dd5c9c06749eb13c8f32694338eb3b66 100644 (file)
@@ -151,6 +151,8 @@ extern "C" {
 #define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id="
 #define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE "
 #define P2P_EVENT_NFC_BOTH_GO "P2P-NFC-BOTH-GO "
+#define P2P_EVENT_NFC_PEER_CLIENT "P2P-NFC-PEER-CLIENT "
+#define P2P_EVENT_NFC_WHILE_CLIENT "P2P-NFC-WHILE-CLIENT "
 
 /* parameters: <PMF enabled> <timeout in ms> <Session Information URL> */
 #define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
index 3e9bc19674159b488bc74133d4016173059df98f..d82f7603637f4db7e5bac219a09845d49f3f7dcd 100644 (file)
@@ -4379,7 +4379,8 @@ void p2p_err(struct p2p_data *p2p, const char *fmt, ...)
 
 #ifdef CONFIG_WPS_NFC
 
-static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p)
+static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p,
+                                             int client_freq)
 {
        struct wpabuf *buf;
        u8 op_class, channel;
@@ -4400,6 +4401,9 @@ static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p)
                role = P2P_GO_IN_A_GROUP;
                p2p_freq_to_channel(p2p_group_get_freq(p2p->groups[0]),
                                    &op_class, &channel);
+       } else if (client_freq > 0) {
+               role = P2P_CLIENT_IN_A_GROUP;
+               p2p_freq_to_channel(client_freq, &op_class, &channel);
        }
 
        p2p_buf_add_oob_go_neg_channel(buf, p2p->cfg->country, op_class,
@@ -4415,15 +4419,17 @@ static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p)
 }
 
 
-struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p)
+struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p,
+                                          int client_freq)
 {
-       return p2p_build_nfc_handover(p2p);
+       return p2p_build_nfc_handover(p2p, client_freq);
 }
 
 
-struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p)
+struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p,
+                                          int client_freq)
 {
-       return p2p_build_nfc_handover(p2p);
+       return p2p_build_nfc_handover(p2p, client_freq);
 }
 
 
@@ -4433,7 +4439,8 @@ int p2p_process_nfc_connection_handover(struct p2p_data *p2p,
        struct p2p_message msg;
        struct p2p_device *dev;
        const u8 *p2p_dev_addr;
-       int peer_go = 0;
+       int freq;
+       enum p2p_role_indication role;
 
        params->next_step = NO_ACTION;
 
@@ -4472,37 +4479,38 @@ int p2p_process_nfc_connection_handover(struct p2p_data *p2p,
        dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
        p2p_copy_wps_info(p2p, dev, 0, &msg);
 
-       if (msg.oob_go_neg_channel) {
-               int freq;
-               if (msg.oob_go_neg_channel[3] == 0 &&
-                   msg.oob_go_neg_channel[4] == 0)
-                       freq = 0;
-               else
-                       freq = p2p_channel_to_freq(msg.oob_go_neg_channel[3],
-                                                  msg.oob_go_neg_channel[4]);
-               if (freq < 0) {
-                       p2p_dbg(p2p, "Unknown peer OOB GO Neg channel");
-               } else {
-                       p2p_dbg(p2p, "Peer OOB GO Neg channel: %u MHz", freq);
-                       dev->oob_go_neg_freq = freq;
-               }
+       if (!msg.oob_go_neg_channel) {
+               p2p_dbg(p2p, "OOB GO Negotiation Channel attribute not included");
+               return -1;
+       }
 
-               if (!params->sel) {
-                       freq = p2p_channel_to_freq(p2p->cfg->reg_class,
-                                                  p2p->cfg->channel);
-                       if (freq < 0) {
-                               p2p_dbg(p2p, "Own listen channel not known");
-                               return -1;
-                       }
-                       p2p_dbg(p2p, "Use own Listen channel as OOB GO Neg channel: %u MHz",
-                               freq);
-                       dev->oob_go_neg_freq = freq;
-               }
+       if (msg.oob_go_neg_channel[3] == 0 &&
+           msg.oob_go_neg_channel[4] == 0)
+               freq = 0;
+       else
+               freq = p2p_channel_to_freq(msg.oob_go_neg_channel[3],
+                                          msg.oob_go_neg_channel[4]);
+       if (freq < 0) {
+               p2p_dbg(p2p, "Unknown peer OOB GO Neg channel");
+               return -1;
+       } else {
+               p2p_dbg(p2p, "Peer OOB GO Neg channel: %u MHz", freq);
+               dev->oob_go_neg_freq = freq;
+       }
 
-               if (msg.oob_go_neg_channel[5] == P2P_GO_IN_A_GROUP)
-                       peer_go = 1;
+       if (!params->sel) {
+               freq = p2p_channel_to_freq(p2p->cfg->reg_class,
+                                          p2p->cfg->channel);
+               if (freq < 0) {
+                       p2p_dbg(p2p, "Own listen channel not known");
+                       return -1;
+               }
+               p2p_dbg(p2p, "Use own Listen channel as OOB GO Neg channel: %u MHz", freq);
+               dev->oob_go_neg_freq = freq;
        }
 
+       role = msg.oob_go_neg_channel[5];
+
        p2p_parse_free(&msg);
 
        if (dev->flags & P2P_DEV_USER_REJECTED) {
@@ -4516,11 +4524,14 @@ int p2p_process_nfc_connection_handover(struct p2p_data *p2p,
                dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
        }
 
-       if (peer_go && p2p->num_groups > 0)
+       if (role == P2P_GO_IN_A_GROUP && p2p->num_groups > 0)
                params->next_step = BOTH_GO;
-       else if (peer_go)
+       else if (role == P2P_GO_IN_A_GROUP)
                params->next_step = JOIN_GROUP;
-       else if (p2p->num_groups > 0)
+       else if (role == P2P_CLIENT_IN_A_GROUP) {
+               dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY;
+               params->next_step = PEER_CLIENT;
+       } else if (p2p->num_groups > 0)
                params->next_step = AUTH_JOIN;
        else if (params->sel)
                params->next_step = INIT_GO_NEG;
index d5432c0a77a75cd047eb36b67ffa1571fb7ad60f..43b24c8501fbaa7b48a8bef8f7feaa7bc7fde07a 100644 (file)
@@ -1899,8 +1899,10 @@ int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
  */
 const char * p2p_get_state_txt(struct p2p_data *p2p);
 
-struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p);
-struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p);
+struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p,
+                                          int client_freq);
+struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p,
+                                          int client_freq);
 
 struct p2p_nfc_params {
        int sel;
@@ -1911,7 +1913,7 @@ struct p2p_nfc_params {
 
        enum {
                NO_ACTION, JOIN_GROUP, AUTH_JOIN, INIT_GO_NEG, RESP_GO_NEG,
-               BOTH_GO
+               BOTH_GO, PEER_CLIENT
        } next_step;
        struct p2p_peer_info *peer;
        u8 oob_dev_pw[WPS_OOB_PUBKEY_HASH_LEN + 2 +
index fa8c648648e448316fd85e291f7a0ab7c6c15f42..254314db755ceb0acde3ed27bc8f726ace444cf5 100644 (file)
@@ -6975,11 +6975,7 @@ static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc,
                                             struct wpabuf *p2p)
 {
        struct wpabuf *ret;
-
-       if (wsc == NULL) {
-               wpabuf_free(p2p);
-               return NULL;
-       }
+       size_t wsc_len;
 
        if (p2p == NULL) {
                wpabuf_free(wsc);
@@ -6987,15 +6983,17 @@ static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc,
                return NULL;
        }
 
-       ret = wpabuf_alloc(2 + wpabuf_len(wsc) + 2 + wpabuf_len(p2p));
+       wsc_len = wsc ? wpabuf_len(wsc) : 0;
+       ret = wpabuf_alloc(2 + wsc_len + 2 + wpabuf_len(p2p));
        if (ret == NULL) {
                wpabuf_free(wsc);
                wpabuf_free(p2p);
                return NULL;
        }
 
-       wpabuf_put_be16(ret, wpabuf_len(wsc));
-       wpabuf_put_buf(ret, wsc);
+       wpabuf_put_be16(ret, wsc_len);
+       if (wsc)
+               wpabuf_put_buf(ret, wsc);
        wpabuf_put_be16(ret, wpabuf_len(p2p));
        wpabuf_put_buf(ret, p2p);
 
@@ -7019,10 +7017,27 @@ static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc,
 }
 
 
+static int wpas_p2p_cli_freq(struct wpa_supplicant *wpa_s)
+{
+       struct wpa_supplicant *iface;
+
+       for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
+               if (iface->wpa_state < WPA_ASSOCIATING ||
+                   iface->current_ssid == NULL || iface->assoc_freq == 0 ||
+                   !iface->current_ssid->p2p_group ||
+                   iface->current_ssid->mode != WPAS_MODE_INFRA)
+                       continue;
+               return iface->assoc_freq;
+       }
+       return 0;
+}
+
+
 struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
                                          int ndef)
 {
        struct wpabuf *wsc, *p2p;
+       int cli_freq = wpas_p2p_cli_freq(wpa_s);
 
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
                wpa_printf(MSG_DEBUG, "P2P: P2P disabled - cannot build handover request");
@@ -7036,9 +7051,12 @@ struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
                return NULL;
        }
 
-       wsc = wps_build_nfc_handover_req_p2p(wpa_s->parent->wps,
-                                            wpa_s->conf->wps_nfc_dh_pubkey);
-       p2p = p2p_build_nfc_handover_req(wpa_s->global->p2p);
+       if (cli_freq == 0) {
+               wsc = wps_build_nfc_handover_req_p2p(
+                       wpa_s->parent->wps, wpa_s->conf->wps_nfc_dh_pubkey);
+       } else
+               wsc = NULL;
+       p2p = p2p_build_nfc_handover_req(wpa_s->global->p2p, cli_freq);
 
        return wpas_p2p_nfc_handover(ndef, wsc, p2p);
 }
@@ -7048,6 +7066,7 @@ struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s,
                                          int ndef, int tag)
 {
        struct wpabuf *wsc, *p2p;
+       int cli_freq = wpas_p2p_cli_freq(wpa_s);
 
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
                return NULL;
@@ -7057,14 +7076,16 @@ struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s,
                           &wpa_s->conf->wps_nfc_dh_privkey) < 0)
                return NULL;
 
-       wsc = wps_build_nfc_handover_sel_p2p(wpa_s->parent->wps,
-                                            tag ?
-                                            wpa_s->conf->wps_nfc_dev_pw_id :
-                                            DEV_PW_NFC_CONNECTION_HANDOVER,
-                                            wpa_s->conf->wps_nfc_dh_pubkey,
-                                            tag ? wpa_s->conf->wps_nfc_dev_pw :
-                                            NULL);
-       p2p = p2p_build_nfc_handover_sel(wpa_s->global->p2p);
+       if (cli_freq == 0) {
+               wsc = wps_build_nfc_handover_sel_p2p(
+                       wpa_s->parent->wps,
+                       tag ? wpa_s->conf->wps_nfc_dev_pw_id :
+                       DEV_PW_NFC_CONNECTION_HANDOVER,
+                       wpa_s->conf->wps_nfc_dh_pubkey,
+                       tag ? wpa_s->conf->wps_nfc_dev_pw : NULL);
+       } else
+               wsc = NULL;
+       p2p = p2p_build_nfc_handover_sel(wpa_s->global->p2p, cli_freq);
 
        return wpas_p2p_nfc_handover(ndef, wsc, p2p);
 }
@@ -7221,6 +7242,18 @@ static int wpas_p2p_nfc_connection_handover(struct wpa_supplicant *wpa_s,
                return 0;
        }
 
+       if (params.next_step == PEER_CLIENT) {
+               wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_PEER_CLIENT "peer="
+                       MACSTR, MAC2STR(params.peer->p2p_device_addr));
+               return 0;
+       }
+
+       if (wpas_p2p_cli_freq(wpa_s)) {
+               wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_WHILE_CLIENT "peer="
+                       MACSTR, MAC2STR(params.peer->p2p_device_addr));
+               return 0;
+       }
+
        wpabuf_free(wpa_s->p2p_oob_dev_pw);
        wpa_s->p2p_oob_dev_pw = NULL;
 
@@ -7271,6 +7304,7 @@ static int wpas_p2p_nfc_connection_handover(struct wpa_supplicant *wpa_s,
        switch (params.next_step) {
        case NO_ACTION:
        case BOTH_GO:
+       case PEER_CLIENT:
                /* already covered above */
                return 0;
        case JOIN_GROUP: