]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
MSCS: Add support to send MSCS Request frames
authorVinita S. Maloo <vmaloo@codeaurora.org>
Tue, 4 Aug 2020 14:42:24 +0000 (20:12 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 14 Aug 2020 08:53:35 +0000 (11:53 +0300)
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>
src/common/ieee802_11_defs.h
wpa_supplicant/Android.mk
wpa_supplicant/Makefile
wpa_supplicant/ctrl_iface.c
wpa_supplicant/robust_av.c [new file with mode: 0644]
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 4d3037eee7e1a546f9946990610f4bb1afb46dc7..1e09e1610dac6019a72330a9a9a9c39882c1ee7c 100644 (file)
 #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 */
@@ -2340,4 +2343,20 @@ enum edmg_bw_config {
 /* 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 */
index 0f24d7b710a7b09d00b57b46a1f19ca67161e86e..ed7e358ac9900d2fef5800e7b13e08d5dc49e40e 100644 (file)
@@ -98,6 +98,7 @@ OBJS += src/utils/crc32.c
 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
index 09ac7a49367f707be3a62fbf9fbbe6c8496f1546..a01a32982dfe1a2eb5da17a082896ffda87e0c32 100644 (file)
@@ -107,6 +107,7 @@ OBJS += ../src/utils/ip_addr.o
 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
index 0dcb0398ca0fbfa249cca3e933df83cc93036c43..5048ee83efff036ccb5a9f1fbe991da41c478a2e 100644 (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;
        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)) {
@@ -8508,6 +8509,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
        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));
 }
 
 
@@ -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 *buf, size_t *resp_len)
 {
@@ -11233,6 +11306,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                        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;
diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c
new file mode 100644 (file)
index 0000000..6bb4e3e
--- /dev/null
@@ -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;
+}
index 6eb09f4962f1c35eb0e8e7ced2f1eec3912388c8..4134d089b986007b66d7166b322d23dd99c26545 100644 (file)
@@ -1899,6 +1899,9 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
                        *pos |= 0x01;
 #endif /* CONFIG_FILS */
                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)
 {
        u8 *pos = buf;
-       u8 len = 10, i;
+       u8 len = 11, i;
 
        if (len < wpa_s->extended_capa_len)
                len = wpa_s->extended_capa_len;
index 9f513c6fe6c06ac2f2b31cf2276f87a7df7d85c3..44f5f375a1d3ba11dd9f95293693cbe45ab36be1 100644 (file)
@@ -491,6 +491,17 @@ struct driver_signal_override {
        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
  *
@@ -1315,6 +1326,7 @@ struct wpa_supplicant {
        unsigned int multi_ap_ie:1;
        unsigned int multi_ap_backhaul: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);
 
+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 */