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 */
*/
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 */
}
+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;
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);
}
+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)
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;
}
}
+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)
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;
}
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 */
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);