mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-31 02:17:58 +00:00 
			
		
		
		
	hostapd: add vlan reload support and ap+sta fix
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		 Felix Fietkau
					Felix Fietkau
				
			
				
					committed by
					
						 John Crispin
						John Crispin
					
				
			
			
				
	
			
			
			 John Crispin
						John Crispin
					
				
			
						parent
						
							018f20119d
						
					
				
				
					commit
					1d9b69ee6f
				
			| @@ -215,6 +215,7 @@ function bss_remove_file_fields(config) | ||||
| 	for (let key in config.hash) | ||||
| 		new_cfg.hash[key] = config.hash[key]; | ||||
| 	delete new_cfg.hash.wpa_psk_file; | ||||
| 	delete new_cfg.hash.vlan_file; | ||||
|  | ||||
| 	return new_cfg; | ||||
| } | ||||
| @@ -475,20 +476,19 @@ function iface_reload_config(phydev, config, old_config) | ||||
| 		             bss_remove_file_fields(bss_list_cfg[i]))) { | ||||
| 			hostapd.printf(`Update config data files for bss ${ifname}`); | ||||
| 			if (bss.set_config(config_inline, i, true) < 0) { | ||||
| 				hostapd.printf(`Failed to update config data files for bss ${ifname}`); | ||||
| 				hostapd.printf(`Could not update config data files for bss ${ifname}`); | ||||
| 				return false; | ||||
| 			} | ||||
| 			} else { | ||||
| 				bss.ctrl("RELOAD_WPA_PSK"); | ||||
| 				continue; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		bss_reload_psk(bss, config.bss[i], bss_list_cfg[i]); | ||||
| 		if (is_equal(config.bss[i], bss_list_cfg[i])) | ||||
| 			continue; | ||||
|  | ||||
| 		hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`); | ||||
| 		hostapd.printf(`old: ${bss_remove_file_fields(bss_list_cfg[i])}`); | ||||
| 		hostapd.printf(`new: ${bss_remove_file_fields(config.bss[i])}`); | ||||
| 		if (bss.set_config(config_inline, i) < 0) { | ||||
| 			hostapd.printf(`Failed to set config for bss ${ifname}`); | ||||
| 			return false; | ||||
| @@ -688,7 +688,6 @@ let main_obj = { | ||||
| 				freq_info.csa_count = req.args.csa_count ?? 10; | ||||
| 				ret = iface.switch_channel(freq_info); | ||||
| 			} else { | ||||
| 				iface.stop(); | ||||
| 				ret = iface.start(freq_info); | ||||
| 			} | ||||
| 			if (!ret) | ||||
|   | ||||
| @@ -111,6 +111,94 @@ uc_hostapd_remove_iface(uc_vm_t *vm, size_t nargs) | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static struct hostapd_vlan * | ||||
| bss_conf_find_vlan(struct hostapd_bss_config *bss, int id) | ||||
| { | ||||
| 	struct hostapd_vlan *vlan; | ||||
|  | ||||
| 	for (vlan = bss->vlan; vlan; vlan = vlan->next) | ||||
| 		if (vlan->vlan_id == id) | ||||
| 			return vlan; | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static int | ||||
| bss_conf_rename_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan, | ||||
| 		     const char *ifname) | ||||
| { | ||||
| 	if (!strcmp(ifname, vlan->ifname)) | ||||
| 		return 0; | ||||
|  | ||||
| 	hostapd_drv_if_rename(hapd, WPA_IF_AP_VLAN, vlan->ifname, ifname); | ||||
| 	os_strlcpy(vlan->ifname, ifname, sizeof(vlan->ifname)); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| bss_reload_vlans(struct hostapd_data *hapd, struct hostapd_bss_config *bss) | ||||
| { | ||||
| 	struct hostapd_bss_config *old_bss = hapd->conf; | ||||
| 	struct hostapd_vlan *vlan, *vlan_new, *wildcard; | ||||
| 	char ifname[IFNAMSIZ + 1], vlan_ifname[IFNAMSIZ + 1], *pos; | ||||
| 	int ret; | ||||
|  | ||||
| 	vlan = bss_conf_find_vlan(old_bss, VLAN_ID_WILDCARD); | ||||
| 	wildcard = bss_conf_find_vlan(bss, VLAN_ID_WILDCARD); | ||||
| 	if (!!vlan != !!wildcard) | ||||
| 		return -1; | ||||
|  | ||||
| 	if (vlan && wildcard && strcmp(vlan->ifname, wildcard->ifname) != 0) | ||||
| 		strcpy(vlan->ifname, wildcard->ifname); | ||||
| 	else | ||||
| 		wildcard = NULL; | ||||
|  | ||||
| 	for (vlan = bss->vlan; vlan; vlan = vlan->next) { | ||||
| 		if (vlan->vlan_id == VLAN_ID_WILDCARD || | ||||
| 		    vlan->dynamic_vlan > 0) | ||||
| 			continue; | ||||
|  | ||||
| 		if (!bss_conf_find_vlan(old_bss, vlan->vlan_id)) | ||||
| 			return -1; | ||||
| 	} | ||||
|  | ||||
| 	for (vlan = old_bss->vlan; vlan; vlan = vlan->next) { | ||||
| 		if (vlan->vlan_id == VLAN_ID_WILDCARD) | ||||
| 			continue; | ||||
|  | ||||
| 		if (vlan->dynamic_vlan == 0) { | ||||
| 			vlan_new = bss_conf_find_vlan(bss, vlan->vlan_id); | ||||
| 			if (!vlan_new) | ||||
| 				return -1; | ||||
|  | ||||
| 			if (bss_conf_rename_vlan(hapd, vlan, vlan_new->ifname)) | ||||
| 				return -1; | ||||
|  | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (!wildcard) | ||||
| 			continue; | ||||
|  | ||||
| 		os_strlcpy(ifname, wildcard->ifname, sizeof(ifname)); | ||||
| 		pos = os_strchr(ifname, '#'); | ||||
| 		if (!pos) | ||||
| 			return -1; | ||||
|  | ||||
| 		*pos++ = '\0'; | ||||
| 		ret = os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s%d%s", | ||||
| 				  ifname, vlan->vlan_id, pos); | ||||
| 	        if (os_snprintf_error(sizeof(vlan_ifname), ret)) | ||||
| 			return -1; | ||||
|  | ||||
| 		if (bss_conf_rename_vlan(hapd, vlan, vlan_ifname)) | ||||
| 			return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static uc_value_t * | ||||
| uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs) | ||||
| { | ||||
| @@ -150,6 +238,7 @@ uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs) | ||||
| 	} while (0) | ||||
|  | ||||
| 		swap_field(ssid.wpa_psk_file); | ||||
| 		ret = bss_reload_vlans(hapd, bss); | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| @@ -382,13 +471,23 @@ uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs) | ||||
| 	struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); | ||||
| 	int i; | ||||
|  | ||||
| 	switch (iface->state) { | ||||
| 	case HAPD_IFACE_ENABLED: | ||||
| 	case HAPD_IFACE_DISABLED: | ||||
| 		break; | ||||
| #ifdef CONFIG_ACS | ||||
| 	if (iface->state == HAPD_IFACE_ACS) { | ||||
| 	case HAPD_IFACE_ACS: | ||||
| 		acs_cleanup(iface); | ||||
| 		iface->scan_cb = NULL; | ||||
| 		hostapd_disable_iface(iface); | ||||
| 	} | ||||
| 		/* fallthrough */ | ||||
| #endif | ||||
| 	default: | ||||
| 		hostapd_disable_iface(iface); | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	if (iface->state != HAPD_IFACE_ENABLED) | ||||
| 		hostapd_disable_iface(iface); | ||||
|  | ||||
| 	for (i = 0; i < iface->num_bss; i++) { | ||||
| 		struct hostapd_data *hapd = iface->bss[i]; | ||||
| @@ -396,6 +495,7 @@ uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs) | ||||
| 		hostapd_drv_stop_ap(hapd); | ||||
| 		hapd->beacon_set_done = 0; | ||||
| 	} | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| @@ -405,28 +505,37 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs) | ||||
| 	struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); | ||||
| 	uc_value_t *info = uc_fn_arg(0); | ||||
| 	struct hostapd_config *conf; | ||||
| 	bool changed = false; | ||||
| 	uint64_t intval; | ||||
| 	int i; | ||||
|  | ||||
| 	if (!iface) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if (!info) { | ||||
| 		iface->freq = 0; | ||||
| 	if (!info) | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (ucv_type(info) != UC_OBJECT) | ||||
| 		return NULL; | ||||
|  | ||||
| #define UPDATE_VAL(field, name)							\ | ||||
| 	if ((intval = ucv_int64_get(ucv_object_get(info, name, NULL))) &&	\ | ||||
| 		!errno && intval != conf->field) do {				\ | ||||
| 		conf->field = intval;						\ | ||||
| 		changed = true;							\ | ||||
| 	} while(0) | ||||
|  | ||||
| 	conf = iface->conf; | ||||
| 	if ((intval = ucv_int64_get(ucv_object_get(info, "op_class", NULL))) &&	!errno) | ||||
| 		conf->op_class = intval; | ||||
| 	if ((intval = ucv_int64_get(ucv_object_get(info, "hw_mode", NULL))) && !errno) | ||||
| 		conf->hw_mode = intval; | ||||
| 	if ((intval = ucv_int64_get(ucv_object_get(info, "channel", NULL))) && !errno) | ||||
| 		conf->channel = intval; | ||||
| 	if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno) | ||||
| 		conf->secondary_channel = intval; | ||||
| 	UPDATE_VAL(op_class, "op_class"); | ||||
| 	UPDATE_VAL(hw_mode, "hw_mode"); | ||||
| 	UPDATE_VAL(channel, "channel"); | ||||
| 	UPDATE_VAL(secondary_channel, "sec_channel"); | ||||
| 	if (!changed && | ||||
| 	    (iface->bss[0]->beacon_set_done || | ||||
| 	     iface->state == HAPD_IFACE_DFS)) | ||||
| 		return ucv_boolean_new(true); | ||||
|  | ||||
| 	intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL)); | ||||
| 	if (!errno) | ||||
| @@ -443,6 +552,8 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs) | ||||
| 	intval = ucv_int64_get(ucv_object_get(info, "frequency", NULL)); | ||||
| 	if (!errno) | ||||
| 		iface->freq = intval; | ||||
| 	else | ||||
| 		iface->freq = 0; | ||||
| 	conf->acs = 0; | ||||
|  | ||||
| out: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user