MSCS: Add support to send MSCS Request frames

Add support to send MSCS add/change/remove types of Action frames
to the connected AP.

Signed-off-by: Vinita S. Maloo <vmaloo@codeaurora.org>
This commit is contained in:
Vinita S. Maloo 2020-08-04 20:12:24 +05:30 committed by Jouni Malinen
parent 1733e356e4
commit a118047245
7 changed files with 215 additions and 1 deletions

View File

@ -478,6 +478,8 @@
#define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
#define WLAN_EID_EXT_EDMG_CAPABILITIES 61 #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
#define WLAN_EID_EXT_EDMG_OPERATION 62 #define WLAN_EID_EXT_EDMG_OPERATION 62
#define WLAN_EID_EXT_MSCS_DESCRIPTOR 88
#define WLAN_EID_EXT_TCLAS_MASK 89
#define WLAN_EID_EXT_REJECTED_GROUPS 92 #define WLAN_EID_EXT_REJECTED_GROUPS 92
#define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93 #define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93
@ -562,6 +564,7 @@
#define WLAN_EXT_CAPAB_SAE_PW_ID 81 #define WLAN_EXT_CAPAB_SAE_PW_ID 81
#define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82 #define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82
#define WLAN_EXT_CAPAB_BEACON_PROTECTION 84 #define WLAN_EXT_CAPAB_BEACON_PROTECTION 84
#define WLAN_EXT_CAPAB_MSCS 85
#define WLAN_EXT_CAPAB_SAE_PK_EXCLUSIVELY 88 #define WLAN_EXT_CAPAB_SAE_PK_EXCLUSIVELY 88
/* Extended RSN Capabilities */ /* Extended RSN Capabilities */
@ -2340,4 +2343,20 @@ enum edmg_bw_config {
/* DPP Public Action frame identifiers - OUI_WFA */ /* DPP Public Action frame identifiers - OUI_WFA */
#define DPP_OUI_TYPE 0x1A #define DPP_OUI_TYPE 0x1A
/* Robust AV streaming Action field values */
enum robust_av_streaming_action {
ROBUST_AV_SCS_REQ = 0,
ROBUST_AV_SCS_RESP = 1,
ROBUST_AV_GROUP_MEMBERSHIP_REQ = 2,
ROBUST_AV_GROUP_MEMBERSHIP_RESP = 3,
ROBUST_AV_MSCS_REQ = 4,
ROBUST_AV_MSCS_RESP = 5,
};
enum scs_request_type {
SCS_REQ_ADD = 0,
SCS_REQ_REMOVE = 1,
SCS_REQ_CHANGE = 2,
};
#endif /* IEEE802_11_DEFS_H */ #endif /* IEEE802_11_DEFS_H */

View File

@ -98,6 +98,7 @@ OBJS += src/utils/crc32.c
OBJS += wmm_ac.c OBJS += wmm_ac.c
OBJS += op_classes.c OBJS += op_classes.c
OBJS += rrm.c OBJS += rrm.c
OBJS += robust_av.c
OBJS_p = wpa_passphrase.c OBJS_p = wpa_passphrase.c
OBJS_p += src/utils/common.c OBJS_p += src/utils/common.c
OBJS_p += src/utils/wpa_debug.c OBJS_p += src/utils/wpa_debug.c

View File

@ -107,6 +107,7 @@ OBJS += ../src/utils/ip_addr.o
OBJS += ../src/utils/crc32.o OBJS += ../src/utils/crc32.o
OBJS += op_classes.o OBJS += op_classes.o
OBJS += rrm.o OBJS += rrm.o
OBJS += robust_av.o
OBJS_p = wpa_passphrase.o OBJS_p = wpa_passphrase.o
OBJS_p += ../src/utils/common.o OBJS_p += ../src/utils/common.o
OBJS_p += ../src/utils/wpa_debug.o OBJS_p += ../src/utils/wpa_debug.o

View File

@ -8483,6 +8483,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->next_scan_bssid_wildcard_ssid = 0; wpa_s->next_scan_bssid_wildcard_ssid = 0;
os_free(wpa_s->select_network_scan_freqs); os_free(wpa_s->select_network_scan_freqs);
wpa_s->select_network_scan_freqs = NULL; wpa_s->select_network_scan_freqs = NULL;
os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
wpa_bss_flush(wpa_s); wpa_bss_flush(wpa_s);
if (!dl_list_empty(&wpa_s->bss)) { if (!dl_list_empty(&wpa_s->bss)) {
@ -8508,6 +8509,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_supplicant_update_channel_list(wpa_s, NULL); wpa_supplicant_update_channel_list(wpa_s, NULL);
free_bss_tmp_disallowed(wpa_s); free_bss_tmp_disallowed(wpa_s);
os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
} }
@ -10342,6 +10345,76 @@ static int wpas_ctrl_cmd_debug_level(const char *cmd)
} }
static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
const char *cmd)
{
size_t frame_classifier_len;
const char *pos, *end;
struct robust_av_data *robust_av = &wpa_s->robust_av;
int val;
/*
* format:
* <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>]
* [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>]
*/
os_memset(robust_av, 0, sizeof(struct robust_av_data));
if (os_strncmp(cmd, "add ", 4) == 0) {
robust_av->request_type = SCS_REQ_ADD;
} else if (os_strcmp(cmd, "remove") == 0) {
robust_av->request_type = SCS_REQ_REMOVE;
robust_av->valid_config = false;
return wpas_send_mscs_req(wpa_s);
} else if (os_strncmp(cmd, "change ", 7) == 0) {
robust_av->request_type = SCS_REQ_CHANGE;
} else {
return -1;
}
pos = os_strstr(cmd, "up_bitmap=");
if (!pos)
return -1;
val = hex2byte(pos + 10);
if (val < 0)
return -1;
robust_av->up_bitmap = val;
pos = os_strstr(cmd, "up_limit=");
if (!pos)
return -1;
robust_av->up_limit = atoi(pos + 9);
pos = os_strstr(cmd, "stream_timeout=");
if (!pos)
return -1;
robust_av->stream_timeout = atoi(pos + 15);
if (robust_av->stream_timeout == 0)
return -1;
pos = os_strstr(cmd, "frame_classifier=");
if (!pos)
return -1;
pos += 17;
end = os_strchr(pos, ' ');
if (!end)
end = pos + os_strlen(pos);
frame_classifier_len = (end - pos) / 2;
if (frame_classifier_len > sizeof(robust_av->frame_classifier) ||
hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len))
return -1;
robust_av->frame_classifier_len = frame_classifier_len;
robust_av->valid_config = true;
return wpas_send_mscs_req(wpa_s);
}
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
char *buf, size_t *resp_len) char *buf, size_t *resp_len)
{ {
@ -11233,6 +11306,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len = -1; reply_len = -1;
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */ #endif /* CONFIG_DPP */
} else if (os_strncmp(buf, "MSCS ", 5) == 0) {
if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
reply_len = -1;
} else { } else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16); os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16; reply_len = 16;

