]>
Commit | Line | Data |
---|---|---|
6fc6879b JM |
1 | /* |
2 | * hostapd / IEEE 802.11 authentication (ACL) | |
6226e38d | 3 | * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> |
6fc6879b JM |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License version 2 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * Alternatively, this software may be distributed under the terms of BSD | |
10 | * license. | |
11 | * | |
12 | * See README and COPYING for more details. | |
1c6e69cc JM |
13 | * |
14 | * Access control list for IEEE 802.11 authentication can uses statically | |
15 | * configured ACL from configuration files or an external RADIUS server. | |
16 | * Results from external RADIUS queries are cached to allow faster | |
17 | * authentication frame processing. | |
6fc6879b JM |
18 | */ |
19 | ||
6226e38d | 20 | #include "utils/includes.h" |
6fc6879b JM |
21 | |
22 | #ifndef CONFIG_NATIVE_WINDOWS | |
23 | ||
6226e38d JM |
24 | #include "utils/common.h" |
25 | #include "utils/eloop.h" | |
26 | #include "radius/radius.h" | |
27 | #include "radius/radius_client.h" | |
6fc6879b | 28 | #include "hostapd.h" |
6226e38d | 29 | #include "ap_config.h" |
6fc6879b JM |
30 | #include "ieee802_11.h" |
31 | #include "ieee802_11_auth.h" | |
6fc6879b JM |
32 | |
33 | #define RADIUS_ACL_TIMEOUT 30 | |
34 | ||
35 | ||
36 | struct hostapd_cached_radius_acl { | |
37 | time_t timestamp; | |
38 | macaddr addr; | |
39 | int accepted; /* HOSTAPD_ACL_* */ | |
40 | struct hostapd_cached_radius_acl *next; | |
41 | u32 session_timeout; | |
42 | u32 acct_interim_interval; | |
43 | int vlan_id; | |
44 | }; | |
45 | ||
46 | ||
47 | struct hostapd_acl_query_data { | |
48 | time_t timestamp; | |
49 | u8 radius_id; | |
50 | macaddr addr; | |
51 | u8 *auth_msg; /* IEEE 802.11 authentication frame from station */ | |
52 | size_t auth_msg_len; | |
53 | struct hostapd_acl_query_data *next; | |
54 | }; | |
55 | ||
56 | ||
f88bd288 | 57 | #ifndef CONFIG_NO_RADIUS |
6fc6879b JM |
58 | static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) |
59 | { | |
60 | struct hostapd_cached_radius_acl *prev; | |
61 | ||
62 | while (acl_cache) { | |
63 | prev = acl_cache; | |
64 | acl_cache = acl_cache->next; | |
65 | os_free(prev); | |
66 | } | |
67 | } | |
68 | ||
69 | ||
70 | static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, | |
71 | u32 *session_timeout, | |
72 | u32 *acct_interim_interval, int *vlan_id) | |
73 | { | |
74 | struct hostapd_cached_radius_acl *entry; | |
75 | time_t now; | |
76 | ||
77 | time(&now); | |
78 | entry = hapd->acl_cache; | |
79 | ||
80 | while (entry) { | |
81 | if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { | |
82 | if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) | |
83 | return -1; /* entry has expired */ | |
84 | if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT) | |
b6745143 CZ |
85 | if (session_timeout) |
86 | *session_timeout = | |
87 | entry->session_timeout; | |
88 | if (acct_interim_interval) | |
89 | *acct_interim_interval = | |
90 | entry->acct_interim_interval; | |
6fc6879b JM |
91 | if (vlan_id) |
92 | *vlan_id = entry->vlan_id; | |
93 | return entry->accepted; | |
94 | } | |
95 | ||
96 | entry = entry->next; | |
97 | } | |
98 | ||
99 | return -1; | |
100 | } | |
f88bd288 | 101 | #endif /* CONFIG_NO_RADIUS */ |
6fc6879b JM |
102 | |
103 | ||
104 | static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) | |
105 | { | |
106 | if (query == NULL) | |
107 | return; | |
108 | os_free(query->auth_msg); | |
109 | os_free(query); | |
110 | } | |
111 | ||
112 | ||
f88bd288 | 113 | #ifndef CONFIG_NO_RADIUS |
6fc6879b JM |
114 | static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, |
115 | struct hostapd_acl_query_data *query) | |
116 | { | |
117 | struct radius_msg *msg; | |
118 | char buf[128]; | |
119 | ||
120 | query->radius_id = radius_client_get_id(hapd->radius); | |
121 | msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); | |
122 | if (msg == NULL) | |
123 | return -1; | |
124 | ||
125 | radius_msg_make_authenticator(msg, addr, ETH_ALEN); | |
126 | ||
127 | os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); | |
128 | if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, | |
129 | os_strlen(buf))) { | |
130 | wpa_printf(MSG_DEBUG, "Could not add User-Name"); | |
131 | goto fail; | |
132 | } | |
133 | ||
134 | if (!radius_msg_add_attr_user_password( | |
135 | msg, (u8 *) buf, os_strlen(buf), | |
136 | hapd->conf->radius->auth_server->shared_secret, | |
137 | hapd->conf->radius->auth_server->shared_secret_len)) { | |
138 | wpa_printf(MSG_DEBUG, "Could not add User-Password"); | |
139 | goto fail; | |
140 | } | |
141 | ||
142 | if (hapd->conf->own_ip_addr.af == AF_INET && | |
143 | !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, | |
144 | (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { | |
145 | wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address"); | |
146 | goto fail; | |
147 | } | |
148 | ||
149 | #ifdef CONFIG_IPV6 | |
150 | if (hapd->conf->own_ip_addr.af == AF_INET6 && | |
151 | !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, | |
152 | (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { | |
153 | wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address"); | |
154 | goto fail; | |
155 | } | |
156 | #endif /* CONFIG_IPV6 */ | |
157 | ||
158 | if (hapd->conf->nas_identifier && | |
159 | !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, | |
160 | (u8 *) hapd->conf->nas_identifier, | |
161 | os_strlen(hapd->conf->nas_identifier))) { | |
162 | wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier"); | |
163 | goto fail; | |
164 | } | |
165 | ||
166 | os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", | |
167 | MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); | |
168 | if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, | |
169 | (u8 *) buf, os_strlen(buf))) { | |
170 | wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id"); | |
171 | goto fail; | |
172 | } | |
173 | ||
174 | os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, | |
175 | MAC2STR(addr)); | |
176 | if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, | |
177 | (u8 *) buf, os_strlen(buf))) { | |
178 | wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id"); | |
179 | goto fail; | |
180 | } | |
181 | ||
182 | if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, | |
183 | RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { | |
184 | wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type"); | |
185 | goto fail; | |
186 | } | |
187 | ||
188 | os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); | |
189 | if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, | |
190 | (u8 *) buf, os_strlen(buf))) { | |
191 | wpa_printf(MSG_DEBUG, "Could not add Connect-Info"); | |
192 | goto fail; | |
193 | } | |
194 | ||
195 | radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr); | |
196 | return 0; | |
197 | ||
198 | fail: | |
199 | radius_msg_free(msg); | |
6fc6879b JM |
200 | return -1; |
201 | } | |
f88bd288 | 202 | #endif /* CONFIG_NO_RADIUS */ |
6fc6879b JM |
203 | |
204 | ||
1c6e69cc JM |
205 | /** |
206 | * hostapd_allowed_address - Check whether a specified STA can be authenticated | |
207 | * @hapd: hostapd BSS data | |
208 | * @addr: MAC address of the STA | |
209 | * @msg: Authentication message | |
210 | * @len: Length of msg in octets | |
211 | * @session_timeout: Buffer for returning session timeout (from RADIUS) | |
212 | * @acct_interim_interval: Buffer for returning account interval (from RADIUS) | |
213 | * @vlan_id: Buffer for returning VLAN ID | |
214 | * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING | |
215 | */ | |
6fc6879b JM |
216 | int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, |
217 | const u8 *msg, size_t len, u32 *session_timeout, | |
218 | u32 *acct_interim_interval, int *vlan_id) | |
219 | { | |
b6745143 CZ |
220 | if (session_timeout) |
221 | *session_timeout = 0; | |
222 | if (acct_interim_interval) | |
223 | *acct_interim_interval = 0; | |
6fc6879b JM |
224 | if (vlan_id) |
225 | *vlan_id = 0; | |
226 | ||
227 | if (hostapd_maclist_found(hapd->conf->accept_mac, | |
271d2830 | 228 | hapd->conf->num_accept_mac, addr, vlan_id)) |
6fc6879b JM |
229 | return HOSTAPD_ACL_ACCEPT; |
230 | ||
231 | if (hostapd_maclist_found(hapd->conf->deny_mac, | |
271d2830 | 232 | hapd->conf->num_deny_mac, addr, vlan_id)) |
6fc6879b JM |
233 | return HOSTAPD_ACL_REJECT; |
234 | ||
235 | if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED) | |
236 | return HOSTAPD_ACL_ACCEPT; | |
237 | if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED) | |
238 | return HOSTAPD_ACL_REJECT; | |
239 | ||
240 | if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) { | |
f88bd288 JM |
241 | #ifdef CONFIG_NO_RADIUS |
242 | return HOSTAPD_ACL_REJECT; | |
243 | #else /* CONFIG_NO_RADIUS */ | |
6fc6879b JM |
244 | struct hostapd_acl_query_data *query; |
245 | ||
246 | /* Check whether ACL cache has an entry for this station */ | |
247 | int res = hostapd_acl_cache_get(hapd, addr, session_timeout, | |
248 | acct_interim_interval, | |
249 | vlan_id); | |
250 | if (res == HOSTAPD_ACL_ACCEPT || | |
251 | res == HOSTAPD_ACL_ACCEPT_TIMEOUT) | |
252 | return res; | |
253 | if (res == HOSTAPD_ACL_REJECT) | |
254 | return HOSTAPD_ACL_REJECT; | |
255 | ||
256 | query = hapd->acl_queries; | |
257 | while (query) { | |
258 | if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) { | |
259 | /* pending query in RADIUS retransmit queue; | |
260 | * do not generate a new one */ | |
261 | return HOSTAPD_ACL_PENDING; | |
262 | } | |
263 | query = query->next; | |
264 | } | |
265 | ||
266 | if (!hapd->conf->radius->auth_server) | |
267 | return HOSTAPD_ACL_REJECT; | |
268 | ||
269 | /* No entry in the cache - query external RADIUS server */ | |
270 | query = os_zalloc(sizeof(*query)); | |
271 | if (query == NULL) { | |
272 | wpa_printf(MSG_ERROR, "malloc for query data failed"); | |
273 | return HOSTAPD_ACL_REJECT; | |
274 | } | |
275 | time(&query->timestamp); | |
276 | os_memcpy(query->addr, addr, ETH_ALEN); | |
277 | if (hostapd_radius_acl_query(hapd, addr, query)) { | |
278 | wpa_printf(MSG_DEBUG, "Failed to send Access-Request " | |
279 | "for ACL query."); | |
280 | hostapd_acl_query_free(query); | |
281 | return HOSTAPD_ACL_REJECT; | |
282 | } | |
283 | ||
284 | query->auth_msg = os_malloc(len); | |
285 | if (query->auth_msg == NULL) { | |
286 | wpa_printf(MSG_ERROR, "Failed to allocate memory for " | |
287 | "auth frame."); | |
288 | hostapd_acl_query_free(query); | |
289 | return HOSTAPD_ACL_REJECT; | |
290 | } | |
291 | os_memcpy(query->auth_msg, msg, len); | |
292 | query->auth_msg_len = len; | |
293 | query->next = hapd->acl_queries; | |
294 | hapd->acl_queries = query; | |
295 | ||
296 | /* Queued data will be processed in hostapd_acl_recv_radius() | |
297 | * when RADIUS server replies to the sent Access-Request. */ | |
298 | return HOSTAPD_ACL_PENDING; | |
f88bd288 | 299 | #endif /* CONFIG_NO_RADIUS */ |
6fc6879b JM |
300 | } |
301 | ||
302 | return HOSTAPD_ACL_REJECT; | |
303 | } | |
304 | ||
305 | ||
f88bd288 | 306 | #ifndef CONFIG_NO_RADIUS |
6fc6879b JM |
307 | static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now) |
308 | { | |
309 | struct hostapd_cached_radius_acl *prev, *entry, *tmp; | |
310 | ||
311 | prev = NULL; | |
312 | entry = hapd->acl_cache; | |
313 | ||
314 | while (entry) { | |
315 | if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) { | |
316 | wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR | |
317 | " has expired.", MAC2STR(entry->addr)); | |
318 | if (prev) | |
319 | prev->next = entry->next; | |
320 | else | |
321 | hapd->acl_cache = entry->next; | |
6affdaee | 322 | #ifdef CONFIG_DRIVER_RADIUS_ACL |
2f3e0bd4 | 323 | hapd->drv.set_radius_acl_expire(hapd, entry->addr); |
6affdaee | 324 | #endif /* CONFIG_DRIVER_RADIUS_ACL */ |
6fc6879b JM |
325 | tmp = entry; |
326 | entry = entry->next; | |
327 | os_free(tmp); | |
328 | continue; | |
329 | } | |
330 | ||
331 | prev = entry; | |
332 | entry = entry->next; | |
333 | } | |
334 | } | |
335 | ||
336 | ||
337 | static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now) | |
338 | { | |
339 | struct hostapd_acl_query_data *prev, *entry, *tmp; | |
340 | ||
341 | prev = NULL; | |
342 | entry = hapd->acl_queries; | |
343 | ||
344 | while (entry) { | |
345 | if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) { | |
346 | wpa_printf(MSG_DEBUG, "ACL query for " MACSTR | |
347 | " has expired.", MAC2STR(entry->addr)); | |
348 | if (prev) | |
349 | prev->next = entry->next; | |
350 | else | |
351 | hapd->acl_queries = entry->next; | |
352 | ||
353 | tmp = entry; | |
354 | entry = entry->next; | |
355 | hostapd_acl_query_free(tmp); | |
356 | continue; | |
357 | } | |
358 | ||
359 | prev = entry; | |
360 | entry = entry->next; | |
361 | } | |
362 | } | |
363 | ||
364 | ||
1c6e69cc JM |
365 | /** |
366 | * hostapd_acl_expire - ACL cache expiration callback | |
367 | * @eloop_ctx: struct hostapd_data * | |
368 | * @timeout_ctx: Not used | |
369 | */ | |
6fc6879b JM |
370 | static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx) |
371 | { | |
372 | struct hostapd_data *hapd = eloop_ctx; | |
373 | time_t now; | |
374 | ||
375 | time(&now); | |
376 | hostapd_acl_expire_cache(hapd, now); | |
377 | hostapd_acl_expire_queries(hapd, now); | |
378 | ||
379 | eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); | |
380 | } | |
381 | ||
382 | ||
1c6e69cc JM |
383 | /** |
384 | * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages | |
385 | * @msg: RADIUS response message | |
386 | * @req: RADIUS request message | |
387 | * @shared_secret: RADIUS shared secret | |
388 | * @shared_secret_len: Length of shared_secret in octets | |
389 | * @data: Context data (struct hostapd_data *) | |
390 | * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and | |
391 | * was processed here) or RADIUS_RX_UNKNOWN if not. | |
392 | */ | |
6fc6879b JM |
393 | static RadiusRxResult |
394 | hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, | |
7d02e641 | 395 | const u8 *shared_secret, size_t shared_secret_len, |
6fc6879b JM |
396 | void *data) |
397 | { | |
398 | struct hostapd_data *hapd = data; | |
399 | struct hostapd_acl_query_data *query, *prev; | |
400 | struct hostapd_cached_radius_acl *cache; | |
1489e11a | 401 | struct radius_hdr *hdr = radius_msg_get_hdr(msg); |
6fc6879b JM |
402 | |
403 | query = hapd->acl_queries; | |
404 | prev = NULL; | |
405 | while (query) { | |
1489e11a | 406 | if (query->radius_id == hdr->identifier) |
6fc6879b JM |
407 | break; |
408 | prev = query; | |
409 | query = query->next; | |
410 | } | |
411 | if (query == NULL) | |
412 | return RADIUS_RX_UNKNOWN; | |
413 | ||
414 | wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS " | |
415 | "message (id=%d)", query->radius_id); | |
416 | ||
417 | if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { | |
418 | wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have " | |
419 | "correct authenticator - dropped\n"); | |
420 | return RADIUS_RX_INVALID_AUTHENTICATOR; | |
421 | } | |
422 | ||
1489e11a JM |
423 | if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && |
424 | hdr->code != RADIUS_CODE_ACCESS_REJECT) { | |
6fc6879b | 425 | wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL " |
1489e11a | 426 | "query", hdr->code); |
6fc6879b JM |
427 | return RADIUS_RX_UNKNOWN; |
428 | } | |
429 | ||
430 | /* Insert Accept/Reject info into ACL cache */ | |
431 | cache = os_zalloc(sizeof(*cache)); | |
432 | if (cache == NULL) { | |
433 | wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry"); | |
434 | goto done; | |
435 | } | |
436 | time(&cache->timestamp); | |
437 | os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); | |
1489e11a | 438 | if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { |
6fc6879b JM |
439 | if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, |
440 | &cache->session_timeout) == 0) | |
441 | cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; | |
442 | else | |
443 | cache->accepted = HOSTAPD_ACL_ACCEPT; | |
444 | ||
445 | if (radius_msg_get_attr_int32( | |
446 | msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, | |
447 | &cache->acct_interim_interval) == 0 && | |
448 | cache->acct_interim_interval < 60) { | |
449 | wpa_printf(MSG_DEBUG, "Ignored too small " | |
450 | "Acct-Interim-Interval %d for STA " MACSTR, | |
451 | cache->acct_interim_interval, | |
452 | MAC2STR(query->addr)); | |
453 | cache->acct_interim_interval = 0; | |
454 | } | |
455 | ||
456 | cache->vlan_id = radius_msg_get_vlanid(msg); | |
457 | } else | |
458 | cache->accepted = HOSTAPD_ACL_REJECT; | |
459 | cache->next = hapd->acl_cache; | |
460 | hapd->acl_cache = cache; | |
461 | ||
6affdaee | 462 | #ifdef CONFIG_DRIVER_RADIUS_ACL |
2f3e0bd4 JM |
463 | hapd->drv.set_radius_acl_auth(hapd, query->addr, cache->accepted, |
464 | cache->session_timeout); | |
6affdaee | 465 | #else /* CONFIG_DRIVER_RADIUS_ACL */ |
fe6bdb77 | 466 | #ifdef NEED_AP_MLME |
6fc6879b JM |
467 | /* Re-send original authentication frame for 802.11 processing */ |
468 | wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " | |
469 | "successful RADIUS ACL query"); | |
f8b1f695 | 470 | ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL); |
fe6bdb77 | 471 | #endif /* NEED_AP_MLME */ |
6affdaee | 472 | #endif /* CONFIG_DRIVER_RADIUS_ACL */ |
6fc6879b JM |
473 | |
474 | done: | |
475 | if (prev == NULL) | |
476 | hapd->acl_queries = query->next; | |
477 | else | |
478 | prev->next = query->next; | |
479 | ||
480 | hostapd_acl_query_free(query); | |
481 | ||
482 | return RADIUS_RX_PROCESSED; | |
483 | } | |
f88bd288 | 484 | #endif /* CONFIG_NO_RADIUS */ |
6fc6879b JM |
485 | |
486 | ||
1c6e69cc JM |
487 | /** |
488 | * hostapd_acl_init: Initialize IEEE 802.11 ACL | |
489 | * @hapd: hostapd BSS data | |
490 | * Returns: 0 on success, -1 on failure | |
491 | */ | |
6fc6879b JM |
492 | int hostapd_acl_init(struct hostapd_data *hapd) |
493 | { | |
f88bd288 | 494 | #ifndef CONFIG_NO_RADIUS |
6fc6879b JM |
495 | if (radius_client_register(hapd->radius, RADIUS_AUTH, |
496 | hostapd_acl_recv_radius, hapd)) | |
497 | return -1; | |
498 | ||
499 | eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); | |
f88bd288 | 500 | #endif /* CONFIG_NO_RADIUS */ |
6fc6879b JM |
501 | |
502 | return 0; | |
503 | } | |
504 | ||
505 | ||
1c6e69cc JM |
506 | /** |
507 | * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL | |
508 | * @hapd: hostapd BSS data | |
509 | */ | |
6fc6879b JM |
510 | void hostapd_acl_deinit(struct hostapd_data *hapd) |
511 | { | |
512 | struct hostapd_acl_query_data *query, *prev; | |
513 | ||
f88bd288 | 514 | #ifndef CONFIG_NO_RADIUS |
6fc6879b JM |
515 | eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL); |
516 | ||
517 | hostapd_acl_cache_free(hapd->acl_cache); | |
f88bd288 | 518 | #endif /* CONFIG_NO_RADIUS */ |
6fc6879b JM |
519 | |
520 | query = hapd->acl_queries; | |
521 | while (query) { | |
522 | prev = query; | |
523 | query = query->next; | |
524 | hostapd_acl_query_free(prev); | |
525 | } | |
526 | } | |
527 | ||
6fc6879b | 528 | #endif /* CONFIG_NATIVE_WINDOWS */ |