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 114216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_printf(MSG_INFO, "AP: could not remove AP " MACSTR 115216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt " from hash table", 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) { 185216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_printf(MSG_INFO, 186216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Failed to allocate AP information entry"); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_ap = 1; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt merge_byte_arrays(ap->supported_rates, WLAN_SUPP_RATES_MAX, 19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt elems->supp_rates, elems->supp_rates_len, 19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt elems->ext_supp_rates, elems->ext_supp_rates_len); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1969d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt if (elems->erp_info) 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->erp = elems->erp_info[0]; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->erp = -1; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2019d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt if (elems->ds_params) 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->channel = elems->ds_params[0]; 2039d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt else if (elems->ht_operation) 204444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt ap->channel = elems->ht_operation[0]; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (fi) 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->channel = fi->channel; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (elems->ht_capabilities) 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->ht_support = 1; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap->ht_support = 0; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt os_get_reltime(&ap->last_beacon); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!new_ap && ap != iface->ap_list) { 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* move AP entry into the beginning of the list so that the 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * oldest entry is always in the end of the list */ 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_ap_list_del(iface, ap); 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_ap_list_add(iface, ap); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->olbc && 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_list_beacon_olbc(iface, ap)) { 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->olbc = 1; 225444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR 226444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt " (channel %d) - enable protection", 227444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt MAC2STR(ap->addr), ap->channel); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_beacon++; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211N 232444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (!iface->olbc_ht && !ap->ht_support && 233444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt (ap->channel == 0 || 234444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt ap->channel == iface->conf->channel || 235444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt ap->channel == iface->conf->channel + 236444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt iface->conf->secondary_channel * 4)) { 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->olbc_ht = 1; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_ht_operation_update(iface); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR 240444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt " (channel %d) - enable protection", 241444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt MAC2STR(ap->addr), ap->channel); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_beacon++; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211N */ 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (set_beacon) 24704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee802_11_update_beacons(iface); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 251d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtvoid ap_list_timer(struct hostapd_iface *iface) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt struct os_reltime now; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ap_info *ap; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int set_beacon = 0; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->ap_list) 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt os_get_reltime(&now); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (iface->ap_list) { 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = iface->ap_list->prev; 26404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!os_reltime_expired(&now, &ap->last_beacon, 26504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->ap_table_expiration_time)) 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_free_ap(iface, ap); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->olbc || iface->olbc_ht) { 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int olbc = 0; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int olbc_ht = 0; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = iface->ap_list; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ap && (olbc == 0 || olbc_ht == 0)) { 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap_list_beacon_olbc(iface, ap)) 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt olbc = 1; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ap->ht_support) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt olbc_ht = 1; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap = ap->next; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!olbc && iface->olbc) { 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "OLBC not detected anymore"); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->olbc = 0; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_beacon++; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211N 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!olbc_ht && iface->olbc_ht) { 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->olbc_ht = 0; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_ht_operation_update(iface); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_beacon++; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211N */ 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (set_beacon) 29904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee802_11_update_beacons(iface); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ap_list_init(struct hostapd_iface *iface) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_list_deinit(struct hostapd_iface *iface) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_free_aps(iface); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 313