aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/p2p/p2p.c52
-rw-r--r--src/p2p/p2p.h3
-rw-r--r--src/p2p/p2p_group.c7
-rw-r--r--src/p2p/p2p_i.h1
-rw-r--r--wpa_supplicant/ctrl_iface.c63
-rw-r--r--wpa_supplicant/p2p_supplicant.c103
-rw-r--r--wpa_supplicant/p2p_supplicant.h4
7 files changed, 233 insertions, 0 deletions
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 0fb2bd4..ae3ba85 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -4370,3 +4370,55 @@ void p2p_err(struct p2p_data *p2p, const char *fmt, ...)
va_end(ap);
p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_ERROR, buf);
}
+
+
+#ifdef CONFIG_WPS_NFC
+
+static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p)
+{
+ struct wpabuf *buf;
+ u8 op_class, channel;
+ enum p2p_role_indication role = P2P_DEVICE_NOT_IN_GROUP;
+
+ buf = wpabuf_alloc(1000);
+ if (buf == NULL)
+ return NULL;
+
+ op_class = p2p->cfg->reg_class;
+ channel = p2p->cfg->channel;
+
+ p2p_buf_add_capability(buf, p2p->dev_capab &
+ ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
+ p2p_buf_add_device_info(buf, p2p, NULL);
+
+ if (p2p->num_groups > 0) {
+ role = P2P_GO_IN_A_GROUP;
+ p2p_freq_to_channel(p2p_group_get_freq(p2p->groups[0]),
+ &op_class, &channel);
+ }
+
+ p2p_buf_add_oob_go_neg_channel(buf, p2p->cfg->country, op_class,
+ channel, role);
+
+ if (p2p->num_groups > 0) {
+ /* Limit number of clients to avoid very long message */
+ p2p_buf_add_group_info(p2p->groups[0], buf, 5);
+ p2p_group_buf_add_id(p2p->groups[0], buf);
+ }
+
+ return buf;
+}
+
+
+struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p)
+{
+ return p2p_build_nfc_handover(p2p);
+}
+
+
+struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p)
+{
+ return p2p_build_nfc_handover(p2p);
+}
+
+#endif /* CONFIG_WPS_NFC */
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 247491e..1dc71fa 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1897,4 +1897,7 @@ 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);
+
#endif /* P2P_H */
diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c
index dddf92c..3154acc 100644
--- a/src/p2p/p2p_group.c
+++ b/src/p2p/p2p_group.c
@@ -419,6 +419,13 @@ void p2p_buf_add_group_info(struct p2p_group *group, struct wpabuf *buf,
}
+void p2p_group_buf_add_id(struct p2p_group *group, struct wpabuf *buf)
+{
+ p2p_buf_add_group_id(buf, group->p2p->cfg->dev_addr, group->cfg->ssid,
+ group->cfg->ssid_len);
+}
+
+
static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group)
{
struct wpabuf *p2p_subelems, *ie;
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 0fa4b70..2101841 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -613,6 +613,7 @@ void p2p_group_force_beacon_update_ies(struct p2p_group *group);
struct wpabuf * p2p_group_get_wfd_ie(struct p2p_group *g);
void p2p_buf_add_group_info(struct p2p_group *group, struct wpabuf *buf,
int max_clients);
+void p2p_group_buf_add_id(struct p2p_group *group, struct wpabuf *buf);
int p2p_group_get_freq(struct p2p_group *group);
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 7ba17db..cde9c46 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -928,6 +928,30 @@ static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
}
+static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
+ char *reply, size_t max_len,
+ int ndef)
+{
+ struct wpabuf *buf;
+ int res;
+
+ buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
+ if (buf == NULL) {
+ wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
+ return -1;
+ }
+
+ res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+ wpabuf_len(buf));
+ reply[res++] = '\n';
+ reply[res] = '\0';
+
+ wpabuf_free(buf);
+
+ return res;
+}
+
+
static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
char *cmd, char *reply,
size_t max_len)
@@ -954,6 +978,11 @@ static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
wpa_s, reply, max_len, ndef);
}
+ if (os_strcmp(pos, "P2P-CR") == 0) {
+ return wpas_ctrl_nfc_get_handover_req_p2p(
+ wpa_s, reply, max_len, ndef);
+ }
+
return -1;
}
@@ -980,6 +1009,28 @@ static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
}
+static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
+ char *reply, size_t max_len,
+ int ndef, int tag)
+{
+ struct wpabuf *buf;
+ int res;
+
+ buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
+ if (buf == NULL)
+ return -1;
+
+ res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+ wpabuf_len(buf));
+ reply[res++] = '\n';
+ reply[res] = '\0';
+
+ wpabuf_free(buf);
+
+ return res;
+}
+
+
static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
char *cmd, char *reply,
size_t max_len)
@@ -1003,11 +1054,23 @@ static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
if (pos2)
*pos2++ = '\0';
if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
+ if (!ndef)
+ return -1;
return wpas_ctrl_nfc_get_handover_sel_wps(
wpa_s, reply, max_len, ndef,
os_strcmp(pos, "WPS-CR") == 0, pos2);
}
+ if (os_strcmp(pos, "P2P-CR") == 0) {
+ return wpas_ctrl_nfc_get_handover_sel_p2p(
+ wpa_s, reply, max_len, ndef, 0);
+ }
+
+ if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
+ return wpas_ctrl_nfc_get_handover_sel_p2p(
+ wpa_s, reply, max_len, ndef, 1);
+ }
+
return -1;
}
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 8ec70dc..e61d5ce 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -6923,3 +6923,106 @@ int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
wpa_s->p2p_last_4way_hs_fail = ssid;
return 0;
}
+
+
+#ifdef CONFIG_WPS_NFC
+
+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;
+ }
+
+ if (p2p == NULL) {
+ wpabuf_free(wsc);
+ wpa_printf(MSG_DEBUG, "P2P: No p2p buffer for handover");
+ return NULL;
+ }
+
+ ret = wpabuf_alloc(2 + wpabuf_len(wsc) + 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, wpabuf_len(p2p));
+ wpabuf_put_buf(ret, p2p);
+
+ wpabuf_free(wsc);
+ wpabuf_free(p2p);
+ wpa_hexdump_buf(MSG_DEBUG,
+ "P2P: Generated NFC connection handover message", ret);
+
+ if (ndef && ret) {
+ struct wpabuf *tmp;
+ tmp = ndef_build_p2p(ret);
+ wpabuf_free(ret);
+ if (tmp == NULL) {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to NDEF encapsulate handover request");
+ return NULL;
+ }
+ ret = tmp;
+ }
+
+ return ret;
+}
+
+
+struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
+ int ndef)
+{
+ struct wpabuf *wsc, *p2p;
+
+ if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
+ wpa_printf(MSG_DEBUG, "P2P: P2P disabled - cannot build handover request");
+ return NULL;
+ }
+
+ if (wpa_s->conf->wps_nfc_dh_pubkey == NULL &&
+ wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
+ &wpa_s->conf->wps_nfc_dh_privkey) < 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No DH key available for handover request");
+ 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);
+
+ return wpas_p2p_nfc_handover(ndef, wsc, p2p);
+}
+
+
+struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+ int ndef, int tag)
+{
+ struct wpabuf *wsc, *p2p;
+
+ if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
+ return NULL;
+
+ if (!tag && wpa_s->conf->wps_nfc_dh_pubkey == NULL &&
+ wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
+ &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);
+
+ return wpas_p2p_nfc_handover(ndef, wsc, p2p);
+}
+
+#endif /* CONFIG_WPS_NFC */
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 7abfb12..17e7bae 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -148,6 +148,10 @@ void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
const u8 *psk, size_t psk_len);
void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer,
int iface_addr);
+struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
+ int ndef);
+struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+ int ndef, int tag);
#ifdef CONFIG_P2P
int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);