• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params, 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, &params);
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