Accumulative patch from commit f5f37d3a4fc2df2a24676b4f95afca15ed793cba
Author: Jouni Malinen <j@w1.fi>
Date: Sun Nov 25 22:05:32 2012 +0200
Fix REAUTHENTICATE command after PMKSA caching
The current PMKSA cache entry needs to be clear to allow EAPOL
reauthentication to be started in case this association used PMKSA
caching.
- Remove old WPS_OOB NCF
- WPS: Add preliminary NFC connection handover support for Enrollee
- WPS: Reenable the networks disabled during wpa_wpas_reassoc
- P2P: Avoid multi-channel scans when they are not needed
- P2P: Allow discoverable interval for p2p_find to be configured
- P2P: Allow all channels with multi-channel concurrency
- Bonjour changes
- Remove disassociate
- HS 2.0 changes
- Add preliminary support for using SQLite for eap_user database
- Add SAE support
- Add disallow_aps parameter to disallow BSSIDs/SSIDs
Change-Id: I85358a05b39d46b8db49acdad667e771c580b05c
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index a3eaa8c..b122f7c 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -256,7 +256,7 @@
}
-static void p2p_listen_in_find(struct p2p_data *p2p)
+static void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc)
{
unsigned int r, tu;
int freq;
@@ -277,6 +277,19 @@
os_get_random((u8 *) &r, sizeof(r));
tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
p2p->min_disc_int) * 100;
+ if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu)
+ tu = p2p->max_disc_tu;
+ if (!dev_disc && tu < 100)
+ tu = 100; /* Need to wait in non-device discovery use cases */
+ if (p2p->cfg->max_listen && 1024 * tu / 1000 > p2p->cfg->max_listen)
+ tu = p2p->cfg->max_listen * 1000 / 1024;
+
+ if (tu == 0) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip listen state "
+ "since duration was 0 TU");
+ p2p_set_timeout(p2p, 0, 0);
+ return;
+ }
p2p->pending_listen_freq = freq;
p2p->pending_listen_sec = 0;
@@ -1153,15 +1166,17 @@
}
-static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq)
+static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq,
+ unsigned int pref_freq)
{
- if (force_freq) {
+ if (force_freq || pref_freq) {
u8 op_reg_class, op_channel;
- if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
+ unsigned int freq = force_freq ? force_freq : pref_freq;
+ if (p2p_freq_to_channel(p2p->cfg->country, freq,
&op_reg_class, &op_channel) < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Unsupported frequency %u MHz",
- force_freq);
+ freq);
return -1;
}
if (!p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
@@ -1169,37 +1184,21 @@
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Frequency %u MHz (oper_class %u "
"channel %u) not allowed for P2P",
- force_freq, op_reg_class, op_channel);
+ freq, op_reg_class, op_channel);
return -1;
}
p2p->op_reg_class = op_reg_class;
p2p->op_channel = op_channel;
-#ifndef ANDROID_P2P
- p2p->channels.reg_classes = 1;
- p2p->channels.reg_class[0].channels = 1;
- p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
- p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
-#else
- if(p2p->cfg->p2p_concurrency == P2P_MULTI_CHANNEL_CONCURRENT) {
- /* We we are requesting for a preferred channel. But since
- * are multichannel concurrent, we have to poplulate the
- * p2p_channels with list of channels that we support.
- */
-#ifdef ANDROID_P2P
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "Full channel list");
-#endif
- os_memcpy(&p2p->channels, &p2p->cfg->channels,
- sizeof(struct p2p_channels));
- } else {
-#ifdef ANDROID_P2P
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "Single channel list %d", p2p->op_channel);
-#endif
+ if (force_freq) {
p2p->channels.reg_classes = 1;
p2p->channels.reg_class[0].channels = 1;
- p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
+ p2p->channels.reg_class[0].reg_class =
+ p2p->op_reg_class;
p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
+ } else {
+ os_memcpy(&p2p->channels, &p2p->cfg->channels,
+ sizeof(struct p2p_channels));
}
-#endif
} else {
u8 op_reg_class, op_channel;
@@ -1279,18 +1278,18 @@
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
const u8 *force_ssid, size_t force_ssid_len,
- int pd_before_go_neg)
+ int pd_before_go_neg, unsigned int pref_freq)
{
struct p2p_device *dev;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Request to start group negotiation - peer=" MACSTR
" GO Intent=%d Intended Interface Address=" MACSTR
- " wps_method=%d persistent_group=%d pd_before_go_neg=%d force_freq %d",
+ " wps_method=%d persistent_group=%d pd_before_go_neg=%d",
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
- wps_method, persistent_group, pd_before_go_neg, force_freq);
+ wps_method, persistent_group, pd_before_go_neg);
- if (p2p_prepare_channel(p2p, force_freq) < 0)
+ if (p2p_prepare_channel(p2p, force_freq, pref_freq) < 0)
return -1;
dev = p2p_get_device(p2p, peer_addr);
@@ -1390,7 +1389,8 @@
enum p2p_wps_method wps_method,
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
- const u8 *force_ssid, size_t force_ssid_len)
+ const u8 *force_ssid, size_t force_ssid_len,
+ unsigned int pref_freq)
{
struct p2p_device *dev;
@@ -1401,7 +1401,7 @@
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
wps_method, persistent_group);
- if (p2p_prepare_channel(p2p, force_freq) < 0)
+ if (p2p_prepare_channel(p2p, force_freq, pref_freq) < 0)
return -1;
dev = p2p_get_device(p2p, peer_addr);
@@ -2416,6 +2416,7 @@
p2p->min_disc_int = 1;
#endif
p2p->max_disc_int = 3;
+ p2p->max_disc_tu = -1;
os_get_random(&p2p->next_tie_breaker, 1);
p2p->next_tie_breaker &= 0x01;
@@ -2712,7 +2713,7 @@
}
}
- p2p_listen_in_find(p2p);
+ p2p_listen_in_find(p2p, 1);
}
@@ -2758,8 +2759,7 @@
/*
* Retry the prov disc req attempt only for the peer that the user had
- * requested for and provided a join has not been initiated on it
- * in the meantime.
+ * requested.
*/
dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
@@ -2768,15 +2768,14 @@
continue;
if (!dev->req_config_methods)
continue;
- if (dev->flags & P2P_DEV_PD_FOR_JOIN)
- continue;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
"pending Provision Discovery Request to "
MACSTR " (config methods 0x%x)",
MAC2STR(dev->info.p2p_device_addr),
dev->req_config_methods);
- p2p_send_prov_disc_req(p2p, dev, 0, 0);
+ p2p_send_prov_disc_req(p2p, dev,
+ dev->flags & P2P_DEV_PD_FOR_JOIN, 0);
return;
}
}
@@ -3198,7 +3197,7 @@
return;
}
p2p_set_state(p2p, P2P_CONNECT_LISTEN);
- p2p_listen_in_find(p2p);
+ p2p_listen_in_find(p2p, 0);
}
@@ -3262,7 +3261,7 @@
"P2P: Go to Listen state while waiting for the peer to become "
"ready for GO Negotiation");
p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
- p2p_listen_in_find(p2p);
+ p2p_listen_in_find(p2p, 0);
}
@@ -3307,9 +3306,23 @@
p2p->pd_retries--;
p2p_retry_pd(p2p);
} else {
+ struct p2p_device *dev;
+ int for_join = 0;
+
+ dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
+ if (os_memcmp(p2p->pending_pd_devaddr,
+ dev->info.p2p_device_addr, ETH_ALEN) != 0)
+ continue;
+ if (dev->req_config_methods &&
+ (dev->flags & P2P_DEV_PD_FOR_JOIN))
+ for_join = 1;
+ }
+
if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
p2p->pending_pd_devaddr,
+ for_join ?
+ P2P_PROV_DISC_TIMEOUT_JOIN :
P2P_PROV_DISC_TIMEOUT);
p2p_reset_pending_pd(p2p);
}
@@ -3330,7 +3343,7 @@
p2p_set_timeout(p2p, 0, 100000);
return;
}
- p2p_listen_in_find(p2p);
+ p2p_listen_in_find(p2p, 0);
}
@@ -4384,3 +4397,20 @@
}
#endif /* CONFIG_WIFI_DISPLAY */
+
+
+int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
+ int max_disc_tu)
+{
+ if (min_disc_int > max_disc_int || min_disc_int < 0 || max_disc_int < 0)
+ return -1;
+
+ p2p->min_disc_int = min_disc_int;
+ p2p->max_disc_int = max_disc_int;
+ p2p->max_disc_tu = max_disc_tu;
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set discoverable interval: "
+ "min=%d max=%d max_tu=%d", min_disc_int, max_disc_int,
+ max_disc_tu);
+
+ return 0;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index b80f898..045e6f7 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -92,6 +92,16 @@
size_t ssid_len;
/**
+ * psk - WPA pre-shared key (256 bits) (GO only)
+ */
+ u8 psk[32];
+
+ /**
+ * psk_set - Whether PSK field is configured (GO only)
+ */
+ int psk_set;
+
+ /**
* passphrase - WPA2-Personal passphrase for the group (GO only)
*/
char passphrase[64];
@@ -227,6 +237,7 @@
P2P_PROV_DISC_SUCCESS,
P2P_PROV_DISC_TIMEOUT,
P2P_PROV_DISC_REJECTED,
+ P2P_PROV_DISC_TIMEOUT_JOIN,
};
struct p2p_channel {
@@ -359,6 +370,11 @@
*/
size_t ssid_postfix_len;
+ /**
+ * max_listen - Maximum listen duration in ms
+ */
+ unsigned int max_listen;
+
#ifdef ANDROID_P2P
enum p2p_concurrency_type {
P2P_NON_CONCURRENT,
@@ -902,6 +918,8 @@
* @pd_before_go_neg: Whether to send Provision Discovery prior to GO
* Negotiation as an interoperability workaround when initiating group
* formation
+ * @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
+ * force_freq == 0)
* Returns: 0 on success, -1 on failure
*/
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
@@ -909,7 +927,7 @@
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
const u8 *force_ssid, size_t force_ssid_len,
- int pd_before_go_neg);
+ int pd_before_go_neg, unsigned int pref_freq);
/**
* p2p_authorize - Authorize P2P group formation (GO negotiation)
@@ -925,6 +943,8 @@
* @force_ssid: Forced SSID for the group if we become GO or %NULL to generate
* a new SSID
* @force_ssid_len: Length of $force_ssid buffer
+ * @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
+ * force_freq == 0)
* Returns: 0 on success, -1 on failure
*
* This is like p2p_connect(), but the actual group negotiation is not
@@ -934,7 +954,8 @@
enum p2p_wps_method wps_method,
int go_intent, const u8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
- const u8 *force_ssid, size_t force_ssid_len);
+ const u8 *force_ssid, size_t force_ssid_len,
+ unsigned int pref_freq);
/**
* p2p_reject - Reject peer device (explicitly block connection attempts)
@@ -951,6 +972,7 @@
* @config_methods: WPS Config Methods value (only one bit set)
* @join: Whether this is used by a client joining an active group
* @force_freq: Forced TX frequency for the frame (mainly for the join case)
+ * @user_initiated_pd: Flag to indicate if initiated by user or not
* Returns: 0 on success, -1 on failure
*
* This function can be used to request a discovered P2P peer to display a PIN
@@ -962,7 +984,8 @@
* indicated with the p2p_config::prov_disc_resp() callback.
*/
int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
- u16 config_methods, int join, int force_freq);
+ u16 config_methods, int join, int force_freq,
+ int user_initiated_pd);
/**
* p2p_sd_request - Schedule a service discovery query
@@ -1767,4 +1790,25 @@
const struct wpabuf *elem);
struct wpabuf * wifi_display_encaps(struct wpabuf *subelems);
+/**
+ * p2p_set_disc_int - Set min/max discoverable interval for p2p_find
+ * @p2p: P2P module context from p2p_init()
+ * @min_disc_int: minDiscoverableInterval (in units of 100 TU); default 1
+ * @max_disc_int: maxDiscoverableInterval (in units of 100 TU); default 3
+ * @max_disc_tu: Maximum number of TUs (1.024 ms) for discoverable interval; or
+ * -1 not to limit
+ * Returns: 0 on success, or -1 on failure
+ *
+ * This function can be used to configure minDiscoverableInterval and
+ * maxDiscoverableInterval parameters for the Listen state during device
+ * discovery (p2p_find). A random number of 100 TU units is picked for each
+ * Listen state iteration from [min_disc_int,max_disc_int] range.
+ *
+ * max_disc_tu can be used to futher limit the discoverable duration. However,
+ * it should be noted that use of this parameter is not recommended since it
+ * would not be compliant with the P2P specification.
+ */
+int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
+ int max_disc_tu);
+
#endif /* P2P_H */
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index be069a5..5838d35 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -136,6 +136,7 @@
len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2);
}
+
void p2p_buf_add_status(struct wpabuf *buf, u8 status)
{
/* Status */
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index b21d97c..fe4b560 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -211,7 +211,7 @@
else
return -1;
return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr,
- config_method, 0, 0);
+ config_method, 0, 0, 1);
}
freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
@@ -302,7 +302,6 @@
p2p->op_channel);
}
p2p_buf_add_intended_addr(buf, p2p->intended_addr);
-
if (status || peer == NULL) {
p2p_buf_add_channel_list(buf, p2p->cfg->country,
&p2p->channels);
@@ -315,7 +314,6 @@
&res);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &res);
}
-
p2p_buf_add_device_info(buf, p2p, peer);
if (peer && peer->go_state == LOCAL_GO) {
p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid,
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 673c4c1..d2868fb 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -226,6 +226,11 @@
int max_disc_int;
/**
+ * max_disc_tu - Maximum number of TUs for discoverable interval
+ */
+ int max_disc_tu;
+
+ /**
* devices - List of known P2P Device peers
*/
struct dl_list devices;
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index 42447e5..e40f2b7 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -19,7 +19,7 @@
* Number of retries to attempt for provision discovery requests
* in case the peer is not listening.
*/
-#define MAX_PROV_DISC_REQ_RETRIES 10
+#define MAX_PROV_DISC_REQ_RETRIES 120
static void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
@@ -408,7 +408,8 @@
int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
- u16 config_methods, int join, int force_freq)
+ u16 config_methods, int join, int force_freq,
+ int user_initiated_pd)
{
struct p2p_device *dev;
@@ -446,11 +447,7 @@
return 0;
}
- /*
- * We use the join param as a cue to differentiate between user
- * initiated PD request and one issued during finds (internal).
- */
- p2p->user_initiated_pd = !join;
+ p2p->user_initiated_pd = user_initiated_pd;
if (p2p->user_initiated_pd)
p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;