View File

@ -0,0 +1,98 @@
/*
* wpa_supplicant - Robust AV procedures
* Copyright (c) 2020, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "common/wpa_ctrl.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "bss.h"
void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av,
struct wpabuf *buf)
{
u8 *len, *len1;
/* MSCS descriptor element */
wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
len = wpabuf_put(buf, 1);
wpabuf_put_u8(buf, WLAN_EID_EXT_MSCS_DESCRIPTOR);
wpabuf_put_u8(buf, robust_av->request_type);
wpabuf_put_u8(buf, robust_av->up_bitmap);
wpabuf_put_u8(buf, robust_av->up_limit);
wpabuf_put_le32(buf, robust_av->stream_timeout);
if (robust_av->request_type != SCS_REQ_REMOVE) {
/* TCLAS mask element */
wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
len1 = wpabuf_put(buf, 1);
wpabuf_put_u8(buf, WLAN_EID_EXT_TCLAS_MASK);
/* Frame classifier */
wpabuf_put_data(buf, robust_av->frame_classifier,
robust_av->frame_classifier_len);
*len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1;
}
*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
}
int wpas_send_mscs_req(struct wpa_supplicant *wpa_s)
{
struct wpabuf *buf;
const u8 *ext_capab = NULL;
size_t buf_len;
int ret;
if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
return 0;
if (wpa_s->current_bss)
ext_capab = wpa_bss_get_ie(wpa_s->current_bss,
WLAN_EID_EXT_CAPAB);
if (!ext_capab || ext_capab[1] < 11 || !(ext_capab[12] & 0x20)) {
wpa_dbg(wpa_s, MSG_INFO,
"AP does not support MSCS - could not send MSCS Req");
return -1;
}
buf_len = 3 + /* Action frame header */
3 + /* MSCS descriptor IE header */
1 + /* Request type */
2 + /* User priority control */
4 + /* Stream timeout */
3 + /* TCLAS Mask IE header */
wpa_s->robust_av.frame_classifier_len;
buf = wpabuf_alloc(buf_len);
if (!buf) {
wpa_printf(MSG_ERROR, "Failed to allocate MSCS req");
return -1;
}
wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING);
wpabuf_put_u8(buf, ROBUST_AV_MSCS_REQ);
wpa_s->robust_av.dialog_token++;
wpabuf_put_u8(buf, wpa_s->robust_av.dialog_token);
/* MSCS descriptor element */
wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf);
wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", wpabuf_head(buf));
ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
wpa_s->own_addr, wpa_s->bssid,
wpabuf_head(buf), wpabuf_len(buf), 0);
if (ret < 0)
wpa_dbg(wpa_s, MSG_INFO, "MSCS: Failed to send MSCS Request");
wpabuf_free(buf);
return ret;
}

