[PATCH 13/19] P2PS: add p2ps_supported_cpt configuration property
Ilan Peer
ilan.peer
Wed Jun 10 01:43:43 PDT 2015
From: Max Stepanov <Max.Stepanov at intel.com>
The p2ps_supported_cpt configuration property allows ASP to
specify supported Coordination Protocol Transports (CPT) and their
priorities. The property value is a list of supported ASP trasport
names ordred by their priority. Currently only two transports are
supported: UDP and MAC. The property can be set with ctrl-iface P2P_SET
command: (e.g. P2P_SET p2ps_supported_cpt UDP MAC). By default only UDP
transport is enabled.
The configuration parameter defines two internal p2p properties used
to verify CPT bitmask field of received provision discovery request's
feature capability as well as to select the best matching CPT option
for a provision discovery response.
The supported CPT bitwise mask value is used to verify a feature_cap=<hex>
parameter of P2P_ASP_PROVISION and P2P_ASP_PROVISION_RESP commands.
An error is returned if the parameter value doesn't match a supported
CPT bitwise mask. If this parameter is not specified, the supplicant
uses a supported CPT bitwise mask as CPT value of feature capability
attribute sent in PD request.
Signed-off-by: Max Stepanov <Max.Stepanov at intel.com>
Reviewed-by: Ilan Peer <ilan.peer at intel.com>
---
src/common/ieee802_11_defs.h | 1 +
src/p2p/p2p.c | 34 ++++++++++++++++++++
src/p2p/p2p.h | 21 +++++++++++++
src/p2p/p2p_pd.c | 56 +++++++++++++++++++++++++++++++--
wpa_supplicant/ctrl_iface.c | 69 ++++++++++++++++++++++++++++++++++++++---
wpa_supplicant/p2p_supplicant.c | 2 ++
6 files changed, 177 insertions(+), 6 deletions(-)
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 1727fa7..734ac5c 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1069,6 +1069,7 @@ enum p2p_attr_id {
/* P2PS Feature Capability bitmap */
#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0)
+#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1)
/* Invitation Flags */
#define P2P_INVITATION_FLAGS_TYPE BIT(0)
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index bfc656b..12a8b96 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -20,6 +20,11 @@
#include "p2p.h"
+static const u8 p2ps_supported_cpt_default[P2PS_FEATURE_CAPAB_CPT_MAX] = {
+ P2PS_FEATURE_CAPAB_UDP_TRANSPORT,
+ 0
+};
+
static void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx);
static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev);
static void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da,
@@ -5384,3 +5389,32 @@ void p2p_go_neg_wait_timeout(void *eloop_ctx, void *timeout_ctx)
"Timeout on waiting peer to become ready for GO Negotiation");
p2p_go_neg_failed(p2p, -1);
}
+
+
+void p2p_set_asp_supported_cpt(struct p2p_data *p2p, const u8 *cpt_priority)
+{
+ int cnt;
+
+ if (!cpt_priority)
+ cpt_priority = p2ps_supported_cpt_default;
+
+ for (p2p->cfg->p2ps_asp_cpt_mask = 0, cnt = 0;
+ cpt_priority[cnt]; cnt++)
+ p2p->cfg->p2ps_asp_cpt_mask |= cpt_priority[cnt];
+
+ os_memcpy(p2p->cfg->p2ps_asp_cpt_priority, cpt_priority, cnt);
+
+ p2p_dbg(p2p, "P2PS set supported ASP CPT mask: 0x%X",
+ p2p->cfg->p2ps_asp_cpt_mask);
+ wpa_hexdump(MSG_DEBUG, "P2PS set supported ASP CPT piorities: ",
+ cpt_priority, cnt);
+}
+
+
+u8 p2p_get_asp_supported_cpt(struct p2p_data *p2p, const u8 **cpt_priority)
+{
+ if (cpt_priority)
+ *cpt_priority = p2p->cfg->p2ps_asp_cpt_priority;
+
+ return p2p->cfg->p2ps_asp_cpt_mask;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 82c8454..acf62cc 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -22,6 +22,7 @@
#define P2PS_HASH_LEN 6
#define P2P_MAX_QUERY_HASH 6
#define P2PS_FEATURE_CAPAB_LEN 2
+#define P2PS_FEATURE_CAPAB_CPT_MAX 2
/**
* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes
@@ -523,6 +524,24 @@ struct p2p_config {
unsigned int passphrase_len;
/**
+ * p2ps_asp_cpt_mask - supported ASP CPT mask
+ *
+ * A bitwise mask of supported ASP Coordination Protocol Transports.
+ * This property is set together and corresponds with
+ * p2ps_asp_cpt_priority.
+ */
+ u8 p2ps_asp_cpt_mask;
+
+ /**
+ * p2ps_asp_cpt_priority - priorities of ASP CPT
+ *
+ * Priorities of supported ASP Coordinatin Protocol Transports.
+ * This property is set together and corresponds with p2ps_asp_cpt.
+ * The last byte of the array has to be 0.
+ */
+ u8 p2ps_asp_cpt_priority[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
+
+ /**
* cb_ctx - Context to use with callback functions
*/
void *cb_ctx;
@@ -2257,5 +2276,7 @@ int p2p_service_add_asp(struct p2p_data *p2p, int auto_accept, u32 adv_id,
int p2p_service_del_asp(struct p2p_data *p2p, u32 adv_id);
void p2p_service_flush_asp(struct p2p_data *p2p);
struct p2ps_advertisement * p2p_get_p2ps_adv_list(struct p2p_data *p2p);
+void p2p_set_asp_supported_cpt(struct p2p_data *p2p, const u8 *cpt_priority);
+u8 p2p_get_asp_supported_cpt(struct p2p_data *p2p, const u8 **cpt_priority);
#endif /* P2P_H */
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index f9e2911..cb8df59 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -401,6 +401,43 @@ static int p2ps_setup_p2ps_prov(struct p2p_data *p2p, u32 adv_id,
}
+static int p2p_match_feat_cap(struct p2p_data *p2p,
+ const u8 *req_cap, u16 req_cap_len,
+ u8 resp_cap[P2PS_FEATURE_CAPAB_LEN])
+{
+ int i;
+
+ /*
+ * P2PS feature capability structure:
+ * u8 - ASP Coordination Protocol Transport Bitmask
+ * u8 - Reserved
+ */
+ if (req_cap_len < P2PS_FEATURE_CAPAB_LEN) {
+ p2p_dbg(p2p,
+ "Invalid length of P2PS feature capability attribute");
+ return -1;
+ }
+
+ if (req_cap[0] & ~(p2p->cfg->p2ps_asp_cpt_mask)) {
+ p2p_dbg(p2p,
+ "Unsupported CPT in P2PS feature capability attribute");
+ return -1;
+ }
+
+ os_memset(resp_cap, 0, P2PS_FEATURE_CAPAB_LEN);
+
+ /* CPT Bitmask: use the best matching CPT option */
+ for (i = 0; p2p->cfg->p2ps_asp_cpt_priority[i]; i++) {
+ if (p2p->cfg->p2ps_asp_cpt_priority[i] & req_cap[0]) {
+ resp_cap[0] = p2p->cfg->p2ps_asp_cpt_priority[i];
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq)
{
@@ -419,6 +456,7 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
u8 group_mac[ETH_ALEN];
int passwd_id = DEV_PW_DEFAULT;
u16 config_methods;
+ u8 feature_cap[P2PS_FEATURE_CAPAB_LEN] = {0};
if (p2p_parse(data, len, &msg))
return;
@@ -552,6 +590,12 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
p2p_dbg(p2p,
"Missing feature capability in Provision Discovery Request");
reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ } else if (p2p_match_feat_cap(p2p, msg.feature_cap,
+ msg.feature_cap_len,
+ feature_cap)) {
+ p2p_dbg(p2p,
+ "Invalid feature capability in Provision Discovery Request");
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
}
if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
@@ -657,6 +701,14 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
"Missing feature capability in Follow-On Provision Discovery Request");
reject =
P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ } else if (p2p_match_feat_cap(
+ p2p, msg.feature_cap,
+ msg.feature_cap_len,
+ feature_cap)) {
+ p2p_dbg(p2p,
+ "Invalid feature capability in Follow-On Provision Discovery Request");
+ reject =
+ P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
} else {
reject = P2P_SC_SUCCESS;
}
@@ -679,8 +731,8 @@ out:
msg.group_id, msg.group_id_len,
msg.persistent_ssid,
msg.persistent_ssid_len,
- msg.feature_cap,
- msg.feature_cap_len);
+ feature_cap,
+ sizeof(feature_cap));
if (resp == NULL) {
p2p_parse_free(&msg);
return;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index ce5a155..be641c7 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -4624,7 +4624,8 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
}
-static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
+static struct p2ps_provision *
+p2p_parse_asp_provision_cmd(struct wpa_supplicant *wpa_s, const char *cmd)
{
struct p2ps_provision *p2ps_prov;
char *pos;
@@ -4632,6 +4633,7 @@ static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
char *info = NULL;
u8 role = P2PS_SETUP_NONE;
long long unsigned val;
+ u8 cpt_mask;
pos = os_strstr(cmd, "info=");
if (pos) {
@@ -4705,14 +4707,24 @@ static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
}
p2ps_prov->role = role;
+ cpt_mask = p2p_get_asp_supported_cpt(wpa_s->global->p2p, NULL);
+
pos = os_strstr(cmd, "feature_cap=");
if (pos) {
/* read a hexadecimal string of all feature capability bytes */
if (hexstr2bin(pos + 12, p2ps_prov->feature_cap,
sizeof(p2ps_prov->feature_cap)) < 0)
goto invalid_args;
+
+ if (~cpt_mask & p2ps_prov->feature_cap[0]) {
+ wpa_printf(MSG_ERROR,
+ "Command CPT %02X of feature_cap conflicts with supported CPT mask %02X",
+ p2ps_prov->feature_cap[0], cpt_mask);
+ goto invalid_args;
+ }
} else {
- p2ps_prov->feature_cap[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
+ /* set CPT field (byte 0) of feature capability */
+ p2ps_prov->feature_cap[0] = cpt_mask;
}
return p2ps_prov;
@@ -4740,7 +4752,7 @@ static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
if (*pos != ' ')
return -1;
- p2ps_prov = p2p_parse_asp_provision_cmd(pos);
+ p2ps_prov = p2p_parse_asp_provision_cmd(wpa_s, pos);
if (!p2ps_prov)
return -1;
@@ -4772,7 +4784,7 @@ static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
if (*pos != ' ')
return -1;
- p2ps_prov = p2p_parse_asp_provision_cmd(pos);
+ p2ps_prov = p2p_parse_asp_provision_cmd(wpa_s, pos);
if (!p2ps_prov)
return -1;
@@ -5690,6 +5702,46 @@ static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
}
+static int p2ps_ctrl_parse_supported_cpt(const char *str, u8 *cpt)
+{
+ char *token, *context = NULL, *buf;
+ int i;
+
+ buf = os_strdup(str);
+ if (!buf)
+ return -1;
+
+ for (i = 0; /* empty */; i++) {
+ token = str_token(buf, " \t", &context);
+ if (!token)
+ break;
+
+ if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) {
+ wpa_printf(MSG_ERROR,
+ "P2PS: CPT name list is too long, expected up to %d names",
+ P2PS_FEATURE_CAPAB_CPT_MAX);
+ os_free(buf);
+ return -1;
+ }
+
+ if (os_strcmp(token, "UDP") == 0) {
+ cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
+ } else if (os_strcmp(token, "MAC") == 0) {
+ cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "P2PS: Unsupported CPT name %s", token);
+ os_free(buf);
+ return -1;
+ }
+ }
+ cpt[i] = 0;
+
+ os_free(buf);
+ return 0;
+}
+
+
static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
{
char *param;
@@ -5890,6 +5942,15 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
return 0;
}
+ if (os_strcmp(cmd, "p2ps_supported_cpt") == 0) {
+ u8 cpt[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
+
+ if (p2ps_ctrl_parse_supported_cpt(param, cpt) == 0) {
+ p2p_set_asp_supported_cpt(wpa_s->global->p2p, cpt);
+ return 0;
+ }
+ }
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
cmd);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 694915a..6c795c4 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -4039,6 +4039,8 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
p2p_set_no_go_freq(global->p2p, &wpa_s->conf->p2p_no_go_freq);
+ p2p_set_asp_supported_cpt(global->p2p, NULL);
+
return 0;
}
--
1.9.1
More information about the Hostap
mailing list