1 /*
2 * hostapd / main()
3 * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * This software may be distributed under the terms of the BSD license.
18 * See README for more details.
19 */
20
21 #include "utils/common.h"
22 #include "ap/ap_drv_ops.h"
23 #include "ap/ap_config.h"
24 #include "ctrl_iface.h"
25 #include "hostapd_if.h"
26 #include "utils/eloop.h"
27 #include "eap_server/eap.h"
28 #include "wifi_api.h"
29 #include "securec.h"
30
31 typedef struct hostapd_conf hostapd_conf;
32
33 struct hostapd_data *g_hapd = NULL;
34
35 struct hapd_global {
36 void **drv_priv;
37 size_t drv_count;
38 };
39
40 static struct hapd_global global;
41 hostapd_conf g_global_conf;
42 static struct hapd_interfaces *g_interfaces = NULL;
43
44 /**
45 * hostapd_driver_init - Preparate driver interface
46 */
hostapd_driver_init(struct hostapd_iface * iface)47 static int hostapd_driver_init(struct hostapd_iface *iface)
48 {
49 struct wpa_init_params params;
50 size_t i;
51 struct hostapd_data *hapd = iface->bss[0];
52 struct hostapd_bss_config *conf = hapd->conf;
53 u8 *b = conf->bssid;
54
55 if ((hapd->driver == NULL) || (hapd->driver->hapd_init == NULL)) {
56 wpa_error_log0(MSG_ERROR, "No hostapd driver wrapper available");
57 return -1;
58 }
59
60 /* Initialize the driver interface */
61 if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
62 b = NULL;
63
64 (void)os_memset(¶ms, 0, sizeof(params));
65 for (i = 0; wpa_drivers[i] != NULL; i++) {
66 if (wpa_drivers[i] != hapd->driver)
67 continue;
68
69 params.global_priv = global.drv_priv[i];
70 break;
71 }
72 params.bssid = b;
73 params.ifname = hapd->conf->iface;
74 params.driver_params = hapd->iconf->driver_params;
75 params.own_addr = hapd->own_addr;
76 wpa_error_buf(MSG_ERROR, "hostapd_driver_init: ifname %s", params.ifname, os_strlen(params.ifname));
77
78 hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms);
79 if (hapd->drv_priv == NULL) {
80 wpa_error_log0(MSG_ERROR, "hapd driver initialization failed.");
81 hapd->driver = NULL;
82 return -1;
83 }
84
85 return 0;
86 }
87
88 /**
89 * hostapd_interface_init - Read configuration file and init BSS data
90 *
91 * This function is used to parse configuration file for a full interface (one
92 * or more BSSes sharing the same radio) and allocate memory for the BSS
93 * interfaces. No actiual driver operations are started.
94 */
hostapd_interface_init(struct hapd_interfaces * interfaces,const char * config,int debug)95 static struct hostapd_iface * hostapd_interface_init(struct hapd_interfaces *interfaces,
96 const char *config, int debug)
97 {
98 struct hostapd_iface *iface = NULL;
99
100 (void)debug;
101 iface = hostapd_init(interfaces, config);
102 if ((iface == NULL) || (iface->conf == NULL))
103 return NULL;
104 iface->interfaces = interfaces;
105
106 if (iface->conf->bss[0]->iface[0] == '\0') {
107 wpa_error_log0(MSG_ERROR, "Interface name not specified");
108 hostapd_interface_deinit_free(iface);
109 return NULL;
110 }
111
112 g_hapd = iface->bss[0];
113 return iface;
114 }
115
eap_server_register_methods(void)116 static int eap_server_register_methods(void)
117 {
118 int ret = 0;
119 #ifdef EAP_SERVER_IDENTITY
120 if (ret == 0)
121 ret = eap_server_identity_register();
122 #endif /* EAP_SERVER_IDENTITY */
123
124 #ifdef EAP_SERVER_WSC
125 if (ret == 0)
126 ret = eap_server_wsc_register();
127 #endif /* EAP_SERVER_WSC */
128 return ret;
129 }
130
hostapd_global_init(const struct hapd_interfaces * interfaces,const char * entropy_file)131 static int hostapd_global_init(const struct hapd_interfaces *interfaces, const char *entropy_file)
132 {
133 int i;
134 (void)interfaces;
135 (void)entropy_file;
136
137 (void)os_memset(&global, 0, sizeof(global));
138 if (eap_server_register_methods()) {
139 wpa_error_log0(MSG_ERROR, "Failed to register EAP methods");
140 return -1;
141 }
142 if (eloop_init(ELOOP_TASK_HOSTAPD)) {
143 wpa_error_log0(MSG_ERROR, "Failed to initialize event loop");
144 return -1;
145 }
146
147 for (i = 0; wpa_drivers[i]; i++)
148 global.drv_count++;
149
150 if (global.drv_count == 0) {
151 wpa_error_log0(MSG_ERROR, "No drivers enabled");
152 return -1;
153 }
154 global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
155 if (global.drv_priv == NULL)
156 return -1;
157 return 0;
158 }
159
hostapd_global_deinit(void)160 void hostapd_global_deinit(void)
161 {
162 os_free(global.drv_priv);
163 global.drv_priv = NULL;
164 g_hapd = NULL;
165 eloop_destroy(ELOOP_TASK_HOSTAPD);
166 eap_server_unregister_methods();
167 }
168
hostapd_global_interfaces_deinit(void)169 void hostapd_global_interfaces_deinit(void)
170 {
171 if (g_interfaces != NULL)
172 os_free(g_interfaces->iface);
173 os_free(g_interfaces);
174 g_interfaces = NULL;
175 wpa_error_log0(MSG_ERROR, "hostapd_exit\n");
176 }
177
hostapd_global_run(const struct hapd_interfaces * ifaces,int daemonize,const char * pid_file)178 static int hostapd_global_run(const struct hapd_interfaces *ifaces, int daemonize, const char *pid_file)
179 {
180 (void)pid_file;
181 (void)daemonize;
182 (void)ifaces;
183 return eloop_run(ELOOP_TASK_HOSTAPD);
184 }
185
hostapd_bss_init(struct hostapd_bss_config * bss,const hostapd_conf * conf,const char * ifname)186 static int hostapd_bss_init(struct hostapd_bss_config *bss, const hostapd_conf *conf, const char *ifname)
187 {
188 int errors = 0;
189 if (ifname != NULL)
190 (void)os_strlcpy(bss->iface, ifname, strlen(ifname) + 1);
191 bss->ssid.ssid_len = os_strlen(conf->ssid);
192 if ((bss->ssid.ssid_len > SSID_MAX_LEN) || (bss->ssid.ssid_len < 1)) {
193 wpa_error_buf(MSG_ERROR, "invalid SSID '%s'", conf->ssid, strlen(conf->ssid));
194 errors++;
195 } else {
196 (void)os_memcpy(bss->ssid.ssid, conf->ssid, bss->ssid.ssid_len);
197 bss->ssid.ssid_set = 1;
198 }
199 bss->auth_algs = conf->auth_algs;
200 bss->wpa_key_mgmt = conf->wpa_key_mgmt;
201 bss->wpa = conf->wpa;
202 if (bss->wpa) {
203 bss->eapol_version = 1;
204 if (conf->wpa_pairwise)
205 bss->wpa_pairwise = conf->wpa_pairwise;
206 }
207 if (bss->wpa && bss->wpa_key_mgmt != WPA_KEY_MGMT_OWE) {
208 size_t len = os_strlen((char *)conf->key);
209 if (len < 8 || len > 64) { /* 8: MIN passphrase len, 64: MAX passphrase len */
210 wpa_error_log1(MSG_ERROR, "invalid WPA passphrase length %u (expected 8..63)", len);
211 errors++;
212 } else if (len == 64) { /* 64: MAX passphrase len */
213 if (bss->ssid.wpa_psk != NULL)
214 (void)memset_s(bss->ssid.wpa_psk, sizeof(*(bss->ssid.wpa_psk)), 0, sizeof(*(bss->ssid.wpa_psk)));
215 os_free(bss->ssid.wpa_psk);
216 bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
217 if (bss->ssid.wpa_psk == NULL)
218 errors++;
219 else if (hexstr2bin((char *)conf->key, bss->ssid.wpa_psk->psk, PMK_LEN) ||
220 conf->key[PMK_LEN * 2] != '\0') { /* 2: HEX String to BIN */
221 errors++;
222 } else {
223 bss->ssid.wpa_psk->group = 1;
224 os_free(bss->ssid.wpa_passphrase);
225 bss->ssid.wpa_passphrase = NULL;
226 }
227 } else {
228 os_free(bss->ssid.wpa_passphrase);
229 bss->ssid.wpa_passphrase = os_strdup((char *)conf->key);
230 if (bss->ssid.wpa_psk != NULL)
231 (void)memset_s(bss->ssid.wpa_psk, sizeof(*(bss->ssid.wpa_psk)), 0, sizeof(*(bss->ssid.wpa_psk)));
232 os_free(bss->ssid.wpa_psk);
233 bss->ssid.wpa_psk = NULL;
234 }
235 }
236 bss->eap_server = 1;
237 #ifdef CONFIG_DRIVER_SOC
238 bss->ignore_broadcast_ssid = conf->ignore_broadcast_ssid; /* set hidden AP */
239 #endif /* CONFIG_DRIVER_SOC */
240 return errors;
241 }
242
243 #ifdef CONFIG_IEEE80211AX
hostapd_config_80211ax(struct hostapd_config * conf)244 static void hostapd_config_80211ax(struct hostapd_config * conf)
245 {
246 // refer to hostapd_config_defaults() function
247 conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >>
248 HE_OPERATION_RTS_THRESHOLD_OFFSET;
249 /* Set default basic MCS/NSS set to single stream MCS 0-7 */
250 conf->he_op.he_basic_mcs_nss_set = 0xfffc;
251
252 // refer to hostapd.conf file
253 conf->he_phy_capab.he_su_beamformer = 0;
254 conf->he_phy_capab.he_su_beamformee = 1;
255 conf->he_phy_capab.he_mu_beamformer = 0;
256 conf->he_op.he_bss_color = 1;
257 conf->he_op.he_default_pe_duration = 0;
258 conf->he_op.he_twt_required = 0;
259 conf->he_op.he_rts_threshold = 0;
260
261 // 0 = 20 or 40 MHz operating Channel width
262 // 1 = 80 MHz channel width
263 // 2 = 160 MHz channel width
264 // 3 = 80+80 MHz channel width
265 conf->he_oper_chwidth = 0;
266
267 conf->he_mu_edca.he_qos_info |= (8 << 0);
268 conf->he_mu_edca.he_qos_info |= (1 << 4);
269 conf->he_mu_edca.he_qos_info |= (1 << 5);
270 conf->he_mu_edca.he_qos_info |= (1 << 6);
271 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |= (0 << 0);
272 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |= (0xf << 0);
273 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |= (0xf << 4);
274 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_TIMER_IDX] = 0xff;
275 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |= (0 << 0);
276 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |= (1 << 5);
277 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |= (0xf << 0);
278 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |= (0xf << 4);
279 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_TIMER_IDX] = 0xff;
280 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |= (0xf << 0);
281 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |= (0xf << 4);
282 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |= (0 << 0);
283 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |= (2 << 5);
284 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_TIMER_IDX] = 0xff;
285 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |= (0 << 0);
286 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |= (3 << 5);
287 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |= (0xf << 0);
288 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |= (0xf << 4);
289 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] = 0xff;
290
291 conf->spr.sr_control = 0xff;
292 }
293 #endif
294
295 #ifdef CONFIG_WEP
hostapd_config_read_wep(struct hostapd_wep_keys * wep,int keyidx,char * val)296 static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
297 char *val)
298 {
299 size_t len = os_strlen(val);
300
301 if (keyidx < 0 || keyidx > 3)
302 return -1;
303
304 if (len == 0) {
305 int i, set = 0;
306
307 bin_clear_free(wep->key[keyidx], wep->len[keyidx]);
308 wep->key[keyidx] = NULL;
309 wep->len[keyidx] = 0;
310 for (i = 0; i < NUM_WEP_KEYS; i++) {
311 if (wep->key[i])
312 set++;
313 }
314 if (!set)
315 wep->keys_set = 0;
316 return 0;
317 }
318
319 if (wep->key[keyidx] != NULL)
320 return -1;
321
322 if (val[0] == '"') {
323 if (len < 2 || val[len - 1] != '"')
324 return -1;
325 len -= 2;
326 wep->key[keyidx] = os_memdup(val + 1, len);
327 if (wep->key[keyidx] == NULL)
328 return -1;
329 wep->len[keyidx] = len;
330 } else {
331 if (len & 1)
332 return -1;
333 len /= 2;
334 wep->key[keyidx] = os_malloc(len);
335 if (wep->key[keyidx] == NULL)
336 return -1;
337 wep->len[keyidx] = len;
338 if (hexstr2bin(val, wep->key[keyidx], len) < 0)
339 return -1;
340 }
341
342 wep->keys_set++;
343
344 return 0;
345 }
346 #endif
347
hostapd_config_read2(const char * ifname)348 struct hostapd_config * hostapd_config_read2(const char *ifname)
349 {
350 int errors = 0;
351 hostapd_conf *hconf = &g_global_conf;
352 if (ifname == NULL)
353 return NULL;
354 struct hostapd_config *conf = hostapd_config_defaults();
355 if (conf == NULL)
356 return NULL;
357
358 conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; /* default setting. */
359 conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
360 #ifdef CONFIG_IEEE80211N
361 conf->ieee80211n = 1;
362 #endif
363 if (g_ap_opt_set.short_gi_off == WPA_FLAG_ON)
364 conf->ht_capab &= ~HT_CAP_INFO_SHORT_GI20MHZ;
365
366 #ifdef CONFIG_IEEE80211AX
367 conf->ieee80211ax = (g_ap_opt_set.hw_mode == WIFI_MODE_11B_G_N_AX);
368 if (conf->ieee80211ax) {
369 hostapd_config_80211ax(conf);
370 }
371 #endif
372
373 /* set default driver based on configuration */
374 for (size_t i = 0; wpa_drivers[i] != NULL; i++) {
375 if (os_strcmp(hconf->driver, wpa_drivers[i]->name) == 0) {
376 conf->driver = wpa_drivers[i];
377 break;
378 }
379 }
380 if (conf->driver == NULL) {
381 wpa_error_log0(MSG_ERROR, "No driver wrappers registered!");
382 hostapd_config_free(conf);
383 return NULL;
384 }
385
386 struct hostapd_bss_config *bss = conf->bss[0];
387 conf->last_bss = conf->bss[0];
388 conf->channel = (u8)hconf->channel_num;
389
390 #ifdef CONFIG_WEP
391 /* WEP加密设置keys */
392 if ((hconf->auth_algs == 1 || hconf->auth_algs == 2) && hconf->wep_idx == 0) {
393 bss->ssid.wep.len[0] = (size_t)os_strlen((char *)hconf->key);
394 if (bss->ssid.wep.len[0] == 0) {
395 bss->ssid.wep.keys_set = 0;
396 wpa_error_log0(MSG_ERROR, "hostapd_config_read2::Invalid password\r\n");
397 }
398 bss->ssid.wep.key[0] = os_memdup(&hconf->key[0], bss->ssid.wep.len[0]);
399 if (bss->ssid.wep.key[0] == NULL) {
400 wpa_error_log0(MSG_ERROR, "hostapd_config_read2::copy fail\r\n");
401 return NULL;
402 }
403 bss->ssid.wep.keys_set = 1;
404 }
405 #endif /* CONFIG_WEP */
406
407 errors += hostapd_bss_init(bss, hconf, ifname);
408 for (size_t i = 0; i < conf->num_bss; i++)
409 hostapd_set_security_params(conf->bss[i], 1);
410
411 if (hostapd_config_check(conf, 1))
412 errors++;
413
414 #ifndef WPA_IGNORE_CONFIG_ERRORS
415 if (errors) {
416 wpa_error_log1(MSG_ERROR, "%d errors found in configuration file ", errors);
417 wpa_error_buf(MSG_ERROR, "'%s'", ifname, strlen(ifname));
418 hostapd_config_free(conf);
419 conf = NULL;
420 }
421 #endif /* WPA_IGNORE_CONFIG_ERRORS */
422
423 return conf;
424 }
425
hostapd_pre_quit(struct hapd_interfaces * interfaces)426 void hostapd_pre_quit(struct hapd_interfaces *interfaces)
427 {
428 if (interfaces == NULL)
429 return;
430
431 hostapd_global_ctrl_iface_deinit(interfaces);
432 if (interfaces->iface == NULL)
433 return;
434 /* Deinitialize all interfaces */
435 for (size_t i = 0; i < interfaces->count; i++) {
436 if (interfaces->iface[i] == NULL)
437 continue;
438 hostapd_interface_deinit_free(interfaces->iface[i]);
439 interfaces->iface[i] = NULL;
440 }
441 }
442
hostapd_quit(struct hapd_interfaces * interfaces,struct ext_wifi_dev * wifi_dev)443 static void hostapd_quit(struct hapd_interfaces *interfaces, struct ext_wifi_dev *wifi_dev)
444 {
445 hostapd_pre_quit(interfaces);
446
447 hostapd_global_deinit();
448
449 os_free(interfaces->iface);
450 interfaces->iface = NULL;
451 os_free(interfaces);
452 interfaces = NULL;
453 g_interfaces = NULL;
454
455 unsigned int int_save;
456 os_task_lock(&int_save);
457 if (wifi_dev != NULL)
458 wifi_dev->priv = NULL;
459 os_task_unlock(int_save);
460
461 /* send sta start failed event, softAP and STA share one task */
462 (void)os_event_write(g_wpa_event, WPA_EVENT_WPA_START_ERROR);
463 }
464
hostapd_interfaces_init(const char * ifname)465 static struct hapd_interfaces *hostapd_interfaces_init(const char *ifname)
466 {
467 struct hapd_interfaces *interfaces = NULL;
468 (void)ifname;
469 interfaces = os_zalloc(sizeof(struct hapd_interfaces));
470 if (interfaces == NULL) {
471 (void)os_event_write(g_wpa_event, WPA_EVENT_WPA_START_ERROR);
472 return NULL;
473 }
474 interfaces->reload_config = hostapd_reload_config;
475 interfaces->config_read_cb = hostapd_config_read2;
476 interfaces->for_each_interface = hostapd_for_each_interface;
477 interfaces->ctrl_iface_init = hostapd_ctrl_iface_init;
478 interfaces->ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
479 interfaces->driver_init = hostapd_driver_init;
480 interfaces->count = 1;
481
482 interfaces->iface = os_calloc(interfaces->count, sizeof(struct hostapd_iface *));
483 if (interfaces->iface == NULL) {
484 wpa_error_log0(MSG_ERROR, "malloc failed");
485 os_free(interfaces);
486 (void)os_event_write(g_wpa_event, WPA_EVENT_WPA_START_ERROR);
487 return NULL;
488 }
489
490 if (hostapd_global_init(interfaces, NULL)) {
491 wpa_error_log0(MSG_ERROR, "Failed to initilize global context");
492 hostapd_global_deinit();
493 os_free(interfaces->iface);
494 os_free(interfaces);
495 (void)os_event_write(g_wpa_event, WPA_EVENT_WPA_START_ERROR);
496 return NULL;
497 }
498
499 return interfaces;
500 }
501
hostapd_get_wifi_dev(const char * ifname)502 static struct ext_wifi_dev * hostapd_get_wifi_dev(const char* ifname)
503 {
504 if (ifname == NULL) {
505 wpa_error_log0(MSG_ERROR, "hostapd_main: ifname is null \n");
506 (void)os_event_write(g_wpa_event, WPA_EVENT_WPA_START_ERROR);
507 return NULL;
508 }
509
510 wpa_debug_level = MSG_DEBUG;
511
512 wpa_printf(MSG_DEBUG, "hostapd_main: ifname = %s", ifname);
513
514 struct ext_wifi_dev *wifi_dev = los_get_wifi_dev_by_name(ifname);
515 if (wifi_dev == NULL) {
516 wpa_error_log0(MSG_ERROR, "hostapd_main: los_get_wifi_dev_by_name failed \n");
517 (void)os_event_write(g_wpa_event, WPA_EVENT_WPA_START_ERROR);
518 return NULL;
519 }
520
521 return wifi_dev;
522 }
523
hostapd_main(const char * ifname)524 void hostapd_main(const char *ifname)
525 {
526 wpa_error_log0(MSG_ERROR, "---> hostapd_main enter.");
527
528 struct ext_wifi_dev *wifi_dev = hostapd_get_wifi_dev(ifname);
529 if (wifi_dev == NULL)
530 return;
531
532 struct hapd_interfaces *interfaces = hostapd_interfaces_init(ifname);
533 if (interfaces == NULL)
534 return;
535
536 /* Allocate and parse configuration for full interface files */
537 for (size_t i = 0; i < interfaces->count; i++) {
538 interfaces->iface[i] = hostapd_interface_init(interfaces, ifname, 0);
539 if (interfaces->iface[i] == NULL) {
540 wpa_error_log0(MSG_ERROR, "Failed to initialize interface");
541 goto OUT;
542 }
543 }
544
545 unsigned int int_save;
546 os_task_lock(&int_save);
547 wifi_dev->priv = g_hapd;
548 os_task_unlock(int_save);
549
550 g_interfaces = interfaces;
551
552 /*
553 * Enable configured interfaces. Depending on channel configuration,
554 * this may complete full initialization before returning or use a
555 * callback mechanism to complete setup in case of operations like HT
556 * co-ex scans, ACS, or DFS are needed to determine channel parameters.
557 * In such case, the interface will be enabled from eloop context within
558 * hostapd_global_run().
559 */
560 interfaces->terminate_on_error = interfaces->count;
561 for (size_t i = 0; i < interfaces->count; i++) {
562 if (hostapd_driver_init(interfaces->iface[i]) || hostapd_setup_interface(interfaces->iface[i]))
563 goto OUT;
564 }
565
566 (void)hostapd_global_ctrl_iface_init(interfaces);
567
568 wpa_error_buf(MSG_ERROR, "hostapd_main: wifi_dev: ifname = %s\n", wifi_dev->ifname, strlen(wifi_dev->ifname));
569 // return 0 on running success, 1 on already running, -1 on running fail.
570 if (hostapd_global_run(interfaces, 0, NULL) >= 0) {
571 (void)os_event_write(g_wpa_event, WPA_EVENT_WPA_START_OK);
572 return;
573 }
574
575 wpa_error_log0(MSG_ERROR, "Failed to start eloop");
576 OUT:
577 hostapd_quit(interfaces, wifi_dev);
578 }
579
580
hostapd_get_interfaces(void)581 struct hapd_interfaces * hostapd_get_interfaces(void)
582 {
583 return g_interfaces;
584 }
585
586