18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / AP table 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2004, Instant802 Networks, Inc. 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006, Devicescape Software, Inc. 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 8c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sta_info.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "beacon.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_list.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* AP list is a double linked list with head->prev pointing to the end of the 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * list and tail->next = NULL. Entries are moved to the head of the list 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * whenever a beacon has been received from the AP in question. The tail entry 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in this link will thus be the least recently used entry. */ 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35ed003d2a93648e6201272d2fb8212cbc01085928Dmitry Shmidt if (iface->current_mode == NULL || 36ed003d2a93648e6201272d2fb8212cbc01085928Dmitry Shmidt iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G || 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel != ap->channel) 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->erp != -1 && (ap->erp & ERP_INFO_NON_ERP_PRESENT)) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) { 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rate = (ap->supported_rates[i] & 0x7f) * 5; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rate == 60 || rate == 90 || rate > 110) 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidtstatic struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap) 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ap_info *s; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = iface->ap_hash[STA_HASH(ap)]; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0) 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = s->hnext; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return s; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_ap_list_add(struct hostapd_iface *iface, struct ap_info *ap) 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->ap_list) { 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->prev = iface->ap_list->prev; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ap_list->prev = ap; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->prev = ap; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->next = iface->ap_list; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ap_list = ap; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_ap_list_del(struct hostapd_iface *iface, struct ap_info *ap) 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->ap_list == ap) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ap_list = ap->next; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->prev->next = ap->next; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap->next) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->next->prev = ap->prev; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (iface->ap_list) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ap_list->prev = ap->prev; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_ap_hash_add(struct hostapd_iface *iface, struct ap_info *ap) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->hnext = iface->ap_hash[STA_HASH(ap->addr)]; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ap_hash[STA_HASH(ap->addr)] = ap; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_ap_hash_del(struct hostapd_iface *iface, struct ap_info *ap) 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ap_info *s; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = iface->ap_hash[STA_HASH(ap->addr)]; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) return; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) { 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ap_hash[STA_HASH(ap->addr)] = s->hnext; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (s->hnext != NULL && 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0) 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = s->hnext; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s->hnext != NULL) 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s->hnext = s->hnext->hnext; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("AP: could not remove AP " MACSTR " from hash table\n", 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(ap->addr)); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_free_ap(struct hostapd_iface *iface, struct ap_info *ap) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_ap_hash_del(iface, ap); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_ap_list_del(iface, ap); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->num_ap--; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ap); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_free_aps(struct hostapd_iface *iface) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ap_info *ap, *prev; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = iface->ap_list; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ap) { 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = ap; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = ap->next; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_free_ap(iface, prev); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->ap_list = NULL; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ap_info *ap; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = os_zalloc(sizeof(struct ap_info)); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap == NULL) 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* initialize AP info data */ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ap->addr, addr, ETH_ALEN); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_ap_list_add(iface, ap); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->num_ap++; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_ap_hash_add(iface, ap); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) { 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Removing the least recently used AP " 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " from AP table", MAC2STR(ap->prev->addr)); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_free_ap(iface, ap->prev); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ap; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_list_process_beacon(struct hostapd_iface *iface, 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ieee80211_mgmt *mgmt, 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_11_elems *elems, 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_frame_info *fi) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ap_info *ap; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int new_ap = 0; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int set_beacon = 0; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->conf->ap_table_max_size < 1) 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = ap_get_ap(iface, mgmt->bssid); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ap) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = ap_ap_add(iface, mgmt->bssid); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ap) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Failed to allocate AP information entry\n"); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_ap = 1; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt merge_byte_arrays(ap->supported_rates, WLAN_SUPP_RATES_MAX, 19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt elems->supp_rates, elems->supp_rates_len, 19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt elems->ext_supp_rates, elems->ext_supp_rates_len); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (elems->erp_info && elems->erp_info_len == 1) 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->erp = elems->erp_info[0]; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->erp = -1; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (elems->ds_params && elems->ds_params_len == 1) 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->channel = elems->ds_params[0]; 202444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt else if (elems->ht_operation && elems->ht_operation_len >= 1) 203444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt ap->channel = elems->ht_operation[0]; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (fi) 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->channel = fi->channel; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (elems->ht_capabilities) 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->ht_support = 1; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->ht_support = 0; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt os_get_reltime(&ap->last_beacon); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!new_ap && ap != iface->ap_list) { 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* move AP entry into the beginning of the list so that the 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * oldest entry is always in the end of the list */ 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_ap_list_del(iface, ap); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_ap_list_add(iface, ap); 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->olbc && 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_list_beacon_olbc(iface, ap)) { 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->olbc = 1; 224444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR 225444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt " (channel %d) - enable protection", 226444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt MAC2STR(ap->addr), ap->channel); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_beacon++; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211N 231444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (!iface->olbc_ht && !ap->ht_support && 232444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt (ap->channel == 0 || 233444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt ap->channel == iface->conf->channel || 234444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt ap->channel == iface->conf->channel + 235444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt iface->conf->secondary_channel * 4)) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->olbc_ht = 1; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_ht_operation_update(iface); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR 239444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt " (channel %d) - enable protection", 240444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt MAC2STR(ap->addr), ap->channel); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_beacon++; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211N */ 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (set_beacon) 24604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee802_11_update_beacons(iface); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_list_timer(void *eloop_ctx, void *timeout_ctx) 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_iface *iface = eloop_ctx; 25304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt struct os_reltime now; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ap_info *ap; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int set_beacon = 0; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(10, 0, ap_list_timer, iface, NULL); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->ap_list) 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt os_get_reltime(&now); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (iface->ap_list) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = iface->ap_list->prev; 26604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!os_reltime_expired(&now, &ap->last_beacon, 26704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->ap_table_expiration_time)) 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_free_ap(iface, ap); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->olbc || iface->olbc_ht) { 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int olbc = 0; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int olbc_ht = 0; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = iface->ap_list; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ap && (olbc == 0 || olbc_ht == 0)) { 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap_list_beacon_olbc(iface, ap)) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt olbc = 1; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ap->ht_support) 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt olbc_ht = 1; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = ap->next; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!olbc && iface->olbc) { 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "OLBC not detected anymore"); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->olbc = 0; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_beacon++; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211N 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!olbc_ht && iface->olbc_ht) { 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->olbc_ht = 0; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_ht_operation_update(iface); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_beacon++; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211N */ 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (set_beacon) 30104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee802_11_update_beacons(iface); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ap_list_init(struct hostapd_iface *iface) 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(10, 0, ap_list_timer, iface, NULL); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_list_deinit(struct hostapd_iface *iface) 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(ap_list_timer, iface, NULL); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_free_aps(iface); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 317