#define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
#define WLAN_EID_EXT_EDMG_CAPABILITIES 61
#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_ANTI_CLOGGING_TOKEN 93
#define WLAN_EXT_CAPAB_SAE_PW_ID 81
#define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82
#define WLAN_EXT_CAPAB_BEACON_PROTECTION 84
+#define WLAN_EXT_CAPAB_MSCS 85
#define WLAN_EXT_CAPAB_SAE_PK_EXCLUSIVELY 88
/* Extended RSN Capabilities */
/* DPP Public Action frame identifiers - OUI_WFA */
#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 */
OBJS += wmm_ac.c
OBJS += op_classes.c
OBJS += rrm.c
+OBJS += robust_av.c
OBJS_p = wpa_passphrase.c
OBJS_p += src/utils/common.c
OBJS_p += src/utils/wpa_debug.c
OBJS += ../src/utils/crc32.o
OBJS += op_classes.o
OBJS += rrm.o
+OBJS += robust_av.o
OBJS_p = wpa_passphrase.o
OBJS_p += ../src/utils/common.o
OBJS_p += ../src/utils/wpa_debug.o
wpa_s->next_scan_bssid_wildcard_ssid = 0;
os_free(wpa_s->select_network_scan_freqs);
wpa_s->select_network_scan_freqs = NULL;
+ os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
wpa_bss_flush(wpa_s);
if (!dl_list_empty(&wpa_s->bss)) {
wpa_supplicant_update_channel_list(wpa_s, NULL);
free_bss_tmp_disallowed(wpa_s);
+
+ os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
}
}
+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 *buf, size_t *resp_len)
{
reply_len = -1;
#endif /* CONFIG_DPP2 */
#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 {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
--- /dev/null
+/*
+ * 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;
+}
*pos |= 0x01;
#endif /* CONFIG_FILS */
break;
+ case 10: /* Bits 80-87 */
+ *pos |= 0x20; /* Bit 85 - Mirrored SCS */
+ break;
}
}
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
{
u8 *pos = buf;
- u8 len = 10, i;
+ u8 len = 11, i;
if (len < wpa_s->extended_capa_len)
len = wpa_s->extended_capa_len;
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
*
unsigned int multi_ap_ie:1;
unsigned int multi_ap_backhaul:1;
unsigned int multi_ap_fronthaul:1;
+ struct robust_av_data robust_av;
};
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 */