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