xref: /freebsd/contrib/wpa/wpa_supplicant/robust_av.c (revision b51f459a2098622c31ed54f5c1bf0e03efce403b)
1 /*
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 
18 void 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 
48 int wpas_send_mscs_req(struct wpa_supplicant *wpa_s)
49 {
50 	struct wpabuf *buf;
51 	size_t buf_len;
52 	int ret;
53 
54 	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
55 		return 0;
56 
57 	if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS)) {
58 		wpa_dbg(wpa_s, MSG_INFO,
59 			"AP does not support MSCS - could not send MSCS Req");
60 		return -1;
61 	}
62 
63 	if (!wpa_s->mscs_setup_done &&
64 	    wpa_s->robust_av.request_type != SCS_REQ_ADD) {
65 		wpa_msg(wpa_s, MSG_INFO,
66 			"MSCS: Failed to send MSCS Request: request type invalid");
67 		return -1;
68 	}
69 
70 	buf_len = 3 +	/* Action frame header */
71 		  3 +	/* MSCS descriptor IE header */
72 		  1 +	/* Request type */
73 		  2 +	/* User priority control */
74 		  4 +	/* Stream timeout */
75 		  3 +	/* TCLAS Mask IE header */
76 		  wpa_s->robust_av.frame_classifier_len;
77 
78 	buf = wpabuf_alloc(buf_len);
79 	if (!buf) {
80 		wpa_printf(MSG_ERROR, "Failed to allocate MSCS req");
81 		return -1;
82 	}
83 
84 	wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING);
85 	wpabuf_put_u8(buf, ROBUST_AV_MSCS_REQ);
86 	wpa_s->robust_av.dialog_token++;
87 	wpabuf_put_u8(buf, wpa_s->robust_av.dialog_token);
88 
89 	/* MSCS descriptor element */
90 	wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf);
91 
92 	wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", buf);
93 	ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
94 				  wpa_s->own_addr, wpa_s->bssid,
95 				  wpabuf_head(buf), wpabuf_len(buf), 0);
96 	if (ret < 0)
97 		wpa_dbg(wpa_s, MSG_INFO, "MSCS: Failed to send MSCS Request");
98 
99 	wpabuf_free(buf);
100 	return ret;
101 }
102 
103 
104 void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
105 				       const u8 *src, const u8 *buf, size_t len)
106 {
107 	u8 dialog_token;
108 	u16 status_code;
109 
110 	if (len < 3)
111 		return;
112 
113 	dialog_token = *buf++;
114 	if (dialog_token != wpa_s->robust_av.dialog_token) {
115 		wpa_printf(MSG_INFO,
116 			   "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u",
117 			   dialog_token, wpa_s->robust_av.dialog_token);
118 		return;
119 	}
120 
121 	status_code = WPA_GET_LE16(buf);
122 	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
123 		" status_code=%u", MAC2STR(src), status_code);
124 	wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
125 }
126 
127 
128 void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
129 				 const u8 *ies, size_t ies_len)
130 {
131 	const u8 *mscs_desc_ie, *mscs_status;
132 	u16 status;
133 
134 	/* Process optional MSCS Status subelement when MSCS IE is in
135 	 * (Re)Association Response frame */
136 	if (!ies || ies_len == 0 || !wpa_s->robust_av.valid_config)
137 		return;
138 
139 	mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR);
140 	if (!mscs_desc_ie || mscs_desc_ie[1] <= 8)
141 		return;
142 
143 	/* Subelements start after (ie_id(1) + ie_len(1) + ext_id(1) +
144 	 * request type(1) + upc(2) + stream timeout(4) =) 10.
145 	 */
146 	mscs_status = get_ie(&mscs_desc_ie[10], mscs_desc_ie[1] - 8,
147 			     MCSC_SUBELEM_STATUS);
148 	if (!mscs_status || mscs_status[1] < 2)
149 		return;
150 
151 	status = WPA_GET_LE16(mscs_status + 2);
152 	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
153 		" status_code=%u", MAC2STR(bssid), status);
154 	wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
155 }
156