]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/ap/hostapd.c
Rename some src/ap files to avoid duplicate file names
[thirdparty/hostap.git] / src / ap / hostapd.c
CommitLineData
6fc6879b
JM
1/*
2 * hostapd / Initialization and configuration
6f78f2fb 3 * Copyright (c) 2002-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.
13 */
14
6226e38d 15#include "utils/includes.h"
6fc6879b 16
6226e38d
JM
17#include "utils/common.h"
18#include "utils/eloop.h"
03da66bd 19#include "common/ieee802_11_defs.h"
03da66bd 20#include "radius/radius_client.h"
6226e38d
JM
21#include "hostapd.h"
22#include "authsrv.h"
23#include "sta_info.h"
24#include "accounting.h"
25#include "ap_list.h"
26#include "beacon.h"
27#include "iapp.h"
28#include "ieee802_1x.h"
29#include "ieee802_11_auth.h"
30#include "vlan_init.h"
31#include "wpa_auth.h"
32#include "wps_hostapd.h"
6fc6879b 33#include "hw_features.h"
bfddd95c 34#include "driver_i.h"
c442055e 35#include "wpa_auth_glue.h"
a4f21109 36#include "ap_drv_ops.h"
6fc6879b
JM
37
38
ad08c363 39static int hostapd_flush_old_stations(struct hostapd_data *hapd);
ad08c363 40static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
6fc6879b 41
6fc6879b 42extern int wpa_debug_level;
6fc6879b 43
6fc6879b 44
ad08c363
JM
45int hostapd_reload_config(struct hostapd_iface *iface)
46{
47 struct hostapd_data *hapd = iface->bss[0];
48 struct hostapd_config *newconf, *oldconf;
c213cc04 49 size_t j;
ad08c363 50
41d719d6
JM
51 if (iface->config_read_cb == NULL)
52 return -1;
53 newconf = iface->config_read_cb(iface->config_fname);
ad08c363
JM
54 if (newconf == NULL)
55 return -1;
56
57 /*
58 * Deauthenticate all stations since the new configuration may not
59 * allow them to use the BSS anymore.
60 */
c213cc04
JM
61 for (j = 0; j < iface->num_bss; j++)
62 hostapd_flush_old_stations(iface->bss[j]);
ad08c363 63
74784010 64#ifndef CONFIG_NO_RADIUS
ad08c363
JM
65 /* TODO: update dynamic data based on changed configuration
66 * items (e.g., open/close sockets, etc.) */
67 radius_client_flush(hapd->radius, 0);
74784010 68#endif /* CONFIG_NO_RADIUS */
ad08c363
JM
69
70 oldconf = hapd->iconf;
71 hapd->iconf = newconf;
72 hapd->conf = &newconf->bss[0];
73 iface->conf = newconf;
74
75 if (hostapd_setup_wpa_psk(hapd->conf)) {
76 wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
77 "after reloading configuration");
78 }
79
80 if (hapd->conf->wpa && hapd->wpa_auth == NULL)
81 hostapd_setup_wpa(hapd);
c442055e
JM
82 else if (hapd->conf->wpa)
83 hostapd_reconfig_wpa(hapd);
84 else if (hapd->wpa_auth) {
ad08c363
JM
85 wpa_deinit(hapd->wpa_auth);
86 hapd->wpa_auth = NULL;
87 hostapd_set_privacy(hapd, 0);
88 hostapd_setup_encryption(hapd->conf->iface, hapd);
89 }
90
91 ieee802_11_set_beacon(hapd);
92
c813b695
JM
93 if (hapd->conf->ssid.ssid_set &&
94 hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid,
95 hapd->conf->ssid.ssid_len)) {
96 wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
97 /* try to continue */
98 }
99
100 if (hapd->conf->ieee802_1x || hapd->conf->wpa)
010401fe 101 hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
e3bd3912 102 else
010401fe 103 hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
c813b695 104
ad08c363
JM
105 hostapd_config_free(oldconf);
106
107 wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
108
109 return 0;
110}
111
112
6fc6879b
JM
113static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
114 char *ifname)
115{
116 int i;
117
118 for (i = 0; i < NUM_WEP_KEYS; i++) {
45cefa0b
JM
119 if (hapd->drv.set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
120 i == 0 ? 1 : 0, NULL, 0, NULL, 0)) {
bb305cbd
JM
121 wpa_printf(MSG_DEBUG, "Failed to clear default "
122 "encryption keys (ifname=%s keyidx=%d)",
123 ifname, i);
6fc6879b
JM
124 }
125 }
1aa5c134
JM
126#ifdef CONFIG_IEEE80211W
127 if (hapd->conf->ieee80211w) {
128 for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
45cefa0b
JM
129 if (hapd->drv.set_key(ifname, hapd, WPA_ALG_NONE, NULL,
130 i, i == 0 ? 1 : 0, NULL, 0,
131 NULL, 0)) {
bb305cbd
JM
132 wpa_printf(MSG_DEBUG, "Failed to clear "
133 "default mgmt encryption keys "
134 "(ifname=%s keyidx=%d)", ifname, i);
1aa5c134
JM
135 }
136 }
137 }
138#endif /* CONFIG_IEEE80211W */
6fc6879b
JM
139}
140
141
142static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
143{
144 hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface);
145 return 0;
146}
147
148
149static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
150{
151 int errors = 0, idx;
152 struct hostapd_ssid *ssid = &hapd->conf->ssid;
153
154 idx = ssid->wep.idx;
155 if (ssid->wep.default_len &&
45cefa0b
JM
156 hapd->drv.set_key(hapd->conf->iface,
157 hapd, WPA_ALG_WEP, NULL, idx,
158 idx == ssid->wep.idx,
159 NULL, 0, ssid->wep.key[idx],
160 ssid->wep.len[idx])) {
bb305cbd 161 wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
6fc6879b
JM
162 errors++;
163 }
164
165 if (ssid->dyn_vlan_keys) {
166 size_t i;
167 for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
168 const char *ifname;
169 struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i];
170 if (key == NULL)
171 continue;
172 ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan,
173 i);
174 if (ifname == NULL)
175 continue;
176
177 idx = key->idx;
45cefa0b
JM
178 if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL,
179 idx, idx == key->idx, NULL, 0,
180 key->key[idx], key->len[idx])) {
bb305cbd
JM
181 wpa_printf(MSG_WARNING, "Could not set "
182 "dynamic VLAN WEP encryption.");
6fc6879b
JM
183 errors++;
184 }
185 }
186 }
187
188 return errors;
189}
190
191/**
192 * hostapd_cleanup - Per-BSS cleanup (deinitialization)
193 * @hapd: Pointer to BSS data
194 *
195 * This function is used to free all per-BSS data structures and resources.
196 * This gets called in a loop for each BSS between calls to
197 * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
198 * is deinitialized. Most of the modules that are initialized in
199 * hostapd_setup_bss() are deinitialized here.
200 */
201static void hostapd_cleanup(struct hostapd_data *hapd)
202{
70db2ab3
JM
203 if (hapd->iface->ctrl_iface_deinit)
204 hapd->iface->ctrl_iface_deinit(hapd);
6fc6879b 205
6fc6879b
JM
206 iapp_deinit(hapd->iapp);
207 hapd->iapp = NULL;
208 accounting_deinit(hapd);
c442055e 209 hostapd_deinit_wpa(hapd);
6fc6879b
JM
210 vlan_deinit(hapd);
211 hostapd_acl_deinit(hapd);
74784010 212#ifndef CONFIG_NO_RADIUS
6fc6879b
JM
213 radius_client_deinit(hapd->radius);
214 hapd->radius = NULL;
74784010 215#endif /* CONFIG_NO_RADIUS */
6fc6879b 216
ad08c363
JM
217 hostapd_deinit_wps(hapd);
218
2586bc64 219 authsrv_deinit(hapd);
6fc6879b
JM
220
221 if (hapd->interface_added &&
22a7c9d7 222 hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
bb305cbd
JM
223 wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
224 hapd->conf->iface);
6fc6879b 225 }
fa16028d
JM
226
227 os_free(hapd->probereq_cb);
228 hapd->probereq_cb = NULL;
6fc6879b
JM
229}
230
231
232/**
233 * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup
234 * @iface: Pointer to interface data
235 *
236 * This function is called before per-BSS data structures are deinitialized
237 * with hostapd_cleanup().
238 */
239static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
240{
241}
242
243
244/**
245 * hostapd_cleanup_iface - Complete per-interface cleanup
246 * @iface: Pointer to interface data
247 *
248 * This function is called after per-BSS data structures are deinitialized
249 * with hostapd_cleanup().
250 */
251static void hostapd_cleanup_iface(struct hostapd_iface *iface)
252{
253 hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
254 iface->hw_features = NULL;
255 os_free(iface->current_rates);
256 iface->current_rates = NULL;
257 ap_list_deinit(iface);
258 hostapd_config_free(iface->conf);
259 iface->conf = NULL;
260
261 os_free(iface->config_fname);
262 os_free(iface->bss);
263 os_free(iface);
264}
265
266
267static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
268{
269 int i;
270
271 hostapd_broadcast_wep_set(hapd);
272
579bc0e6
JM
273 if (hapd->conf->ssid.wep.default_len) {
274 hostapd_set_privacy(hapd, 1);
6fc6879b 275 return 0;
579bc0e6 276 }
6fc6879b
JM
277
278 for (i = 0; i < 4; i++) {
279 if (hapd->conf->ssid.wep.key[i] &&
45cefa0b
JM
280 hapd->drv.set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
281 i == hapd->conf->ssid.wep.idx, NULL, 0,
282 hapd->conf->ssid.wep.key[i],
283 hapd->conf->ssid.wep.len[i])) {
bb305cbd
JM
284 wpa_printf(MSG_WARNING, "Could not set WEP "
285 "encryption.");
6fc6879b
JM
286 return -1;
287 }
288 if (hapd->conf->ssid.wep.key[i] &&
289 i == hapd->conf->ssid.wep.idx)
290 hostapd_set_privacy(hapd, 1);
291 }
292
293 return 0;
294}
295
296
297static int hostapd_flush_old_stations(struct hostapd_data *hapd)
298{
299 int ret = 0;
300
85141289
JM
301 if (hostapd_drv_none(hapd))
302 return 0;
303
6fc6879b
JM
304 wpa_printf(MSG_DEBUG, "Flushing old station entries");
305 if (hostapd_flush(hapd)) {
bb305cbd 306 wpa_printf(MSG_WARNING, "Could not connect to kernel driver.");
6fc6879b
JM
307 ret = -1;
308 }
309 wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
9302c5e1
JM
310
311 /* New Prism2.5/3 STA firmware versions seem to have issues with this
312 * broadcast deauth frame. This gets the firmware in odd state where
313 * nothing works correctly, so let's skip sending this for the hostap
314 * driver. */
315 if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") != 0) {
316 u8 addr[ETH_ALEN];
317 os_memset(addr, 0xff, ETH_ALEN);
bdee6fce
JM
318 hapd->drv.sta_deauth(hapd, addr,
319 WLAN_REASON_PREV_AUTH_NOT_VALID);
9302c5e1 320 }
6fc6879b
JM
321
322 return ret;
323}
324
325
6fc6879b
JM
326/**
327 * hostapd_validate_bssid_configuration - Validate BSSID configuration
328 * @iface: Pointer to interface data
329 * Returns: 0 on success, -1 on failure
330 *
331 * This function is used to validate that the configured BSSIDs are valid.
332 */
333static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
334{
335 u8 mask[ETH_ALEN] = { 0 };
336 struct hostapd_data *hapd = iface->bss[0];
337 unsigned int i = iface->conf->num_bss, bits = 0, j;
338 int res;
90ac1f9f 339 int auto_addr = 0;
6fc6879b 340
85141289
JM
341 if (hostapd_drv_none(hapd))
342 return 0;
343
6fc6879b
JM
344 /* Generate BSSID mask that is large enough to cover the BSSIDs. */
345
346 /* Determine the bits necessary to cover the number of BSSIDs. */
347 for (i--; i; i >>= 1)
348 bits++;
349
350 /* Determine the bits necessary to any configured BSSIDs,
351 if they are higher than the number of BSSIDs. */
352 for (j = 0; j < iface->conf->num_bss; j++) {
90ac1f9f
JM
353 if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) {
354 if (j)
355 auto_addr++;
6fc6879b 356 continue;
90ac1f9f 357 }
6fc6879b
JM
358
359 for (i = 0; i < ETH_ALEN; i++) {
360 mask[i] |=
361 iface->conf->bss[j].bssid[i] ^
362 hapd->own_addr[i];
363 }
364 }
365
90ac1f9f
JM
366 if (!auto_addr)
367 goto skip_mask_ext;
368
6fc6879b
JM
369 for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
370 ;
371 j = 0;
372 if (i < ETH_ALEN) {
373 j = (5 - i) * 8;
374
375 while (mask[i] != 0) {
376 mask[i] >>= 1;
377 j++;
378 }
379 }
380
381 if (bits < j)
382 bits = j;
383
90ac1f9f
JM
384 if (bits > 40) {
385 wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)",
386 bits);
6fc6879b 387 return -1;
90ac1f9f 388 }
6fc6879b
JM
389
390 os_memset(mask, 0xff, ETH_ALEN);
391 j = bits / 8;
392 for (i = 5; i > 5 - j; i--)
393 mask[i] = 0;
394 j = bits % 8;
395 while (j--)
396 mask[i] <<= 1;
397
90ac1f9f 398skip_mask_ext:
6fc6879b
JM
399 wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
400 (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
401
402 res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask);
403 if (res == 0)
404 return 0;
405
406 if (res < 0) {
bb305cbd
JM
407 wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask "
408 MACSTR " for start address " MACSTR ".",
409 MAC2STR(mask), MAC2STR(hapd->own_addr));
6fc6879b
JM
410 return -1;
411 }
412
90ac1f9f
JM
413 if (!auto_addr)
414 return 0;
415
6fc6879b
JM
416 for (i = 0; i < ETH_ALEN; i++) {
417 if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
bb305cbd
JM
418 wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
419 " for start address " MACSTR ".",
420 MAC2STR(mask), MAC2STR(hapd->own_addr));
421 wpa_printf(MSG_ERROR, "Start address must be the "
422 "first address in the block (i.e., addr "
423 "AND mask == addr).");
6fc6879b
JM
424 return -1;
425 }
426 }
427
428 return 0;
429}
430
431
432static int mac_in_conf(struct hostapd_config *conf, const void *a)
433{
434 size_t i;
435
436 for (i = 0; i < conf->num_bss; i++) {
437 if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) {
438 return 1;
439 }
440 }
441
442 return 0;
443}
444
445
6fc6879b
JM
446
447
6fc6879b
JM
448/**
449 * hostapd_setup_bss - Per-BSS setup (initialization)
450 * @hapd: Pointer to BSS data
451 * @first: Whether this BSS is the first BSS of an interface
452 *
453 * This function is used to initialize all per-BSS data structures and
454 * resources. This gets called in a loop for each BSS when an interface is
455 * initialized. Most of the modules that are initialized here will be
456 * deinitialized in hostapd_cleanup().
457 */
458static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
459{
460 struct hostapd_bss_config *conf = hapd->conf;
461 u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
462 int ssid_len, set_ssid;
463
464 if (!first) {
465 if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
466 /* Allocate the next available BSSID. */
467 do {
468 inc_byte_array(hapd->own_addr, ETH_ALEN);
469 } while (mac_in_conf(hapd->iconf, hapd->own_addr));
470 } else {
471 /* Allocate the configured BSSID. */
472 os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN);
473
474 if (hostapd_mac_comp(hapd->own_addr,
475 hapd->iface->bss[0]->own_addr) ==
476 0) {
bb305cbd
JM
477 wpa_printf(MSG_ERROR, "BSS '%s' may not have "
478 "BSSID set to the MAC address of "
479 "the radio", hapd->conf->iface);
6fc6879b
JM
480 return -1;
481 }
482 }
483
484 hapd->interface_added = 1;
22a7c9d7 485 if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
8043e725 486 hapd->conf->iface, hapd->own_addr, hapd)) {
bb305cbd
JM
487 wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
488 MACSTR ")", MAC2STR(hapd->own_addr));
6fc6879b
JM
489 return -1;
490 }
491 }
492
c213cc04
JM
493 hostapd_flush_old_stations(hapd);
494 hostapd_set_privacy(hapd, 0);
495
496 hostapd_broadcast_wep_clear(hapd);
497 if (hostapd_setup_encryption(hapd->conf->iface, hapd))
498 return -1;
499
6fc6879b
JM
500 /*
501 * Fetch the SSID from the system and use it or,
502 * if one was specified in the config file, verify they
503 * match.
504 */
505 ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
506 if (ssid_len < 0) {
bb305cbd 507 wpa_printf(MSG_ERROR, "Could not read SSID from system");
6fc6879b
JM
508 return -1;
509 }
510 if (conf->ssid.ssid_set) {
511 /*
512 * If SSID is specified in the config file and it differs
513 * from what is being used then force installation of the
514 * new SSID.
515 */
516 set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len ||
517 os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0);
518 } else {
519 /*
520 * No SSID in the config file; just use the one we got
521 * from the system.
522 */
523 set_ssid = 0;
524 conf->ssid.ssid_len = ssid_len;
525 os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
526 conf->ssid.ssid[conf->ssid.ssid_len] = '\0';
527 }
528
85141289 529 if (!hostapd_drv_none(hapd)) {
bb305cbd
JM
530 wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
531 " and ssid '%s'",
532 hapd->conf->iface, MAC2STR(hapd->own_addr),
533 hapd->conf->ssid.ssid);
85141289 534 }
6fc6879b
JM
535
536 if (hostapd_setup_wpa_psk(conf)) {
bb305cbd 537 wpa_printf(MSG_ERROR, "WPA-PSK setup failed.");
6fc6879b
JM
538 return -1;
539 }
540
6fc6879b
JM
541 /* Set SSID for the kernel driver (to be used in beacon and probe
542 * response frames) */
543 if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid,
544 conf->ssid.ssid_len)) {
bb305cbd 545 wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
6fc6879b
JM
546 return -1;
547 }
548
549 if (wpa_debug_level == MSG_MSGDUMP)
550 conf->radius->msg_dumps = 1;
74784010 551#ifndef CONFIG_NO_RADIUS
6fc6879b
JM
552 hapd->radius = radius_client_init(hapd, conf->radius);
553 if (hapd->radius == NULL) {
bb305cbd 554 wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
6fc6879b
JM
555 return -1;
556 }
74784010 557#endif /* CONFIG_NO_RADIUS */
6fc6879b
JM
558
559 if (hostapd_acl_init(hapd)) {
bb305cbd 560 wpa_printf(MSG_ERROR, "ACL initialization failed.");
6fc6879b
JM
561 return -1;
562 }
ad08c363
JM
563 if (hostapd_init_wps(hapd, conf))
564 return -1;
6fc6879b
JM
565
566 if (ieee802_1x_init(hapd)) {
bb305cbd 567 wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed.");
6fc6879b
JM
568 return -1;
569 }
570
571 if (hapd->conf->wpa && hostapd_setup_wpa(hapd))
572 return -1;
573
574 if (accounting_init(hapd)) {
bb305cbd 575 wpa_printf(MSG_ERROR, "Accounting initialization failed.");
6fc6879b
JM
576 return -1;
577 }
578
579 if (hapd->conf->ieee802_11f &&
580 (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
bb305cbd
JM
581 wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
582 "failed.");
6fc6879b
JM
583 return -1;
584 }
585
70db2ab3
JM
586 if (hapd->iface->ctrl_iface_init &&
587 hapd->iface->ctrl_iface_init(hapd)) {
bb305cbd 588 wpa_printf(MSG_ERROR, "Failed to setup control interface");
6fc6879b
JM
589 return -1;
590 }
591
85141289 592 if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
bb305cbd 593 wpa_printf(MSG_ERROR, "VLAN initialization failed.");
6fc6879b
JM
594 return -1;
595 }
596
6fc6879b
JM
597 ieee802_11_set_beacon(hapd);
598
2586bc64 599 if (authsrv_init(hapd) < 0)
6fc6879b
JM
600 return -1;
601
602 return 0;
603}
604
605
990ec378
JM
606static void hostapd_tx_queue_params(struct hostapd_iface *iface)
607{
608 struct hostapd_data *hapd = iface->bss[0];
609 int i;
610 struct hostapd_tx_queue_params *p;
611
612 for (i = 0; i < NUM_TX_QUEUES; i++) {
613 p = &iface->conf->tx_queue[i];
614
615 if (!p->configured)
616 continue;
617
618 if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
619 p->cwmax, p->burst)) {
bb305cbd
JM
620 wpa_printf(MSG_DEBUG, "Failed to set TX queue "
621 "parameters for queue %d.", i);
990ec378
JM
622 /* Continue anyway */
623 }
624 }
625}
626
627
ddaa83eb 628static int setup_interface(struct hostapd_iface *iface)
6fc6879b
JM
629{
630 struct hostapd_data *hapd = iface->bss[0];
6fc6879b
JM
631 size_t i;
632 char country[4];
6fc6879b
JM
633
634 /*
e5f2b59c
JM
635 * Make sure that all BSSes get configured with a pointer to the same
636 * driver interface.
6fc6879b 637 */
e5f2b59c 638 for (i = 1; i < iface->num_bss; i++) {
6fc6879b
JM
639 iface->bss[i]->driver = hapd->driver;
640 iface->bss[i]->drv_priv = hapd->drv_priv;
641 }
642
643 if (hostapd_validate_bssid_configuration(iface))
644 return -1;
645
6f4071c0
JM
646 if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
647 os_memcpy(country, hapd->iconf->country, 3);
648 country[3] = '\0';
649 if (hostapd_set_country(hapd, country) < 0) {
650 wpa_printf(MSG_ERROR, "Failed to set country code");
651 return -1;
652 }
6fc6879b
JM
653 }
654
6fc6879b
JM
655 if (hostapd_get_hw_features(iface)) {
656 /* Not all drivers support this yet, so continue without hw
657 * feature data. */
658 } else {
ddaa83eb
JM
659 int ret = hostapd_select_hw_mode(iface);
660 if (ret < 0) {
bb305cbd
JM
661 wpa_printf(MSG_ERROR, "Could not select hw_mode and "
662 "channel. (%d)", ret);
ddaa83eb
JM
663 return -1;
664 }
ad1e68e6
JM
665 ret = hostapd_check_ht_capab(iface);
666 if (ret < 0)
667 return -1;
668 if (ret == 1) {
669 wpa_printf(MSG_DEBUG, "Interface initialization will "
670 "be completed in a callback");
671 return 0;
672 }
673 }
674 return hostapd_setup_interface_complete(iface, 0);
675}
676
677
678int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
679{
680 struct hostapd_data *hapd = iface->bss[0];
681 int freq;
682 size_t j;
683 u8 *prev_addr;
684
685 if (err) {
686 wpa_printf(MSG_ERROR, "Interface initialization failed");
687 eloop_terminate();
688 return -1;
6fc6879b
JM
689 }
690
ad1e68e6 691 wpa_printf(MSG_DEBUG, "Completing interface initialization");
ddaa83eb
JM
692 if (hapd->iconf->channel) {
693 freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel);
bb305cbd
JM
694 wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d "
695 "Frequency: %d MHz",
696 hostapd_hw_mode_txt(hapd->iconf->hw_mode),
697 hapd->iconf->channel, freq);
6fc6879b 698
95da9bbc 699 if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, freq,
9c6d8e1d 700 hapd->iconf->channel,
fe0f58fa 701 hapd->iconf->ieee80211n,
95da9bbc 702 hapd->iconf->secondary_channel)) {
bb305cbd
JM
703 wpa_printf(MSG_ERROR, "Could not set channel for "
704 "kernel driver");
ddaa83eb
JM
705 return -1;
706 }
707 }
6fc6879b 708
ddaa83eb
JM
709 if (hapd->iconf->rts_threshold > -1 &&
710 hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
bb305cbd
JM
711 wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
712 "kernel driver");
ddaa83eb
JM
713 return -1;
714 }
715
716 if (hapd->iconf->fragm_threshold > -1 &&
717 hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
bb305cbd
JM
718 wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
719 "for kernel driver");
ddaa83eb
JM
720 return -1;
721 }
6fc6879b 722
ddaa83eb
JM
723 prev_addr = hapd->own_addr;
724
725 for (j = 0; j < iface->num_bss; j++) {
726 hapd = iface->bss[j];
727 if (j)
728 os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
729 if (hostapd_setup_bss(hapd, j == 0))
730 return -1;
731 if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
732 prev_addr = hapd->own_addr;
733 }
734
735 hostapd_tx_queue_params(iface);
736
737 ap_list_init(iface);
738
739 if (hostapd_driver_commit(hapd) < 0) {
740 wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
741 "configuration", __func__);
742 return -1;
743 }
744
ad1e68e6
JM
745 wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
746 iface->bss[0]->conf->iface);
747
21db94c5 748 return 0;
6fc6879b
JM
749}
750
751
752/**
ddaa83eb 753 * hostapd_setup_interface - Setup of an interface
6fc6879b 754 * @iface: Pointer to interface data.
ddaa83eb 755 * Returns: 0 on success, -1 on failure
6fc6879b
JM
756 *
757 * Initializes the driver interface, validates the configuration,
758 * and sets driver parameters based on the configuration.
ddaa83eb 759 * Flushes old stations, sets the channel, encryption,
6fc6879b
JM
760 * beacons, and WDS links based on the configuration.
761 */
5c333467 762int hostapd_setup_interface(struct hostapd_iface *iface)
6fc6879b 763{
ddaa83eb
JM
764 int ret;
765
766 ret = setup_interface(iface);
767 if (ret) {
bee07ce8 768 wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
6fc6879b
JM
769 iface->bss[0]->conf->iface);
770 return -1;
771 }
772
6fc6879b
JM
773 return 0;
774}
775
776
6fc6879b
JM
777/**
778 * hostapd_alloc_bss_data - Allocate and initialize per-BSS data
779 * @hapd_iface: Pointer to interface data
780 * @conf: Pointer to per-interface configuration
781 * @bss: Pointer to per-BSS configuration for this BSS
782 * Returns: Pointer to allocated BSS data
783 *
784 * This function is used to allocate per-BSS data structure. This data will be
785 * freed after hostapd_cleanup() is called for it during interface
786 * deinitialization.
787 */
b6a7859d 788struct hostapd_data *
6fc6879b
JM
789hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
790 struct hostapd_config *conf,
791 struct hostapd_bss_config *bss)
792{
793 struct hostapd_data *hapd;
794
795 hapd = os_zalloc(sizeof(*hapd));
796 if (hapd == NULL)
797 return NULL;
798
bf65bc63 799 hostapd_set_driver_ops(&hapd->drv);
d24df7c3 800 hapd->new_assoc_sta_cb = hostapd_new_assoc_sta;
6fc6879b
JM
801 hapd->iconf = conf;
802 hapd->conf = bss;
803 hapd->iface = hapd_iface;
6fc6879b
JM
804 hapd->driver = hapd->iconf->driver;
805
806 return hapd;
6fc6879b
JM
807}
808
809
5c333467 810void hostapd_interface_deinit(struct hostapd_iface *iface)
5fa30f32
JM
811{
812 size_t j;
813
814 if (iface == NULL)
815 return;
816
817 hostapd_cleanup_iface_pre(iface);
818 for (j = 0; j < iface->num_bss; j++) {
819 struct hostapd_data *hapd = iface->bss[j];
820 hostapd_free_stas(hapd);
821 hostapd_flush_old_stations(hapd);
822 hostapd_cleanup(hapd);
5fa30f32
JM
823 }
824 for (j = 0; j < iface->num_bss; j++)
825 os_free(iface->bss[j]);
826 hostapd_cleanup_iface(iface);
827}
fa16028d
JM
828
829
a2de634d
JM
830/**
831 * hostapd_new_assoc_sta - Notify that a new station associated with the AP
832 * @hapd: Pointer to BSS data
833 * @sta: Pointer to the associated STA data
834 * @reassoc: 1 to indicate this was a re-association; 0 = first association
835 *
836 * This function will be called whenever a station associates with the AP. It
837 * can be called from ieee802_11.c for drivers that export MLME to hostapd and
838 * from drv_callbacks.c based on driver events for drivers that take care of
839 * management frames (IEEE 802.11 authentication and association) internally.
840 */
841void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
842 int reassoc)
843{
844 if (hapd->tkip_countermeasures) {
bdee6fce
JM
845 hapd->drv.sta_deauth(hapd, sta->addr,
846 WLAN_REASON_MICHAEL_MIC_FAILURE);
a2de634d
JM
847 return;
848 }
849
0aef3ec8 850 hostapd_prune_associations(hapd, sta->addr);
a2de634d
JM
851
852 /* IEEE 802.11F (IAPP) */
853 if (hapd->conf->ieee802_11f)
854 iapp_new_station(hapd->iapp, sta);
855
856 /* Start accounting here, if IEEE 802.1X and WPA are not used.
857 * IEEE 802.1X/WPA code will start accounting after the station has
858 * been authorized. */
859 if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
860 accounting_sta_start(hapd, sta);
861
862 /* Start IEEE 802.1X authentication process for new stations */
863 ieee802_1x_new_station(hapd, sta);
864 if (reassoc) {
865 if (sta->auth_alg != WLAN_AUTH_FT &&
866 !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
867 wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
868 } else
869 wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
870}