View File

@ -1899,6 +1899,9 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
*pos |= 0x01; *pos |= 0x01;
#endif /* CONFIG_FILS */ #endif /* CONFIG_FILS */
break; break;
case 10: /* Bits 80-87 */
*pos |= 0x20; /* Bit 85 - Mirrored SCS */
break;
} }
} }
@ -1906,7 +1909,7 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen) int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
{ {
u8 *pos = buf; u8 *pos = buf;
u8 len = 10, i; u8 len = 11, i;
if (len < wpa_s->extended_capa_len) if (len < wpa_s->extended_capa_len)
len = wpa_s->extended_capa_len; len = wpa_s->extended_capa_len;

View File

@ -491,6 +491,17 @@ struct driver_signal_override {
int scan_level; int scan_level;
}; };
struct robust_av_data {
u8 dialog_token;
enum scs_request_type request_type;
u8 up_bitmap;
u8 up_limit;
u32 stream_timeout;
u8 frame_classifier[48];
size_t frame_classifier_len;
bool valid_config;
};
/** /**
* struct wpa_supplicant - Internal data for wpa_supplicant interface * struct wpa_supplicant - Internal data for wpa_supplicant interface
* *
@ -1315,6 +1326,7 @@ struct wpa_supplicant {
unsigned int multi_ap_ie:1; unsigned int multi_ap_ie:1;
unsigned int multi_ap_backhaul:1; unsigned int multi_ap_backhaul:1;
unsigned int multi_ap_fronthaul:1; unsigned int multi_ap_fronthaul:1;
struct robust_av_data robust_av;
}; };
@ -1623,4 +1635,8 @@ int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);
void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s); void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s);
int wpas_send_mscs_req(struct wpa_supplicant *wpa_s);
void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av,
struct wpabuf *buf);
#endif /* WPA_SUPPLICANT_I_H */ #endif /* WPA_SUPPLICANT_I_H */