}
+static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
+{
+ union wpa_event_data event;
+
+ if (os_strcmp(band, "AUTO") == 0)
+ wpa_s->setband = WPA_SETBAND_AUTO;
+ else if (os_strcmp(band, "5G") == 0)
+ wpa_s->setband = WPA_SETBAND_5G;
+ else if (os_strcmp(band, "2G") == 0)
+ wpa_s->setband = WPA_SETBAND_2G;
+ else
+ return -1;
+
+ if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
+ os_memset(&event, 0, sizeof(event));
+ event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+ event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+ wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
+ }
+
+ return 0;
+}
+
+
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
ret = wpas_ctrl_set_blob(wpa_s, value);
#endif /* CONFIG_NO_CONFIG_BLOBS */
} else if (os_strcasecmp(cmd, "setband") == 0) {
- if (os_strcmp(value, "AUTO") == 0)
- wpa_s->setband = WPA_SETBAND_AUTO;
- else if (os_strcmp(value, "5G") == 0)
- wpa_s->setband = WPA_SETBAND_5G;
- else if (os_strcmp(value, "2G") == 0)
- wpa_s->setband = WPA_SETBAND_2G;
- else
- ret = -1;
+ ret = wpas_ctrl_set_band(wpa_s, value);
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
}
+static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt)
+{
+ const char *last = NULL;
+ const char *token;
+ long int token_len;
+ unsigned int i;
+
+ /* Expected predefined CPT names delimited by ':' */
+ for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) {
+ 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);
+ cpt[0] = 0;
+ return -1;
+ }
+
+ token_len = last - token;
+
+ if (token_len == 3 &&
+ os_memcmp(token, "UDP", token_len) == 0) {
+ cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
+ } else if (token_len == 3 &&
+ os_memcmp(token, "MAC", token_len) == 0) {
+ cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "P2PS: Unsupported CPT name '%s'", token);
+ cpt[0] = 0;
+ return -1;
+ }
+
+ if (isblank(*last)) {
+ i++;
+ break;
+ }
+ }
+ cpt[i] = 0;
+ return 0;
+}
+
+
static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
{
struct p2ps_provision *p2ps_prov;
char *info = NULL;
u8 role = P2PS_SETUP_NONE;
long long unsigned val;
+ int i;
pos = os_strstr(cmd, "info=");
if (pos) {
if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
goto invalid_args;
+ pos = os_strstr(cmd, "cpt=");
+ if (pos) {
+ if (p2ps_ctrl_parse_cpt_priority(pos + 4,
+ p2ps_prov->cpt_priority))
+ goto invalid_args;
+ } else {
+ p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
+ }
+
+ for (i = 0; p2ps_prov->cpt_priority[i]; i++)
+ p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
+
/* force conncap with tstCap (no sanity checks) */
pos = os_strstr(cmd, "tstCap=");
if (pos) {
char *adv_str;
u32 auto_accept, adv_id, svc_state, config_methods;
char *svc_info = NULL;
+ char *cpt_prio_str;
+ u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
pos = os_strchr(cmd, ' ');
if (pos == NULL)
if (pos != NULL)
*pos++ = '\0';
+ cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL;
+ if (cpt_prio_str) {
+ pos = os_strchr(pos, ' ');
+ if (pos != NULL)
+ *pos++ = '\0';
+
+ if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio))
+ return -1;
+ } else {
+ cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT;
+ cpt_prio[1] = 0;
+ }
+
/* Service and Response Information are optional */
if (pos && pos[0]) {
size_t len;
return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
(u8) svc_state, (u16) config_methods,
- svc_info);
+ svc_info, cpt_prio);
}
if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
wpa_s = wpa_supplicant_get_iface(global, ifname);
if (wpa_s) {
+ if (wpa_s->fst) {
+ wpa_printf(MSG_INFO, "FST: Already attached");
+ return -1;
+ }
fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
wpa_s->fst = fst_attach(ifname, wpa_s->own_addr,
&iface_obj, &cfg);