]>
git.ipfire.org Git - thirdparty/hostap.git/blob - src/ap/ap_list.c
3 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2003-2004, Instant802 Networks, Inc.
5 * Copyright (c) 2006, Devicescape Software, Inc.
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
11 #include "utils/includes.h"
13 #include "utils/common.h"
14 #include "utils/eloop.h"
15 #include "common/ieee802_11_defs.h"
16 #include "common/ieee802_11_common.h"
18 #include "ap_config.h"
19 #include "ieee802_11.h"
25 /* AP list is a double linked list with head->prev pointing to the end of the
26 * list and tail->next = NULL. Entries are moved to the head of the list
27 * whenever a beacon has been received from the AP in question. The tail entry
28 * in this link will thus be the least recently used entry. */
31 static int ap_list_beacon_olbc(struct hostapd_iface
*iface
, struct ap_info
*ap
)
35 if (iface
->current_mode
== NULL
||
36 iface
->current_mode
->mode
!= HOSTAPD_MODE_IEEE80211G
||
37 iface
->conf
->channel
!= ap
->channel
)
40 if (ap
->erp
!= -1 && (ap
->erp
& ERP_INFO_NON_ERP_PRESENT
))
43 for (i
= 0; i
< WLAN_SUPP_RATES_MAX
; i
++) {
44 int rate
= (ap
->supported_rates
[i
] & 0x7f) * 5;
45 if (rate
== 60 || rate
== 90 || rate
> 110)
53 static struct ap_info
* ap_get_ap(struct hostapd_iface
*iface
, const u8
*ap
)
57 s
= iface
->ap_hash
[STA_HASH(ap
)];
58 while (s
!= NULL
&& os_memcmp(s
->addr
, ap
, ETH_ALEN
) != 0)
64 static void ap_ap_list_add(struct hostapd_iface
*iface
, struct ap_info
*ap
)
67 ap
->prev
= iface
->ap_list
->prev
;
68 iface
->ap_list
->prev
= ap
;
71 ap
->next
= iface
->ap_list
;
76 static void ap_ap_list_del(struct hostapd_iface
*iface
, struct ap_info
*ap
)
78 if (iface
->ap_list
== ap
)
79 iface
->ap_list
= ap
->next
;
81 ap
->prev
->next
= ap
->next
;
84 ap
->next
->prev
= ap
->prev
;
85 else if (iface
->ap_list
)
86 iface
->ap_list
->prev
= ap
->prev
;
90 static void ap_ap_hash_add(struct hostapd_iface
*iface
, struct ap_info
*ap
)
92 ap
->hnext
= iface
->ap_hash
[STA_HASH(ap
->addr
)];
93 iface
->ap_hash
[STA_HASH(ap
->addr
)] = ap
;
97 static void ap_ap_hash_del(struct hostapd_iface
*iface
, struct ap_info
*ap
)
101 s
= iface
->ap_hash
[STA_HASH(ap
->addr
)];
102 if (s
== NULL
) return;
103 if (os_memcmp(s
->addr
, ap
->addr
, ETH_ALEN
) == 0) {
104 iface
->ap_hash
[STA_HASH(ap
->addr
)] = s
->hnext
;
108 while (s
->hnext
!= NULL
&&
109 os_memcmp(s
->hnext
->addr
, ap
->addr
, ETH_ALEN
) != 0)
111 if (s
->hnext
!= NULL
)
112 s
->hnext
= s
->hnext
->hnext
;
114 wpa_printf(MSG_INFO
, "AP: could not remove AP " MACSTR
115 " from hash table", MAC2STR(ap
->addr
));
119 static void ap_free_ap(struct hostapd_iface
*iface
, struct ap_info
*ap
)
121 ap_ap_hash_del(iface
, ap
);
122 ap_ap_list_del(iface
, ap
);
129 static void hostapd_free_aps(struct hostapd_iface
*iface
)
131 struct ap_info
*ap
, *prev
;
138 ap_free_ap(iface
, prev
);
141 iface
->ap_list
= NULL
;
145 static struct ap_info
* ap_ap_add(struct hostapd_iface
*iface
, const u8
*addr
)
149 ap
= os_zalloc(sizeof(struct ap_info
));
153 /* initialize AP info data */
154 os_memcpy(ap
->addr
, addr
, ETH_ALEN
);
155 ap_ap_list_add(iface
, ap
);
157 ap_ap_hash_add(iface
, ap
);
159 if (iface
->num_ap
> iface
->conf
->ap_table_max_size
&& ap
!= ap
->prev
) {
160 wpa_printf(MSG_DEBUG
, "Removing the least recently used AP "
161 MACSTR
" from AP table", MAC2STR(ap
->prev
->addr
));
162 ap_free_ap(iface
, ap
->prev
);
169 void ap_list_process_beacon(struct hostapd_iface
*iface
,
170 const struct ieee80211_mgmt
*mgmt
,
171 struct ieee802_11_elems
*elems
,
172 struct hostapd_frame_info
*fi
)
178 if (iface
->conf
->ap_table_max_size
< 1)
181 ap
= ap_get_ap(iface
, mgmt
->bssid
);
183 ap
= ap_ap_add(iface
, mgmt
->bssid
);
186 "Failed to allocate AP information entry");
192 merge_byte_arrays(ap
->supported_rates
, WLAN_SUPP_RATES_MAX
,
193 elems
->supp_rates
, elems
->supp_rates_len
,
194 elems
->ext_supp_rates
, elems
->ext_supp_rates_len
);
197 ap
->erp
= elems
->erp_info
[0];
201 if (elems
->ds_params
)
202 ap
->channel
= elems
->ds_params
[0];
203 else if (elems
->ht_operation
)
204 ap
->channel
= elems
->ht_operation
[0];
206 ap
->channel
= fi
->channel
;
208 if (elems
->ht_capabilities
)
213 os_get_reltime(&ap
->last_beacon
);
215 if (!new_ap
&& ap
!= iface
->ap_list
) {
216 /* move AP entry into the beginning of the list so that the
217 * oldest entry is always in the end of the list */
218 ap_ap_list_del(iface
, ap
);
219 ap_ap_list_add(iface
, ap
);
223 ap_list_beacon_olbc(iface
, ap
)) {
225 wpa_printf(MSG_DEBUG
, "OLBC AP detected: " MACSTR
226 " (channel %d) - enable protection",
227 MAC2STR(ap
->addr
), ap
->channel
);
231 #ifdef CONFIG_IEEE80211N
232 if (!iface
->olbc_ht
&& !ap
->ht_support
&&
234 ap
->channel
== iface
->conf
->channel
||
235 ap
->channel
== iface
->conf
->channel
+
236 iface
->conf
->secondary_channel
* 4)) {
238 hostapd_ht_operation_update(iface
);
239 wpa_printf(MSG_DEBUG
, "OLBC HT AP detected: " MACSTR
240 " (channel %d) - enable protection",
241 MAC2STR(ap
->addr
), ap
->channel
);
244 #endif /* CONFIG_IEEE80211N */
247 ieee802_11_update_beacons(iface
);
251 void ap_list_timer(struct hostapd_iface
*iface
)
253 struct os_reltime now
;
260 os_get_reltime(&now
);
262 while (iface
->ap_list
) {
263 ap
= iface
->ap_list
->prev
;
264 if (!os_reltime_expired(&now
, &ap
->last_beacon
,
265 iface
->conf
->ap_table_expiration_time
))
268 ap_free_ap(iface
, ap
);
271 if (iface
->olbc
|| iface
->olbc_ht
) {
276 while (ap
&& (olbc
== 0 || olbc_ht
== 0)) {
277 if (ap_list_beacon_olbc(iface
, ap
))
283 if (!olbc
&& iface
->olbc
) {
284 wpa_printf(MSG_DEBUG
, "OLBC not detected anymore");
288 #ifdef CONFIG_IEEE80211N
289 if (!olbc_ht
&& iface
->olbc_ht
) {
290 wpa_printf(MSG_DEBUG
, "OLBC HT not detected anymore");
292 hostapd_ht_operation_update(iface
);
295 #endif /* CONFIG_IEEE80211N */
299 ieee802_11_update_beacons(iface
);
303 int ap_list_init(struct hostapd_iface
*iface
)
309 void ap_list_deinit(struct hostapd_iface
*iface
)
311 hostapd_free_aps(iface
);