1 1.1 christos /* 2 1.1 christos * wpa_supplicant - Robust AV procedures 3 1.1 christos * Copyright (c) 2020, The Linux Foundation 4 1.1 christos * 5 1.1 christos * This software may be distributed under the terms of the BSD license. 6 1.1 christos * See README for more details. 7 1.1 christos */ 8 1.1 christos 9 1.1 christos #include "utils/includes.h" 10 1.1 christos #include "utils/common.h" 11 1.1 christos #include "utils/eloop.h" 12 1.1 christos #include "common/wpa_ctrl.h" 13 1.1 christos #include "common/ieee802_11_common.h" 14 1.1 christos #include "wpa_supplicant_i.h" 15 1.1 christos #include "driver_i.h" 16 1.1 christos #include "bss.h" 17 1.1 christos 18 1.1 christos 19 1.1 christos #define SCS_RESP_TIMEOUT 1 20 1.1 christos #define DSCP_REQ_TIMEOUT 5 21 1.1 christos 22 1.1 christos 23 1.1 christos void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, 24 1.1 christos struct wpabuf *buf) 25 1.1 christos { 26 1.1 christos u8 *len, *len1; 27 1.1 christos 28 1.1 christos /* MSCS descriptor element */ 29 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 30 1.1 christos len = wpabuf_put(buf, 1); 31 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXT_MSCS_DESCRIPTOR); 32 1.1 christos wpabuf_put_u8(buf, robust_av->request_type); 33 1.1 christos wpabuf_put_u8(buf, robust_av->up_bitmap); 34 1.1 christos wpabuf_put_u8(buf, robust_av->up_limit); 35 1.1 christos wpabuf_put_le32(buf, robust_av->stream_timeout); 36 1.1 christos 37 1.1 christos if (robust_av->request_type != SCS_REQ_REMOVE) { 38 1.1 christos /* TCLAS mask element */ 39 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 40 1.1 christos len1 = wpabuf_put(buf, 1); 41 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXT_TCLAS_MASK); 42 1.1 christos 43 1.1 christos /* Frame classifier */ 44 1.1 christos wpabuf_put_data(buf, robust_av->frame_classifier, 45 1.1 christos robust_av->frame_classifier_len); 46 1.1 christos *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1; 47 1.1 christos } 48 1.1 christos 49 1.1 christos *len = (u8 *) wpabuf_put(buf, 0) - len - 1; 50 1.1 christos } 51 1.1 christos 52 1.1 christos 53 1.1 christos static int wpas_populate_type4_classifier(struct type4_params *type4_param, 54 1.1 christos struct wpabuf *buf) 55 1.1 christos { 56 1.1 christos /* classifier parameters */ 57 1.1 christos wpabuf_put_u8(buf, type4_param->classifier_mask); 58 1.1 christos if (type4_param->ip_version == IPV4) { 59 1.1 christos wpabuf_put_u8(buf, IPV4); /* IP version */ 60 1.1 christos wpabuf_put_data(buf, &type4_param->ip_params.v4.src_ip.s_addr, 61 1.1 christos 4); 62 1.1 christos wpabuf_put_data(buf, &type4_param->ip_params.v4.dst_ip.s_addr, 63 1.1 christos 4); 64 1.1 christos wpabuf_put_be16(buf, type4_param->ip_params.v4.src_port); 65 1.1 christos wpabuf_put_be16(buf, type4_param->ip_params.v4.dst_port); 66 1.1 christos wpabuf_put_u8(buf, type4_param->ip_params.v4.dscp); 67 1.1 christos wpabuf_put_u8(buf, type4_param->ip_params.v4.protocol); 68 1.1 christos wpabuf_put_u8(buf, 0); /* Reserved octet */ 69 1.1 christos } else { 70 1.1 christos wpabuf_put_u8(buf, IPV6); 71 1.1 christos wpabuf_put_data(buf, &type4_param->ip_params.v6.src_ip.s6_addr, 72 1.1 christos 16); 73 1.1 christos wpabuf_put_data(buf, &type4_param->ip_params.v6.dst_ip.s6_addr, 74 1.1 christos 16); 75 1.1 christos wpabuf_put_be16(buf, type4_param->ip_params.v6.src_port); 76 1.1 christos wpabuf_put_be16(buf, type4_param->ip_params.v6.dst_port); 77 1.1 christos wpabuf_put_u8(buf, type4_param->ip_params.v6.dscp); 78 1.1 christos wpabuf_put_u8(buf, type4_param->ip_params.v6.next_header); 79 1.1 christos wpabuf_put_data(buf, type4_param->ip_params.v6.flow_label, 3); 80 1.1 christos } 81 1.1 christos 82 1.1 christos return 0; 83 1.1 christos } 84 1.1 christos 85 1.1 christos 86 1.1 christos static int wpas_populate_type10_classifier(struct type10_params *type10_param, 87 1.1 christos struct wpabuf *buf) 88 1.1 christos { 89 1.1 christos /* classifier parameters */ 90 1.1 christos wpabuf_put_u8(buf, type10_param->prot_instance); 91 1.1 christos wpabuf_put_u8(buf, type10_param->prot_number); 92 1.1 christos wpabuf_put_data(buf, type10_param->filter_value, 93 1.1 christos type10_param->filter_len); 94 1.1 christos wpabuf_put_data(buf, type10_param->filter_mask, 95 1.1 christos type10_param->filter_len); 96 1.1 christos return 0; 97 1.1 christos } 98 1.1 christos 99 1.1 christos 100 1.1 christos static bool tclas_elem_required(const struct qos_characteristics *qos_elem) 101 1.1 christos { 102 1.1 christos if (!qos_elem || !qos_elem->available) 103 1.1 christos return true; 104 1.1 christos 105 1.1 christos if (qos_elem->direction == SCS_DIRECTION_DOWN) 106 1.1 christos return true; 107 1.1 christos 108 1.1 christos return false; 109 1.1 christos } 110 1.1 christos 111 1.1 christos 112 1.1 christos static int wpas_populate_scs_descriptor_ie(struct scs_desc_elem *desc_elem, 113 1.1 christos struct wpabuf *buf, 114 1.1 christos bool allow_scs_traffic_desc) 115 1.1 christos { 116 1.1 christos u8 *len, *len1; 117 1.1 christos struct tclas_element *tclas_elem; 118 1.1 christos unsigned int i; 119 1.1 christos struct qos_characteristics *qos_elem; 120 1.1 christos u32 control_info = 0; 121 1.1 christos 122 1.1 christos /* SCS Descriptor element */ 123 1.1 christos wpabuf_put_u8(buf, WLAN_EID_SCS_DESCRIPTOR); 124 1.1 christos len = wpabuf_put(buf, 1); 125 1.1 christos wpabuf_put_u8(buf, desc_elem->scs_id); 126 1.1 christos wpabuf_put_u8(buf, desc_elem->request_type); 127 1.1 christos if (desc_elem->request_type == SCS_REQ_REMOVE) 128 1.1 christos goto end; 129 1.1 christos 130 1.1 christos if (!tclas_elem_required(&desc_elem->qos_char_elem)) 131 1.1 christos goto skip_tclas_elem; 132 1.1 christos 133 1.1 christos if (desc_elem->intra_access_priority || desc_elem->scs_up_avail) { 134 1.1 christos wpabuf_put_u8(buf, WLAN_EID_INTRA_ACCESS_CATEGORY_PRIORITY); 135 1.1 christos wpabuf_put_u8(buf, 1); 136 1.1 christos wpabuf_put_u8(buf, desc_elem->intra_access_priority); 137 1.1 christos } 138 1.1 christos 139 1.1 christos tclas_elem = desc_elem->tclas_elems; 140 1.1 christos 141 1.1 christos if (!tclas_elem) 142 1.1 christos return -1; 143 1.1 christos 144 1.1 christos for (i = 0; i < desc_elem->num_tclas_elem; i++, tclas_elem++) { 145 1.1 christos int ret; 146 1.1 christos 147 1.1 christos /* TCLAS element */ 148 1.1 christos wpabuf_put_u8(buf, WLAN_EID_TCLAS); 149 1.1 christos len1 = wpabuf_put(buf, 1); 150 1.1 christos wpabuf_put_u8(buf, 255); /* User Priority: not compared */ 151 1.1 christos /* Frame Classifier */ 152 1.1 christos wpabuf_put_u8(buf, tclas_elem->classifier_type); 153 1.1 christos /* Frame classifier parameters */ 154 1.1 christos switch (tclas_elem->classifier_type) { 155 1.1 christos case 4: 156 1.1 christos ret = wpas_populate_type4_classifier( 157 1.1 christos &tclas_elem->frame_classifier.type4_param, 158 1.1 christos buf); 159 1.1 christos break; 160 1.1 christos case 10: 161 1.1 christos ret = wpas_populate_type10_classifier( 162 1.1 christos &tclas_elem->frame_classifier.type10_param, 163 1.1 christos buf); 164 1.1 christos break; 165 1.1 christos default: 166 1.1 christos return -1; 167 1.1 christos } 168 1.1 christos 169 1.1 christos if (ret == -1) { 170 1.1 christos wpa_printf(MSG_ERROR, 171 1.1 christos "Failed to populate frame classifier"); 172 1.1 christos return -1; 173 1.1 christos } 174 1.1 christos 175 1.1 christos *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1; 176 1.1 christos } 177 1.1 christos 178 1.1 christos if (desc_elem->num_tclas_elem > 1) { 179 1.1 christos /* TCLAS Processing element */ 180 1.1 christos wpabuf_put_u8(buf, WLAN_EID_TCLAS_PROCESSING); 181 1.1 christos wpabuf_put_u8(buf, 1); 182 1.1 christos wpabuf_put_u8(buf, desc_elem->tclas_processing); 183 1.1 christos } 184 1.1 christos 185 1.1 christos skip_tclas_elem: 186 1.1 christos if (allow_scs_traffic_desc && desc_elem->qos_char_elem.available) { 187 1.1 christos qos_elem = &desc_elem->qos_char_elem; 188 1.1 christos /* Element ID, Length, and Element ID Extension */ 189 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 190 1.1 christos len1 = wpabuf_put(buf, 1); 191 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXT_QOS_CHARACTERISTICS); 192 1.1 christos 193 1.1 christos /* Remove invalid mask bits */ 194 1.1 christos 195 1.1 christos /* Medium Time is applicable only for direct link */ 196 1.1 christos if ((qos_elem->mask & SCS_QOS_BIT_MEDIUM_TIME) && 197 1.1 christos qos_elem->direction != SCS_DIRECTION_DIRECT) 198 1.1 christos qos_elem->mask &= ~SCS_QOS_BIT_MEDIUM_TIME; 199 1.1 christos 200 1.1 christos /* Service Start Time LinkID is valid only when Service Start 201 1.1 christos * Time is present. 202 1.1 christos */ 203 1.1 christos if ((qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME_LINKID) && 204 1.1 christos !(qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME)) 205 1.1 christos qos_elem->mask &= 206 1.1 christos ~SCS_QOS_BIT_SERVICE_START_TIME_LINKID; 207 1.1 christos 208 1.1 christos /* IEEE P802.11be/D4.0, 9.4.2.316 QoS Characteristics element, 209 1.1 christos * Figure 9-1001av (Control Info field format) 210 1.1 christos */ 211 1.1 christos control_info = ((u32) qos_elem->direction << 212 1.1 christos EHT_QOS_CONTROL_INFO_DIRECTION_OFFSET); 213 1.1 christos control_info |= ((u32) desc_elem->intra_access_priority << 214 1.1 christos EHT_QOS_CONTROL_INFO_TID_OFFSET); 215 1.1 christos control_info |= ((u32) desc_elem->intra_access_priority << 216 1.1 christos EHT_QOS_CONTROL_INFO_USER_PRIORITY_OFFSET); 217 1.1 christos control_info |= ((u32) qos_elem->mask << 218 1.1 christos EHT_QOS_CONTROL_INFO_PRESENCE_MASK_OFFSET); 219 1.1 christos 220 1.1 christos /* Control Info */ 221 1.1 christos wpabuf_put_le32(buf, control_info); 222 1.1 christos /* Minimum Service Interval */ 223 1.1 christos wpabuf_put_le32(buf, qos_elem->min_si); 224 1.1 christos /* Maximum Service Interval */ 225 1.1 christos wpabuf_put_le32(buf, qos_elem->max_si); 226 1.1 christos /* Minimum Data Rate */ 227 1.1 christos wpabuf_put_le24(buf, qos_elem->min_data_rate); 228 1.1 christos /* Delay Bound */ 229 1.1 christos wpabuf_put_le24(buf, qos_elem->delay_bound); 230 1.1 christos 231 1.1 christos /* Maximum MSDU Size */ 232 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MAX_MSDU_SIZE) 233 1.1 christos wpabuf_put_le16(buf, qos_elem->max_msdu_size); 234 1.1 christos /* Start Service Time */ 235 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME) 236 1.1 christos wpabuf_put_le32(buf, qos_elem->service_start_time); 237 1.1 christos /* Service Start Time LinkID */ 238 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME_LINKID) 239 1.1 christos wpabuf_put_u8(buf, 240 1.1 christos qos_elem->service_start_time_link_id); 241 1.1 christos /* Mean Data Rate */ 242 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MEAN_DATA_RATE) 243 1.1 christos wpabuf_put_le24(buf, qos_elem->mean_data_rate); 244 1.1 christos /* Delayed Bounded Burst Size */ 245 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE) 246 1.1 christos wpabuf_put_le32(buf, qos_elem->burst_size); 247 1.1 christos /* MSDU Lifetime */ 248 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MSDU_LIFETIME) 249 1.1 christos wpabuf_put_le16(buf, qos_elem->msdu_lifetime); 250 1.1 christos /* MSDU Delivery Info */ 251 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MSDU_DELIVERY_INFO) 252 1.1 christos wpabuf_put_u8(buf, qos_elem->msdu_delivery_info); 253 1.1 christos /* Medium Time */ 254 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MEDIUM_TIME) 255 1.1 christos wpabuf_put_le16(buf, qos_elem->medium_time); 256 1.1 christos 257 1.1 christos *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1; 258 1.1 christos } 259 1.1 christos 260 1.1 christos end: 261 1.1 christos *len = (u8 *) wpabuf_put(buf, 0) - len - 1; 262 1.1 christos return 0; 263 1.1 christos } 264 1.1 christos 265 1.1 christos 266 1.1 christos int wpas_send_mscs_req(struct wpa_supplicant *wpa_s) 267 1.1 christos { 268 1.1 christos struct wpabuf *buf; 269 1.1 christos size_t buf_len; 270 1.1 christos int ret; 271 1.1 christos 272 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) 273 1.1 christos return 0; 274 1.1 christos 275 1.1 christos if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS)) { 276 1.1 christos wpa_dbg(wpa_s, MSG_INFO, 277 1.1 christos "AP does not support MSCS - could not send MSCS Req"); 278 1.1 christos return -1; 279 1.1 christos } 280 1.1 christos 281 1.1 christos if (!wpa_s->mscs_setup_done && 282 1.1 christos wpa_s->robust_av.request_type != SCS_REQ_ADD) { 283 1.1 christos wpa_msg(wpa_s, MSG_INFO, 284 1.1 christos "MSCS: Failed to send MSCS Request: request type invalid"); 285 1.1 christos return -1; 286 1.1 christos } 287 1.1 christos 288 1.1 christos buf_len = 3 + /* Action frame header */ 289 1.1 christos 3 + /* MSCS descriptor IE header */ 290 1.1 christos 1 + /* Request type */ 291 1.1 christos 2 + /* User priority control */ 292 1.1 christos 4 + /* Stream timeout */ 293 1.1 christos 3 + /* TCLAS Mask IE header */ 294 1.1 christos wpa_s->robust_av.frame_classifier_len; 295 1.1 christos 296 1.1 christos buf = wpabuf_alloc(buf_len); 297 1.1 christos if (!buf) { 298 1.1 christos wpa_printf(MSG_ERROR, "Failed to allocate MSCS req"); 299 1.1 christos return -1; 300 1.1 christos } 301 1.1 christos 302 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING); 303 1.1 christos wpabuf_put_u8(buf, ROBUST_AV_MSCS_REQ); 304 1.1 christos wpa_s->robust_av.dialog_token++; 305 1.1 christos wpabuf_put_u8(buf, wpa_s->robust_av.dialog_token); 306 1.1 christos 307 1.1 christos /* MSCS descriptor element */ 308 1.1 christos wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf); 309 1.1 christos 310 1.1 christos wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", buf); 311 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 312 1.1 christos wpa_s->own_addr, wpa_s->bssid, 313 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0); 314 1.1 christos if (ret < 0) 315 1.1 christos wpa_dbg(wpa_s, MSG_INFO, "MSCS: Failed to send MSCS Request"); 316 1.1 christos 317 1.1 christos wpabuf_free(buf); 318 1.1 christos return ret; 319 1.1 christos } 320 1.1 christos 321 1.1 christos 322 1.1 christos static size_t tclas_elem_len(const struct tclas_element *elem) 323 1.1 christos { 324 1.1 christos size_t buf_len = 0; 325 1.1 christos 326 1.1 christos buf_len += 2 + /* TCLAS element header */ 327 1.1 christos 1 + /* User Priority */ 328 1.1 christos 1 ; /* Classifier Type */ 329 1.1 christos 330 1.1 christos if (elem->classifier_type == 4) { 331 1.1 christos enum ip_version ip_ver; 332 1.1 christos 333 1.1 christos buf_len += 1 + /* Classifier mask */ 334 1.1 christos 1 + /* IP version */ 335 1.1 christos 1 + /* user priority */ 336 1.1 christos 2 + /* src_port */ 337 1.1 christos 2 + /* dst_port */ 338 1.1 christos 1 ; /* dscp */ 339 1.1 christos ip_ver = elem->frame_classifier.type4_param.ip_version; 340 1.1 christos if (ip_ver == IPV4) { 341 1.1 christos buf_len += 4 + /* src_ip */ 342 1.1 christos 4 + /* dst_ip */ 343 1.1 christos 1 + /* protocol */ 344 1.1 christos 1 ; /* Reserved */ 345 1.1 christos } else if (ip_ver == IPV6) { 346 1.1 christos buf_len += 16 + /* src_ip */ 347 1.1 christos 16 + /* dst_ip */ 348 1.1 christos 1 + /* next_header */ 349 1.1 christos 3 ; /* flow_label */ 350 1.1 christos } else { 351 1.1 christos wpa_printf(MSG_ERROR, "%s: Incorrect IP version %d", 352 1.1 christos __func__, ip_ver); 353 1.1 christos return 0; 354 1.1 christos } 355 1.1 christos } else if (elem->classifier_type == 10) { 356 1.1 christos buf_len += 1 + /* protocol instance */ 357 1.1 christos 1 + /* protocol number */ 358 1.1 christos 2 * elem->frame_classifier.type10_param.filter_len; 359 1.1 christos } else { 360 1.1 christos wpa_printf(MSG_ERROR, "%s: Incorrect classifier type %u", 361 1.1 christos __func__, elem->classifier_type); 362 1.1 christos return 0; 363 1.1 christos } 364 1.1 christos 365 1.1 christos return buf_len; 366 1.1 christos } 367 1.1 christos 368 1.1 christos 369 1.1 christos static size_t qos_char_len(const struct qos_characteristics *qos_elem) 370 1.1 christos { 371 1.1 christos size_t buf_len = 0; 372 1.1 christos 373 1.1 christos buf_len += 1 + /* Element ID */ 374 1.1 christos 1 + /* Length */ 375 1.1 christos 1 + /* Element ID Extension */ 376 1.1 christos 4 + /* Control Info */ 377 1.1 christos 4 + /* Minimum Service Interval */ 378 1.1 christos 4 + /* Maximum Service Interval */ 379 1.1 christos 3 + /* Minimum Data Rate */ 380 1.1 christos 3; /* Delay Bound */ 381 1.1 christos 382 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MAX_MSDU_SIZE) 383 1.1 christos buf_len += 2; /* Maximum MSDU Size */ 384 1.1 christos 385 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME) { 386 1.1 christos buf_len += 4; /* Service Start Time */ 387 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME_LINKID) 388 1.1 christos buf_len++; /* Service Start Time LinkID */ 389 1.1 christos } 390 1.1 christos 391 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MEAN_DATA_RATE) 392 1.1 christos buf_len += 3; /* Mean Data Rate */ 393 1.1 christos 394 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE) 395 1.1 christos buf_len += 4; /* Delayed Bounded Burst Size */ 396 1.1 christos 397 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MSDU_LIFETIME) 398 1.1 christos buf_len += 2; /* MSDU Lifetime */ 399 1.1 christos 400 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MSDU_DELIVERY_INFO) 401 1.1 christos buf_len++; /* MSDU Delivery Info */ 402 1.1 christos 403 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MEDIUM_TIME && 404 1.1 christos qos_elem->direction == SCS_DIRECTION_DIRECT) 405 1.1 christos buf_len += 2; /* Medium Time */ 406 1.1 christos 407 1.1 christos return buf_len; 408 1.1 christos } 409 1.1 christos 410 1.1 christos 411 1.1 christos static struct wpabuf * allocate_scs_buf(struct scs_desc_elem *desc_elem, 412 1.1 christos unsigned int num_scs_desc, 413 1.1 christos bool allow_scs_traffic_desc) 414 1.1 christos { 415 1.1 christos struct wpabuf *buf; 416 1.1 christos size_t buf_len = 0; 417 1.1 christos unsigned int i, j; 418 1.1 christos 419 1.1 christos buf_len = 3; /* Action frame header */ 420 1.1 christos 421 1.1 christos for (i = 0; i < num_scs_desc; i++, desc_elem++) { 422 1.1 christos struct tclas_element *tclas_elem; 423 1.1 christos 424 1.1 christos buf_len += 2 + /* SCS descriptor IE header */ 425 1.1 christos 1 + /* SCSID */ 426 1.1 christos 1 ; /* Request type */ 427 1.1 christos 428 1.1 christos if (desc_elem->request_type == SCS_REQ_REMOVE) 429 1.1 christos continue; 430 1.1 christos 431 1.1 christos if (allow_scs_traffic_desc && 432 1.1 christos desc_elem->qos_char_elem.available) 433 1.1 christos buf_len += qos_char_len(&desc_elem->qos_char_elem); 434 1.1 christos 435 1.1 christos if (!tclas_elem_required(&desc_elem->qos_char_elem)) 436 1.1 christos continue; 437 1.1 christos 438 1.1 christos if (desc_elem->intra_access_priority || desc_elem->scs_up_avail) 439 1.1 christos buf_len += 3; 440 1.1 christos 441 1.1 christos tclas_elem = desc_elem->tclas_elems; 442 1.1 christos if (!tclas_elem) { 443 1.1 christos wpa_printf(MSG_ERROR, "%s: TCLAS element null", 444 1.1 christos __func__); 445 1.1 christos return NULL; 446 1.1 christos } 447 1.1 christos 448 1.1 christos for (j = 0; j < desc_elem->num_tclas_elem; j++, tclas_elem++) { 449 1.1 christos size_t elen; 450 1.1 christos 451 1.1 christos elen = tclas_elem_len(tclas_elem); 452 1.1 christos if (elen == 0) 453 1.1 christos return NULL; 454 1.1 christos buf_len += elen; 455 1.1 christos } 456 1.1 christos 457 1.1 christos if (desc_elem->num_tclas_elem > 1) { 458 1.1 christos buf_len += 1 + /* TCLAS Processing eid */ 459 1.1 christos 1 + /* length */ 460 1.1 christos 1 ; /* processing */ 461 1.1 christos } 462 1.1 christos } 463 1.1 christos 464 1.1 christos buf = wpabuf_alloc(buf_len); 465 1.1 christos if (!buf) { 466 1.1 christos wpa_printf(MSG_ERROR, "Failed to allocate SCS req"); 467 1.1 christos return NULL; 468 1.1 christos } 469 1.1 christos 470 1.1 christos return buf; 471 1.1 christos } 472 1.1 christos 473 1.1 christos 474 1.1 christos static void scs_request_timer(void *eloop_ctx, void *timeout_ctx) 475 1.1 christos { 476 1.1 christos struct wpa_supplicant *wpa_s = eloop_ctx; 477 1.1 christos struct active_scs_elem *scs_desc, *prev; 478 1.1 christos 479 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) 480 1.1 christos return; 481 1.1 christos 482 1.1 christos /* Once timeout is over, remove all SCS descriptors with no response */ 483 1.1 christos dl_list_for_each_safe(scs_desc, prev, &wpa_s->active_scs_ids, 484 1.1 christos struct active_scs_elem, list) { 485 1.1 christos u8 bssid[ETH_ALEN] = { 0 }; 486 1.1 christos const u8 *src; 487 1.1 christos 488 1.1 christos if (scs_desc->status == SCS_DESC_SUCCESS) 489 1.1 christos continue; 490 1.1 christos 491 1.1 christos if (wpa_s->current_bss) 492 1.1 christos src = wpa_s->current_bss->bssid; 493 1.1 christos else 494 1.1 christos src = bssid; 495 1.1 christos 496 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCS_RESULT "bssid=" MACSTR 497 1.1 christos " SCSID=%u status_code=timedout", MAC2STR(src), 498 1.1 christos scs_desc->scs_id); 499 1.1 christos 500 1.1 christos dl_list_del(&scs_desc->list); 501 1.1 christos wpa_printf(MSG_INFO, "%s: SCSID %d removed after timeout", 502 1.1 christos __func__, scs_desc->scs_id); 503 1.1 christos os_free(scs_desc); 504 1.1 christos } 505 1.1 christos 506 1.1 christos eloop_cancel_timeout(scs_request_timer, wpa_s, NULL); 507 1.1 christos wpa_s->ongoing_scs_req = false; 508 1.1 christos } 509 1.1 christos 510 1.1 christos 511 1.1 christos int wpas_send_scs_req(struct wpa_supplicant *wpa_s) 512 1.1 christos { 513 1.1 christos struct wpabuf *buf = NULL; 514 1.1 christos struct scs_desc_elem *desc_elem = NULL; 515 1.1 christos const struct ieee80211_eht_capabilities *eht; 516 1.1 christos const u8 *eht_ie; 517 1.1 christos int ret = -1; 518 1.1 christos unsigned int i; 519 1.1 christos bool allow_scs_traffic_desc = false; 520 1.1 christos 521 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) 522 1.1 christos return -1; 523 1.1 christos 524 1.1 christos if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_SCS)) { 525 1.1 christos wpa_dbg(wpa_s, MSG_INFO, 526 1.1 christos "AP does not support SCS - could not send SCS Request"); 527 1.1 christos return -1; 528 1.1 christos } 529 1.1 christos 530 1.1 christos desc_elem = wpa_s->scs_robust_av_req.scs_desc_elems; 531 1.1 christos if (!desc_elem) 532 1.1 christos return -1; 533 1.1 christos 534 1.1 christos if (wpa_is_non_eht_scs_traffic_desc_supported(wpa_s->current_bss)) 535 1.1 christos allow_scs_traffic_desc = true; 536 1.1 christos 537 1.1 christos /* Allow SCS Traffic descriptor support for EHT connection */ 538 1.1 christos eht_ie = wpa_bss_get_ie_ext(wpa_s->current_bss, 539 1.1 christos WLAN_EID_EXT_EHT_CAPABILITIES); 540 1.1 christos if (wpa_s->connection_eht && eht_ie && 541 1.1 christos eht_ie[1] >= 1 + IEEE80211_EHT_CAPAB_MIN_LEN) { 542 1.1 christos eht = (const struct ieee80211_eht_capabilities *) &eht_ie[3]; 543 1.1 christos if (eht->mac_cap & EHT_MACCAP_SCS_TRAFFIC_DESC) 544 1.1 christos allow_scs_traffic_desc = true; 545 1.1 christos } 546 1.1 christos 547 1.1 christos if (!allow_scs_traffic_desc && desc_elem->qos_char_elem.available) { 548 1.1 christos wpa_dbg(wpa_s, MSG_INFO, 549 1.1 christos "Connection does not support EHT/non-EHT SCS Traffic Description - could not send SCS Request with QoS Characteristics"); 550 1.1 christos return -1; 551 1.1 christos } 552 1.1 christos 553 1.1 christos buf = allocate_scs_buf(desc_elem, 554 1.1 christos wpa_s->scs_robust_av_req.num_scs_desc, 555 1.1 christos allow_scs_traffic_desc); 556 1.1 christos if (!buf) 557 1.1 christos return -1; 558 1.1 christos 559 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING); 560 1.1 christos wpabuf_put_u8(buf, ROBUST_AV_SCS_REQ); 561 1.1 christos wpa_s->scs_dialog_token++; 562 1.1 christos if (wpa_s->scs_dialog_token == 0) 563 1.1 christos wpa_s->scs_dialog_token++; 564 1.1 christos wpabuf_put_u8(buf, wpa_s->scs_dialog_token); 565 1.1 christos 566 1.1 christos for (i = 0; i < wpa_s->scs_robust_av_req.num_scs_desc; 567 1.1 christos i++, desc_elem++) { 568 1.1 christos /* SCS Descriptor element */ 569 1.1 christos if (wpas_populate_scs_descriptor_ie(desc_elem, buf, 570 1.1 christos allow_scs_traffic_desc) < 0) 571 1.1 christos goto end; 572 1.1 christos } 573 1.1 christos 574 1.1 christos wpa_hexdump_buf(MSG_DEBUG, "SCS Request", buf); 575 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 576 1.1 christos wpa_s->own_addr, wpa_s->bssid, 577 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0); 578 1.1 christos if (ret < 0) { 579 1.1 christos wpa_dbg(wpa_s, MSG_ERROR, "SCS: Failed to send SCS Request"); 580 1.1 christos wpa_s->scs_dialog_token--; 581 1.1 christos goto end; 582 1.1 christos } 583 1.1 christos 584 1.1 christos desc_elem = wpa_s->scs_robust_av_req.scs_desc_elems; 585 1.1 christos for (i = 0; i < wpa_s->scs_robust_av_req.num_scs_desc; 586 1.1 christos i++, desc_elem++) { 587 1.1 christos struct active_scs_elem *active_scs_elem; 588 1.1 christos 589 1.1 christos if (desc_elem->request_type != SCS_REQ_ADD) 590 1.1 christos continue; 591 1.1 christos 592 1.1 christos active_scs_elem = os_malloc(sizeof(struct active_scs_elem)); 593 1.1 christos if (!active_scs_elem) 594 1.1 christos break; 595 1.1 christos active_scs_elem->scs_id = desc_elem->scs_id; 596 1.1 christos active_scs_elem->status = SCS_DESC_SENT; 597 1.1 christos dl_list_add(&wpa_s->active_scs_ids, &active_scs_elem->list); 598 1.1 christos } 599 1.1 christos 600 1.1 christos /* 601 1.1 christos * Register a timeout after which this request will be removed from 602 1.1 christos * the cache. 603 1.1 christos */ 604 1.1 christos eloop_register_timeout(SCS_RESP_TIMEOUT, 0, scs_request_timer, wpa_s, 605 1.1 christos NULL); 606 1.1 christos wpa_s->ongoing_scs_req = true; 607 1.1 christos 608 1.1 christos end: 609 1.1 christos wpabuf_free(buf); 610 1.1 christos free_up_scs_desc(&wpa_s->scs_robust_av_req); 611 1.1 christos 612 1.1 christos return ret; 613 1.1 christos } 614 1.1 christos 615 1.1 christos 616 1.1 christos void free_up_tclas_elem(struct scs_desc_elem *elem) 617 1.1 christos { 618 1.1 christos struct tclas_element *tclas_elems = elem->tclas_elems; 619 1.1 christos unsigned int num_tclas_elem = elem->num_tclas_elem; 620 1.1 christos struct tclas_element *tclas_data; 621 1.1 christos unsigned int j; 622 1.1 christos 623 1.1 christos elem->tclas_elems = NULL; 624 1.1 christos elem->num_tclas_elem = 0; 625 1.1 christos 626 1.1 christos if (!tclas_elems) 627 1.1 christos return; 628 1.1 christos 629 1.1 christos tclas_data = tclas_elems; 630 1.1 christos for (j = 0; j < num_tclas_elem; j++, tclas_data++) { 631 1.1 christos if (tclas_data->classifier_type != 10) 632 1.1 christos continue; 633 1.1 christos 634 1.1 christos os_free(tclas_data->frame_classifier.type10_param.filter_value); 635 1.1 christos os_free(tclas_data->frame_classifier.type10_param.filter_mask); 636 1.1 christos } 637 1.1 christos 638 1.1 christos os_free(tclas_elems); 639 1.1 christos } 640 1.1 christos 641 1.1 christos 642 1.1 christos void free_up_scs_desc(struct scs_robust_av_data *data) 643 1.1 christos { 644 1.1 christos struct scs_desc_elem *desc_elems = data->scs_desc_elems; 645 1.1 christos unsigned int num_scs_desc = data->num_scs_desc; 646 1.1 christos struct scs_desc_elem *desc_data; 647 1.1 christos unsigned int i; 648 1.1 christos 649 1.1 christos data->scs_desc_elems = NULL; 650 1.1 christos data->num_scs_desc = 0; 651 1.1 christos 652 1.1 christos if (!desc_elems) 653 1.1 christos return; 654 1.1 christos 655 1.1 christos desc_data = desc_elems; 656 1.1 christos for (i = 0; i < num_scs_desc; i++, desc_data++) { 657 1.1 christos if (desc_data->request_type == SCS_REQ_REMOVE || 658 1.1 christos !desc_data->tclas_elems) 659 1.1 christos continue; 660 1.1 christos 661 1.1 christos free_up_tclas_elem(desc_data); 662 1.1 christos } 663 1.1 christos os_free(desc_elems); 664 1.1 christos } 665 1.1 christos 666 1.1 christos 667 1.1 christos /* Element ID Extension(1) + Request Type(1) + User Priority Control(2) + 668 1.1 christos * Stream Timeout(4) */ 669 1.1 christos #define MSCS_DESCRIPTOR_FIXED_LEN 8 670 1.1 christos 671 1.1 christos static void wpas_parse_mscs_resp(struct wpa_supplicant *wpa_s, 672 1.1 christos u16 status, const u8 *bssid, 673 1.1 christos const u8 *mscs_desc_ie) 674 1.1 christos { 675 1.1 christos struct robust_av_data robust_av; 676 1.1 christos const u8 *pos; 677 1.1 christos 678 1.1 christos /* The MSCS Descriptor element is optional in the MSCS Response frame */ 679 1.1 christos if (!mscs_desc_ie) 680 1.1 christos goto event_mscs_result; 681 1.1 christos 682 1.1 christos if (mscs_desc_ie[1] < MSCS_DESCRIPTOR_FIXED_LEN) { 683 1.1 christos wpa_printf(MSG_INFO, 684 1.1 christos "MSCS: Drop received frame: invalid MSCS Descriptor element length: %d", 685 1.1 christos mscs_desc_ie[1]); 686 1.1 christos return; 687 1.1 christos } 688 1.1 christos 689 1.1 christos os_memset(&robust_av, 0, sizeof(struct robust_av_data)); 690 1.1 christos 691 1.1 christos /* Skip Element ID, Length, and Element ID Extension */ 692 1.1 christos pos = &mscs_desc_ie[3]; 693 1.1 christos 694 1.1 christos robust_av.request_type = *pos++; 695 1.1 christos 696 1.1 christos switch (robust_av.request_type) { 697 1.1 christos case SCS_REQ_CHANGE: 698 1.1 christos /* 699 1.1 christos * Inform the suggested set of parameters that could be accepted 700 1.1 christos * by the AP in response to a subsequent request by the station. 701 1.1 christos */ 702 1.1 christos robust_av.up_bitmap = *pos++; 703 1.1 christos robust_av.up_limit = *pos++ & 0x07; 704 1.1 christos robust_av.stream_timeout = WPA_GET_LE32(pos); 705 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR 706 1.1 christos " status_code=%u change up_bitmap=%u up_limit=%u stream_timeout=%u", 707 1.1 christos MAC2STR(bssid), status, robust_av.up_bitmap, 708 1.1 christos robust_av.up_limit, robust_av.stream_timeout); 709 1.1 christos wpa_s->mscs_setup_done = false; 710 1.1 christos return; 711 1.1 christos case SCS_REQ_ADD: 712 1.1 christos /* 713 1.1 christos * This type is used in (Re)Association Response frame MSCS 714 1.1 christos * Descriptor element if no change is required. 715 1.1 christos */ 716 1.1 christos break; 717 1.1 christos default: 718 1.1 christos wpa_printf(MSG_INFO, 719 1.1 christos "MSCS: Drop received frame with unknown Request Type: %u", 720 1.1 christos robust_av.request_type); 721 1.1 christos return; 722 1.1 christos } 723 1.1 christos 724 1.1 christos event_mscs_result: 725 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR 726 1.1 christos " status_code=%u", MAC2STR(bssid), status); 727 1.1 christos wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS; 728 1.1 christos } 729 1.1 christos 730 1.1 christos 731 1.1 christos void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, 732 1.1 christos const u8 *src, const u8 *buf, size_t len) 733 1.1 christos { 734 1.1 christos u8 dialog_token; 735 1.1 christos u16 status_code; 736 1.1 christos const u8 *mscs_desc_ie; 737 1.1 christos 738 1.1 christos if (len < 3) 739 1.1 christos return; 740 1.1 christos 741 1.1 christos dialog_token = *buf++; 742 1.1 christos len--; 743 1.1 christos 744 1.1 christos /* AP sets dialog token to 0 for unsolicited response */ 745 1.1 christos if (!dialog_token && !wpa_s->mscs_setup_done) { 746 1.1 christos wpa_printf(MSG_INFO, 747 1.1 christos "MSCS: Drop unsolicited received frame: inactive"); 748 1.1 christos return; 749 1.1 christos } 750 1.1 christos 751 1.1 christos if (dialog_token && dialog_token != wpa_s->robust_av.dialog_token) { 752 1.1 christos wpa_printf(MSG_INFO, 753 1.1 christos "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u", 754 1.1 christos dialog_token, wpa_s->robust_av.dialog_token); 755 1.1 christos return; 756 1.1 christos } 757 1.1 christos 758 1.1 christos status_code = WPA_GET_LE16(buf); 759 1.1 christos buf += 2; 760 1.1 christos len -= 2; 761 1.1 christos 762 1.1 christos mscs_desc_ie = get_ie_ext(buf, len, WLAN_EID_EXT_MSCS_DESCRIPTOR); 763 1.1 christos wpas_parse_mscs_resp(wpa_s, status_code, src, mscs_desc_ie); 764 1.1 christos } 765 1.1 christos 766 1.1 christos 767 1.1 christos void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, 768 1.1 christos const u8 *ies, size_t ies_len) 769 1.1 christos { 770 1.1 christos const u8 *mscs_desc_ie, *mscs_status; 771 1.1 christos u16 status; 772 1.1 christos 773 1.1 christos /* Process optional MSCS Status subelement when MSCS IE is in 774 1.1 christos * (Re)Association Response frame */ 775 1.1 christos if (!ies || ies_len == 0 || !wpa_s->robust_av.valid_config) 776 1.1 christos return; 777 1.1 christos 778 1.1 christos mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR); 779 1.1 christos if (!mscs_desc_ie || mscs_desc_ie[1] <= MSCS_DESCRIPTOR_FIXED_LEN) 780 1.1 christos return; 781 1.1 christos 782 1.1 christos /* Subelements start after element header and fixed fields */ 783 1.1 christos mscs_status = get_ie(&mscs_desc_ie[2 + MSCS_DESCRIPTOR_FIXED_LEN], 784 1.1 christos mscs_desc_ie[1] - MSCS_DESCRIPTOR_FIXED_LEN, 785 1.1 christos MCSC_SUBELEM_STATUS); 786 1.1 christos if (!mscs_status || mscs_status[1] < 2) 787 1.1 christos return; 788 1.1 christos 789 1.1 christos status = WPA_GET_LE16(mscs_status + 2); 790 1.1 christos 791 1.1 christos wpas_parse_mscs_resp(wpa_s, status, bssid, mscs_desc_ie); 792 1.1 christos } 793 1.1 christos 794 1.1 christos 795 1.1 christos static void wpas_wait_for_dscp_req_timer(void *eloop_ctx, void *timeout_ctx) 796 1.1 christos { 797 1.1 christos struct wpa_supplicant *wpa_s = eloop_ctx; 798 1.1 christos 799 1.1 christos /* Once timeout is over, reset wait flag and allow sending DSCP query */ 800 1.1 christos wpa_printf(MSG_DEBUG, 801 1.1 christos "QM: Wait time over for sending DSCP request - allow DSCP query"); 802 1.1 christos wpa_s->wait_for_dscp_req = 0; 803 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait end"); 804 1.1 christos } 805 1.1 christos 806 1.1 christos 807 1.1 christos void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s, 808 1.1 christos const u8 *ies, size_t ies_len) 809 1.1 christos { 810 1.1 christos const u8 *wfa_capa; 811 1.1 christos 812 1.1 christos wpa_s->connection_dscp = 0; 813 1.1 christos if (wpa_s->wait_for_dscp_req) 814 1.1 christos eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL); 815 1.1 christos 816 1.1 christos if (!ies || ies_len == 0 || !wpa_s->enable_dscp_policy_capa) 817 1.1 christos return; 818 1.1 christos 819 1.1 christos wfa_capa = get_vendor_ie(ies, ies_len, WFA_CAPA_IE_VENDOR_TYPE); 820 1.1 christos if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 || 821 1.1 christos !(wfa_capa[7] & WFA_CAPA_QM_DSCP_POLICY)) 822 1.1 christos return; /* AP does not enable QM DSCP Policy */ 823 1.1 christos 824 1.1 christos wpa_s->connection_dscp = 1; 825 1.1 christos wpa_s->wait_for_dscp_req = !!(wfa_capa[7] & 826 1.1 christos WFA_CAPA_QM_UNSOLIC_DSCP); 827 1.1 christos if (!wpa_s->wait_for_dscp_req) 828 1.1 christos return; 829 1.1 christos 830 1.1 christos /* Register a timeout after which dscp query can be sent to AP. */ 831 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait start"); 832 1.1 christos eloop_register_timeout(DSCP_REQ_TIMEOUT, 0, 833 1.1 christos wpas_wait_for_dscp_req_timer, wpa_s, NULL); 834 1.1 christos } 835 1.1 christos 836 1.1 christos 837 1.1 christos void wpas_handle_robust_av_scs_recv_action(struct wpa_supplicant *wpa_s, 838 1.1 christos const u8 *src, const u8 *buf, 839 1.1 christos size_t len) 840 1.1 christos { 841 1.1 christos u8 dialog_token; 842 1.1 christos unsigned int i, count; 843 1.1 christos struct active_scs_elem *scs_desc, *prev; 844 1.1 christos 845 1.1 christos if (len < 2) 846 1.1 christos return; 847 1.1 christos if (!wpa_s->ongoing_scs_req) { 848 1.1 christos wpa_printf(MSG_INFO, 849 1.1 christos "SCS: Drop received response due to no ongoing request"); 850 1.1 christos return; 851 1.1 christos } 852 1.1 christos 853 1.1 christos dialog_token = *buf++; 854 1.1 christos len--; 855 1.1 christos if (dialog_token != wpa_s->scs_dialog_token) { 856 1.1 christos wpa_printf(MSG_INFO, 857 1.1 christos "SCS: Drop received frame due to dialog token mismatch: received:%u expected:%u", 858 1.1 christos dialog_token, wpa_s->scs_dialog_token); 859 1.1 christos return; 860 1.1 christos } 861 1.1 christos 862 1.1 christos /* This Count field does not exist in the IEEE Std 802.11-2020 863 1.1 christos * definition of the SCS Response frame. However, it was accepted to 864 1.1 christos * be added into REVme per REVme/D0.0 CC35 CID 49 (edits in document 865 1.1 christos * 11-21-0688-07). */ 866 1.1 christos count = *buf++; 867 1.1 christos len--; 868 1.1 christos if (count == 0 || count * 3 > len) { 869 1.1 christos wpa_printf(MSG_INFO, 870 1.1 christos "SCS: Drop received frame due to invalid count: %u (remaining %zu octets)", 871 1.1 christos count, len); 872 1.1 christos return; 873 1.1 christos } 874 1.1 christos 875 1.1 christos for (i = 0; i < count; i++) { 876 1.1 christos u8 id; 877 1.1 christos u16 status; 878 1.1 christos bool scs_desc_found = false; 879 1.1 christos 880 1.1 christos id = *buf++; 881 1.1 christos status = WPA_GET_LE16(buf); 882 1.1 christos buf += 2; 883 1.1 christos len -= 3; 884 1.1 christos 885 1.1 christos dl_list_for_each(scs_desc, &wpa_s->active_scs_ids, 886 1.1 christos struct active_scs_elem, list) { 887 1.1 christos if (id == scs_desc->scs_id) { 888 1.1 christos scs_desc_found = true; 889 1.1 christos break; 890 1.1 christos } 891 1.1 christos } 892 1.1 christos 893 1.1 christos if (!scs_desc_found) { 894 1.1 christos wpa_printf(MSG_INFO, "SCS: SCS ID invalid %u", id); 895 1.1 christos continue; 896 1.1 christos } 897 1.1 christos 898 1.1 christos if (status != WLAN_STATUS_SUCCESS) { 899 1.1 christos dl_list_del(&scs_desc->list); 900 1.1 christos os_free(scs_desc); 901 1.1 christos } else if (status == WLAN_STATUS_SUCCESS) { 902 1.1 christos scs_desc->status = SCS_DESC_SUCCESS; 903 1.1 christos } 904 1.1 christos 905 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCS_RESULT "bssid=" MACSTR 906 1.1 christos " SCSID=%u status_code=%u", MAC2STR(src), id, status); 907 1.1 christos } 908 1.1 christos 909 1.1 christos eloop_cancel_timeout(scs_request_timer, wpa_s, NULL); 910 1.1 christos wpa_s->ongoing_scs_req = false; 911 1.1 christos 912 1.1 christos dl_list_for_each_safe(scs_desc, prev, &wpa_s->active_scs_ids, 913 1.1 christos struct active_scs_elem, list) { 914 1.1 christos if (scs_desc->status != SCS_DESC_SUCCESS) { 915 1.1 christos wpa_msg(wpa_s, MSG_INFO, 916 1.1 christos WPA_EVENT_SCS_RESULT "bssid=" MACSTR 917 1.1 christos " SCSID=%u status_code=response_not_received", 918 1.1 christos MAC2STR(src), scs_desc->scs_id); 919 1.1 christos dl_list_del(&scs_desc->list); 920 1.1 christos os_free(scs_desc); 921 1.1 christos } 922 1.1 christos } 923 1.1 christos } 924 1.1 christos 925 1.1 christos 926 1.1 christos static void wpas_clear_active_scs_ids(struct wpa_supplicant *wpa_s) 927 1.1 christos { 928 1.1 christos struct active_scs_elem *scs_elem; 929 1.1 christos 930 1.1 christos while ((scs_elem = dl_list_first(&wpa_s->active_scs_ids, 931 1.1 christos struct active_scs_elem, list))) { 932 1.1 christos dl_list_del(&scs_elem->list); 933 1.1 christos os_free(scs_elem); 934 1.1 christos } 935 1.1 christos } 936 1.1 christos 937 1.1 christos 938 1.1 christos void wpas_scs_deinit(struct wpa_supplicant *wpa_s) 939 1.1 christos { 940 1.1 christos free_up_scs_desc(&wpa_s->scs_robust_av_req); 941 1.1 christos wpa_s->scs_dialog_token = 0; 942 1.1 christos wpas_clear_active_scs_ids(wpa_s); 943 1.1 christos eloop_cancel_timeout(scs_request_timer, wpa_s, NULL); 944 1.1 christos wpa_s->ongoing_scs_req = false; 945 1.1 christos } 946 1.1 christos 947 1.1 christos 948 1.1 christos static int write_ipv4_info(char *pos, int total_len, 949 1.1 christos const struct ipv4_params *v4, 950 1.1 christos u8 classifier_mask) 951 1.1 christos { 952 1.1 christos int res, rem_len; 953 1.1 christos char addr[INET_ADDRSTRLEN]; 954 1.1 christos 955 1.1 christos rem_len = total_len; 956 1.1 christos 957 1.1 christos if (classifier_mask & BIT(1)) { 958 1.1 christos if (!inet_ntop(AF_INET, &v4->src_ip, addr, INET_ADDRSTRLEN)) { 959 1.1 christos wpa_printf(MSG_ERROR, 960 1.1 christos "QM: Failed to set IPv4 source address"); 961 1.1 christos return -1; 962 1.1 christos } 963 1.1 christos 964 1.1 christos res = os_snprintf(pos, rem_len, " src_ip=%s", addr); 965 1.1 christos if (os_snprintf_error(rem_len, res)) 966 1.1 christos return -1; 967 1.1 christos 968 1.1 christos pos += res; 969 1.1 christos rem_len -= res; 970 1.1 christos } 971 1.1 christos 972 1.1 christos if (classifier_mask & BIT(2)) { 973 1.1 christos if (!inet_ntop(AF_INET, &v4->dst_ip, addr, INET_ADDRSTRLEN)) { 974 1.1 christos wpa_printf(MSG_ERROR, 975 1.1 christos "QM: Failed to set IPv4 destination address"); 976 1.1 christos return -1; 977 1.1 christos } 978 1.1 christos 979 1.1 christos res = os_snprintf(pos, rem_len, " dst_ip=%s", addr); 980 1.1 christos if (os_snprintf_error(rem_len, res)) 981 1.1 christos return -1; 982 1.1 christos 983 1.1 christos pos += res; 984 1.1 christos rem_len -= res; 985 1.1 christos } 986 1.1 christos 987 1.1 christos if (classifier_mask & BIT(3)) { 988 1.1 christos res = os_snprintf(pos, rem_len, " src_port=%d", v4->src_port); 989 1.1 christos if (os_snprintf_error(rem_len, res)) 990 1.1 christos return -1; 991 1.1 christos 992 1.1 christos pos += res; 993 1.1 christos rem_len -= res; 994 1.1 christos } 995 1.1 christos 996 1.1 christos if (classifier_mask & BIT(4)) { 997 1.1 christos res = os_snprintf(pos, rem_len, " dst_port=%d", v4->dst_port); 998 1.1 christos if (os_snprintf_error(rem_len, res)) 999 1.1 christos return -1; 1000 1.1 christos 1001 1.1 christos pos += res; 1002 1.1 christos rem_len -= res; 1003 1.1 christos } 1004 1.1 christos 1005 1.1 christos if (classifier_mask & BIT(6)) { 1006 1.1 christos res = os_snprintf(pos, rem_len, " protocol=%d", v4->protocol); 1007 1.1 christos if (os_snprintf_error(rem_len, res)) 1008 1.1 christos return -1; 1009 1.1 christos 1010 1.1 christos pos += res; 1011 1.1 christos rem_len -= res; 1012 1.1 christos } 1013 1.1 christos 1014 1.1 christos return total_len - rem_len; 1015 1.1 christos } 1016 1.1 christos 1017 1.1 christos 1018 1.1 christos static int write_ipv6_info(char *pos, int total_len, 1019 1.1 christos const struct ipv6_params *v6, 1020 1.1 christos u8 classifier_mask) 1021 1.1 christos { 1022 1.1 christos int res, rem_len; 1023 1.1 christos char addr[INET6_ADDRSTRLEN]; 1024 1.1 christos 1025 1.1 christos rem_len = total_len; 1026 1.1 christos 1027 1.1 christos if (classifier_mask & BIT(1)) { 1028 1.1 christos if (!inet_ntop(AF_INET6, &v6->src_ip, addr, INET6_ADDRSTRLEN)) { 1029 1.1 christos wpa_printf(MSG_ERROR, 1030 1.1 christos "QM: Failed to set IPv6 source addr"); 1031 1.1 christos return -1; 1032 1.1 christos } 1033 1.1 christos 1034 1.1 christos res = os_snprintf(pos, rem_len, " src_ip=%s", addr); 1035 1.1 christos if (os_snprintf_error(rem_len, res)) 1036 1.1 christos return -1; 1037 1.1 christos 1038 1.1 christos pos += res; 1039 1.1 christos rem_len -= res; 1040 1.1 christos } 1041 1.1 christos 1042 1.1 christos if (classifier_mask & BIT(2)) { 1043 1.1 christos if (!inet_ntop(AF_INET6, &v6->dst_ip, addr, INET6_ADDRSTRLEN)) { 1044 1.1 christos wpa_printf(MSG_ERROR, 1045 1.1 christos "QM: Failed to set IPv6 destination addr"); 1046 1.1 christos return -1; 1047 1.1 christos } 1048 1.1 christos 1049 1.1 christos res = os_snprintf(pos, rem_len, " dst_ip=%s", addr); 1050 1.1 christos if (os_snprintf_error(rem_len, res)) 1051 1.1 christos return -1; 1052 1.1 christos 1053 1.1 christos pos += res; 1054 1.1 christos rem_len -= res; 1055 1.1 christos } 1056 1.1 christos 1057 1.1 christos if (classifier_mask & BIT(3)) { 1058 1.1 christos res = os_snprintf(pos, rem_len, " src_port=%d", v6->src_port); 1059 1.1 christos if (os_snprintf_error(rem_len, res)) 1060 1.1 christos return -1; 1061 1.1 christos 1062 1.1 christos pos += res; 1063 1.1 christos rem_len -= res; 1064 1.1 christos } 1065 1.1 christos 1066 1.1 christos if (classifier_mask & BIT(4)) { 1067 1.1 christos res = os_snprintf(pos, rem_len, " dst_port=%d", v6->dst_port); 1068 1.1 christos if (os_snprintf_error(rem_len, res)) 1069 1.1 christos return -1; 1070 1.1 christos 1071 1.1 christos pos += res; 1072 1.1 christos rem_len -= res; 1073 1.1 christos } 1074 1.1 christos 1075 1.1 christos if (classifier_mask & BIT(6)) { 1076 1.1 christos res = os_snprintf(pos, rem_len, " protocol=%d", 1077 1.1 christos v6->next_header); 1078 1.1 christos if (os_snprintf_error(rem_len, res)) 1079 1.1 christos return -1; 1080 1.1 christos 1081 1.1 christos pos += res; 1082 1.1 christos rem_len -= res; 1083 1.1 christos } 1084 1.1 christos 1085 1.1 christos return total_len - rem_len; 1086 1.1 christos } 1087 1.1 christos 1088 1.1 christos 1089 1.1 christos struct dscp_policy_data { 1090 1.1 christos u8 policy_id; 1091 1.1 christos u8 req_type; 1092 1.1 christos u8 dscp; 1093 1.1 christos bool dscp_info; 1094 1.1 christos const u8 *frame_classifier; 1095 1.1 christos u8 frame_classifier_len; 1096 1.1 christos struct type4_params type4_param; 1097 1.1 christos const u8 *domain_name; 1098 1.1 christos u8 domain_name_len; 1099 1.1 christos u16 start_port; 1100 1.1 christos u16 end_port; 1101 1.1 christos bool port_range_info; 1102 1.1 christos }; 1103 1.1 christos 1104 1.1 christos 1105 1.1 christos static int set_frame_classifier_type4_ipv4(struct dscp_policy_data *policy) 1106 1.1 christos { 1107 1.1 christos u8 classifier_mask; 1108 1.1 christos const u8 *frame_classifier = policy->frame_classifier; 1109 1.1 christos struct type4_params *type4_param = &policy->type4_param; 1110 1.1 christos 1111 1.1 christos if (policy->frame_classifier_len < 18) { 1112 1.1 christos wpa_printf(MSG_ERROR, 1113 1.1 christos "QM: Received IPv4 frame classifier with insufficient length %d", 1114 1.1 christos policy->frame_classifier_len); 1115 1.1 christos return -1; 1116 1.1 christos } 1117 1.1 christos 1118 1.1 christos classifier_mask = frame_classifier[1]; 1119 1.1 christos 1120 1.1 christos /* Classifier Mask - bit 1 = Source IP Address */ 1121 1.1 christos if (classifier_mask & BIT(1)) { 1122 1.1 christos type4_param->classifier_mask |= BIT(1); 1123 1.1 christos os_memcpy(&type4_param->ip_params.v4.src_ip, 1124 1.1 christos &frame_classifier[3], 4); 1125 1.1 christos } 1126 1.1 christos 1127 1.1 christos /* Classifier Mask - bit 2 = Destination IP Address */ 1128 1.1 christos if (classifier_mask & BIT(2)) { 1129 1.1 christos if (policy->domain_name) { 1130 1.1 christos wpa_printf(MSG_ERROR, 1131 1.1 christos "QM: IPv4: Both domain name and destination IP address not expected"); 1132 1.1 christos return -1; 1133 1.1 christos } 1134 1.1 christos 1135 1.1 christos type4_param->classifier_mask |= BIT(2); 1136 1.1 christos os_memcpy(&type4_param->ip_params.v4.dst_ip, 1137 1.1 christos &frame_classifier[7], 4); 1138 1.1 christos } 1139 1.1 christos 1140 1.1 christos /* Classifier Mask - bit 3 = Source Port */ 1141 1.1 christos if (classifier_mask & BIT(3)) { 1142 1.1 christos type4_param->classifier_mask |= BIT(3); 1143 1.1 christos type4_param->ip_params.v4.src_port = 1144 1.1 christos WPA_GET_BE16(&frame_classifier[11]); 1145 1.1 christos } 1146 1.1 christos 1147 1.1 christos /* Classifier Mask - bit 4 = Destination Port */ 1148 1.1 christos if (classifier_mask & BIT(4)) { 1149 1.1 christos if (policy->port_range_info) { 1150 1.1 christos wpa_printf(MSG_ERROR, 1151 1.1 christos "QM: IPv4: Both port range and destination port not expected"); 1152 1.1 christos return -1; 1153 1.1 christos } 1154 1.1 christos 1155 1.1 christos type4_param->classifier_mask |= BIT(4); 1156 1.1 christos type4_param->ip_params.v4.dst_port = 1157 1.1 christos WPA_GET_BE16(&frame_classifier[13]); 1158 1.1 christos } 1159 1.1 christos 1160 1.1 christos /* Classifier Mask - bit 5 = DSCP (ignored) */ 1161 1.1 christos 1162 1.1 christos /* Classifier Mask - bit 6 = Protocol */ 1163 1.1 christos if (classifier_mask & BIT(6)) { 1164 1.1 christos type4_param->classifier_mask |= BIT(6); 1165 1.1 christos type4_param->ip_params.v4.protocol = frame_classifier[16]; 1166 1.1 christos } 1167 1.1 christos 1168 1.1 christos return 0; 1169 1.1 christos } 1170 1.1 christos 1171 1.1 christos 1172 1.1 christos static int set_frame_classifier_type4_ipv6(struct dscp_policy_data *policy) 1173 1.1 christos { 1174 1.1 christos u8 classifier_mask; 1175 1.1 christos const u8 *frame_classifier = policy->frame_classifier; 1176 1.1 christos struct type4_params *type4_param = &policy->type4_param; 1177 1.1 christos 1178 1.1 christos if (policy->frame_classifier_len < 44) { 1179 1.1 christos wpa_printf(MSG_ERROR, 1180 1.1 christos "QM: Received IPv6 frame classifier with insufficient length %d", 1181 1.1 christos policy->frame_classifier_len); 1182 1.1 christos return -1; 1183 1.1 christos } 1184 1.1 christos 1185 1.1 christos classifier_mask = frame_classifier[1]; 1186 1.1 christos 1187 1.1 christos /* Classifier Mask - bit 1 = Source IP Address */ 1188 1.1 christos if (classifier_mask & BIT(1)) { 1189 1.1 christos type4_param->classifier_mask |= BIT(1); 1190 1.1 christos os_memcpy(&type4_param->ip_params.v6.src_ip, 1191 1.1 christos &frame_classifier[3], 16); 1192 1.1 christos } 1193 1.1 christos 1194 1.1 christos /* Classifier Mask - bit 2 = Destination IP Address */ 1195 1.1 christos if (classifier_mask & BIT(2)) { 1196 1.1 christos if (policy->domain_name) { 1197 1.1 christos wpa_printf(MSG_ERROR, 1198 1.1 christos "QM: IPv6: Both domain name and destination IP address not expected"); 1199 1.1 christos return -1; 1200 1.1 christos } 1201 1.1 christos type4_param->classifier_mask |= BIT(2); 1202 1.1 christos os_memcpy(&type4_param->ip_params.v6.dst_ip, 1203 1.1 christos &frame_classifier[19], 16); 1204 1.1 christos } 1205 1.1 christos 1206 1.1 christos /* Classifier Mask - bit 3 = Source Port */ 1207 1.1 christos if (classifier_mask & BIT(3)) { 1208 1.1 christos type4_param->classifier_mask |= BIT(3); 1209 1.1 christos type4_param->ip_params.v6.src_port = 1210 1.1 christos WPA_GET_BE16(&frame_classifier[35]); 1211 1.1 christos } 1212 1.1 christos 1213 1.1 christos /* Classifier Mask - bit 4 = Destination Port */ 1214 1.1 christos if (classifier_mask & BIT(4)) { 1215 1.1 christos if (policy->port_range_info) { 1216 1.1 christos wpa_printf(MSG_ERROR, 1217 1.1 christos "IPv6: Both port range and destination port not expected"); 1218 1.1 christos return -1; 1219 1.1 christos } 1220 1.1 christos 1221 1.1 christos type4_param->classifier_mask |= BIT(4); 1222 1.1 christos type4_param->ip_params.v6.dst_port = 1223 1.1 christos WPA_GET_BE16(&frame_classifier[37]); 1224 1.1 christos } 1225 1.1 christos 1226 1.1 christos /* Classifier Mask - bit 5 = DSCP (ignored) */ 1227 1.1 christos 1228 1.1 christos /* Classifier Mask - bit 6 = Next Header */ 1229 1.1 christos if (classifier_mask & BIT(6)) { 1230 1.1 christos type4_param->classifier_mask |= BIT(6); 1231 1.1 christos type4_param->ip_params.v6.next_header = frame_classifier[40]; 1232 1.1 christos } 1233 1.1 christos 1234 1.1 christos return 0; 1235 1.1 christos } 1236 1.1 christos 1237 1.1 christos 1238 1.1 christos static int wpas_set_frame_classifier_params(struct dscp_policy_data *policy) 1239 1.1 christos { 1240 1.1 christos const u8 *frame_classifier = policy->frame_classifier; 1241 1.1 christos u8 frame_classifier_len = policy->frame_classifier_len; 1242 1.1 christos 1243 1.1 christos if (frame_classifier_len < 3) { 1244 1.1 christos wpa_printf(MSG_ERROR, 1245 1.1 christos "QM: Received frame classifier with insufficient length %d", 1246 1.1 christos frame_classifier_len); 1247 1.1 christos return -1; 1248 1.1 christos } 1249 1.1 christos 1250 1.1 christos /* Only allowed Classifier Type: IP and higher layer parameters (4) */ 1251 1.1 christos if (frame_classifier[0] != 4) { 1252 1.1 christos wpa_printf(MSG_ERROR, 1253 1.1 christos "QM: Received frame classifier with invalid classifier type %d", 1254 1.1 christos frame_classifier[0]); 1255 1.1 christos return -1; 1256 1.1 christos } 1257 1.1 christos 1258 1.1 christos /* Classifier Mask - bit 0 = Version */ 1259 1.1 christos if (!(frame_classifier[1] & BIT(0))) { 1260 1.1 christos wpa_printf(MSG_ERROR, 1261 1.1 christos "QM: Received frame classifier without IP version"); 1262 1.1 christos return -1; 1263 1.1 christos } 1264 1.1 christos 1265 1.1 christos /* Version (4 or 6) */ 1266 1.1 christos if (frame_classifier[2] == 4) { 1267 1.1 christos if (set_frame_classifier_type4_ipv4(policy)) { 1268 1.1 christos wpa_printf(MSG_ERROR, 1269 1.1 christos "QM: Failed to set IPv4 parameters"); 1270 1.1 christos return -1; 1271 1.1 christos } 1272 1.1 christos 1273 1.1 christos policy->type4_param.ip_version = IPV4; 1274 1.1 christos } else if (frame_classifier[2] == 6) { 1275 1.1 christos if (set_frame_classifier_type4_ipv6(policy)) { 1276 1.1 christos wpa_printf(MSG_ERROR, 1277 1.1 christos "QM: Failed to set IPv6 parameters"); 1278 1.1 christos return -1; 1279 1.1 christos } 1280 1.1 christos 1281 1.1 christos policy->type4_param.ip_version = IPV6; 1282 1.1 christos } else { 1283 1.1 christos wpa_printf(MSG_ERROR, 1284 1.1 christos "QM: Received unknown IP version %d", 1285 1.1 christos frame_classifier[2]); 1286 1.1 christos return -1; 1287 1.1 christos } 1288 1.1 christos 1289 1.1 christos return 0; 1290 1.1 christos } 1291 1.1 christos 1292 1.1 christos 1293 1.1 christos static bool dscp_valid_domain_name(const char *str) 1294 1.1 christos { 1295 1.1 christos if (!str[0]) 1296 1.1 christos return false; 1297 1.1 christos 1298 1.1 christos while (*str) { 1299 1.1 christos if (is_ctrl_char(*str) || *str == ' ' || *str == '=') 1300 1.1 christos return false; 1301 1.1 christos str++; 1302 1.1 christos } 1303 1.1 christos 1304 1.1 christos return true; 1305 1.1 christos } 1306 1.1 christos 1307 1.1 christos 1308 1.1 christos static void wpas_add_dscp_policy(struct wpa_supplicant *wpa_s, 1309 1.1 christos struct dscp_policy_data *policy) 1310 1.1 christos { 1311 1.1 christos int ip_ver = 0, res; 1312 1.1 christos char policy_str[1000], *pos; 1313 1.1 christos int len; 1314 1.1 christos 1315 1.1 christos if (!policy->frame_classifier && !policy->domain_name && 1316 1.1 christos !policy->port_range_info) { 1317 1.1 christos wpa_printf(MSG_ERROR, 1318 1.1 christos "QM: Invalid DSCP policy - no attributes present"); 1319 1.1 christos goto fail; 1320 1.1 christos } 1321 1.1 christos 1322 1.1 christos policy_str[0] = '\0'; 1323 1.1 christos pos = policy_str; 1324 1.1 christos len = sizeof(policy_str); 1325 1.1 christos 1326 1.1 christos if (policy->frame_classifier) { 1327 1.1 christos struct type4_params *type4 = &policy->type4_param; 1328 1.1 christos 1329 1.1 christos if (wpas_set_frame_classifier_params(policy)) { 1330 1.1 christos wpa_printf(MSG_ERROR, 1331 1.1 christos "QM: Failed to set frame classifier parameters"); 1332 1.1 christos goto fail; 1333 1.1 christos } 1334 1.1 christos 1335 1.1 christos if (type4->ip_version == IPV4) 1336 1.1 christos res = write_ipv4_info(pos, len, &type4->ip_params.v4, 1337 1.1 christos type4->classifier_mask); 1338 1.1 christos else 1339 1.1 christos res = write_ipv6_info(pos, len, &type4->ip_params.v6, 1340 1.1 christos type4->classifier_mask); 1341 1.1 christos 1342 1.1 christos if (res <= 0) { 1343 1.1 christos wpa_printf(MSG_ERROR, 1344 1.1 christos "QM: Failed to write IP parameters"); 1345 1.1 christos goto fail; 1346 1.1 christos } 1347 1.1 christos 1348 1.1 christos ip_ver = type4->ip_version; 1349 1.1 christos 1350 1.1 christos pos += res; 1351 1.1 christos len -= res; 1352 1.1 christos } 1353 1.1 christos 1354 1.1 christos if (policy->port_range_info) { 1355 1.1 christos res = os_snprintf(pos, len, " start_port=%u end_port=%u", 1356 1.1 christos policy->start_port, policy->end_port); 1357 1.1 christos if (os_snprintf_error(len, res)) { 1358 1.1 christos wpa_printf(MSG_ERROR, 1359 1.1 christos "QM: Failed to write port range attributes for policy id = %d", 1360 1.1 christos policy->policy_id); 1361 1.1 christos goto fail; 1362 1.1 christos } 1363 1.1 christos 1364 1.1 christos pos += res; 1365 1.1 christos len -= res; 1366 1.1 christos } 1367 1.1 christos 1368 1.1 christos if (policy->domain_name) { 1369 1.1 christos char domain_name_str[250]; 1370 1.1 christos 1371 1.1 christos if (policy->domain_name_len >= sizeof(domain_name_str)) { 1372 1.1 christos wpa_printf(MSG_ERROR, 1373 1.1 christos "QM: Domain name length higher than max expected"); 1374 1.1 christos goto fail; 1375 1.1 christos } 1376 1.1 christos os_memcpy(domain_name_str, policy->domain_name, 1377 1.1 christos policy->domain_name_len); 1378 1.1 christos domain_name_str[policy->domain_name_len] = '\0'; 1379 1.1 christos if (!dscp_valid_domain_name(domain_name_str)) { 1380 1.1 christos wpa_printf(MSG_ERROR, "QM: Invalid domain name string"); 1381 1.1 christos goto fail; 1382 1.1 christos } 1383 1.1 christos res = os_snprintf(pos, len, " domain_name=%s", domain_name_str); 1384 1.1 christos if (os_snprintf_error(len, res)) { 1385 1.1 christos wpa_printf(MSG_ERROR, 1386 1.1 christos "QM: Failed to write domain name attribute for policy id = %d", 1387 1.1 christos policy->policy_id); 1388 1.1 christos goto fail; 1389 1.1 christos } 1390 1.1 christos } 1391 1.1 christos 1392 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY 1393 1.1 christos "add policy_id=%u dscp=%u ip_version=%d%s", 1394 1.1 christos policy->policy_id, policy->dscp, ip_ver, policy_str); 1395 1.1 christos return; 1396 1.1 christos fail: 1397 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "reject policy_id=%u", 1398 1.1 christos policy->policy_id); 1399 1.1 christos } 1400 1.1 christos 1401 1.1 christos 1402 1.1 christos void wpas_dscp_deinit(struct wpa_supplicant *wpa_s) 1403 1.1 christos { 1404 1.1 christos wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies"); 1405 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all"); 1406 1.1 christos wpa_s->dscp_req_dialog_token = 0; 1407 1.1 christos wpa_s->dscp_query_dialog_token = 0; 1408 1.1 christos wpa_s->connection_dscp = 0; 1409 1.1 christos if (wpa_s->wait_for_dscp_req) { 1410 1.1 christos wpa_s->wait_for_dscp_req = 0; 1411 1.1 christos eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL); 1412 1.1 christos } 1413 1.1 christos } 1414 1.1 christos 1415 1.1 christos 1416 1.1 christos static void wpas_fill_dscp_policy(struct dscp_policy_data *policy, u8 attr_id, 1417 1.1 christos u8 attr_len, const u8 *attr_data) 1418 1.1 christos { 1419 1.1 christos switch (attr_id) { 1420 1.1 christos case QM_ATTR_PORT_RANGE: 1421 1.1 christos if (attr_len < 4) { 1422 1.1 christos wpa_printf(MSG_ERROR, 1423 1.1 christos "QM: Received Port Range attribute with insufficient length %d", 1424 1.1 christos attr_len); 1425 1.1 christos break; 1426 1.1 christos } 1427 1.1 christos policy->start_port = WPA_GET_BE16(attr_data); 1428 1.1 christos policy->end_port = WPA_GET_BE16(attr_data + 2); 1429 1.1 christos policy->port_range_info = true; 1430 1.1 christos break; 1431 1.1 christos case QM_ATTR_DSCP_POLICY: 1432 1.1 christos if (attr_len < 3) { 1433 1.1 christos wpa_printf(MSG_ERROR, 1434 1.1 christos "QM: Received DSCP Policy attribute with insufficient length %d", 1435 1.1 christos attr_len); 1436 1.1 christos return; 1437 1.1 christos } 1438 1.1 christos policy->policy_id = attr_data[0]; 1439 1.1 christos policy->req_type = attr_data[1]; 1440 1.1 christos policy->dscp = attr_data[2]; 1441 1.1 christos policy->dscp_info = true; 1442 1.1 christos break; 1443 1.1 christos case QM_ATTR_TCLAS: 1444 1.1 christos if (attr_len < 1) { 1445 1.1 christos wpa_printf(MSG_ERROR, 1446 1.1 christos "QM: Received TCLAS attribute with insufficient length %d", 1447 1.1 christos attr_len); 1448 1.1 christos return; 1449 1.1 christos } 1450 1.1 christos policy->frame_classifier = attr_data; 1451 1.1 christos policy->frame_classifier_len = attr_len; 1452 1.1 christos break; 1453 1.1 christos case QM_ATTR_DOMAIN_NAME: 1454 1.1 christos if (attr_len < 1) { 1455 1.1 christos wpa_printf(MSG_ERROR, 1456 1.1 christos "QM: Received domain name attribute with insufficient length %d", 1457 1.1 christos attr_len); 1458 1.1 christos return; 1459 1.1 christos } 1460 1.1 christos policy->domain_name = attr_data; 1461 1.1 christos policy->domain_name_len = attr_len; 1462 1.1 christos break; 1463 1.1 christos default: 1464 1.1 christos wpa_printf(MSG_ERROR, "QM: Received invalid QoS attribute %d", 1465 1.1 christos attr_id); 1466 1.1 christos break; 1467 1.1 christos } 1468 1.1 christos } 1469 1.1 christos 1470 1.1 christos 1471 1.1 christos void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s, 1472 1.1 christos const u8 *src, 1473 1.1 christos const u8 *buf, size_t len) 1474 1.1 christos { 1475 1.1 christos int rem_len; 1476 1.1 christos const u8 *qos_ie, *attr; 1477 1.1 christos int more, reset; 1478 1.1 christos 1479 1.1 christos if (!wpa_s->enable_dscp_policy_capa) { 1480 1.1 christos wpa_printf(MSG_ERROR, 1481 1.1 christos "QM: Ignore DSCP Policy frame since the capability is not enabled"); 1482 1.1 christos return; 1483 1.1 christos } 1484 1.1 christos 1485 1.1 christos if (!pmf_in_use(wpa_s, src)) { 1486 1.1 christos wpa_printf(MSG_ERROR, 1487 1.1 christos "QM: Ignore DSCP Policy frame since PMF is not in use"); 1488 1.1 christos return; 1489 1.1 christos } 1490 1.1 christos 1491 1.1 christos if (!wpa_s->connection_dscp) { 1492 1.1 christos wpa_printf(MSG_DEBUG, 1493 1.1 christos "QM: DSCP Policy capability not enabled for the current association - ignore QoS Management Action frames"); 1494 1.1 christos return; 1495 1.1 christos } 1496 1.1 christos 1497 1.1 christos if (len < 1) 1498 1.1 christos return; 1499 1.1 christos 1500 1.1 christos /* Handle only DSCP Policy Request frame */ 1501 1.1 christos if (buf[0] != QM_DSCP_POLICY_REQ) { 1502 1.1 christos wpa_printf(MSG_ERROR, "QM: Received unexpected QoS action frame %d", 1503 1.1 christos buf[0]); 1504 1.1 christos return; 1505 1.1 christos } 1506 1.1 christos 1507 1.1 christos if (len < 3) { 1508 1.1 christos wpa_printf(MSG_ERROR, 1509 1.1 christos "Received QoS Management DSCP Policy Request frame with invalid length %zu", 1510 1.1 christos len); 1511 1.1 christos return; 1512 1.1 christos } 1513 1.1 christos 1514 1.1 christos /* Clear wait_for_dscp_req on receiving first DSCP request from AP */ 1515 1.1 christos if (wpa_s->wait_for_dscp_req) { 1516 1.1 christos wpa_s->wait_for_dscp_req = 0; 1517 1.1 christos eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL); 1518 1.1 christos } 1519 1.1 christos 1520 1.1 christos wpa_s->dscp_req_dialog_token = buf[1]; 1521 1.1 christos more = buf[2] & DSCP_POLICY_CTRL_MORE; 1522 1.1 christos reset = buf[2] & DSCP_POLICY_CTRL_RESET; 1523 1.1 christos 1524 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_start%s%s", 1525 1.1 christos reset ? " clear_all" : "", more ? " more" : ""); 1526 1.1 christos 1527 1.1 christos qos_ie = buf + 3; 1528 1.1 christos rem_len = len - 3; 1529 1.1 christos while (rem_len > 2) { 1530 1.1 christos struct dscp_policy_data policy; 1531 1.1 christos int rem_attrs_len, ie_len; 1532 1.1 christos 1533 1.1 christos ie_len = 2 + qos_ie[1]; 1534 1.1 christos if (rem_len < ie_len) 1535 1.1 christos break; 1536 1.1 christos 1537 1.1 christos if (rem_len < 6 || qos_ie[0] != WLAN_EID_VENDOR_SPECIFIC || 1538 1.1 christos qos_ie[1] < 4 || 1539 1.1 christos WPA_GET_BE32(&qos_ie[2]) != QM_IE_VENDOR_TYPE) { 1540 1.1 christos rem_len -= ie_len; 1541 1.1 christos qos_ie += ie_len; 1542 1.1 christos continue; 1543 1.1 christos } 1544 1.1 christos 1545 1.1 christos os_memset(&policy, 0, sizeof(struct dscp_policy_data)); 1546 1.1 christos attr = qos_ie + 6; 1547 1.1 christos rem_attrs_len = qos_ie[1] - 4; 1548 1.1 christos 1549 1.1 christos while (rem_attrs_len > 2) { 1550 1.1 christos u8 attr_id, attr_len; 1551 1.1 christos 1552 1.1 christos attr_id = *attr++; 1553 1.1 christos attr_len = *attr++; 1554 1.1 christos rem_attrs_len -= 2; 1555 1.1 christos if (attr_len > rem_attrs_len) 1556 1.1 christos break; 1557 1.1 christos wpas_fill_dscp_policy(&policy, attr_id, attr_len, attr); 1558 1.1 christos rem_attrs_len -= attr_len; 1559 1.1 christos attr += attr_len; 1560 1.1 christos } 1561 1.1 christos 1562 1.1 christos rem_len -= ie_len; 1563 1.1 christos qos_ie += ie_len; 1564 1.1 christos 1565 1.1 christos if (!policy.dscp_info) { 1566 1.1 christos wpa_printf(MSG_ERROR, 1567 1.1 christos "QM: Received QoS IE without DSCP Policy attribute"); 1568 1.1 christos continue; 1569 1.1 christos } 1570 1.1 christos 1571 1.1 christos if (policy.req_type == DSCP_POLICY_REQ_ADD) 1572 1.1 christos wpas_add_dscp_policy(wpa_s, &policy); 1573 1.1 christos else if (policy.req_type == DSCP_POLICY_REQ_REMOVE) 1574 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY 1575 1.1 christos "remove policy_id=%u", policy.policy_id); 1576 1.1 christos else 1577 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY 1578 1.1 christos "reject policy_id=%u", policy.policy_id); 1579 1.1 christos } 1580 1.1 christos 1581 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_end"); 1582 1.1 christos } 1583 1.1 christos 1584 1.1 christos 1585 1.1 christos int wpas_send_dscp_response(struct wpa_supplicant *wpa_s, 1586 1.1 christos struct dscp_resp_data *resp_data) 1587 1.1 christos { 1588 1.1 christos struct wpabuf *buf = NULL; 1589 1.1 christos size_t buf_len; 1590 1.1 christos int ret = -1, i; 1591 1.1 christos u8 resp_control = 0; 1592 1.1 christos 1593 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) { 1594 1.1 christos wpa_printf(MSG_ERROR, 1595 1.1 christos "QM: Failed to send DSCP response - not connected to AP"); 1596 1.1 christos return -1; 1597 1.1 christos } 1598 1.1 christos 1599 1.1 christos if (resp_data->solicited && !wpa_s->dscp_req_dialog_token) { 1600 1.1 christos wpa_printf(MSG_ERROR, "QM: No ongoing DSCP request"); 1601 1.1 christos return -1; 1602 1.1 christos } 1603 1.1 christos 1604 1.1 christos if (!wpa_s->connection_dscp) { 1605 1.1 christos wpa_printf(MSG_ERROR, 1606 1.1 christos "QM: Failed to send DSCP response - DSCP capability not enabled for the current association"); 1607 1.1 christos return -1; 1608 1.1 christos 1609 1.1 christos } 1610 1.1 christos 1611 1.1 christos buf_len = 1 + /* Category */ 1612 1.1 christos 3 + /* OUI */ 1613 1.1 christos 1 + /* OUI Type */ 1614 1.1 christos 1 + /* OUI Subtype */ 1615 1.1 christos 1 + /* Dialog Token */ 1616 1.1 christos 1 + /* Response Control */ 1617 1.1 christos 1 + /* Count */ 1618 1.1 christos 2 * resp_data->num_policies; /* Status list */ 1619 1.1 christos buf = wpabuf_alloc(buf_len); 1620 1.1 christos if (!buf) { 1621 1.1 christos wpa_printf(MSG_ERROR, 1622 1.1 christos "QM: Failed to allocate DSCP policy response"); 1623 1.1 christos return -1; 1624 1.1 christos } 1625 1.1 christos 1626 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED); 1627 1.1 christos wpabuf_put_be24(buf, OUI_WFA); 1628 1.1 christos wpabuf_put_u8(buf, QM_ACTION_OUI_TYPE); 1629 1.1 christos wpabuf_put_u8(buf, QM_DSCP_POLICY_RESP); 1630 1.1 christos 1631 1.1 christos wpabuf_put_u8(buf, resp_data->solicited ? 1632 1.1 christos wpa_s->dscp_req_dialog_token : 0); 1633 1.1 christos 1634 1.1 christos if (resp_data->more) 1635 1.1 christos resp_control |= DSCP_POLICY_CTRL_MORE; 1636 1.1 christos if (resp_data->reset) 1637 1.1 christos resp_control |= DSCP_POLICY_CTRL_RESET; 1638 1.1 christos wpabuf_put_u8(buf, resp_control); 1639 1.1 christos 1640 1.1 christos wpabuf_put_u8(buf, resp_data->num_policies); 1641 1.1 christos for (i = 0; i < resp_data->num_policies; i++) { 1642 1.1 christos wpabuf_put_u8(buf, resp_data->policy[i].id); 1643 1.1 christos wpabuf_put_u8(buf, resp_data->policy[i].status); 1644 1.1 christos } 1645 1.1 christos 1646 1.1 christos wpa_hexdump_buf(MSG_MSGDUMP, "DSCP response frame: ", buf); 1647 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 1648 1.1 christos wpa_s->own_addr, wpa_s->bssid, 1649 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0); 1650 1.1 christos if (ret < 0) { 1651 1.1 christos wpa_msg(wpa_s, MSG_INFO, "QM: Failed to send DSCP response"); 1652 1.1 christos goto fail; 1653 1.1 christos } 1654 1.1 christos 1655 1.1 christos /* 1656 1.1 christos * Mark DSCP request complete whether response sent is solicited or 1657 1.1 christos * unsolicited 1658 1.1 christos */ 1659 1.1 christos wpa_s->dscp_req_dialog_token = 0; 1660 1.1 christos 1661 1.1 christos fail: 1662 1.1 christos wpabuf_free(buf); 1663 1.1 christos return ret; 1664 1.1 christos } 1665 1.1 christos 1666 1.1 christos 1667 1.1 christos int wpas_send_dscp_query(struct wpa_supplicant *wpa_s, const char *domain_name, 1668 1.1 christos size_t domain_name_length) 1669 1.1 christos { 1670 1.1 christos struct wpabuf *buf = NULL; 1671 1.1 christos int ret, dscp_query_size; 1672 1.1 christos 1673 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) 1674 1.1 christos return -1; 1675 1.1 christos 1676 1.1 christos if (!wpa_s->connection_dscp) { 1677 1.1 christos wpa_printf(MSG_ERROR, 1678 1.1 christos "QM: Failed to send DSCP query - DSCP capability not enabled for the current association"); 1679 1.1 christos return -1; 1680 1.1 christos } 1681 1.1 christos 1682 1.1 christos if (wpa_s->wait_for_dscp_req) { 1683 1.1 christos wpa_printf(MSG_INFO, "QM: Wait until AP sends a DSCP request"); 1684 1.1 christos return -1; 1685 1.1 christos } 1686 1.1 christos 1687 1.1 christos #define DOMAIN_NAME_OFFSET (4 /* OUI */ + 1 /* Attr Id */ + 1 /* Attr len */) 1688 1.1 christos 1689 1.1 christos if (domain_name_length > 255 - DOMAIN_NAME_OFFSET) { 1690 1.1 christos wpa_printf(MSG_ERROR, "QM: Too long domain name"); 1691 1.1 christos return -1; 1692 1.1 christos } 1693 1.1 christos 1694 1.1 christos dscp_query_size = 1 + /* Category */ 1695 1.1 christos 4 + /* OUI Type */ 1696 1.1 christos 1 + /* OUI subtype */ 1697 1.1 christos 1; /* Dialog Token */ 1698 1.1 christos if (domain_name && domain_name_length) 1699 1.1 christos dscp_query_size += 1 + /* Element ID */ 1700 1.1 christos 1 + /* IE Length */ 1701 1.1 christos DOMAIN_NAME_OFFSET + domain_name_length; 1702 1.1 christos 1703 1.1 christos buf = wpabuf_alloc(dscp_query_size); 1704 1.1 christos if (!buf) { 1705 1.1 christos wpa_printf(MSG_ERROR, "QM: Failed to allocate DSCP query"); 1706 1.1 christos return -1; 1707 1.1 christos } 1708 1.1 christos 1709 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED); 1710 1.1 christos wpabuf_put_be32(buf, QM_ACTION_VENDOR_TYPE); 1711 1.1 christos wpabuf_put_u8(buf, QM_DSCP_POLICY_QUERY); 1712 1.1 christos wpa_s->dscp_query_dialog_token++; 1713 1.1 christos if (wpa_s->dscp_query_dialog_token == 0) 1714 1.1 christos wpa_s->dscp_query_dialog_token++; 1715 1.1 christos wpabuf_put_u8(buf, wpa_s->dscp_query_dialog_token); 1716 1.1 christos 1717 1.1 christos if (domain_name && domain_name_length) { 1718 1.1 christos /* Domain Name attribute */ 1719 1.1 christos wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 1720 1.1 christos wpabuf_put_u8(buf, DOMAIN_NAME_OFFSET + domain_name_length); 1721 1.1 christos wpabuf_put_be32(buf, QM_IE_VENDOR_TYPE); 1722 1.1 christos wpabuf_put_u8(buf, QM_ATTR_DOMAIN_NAME); 1723 1.1 christos wpabuf_put_u8(buf, domain_name_length); 1724 1.1 christos wpabuf_put_data(buf, domain_name, domain_name_length); 1725 1.1 christos } 1726 1.1 christos #undef DOMAIN_NAME_OFFSET 1727 1.1 christos 1728 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 1729 1.1 christos wpa_s->own_addr, wpa_s->bssid, 1730 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0); 1731 1.1 christos if (ret < 0) { 1732 1.1 christos wpa_dbg(wpa_s, MSG_ERROR, "QM: Failed to send DSCP query"); 1733 1.1 christos wpa_s->dscp_query_dialog_token--; 1734 1.1 christos } 1735 1.1 christos 1736 1.1 christos wpabuf_free(buf); 1737 1.1 christos return ret; 1738 1.1 christos } 1739