blob: 1280f5d96e7e29a35a95691346d1407a136e3acf [file] [log] [blame]
Hai Shalom899fcc72020-10-19 14:38:18 -07001/*
2 * wpa_supplicant - Robust AV procedures
3 * Copyright (c) 2020, The Linux Foundation
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10#include "utils/common.h"
11#include "common/wpa_ctrl.h"
12#include "common/ieee802_11_common.h"
13#include "wpa_supplicant_i.h"
14#include "driver_i.h"
15#include "bss.h"
16
17
18void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av,
19 struct wpabuf *buf)
20{
21 u8 *len, *len1;
22
23 /* MSCS descriptor element */
24 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
25 len = wpabuf_put(buf, 1);
26 wpabuf_put_u8(buf, WLAN_EID_EXT_MSCS_DESCRIPTOR);
27 wpabuf_put_u8(buf, robust_av->request_type);
28 wpabuf_put_u8(buf, robust_av->up_bitmap);
29 wpabuf_put_u8(buf, robust_av->up_limit);
30 wpabuf_put_le32(buf, robust_av->stream_timeout);
31
32 if (robust_av->request_type != SCS_REQ_REMOVE) {
33 /* TCLAS mask element */
34 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
35 len1 = wpabuf_put(buf, 1);
36 wpabuf_put_u8(buf, WLAN_EID_EXT_TCLAS_MASK);
37
38 /* Frame classifier */
39 wpabuf_put_data(buf, robust_av->frame_classifier,
40 robust_av->frame_classifier_len);
41 *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1;
42 }
43
44 *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
45}
46
47
48int wpas_send_mscs_req(struct wpa_supplicant *wpa_s)
49{
50 struct wpabuf *buf;
51 const u8 *ext_capab = NULL;
52 size_t buf_len;
53 int ret;
54
55 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
56 return 0;
57
58 if (wpa_s->current_bss)
59 ext_capab = wpa_bss_get_ie(wpa_s->current_bss,
60 WLAN_EID_EXT_CAPAB);
61
62 if (!ext_capab || ext_capab[1] < 11 || !(ext_capab[12] & 0x20)) {
63 wpa_dbg(wpa_s, MSG_INFO,
64 "AP does not support MSCS - could not send MSCS Req");
65 return -1;
66 }
67
68 if (!wpa_s->mscs_setup_done &&
69 wpa_s->robust_av.request_type != SCS_REQ_ADD) {
70 wpa_msg(wpa_s, MSG_INFO,
71 "MSCS: Failed to send MSCS Request: request type invalid");
72 return -1;
73 }
74
75 buf_len = 3 + /* Action frame header */
76 3 + /* MSCS descriptor IE header */
77 1 + /* Request type */
78 2 + /* User priority control */
79 4 + /* Stream timeout */
80 3 + /* TCLAS Mask IE header */
81 wpa_s->robust_av.frame_classifier_len;
82
83 buf = wpabuf_alloc(buf_len);
84 if (!buf) {
85 wpa_printf(MSG_ERROR, "Failed to allocate MSCS req");
86 return -1;
87 }
88
89 wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING);
90 wpabuf_put_u8(buf, ROBUST_AV_MSCS_REQ);
91 wpa_s->robust_av.dialog_token++;
92 wpabuf_put_u8(buf, wpa_s->robust_av.dialog_token);
93
94 /* MSCS descriptor element */
95 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf);
96
97 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", buf);
98 ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
99 wpa_s->own_addr, wpa_s->bssid,
100 wpabuf_head(buf), wpabuf_len(buf), 0);
101 if (ret < 0)
102 wpa_dbg(wpa_s, MSG_INFO, "MSCS: Failed to send MSCS Request");
103
104 wpabuf_free(buf);
105 return ret;
106}
107
108
109void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
110 const u8 *src, const u8 *buf, size_t len)
111{
112 u8 dialog_token;
113 u16 status_code;
114
115 if (len < 3)
116 return;
117
118 dialog_token = *buf++;
119 if (dialog_token != wpa_s->robust_av.dialog_token) {
120 wpa_printf(MSG_INFO,
121 "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u",
122 dialog_token, wpa_s->robust_av.dialog_token);
123 return;
124 }
125
126 status_code = *buf;
127 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
128 " status_code=%u", MAC2STR(src), status_code);
129 wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
130}
131
132
133void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
134 const u8 *ies, size_t ies_len)
135{
136 const u8 *mscs_desc_ie, *mscs_status;
137 u16 status;
138
139 /* Process optional MSCS Status subelement when MSCS IE is in
140 * (Re)Association Response frame */
141 if (!ies || ies_len == 0 || !wpa_s->robust_av.valid_config)
142 return;
143
144 mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR);
145 if (!mscs_desc_ie || mscs_desc_ie[1] <= 8)
146 return;
147
148 /* Subelements start after (ie_id(1) + ie_len(1) + ext_id(1) +
149 * request type(1) + upc(2) + stream timeout(4) =) 10.
150 */
151 mscs_status = get_ie(&mscs_desc_ie[10], mscs_desc_ie[1] - 8,
152 MCSC_SUBELEM_STATUS);
153 if (!mscs_status || mscs_status[1] < 2)
154 return;
155
156 status = WPA_GET_LE16(mscs_status + 2);
157 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
158 " status_code=%u", MAC2STR(bssid), status);
159 wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
160}