mbo_ap.c revision 57c2d39d85825f38c5fdac9b73bb0088406ffc85
157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt/* 257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * hostapd - MBO 357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * Copyright (c) 2016, Qualcomm Atheros, Inc. 457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * 557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * See README for more details. 757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt */ 857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "utils/includes.h" 1057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 1157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "utils/common.h" 1257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "common/ieee802_11_defs.h" 1357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "common/ieee802_11_common.h" 1457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "hostapd.h" 1557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "sta_info.h" 1657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#include "mbo_ap.h" 1757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 1857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 1957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtvoid mbo_ap_sta_free(struct sta_info *sta) 2057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 2157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt struct mbo_non_pref_chan_info *info, *prev; 2257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 2357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info = sta->non_pref_chan; 2457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt sta->non_pref_chan = NULL; 2557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt while (info) { 2657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt prev = info; 2757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info = info->next; 2857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt os_free(prev); 2957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 3057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 3157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 3257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 3357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtstatic void mbo_ap_parse_non_pref_chan(struct sta_info *sta, 3457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *buf, size_t len) 3557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 3657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt struct mbo_non_pref_chan_info *info, *tmp; 3757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt char channels[200], *pos, *end; 3857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt size_t num_chan, i; 3957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt int ret; 4057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 4157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (len <= 4) 4257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return; /* Not enough room for any channels */ 4357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 4457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt num_chan = len - 4; 4557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info = os_zalloc(sizeof(*info) + num_chan); 4657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (!info) 4757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return; 4857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info->op_class = buf[0]; 4957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info->pref = buf[len - 3]; 5057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info->reason_code = buf[len - 2]; 5157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info->reason_detail = buf[len - 1]; 5257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info->num_channels = num_chan; 5357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt buf++; 5457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt os_memcpy(info->channels, buf, num_chan); 5557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (!sta->non_pref_chan) { 5657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt sta->non_pref_chan = info; 5757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } else { 5857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt tmp = sta->non_pref_chan; 5957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt while (tmp->next) 6057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt tmp = tmp->next; 6157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt tmp->next = info; 6257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 6357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 6457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos = channels; 6557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt end = pos + sizeof(channels); 6657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *pos = '\0'; 6757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt for (i = 0; i < num_chan; i++) { 6857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%s%u", 6957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt i == 0 ? "" : " ", buf[i]); 7057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (os_snprintf_error(end - pos, ret)) { 7157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *pos = '\0'; 7257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 7357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 7457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos += ret; 7557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 7657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 7757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt wpa_printf(MSG_DEBUG, "MBO: STA " MACSTR 7857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt " non-preferred channel list (op class %u, pref %u, reason code %u, reason detail %u, channels %s)", 7957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt MAC2STR(sta->addr), info->op_class, info->pref, 8057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info->reason_code, info->reason_detail, channels); 8157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 8257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 8357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 8457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtvoid mbo_ap_check_sta_assoc(struct hostapd_data *hapd, struct sta_info *sta, 8557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt struct ieee802_11_elems *elems) 8657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 8757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *pos, *attr, *end; 8857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt size_t len; 8957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 9057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (!hapd->conf->mbo_enabled || !elems->mbo) 9157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return; 9257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 9357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos = elems->mbo + 4; 9457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt len = elems->mbo_len - 4; 9557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "MBO: Association Request attributes", pos, len); 9657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 9757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt attr = get_ie(pos, len, MBO_ATTR_ID_CELL_DATA_CAPA); 9857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (attr && attr[1] >= 1) 9957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt sta->cell_capa = attr[2]; 10057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 10157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt mbo_ap_sta_free(sta); 10257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt end = pos + len; 10357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt while (end - pos > 1) { 10457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt u8 ie_len = pos[1]; 10557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 10657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (2 + ie_len > end - pos) 10757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 10857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 10957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (pos[0] == MBO_ATTR_ID_NON_PREF_CHAN_REPORT) 11057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt mbo_ap_parse_non_pref_chan(sta, pos + 2, ie_len); 11157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos += 2 + pos[1]; 11257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 11357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 11457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 11557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 11657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtint mbo_ap_get_info(struct sta_info *sta, char *buf, size_t buflen) 11757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 11857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt char *pos = buf, *end = buf + buflen; 11957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt int ret; 12057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt struct mbo_non_pref_chan_info *info; 12157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt u8 i; 12257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt unsigned int count = 0; 12357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 12457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (!sta->cell_capa) 12557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return 0; 12657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 12757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ret = os_snprintf(pos, end - pos, "mbo_cell_capa=%u\n", sta->cell_capa); 12857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (os_snprintf_error(end - pos, ret)) 12957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return pos - buf; 13057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos += ret; 13157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 13257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt for (info = sta->non_pref_chan; info; info = info->next) { 13357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt char *pos2 = pos; 13457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 13557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ret = os_snprintf(pos2, end - pos2, 13657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt "non_pref_chan[%u]=%u:%u:%u:%u:", 13757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt count, info->op_class, info->pref, 13857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info->reason_code, info->reason_detail); 13957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt count++; 14057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (os_snprintf_error(end - pos2, ret)) 14157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 14257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos2 += ret; 14357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 14457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt for (i = 0; i < info->num_channels; i++) { 14557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ret = os_snprintf(pos2, end - pos2, "%u%s", 14657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt info->channels[i], 14757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt i + 1 < info->num_channels ? 14857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt "," : ""); 14957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (os_snprintf_error(end - pos2, ret)) { 15057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos2 = NULL; 15157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 15257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 15357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos2 += ret; 15457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 15557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 15657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (!pos2) 15757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 15857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ret = os_snprintf(pos2, end - pos2, "\n"); 15957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (os_snprintf_error(end - pos2, ret)) 16057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 16157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos2 += ret; 16257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos = pos2; 16357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 16457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 16557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return pos - buf; 16657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 16757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 16857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 16957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtstatic void mbo_ap_wnm_notif_req_cell_capa(struct sta_info *sta, 17057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *buf, size_t len) 17157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 17257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (len < 1) 17357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return; 17457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt wpa_printf(MSG_DEBUG, "MBO: STA " MACSTR 17557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt " updated cellular data capability: %u", 17657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt MAC2STR(sta->addr), buf[0]); 17757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt sta->cell_capa = buf[0]; 17857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 17957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 18057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 18157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtstatic void mbo_ap_wnm_notif_req_elem(struct sta_info *sta, u8 type, 18257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *buf, size_t len, 18357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt int *first_non_pref_chan) 18457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 18557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt switch (type) { 18657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt case WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT: 18757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (*first_non_pref_chan) { 18857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt /* 18957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * Need to free the previously stored entries now to 19057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * allow the update to replace all entries. 19157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt */ 19257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *first_non_pref_chan = 0; 19357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt mbo_ap_sta_free(sta); 19457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 19557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt mbo_ap_parse_non_pref_chan(sta, buf, len); 19657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 19757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt case WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA: 19857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt mbo_ap_wnm_notif_req_cell_capa(sta, buf, len); 19957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 20057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt default: 20157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt wpa_printf(MSG_DEBUG, 20257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt "MBO: Ignore unknown WNM Notification WFA subelement %u", 20357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt type); 20457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 20557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 20657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 20757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 20857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 20957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtvoid mbo_ap_wnm_notification_req(struct hostapd_data *hapd, const u8 *addr, 21057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *buf, size_t len) 21157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 21257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *pos, *end; 21357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt u8 ie_len; 21457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt struct sta_info *sta; 21557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt int first_non_pref_chan = 1; 21657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 21757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (!hapd->conf->mbo_enabled) 21857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return; 21957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 22057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt sta = ap_get_sta(hapd, addr); 22157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (!sta) 22257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return; 22357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 22457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos = buf; 22557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt end = buf + len; 22657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 22757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt while (end - pos > 1) { 22857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ie_len = pos[1]; 22957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 23057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (2 + ie_len > end - pos) 23157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt break; 23257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 23357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && 23457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt ie_len >= 4 && WPA_GET_BE24(pos + 2) == OUI_WFA) 23557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt mbo_ap_wnm_notif_req_elem(sta, pos[5], 23657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos + 6, ie_len - 4, 23757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt &first_non_pref_chan); 23857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt else 23957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt wpa_printf(MSG_DEBUG, 24057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt "MBO: Ignore unknown WNM Notification element %u (len=%u)", 24157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos[0], pos[1]); 24257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 24357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos += 2 + pos[1]; 24457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 24557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 246