if (p2p->invite_peer == NULL)
return;
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
- p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr);
+ p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr,
+ p2p->invite_dev_pw_id);
}
if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
p2p_set_state(p2p, P2P_INVITE);
p2p_invite_send(p2p, p2p->invite_peer,
- p2p->invite_go_dev_addr);
+ p2p->invite_go_dev_addr, p2p->invite_dev_pw_id);
} else {
if (p2p->invite_peer) {
p2p_dbg(p2p, "Invitation Request retry limit reached");
* persistent group (instead of invitation to join an active
* group)
* @channels: Available operating channels for the group
+ * @dev_pw_id: Device Password ID for NFC static handover or -1 if not
+ * used
* Returns: Status code (P2P_SC_*)
*
* This optional callback can be used to implement persistent reconnect
const u8 *go_dev_addr, const u8 *ssid,
size_t ssid_len, int *go, u8 *group_bssid,
int *force_freq, int persistent_group,
- const struct p2p_channels *channels);
+ const struct p2p_channels *channels,
+ int dev_pw_id);
/**
* invitation_received - Callback on Invitation Request RX
* @persistent_group: Whether this is to reinvoke a persistent group
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
* force_freq == 0)
+ * @dev_pw_id: Device Password ID from OOB Device Password (NFC) static handover
+ * case or -1 if not used
* Returns: 0 on success, -1 on failure
*/
int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
const u8 *bssid, const u8 *ssid, size_t ssid_len,
unsigned int force_freq, const u8 *go_dev_addr,
- int persistent_group, unsigned int pref_freq);
+ int persistent_group, unsigned int pref_freq, int dev_pw_id);
/**
* p2p_presence_req - Request GO presence
const u8 *invite_go_dev_addr;
u8 invite_go_dev_addr_buf[ETH_ALEN];
+ int invite_dev_pw_id;
/**
* sd_peer - Pointer to Service Discovery peer
/* WPS IE */
u16 dev_password_id;
+ int dev_password_id_present;
u16 wps_config_methods;
const u8 *wps_pri_dev_type;
const u8 *wps_sec_dev_type_list;
void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len);
int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
- const u8 *go_dev_addr);
+ const u8 *go_dev_addr, int dev_pw_id);
void p2p_invitation_req_cb(struct p2p_data *p2p, int success);
void p2p_invitation_resp_cb(struct p2p_data *p2p, int success);
static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
struct p2p_device *peer,
- const u8 *go_dev_addr)
+ const u8 *go_dev_addr,
+ int dev_pw_id)
{
struct wpabuf *buf;
u8 *len;
wpabuf_put_buf(buf, wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (dev_pw_id >= 0) {
+ /* WSC IE in Invitation Request for NFC static handover */
+ p2p_build_wps_ie(p2p, buf, dev_pw_id, 0);
+ }
+
return buf;
}
status = p2p->cfg->invitation_process(
p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id,
msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
- &go, group_bssid, &op_freq, persistent, &intersection);
+ &go, group_bssid, &op_freq, persistent, &intersection,
+ msg.dev_password_id_present ? msg.dev_password_id : -1);
}
if (op_freq) {
int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
- const u8 *go_dev_addr)
+ const u8 *go_dev_addr, int dev_pw_id)
{
struct wpabuf *req;
int freq;
freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
+ if (freq <= 0)
+ freq = dev->oob_go_neg_freq;
if (freq <= 0) {
p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
MACSTR " to send Invitation Request",
return -1;
}
- req = p2p_build_invitation_req(p2p, dev, go_dev_addr);
+ req = p2p_build_invitation_req(p2p, dev, go_dev_addr, dev_pw_id);
if (req == NULL)
return -1;
if (p2p->state != P2P_IDLE)
int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
const u8 *bssid, const u8 *ssid, size_t ssid_len,
unsigned int force_freq, const u8 *go_dev_addr,
- int persistent_group, unsigned int pref_freq)
+ int persistent_group, unsigned int pref_freq, int dev_pw_id)
{
struct p2p_device *dev;
p2p->invite_go_dev_addr = NULL;
wpa_hexdump_ascii(MSG_DEBUG, "Invitation for SSID",
ssid, ssid_len);
+ if (dev_pw_id >= 0) {
+ p2p_dbg(p2p, "Invitation to use Device Password ID %d",
+ dev_pw_id);
+ }
+ p2p->invite_dev_pw_id = dev_pw_id;
dev = p2p_get_device(p2p, peer);
- if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) {
+ if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0 &&
+ dev->oob_go_neg_freq <= 0)) {
p2p_dbg(p2p, "Cannot invite unknown P2P Device " MACSTR,
MAC2STR(peer));
return -1;
os_memcpy(p2p->inv_ssid, ssid, ssid_len);
p2p->inv_ssid_len = ssid_len;
p2p->inv_persistent = persistent_group;
- return p2p_invite_send(p2p, dev, go_dev_addr);
+ return p2p_invite_send(p2p, dev, go_dev_addr, dev_pw_id);
}
msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id);
wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d",
msg->dev_password_id);
+ msg->dev_password_id_present = 1;
}
if (attr.primary_dev_type) {
char devtype[WPS_DEV_TYPE_BUFSIZE];
struct p2p_go_neg_results *res)
{
wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR
- " dev_addr " MACSTR,
+ " dev_addr " MACSTR " wps_method %d",
MAC2STR(res->peer_interface_addr),
- MAC2STR(res->peer_device_addr));
+ MAC2STR(res->peer_device_addr), res->wps_method);
wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start WPS Enrollee for SSID",
res->ssid, res->ssid_len);
wpa_supplicant_ap_deinit(wpa_s);
const u8 *go_dev_addr, const u8 *ssid,
size_t ssid_len, int *go, u8 *group_bssid,
int *force_freq, int persistent_group,
- const struct p2p_channels *channels)
+ const struct p2p_channels *channels,
+ int dev_pw_id)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *s;
"authorized invitation");
goto accept_inv;
}
+
+#ifdef CONFIG_WPS_NFC
+ if (dev_pw_id >= 0 && wpa_s->parent->p2p_nfc_tag_enabled &&
+ dev_pw_id == wpa_s->parent->p2p_oob_dev_pw_id) {
+ wpa_printf(MSG_DEBUG, "P2P: Accept invitation based on local enabled NFC Tag");
+ wpa_s->parent->p2p_wps_method = WPS_NFC;
+ wpa_s->parent->pending_join_wps_method = WPS_NFC;
+ os_memcpy(wpa_s->parent->pending_join_dev_addr,
+ go_dev_addr, ETH_ALEN);
+ os_memcpy(wpa_s->parent->pending_join_iface_addr,
+ bssid, ETH_ALEN);
+ goto accept_inv;
+ }
+#endif /* CONFIG_WPS_NFC */
+
/*
* Do not accept the invitation automatically; notify user and
* request approval.
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr,
- 1, pref_freq);
+ 1, pref_freq, -1);
}
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
ssid->ssid, ssid->ssid_len, force_freq,
- go_dev_addr, persistent, pref_freq);
+ go_dev_addr, persistent, pref_freq, -1);
}
static int wpas_p2p_nfc_auth_join(struct wpa_supplicant *wpa_s,
- struct p2p_nfc_params *params)
+ struct p2p_nfc_params *params, int tag)
{
+ int res, persistent;
+ struct wpa_ssid *ssid;
+
wpa_printf(MSG_DEBUG, "P2P: Authorize join-group based on NFC "
"connection handover");
for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
- struct wpa_ssid *ssid = wpa_s->current_ssid;
+ ssid = wpa_s->current_ssid;
if (ssid == NULL)
continue;
if (ssid->mode != WPAS_MODE_P2P_GO)
wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
return -1;
}
- return wpas_ap_wps_add_nfc_pw(
+ res = wpas_ap_wps_add_nfc_pw(
wpa_s, wpa_s->parent->p2p_oob_dev_pw_id,
wpa_s->parent->p2p_oob_dev_pw,
wpa_s->parent->p2p_peer_oob_pk_hash_known ?
wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL);
+ if (res)
+ return res;
+
+ if (!tag) {
+ wpa_printf(MSG_DEBUG, "P2P: Negotiated handover - wait for peer to join without invitation");
+ return 0;
+ }
+
+ if (!params->peer ||
+ !(params->peer->dev_capab & P2P_DEV_CAPAB_INVITATION_PROCEDURE))
+ return 0;
+
+ wpa_printf(MSG_DEBUG, "P2P: Static handover - invite peer " MACSTR
+ " to join", MAC2STR(params->peer->p2p_device_addr));
+
+ wpa_s->global->p2p_invite_group = wpa_s;
+ persistent = ssid->p2p_persistent_group &&
+ wpas_p2p_get_persistent(wpa_s->parent,
+ params->peer->p2p_device_addr,
+ ssid->ssid, ssid->ssid_len);
+ wpa_s->parent->pending_invite_ssid_id = -1;
+
+ return p2p_invite(wpa_s->global->p2p, params->peer->p2p_device_addr,
+ P2P_INVITE_ROLE_ACTIVE_GO, wpa_s->own_addr,
+ ssid->ssid, ssid->ssid_len, ssid->frequency,
+ wpa_s->global->p2p_dev_addr, persistent, 0,
+ wpa_s->parent->p2p_oob_dev_pw_id);
}
case JOIN_GROUP:
return wpas_p2p_nfc_join_group(wpa_s, ¶ms);
case AUTH_JOIN:
- return wpas_p2p_nfc_auth_join(wpa_s, ¶ms);
+ return wpas_p2p_nfc_auth_join(wpa_s, ¶ms, tag);
case INIT_GO_NEG:
return wpas_p2p_nfc_init_go_neg(wpa_s, ¶ms);
case RESP_GO_NEG: