#include "ap/ap_config.h"
#include "ap/sta_info.h"
#include "ap/ap_drv_ops.h"
+#include "ap/wps_hostapd.h"
#include "ap/p2p_hostapd.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "rsn_supp/wpa.h"
static struct wpa_supplicant *
wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
int go);
-static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s);
+static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
+ const u8 *ssid, size_t ssid_len);
static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
const u8 *ssid, size_t ssid_len);
static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
const u8 *dev_addr, enum p2p_wps_method wps_method,
- int auto_join, const u8 *ssid, size_t ssid_len);
+ int auto_join, int freq,
+ const u8 *ssid, size_t ssid_len);
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
int group_added);
static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
+static void wpas_stop_listen(void *ctx);
/*
int ret;
if (deinit) {
- wpa_scan_free_params(params);
+ if (!work->started) {
+ wpa_scan_free_params(params);
+ return;
+ }
+
+ wpa_s->p2p_scan_work = NULL;
return;
}
break;
}
- radio_remove_unstarted_work(wpa_s, "p2p-scan");
+ radio_remove_works(wpa_s, "p2p-scan", 0);
if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb,
params) < 0)
goto fail;
bssid = wpa_s->bssid;
bss = wpa_bss_get(wpa_s, bssid, ssid, ssid_len);
+ if (bss == NULL && wpa_s->go_params &&
+ !is_zero_ether_addr(wpa_s->go_params->peer_device_addr))
+ bss = wpa_bss_get_p2p_dev_addr(
+ wpa_s, wpa_s->go_params->peer_device_addr);
if (bss == NULL) {
u8 iface_addr[ETH_ALEN];
if (p2p_get_interface_addr(wpa_s->global->p2p, bssid,
changed = 1;
}
-#ifndef CONFIG_NO_CONFIG_WRITE
if (changed && wpa_s->conf->update_config &&
wpa_config_write(wpa_s->confname, wpa_s->conf)) {
wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
}
-#endif /* CONFIG_NO_CONFIG_WRITE */
return s->id;
}
addr, ETH_ALEN);
}
-#ifndef CONFIG_NO_CONFIG_WRITE
if (wpa_s->parent->conf->update_config &&
wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
-#endif /* CONFIG_NO_CONFIG_WRITE */
}
struct send_action_work *awork = work->ctx;
if (deinit) {
+ if (work->started) {
+ eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
+ wpa_s, NULL);
+ wpa_s->p2p_send_action_work = NULL;
+ offchannel_send_action_done(wpa_s);
+ }
os_free(awork);
return;
}
static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *res)
{
- wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR,
- MAC2STR(res->peer_interface_addr));
+ wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR
+ " dev_addr " MACSTR " wps_method %d",
+ MAC2STR(res->peer_interface_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);
wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1);
#ifdef CONFIG_WPS_NFC
} else if (res->wps_method == WPS_NFC) {
- wpas_wps_start_nfc(wpa_s, res->peer_interface_addr,
+ wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
+ res->peer_interface_addr,
wpa_s->parent->p2p_oob_dev_pw,
wpa_s->parent->p2p_oob_dev_pw_id, 1,
wpa_s->parent->p2p_oob_dev_pw_id ==
DEV_PW_NFC_CONNECTION_HANDOVER ?
wpa_s->parent->p2p_peer_oob_pubkey_hash :
NULL,
- NULL, 0);
+ NULL, 0, 0);
#endif /* CONFIG_WPS_NFC */
} else {
u16 dev_pw_id = DEV_PW_DEFAULT;
d->dtim_period = s->dtim_period;
d->disassoc_low_ack = s->disassoc_low_ack;
d->disable_scan_offload = s->disable_scan_offload;
+
+ if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey) {
+ d->wps_nfc_dh_privkey = wpabuf_dup(s->wps_nfc_dh_privkey);
+ d->wps_nfc_dh_pubkey = wpabuf_dup(s->wps_nfc_dh_pubkey);
+ }
}
info->dev_capab, info->group_capab,
wfd_dev_info_hex ? " wfd_dev_info=0x" : "",
wfd_dev_info_hex ? wfd_dev_info_hex : "");
-#endif /* CONFIG_NO_STDOUT_DEBUG */
os_free(wfd_dev_info_hex);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
wpas_notify_p2p_device_found(ctx, info->p2p_device_addr, new_device);
}
struct wpas_p2p_listen_work *lwork = work->ctx;
if (deinit) {
+ if (work->started) {
+ wpa_s->p2p_listen_work = NULL;
+ wpas_stop_listen(wpa_s);
+ }
wpas_p2p_listen_work_free(lwork);
return;
}
wpa_s->pending_pd_before_join = 0;
wpa_printf(MSG_DEBUG, "P2P: Starting pending "
"join-existing-group operation");
- wpas_p2p_join_start(wpa_s);
+ wpas_p2p_join_start(wpa_s, 0, NULL, 0);
return;
}
wpa_printf(MSG_DEBUG, "P2P: Starting pending "
"join-existing-group operation (no ACK for PD "
"Req attempts)");
- wpas_p2p_join_start(wpa_s);
+ wpas_p2p_join_start(wpa_s, 0, NULL, 0);
return;
}
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.
if (s) {
int go = s->mode == WPAS_MODE_P2P_GO;
wpas_p2p_group_add_persistent(
- wpa_s, s, go, go ? op_freq : 0, 0, 0, NULL,
+ wpa_s, s, go, 0, go ? op_freq : 0, 0, 0, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
wpas_p2p_join(wpa_s, bssid, go_dev_addr,
- wpa_s->p2p_wps_method, 0,
+ wpa_s->p2p_wps_method, 0, op_freq,
ssid, ssid_len);
}
return;
ssid->p2p_client_list + (i + 1) * ETH_ALEN,
(ssid->num_p2p_clients - i - 1) * ETH_ALEN);
ssid->num_p2p_clients--;
-#ifndef CONFIG_NO_CONFIG_WRITE
if (wpa_s->parent->conf->update_config &&
wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
-#endif /* CONFIG_NO_CONFIG_WRITE */
}
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid;
- int freq;
if (bssid) {
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
"starting persistent group");
os_sleep(0, 50000);
- freq = wpa_s->p2p_persistent_go_freq;
- if (neg_freq > 0 && ssid->mode == WPAS_MODE_P2P_GO &&
- freq_included(channels, neg_freq)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use frequence %d MHz from invitation for GO mode",
- neg_freq);
- freq = neg_freq;
- }
-
wpas_p2p_group_add_persistent(wpa_s, ssid,
ssid->mode == WPAS_MODE_P2P_GO,
- freq,
+ wpa_s->p2p_persistent_go_freq,
+ neg_freq,
wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
channels,
ssid->mode == WPAS_MODE_P2P_GO ?
struct hostapd_hw_modes *mode,
u8 channel, u8 bw)
{
- int flag;
+ int flag = 0;
enum chan_allowed res, res2;
res2 = res = has_channel(wpa_s->global, mode, channel, &flag);
iface.ifname = wpa_s->pending_interface_name;
iface.driver = wpa_s->driver->name;
iface.driver_param = wpa_s->conf->driver_param;
- iface.confname = wpa_s->confname;
+
+ /*
+ * If a P2P Device configuration file was given, use it as the interface
+ * configuration file (instead of using parent's configuration file.
+ */
+ if (wpa_s->conf_p2p_dev) {
+ iface.confname = wpa_s->conf_p2p_dev;
+ iface.ctrl_interface = NULL;
+ } else {
+ iface.confname = wpa_s->confname;
+ iface.ctrl_interface = wpa_s->conf->ctrl_interface;
+ }
+ iface.conf_p2p_dev = NULL;
+
p2pdev_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
if (!p2pdev_wpa_s) {
wpa_printf(MSG_DEBUG, "P2P: Failed to add P2P Device interface");
start:
/* Start join operation immediately */
- wpas_p2p_join_start(wpa_s);
+ wpas_p2p_join_start(wpa_s, 0, NULL, 0);
}
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
const u8 *dev_addr, enum p2p_wps_method wps_method,
- int auto_join, const u8 *ssid, size_t ssid_len)
+ int auto_join, int op_freq,
+ const u8 *ssid, size_t ssid_len)
{
wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
- MACSTR " dev " MACSTR ")%s",
- MAC2STR(iface_addr), MAC2STR(dev_addr),
+ MACSTR " dev " MACSTR " op_freq=%d)%s",
+ MAC2STR(iface_addr), MAC2STR(dev_addr), op_freq,
auto_join ? " (auto_join)" : "");
if (ssid && ssid_len) {
wpa_printf(MSG_DEBUG, "P2P: Group SSID specified: %s",
wpas_p2p_stop_find(wpa_s);
wpa_s->p2p_join_scan_count = 0;
- wpas_p2p_join_scan_req(wpa_s, 0, ssid, ssid_len);
+ wpas_p2p_join_scan_req(wpa_s, op_freq, ssid, ssid_len);
return 0;
}
-static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
+static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
+ const u8 *ssid, size_t ssid_len)
{
struct wpa_supplicant *group;
struct p2p_go_neg_results res;
group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg;
os_memset(&res, 0, sizeof(res));
+ os_memcpy(res.peer_device_addr, wpa_s->pending_join_dev_addr, ETH_ALEN);
os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
ETH_ALEN);
res.wps_method = wpa_s->pending_join_wps_method;
- bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr);
- if (bss) {
- res.freq = bss->freq;
- res.ssid_len = bss->ssid_len;
- os_memcpy(res.ssid, bss->ssid, bss->ssid_len);
- wpa_printf(MSG_DEBUG, "P2P: Join target GO operating frequency "
- "from BSS table: %d MHz (SSID %s)", bss->freq,
- wpa_ssid_txt(bss->ssid, bss->ssid_len));
+ if (freq && ssid && ssid_len) {
+ res.freq = freq;
+ res.ssid_len = ssid_len;
+ os_memcpy(res.ssid, ssid, ssid_len);
+ } else {
+ bss = wpa_bss_get_bssid_latest(wpa_s,
+ wpa_s->pending_join_iface_addr);
+ if (bss) {
+ res.freq = bss->freq;
+ res.ssid_len = bss->ssid_len;
+ os_memcpy(res.ssid, bss->ssid, bss->ssid_len);
+ wpa_printf(MSG_DEBUG, "P2P: Join target GO operating frequency from BSS table: %d MHz (SSID %s)",
+ bss->freq,
+ wpa_ssid_txt(bss->ssid, bss->ssid_len));
+ }
}
if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
}
wpa_s->user_initiated_pd = 1;
if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
- auto_join, NULL, 0) < 0)
+ auto_join, freq, NULL, 0) < 0)
return -1;
return ret;
}
p2p_listen_cb(wpa_s->global->p2p, wpa_s->pending_listen_freq,
wpa_s->pending_listen_duration);
wpa_s->pending_listen_freq = 0;
+ } else {
+ wpa_printf(MSG_DEBUG, "P2P: Ignore remain-on-channel callback (off_channel_freq=%u pending_listen_freq=%d freq=%u duration=%u)",
+ wpa_s->off_channel_freq, wpa_s->pending_listen_freq,
+ freq, duration);
}
}
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
- int freq, int ht40, int vht,
- const struct p2p_channels *channels,
+ int force_freq, int neg_freq, int ht40,
+ int vht, const struct p2p_channels *channels,
int connection_timeout)
{
struct p2p_go_neg_results params;
- int go = 0;
+ int go = 0, freq;
if (ssid->disabled != 2 || ssid->ssid == NULL)
return -1;
if (ssid->mode != WPAS_MODE_P2P_GO)
return -1;
- freq = wpas_p2p_select_go_freq(wpa_s, freq);
- if (freq < 0)
- return -1;
+ if (force_freq > 0) {
+ freq = wpas_p2p_select_go_freq(wpa_s, force_freq);
+ if (freq < 0)
+ return -1;
+ } else {
+ freq = wpas_p2p_select_go_freq(wpa_s, neg_freq);
+ if (freq < 0 || (freq > 0 && !freq_included(channels, freq)))
+ freq = 0;
+ }
if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, vht, channels))
return -1;
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);
}
}
dl_list_add(&persistent->psk_list, &p->list);
-#ifndef CONFIG_NO_CONFIG_WRITE
if (wpa_s->parent->conf->update_config &&
wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
-#endif /* CONFIG_NO_CONFIG_WRITE */
}
int res;
res = wpas_p2p_remove_psk_entry(wpa_s, s, addr, iface_addr);
- if (res > 0) {
-#ifndef CONFIG_NO_CONFIG_WRITE
- if (wpa_s->conf->update_config &&
- wpa_config_write(wpa_s->confname, wpa_s->conf))
- wpa_dbg(wpa_s, MSG_DEBUG,
- "P2P: Failed to update configuration");
-#endif /* CONFIG_NO_CONFIG_WRITE */
- }
+ if (res > 0 && wpa_s->conf->update_config &&
+ wpa_config_write(wpa_s->confname, wpa_s->conf))
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Failed to update configuration");
}
struct wpabuf *p2p)
{
struct wpabuf *ret;
-
- if (wsc == NULL) {
- wpabuf_free(p2p);
- return NULL;
- }
+ size_t wsc_len;
if (p2p == NULL) {
wpabuf_free(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);
}
+static int wpas_p2p_cli_freq(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid **ssid, u8 *go_dev_addr)
+{
+ struct wpa_supplicant *iface;
+
+ if (go_dev_addr)
+ os_memset(go_dev_addr, 0, ETH_ALEN);
+ if (ssid)
+ *ssid = NULL;
+ 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;
+ if (ssid)
+ *ssid = iface->current_ssid;
+ if (go_dev_addr)
+ os_memcpy(go_dev_addr, iface->go_dev_addr, ETH_ALEN);
+ return iface->assoc_freq;
+ }
+ return 0;
+}
+
+
struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
int ndef)
{
struct wpabuf *wsc, *p2p;
+ struct wpa_ssid *ssid;
+ u8 go_dev_addr[ETH_ALEN];
+ int cli_freq = wpas_p2p_cli_freq(wpa_s, &ssid, go_dev_addr);
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
wpa_printf(MSG_DEBUG, "P2P: P2P disabled - cannot build 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);
+ 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,
+ go_dev_addr, ssid ? ssid->ssid : NULL,
+ ssid ? ssid->ssid_len : 0);
return wpas_p2p_nfc_handover(ndef, wsc, p2p);
}
int ndef, int tag)
{
struct wpabuf *wsc, *p2p;
+ struct wpa_ssid *ssid;
+ u8 go_dev_addr[ETH_ALEN];
+ int cli_freq = wpas_p2p_cli_freq(wpa_s, &ssid, go_dev_addr);
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return NULL;
&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,
+ go_dev_addr, ssid ? ssid->ssid : NULL,
+ ssid ? ssid->ssid_len : 0);
return wpas_p2p_nfc_handover(ndef, wsc, p2p);
}
struct p2p_nfc_params *params)
{
wpa_printf(MSG_DEBUG, "P2P: Initiate join-group based on NFC "
- "connection handover");
+ "connection handover (freq=%d)",
+ params->go_freq);
+
+ if (params->go_freq && params->go_ssid_len) {
+ wpa_s->p2p_wps_method = WPS_NFC;
+ wpa_s->pending_join_wps_method = WPS_NFC;
+ os_memset(wpa_s->pending_join_iface_addr, 0, ETH_ALEN);
+ os_memcpy(wpa_s->pending_join_dev_addr, params->go_dev_addr,
+ ETH_ALEN);
+ return wpas_p2p_join_start(wpa_s, params->go_freq,
+ params->go_ssid,
+ params->go_ssid_len);
+ }
+
return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
- 0, -1, 0, 1, 1);
+ params->go_freq, -1, 0, 1, 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);
}
static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s,
- struct p2p_nfc_params *params)
+ struct p2p_nfc_params *params,
+ int forced_freq)
{
wpa_printf(MSG_DEBUG, "P2P: Initiate GO Negotiation based on NFC "
"connection handover");
return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
- 0, -1, 0, 1, 1);
+ forced_freq, -1, 0, 1, 1);
}
static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s,
- struct p2p_nfc_params *params)
+ struct p2p_nfc_params *params,
+ int forced_freq)
{
int res;
"connection handover");
res = wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
- 0, -1, 0, 1, 1);
+ forced_freq, -1, 0, 1, 1);
if (res)
return res;
static int wpas_p2p_nfc_connection_handover(struct wpa_supplicant *wpa_s,
const struct wpabuf *data,
- int sel, int tag)
+ int sel, int tag, int forced_freq)
{
const u8 *pos, *end;
u16 len, id;
if (res)
return res;
+ if (params.next_step == NO_ACTION)
+ return 0;
+
+ if (params.next_step == BOTH_GO) {
+ wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_BOTH_GO "peer=" MACSTR,
+ MAC2STR(params.peer->p2p_device_addr));
+ return 0;
+ }
+
+ if (params.next_step == PEER_CLIENT) {
+ if (!is_zero_ether_addr(params.go_dev_addr)) {
+ wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_PEER_CLIENT
+ "peer=" MACSTR " freq=%d go_dev_addr=" MACSTR
+ " ssid=\"%s\"",
+ MAC2STR(params.peer->p2p_device_addr),
+ params.go_freq,
+ MAC2STR(params.go_dev_addr),
+ wpa_ssid_txt(params.go_ssid,
+ params.go_ssid_len));
+ } else {
+ wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_PEER_CLIENT
+ "peer=" MACSTR " freq=%d",
+ MAC2STR(params.peer->p2p_device_addr),
+ params.go_freq);
+ }
+ return 0;
+ }
+
+ if (wpas_p2p_cli_freq(wpa_s, NULL, NULL)) {
+ 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;
switch (params.next_step) {
case NO_ACTION:
+ case BOTH_GO:
+ case PEER_CLIENT:
+ /* already covered above */
return 0;
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);
+ return wpas_p2p_nfc_init_go_neg(wpa_s, ¶ms, forced_freq);
case RESP_GO_NEG:
/* TODO: use own OOB Dev Pw */
- return wpas_p2p_nfc_resp_go_neg(wpa_s, ¶ms);
+ return wpas_p2p_nfc_resp_go_neg(wpa_s, ¶ms, forced_freq);
}
return -1;
int wpas_p2p_nfc_tag_process(struct wpa_supplicant *wpa_s,
- const struct wpabuf *data)
+ const struct wpabuf *data, int forced_freq)
{
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
- return wpas_p2p_nfc_connection_handover(wpa_s, data, 1, 1);
+ return wpas_p2p_nfc_connection_handover(wpa_s, data, 1, 1, forced_freq);
}
int wpas_p2p_nfc_report_handover(struct wpa_supplicant *wpa_s, int init,
const struct wpabuf *req,
- const struct wpabuf *sel)
+ const struct wpabuf *sel, int forced_freq)
{
struct wpabuf *tmp;
int ret;
wpabuf_head(req), wpabuf_len(req));
wpa_hexdump_ascii(MSG_DEBUG, "NFC: Sel",
wpabuf_head(sel), wpabuf_len(sel));
+ if (forced_freq)
+ wpa_printf(MSG_DEBUG, "NFC: Forced freq %d", forced_freq);
tmp = ndef_parse_p2p(init ? sel : req);
if (tmp == NULL) {
wpa_printf(MSG_DEBUG, "P2P: Could not parse NDEF");
return -1;
}
- ret = wpas_p2p_nfc_connection_handover(wpa_s, tmp, init, 0);
+ ret = wpas_p2p_nfc_connection_handover(wpa_s, tmp, init, 0,
+ forced_freq);
wpabuf_free(tmp);
return ret;
{
const u8 *if_addr;
int go_intent = wpa_s->conf->p2p_go_intent;
+ struct wpa_supplicant *iface;
if (wpa_s->global->p2p == NULL)
return -1;
if (!enabled) {
+ wpa_printf(MSG_DEBUG, "P2P: Disable use of own NFC Tag");
+ for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
+ {
+ if (!iface->ap_iface)
+ continue;
+ hostapd_wps_nfc_token_disable(iface->ap_iface->bss[0]);
+ }
p2p_set_authorized_oob_dev_pw_id(wpa_s->global->p2p, 0,
0, NULL);
if (wpa_s->p2p_nfc_tag_enabled)
return -1;
}
+ wpa_printf(MSG_DEBUG, "P2P: Enable use of own NFC Tag");
+
wpa_s->p2p_oob_dev_pw_id = wpa_s->conf->wps_nfc_dev_pw_id;
wpabuf_free(wpa_s->p2p_oob_dev_pw);
wpa_s->p2p_oob_dev_pw = wpabuf_dup(wpa_s->conf->wps_nfc_dev_pw);
wpa_s->p2p_nfc_tag_enabled = enabled;
+ for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
+ struct hostapd_data *hapd;
+ if (iface->ap_iface == NULL)
+ continue;
+ hapd = iface->ap_iface->bss[0];
+ wpabuf_free(hapd->conf->wps_nfc_dh_pubkey);
+ hapd->conf->wps_nfc_dh_pubkey =
+ wpabuf_dup(wpa_s->conf->wps_nfc_dh_pubkey);
+ wpabuf_free(hapd->conf->wps_nfc_dh_privkey);
+ hapd->conf->wps_nfc_dh_privkey =
+ wpabuf_dup(wpa_s->conf->wps_nfc_dh_privkey);
+ wpabuf_free(hapd->conf->wps_nfc_dev_pw);
+ hapd->conf->wps_nfc_dev_pw =
+ wpabuf_dup(wpa_s->conf->wps_nfc_dev_pw);
+ hapd->conf->wps_nfc_dev_pw_id = wpa_s->conf->wps_nfc_dev_pw_id;
+
+ if (hostapd_wps_nfc_token_enable(iface->ap_iface->bss[0]) < 0) {
+ wpa_dbg(iface, MSG_DEBUG,
+ "P2P: Failed to enable NFC Tag for GO");
+ }
+ }
p2p_set_authorized_oob_dev_pw_id(
wpa_s->global->p2p, wpa_s->conf->wps_nfc_dev_pw_id, go_intent,
if_addr);