mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-31 02:17:58 +00:00 
			
		
		
		
	ipq9574: add wifi hot-reload
Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
		| @@ -85,6 +85,8 @@ ifneq ($(CONFIG_DRIVER_11AX_SUPPORT),) | |||||||
|   HOSTAPD_IEEE80211BE:=y |   HOSTAPD_IEEE80211BE:=y | ||||||
| endif | endif | ||||||
|  |  | ||||||
|  | CORE_DEPENDS = +libubus +libucode +ucode-mod-fs +ucode-mod-nl80211 +ucode-mod-ubus +ucode-mod-uloop +ucode-mod-rtnl +libblobmsg-json | ||||||
|  |  | ||||||
| DRIVER_MAKEOPTS= \ | DRIVER_MAKEOPTS= \ | ||||||
| 	CONFIG_ACS=$(CONFIG_PACKAGE_kmod-cfg80211) \ | 	CONFIG_ACS=$(CONFIG_PACKAGE_kmod-cfg80211) \ | ||||||
| 	CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-cfg80211) \ | 	CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-cfg80211) \ | ||||||
| @@ -93,6 +95,7 @@ DRIVER_MAKEOPTS= \ | |||||||
| 	CONFIG_IEEE80211AX=$(HOSTAPD_IEEE80211AX) \ | 	CONFIG_IEEE80211AX=$(HOSTAPD_IEEE80211AX) \ | ||||||
| 	CONFIG_IEEE80211BE=$(HOSTAPD_IEEE80211BE) \ | 	CONFIG_IEEE80211BE=$(HOSTAPD_IEEE80211BE) \ | ||||||
| 	CONFIG_DRIVER_WEXT=$(CONFIG_DRIVER_WEXT_SUPPORT) \ | 	CONFIG_DRIVER_WEXT=$(CONFIG_DRIVER_WEXT_SUPPORT) \ | ||||||
|  | 	CONFIG_UCODE=y | ||||||
|  |  | ||||||
| ifeq ($(SSL_VARIANT),openssl) | ifeq ($(SSL_VARIANT),openssl) | ||||||
|   DRIVER_MAKEOPTS += CONFIG_TLS=openssl CONFIG_SAE=y |   DRIVER_MAKEOPTS += CONFIG_TLS=openssl CONFIG_SAE=y | ||||||
| @@ -144,7 +147,7 @@ define Package/hostapd/Default | |||||||
|   SUBMENU:=WirelessAPD |   SUBMENU:=WirelessAPD | ||||||
|   TITLE:=IEEE 802.1x Authenticator |   TITLE:=IEEE 802.1x Authenticator | ||||||
|   URL:=http://hostap.epitest.fi/ |   URL:=http://hostap.epitest.fi/ | ||||||
|   DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus |   DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS) | ||||||
|   USERID:=network=101:network=101 |   USERID:=network=101:network=101 | ||||||
|   PROVIDES:=hostapd |   PROVIDES:=hostapd | ||||||
|   CONFLICTS:=$(HOSTAPD_PROVIDERS) |   CONFLICTS:=$(HOSTAPD_PROVIDERS) | ||||||
| @@ -228,7 +231,7 @@ define Package/wpad/Default | |||||||
|   CATEGORY:=Network |   CATEGORY:=Network | ||||||
|   SUBMENU:=WirelessAPD |   SUBMENU:=WirelessAPD | ||||||
|   TITLE:=IEEE 802.1x Auth/Supplicant |   TITLE:=IEEE 802.1x Auth/Supplicant | ||||||
|   DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus |   DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS) | ||||||
|   USERID:=network=101:network=101 |   USERID:=network=101:network=101 | ||||||
|   URL:=http://hostap.epitest.fi/ |   URL:=http://hostap.epitest.fi/ | ||||||
|   PROVIDES:=hostapd wpa-supplicant |   PROVIDES:=hostapd wpa-supplicant | ||||||
| @@ -505,7 +508,7 @@ TARGET_CPPFLAGS := \ | |||||||
| 	$(if $(CONFIG_WPA_MSG_MIN_PRIORITY),-DCONFIG_MSG_MIN_PRIORITY=$(CONFIG_WPA_MSG_MIN_PRIORITY)) | 	$(if $(CONFIG_WPA_MSG_MIN_PRIORITY),-DCONFIG_MSG_MIN_PRIORITY=$(CONFIG_WPA_MSG_MIN_PRIORITY)) | ||||||
|  |  | ||||||
| TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto | TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto | ||||||
| TARGET_LDFLAGS += -Wl,--gc-sections -flto=jobserver -fuse-linker-plugin -lubox -lubus | TARGET_LDFLAGS += -Wl,--gc-sections -flto=jobserver -fuse-linker-plugin -lubox -lubus -lucode | ||||||
|  |  | ||||||
| ifdef CONFIG_PACKAGE_kmod-cfg80211 | ifdef CONFIG_PACKAGE_kmod-cfg80211 | ||||||
|   TARGET_LDFLAGS += -lm -lnl-tiny |   TARGET_LDFLAGS += -lm -lnl-tiny | ||||||
| @@ -589,20 +592,24 @@ define Build/Compile | |||||||
| endef | endef | ||||||
|  |  | ||||||
| define Install/hostapd | define Install/hostapd | ||||||
| 	$(INSTALL_DIR) $(1)/usr/sbin | 	$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hostap | ||||||
|  | 	$(INSTALL_DATA) ./files/hostapd.uc $(1)/usr/share/hostap/ | ||||||
| endef | endef | ||||||
|  |  | ||||||
| define Install/supplicant | define Install/supplicant | ||||||
| 	$(INSTALL_DIR) $(1)/usr/sbin | 	$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hostap | ||||||
|  | 	$(INSTALL_DATA) ./files/wpa_supplicant.uc $(1)/usr/share/hostap/ | ||||||
| endef | endef | ||||||
|  |  | ||||||
| define Package/hostapd-common/install | define Package/hostapd-common/install | ||||||
| 	$(INSTALL_DIR) $(1)/etc/capabilities $(1)/etc/rc.button $(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d $(1)/lib/netifd  $(1)/usr/share/acl.d | 	$(INSTALL_DIR) $(1)/etc/capabilities $(1)/etc/rc.button $(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d $(1)/lib/netifd  $(1)/usr/share/acl.d $(1)/usr/share/hostap | ||||||
| 	$(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/netifd/hostapd.sh | 	$(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/netifd/hostapd.sh | ||||||
| 	$(INSTALL_BIN) ./files/wpad.init $(1)/etc/init.d/wpad | 	$(INSTALL_BIN) ./files/wpad.init $(1)/etc/init.d/wpad | ||||||
| 	$(INSTALL_BIN) ./files/wps-hotplug.sh $(1)/etc/rc.button/wps | 	$(INSTALL_BIN) ./files/wps-hotplug.sh $(1)/etc/rc.button/wps | ||||||
| 	$(INSTALL_DATA) ./files/wpad_acl.json $(1)/usr/share/acl.d | 	$(INSTALL_DATA) ./files/wpad_acl.json $(1)/usr/share/acl.d | ||||||
| 	$(INSTALL_DATA) ./files/wpad.json $(1)/etc/capabilities | 	$(INSTALL_DATA) ./files/wpad.json $(1)/etc/capabilities | ||||||
|  | 	$(INSTALL_DATA) ./files/common.uc $(1)/usr/share/hostap/ | ||||||
|  | 	$(INSTALL_DATA) ./files/wdev.uc $(1)/usr/share/hostap/ | ||||||
| endef | endef | ||||||
|  |  | ||||||
| define Package/hostapd/install | define Package/hostapd/install | ||||||
|   | |||||||
							
								
								
									
										318
									
								
								feeds/ipq95xx/hostapd/files/common.uc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								feeds/ipq95xx/hostapd/files/common.uc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,318 @@ | |||||||
|  | import * as nl80211 from "nl80211"; | ||||||
|  | import * as rtnl from "rtnl"; | ||||||
|  | import { readfile, glob, basename, readlink } from "fs"; | ||||||
|  |  | ||||||
|  | const iftypes = { | ||||||
|  | 	ap: nl80211.const.NL80211_IFTYPE_AP, | ||||||
|  | 	mesh: nl80211.const.NL80211_IFTYPE_MESH_POINT, | ||||||
|  | 	sta: nl80211.const.NL80211_IFTYPE_STATION, | ||||||
|  | 	adhoc: nl80211.const.NL80211_IFTYPE_ADHOC, | ||||||
|  | 	monitor: nl80211.const.NL80211_IFTYPE_MONITOR, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function wdev_remove(name) | ||||||
|  | { | ||||||
|  | 	nl80211.request(nl80211.const.NL80211_CMD_DEL_INTERFACE, 0, { dev: name }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function __phy_is_fullmac(phyidx) | ||||||
|  | { | ||||||
|  | 	let data = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, 0, { wiphy: phyidx }); | ||||||
|  |  | ||||||
|  | 	return !data.software_iftypes.ap_vlan; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function phy_is_fullmac(phy) | ||||||
|  | { | ||||||
|  | 	let phyidx = int(trim(readfile(`/sys/class/ieee80211/${phy}/index`))); | ||||||
|  |  | ||||||
|  | 	return __phy_is_fullmac(phyidx); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function find_reusable_wdev(phyidx) | ||||||
|  | { | ||||||
|  | 	if (!__phy_is_fullmac(phyidx)) | ||||||
|  | 		return null; | ||||||
|  |  | ||||||
|  | 	let data = nl80211.request( | ||||||
|  | 		nl80211.const.NL80211_CMD_GET_INTERFACE, | ||||||
|  | 		nl80211.const.NLM_F_DUMP, | ||||||
|  | 		{ wiphy: phyidx }); | ||||||
|  | 	for (let res in data) | ||||||
|  | 		if (trim(readfile(`/sys/class/net/${res.ifname}/operstate`)) == "down") | ||||||
|  | 			return res.ifname; | ||||||
|  | 	return null; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function wdev_create(phy, name, data) | ||||||
|  | { | ||||||
|  | 	let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`)); | ||||||
|  |  | ||||||
|  | 	wdev_remove(name); | ||||||
|  |  | ||||||
|  | 	if (!iftypes[data.mode]) | ||||||
|  | 		return `Invalid mode: ${data.mode}`; | ||||||
|  |  | ||||||
|  | 	let req = { | ||||||
|  | 		wiphy: phyidx, | ||||||
|  | 		ifname: name, | ||||||
|  | 		iftype: iftypes[data.mode], | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	if (data["4addr"]) | ||||||
|  | 		req["4addr"] = data["4addr"]; | ||||||
|  | 	if (data.macaddr) | ||||||
|  | 		req.mac = data.macaddr; | ||||||
|  |  | ||||||
|  | 	nl80211.error(); | ||||||
|  |  | ||||||
|  | 	let reuse_ifname = find_reusable_wdev(phyidx); | ||||||
|  | 	if (reuse_ifname && | ||||||
|  | 	    (reuse_ifname == name || | ||||||
|  | 	     rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false)) | ||||||
|  | 		nl80211.request( | ||||||
|  | 			nl80211.const.NL80211_CMD_SET_INTERFACE, 0, { | ||||||
|  | 				wiphy: phyidx, | ||||||
|  | 				dev: name, | ||||||
|  | 				iftype: iftypes[data.mode], | ||||||
|  | 			}); | ||||||
|  | 	else | ||||||
|  | 		nl80211.request( | ||||||
|  | 			nl80211.const.NL80211_CMD_NEW_INTERFACE, | ||||||
|  | 			nl80211.const.NLM_F_CREATE, | ||||||
|  | 			req); | ||||||
|  |  | ||||||
|  | 	let error = nl80211.error(); | ||||||
|  | 	if (error) | ||||||
|  | 		return error; | ||||||
|  |  | ||||||
|  | 	if (data.powersave != null) { | ||||||
|  | 		nl80211.request(nl80211.const.NL80211_CMD_SET_POWER_SAVE, 0, | ||||||
|  | 			{ dev: name, ps_state: data.powersave ? 1 : 0}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return null; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function phy_sysfs_file(phy, name) | ||||||
|  | { | ||||||
|  | 	return trim(readfile(`/sys/class/ieee80211/${phy}/${name}`)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function macaddr_split(str) | ||||||
|  | { | ||||||
|  | 	return map(split(str, ":"), (val) => hex(val)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function macaddr_join(addr) | ||||||
|  | { | ||||||
|  | 	return join(":", map(addr, (val) => sprintf("%02x", val))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function wdev_macaddr(wdev) | ||||||
|  | { | ||||||
|  | 	return trim(readfile(`/sys/class/net/${wdev}/address`)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const phy_proto = { | ||||||
|  | 	macaddr_init: function(used, options) { | ||||||
|  | 		this.macaddr_options = options ?? {}; | ||||||
|  | 		this.macaddr_list = {}; | ||||||
|  |  | ||||||
|  | 		if (type(used) == "object") | ||||||
|  | 			for (let addr in used) | ||||||
|  | 				this.macaddr_list[addr] = used[addr]; | ||||||
|  | 		else | ||||||
|  | 			for (let addr in used) | ||||||
|  | 				this.macaddr_list[addr] = -1; | ||||||
|  |  | ||||||
|  | 		this.for_each_wdev((wdev) => { | ||||||
|  | 			let macaddr = wdev_macaddr(wdev); | ||||||
|  | 			this.macaddr_list[macaddr] ??= -1; | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		return this.macaddr_list; | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	macaddr_generate: function(data) { | ||||||
|  | 		let phy = this.name; | ||||||
|  | 		let idx = int(data.id ?? 0); | ||||||
|  | 		let mbssid = int(data.mbssid ?? 0) > 0; | ||||||
|  | 		let num_global = int(data.num_global ?? 1); | ||||||
|  | 		let use_global = !mbssid && idx < num_global; | ||||||
|  |  | ||||||
|  | 		let base_addr = phy_sysfs_file(phy, "macaddress"); | ||||||
|  | 		if (!base_addr) | ||||||
|  | 			return null; | ||||||
|  |  | ||||||
|  | 		if (!idx && !mbssid) | ||||||
|  | 			return base_addr; | ||||||
|  |  | ||||||
|  | 		let base_mask = phy_sysfs_file(phy, "address_mask"); | ||||||
|  | 		if (!base_mask) | ||||||
|  | 			return null; | ||||||
|  |  | ||||||
|  | 		if (base_mask == "00:00:00:00:00:00" && idx >= num_global) { | ||||||
|  | 			let addrs = split(phy_sysfs_file(phy, "addresses"), "\n"); | ||||||
|  |  | ||||||
|  | 			if (idx < length(addrs)) | ||||||
|  | 				return addrs[idx]; | ||||||
|  |  | ||||||
|  | 			base_mask = "ff:ff:ff:ff:ff:ff"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let addr = macaddr_split(base_addr); | ||||||
|  | 		let mask = macaddr_split(base_mask); | ||||||
|  | 		let type; | ||||||
|  |  | ||||||
|  | 		if (mbssid) | ||||||
|  | 			type = "b5"; | ||||||
|  | 		else if (use_global) | ||||||
|  | 			type = "add"; | ||||||
|  | 		else if (mask[0] > 0) | ||||||
|  | 			type = "b1"; | ||||||
|  | 		else if (mask[5] < 0xff) | ||||||
|  | 			type = "b5"; | ||||||
|  | 		else | ||||||
|  | 			type = "add"; | ||||||
|  |  | ||||||
|  | 		switch (type) { | ||||||
|  | 		case "b1": | ||||||
|  | 			if (!(addr[0] & 2)) | ||||||
|  | 				idx--; | ||||||
|  | 			addr[0] |= 2; | ||||||
|  | 			addr[0] ^= idx << 2; | ||||||
|  | 			break; | ||||||
|  | 		case "b5": | ||||||
|  | 			if (mbssid) | ||||||
|  | 				addr[0] |= 2; | ||||||
|  | 			addr[5] ^= idx; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			for (let i = 5; i > 0; i--) { | ||||||
|  | 				addr[i] += idx; | ||||||
|  | 				if (addr[i] < 256) | ||||||
|  | 					break; | ||||||
|  | 				addr[i] %= 256; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return macaddr_join(addr); | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	macaddr_next: function(val) { | ||||||
|  | 		let data = this.macaddr_options ?? {}; | ||||||
|  | 		let list = this.macaddr_list; | ||||||
|  |  | ||||||
|  | 		for (let i = 0; i < 32; i++) { | ||||||
|  | 			data.id = i; | ||||||
|  |  | ||||||
|  | 			let mac = this.macaddr_generate(data); | ||||||
|  | 			if (!mac) | ||||||
|  | 				return null; | ||||||
|  |  | ||||||
|  | 			if (list[mac] != null) | ||||||
|  | 				continue; | ||||||
|  |  | ||||||
|  | 			list[mac] = val != null ? val : -1; | ||||||
|  | 			return mac; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	for_each_wdev: function(cb) { | ||||||
|  | 		let wdevs = glob(`/sys/class/ieee80211/${this.name}/device/net/*`); | ||||||
|  | 		wdevs = map(wdevs, (arg) => basename(arg)); | ||||||
|  | 		for (let wdev in wdevs) { | ||||||
|  | 			if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != this.name) | ||||||
|  | 				continue; | ||||||
|  |  | ||||||
|  | 			cb(wdev); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function phy_open(phy) | ||||||
|  | { | ||||||
|  | 	let phyidx = readfile(`/sys/class/ieee80211/${phy}/index`); | ||||||
|  | 	if (!phyidx) | ||||||
|  | 		return null; | ||||||
|  |  | ||||||
|  | 	return proto({ | ||||||
|  | 		name: phy, | ||||||
|  | 		idx: int(phyidx) | ||||||
|  | 	}, phy_proto); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const vlist_proto = { | ||||||
|  | 	update: function(values, arg) { | ||||||
|  | 		let data = this.data; | ||||||
|  | 		let cb = this.cb; | ||||||
|  | 		let seq = { }; | ||||||
|  | 		let new_data = {}; | ||||||
|  | 		let old_data = {}; | ||||||
|  |  | ||||||
|  | 		this.data = new_data; | ||||||
|  |  | ||||||
|  | 		if (type(values) == "object") { | ||||||
|  | 			for (let key in values) { | ||||||
|  | 				old_data[key] = data[key]; | ||||||
|  | 				new_data[key] = values[key]; | ||||||
|  | 				delete data[key]; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			for (let val in values) { | ||||||
|  | 				let cur_key = val[0]; | ||||||
|  | 				let cur_obj = val[1]; | ||||||
|  |  | ||||||
|  | 				old_data[cur_key] = data[cur_key]; | ||||||
|  | 				new_data[cur_key] = val[1]; | ||||||
|  | 				delete data[cur_key]; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for (let key in data) { | ||||||
|  | 			cb(null, data[key], arg); | ||||||
|  | 			delete data[key]; | ||||||
|  | 		} | ||||||
|  | 		for (let key in new_data) | ||||||
|  | 			cb(new_data[key], old_data[key], arg); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function is_equal(val1, val2) { | ||||||
|  | 	let t1 = type(val1); | ||||||
|  |  | ||||||
|  | 	if (t1 != type(val2)) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	if (t1 == "array") { | ||||||
|  | 		if (length(val1) != length(val2)) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 		for (let i = 0; i < length(val1); i++) | ||||||
|  | 			if (!is_equal(val1[i], val2[i])) | ||||||
|  | 				return false; | ||||||
|  |  | ||||||
|  | 		return true; | ||||||
|  | 	} else if (t1 == "object") { | ||||||
|  | 		for (let key in val1) | ||||||
|  | 			if (!is_equal(val1[key], val2[key])) | ||||||
|  | 				return false; | ||||||
|  | 		for (let key in val2) | ||||||
|  | 			if (val1[key] == null) | ||||||
|  | 				return false; | ||||||
|  | 		return true; | ||||||
|  | 	} else { | ||||||
|  | 		return val1 == val2; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function vlist_new(cb) { | ||||||
|  | 	return proto({ | ||||||
|  | 			cb: cb, | ||||||
|  | 			data: {} | ||||||
|  | 		}, vlist_proto); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac, phy_open }; | ||||||
| @@ -725,8 +725,7 @@ hostapd_set_bss_options() { | |||||||
| 		[ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N" | 		[ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	set_default nasid "${macaddr//\:}" | 	[ -n "$nasid" ] && append bss_conf "nas_identifier=$nasid" "$N" | ||||||
| 	append bss_conf "nas_identifier=$nasid" "$N" |  | ||||||
|  |  | ||||||
| 	[ -n "$acct_server" ] && { | 	[ -n "$acct_server" ] && { | ||||||
| 		append bss_conf "acct_server_addr=$acct_server" "$N" | 		append bss_conf "acct_server_addr=$acct_server" "$N" | ||||||
| @@ -771,8 +770,8 @@ hostapd_set_bss_options() { | |||||||
| 			wps_possible=1 | 			wps_possible=1 | ||||||
| 			# Here we make the assumption that if we're in open mode | 			# Here we make the assumption that if we're in open mode | ||||||
| 			# with WPS enabled, we got to be in unconfigured state. | 			# with WPS enabled, we got to be in unconfigured state. | ||||||
| 			vlan_possible=1 |  | ||||||
| 			wps_not_configured=1 | 			wps_not_configured=1 | ||||||
|  | 			vlan_possible=1 | ||||||
| 			[ "$macfilter" = radius ] && { | 			[ "$macfilter" = radius ] && { | ||||||
| 				append_radius_server | 				append_radius_server | ||||||
| 			} | 			} | ||||||
| @@ -795,6 +794,9 @@ hostapd_set_bss_options() { | |||||||
| 			[ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N" | 			[ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N" | ||||||
|  |  | ||||||
| 			set_default dynamic_vlan 0 | 			set_default dynamic_vlan 0 | ||||||
|  | 			[ "$macfilter" = radius ] && { | ||||||
|  | 				append_radius_server | ||||||
|  | 			} | ||||||
| 			vlan_possible=1 | 			vlan_possible=1 | ||||||
| 			wps_possible=1 | 			wps_possible=1 | ||||||
| 		;; | 		;; | ||||||
| @@ -1203,9 +1205,6 @@ hostapd_set_bss_options() { | |||||||
| 		append bss_conf "$val" "$N" | 		append bss_conf "$val" "$N" | ||||||
| 	done | 	done | ||||||
|  |  | ||||||
| 	bss_md5sum=$(echo $bss_conf | md5sum | cut -d" " -f1) |  | ||||||
| 	append bss_conf "config_id=$bss_md5sum" "$N" |  | ||||||
|  |  | ||||||
| 	append "$var" "$bss_conf" "$N" | 	append "$var" "$bss_conf" "$N" | ||||||
| 	return 0 | 	return 0 | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										811
									
								
								feeds/ipq95xx/hostapd/files/hostapd.uc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										811
									
								
								feeds/ipq95xx/hostapd/files/hostapd.uc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,811 @@ | |||||||
|  | let libubus = require("ubus"); | ||||||
|  | import { open, readfile } from "fs"; | ||||||
|  | import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common"; | ||||||
|  |  | ||||||
|  | let ubus = libubus.connect(); | ||||||
|  |  | ||||||
|  | hostapd.data.config = {}; | ||||||
|  |  | ||||||
|  | hostapd.data.file_fields = { | ||||||
|  | 	vlan_file: true, | ||||||
|  | 	wpa_psk_file: true, | ||||||
|  | 	accept_mac_file: true, | ||||||
|  | 	deny_mac_file: true, | ||||||
|  | 	eap_user_file: true, | ||||||
|  | 	ca_cert: true, | ||||||
|  | 	server_cert: true, | ||||||
|  | 	server_cert2: true, | ||||||
|  | 	private_key: true, | ||||||
|  | 	private_key2: true, | ||||||
|  | 	dh_file: true, | ||||||
|  | 	eap_sim_db: true, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function iface_remove(cfg) | ||||||
|  | { | ||||||
|  | 	if (!cfg || !cfg.bss || !cfg.bss[0] || !cfg.bss[0].ifname) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	for (let bss in cfg.bss) | ||||||
|  | 		wdev_remove(bss.ifname); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_gen_config(phy, config, start_disabled) | ||||||
|  | { | ||||||
|  | 	let str = `data: | ||||||
|  | ${join("\n", config.radio.data)} | ||||||
|  | channel=${config.radio.channel} | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | 	for (let i = 0; i < length(config.bss); i++) { | ||||||
|  | 		let bss = config.bss[i]; | ||||||
|  | 		let type = i > 0 ? "bss" : "interface"; | ||||||
|  | 		let nasid = bss.nasid ?? replace(bss.bssid, ":", ""); | ||||||
|  |  | ||||||
|  | 		str += ` | ||||||
|  | ${type}=${bss.ifname} | ||||||
|  | bssid=${bss.bssid} | ||||||
|  | ${join("\n", bss.data)} | ||||||
|  | nas_identifier=${nasid} | ||||||
|  | `; | ||||||
|  | 		if (start_disabled) | ||||||
|  | 			str += ` | ||||||
|  | start_disabled=1 | ||||||
|  | `; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return str; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_freq_info(iface, config, params) | ||||||
|  | { | ||||||
|  | 	let freq = params.frequency; | ||||||
|  | 	if (!freq) | ||||||
|  | 		return null; | ||||||
|  |  | ||||||
|  | 	let sec_offset = params.sec_chan_offset; | ||||||
|  | 	if (sec_offset != -1 && sec_offset != 1) | ||||||
|  | 		sec_offset = 0; | ||||||
|  |  | ||||||
|  | 	let width = 0; | ||||||
|  | 	for (let line in config.radio.data) { | ||||||
|  | 		if (!sec_offset && match(line, /^ht_capab=.*HT40/)) { | ||||||
|  | 			sec_offset = null; // auto-detect | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let val = match(line, /^(vht_oper_chwidth|he_oper_chwidth)=(\d+)/); | ||||||
|  | 		if (!val) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		val = int(val[2]); | ||||||
|  | 		if (val > width) | ||||||
|  | 			width = val; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (freq < 4000) | ||||||
|  | 		width = 0; | ||||||
|  |  | ||||||
|  | 	return hostapd.freq_info(freq, sec_offset, width); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_add(phy, config, phy_status) | ||||||
|  | { | ||||||
|  | 	let config_inline = iface_gen_config(phy, config, !!phy_status); | ||||||
|  |  | ||||||
|  | 	let bss = config.bss[0]; | ||||||
|  | 	let ret = hostapd.add_iface(`bss_config=${phy}:${config_inline}`); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	if (!phy_status) | ||||||
|  | 		return true; | ||||||
|  |  | ||||||
|  | 	let iface = hostapd.interfaces[phy]; | ||||||
|  | 	if (!iface) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	let freq_info = iface_freq_info(iface, config, phy_status); | ||||||
|  |  | ||||||
|  | 	return iface.start(freq_info) >= 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_config_macaddr_list(config) | ||||||
|  | { | ||||||
|  | 	let macaddr_list = {}; | ||||||
|  | 	for (let i = 0; i < length(config.bss); i++) { | ||||||
|  | 		let bss = config.bss[i]; | ||||||
|  | 		if (!bss.default_macaddr) | ||||||
|  | 			macaddr_list[bss.bssid] = i; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return macaddr_list; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_restart(phydev, config, old_config) | ||||||
|  | { | ||||||
|  | 	let phy = phydev.name; | ||||||
|  |  | ||||||
|  | 	hostapd.remove_iface(phy); | ||||||
|  | 	iface_remove(old_config); | ||||||
|  | 	iface_remove(config); | ||||||
|  |  | ||||||
|  | 	if (!config.bss || !config.bss[0]) { | ||||||
|  | 		hostapd.printf(`No bss for phy ${phy}`); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	phydev.macaddr_init(iface_config_macaddr_list(config)); | ||||||
|  | 	for (let i = 0; i < length(config.bss); i++) { | ||||||
|  | 		let bss = config.bss[i]; | ||||||
|  | 		if (bss.default_macaddr) | ||||||
|  | 			bss.bssid = phydev.macaddr_next(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	let bss = config.bss[0]; | ||||||
|  | 	let err = wdev_create(phy, bss.ifname, { mode: "ap" }); | ||||||
|  | 	if (err) | ||||||
|  | 		hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); | ||||||
|  |  | ||||||
|  | 	let ubus = hostapd.data.ubus; | ||||||
|  | 	let phy_status = ubus.call("wpa_supplicant", "phy_status", { phy: phy }); | ||||||
|  | 	if (phy_status && phy_status.state == "COMPLETED") { | ||||||
|  | 		if (iface_add(phy, config, phy_status)) | ||||||
|  | 			return; | ||||||
|  |  | ||||||
|  | 		hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true }); | ||||||
|  | 	if (!iface_add(phy, config)) | ||||||
|  | 		hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`); | ||||||
|  | 	ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function array_to_obj(arr, key, start) | ||||||
|  | { | ||||||
|  | 	let obj = {}; | ||||||
|  |  | ||||||
|  | 	start ??= 0; | ||||||
|  | 	for (let i = start; i < length(arr); i++) { | ||||||
|  | 		let cur = arr[i]; | ||||||
|  | 		obj[cur[key]] = cur; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return obj; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function find_array_idx(arr, key, val) | ||||||
|  | { | ||||||
|  | 	for (let i = 0; i < length(arr); i++) | ||||||
|  | 		if (arr[i][key] == val) | ||||||
|  | 			return i; | ||||||
|  |  | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function bss_reload_psk(bss, config, old_config) | ||||||
|  | { | ||||||
|  | 	if (is_equal(old_config.hash.wpa_psk_file, config.hash.wpa_psk_file)) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	old_config.hash.wpa_psk_file = config.hash.wpa_psk_file; | ||||||
|  | 	if (!is_equal(old_config, config)) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	let ret = bss.ctrl("RELOAD_WPA_PSK"); | ||||||
|  | 	ret ??= "failed"; | ||||||
|  |  | ||||||
|  | 	hostapd.printf(`Reload WPA PSK file for bss ${config.ifname}: ${ret}`); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function remove_file_fields(config) | ||||||
|  | { | ||||||
|  | 	return filter(config, (line) => !hostapd.data.file_fields[split(line, "=")[0]]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function bss_remove_file_fields(config) | ||||||
|  | { | ||||||
|  | 	let new_cfg = {}; | ||||||
|  |  | ||||||
|  | 	for (let key in config) | ||||||
|  | 		new_cfg[key] = config[key]; | ||||||
|  | 	new_cfg.data = remove_file_fields(new_cfg.data); | ||||||
|  | 	new_cfg.hash = {}; | ||||||
|  | 	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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function bss_config_hash(config) | ||||||
|  | { | ||||||
|  | 	return hostapd.sha1(remove_file_fields(config) + ""); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function bss_find_existing(config, prev_config, prev_hash) | ||||||
|  | { | ||||||
|  | 	let hash = bss_config_hash(config.data); | ||||||
|  |  | ||||||
|  | 	for (let i = 0; i < length(prev_config.bss); i++) { | ||||||
|  | 		if (!prev_hash[i] || hash != prev_hash[i]) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		prev_hash[i] = null; | ||||||
|  | 		return i; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function get_config_bss(config, idx) | ||||||
|  | { | ||||||
|  | 	if (!config.bss[idx]) { | ||||||
|  | 		hostapd.printf(`Invalid bss index ${idx}`); | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	let ifname = config.bss[idx].ifname; | ||||||
|  | 	if (!ifname) | ||||||
|  | 		hostapd.printf(`Could not find bss ${config.bss[idx].ifname}`); | ||||||
|  |  | ||||||
|  | 	return hostapd.bss[ifname]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_reload_config(phydev, config, old_config) | ||||||
|  | { | ||||||
|  | 	let phy = phydev.name; | ||||||
|  |  | ||||||
|  | 	if (!old_config || !is_equal(old_config.radio, config.radio)) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	if (is_equal(old_config.bss, config.bss)) | ||||||
|  | 		return true; | ||||||
|  |  | ||||||
|  | 	if (!old_config.bss || !old_config.bss[0]) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	let iface = hostapd.interfaces[phy]; | ||||||
|  | 	if (!iface) { | ||||||
|  | 		hostapd.printf(`Could not find previous interface ${iface_name}`); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	let iface_name = old_config.bss[0].ifname; | ||||||
|  | 	let first_bss = hostapd.bss[iface_name]; | ||||||
|  | 	if (!first_bss) { | ||||||
|  | 		hostapd.printf(`Could not find bss of previous interface ${iface_name}`); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	let macaddr_list = iface_config_macaddr_list(config); | ||||||
|  | 	let bss_list = []; | ||||||
|  | 	let bss_list_cfg = []; | ||||||
|  | 	let prev_bss_hash = []; | ||||||
|  |  | ||||||
|  | 	for (let bss in old_config.bss) { | ||||||
|  | 		let hash = bss_config_hash(bss.data); | ||||||
|  | 		push(prev_bss_hash, bss_config_hash(bss.data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Step 1: find (possibly renamed) interfaces with the same config | ||||||
|  | 	// and store them in the new order (with gaps) | ||||||
|  | 	for (let i = 0; i < length(config.bss); i++) { | ||||||
|  | 		let prev; | ||||||
|  |  | ||||||
|  | 		// For fullmac devices, the first interface needs to be preserved, | ||||||
|  | 		// since it's treated as the master | ||||||
|  | 		if (!i && phy_is_fullmac(phy)) { | ||||||
|  | 			prev = 0; | ||||||
|  | 			prev_bss_hash[0] = null; | ||||||
|  | 		} else { | ||||||
|  | 			prev = bss_find_existing(config.bss[i], old_config, prev_bss_hash); | ||||||
|  | 		} | ||||||
|  | 		if (prev < 0) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		let cur_config = config.bss[i]; | ||||||
|  | 		let prev_config = old_config.bss[prev]; | ||||||
|  |  | ||||||
|  | 		let prev_bss = get_config_bss(old_config, prev); | ||||||
|  | 		if (!prev_bss) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 		// try to preserve MAC address of this BSS by reassigning another | ||||||
|  | 		// BSS if necessary | ||||||
|  | 		if (cur_config.default_macaddr && | ||||||
|  | 		    !macaddr_list[prev_config.bssid]) { | ||||||
|  | 			macaddr_list[prev_config.bssid] = i; | ||||||
|  | 			cur_config.bssid = prev_config.bssid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bss_list[i] = prev_bss; | ||||||
|  | 		bss_list_cfg[i] = old_config.bss[prev]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (config.mbssid && !bss_list_cfg[0]) { | ||||||
|  | 		hostapd.printf("First BSS changed with MBSSID enabled"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Step 2: if none were found, rename and preserve the first one | ||||||
|  | 	if (length(bss_list) == 0) { | ||||||
|  | 		// can't change the bssid of the first bss | ||||||
|  | 		if (config.bss[0].bssid != old_config.bss[0].bssid) { | ||||||
|  | 			if (!config.bss[0].default_macaddr) { | ||||||
|  | 				hostapd.printf(`BSSID of first interface changed: ${lc(old_config.bss[0].bssid)} -> ${lc(config.bss[0].bssid)}`); | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			config.bss[0].bssid = old_config.bss[0].bssid; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let prev_bss = get_config_bss(old_config, 0); | ||||||
|  | 		if (!prev_bss) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 		macaddr_list[config.bss[0].bssid] = 0; | ||||||
|  | 		bss_list[0] = prev_bss; | ||||||
|  | 		bss_list_cfg[0] = old_config.bss[0]; | ||||||
|  | 		prev_bss_hash[0] = null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Step 3: delete all unused old interfaces | ||||||
|  | 	for (let i = 0; i < length(prev_bss_hash); i++) { | ||||||
|  | 		if (!prev_bss_hash[i]) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		let prev_bss = get_config_bss(old_config, i); | ||||||
|  | 		if (!prev_bss) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 		let ifname = old_config.bss[i].ifname; | ||||||
|  | 		hostapd.printf(`Remove bss '${ifname}' on phy '${phy}'`); | ||||||
|  | 		prev_bss.delete(); | ||||||
|  | 		wdev_remove(ifname); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Step 4: rename preserved interfaces, use temporary name on duplicates | ||||||
|  | 	let rename_list = []; | ||||||
|  | 	for (let i = 0; i < length(bss_list); i++) { | ||||||
|  | 		if (!bss_list[i]) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		let old_ifname = bss_list_cfg[i].ifname; | ||||||
|  | 		let new_ifname = config.bss[i].ifname; | ||||||
|  | 		if (old_ifname == new_ifname) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		if (hostapd.bss[new_ifname]) { | ||||||
|  | 			new_ifname = "tmp_" + substr(hostapd.sha1(new_ifname), 0, 8); | ||||||
|  | 			push(rename_list, i); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		hostapd.printf(`Rename bss ${old_ifname} to ${new_ifname}`); | ||||||
|  | 		if (!bss_list[i].rename(new_ifname)) { | ||||||
|  | 			hostapd.printf(`Failed to rename bss ${old_ifname} to ${new_ifname}`); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bss_list_cfg[i].ifname = new_ifname; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Step 5: rename interfaces with temporary names | ||||||
|  | 	for (let i in rename_list) { | ||||||
|  | 		let new_ifname = config.bss[i].ifname; | ||||||
|  | 		if (!bss_list[i].rename(new_ifname)) { | ||||||
|  | 			hostapd.printf(`Failed to rename bss to ${new_ifname}`); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		bss_list_cfg[i].ifname = new_ifname; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Step 6: assign BSSID for newly created interfaces | ||||||
|  | 	let macaddr_data = { | ||||||
|  | 		num_global: config.num_global_macaddr ?? 1, | ||||||
|  | 		mbssid: config.mbssid ?? 0, | ||||||
|  | 	}; | ||||||
|  | 	macaddr_list = phydev.macaddr_init(macaddr_list, macaddr_data); | ||||||
|  | 	for (let i = 0; i < length(config.bss); i++) { | ||||||
|  | 		if (bss_list[i]) | ||||||
|  | 			continue; | ||||||
|  | 		let bsscfg = config.bss[i]; | ||||||
|  |  | ||||||
|  | 		let mac_idx = macaddr_list[bsscfg.bssid]; | ||||||
|  | 		if (mac_idx < 0) | ||||||
|  | 			macaddr_list[bsscfg.bssid] = i; | ||||||
|  | 		if (mac_idx == i) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		// statically assigned bssid of the new interface is in conflict | ||||||
|  | 		// with the bssid of a reused interface. reassign the reused interface | ||||||
|  | 		if (!bsscfg.default_macaddr) { | ||||||
|  | 			// can't update bssid of the first BSS, need to restart | ||||||
|  | 			if (!mac_idx < 0) | ||||||
|  | 				return false; | ||||||
|  |  | ||||||
|  | 			bsscfg = config.bss[mac_idx]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let addr = phydev.macaddr_next(i); | ||||||
|  | 		if (!addr) { | ||||||
|  | 			hostapd.printf(`Failed to generate mac address for phy ${phy}`); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		bsscfg.bssid = addr; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	let config_inline = iface_gen_config(phy, config); | ||||||
|  |  | ||||||
|  | 	// Step 7: fill in the gaps with new interfaces | ||||||
|  | 	for (let i = 0; i < length(config.bss); i++) { | ||||||
|  | 		let ifname = config.bss[i].ifname; | ||||||
|  | 		let bss = bss_list[i]; | ||||||
|  |  | ||||||
|  | 		if (bss) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		hostapd.printf(`Add bss ${ifname} on phy ${phy}`); | ||||||
|  | 		bss_list[i] = iface.add_bss(config_inline, i); | ||||||
|  | 		if (!bss_list[i]) { | ||||||
|  | 			hostapd.printf(`Failed to add new bss ${ifname} on phy ${phy}`); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Step 8: update interface bss order | ||||||
|  | 	if (!iface.set_bss_order(bss_list)) { | ||||||
|  | 		hostapd.printf(`Failed to update BSS order on phy '${phy}'`); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Step 9: update config | ||||||
|  | 	for (let i = 0; i < length(config.bss); i++) { | ||||||
|  | 		if (!bss_list_cfg[i]) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		let ifname = config.bss[i].ifname; | ||||||
|  | 		let bss = bss_list[i]; | ||||||
|  |  | ||||||
|  | 		if (is_equal(config.bss[i], bss_list_cfg[i])) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		if (is_equal(bss_remove_file_fields(config.bss[i]), | ||||||
|  | 		             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(`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}'`); | ||||||
|  | 		if (bss.set_config(config_inline, i) < 0) { | ||||||
|  | 			hostapd.printf(`Failed to set config for bss ${ifname}`); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_update_supplicant_macaddr(phy, config) | ||||||
|  | { | ||||||
|  | 	let macaddr_list = []; | ||||||
|  | 	for (let i = 0; i < length(config.bss); i++) | ||||||
|  | 		push(macaddr_list, config.bss[i].bssid); | ||||||
|  | 	ubus.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_set_config(phy, config) | ||||||
|  | { | ||||||
|  | 	let old_config = hostapd.data.config[phy]; | ||||||
|  |  | ||||||
|  | 	hostapd.data.config[phy] = config; | ||||||
|  |  | ||||||
|  | 	if (!config) { | ||||||
|  | 		hostapd.remove_iface(phy); | ||||||
|  | 		return iface_remove(old_config); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	let phydev = phy_open(phy); | ||||||
|  | 	if (!phydev) { | ||||||
|  | 		hostapd.printf(`Failed to open phy ${phy}`); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	try { | ||||||
|  | 		let ret = iface_reload_config(phydev, config, old_config); | ||||||
|  | 		if (ret) { | ||||||
|  | 			iface_update_supplicant_macaddr(phy, config); | ||||||
|  | 			hostapd.printf(`Reloaded settings for phy ${phy}`); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} catch (e) { | ||||||
|  | 			hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hostapd.printf(`Restart interface for phy ${phy}`); | ||||||
|  | 	let ret = iface_restart(phydev, config, old_config); | ||||||
|  | 	iface_update_supplicant_macaddr(phy, config); | ||||||
|  |  | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function config_add_bss(config, name) | ||||||
|  | { | ||||||
|  | 	let bss = { | ||||||
|  | 		ifname: name, | ||||||
|  | 		data: [], | ||||||
|  | 		hash: {} | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	push(config.bss, bss); | ||||||
|  |  | ||||||
|  | 	return bss; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_load_config(filename) | ||||||
|  | { | ||||||
|  | 	let f = open(filename, "r"); | ||||||
|  | 	if (!f) | ||||||
|  | 		return null; | ||||||
|  |  | ||||||
|  | 	let config = { | ||||||
|  | 		radio: { | ||||||
|  | 			data: [] | ||||||
|  | 		}, | ||||||
|  | 		bss: [], | ||||||
|  | 		orig_file: filename, | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	let bss; | ||||||
|  | 	let line; | ||||||
|  | 	while ((line = trim(f.read("line"))) != null) { | ||||||
|  | 		let val = split(line, "=", 2); | ||||||
|  | 		if (!val[0]) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		if (val[0] == "interface") { | ||||||
|  | 			bss = config_add_bss(config, val[1]); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (val[0] == "channel") { | ||||||
|  | 			config.radio.channel = val[1]; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (val[0] == "#num_global_macaddr" || | ||||||
|  | 		    val[0] == "mbssid") | ||||||
|  | 			config[val[0]] = int(val[1]); | ||||||
|  |  | ||||||
|  | 		push(config.radio.data, line); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	while ((line = trim(f.read("line"))) != null) { | ||||||
|  | 		if (line == "#default_macaddr") | ||||||
|  | 			bss.default_macaddr = true; | ||||||
|  |  | ||||||
|  | 		let val = split(line, "=", 2); | ||||||
|  | 		if (!val[0]) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		if (val[0] == "bssid") { | ||||||
|  | 			bss.bssid = lc(val[1]); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (val[0] == "nas_identifier") | ||||||
|  | 			bss.nasid = val[1]; | ||||||
|  |  | ||||||
|  | 		if (val[0] == "bss") { | ||||||
|  | 			bss = config_add_bss(config, val[1]); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (hostapd.data.file_fields[val[0]]) | ||||||
|  | 			bss.hash[val[0]] = hostapd.sha1(readfile(val[1])); | ||||||
|  |  | ||||||
|  | 		push(bss.data, line); | ||||||
|  | 	} | ||||||
|  | 	f.close(); | ||||||
|  |  | ||||||
|  | 	return config; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function ex_wrap(func) { | ||||||
|  | 	return (req) => { | ||||||
|  | 		try { | ||||||
|  | 			let ret = func(req); | ||||||
|  | 			return ret; | ||||||
|  | 		} catch(e) { | ||||||
|  | 			hostapd.printf(`Exception in ubus function: ${e}\n${e.stacktrace[0].context}`); | ||||||
|  | 		} | ||||||
|  | 		return libubus.STATUS_UNKNOWN_ERROR; | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | let main_obj = { | ||||||
|  | 	reload: { | ||||||
|  | 		args: { | ||||||
|  | 			phy: "", | ||||||
|  | 		}, | ||||||
|  | 		call: ex_wrap(function(req) { | ||||||
|  | 			let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config); | ||||||
|  | 			for (let phy_name in phy_list) { | ||||||
|  | 				let phy = hostapd.data.config[phy_name]; | ||||||
|  | 				let config = iface_load_config(phy.orig_file); | ||||||
|  | 				iface_set_config(phy_name, config); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return 0; | ||||||
|  | 		}) | ||||||
|  | 	}, | ||||||
|  | 	apsta_state: { | ||||||
|  | 		args: { | ||||||
|  | 			phy: "", | ||||||
|  | 			up: true, | ||||||
|  | 			frequency: 0, | ||||||
|  | 			sec_chan_offset: 0, | ||||||
|  | 			csa: true, | ||||||
|  | 			csa_count: 0, | ||||||
|  | 		}, | ||||||
|  | 		call: ex_wrap(function(req) { | ||||||
|  | 			if (req.args.up == null || !req.args.phy) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			let phy = req.args.phy; | ||||||
|  | 			let config = hostapd.data.config[phy]; | ||||||
|  | 			if (!config || !config.bss || !config.bss[0] || !config.bss[0].ifname) | ||||||
|  | 				return 0; | ||||||
|  |  | ||||||
|  | 			let iface = hostapd.interfaces[phy]; | ||||||
|  | 			if (!iface) | ||||||
|  | 				return 0; | ||||||
|  |  | ||||||
|  | 			if (!req.args.up) { | ||||||
|  | 				iface.stop(); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (!req.args.frequency) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			let freq_info = iface_freq_info(iface, config, req.args); | ||||||
|  | 			if (!freq_info) | ||||||
|  | 				return libubus.STATUS_UNKNOWN_ERROR; | ||||||
|  |  | ||||||
|  | 			let ret; | ||||||
|  | 			if (req.args.csa) { | ||||||
|  | 				freq_info.csa_count = req.args.csa_count ?? 10; | ||||||
|  | 				ret = iface.switch_channel(freq_info); | ||||||
|  | 			} else { | ||||||
|  | 				ret = iface.start(freq_info); | ||||||
|  | 			} | ||||||
|  | 			if (!ret) | ||||||
|  | 				return libubus.STATUS_UNKNOWN_ERROR; | ||||||
|  |  | ||||||
|  | 			return 0; | ||||||
|  | 		}) | ||||||
|  | 	}, | ||||||
|  | 	config_get_macaddr_list: { | ||||||
|  | 		args: { | ||||||
|  | 			phy: "" | ||||||
|  | 		}, | ||||||
|  | 		call: ex_wrap(function(req) { | ||||||
|  | 			let phy = req.args.phy; | ||||||
|  | 			if (!phy) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			let ret = { | ||||||
|  | 				macaddr: [], | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			let config = hostapd.data.config[phy]; | ||||||
|  | 			if (!config) | ||||||
|  | 				return ret; | ||||||
|  |  | ||||||
|  | 			ret.macaddr = map(config.bss, (bss) => bss.bssid); | ||||||
|  | 			return ret; | ||||||
|  | 		}) | ||||||
|  | 	}, | ||||||
|  | 	config_set: { | ||||||
|  | 		args: { | ||||||
|  | 			phy: "", | ||||||
|  | 			config: "", | ||||||
|  | 			prev_config: "", | ||||||
|  | 		}, | ||||||
|  | 		call: ex_wrap(function(req) { | ||||||
|  | 			let phy = req.args.phy; | ||||||
|  | 			let file = req.args.config; | ||||||
|  | 			let prev_file = req.args.prev_config; | ||||||
|  |  | ||||||
|  | 			if (!phy) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			if (prev_file && !hostapd.data.config[phy]) { | ||||||
|  | 				let config = iface_load_config(prev_file); | ||||||
|  | 				if (config) | ||||||
|  | 					config.radio.data = []; | ||||||
|  | 				hostapd.data.config[phy] = config; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			let config = iface_load_config(file); | ||||||
|  |  | ||||||
|  | 			hostapd.printf(`Set new config for phy ${phy}: ${file}`); | ||||||
|  | 			iface_set_config(phy, config); | ||||||
|  |  | ||||||
|  | 			return { | ||||||
|  | 				pid: hostapd.getpid() | ||||||
|  | 			}; | ||||||
|  | 		}) | ||||||
|  | 	}, | ||||||
|  | 	config_add: { | ||||||
|  | 		args: { | ||||||
|  | 			iface: "", | ||||||
|  | 			config: "", | ||||||
|  | 		}, | ||||||
|  | 		call: ex_wrap(function(req) { | ||||||
|  | 			if (!req.args.iface || !req.args.config) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			if (hostapd.add_iface(`bss_config=${req.args.iface}:${req.args.config}`) < 0) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			return { | ||||||
|  | 				pid: hostapd.getpid() | ||||||
|  | 			}; | ||||||
|  | 		}) | ||||||
|  | 	}, | ||||||
|  | 	config_remove: { | ||||||
|  | 		args: { | ||||||
|  | 			iface: "" | ||||||
|  | 		}, | ||||||
|  | 		call: ex_wrap(function(req) { | ||||||
|  | 			if (!req.args.iface) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			hostapd.remove_iface(req.args.iface); | ||||||
|  | 			return 0; | ||||||
|  | 		}) | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | hostapd.data.ubus = ubus; | ||||||
|  | hostapd.data.obj = ubus.publish("hostapd", main_obj); | ||||||
|  |  | ||||||
|  | function bss_event(type, name, data) { | ||||||
|  | 	let ubus = hostapd.data.ubus; | ||||||
|  |  | ||||||
|  | 	data ??= {}; | ||||||
|  | 	data.name = name; | ||||||
|  | 	hostapd.data.obj.notify(`bss.${type}`, data, null, null, null, -1); | ||||||
|  | 	ubus.call("service", "event", { type: `hostapd.${name}.${type}`, data: {} }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | return { | ||||||
|  | 	shutdown: function() { | ||||||
|  | 		for (let phy in hostapd.data.config) | ||||||
|  | 			iface_set_config(phy, null); | ||||||
|  | 		hostapd.ubus.disconnect(); | ||||||
|  | 	}, | ||||||
|  | 	bss_add: function(name, obj) { | ||||||
|  | 		bss_event("add", name); | ||||||
|  | 	}, | ||||||
|  | 	bss_reload: function(name, obj, reconf) { | ||||||
|  | 		bss_event("reload", name, { reconf: reconf != 0 }); | ||||||
|  | 	}, | ||||||
|  | 	bss_remove: function(name, obj) { | ||||||
|  | 		bss_event("remove", name); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
							
								
								
									
										207
									
								
								feeds/ipq95xx/hostapd/files/wdev.uc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								feeds/ipq95xx/hostapd/files/wdev.uc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | |||||||
|  | #!/usr/bin/env ucode | ||||||
|  | 'use strict'; | ||||||
|  | import { vlist_new, is_equal, wdev_create, wdev_remove, phy_open } from "/usr/share/hostap/common.uc"; | ||||||
|  | import { readfile, writefile, basename, readlink, glob } from "fs"; | ||||||
|  | let libubus = require("ubus"); | ||||||
|  |  | ||||||
|  | let keep_devices = {}; | ||||||
|  | let phy = shift(ARGV); | ||||||
|  | let command = shift(ARGV); | ||||||
|  | let phydev; | ||||||
|  |  | ||||||
|  | const mesh_params = [ | ||||||
|  | 	"mesh_retry_timeout", "mesh_confirm_timeout", "mesh_holding_timeout", "mesh_max_peer_links", | ||||||
|  | 	"mesh_max_retries", "mesh_ttl", "mesh_element_ttl", "mesh_hwmp_max_preq_retries", | ||||||
|  | 	"mesh_path_refresh_time", "mesh_min_discovery_timeout", "mesh_hwmp_active_path_timeout", | ||||||
|  | 	"mesh_hwmp_preq_min_interval", "mesh_hwmp_net_diameter_traversal_time", "mesh_hwmp_rootmode", | ||||||
|  | 	"mesh_hwmp_rann_interval", "mesh_gate_announcements", "mesh_sync_offset_max_neighor", | ||||||
|  | 	"mesh_rssi_threshold", "mesh_hwmp_active_path_to_root_timeout", "mesh_hwmp_root_interval", | ||||||
|  | 	"mesh_hwmp_confirmation_interval", "mesh_awake_window", "mesh_plink_timeout", | ||||||
|  | 	"mesh_auto_open_plinks", "mesh_fwding", "mesh_power_mode" | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | function iface_stop(wdev) | ||||||
|  | { | ||||||
|  | 	if (keep_devices[wdev.ifname]) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	wdev_remove(wdev.ifname); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_start(wdev) | ||||||
|  | { | ||||||
|  | 	let ifname = wdev.ifname; | ||||||
|  |  | ||||||
|  | 	if (readfile(`/sys/class/net/${ifname}/ifindex`)) { | ||||||
|  | 		system([ "ip", "link", "set", "dev", ifname, "down" ]); | ||||||
|  | 		wdev_remove(ifname); | ||||||
|  | 	} | ||||||
|  | 	let wdev_config = {}; | ||||||
|  | 	for (let key in wdev) | ||||||
|  | 		wdev_config[key] = wdev[key]; | ||||||
|  | 	if (!wdev_config.macaddr && wdev.mode != "monitor") | ||||||
|  | 		wdev_config.macaddr = phydev.macaddr_next(); | ||||||
|  | 	wdev_create(phy, ifname, wdev); | ||||||
|  | 	system([ "ip", "link", "set", "dev", ifname, "up" ]); | ||||||
|  | 	if (wdev.freq) | ||||||
|  | 		system(`iw dev ${ifname} set freq ${wdev.freq} ${wdev.htmode}`); | ||||||
|  | 	if (wdev.mode == "adhoc") { | ||||||
|  | 		let cmd = ["iw", "dev", ifname, "ibss", "join", wdev.ssid, wdev.freq, wdev.htmode, "fixed-freq" ]; | ||||||
|  | 		if (wdev.bssid) | ||||||
|  | 			push(cmd, wdev.bssid); | ||||||
|  | 		for (let key in [ "beacon-interval", "basic-rates", "mcast-rate", "keys" ]) | ||||||
|  | 			if (wdev[key]) | ||||||
|  | 				push(cmd, key, wdev[key]); | ||||||
|  | 		system(cmd); | ||||||
|  | 	} else if (wdev.mode == "mesh") { | ||||||
|  | 		let cmd = [ "iw", "dev", ifname, "mesh", "join", wdev.ssid, "freq", wdev.freq, wdev.htmode ]; | ||||||
|  | 		for (let key in [ "mcast-rate", "beacon-interval" ]) | ||||||
|  | 			if (wdev[key]) | ||||||
|  | 				push(cmd, key, wdev[key]); | ||||||
|  | 		system(cmd); | ||||||
|  |  | ||||||
|  | 		cmd = ["iw", "dev", ifname, "set", "mesh_param" ]; | ||||||
|  | 		let len = length(cmd); | ||||||
|  |  | ||||||
|  | 		for (let param in mesh_params) | ||||||
|  | 			if (wdev[param]) | ||||||
|  | 				push(cmd, param, wdev[param]); | ||||||
|  |  | ||||||
|  | 		if (len == length(cmd)) | ||||||
|  | 			return; | ||||||
|  |  | ||||||
|  | 		system(cmd); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_cb(new_if, old_if) | ||||||
|  | { | ||||||
|  | 	if (old_if && new_if && is_equal(old_if, new_if)) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	if (old_if) | ||||||
|  | 		iface_stop(old_if); | ||||||
|  | 	if (new_if) | ||||||
|  | 		iface_start(new_if); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function drop_inactive(config) | ||||||
|  | { | ||||||
|  | 	for (let key in config) { | ||||||
|  | 		if (!readfile(`/sys/class/net/${key}/ifindex`)) | ||||||
|  | 			delete config[key]; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function add_ifname(config) | ||||||
|  | { | ||||||
|  | 	for (let key in config) | ||||||
|  | 		config[key].ifname = key; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function delete_ifname(config) | ||||||
|  | { | ||||||
|  | 	for (let key in config) | ||||||
|  | 		delete config[key].ifname; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function add_existing(phy, config) | ||||||
|  | { | ||||||
|  | 	let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`); | ||||||
|  | 	wdevs = map(wdevs, (arg) => basename(arg)); | ||||||
|  | 	for (let wdev in wdevs) { | ||||||
|  | 		if (config[wdev]) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != phy) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down") | ||||||
|  | 			config[wdev] = {}; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function usage() | ||||||
|  | { | ||||||
|  | 	warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>] | ||||||
|  |  | ||||||
|  | Commands: | ||||||
|  | 	set_config <config> [<device]...] - set phy configuration | ||||||
|  | 	get_macaddr <id>		  - get phy MAC address for vif index <id> | ||||||
|  | `); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const commands = { | ||||||
|  | 	set_config: function(args) { | ||||||
|  | 		let statefile = `/var/run/wdev-${phy}.json`; | ||||||
|  |  | ||||||
|  | 		let new_config = shift(args); | ||||||
|  | 		for (let dev in ARGV) | ||||||
|  | 			keep_devices[dev] = true; | ||||||
|  |  | ||||||
|  | 		if (!new_config) | ||||||
|  | 			usage(); | ||||||
|  |  | ||||||
|  | 		new_config = json(new_config); | ||||||
|  | 		if (!new_config) { | ||||||
|  | 			warn("Invalid configuration\n"); | ||||||
|  | 			exit(1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let old_config = readfile(statefile); | ||||||
|  | 		if (old_config) | ||||||
|  | 			old_config = json(old_config); | ||||||
|  |  | ||||||
|  | 		let config = vlist_new(iface_cb); | ||||||
|  | 		if (type(old_config) == "object") | ||||||
|  | 			config.data = old_config; | ||||||
|  |  | ||||||
|  | 		add_existing(phy, config.data); | ||||||
|  | 		add_ifname(config.data); | ||||||
|  | 		drop_inactive(config.data); | ||||||
|  |  | ||||||
|  | 		let ubus = libubus.connect(); | ||||||
|  | 		let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phy }); | ||||||
|  | 		let macaddr_list = []; | ||||||
|  | 		if (type(data) == "object" && data.macaddr) | ||||||
|  | 			macaddr_list = data.macaddr; | ||||||
|  | 		ubus.disconnect(); | ||||||
|  | 		phydev.macaddr_init(macaddr_list); | ||||||
|  |  | ||||||
|  | 		add_ifname(new_config); | ||||||
|  | 		config.update(new_config); | ||||||
|  |  | ||||||
|  | 		drop_inactive(config.data); | ||||||
|  | 		delete_ifname(config.data); | ||||||
|  | 		writefile(statefile, sprintf("%J", config.data)); | ||||||
|  | 	}, | ||||||
|  | 	get_macaddr: function(args) { | ||||||
|  | 		let data = {}; | ||||||
|  |  | ||||||
|  | 		for (let arg in args) { | ||||||
|  | 			arg = split(arg, "=", 2); | ||||||
|  | 			data[arg[0]] = arg[1]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let macaddr = phydev.macaddr_generate(data); | ||||||
|  | 		if (!macaddr) { | ||||||
|  | 			warn(`Could not get MAC address for phy ${phy}\n`); | ||||||
|  | 			exit(1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		print(macaddr + "\n"); | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | if (!phy || !command | !commands[command]) | ||||||
|  | 	usage(); | ||||||
|  |  | ||||||
|  | phydev = phy_open(phy); | ||||||
|  | if (!phydev) { | ||||||
|  | 	warn(`PHY ${phy} does not exist\n`); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | commands[command](ARGV); | ||||||
							
								
								
									
										330
									
								
								feeds/ipq95xx/hostapd/files/wpa_supplicant.uc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								feeds/ipq95xx/hostapd/files/wpa_supplicant.uc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,330 @@ | |||||||
|  | let libubus = require("ubus"); | ||||||
|  | import { open, readfile } from "fs"; | ||||||
|  | import { wdev_create, wdev_remove, is_equal, vlist_new, phy_open } from "common"; | ||||||
|  |  | ||||||
|  | let ubus = libubus.connect(); | ||||||
|  |  | ||||||
|  | wpas.data.config = {}; | ||||||
|  | wpas.data.iface_phy = {}; | ||||||
|  | wpas.data.macaddr_list = {}; | ||||||
|  |  | ||||||
|  | function iface_stop(iface) | ||||||
|  | { | ||||||
|  | 	let ifname = iface.config.iface; | ||||||
|  |  | ||||||
|  | 	if (!iface.running) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	delete wpas.data.iface_phy[ifname]; | ||||||
|  | 	wpas.remove_iface(ifname); | ||||||
|  | 	wdev_remove(ifname); | ||||||
|  | 	iface.running = false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_start(phydev, iface, macaddr_list) | ||||||
|  | { | ||||||
|  | 	let phy = phydev.name; | ||||||
|  |  | ||||||
|  | 	if (iface.running) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	let ifname = iface.config.iface; | ||||||
|  | 	let wdev_config = {}; | ||||||
|  | 	for (let field in iface.config) | ||||||
|  | 		wdev_config[field] = iface.config[field]; | ||||||
|  | 	if (!wdev_config.macaddr) | ||||||
|  | 		wdev_config.macaddr = phydev.macaddr_next(); | ||||||
|  |  | ||||||
|  | 	wpas.data.iface_phy[ifname] = phy; | ||||||
|  | 	wdev_remove(ifname); | ||||||
|  | 	let ret = wdev_create(phy, ifname, wdev_config); | ||||||
|  | 	if (ret) | ||||||
|  | 		wpas.printf(`Failed to create device ${ifname}: ${ret}`); | ||||||
|  | 	wpas.add_iface(iface.config); | ||||||
|  | 	iface.running = true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_cb(new_if, old_if) | ||||||
|  | { | ||||||
|  | 	if (old_if && new_if && is_equal(old_if.config, new_if.config)) { | ||||||
|  | 		new_if.running = old_if.running; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (new_if && old_if) | ||||||
|  | 		wpas.printf(`Update configuration for interface ${old_if.config.iface}`); | ||||||
|  | 	else if (old_if) | ||||||
|  | 		wpas.printf(`Remove interface ${old_if.config.iface}`); | ||||||
|  |  | ||||||
|  | 	if (old_if) | ||||||
|  | 		iface_stop(old_if); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function prepare_config(config) | ||||||
|  | { | ||||||
|  | 	config.config_data = readfile(config.config); | ||||||
|  |  | ||||||
|  | 	return { config: config }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function set_config(phy_name, config_list) | ||||||
|  | { | ||||||
|  | 	let phy = wpas.data.config[phy_name]; | ||||||
|  |  | ||||||
|  | 	if (!phy) { | ||||||
|  | 		phy = vlist_new(iface_cb, false); | ||||||
|  | 		wpas.data.config[phy_name] = phy; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	let values = []; | ||||||
|  | 	for (let config in config_list) | ||||||
|  | 		push(values, [ config.iface, prepare_config(config) ]); | ||||||
|  |  | ||||||
|  | 	phy.update(values); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function start_pending(phy_name) | ||||||
|  | { | ||||||
|  | 	let phy = wpas.data.config[phy_name]; | ||||||
|  | 	let ubus = wpas.data.ubus; | ||||||
|  |  | ||||||
|  | 	if (!phy || !phy.data) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	let phydev = phy_open(phy_name); | ||||||
|  | 	if (!phydev) { | ||||||
|  | 		wpas.printf(`Could not open phy ${phy_name}`); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	let macaddr_list = wpas.data.macaddr_list[phy_name]; | ||||||
|  | 	phydev.macaddr_init(macaddr_list); | ||||||
|  |  | ||||||
|  | 	for (let ifname in phy.data) | ||||||
|  | 		iface_start(phydev, phy.data[ifname]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | let main_obj = { | ||||||
|  | 	phy_set_state: { | ||||||
|  | 		args: { | ||||||
|  | 			phy: "", | ||||||
|  | 			stop: true, | ||||||
|  | 		}, | ||||||
|  | 		call: function(req) { | ||||||
|  | 			if (!req.args.phy || req.args.stop == null) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			let phy = wpas.data.config[req.args.phy]; | ||||||
|  | 			if (!phy) | ||||||
|  | 				return libubus.STATUS_NOT_FOUND; | ||||||
|  |  | ||||||
|  | 			try { | ||||||
|  | 				if (req.args.stop) { | ||||||
|  | 					for (let ifname in phy.data) | ||||||
|  | 						iface_stop(phy.data[ifname]); | ||||||
|  | 				} else { | ||||||
|  | 					start_pending(req.args.phy); | ||||||
|  | 				} | ||||||
|  | 			} catch (e) { | ||||||
|  | 				wpas.printf(`Error chaging state: ${e}\n${e.stacktrace[0].context}`); | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  | 			} | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	phy_set_macaddr_list: { | ||||||
|  | 		args: { | ||||||
|  | 			phy: "", | ||||||
|  | 			macaddr: [], | ||||||
|  | 		}, | ||||||
|  | 		call: function(req) { | ||||||
|  | 			let phy = req.args.phy; | ||||||
|  | 			if (!phy) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			wpas.data.macaddr_list[phy] = req.args.macaddr; | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	phy_status: { | ||||||
|  | 		args: { | ||||||
|  | 			phy: "" | ||||||
|  | 		}, | ||||||
|  | 		call: function(req) { | ||||||
|  | 			if (!req.args.phy) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			let phy = wpas.data.config[req.args.phy]; | ||||||
|  | 			if (!phy) | ||||||
|  | 				return libubus.STATUS_NOT_FOUND; | ||||||
|  |  | ||||||
|  | 			for (let ifname in phy.data) { | ||||||
|  | 				try { | ||||||
|  | 					let iface = wpas.interfaces[ifname]; | ||||||
|  | 					if (!iface) | ||||||
|  | 						continue; | ||||||
|  |  | ||||||
|  | 					let status = iface.status(); | ||||||
|  | 					if (!status) | ||||||
|  | 						continue; | ||||||
|  |  | ||||||
|  | 					if (status.state == "INTERFACE_DISABLED") | ||||||
|  | 						continue; | ||||||
|  |  | ||||||
|  | 					status.ifname = ifname; | ||||||
|  | 					return status; | ||||||
|  | 				} catch (e) { | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return libubus.STATUS_NOT_FOUND; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	config_set: { | ||||||
|  | 		args: { | ||||||
|  | 			phy: "", | ||||||
|  | 			config: [], | ||||||
|  | 			defer: true, | ||||||
|  | 		}, | ||||||
|  | 		call: function(req) { | ||||||
|  | 			if (!req.args.phy) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			wpas.printf(`Set new config for phy ${req.args.phy}`); | ||||||
|  | 			try { | ||||||
|  | 				if (req.args.config) | ||||||
|  | 					set_config(req.args.phy, req.args.config); | ||||||
|  |  | ||||||
|  | 				if (!req.args.defer) | ||||||
|  | 					start_pending(req.args.phy); | ||||||
|  | 			} catch (e) { | ||||||
|  | 				wpas.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`); | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return { | ||||||
|  | 				pid: wpas.getpid() | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	config_add: { | ||||||
|  | 		args: { | ||||||
|  | 			driver: "", | ||||||
|  | 			iface: "", | ||||||
|  | 			bridge: "", | ||||||
|  | 			hostapd_ctrl: "", | ||||||
|  | 			ctrl: "", | ||||||
|  | 			config: "", | ||||||
|  | 		}, | ||||||
|  | 		call: function(req) { | ||||||
|  | 			if (!req.args.iface || !req.args.config) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			if (wpas.add_iface(req.args) < 0) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			return { | ||||||
|  | 				pid: wpas.getpid() | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	config_remove: { | ||||||
|  | 		args: { | ||||||
|  | 			iface: "" | ||||||
|  | 		}, | ||||||
|  | 		call: function(req) { | ||||||
|  | 			if (!req.args.iface) | ||||||
|  | 				return libubus.STATUS_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  | 			wpas.remove_iface(req.args.iface); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | wpas.data.ubus = ubus; | ||||||
|  | wpas.data.obj = ubus.publish("wpa_supplicant", main_obj); | ||||||
|  |  | ||||||
|  | function iface_event(type, name, data) { | ||||||
|  | 	let ubus = wpas.data.ubus; | ||||||
|  |  | ||||||
|  | 	data ??= {}; | ||||||
|  | 	data.name = name; | ||||||
|  | 	wpas.data.obj.notify(`iface.${type}`, data, null, null, null, -1); | ||||||
|  | 	ubus.call("service", "event", { type: `wpa_supplicant.${name}.${type}`, data: {} }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_hostapd_notify(phy, ifname, iface, state) | ||||||
|  | { | ||||||
|  | 	let ubus = wpas.data.ubus; | ||||||
|  | 	let status = iface.status(); | ||||||
|  | 	let msg = { phy: phy }; | ||||||
|  |  | ||||||
|  | 	switch (state) { | ||||||
|  | 	case "DISCONNECTED": | ||||||
|  | 	case "AUTHENTICATING": | ||||||
|  | 	case "SCANNING": | ||||||
|  | 		msg.up = false; | ||||||
|  | 		break; | ||||||
|  | 	case "INTERFACE_DISABLED": | ||||||
|  | 	case "INACTIVE": | ||||||
|  | 		msg.up = true; | ||||||
|  | 		break; | ||||||
|  | 	case "COMPLETED": | ||||||
|  | 		msg.up = true; | ||||||
|  | 		msg.frequency = status.frequency; | ||||||
|  | 		msg.sec_chan_offset = status.sec_chan_offset; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ubus.call("hostapd", "apsta_state", msg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function iface_channel_switch(phy, ifname, iface, info) | ||||||
|  | { | ||||||
|  | 	let msg = { | ||||||
|  | 		phy: phy, | ||||||
|  | 		up: true, | ||||||
|  | 		csa: true, | ||||||
|  | 		csa_count: info.csa_count ? info.csa_count - 1 : 0, | ||||||
|  | 		frequency: info.frequency, | ||||||
|  | 		sec_chan_offset: info.sec_chan_offset, | ||||||
|  | 	}; | ||||||
|  | 	ubus.call("hostapd", "apsta_state", msg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | return { | ||||||
|  | 	shutdown: function() { | ||||||
|  | 		for (let phy in wpas.data.config) | ||||||
|  | 			set_config(phy, []); | ||||||
|  | 		wpas.ubus.disconnect(); | ||||||
|  | 	}, | ||||||
|  | 	iface_add: function(name, obj) { | ||||||
|  | 		iface_event("add", name); | ||||||
|  | 	}, | ||||||
|  | 	iface_remove: function(name, obj) { | ||||||
|  | 		iface_event("remove", name); | ||||||
|  | 	}, | ||||||
|  | 	state: function(ifname, iface, state) { | ||||||
|  | 		let phy = wpas.data.iface_phy[ifname]; | ||||||
|  | 		if (!phy) { | ||||||
|  | 			wpas.printf(`no PHY for ifname ${ifname}`); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		iface_hostapd_notify(phy, ifname, iface, state); | ||||||
|  | 	}, | ||||||
|  | 	event: function(ifname, iface, ev, info) { | ||||||
|  | 		let phy = wpas.data.iface_phy[ifname]; | ||||||
|  | 		if (!phy) { | ||||||
|  | 			wpas.printf(`no PHY for ifname ${ifname}`); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (ev == "CH_SWITCH_STARTED") | ||||||
|  | 			iface_channel_switch(phy, ifname, iface, info); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
| @@ -72,7 +72,7 @@ | |||||||
|  include ../src/build.rules |  include ../src/build.rules | ||||||
|   |   | ||||||
|  ifdef LIBS |  ifdef LIBS | ||||||
| @@ -359,7 +360,9 @@ endif | @@ -354,7 +355,9 @@ endif | ||||||
|  ifdef CONFIG_IBSS_RSN |  ifdef CONFIG_IBSS_RSN | ||||||
|  NEED_RSN_AUTHENTICATOR=y |  NEED_RSN_AUTHENTICATOR=y | ||||||
|  CFLAGS += -DCONFIG_IBSS_RSN |  CFLAGS += -DCONFIG_IBSS_RSN | ||||||
| @@ -82,7 +82,7 @@ | |||||||
|  OBJS += ibss_rsn.o |  OBJS += ibss_rsn.o | ||||||
|  endif |  endif | ||||||
|   |   | ||||||
| @@ -897,6 +900,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS | @@ -886,6 +889,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS | ||||||
|  CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS |  CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS | ||||||
|  LIBS += -ldl -rdynamic |  LIBS += -ldl -rdynamic | ||||||
|  endif |  endif | ||||||
| @@ -93,7 +93,7 @@ | |||||||
|  endif |  endif | ||||||
|   |   | ||||||
|  ifdef CONFIG_AP |  ifdef CONFIG_AP | ||||||
| @@ -904,9 +911,11 @@ NEED_EAP_COMMON=y | @@ -893,9 +900,11 @@ NEED_EAP_COMMON=y | ||||||
|  NEED_RSN_AUTHENTICATOR=y |  NEED_RSN_AUTHENTICATOR=y | ||||||
|  CFLAGS += -DCONFIG_AP |  CFLAGS += -DCONFIG_AP | ||||||
|  OBJS += ap.o |  OBJS += ap.o | ||||||
| @@ -105,7 +105,7 @@ | |||||||
|  OBJS += ../src/ap/hostapd.o |  OBJS += ../src/ap/hostapd.o | ||||||
|  OBJS += ../src/ap/wpa_auth_glue.o |  OBJS += ../src/ap/wpa_auth_glue.o | ||||||
|  OBJS += ../src/ap/utils.o |  OBJS += ../src/ap/utils.o | ||||||
| @@ -986,6 +995,12 @@ endif | @@ -975,6 +984,12 @@ endif | ||||||
|  ifdef CONFIG_HS20 |  ifdef CONFIG_HS20 | ||||||
|  OBJS += ../src/ap/hs20.o |  OBJS += ../src/ap/hs20.o | ||||||
|  endif |  endif | ||||||
| @@ -118,7 +118,7 @@ | |||||||
|  endif |  endif | ||||||
|   |   | ||||||
|  ifdef CONFIG_MBO |  ifdef CONFIG_MBO | ||||||
| @@ -994,7 +1009,9 @@ CFLAGS += -DCONFIG_MBO | @@ -983,7 +998,9 @@ CFLAGS += -DCONFIG_MBO | ||||||
|  endif |  endif | ||||||
|   |   | ||||||
|  ifdef NEED_RSN_AUTHENTICATOR |  ifdef NEED_RSN_AUTHENTICATOR | ||||||
| @@ -128,7 +128,7 @@ | |||||||
|  NEED_AES_WRAP=y |  NEED_AES_WRAP=y | ||||||
|  OBJS += ../src/ap/wpa_auth.o |  OBJS += ../src/ap/wpa_auth.o | ||||||
|  OBJS += ../src/ap/wpa_auth_ie.o |  OBJS += ../src/ap/wpa_auth_ie.o | ||||||
| @@ -1889,6 +1906,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv) | @@ -1878,6 +1895,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv) | ||||||
|   |   | ||||||
|  _OBJS_VAR := OBJS |  _OBJS_VAR := OBJS | ||||||
|  include ../src/objs.mk |  include ../src/objs.mk | ||||||
| @@ -141,7 +141,7 @@ | |||||||
|  wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) |  wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) | ||||||
|  	$(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) |  	$(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) | ||||||
|  	@$(E) "  LD " $@ |  	@$(E) "  LD " $@ | ||||||
| @@ -2021,6 +2044,12 @@ eap_gpsk.so: $(SRC_EAP_GPSK) | @@ -1983,6 +2006,12 @@ eap_eke.so: ../src/eap_peer/eap_eke.c .. | ||||||
|  	$(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@ |  	$(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@ | ||||||
|  	@$(E) "  sed" $< |  	@$(E) "  sed" $< | ||||||
|   |   | ||||||
| @@ -156,7 +156,7 @@ | |||||||
|  wpa_cli.exe: wpa_cli |  wpa_cli.exe: wpa_cli | ||||||
| --- a/src/drivers/driver.h | --- a/src/drivers/driver.h | ||||||
| +++ b/src/drivers/driver.h | +++ b/src/drivers/driver.h | ||||||
| @@ -6025,8 +6025,8 @@ union wpa_event_data { | @@ -6018,8 +6018,8 @@ union wpa_event_data { | ||||||
|   * Driver wrapper code should call this function whenever an event is received |   * Driver wrapper code should call this function whenever an event is received | ||||||
|   * from the driver. |   * from the driver. | ||||||
|   */ |   */ | ||||||
| @@ -167,7 +167,7 @@ | |||||||
|   |   | ||||||
|  /** |  /** | ||||||
|   * wpa_supplicant_event_global - Report a driver event for wpa_supplicant |   * wpa_supplicant_event_global - Report a driver event for wpa_supplicant | ||||||
| @@ -6038,7 +6038,7 @@ void wpa_supplicant_event(void *ctx, enu | @@ -6031,7 +6031,7 @@ void wpa_supplicant_event(void *ctx, enu | ||||||
|   * Same as wpa_supplicant_event(), but we search for the interface in |   * Same as wpa_supplicant_event(), but we search for the interface in | ||||||
|   * wpa_global. |   * wpa_global. | ||||||
|   */ |   */ | ||||||
| @@ -178,7 +178,7 @@ | |||||||
|  /* |  /* | ||||||
| --- a/src/ap/drv_callbacks.c | --- a/src/ap/drv_callbacks.c | ||||||
| +++ b/src/ap/drv_callbacks.c | +++ b/src/ap/drv_callbacks.c | ||||||
| @@ -1836,8 +1836,8 @@ err: | @@ -1827,8 +1827,8 @@ err: | ||||||
|  #endif /* CONFIG_OWE */ |  #endif /* CONFIG_OWE */ | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -189,7 +189,7 @@ | |||||||
|  { |  { | ||||||
|  	struct hostapd_data *hapd = ctx; |  	struct hostapd_data *hapd = ctx; | ||||||
|  #ifndef CONFIG_NO_STDOUT_DEBUG |  #ifndef CONFIG_NO_STDOUT_DEBUG | ||||||
| @@ -2082,7 +2082,7 @@ void wpa_supplicant_event(void *ctx, enu | @@ -2073,7 +2073,7 @@ void wpa_supplicant_event(void *ctx, enu | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -231,7 +231,7 @@ | |||||||
|  	os_memset(&global, 0, sizeof(global)); |  	os_memset(&global, 0, sizeof(global)); | ||||||
| --- a/wpa_supplicant/events.c | --- a/wpa_supplicant/events.c | ||||||
| +++ b/wpa_supplicant/events.c | +++ b/wpa_supplicant/events.c | ||||||
| @@ -4665,8 +4665,8 @@ static void wpas_event_unprot_beacon(str | @@ -4666,8 +4666,8 @@ static void wpas_event_unprot_beacon(str | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -242,7 +242,7 @@ | |||||||
|  { |  { | ||||||
|  	struct wpa_supplicant *wpa_s = ctx; |  	struct wpa_supplicant *wpa_s = ctx; | ||||||
|  	int resched; |  	int resched; | ||||||
| @@ -5511,7 +5511,7 @@ void wpa_supplicant_event(void *ctx, enu | @@ -5512,7 +5512,7 @@ void wpa_supplicant_event(void *ctx, enu | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -253,7 +253,7 @@ | |||||||
|  	struct wpa_supplicant *wpa_s; |  	struct wpa_supplicant *wpa_s; | ||||||
| --- a/wpa_supplicant/wpa_supplicant.c | --- a/wpa_supplicant/wpa_supplicant.c | ||||||
| +++ b/wpa_supplicant/wpa_supplicant.c | +++ b/wpa_supplicant/wpa_supplicant.c | ||||||
| @@ -6819,7 +6819,6 @@ struct wpa_interface * wpa_supplicant_ma | @@ -6814,7 +6814,6 @@ struct wpa_interface * wpa_supplicant_ma | ||||||
|  	return NULL; |  	return NULL; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -261,7 +261,7 @@ | |||||||
|  /** |  /** | ||||||
|   * wpa_supplicant_match_existing - Match existing interfaces |   * wpa_supplicant_match_existing - Match existing interfaces | ||||||
|   * @global: Pointer to global data from wpa_supplicant_init() |   * @global: Pointer to global data from wpa_supplicant_init() | ||||||
| @@ -6854,6 +6853,11 @@ static int wpa_supplicant_match_existing | @@ -6849,6 +6848,11 @@ static int wpa_supplicant_match_existing | ||||||
|   |   | ||||||
|  #endif /* CONFIG_MATCH_IFACE */ |  #endif /* CONFIG_MATCH_IFACE */ | ||||||
|   |   | ||||||
| @@ -273,7 +273,7 @@ | |||||||
|   |   | ||||||
|  /** |  /** | ||||||
|   * wpa_supplicant_add_iface - Add a new network interface |   * wpa_supplicant_add_iface - Add a new network interface | ||||||
| @@ -7110,6 +7114,8 @@ struct wpa_global * wpa_supplicant_init( | @@ -7105,6 +7109,8 @@ struct wpa_global * wpa_supplicant_init( | ||||||
|  #ifndef CONFIG_NO_WPA_MSG |  #ifndef CONFIG_NO_WPA_MSG | ||||||
|  	wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb); |  	wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb); | ||||||
|  #endif /* CONFIG_NO_WPA_MSG */ |  #endif /* CONFIG_NO_WPA_MSG */ | ||||||
| @@ -333,7 +333,7 @@ | |||||||
|   |   | ||||||
|  const struct wpa_driver_ops *const wpa_drivers[] = { NULL }; |  const struct wpa_driver_ops *const wpa_drivers[] = { NULL }; | ||||||
|   |   | ||||||
| @@ -1291,6 +1296,10 @@ static void usage(void) | @@ -1292,6 +1297,10 @@ static void usage(void) | ||||||
|  	       "option several times.\n"); |  	       "option several times.\n"); | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -344,7 +344,7 @@ | |||||||
|   |   | ||||||
|  int main(int argc, char *argv[]) |  int main(int argc, char *argv[]) | ||||||
|  { |  { | ||||||
| @@ -1311,6 +1320,8 @@ int main(int argc, char *argv[]) | @@ -1312,6 +1321,8 @@ int main(int argc, char *argv[]) | ||||||
|  	if (os_program_init()) |  	if (os_program_init()) | ||||||
|  		return -1; |  		return -1; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/hostapd/config_file.c | --- a/hostapd/config_file.c | ||||||
| +++ b/hostapd/config_file.c | +++ b/hostapd/config_file.c | ||||||
| @@ -3459,6 +3459,10 @@ static int hostapd_config_fill(struct ho | @@ -3439,6 +3439,10 @@ static int hostapd_config_fill(struct ho | ||||||
|  		if (bss->ocv && !bss->ieee80211w) |  		if (bss->ocv && !bss->ieee80211w) | ||||||
|  			bss->ieee80211w = 1; |  			bss->ieee80211w = 1; | ||||||
|  #endif /* CONFIG_OCV */ |  #endif /* CONFIG_OCV */ | ||||||
| @@ -13,7 +13,7 @@ | |||||||
|  	} else if (os_strcmp(buf, "ht_capab") == 0) { |  	} else if (os_strcmp(buf, "ht_capab") == 0) { | ||||||
| --- a/src/ap/ap_config.h | --- a/src/ap/ap_config.h | ||||||
| +++ b/src/ap/ap_config.h | +++ b/src/ap/ap_config.h | ||||||
| @@ -1009,6 +1009,8 @@ struct hostapd_config { | @@ -995,6 +995,8 @@ struct hostapd_config { | ||||||
|   |   | ||||||
|  	int ht_op_mode_fixed; |  	int ht_op_mode_fixed; | ||||||
|  	u16 ht_capab; |  	u16 ht_capab; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/wpa_supplicant/wpa_supplicant.c | --- a/wpa_supplicant/wpa_supplicant.c | ||||||
| +++ b/wpa_supplicant/wpa_supplicant.c | +++ b/wpa_supplicant/wpa_supplicant.c | ||||||
| @@ -5154,7 +5154,7 @@ wpa_supplicant_alloc(struct wpa_supplica | @@ -5147,7 +5147,7 @@ wpa_supplicant_alloc(struct wpa_supplica | ||||||
|  	if (wpa_s == NULL) |  	if (wpa_s == NULL) | ||||||
|  		return NULL; |  		return NULL; | ||||||
|  	wpa_s->scan_req = INITIAL_SCAN_REQ; |  	wpa_s->scan_req = INITIAL_SCAN_REQ; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/src/drivers/drivers.mak | --- a/src/drivers/drivers.mak | ||||||
| +++ b/src/drivers/drivers.mak | +++ b/src/drivers/drivers.mak | ||||||
| @@ -54,7 +54,6 @@ NEED_SME=y | @@ -50,7 +50,6 @@ NEED_SME=y | ||||||
|  NEED_AP_MLME=y |  NEED_AP_MLME=y | ||||||
|  NEED_NETLINK=y |  NEED_NETLINK=y | ||||||
|  NEED_LINUX_IOCTL=y |  NEED_LINUX_IOCTL=y | ||||||
| @@ -8,7 +8,7 @@ | |||||||
|  NEED_RADIOTAP=y |  NEED_RADIOTAP=y | ||||||
|  NEED_LIBNL=y |  NEED_LIBNL=y | ||||||
|  endif |  endif | ||||||
| @@ -111,7 +110,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT | @@ -107,7 +106,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT | ||||||
|  CONFIG_WIRELESS_EXTENSION=y |  CONFIG_WIRELESS_EXTENSION=y | ||||||
|  NEED_NETLINK=y |  NEED_NETLINK=y | ||||||
|  NEED_LINUX_IOCTL=y |  NEED_LINUX_IOCTL=y | ||||||
| @@ -16,7 +16,7 @@ | |||||||
|  endif |  endif | ||||||
|   |   | ||||||
|  ifdef CONFIG_DRIVER_NDIS |  ifdef CONFIG_DRIVER_NDIS | ||||||
| @@ -137,7 +135,6 @@ endif | @@ -133,7 +131,6 @@ endif | ||||||
|  ifdef CONFIG_WIRELESS_EXTENSION |  ifdef CONFIG_WIRELESS_EXTENSION | ||||||
|  DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION |  DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION | ||||||
|  DRV_WPA_OBJS += ../src/drivers/driver_wext.o |  DRV_WPA_OBJS += ../src/drivers/driver_wext.o | ||||||
| @@ -24,7 +24,7 @@ | |||||||
|  endif |  endif | ||||||
|   |   | ||||||
|  ifdef NEED_NETLINK |  ifdef NEED_NETLINK | ||||||
| @@ -146,6 +143,7 @@ endif | @@ -142,6 +139,7 @@ endif | ||||||
|   |   | ||||||
|  ifdef NEED_RFKILL |  ifdef NEED_RFKILL | ||||||
|  DRV_OBJS += ../src/drivers/rfkill.o |  DRV_OBJS += ../src/drivers/rfkill.o | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/src/drivers/driver_nl80211.c | --- a/src/drivers/driver_nl80211.c | ||||||
| +++ b/src/drivers/driver_nl80211.c | +++ b/src/drivers/driver_nl80211.c | ||||||
| @@ -4973,7 +4973,7 @@ static int nl80211_set_channel(struct i8 | @@ -4919,7 +4919,7 @@ static int nl80211_set_channel(struct i8 | ||||||
|  		   freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled, |  		   freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled, | ||||||
|  		   freq->bandwidth, freq->center_freq1, freq->center_freq2); |  		   freq->bandwidth, freq->center_freq1, freq->center_freq2); | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/src/drivers/driver_nl80211.c | --- a/src/drivers/driver_nl80211.c | ||||||
| +++ b/src/drivers/driver_nl80211.c | +++ b/src/drivers/driver_nl80211.c | ||||||
| @@ -2918,10 +2918,15 @@ static int wpa_driver_nl80211_del_beacon | @@ -2891,10 +2891,15 @@ static int wpa_driver_nl80211_del_beacon | ||||||
|  	struct nl_msg *msg; |  	struct nl_msg *msg; | ||||||
|  	struct wpa_driver_nl80211_data *drv = bss->drv; |  	struct wpa_driver_nl80211_data *drv = bss->drv; | ||||||
|   |   | ||||||
| @@ -18,7 +18,7 @@ | |||||||
|  	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); |  	return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -5602,7 +5607,7 @@ static void nl80211_teardown_ap(struct i | @@ -5550,7 +5555,7 @@ static void nl80211_teardown_ap(struct i | ||||||
|  		nl80211_mgmt_unsubscribe(bss, "AP teardown"); |  		nl80211_mgmt_unsubscribe(bss, "AP teardown"); | ||||||
|   |   | ||||||
|  	nl80211_put_wiphy_data_ap(bss); |  	nl80211_put_wiphy_data_ap(bss); | ||||||
| @@ -27,7 +27,7 @@ | |||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -8051,8 +8056,6 @@ static int wpa_driver_nl80211_if_remove( | @@ -7990,8 +7995,6 @@ static int wpa_driver_nl80211_if_remove( | ||||||
|  	} else { |  	} else { | ||||||
|  		wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context"); |  		wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context"); | ||||||
|  		nl80211_teardown_ap(bss); |  		nl80211_teardown_ap(bss); | ||||||
| @@ -36,7 +36,7 @@ | |||||||
|  		nl80211_destroy_bss(bss); |  		nl80211_destroy_bss(bss); | ||||||
|  		if (!bss->added_if) |  		if (!bss->added_if) | ||||||
|  			i802_set_iface_flags(bss, 0); |  			i802_set_iface_flags(bss, 0); | ||||||
| @@ -8449,7 +8452,6 @@ static int wpa_driver_nl80211_deinit_ap( | @@ -8388,7 +8391,6 @@ static int wpa_driver_nl80211_deinit_ap( | ||||||
|  	if (!is_ap_interface(drv->nlmode)) |  	if (!is_ap_interface(drv->nlmode)) | ||||||
|  		return -1; |  		return -1; | ||||||
|  	wpa_driver_nl80211_del_beacon(bss); |  	wpa_driver_nl80211_del_beacon(bss); | ||||||
| @@ -44,7 +44,7 @@ | |||||||
|   |   | ||||||
|  	/* |  	/* | ||||||
|  	 * If the P2P GO interface was dynamically added, then it is |  	 * If the P2P GO interface was dynamically added, then it is | ||||||
| @@ -8469,7 +8471,6 @@ static int wpa_driver_nl80211_stop_ap(vo | @@ -8408,7 +8410,6 @@ static int wpa_driver_nl80211_stop_ap(vo | ||||||
|  	if (!is_ap_interface(drv->nlmode)) |  	if (!is_ap_interface(drv->nlmode)) | ||||||
|  		return -1; |  		return -1; | ||||||
|  	wpa_driver_nl80211_del_beacon(bss); |  	wpa_driver_nl80211_del_beacon(bss); | ||||||
|   | |||||||
| @@ -1,106 +0,0 @@ | |||||||
| --- a/hostapd/ctrl_iface.c |  | ||||||
| +++ b/hostapd/ctrl_iface.c |  | ||||||
| @@ -67,6 +67,7 @@ |  | ||||||
|  #include "fst/fst_ctrl_iface.h" |  | ||||||
|  #include "config_file.h" |  | ||||||
|  #include "ctrl_iface.h" |  | ||||||
| +#include "config_file.h" |  | ||||||
|   |  | ||||||
|   |  | ||||||
|  #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256 |  | ||||||
| @@ -82,6 +83,7 @@ static void hostapd_ctrl_iface_send(stru |  | ||||||
|  				    enum wpa_msg_type type, |  | ||||||
|  				    const char *buf, size_t len); |  | ||||||
|   |  | ||||||
| +static char *reload_opts = NULL; |  | ||||||
|   |  | ||||||
|  static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, |  | ||||||
|  				     struct sockaddr_storage *from, |  | ||||||
| @@ -133,6 +135,61 @@ static int hostapd_ctrl_iface_new_sta(st |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static char *get_option(char *opt, char *str) |  | ||||||
| +{ |  | ||||||
| +	int len = strlen(str); |  | ||||||
| + |  | ||||||
| +	if (!strncmp(opt, str, len)) |  | ||||||
| +		return opt + len; |  | ||||||
| +	else |  | ||||||
| +		return NULL; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static struct hostapd_config *hostapd_ctrl_iface_config_read(const char *fname) |  | ||||||
| +{ |  | ||||||
| +	struct hostapd_config *conf; |  | ||||||
| +	char *opt, *val; |  | ||||||
| + |  | ||||||
| +	conf = hostapd_config_read(fname); |  | ||||||
| +	if (!conf) |  | ||||||
| +		return NULL; |  | ||||||
| + |  | ||||||
| +	for (opt = strtok(reload_opts, " "); |  | ||||||
| +	     opt; |  | ||||||
| +		 opt = strtok(NULL, " ")) { |  | ||||||
| + |  | ||||||
| +		if ((val = get_option(opt, "channel="))) |  | ||||||
| +			conf->channel = atoi(val); |  | ||||||
| +		else if ((val = get_option(opt, "ht_capab="))) |  | ||||||
| +			conf->ht_capab = atoi(val); |  | ||||||
| +		else if ((val = get_option(opt, "ht_capab_mask="))) |  | ||||||
| +			conf->ht_capab &= atoi(val); |  | ||||||
| +		else if ((val = get_option(opt, "sec_chan="))) |  | ||||||
| +			conf->secondary_channel = atoi(val); |  | ||||||
| +		else if ((val = get_option(opt, "hw_mode="))) |  | ||||||
| +			conf->hw_mode = atoi(val); |  | ||||||
| +		else if ((val = get_option(opt, "ieee80211n="))) |  | ||||||
| +			conf->ieee80211n = atoi(val); |  | ||||||
| +		else |  | ||||||
| +			break; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	return conf; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int hostapd_ctrl_iface_update(struct hostapd_data *hapd, char *txt) |  | ||||||
| +{ |  | ||||||
| +	struct hostapd_config * (*config_read_cb)(const char *config_fname); |  | ||||||
| +	struct hostapd_iface *iface = hapd->iface; |  | ||||||
| + |  | ||||||
| +	config_read_cb = iface->interfaces->config_read_cb; |  | ||||||
| +	iface->interfaces->config_read_cb = hostapd_ctrl_iface_config_read; |  | ||||||
| +	reload_opts = txt; |  | ||||||
| + |  | ||||||
| +	hostapd_reload_config(iface); |  | ||||||
| + |  | ||||||
| +	iface->interfaces->config_read_cb = config_read_cb; |  | ||||||
| +} |  | ||||||
|   |  | ||||||
|  #ifdef NEED_AP_MLME |  | ||||||
|  static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, |  | ||||||
| @@ -3754,6 +3811,8 @@ static int hostapd_ctrl_iface_receive_pr |  | ||||||
|  	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) { |  | ||||||
|  		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, |  | ||||||
|  						      reply_size); |  | ||||||
| +	} else if (os_strncmp(buf, "UPDATE ", 7) == 0) { |  | ||||||
| +		hostapd_ctrl_iface_update(hapd, buf + 7); |  | ||||||
|  	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) { |  | ||||||
|  		ieee802_1x_erp_flush(hapd); |  | ||||||
|  #ifdef RADIUS_SERVER |  | ||||||
| --- a/src/ap/ctrl_iface_ap.c |  | ||||||
| +++ b/src/ap/ctrl_iface_ap.c |  | ||||||
| @@ -919,7 +919,13 @@ int hostapd_parse_csa_settings(const cha |  | ||||||
|   |  | ||||||
|  int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd) |  | ||||||
|  { |  | ||||||
| -	return hostapd_drv_stop_ap(hapd); |  | ||||||
| +	struct hostapd_iface *iface = hapd->iface; |  | ||||||
| +	int i; |  | ||||||
| + |  | ||||||
| +	for (i = 0; i < iface->num_bss; i++) |  | ||||||
| +		hostapd_drv_stop_ap(iface->bss[i]); |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|   |  | ||||||
| @@ -1,414 +0,0 @@ | |||||||
| Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/Makefile |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/Makefile |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/Makefile |  | ||||||
| @@ -108,6 +108,8 @@ OBJS_c += ../src/utils/common.o |  | ||||||
|  OBJS_c += ../src/common/cli.o |  | ||||||
|  OBJS += wmm_ac.o |  | ||||||
|   |  | ||||||
| +OBJS += ../src/common/wpa_ctrl.o |  | ||||||
| + |  | ||||||
|  ifndef CONFIG_OS |  | ||||||
|  ifdef CONFIG_NATIVE_WINDOWS |  | ||||||
|  CONFIG_OS=win32 |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/bss.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/bss.c |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/bss.c |  | ||||||
| @@ -11,6 +11,7 @@ |  | ||||||
|  #include "utils/common.h" |  | ||||||
|  #include "utils/eloop.h" |  | ||||||
|  #include "common/ieee802_11_defs.h" |  | ||||||
| +#include "common/ieee802_11_common.h" |  | ||||||
|  #include "drivers/driver.h" |  | ||||||
|  #include "eap_peer/eap.h" |  | ||||||
|  #include "wpa_supplicant_i.h" |  | ||||||
| @@ -282,6 +283,10 @@ void calculate_update_time(const struct |  | ||||||
|  static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src, |  | ||||||
|  			     struct os_reltime *fetch_time) |  | ||||||
|  { |  | ||||||
| +	struct ieee80211_ht_capabilities *capab; |  | ||||||
| +	struct ieee80211_ht_operation *oper; |  | ||||||
| +	struct ieee802_11_elems elems; |  | ||||||
| + |  | ||||||
|  	dst->flags = src->flags; |  | ||||||
|  	os_memcpy(dst->bssid, src->bssid, ETH_ALEN); |  | ||||||
|  	dst->freq = src->freq; |  | ||||||
| @@ -294,6 +299,15 @@ static void wpa_bss_copy_res(struct wpa_ |  | ||||||
|  	dst->est_throughput = src->est_throughput; |  | ||||||
|  	dst->snr = src->snr; |  | ||||||
|   |  | ||||||
| +	memset(&elems, 0, sizeof(elems)); |  | ||||||
| +	ieee802_11_parse_elems((u8 *) (src + 1), src->ie_len, &elems, 0); |  | ||||||
| +	capab = (struct ieee80211_ht_capabilities *) elems.ht_capabilities; |  | ||||||
| +	oper = (struct ieee80211_ht_operation *) elems.ht_operation; |  | ||||||
| +	if (capab) |  | ||||||
| +		dst->ht_capab = le_to_host16(capab->ht_capabilities_info); |  | ||||||
| +	if (oper) |  | ||||||
| +		dst->ht_param = oper->ht_param; |  | ||||||
| + |  | ||||||
|  	calculate_update_time(fetch_time, src->age, &dst->last_update); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/bss.h |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/bss.h |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/bss.h |  | ||||||
| @@ -94,6 +94,10 @@ struct wpa_bss { |  | ||||||
|  	u8 ssid[SSID_MAX_LEN]; |  | ||||||
|  	/** Length of SSID */ |  | ||||||
|  	size_t ssid_len; |  | ||||||
| +	/** HT capabilities */ |  | ||||||
| +	u16 ht_capab; |  | ||||||
| +	/* Five octets of HT Operation Information */ |  | ||||||
| +	u8 ht_param; |  | ||||||
|  	/** Frequency of the channel in MHz (e.g., 2412 = channel 1) */ |  | ||||||
|  	int freq; |  | ||||||
|  	/** Beacon interval in TUs (host byte order) */ |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/main.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/main.c |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/main.c |  | ||||||
| @@ -34,7 +34,7 @@ static void usage(void) |  | ||||||
|  	       "vW] [-P<pid file>] " |  | ||||||
|  	       "[-g<global ctrl>] \\\n" |  | ||||||
|  	       "        [-G<group>] \\\n" |  | ||||||
| -	       "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] " |  | ||||||
| +	       "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-H<hostapd path>] " |  | ||||||
|  	       "[-p<driver_param>] \\\n" |  | ||||||
|  	       "        [-b<br_ifname>] [-e<entropy file>]" |  | ||||||
|  #ifdef CONFIG_DEBUG_FILE |  | ||||||
| @@ -74,6 +74,7 @@ static void usage(void) |  | ||||||
|  	       "  -g = global ctrl_interface\n" |  | ||||||
|  	       "  -G = global ctrl_interface group\n" |  | ||||||
|  	       "  -h = show this help text\n" |  | ||||||
| +	       "  -H = connect to a hostapd instance to manage state changes\n" |  | ||||||
|  	       "  -i = interface name\n" |  | ||||||
|  	       "  -I = additional configuration file\n" |  | ||||||
|  	       "  -K = include keys (passwords, etc.) in debug output\n" |  | ||||||
| @@ -201,7 +202,7 @@ int main(int argc, char *argv[]) |  | ||||||
|   |  | ||||||
|  	for (;;) { |  | ||||||
|  		c = getopt(argc, argv, |  | ||||||
| -			   "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); |  | ||||||
| +			   "b:Bc:C:D:de:f:g:G:hH:i:I:KLMm:No:O:p:P:qsTtuvW"); |  | ||||||
|  		if (c < 0) |  | ||||||
|  			break; |  | ||||||
|  		switch (c) { |  | ||||||
| @@ -248,6 +249,9 @@ int main(int argc, char *argv[]) |  | ||||||
|  			usage(); |  | ||||||
|  			exitcode = 0; |  | ||||||
|  			goto out; |  | ||||||
| +		case 'H': |  | ||||||
| +			iface->hostapd_ctrl = optarg; |  | ||||||
| +			break; |  | ||||||
|  		case 'i': |  | ||||||
|  			iface->ifname = optarg; |  | ||||||
|  			break; |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.c |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c |  | ||||||
| @@ -130,6 +130,54 @@ static void wpas_update_fils_connect_par |  | ||||||
|  static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s); |  | ||||||
|  #endif /* CONFIG_OWE */ |  | ||||||
|   |  | ||||||
| +static int hostapd_stop(struct wpa_supplicant *wpa_s) |  | ||||||
| +{ |  | ||||||
| +	const char *cmd = "STOP_AP"; |  | ||||||
| +	char buf[256]; |  | ||||||
| +	size_t len = sizeof(buf); |  | ||||||
| + |  | ||||||
| +	if (wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL) < 0) { |  | ||||||
| +		wpa_printf(MSG_ERROR, "\nFailed to stop hostapd AP interfaces\n"); |  | ||||||
| +		return -1; |  | ||||||
| +	} |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int hostapd_reload(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) |  | ||||||
| +{ |  | ||||||
| +	char *cmd = NULL; |  | ||||||
| +	char buf[256]; |  | ||||||
| +	size_t len = sizeof(buf); |  | ||||||
| +	enum hostapd_hw_mode hw_mode; |  | ||||||
| +	u8 channel; |  | ||||||
| +	int sec_chan = 0; |  | ||||||
| +	int ret; |  | ||||||
| + |  | ||||||
| +	if (!bss) |  | ||||||
| +		return -1; |  | ||||||
| + |  | ||||||
| +	if (bss->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) { |  | ||||||
| +		int sec = bss->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; |  | ||||||
| +		if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) |  | ||||||
| +			sec_chan = 1; |  | ||||||
| +		else if (sec ==  HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) |  | ||||||
| +			sec_chan = -1; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	hw_mode = ieee80211_freq_to_chan(bss->freq, &channel); |  | ||||||
| +	if (asprintf(&cmd, "UPDATE channel=%d sec_chan=%d hw_mode=%d", |  | ||||||
| +		     channel, sec_chan, hw_mode) < 0) |  | ||||||
| +		return -1; |  | ||||||
| + |  | ||||||
| +	ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL); |  | ||||||
| +	free(cmd); |  | ||||||
| + |  | ||||||
| +	if (ret < 0) { |  | ||||||
| +		wpa_printf(MSG_ERROR, "\nFailed to reload hostapd AP interfaces\n"); |  | ||||||
| +		return -1; |  | ||||||
| +	} |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
|   |  | ||||||
|  #ifdef CONFIG_WEP |  | ||||||
|  /* Configure default/group WEP keys for static WEP */ |  | ||||||
| @@ -1015,6 +1063,8 @@ void wpa_supplicant_set_state(struct wpa |  | ||||||
|   |  | ||||||
|  		sme_sched_obss_scan(wpa_s, 1); |  | ||||||
|   |  | ||||||
| +		if (wpa_s->hostapd) |  | ||||||
| +			hostapd_reload(wpa_s, wpa_s->current_bss); |  | ||||||
|  #if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) |  | ||||||
|  		if (!fils_hlp_sent && ssid && ssid->eap.erp) |  | ||||||
|  			update_fils_connect_params = true; |  | ||||||
| @@ -1025,6 +1075,8 @@ void wpa_supplicant_set_state(struct wpa |  | ||||||
|  #endif /* CONFIG_OWE */ |  | ||||||
|  	} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || |  | ||||||
|  		   state == WPA_ASSOCIATED) { |  | ||||||
| +		if (wpa_s->hostapd) |  | ||||||
| +			hostapd_stop(wpa_s); |  | ||||||
|  		wpa_s->new_connection = 1; |  | ||||||
|  		wpa_drv_set_operstate(wpa_s, 0); |  | ||||||
|  #ifndef IEEE8021X_EAPOL |  | ||||||
| @@ -2308,6 +2360,8 @@ void wpa_supplicant_associate(struct wpa |  | ||||||
|  			return; |  | ||||||
|  		} |  | ||||||
|  		wpa_s->current_bss = bss; |  | ||||||
| +		if (wpa_s->hostapd) |  | ||||||
| +			hostapd_reload(wpa_s, wpa_s->current_bss); |  | ||||||
|  #else /* CONFIG_MESH */ |  | ||||||
|  		wpa_msg(wpa_s, MSG_ERROR, |  | ||||||
|  			"mesh mode support not included in the build"); |  | ||||||
| @@ -6632,6 +6686,16 @@ static int wpa_supplicant_init_iface(str |  | ||||||
|  			   sizeof(wpa_s->bridge_ifname)); |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| +	if (iface->hostapd_ctrl) { |  | ||||||
| +		wpa_s->hostapd = wpa_ctrl_open(iface->hostapd_ctrl); |  | ||||||
| +		if (!wpa_s->hostapd) { |  | ||||||
| +			wpa_printf(MSG_ERROR, "\nFailed to connect to hostapd\n"); |  | ||||||
| +			return -1; |  | ||||||
| +		} |  | ||||||
| +		if (hostapd_stop(wpa_s) < 0) |  | ||||||
| +			return -1; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
|  	/* RSNA Supplicant Key Management - INITIALIZE */ |  | ||||||
|  	eapol_sm_notify_portEnabled(wpa_s->eapol, false); |  | ||||||
|  	eapol_sm_notify_portValid(wpa_s->eapol, false); |  | ||||||
| @@ -6969,6 +7033,11 @@ static void wpa_supplicant_deinit_iface( |  | ||||||
|  	if (terminate) |  | ||||||
|  		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING); |  | ||||||
|   |  | ||||||
| +	if (wpa_s->hostapd) { |  | ||||||
| +		wpa_ctrl_close(wpa_s->hostapd); |  | ||||||
| +		wpa_s->hostapd = NULL; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
|  	wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface); |  | ||||||
|  	wpa_s->ctrl_iface = NULL; |  | ||||||
|   |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant_i.h |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant_i.h |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant_i.h |  | ||||||
| @@ -104,6 +104,11 @@ struct wpa_interface { |  | ||||||
|  	const char *ifname; |  | ||||||
|   |  | ||||||
|  	/** |  | ||||||
| +	 * hostapd_ctrl - path to hostapd control socket for notification |  | ||||||
| +	 */ |  | ||||||
| +	const char *hostapd_ctrl; |  | ||||||
| + |  | ||||||
| +	/** |  | ||||||
|  	 * bridge_ifname - Optional bridge interface name |  | ||||||
|  	 * |  | ||||||
|  	 * If the driver interface (ifname) is included in a Linux bridge |  | ||||||
| @@ -718,6 +723,8 @@ struct wpa_supplicant { |  | ||||||
|  #endif /* CONFIG_CTRL_IFACE_BINDER */ |  | ||||||
|  	char bridge_ifname[16]; |  | ||||||
|   |  | ||||||
| +	struct wpa_ctrl *hostapd; |  | ||||||
| + |  | ||||||
|  	char *confname; |  | ||||||
|  	char *confanother; |  | ||||||
|   |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/hostapd/ctrl_iface.c |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c |  | ||||||
| @@ -2889,6 +2889,11 @@ static int hostapd_ctrl_iface_chan_switc |  | ||||||
|  		return 0; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| +	if (os_strstr(pos, " auto-ht")) { |  | ||||||
| +		settings.freq_params.ht_enabled = iface->conf->ieee80211n; |  | ||||||
| +		settings.freq_params.vht_enabled = iface->conf->ieee80211ac; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
|  	for (i = 0; i < iface->num_bss; i++) { |  | ||||||
|   |  | ||||||
|  		/* Save CHAN_SWITCH VHT and HE config */ |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/beacon.c |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c |  | ||||||
| @@ -1791,11 +1791,6 @@ static int __ieee802_11_set_beacon(struc |  | ||||||
|  		return -1; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	if (hapd->csa_in_progress) { |  | ||||||
| -		wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period"); |  | ||||||
| -		return -1; |  | ||||||
| -	} |  | ||||||
| - |  | ||||||
|  	hapd->beacon_set_done = 1; |  | ||||||
|   |  | ||||||
|  	if (ieee802_11_build_ap_params(hapd, ¶ms) < 0) |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/events.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/events.c |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/events.c |  | ||||||
| @@ -4891,6 +4891,60 @@ static void wpas_event_unprot_beacon(str |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|   |  | ||||||
| +static void |  | ||||||
| +supplicant_ch_switch_started(struct wpa_supplicant *wpa_s, |  | ||||||
| +			    union wpa_event_data *data) |  | ||||||
| +{ |  | ||||||
| +	char buf[256]; |  | ||||||
| +	size_t len = sizeof(buf); |  | ||||||
| +	char *cmd = NULL; |  | ||||||
| +	int width = 20; |  | ||||||
| +	int ret; |  | ||||||
| + |  | ||||||
| +	if (!wpa_s->hostapd) |  | ||||||
| +		return; |  | ||||||
| + |  | ||||||
| +	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH |  | ||||||
| +		"count=%d freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d", |  | ||||||
| +		data->ch_switch.count, |  | ||||||
| +		data->ch_switch.freq, |  | ||||||
| +		data->ch_switch.ht_enabled, |  | ||||||
| +		data->ch_switch.ch_offset, |  | ||||||
| +		channel_width_to_string(data->ch_switch.ch_width), |  | ||||||
| +		data->ch_switch.cf1, |  | ||||||
| +		data->ch_switch.cf2); |  | ||||||
| + |  | ||||||
| +	switch (data->ch_switch.ch_width) { |  | ||||||
| +	case CHAN_WIDTH_20_NOHT: |  | ||||||
| +	case CHAN_WIDTH_20: |  | ||||||
| +		width = 20; |  | ||||||
| +		break; |  | ||||||
| +	case CHAN_WIDTH_40: |  | ||||||
| +		width = 40; |  | ||||||
| +		break; |  | ||||||
| +	case CHAN_WIDTH_80: |  | ||||||
| +		width = 80; |  | ||||||
| +		break; |  | ||||||
| +	case CHAN_WIDTH_160: |  | ||||||
| +	case CHAN_WIDTH_80P80: |  | ||||||
| +		width = 160; |  | ||||||
| +		break; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	asprintf(&cmd, "CHAN_SWITCH %d %d sec_channel_offset=%d center_freq1=%d center_freq2=%d, bandwidth=%d auto-ht\n", |  | ||||||
| +		data->ch_switch.count - 1, |  | ||||||
| +		data->ch_switch.freq, |  | ||||||
| +		data->ch_switch.ch_offset, |  | ||||||
| +		data->ch_switch.cf1, |  | ||||||
| +		data->ch_switch.cf2, |  | ||||||
| +		width); |  | ||||||
| +	ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL); |  | ||||||
| +	free(cmd); |  | ||||||
| + |  | ||||||
| +	if (ret < 0) |  | ||||||
| +		wpa_printf(MSG_ERROR, "\nFailed to reload hostapd AP interfaces\n"); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
|  void supplicant_event(void *ctx, enum wpa_event_type event, |  | ||||||
|  		      union wpa_event_data *data) |  | ||||||
|  { |  | ||||||
| @@ -5206,8 +5260,10 @@ void supplicant_event(void *ctx, enum wp |  | ||||||
|  			channel_width_to_string(data->ch_switch.ch_width), |  | ||||||
|  			data->ch_switch.cf1, |  | ||||||
|  			data->ch_switch.cf2); |  | ||||||
| -		if (event == EVENT_CH_SWITCH_STARTED) |  | ||||||
| +		if (event == EVENT_CH_SWITCH_STARTED) { |  | ||||||
| +			supplicant_ch_switch_started(wpa_s, data); |  | ||||||
|  			break; |  | ||||||
| +		} |  | ||||||
|   |  | ||||||
|  		wpa_s->assoc_freq = data->ch_switch.freq; |  | ||||||
|  		wpa_s->current_ssid->frequency = data->ch_switch.freq; |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h |  | ||||||
| @@ -5837,6 +5837,7 @@ union wpa_event_data { |  | ||||||
|   |  | ||||||
|  	/** |  | ||||||
|  	 * struct ch_switch |  | ||||||
| +	 * @count: Count until channel switch activates |  | ||||||
|  	 * @freq: Frequency of new channel in MHz |  | ||||||
|  	 * @ht_enabled: Whether this is an HT channel |  | ||||||
|  	 * @ch_offset: Secondary channel offset |  | ||||||
| @@ -5845,6 +5846,7 @@ union wpa_event_data { |  | ||||||
|  	 * @cf2: Center frequency 2 |  | ||||||
|  	 */ |  | ||||||
|  	struct ch_switch { |  | ||||||
| +		int count; |  | ||||||
|  		int freq; |  | ||||||
|  		int ht_enabled; |  | ||||||
|  		int ch_offset; |  | ||||||
| Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211_event.c |  | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c |  | ||||||
| @@ -684,7 +684,7 @@ static void mlme_event_ch_switch(struct |  | ||||||
|  				 struct nlattr *ifindex, struct nlattr *freq, |  | ||||||
|  				 struct nlattr *type, struct nlattr *bw, |  | ||||||
|  				 struct nlattr *cf1, struct nlattr *cf2, |  | ||||||
| -				 int finished) |  | ||||||
| +				 struct nlattr *count, int finished) |  | ||||||
|  { |  | ||||||
|  	struct i802_bss *bss; |  | ||||||
|  	union wpa_event_data data; |  | ||||||
| @@ -745,6 +745,8 @@ static void mlme_event_ch_switch(struct |  | ||||||
|  		data.ch_switch.cf1 = nla_get_u32(cf1); |  | ||||||
|  	if (cf2) |  | ||||||
|  		data.ch_switch.cf2 = nla_get_u32(cf2); |  | ||||||
| +	if (count) |  | ||||||
| +		data.ch_switch.count = nla_get_u32(count); |  | ||||||
|   |  | ||||||
|  	if (finished) |  | ||||||
|  		bss->freq = data.ch_switch.freq; |  | ||||||
| @@ -3003,6 +3005,7 @@ static void do_process_drv_event(struct |  | ||||||
|  				     tb[NL80211_ATTR_CHANNEL_WIDTH], |  | ||||||
|  				     tb[NL80211_ATTR_CENTER_FREQ1], |  | ||||||
|  				     tb[NL80211_ATTR_CENTER_FREQ2], |  | ||||||
| +				     tb[NL80211_ATTR_CH_SWITCH_COUNT], |  | ||||||
|  				     0); |  | ||||||
|  		break; |  | ||||||
|  	case NL80211_CMD_CH_SWITCH_NOTIFY: |  | ||||||
| @@ -3013,6 +3016,7 @@ static void do_process_drv_event(struct |  | ||||||
|  				     tb[NL80211_ATTR_CHANNEL_WIDTH], |  | ||||||
|  				     tb[NL80211_ATTR_CENTER_FREQ1], |  | ||||||
|  				     tb[NL80211_ATTR_CENTER_FREQ2], |  | ||||||
| +				     NULL, |  | ||||||
|  				     1); |  | ||||||
|  		break; |  | ||||||
|  	case NL80211_CMD_DISCONNECT: |  | ||||||
| @@ -12,7 +12,7 @@ | |||||||
|  else |  else | ||||||
| --- a/hostapd/ctrl_iface.c | --- a/hostapd/ctrl_iface.c | ||||||
| +++ b/hostapd/ctrl_iface.c | +++ b/hostapd/ctrl_iface.c | ||||||
| @@ -3569,6 +3569,7 @@ static int hostapd_ctrl_iface_receive_pr | @@ -3388,6 +3388,7 @@ static int hostapd_ctrl_iface_receive_pr | ||||||
|  						      reply_size); |  						      reply_size); | ||||||
|  	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { |  	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { | ||||||
|  		reply_len = hostapd_drv_status(hapd, reply, reply_size); |  		reply_len = hostapd_drv_status(hapd, reply, reply_size); | ||||||
| @@ -20,7 +20,7 @@ | |||||||
|  	} else if (os_strcmp(buf, "MIB") == 0) { |  	} else if (os_strcmp(buf, "MIB") == 0) { | ||||||
|  		reply_len = ieee802_11_get_mib(hapd, reply, reply_size); |  		reply_len = ieee802_11_get_mib(hapd, reply, reply_size); | ||||||
|  		if (reply_len >= 0) { |  		if (reply_len >= 0) { | ||||||
| @@ -3610,6 +3611,7 @@ static int hostapd_ctrl_iface_receive_pr | @@ -3429,6 +3430,7 @@ static int hostapd_ctrl_iface_receive_pr | ||||||
|  	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { |  	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { | ||||||
|  		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, |  		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, | ||||||
|  							reply_size); |  							reply_size); | ||||||
| @@ -30,7 +30,7 @@ | |||||||
|  			reply_len = -1; |  			reply_len = -1; | ||||||
| --- a/wpa_supplicant/Makefile | --- a/wpa_supplicant/Makefile | ||||||
| +++ b/wpa_supplicant/Makefile | +++ b/wpa_supplicant/Makefile | ||||||
| @@ -955,6 +955,9 @@ ifdef CONFIG_FILS | @@ -942,6 +942,9 @@ ifdef CONFIG_FILS | ||||||
|  OBJS += ../src/ap/fils_hlp.o |  OBJS += ../src/ap/fils_hlp.o | ||||||
|  endif |  endif | ||||||
|  ifdef CONFIG_CTRL_IFACE |  ifdef CONFIG_CTRL_IFACE | ||||||
| @@ -42,7 +42,7 @@ | |||||||
|   |   | ||||||
| --- a/wpa_supplicant/ctrl_iface.c | --- a/wpa_supplicant/ctrl_iface.c | ||||||
| +++ b/wpa_supplicant/ctrl_iface.c | +++ b/wpa_supplicant/ctrl_iface.c | ||||||
| @@ -2308,7 +2308,7 @@ static int wpa_supplicant_ctrl_iface_sta | @@ -2294,7 +2294,7 @@ static int wpa_supplicant_ctrl_iface_sta | ||||||
|  			pos += ret; |  			pos += ret; | ||||||
|  		} |  		} | ||||||
|   |   | ||||||
| @@ -51,7 +51,7 @@ | |||||||
|  		if (wpa_s->ap_iface) { |  		if (wpa_s->ap_iface) { | ||||||
|  			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, |  			pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, | ||||||
|  							    end - pos, |  							    end - pos, | ||||||
| @@ -10919,6 +10919,7 @@ char * wpa_supplicant_ctrl_iface_process | @@ -10602,6 +10602,7 @@ char * wpa_supplicant_ctrl_iface_process | ||||||
|  			reply_len = -1; |  			reply_len = -1; | ||||||
|  	} else if (os_strncmp(buf, "NOTE ", 5) == 0) { |  	} else if (os_strncmp(buf, "NOTE ", 5) == 0) { | ||||||
|  		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); |  		wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); | ||||||
| @@ -59,7 +59,7 @@ | |||||||
|  	} else if (os_strcmp(buf, "MIB") == 0) { |  	} else if (os_strcmp(buf, "MIB") == 0) { | ||||||
|  		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); |  		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); | ||||||
|  		if (reply_len >= 0) { |  		if (reply_len >= 0) { | ||||||
| @@ -10931,6 +10932,7 @@ char * wpa_supplicant_ctrl_iface_process | @@ -10614,6 +10615,7 @@ char * wpa_supplicant_ctrl_iface_process | ||||||
|  				reply_size - reply_len); |  				reply_size - reply_len); | ||||||
|  #endif /* CONFIG_MACSEC */ |  #endif /* CONFIG_MACSEC */ | ||||||
|  		} |  		} | ||||||
| @@ -67,7 +67,7 @@ | |||||||
|  	} else if (os_strncmp(buf, "STATUS", 6) == 0) { |  	} else if (os_strncmp(buf, "STATUS", 6) == 0) { | ||||||
|  		reply_len = wpa_supplicant_ctrl_iface_status( |  		reply_len = wpa_supplicant_ctrl_iface_status( | ||||||
|  			wpa_s, buf + 6, reply, reply_size); |  			wpa_s, buf + 6, reply, reply_size); | ||||||
| @@ -11419,6 +11421,7 @@ char * wpa_supplicant_ctrl_iface_process | @@ -11102,6 +11104,7 @@ char * wpa_supplicant_ctrl_iface_process | ||||||
|  		reply_len = wpa_supplicant_ctrl_iface_bss( |  		reply_len = wpa_supplicant_ctrl_iface_bss( | ||||||
|  			wpa_s, buf + 4, reply, reply_size); |  			wpa_s, buf + 4, reply, reply_size); | ||||||
|  #ifdef CONFIG_AP |  #ifdef CONFIG_AP | ||||||
| @@ -75,7 +75,7 @@ | |||||||
|  	} else if (os_strcmp(buf, "STA-FIRST") == 0) { |  	} else if (os_strcmp(buf, "STA-FIRST") == 0) { | ||||||
|  		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); |  		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); | ||||||
|  	} else if (os_strncmp(buf, "STA ", 4) == 0) { |  	} else if (os_strncmp(buf, "STA ", 4) == 0) { | ||||||
| @@ -11427,12 +11430,15 @@ char * wpa_supplicant_ctrl_iface_process | @@ -11110,12 +11113,15 @@ char * wpa_supplicant_ctrl_iface_process | ||||||
|  	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { |  	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { | ||||||
|  		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, |  		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, | ||||||
|  						   reply_size); |  						   reply_size); | ||||||
| @@ -144,7 +144,7 @@ | |||||||
|  static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx) |  static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx) | ||||||
| --- a/src/ap/wpa_auth.c | --- a/src/ap/wpa_auth.c | ||||||
| +++ b/src/ap/wpa_auth.c | +++ b/src/ap/wpa_auth.c | ||||||
| @@ -4519,6 +4519,7 @@ static const char * wpa_bool_txt(int val | @@ -4503,6 +4503,7 @@ static const char * wpa_bool_txt(int val | ||||||
|  	return val ? "TRUE" : "FALSE"; |  	return val ? "TRUE" : "FALSE"; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -152,7 +152,7 @@ | |||||||
|   |   | ||||||
|  #define RSN_SUITE "%02x-%02x-%02x-%d" |  #define RSN_SUITE "%02x-%02x-%02x-%d" | ||||||
|  #define RSN_SUITE_ARG(s) \ |  #define RSN_SUITE_ARG(s) \ | ||||||
| @@ -4669,7 +4670,7 @@ int wpa_get_mib_sta(struct wpa_state_mac | @@ -4653,7 +4654,7 @@ int wpa_get_mib_sta(struct wpa_state_mac | ||||||
|   |   | ||||||
|  	return len; |  	return len; | ||||||
|  } |  } | ||||||
| @@ -163,7 +163,7 @@ | |||||||
|  { |  { | ||||||
| --- a/src/rsn_supp/wpa.c | --- a/src/rsn_supp/wpa.c | ||||||
| +++ b/src/rsn_supp/wpa.c | +++ b/src/rsn_supp/wpa.c | ||||||
| @@ -2767,6 +2767,8 @@ static u32 wpa_key_mgmt_suite(struct wpa | @@ -2763,6 +2763,8 @@ static u32 wpa_key_mgmt_suite(struct wpa | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -172,7 +172,7 @@ | |||||||
|  #define RSN_SUITE "%02x-%02x-%02x-%d" |  #define RSN_SUITE "%02x-%02x-%02x-%d" | ||||||
|  #define RSN_SUITE_ARG(s) \ |  #define RSN_SUITE_ARG(s) \ | ||||||
|  ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff |  ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff | ||||||
| @@ -2848,6 +2850,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch | @@ -2844,6 +2846,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch | ||||||
|   |   | ||||||
|  	return (int) len; |  	return (int) len; | ||||||
|  } |  } | ||||||
|   | |||||||
| @@ -36,16 +36,16 @@ | |||||||
|  #include "fst/fst.h" |  #include "fst/fst.h" | ||||||
|  #include "wpa_supplicant_i.h" |  #include "wpa_supplicant_i.h" | ||||||
|  #include "driver_i.h" |  #include "driver_i.h" | ||||||
| @@ -202,7 +203,7 @@ int main(int argc, char *argv[]) | @@ -201,7 +202,7 @@ int main(int argc, char *argv[]) | ||||||
|   |   | ||||||
|  	for (;;) { |  	for (;;) { | ||||||
|  		c = getopt(argc, argv, |  		c = getopt(argc, argv, | ||||||
| -			   "b:Bc:C:D:de:f:g:G:hH:i:I:KLMm:No:O:p:P:qsTtuvW"); | -			   "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); | ||||||
| +			   "b:Bc:C:D:de:f:g:G:hH:i:I:KLMm:No:O:p:P:qsTtuv::W"); | +			   "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuv::W"); | ||||||
|  		if (c < 0) |  		if (c < 0) | ||||||
|  			break; |  			break; | ||||||
|  		switch (c) { |  		switch (c) { | ||||||
| @@ -305,8 +306,12 @@ int main(int argc, char *argv[]) | @@ -301,8 +302,12 @@ int main(int argc, char *argv[]) | ||||||
|  			break; |  			break; | ||||||
|  #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ |  #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ | ||||||
|  		case 'v': |  		case 'v': | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
|   |   | ||||||
|   |   | ||||||
|  static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc, |  static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc, | ||||||
| @@ -1579,13 +1575,10 @@ static const struct hostapd_cli_cmd host | @@ -1571,13 +1567,10 @@ static const struct hostapd_cli_cmd host | ||||||
|  	{ "disassociate", hostapd_cli_cmd_disassociate, |  	{ "disassociate", hostapd_cli_cmd_disassociate, | ||||||
|  	  hostapd_complete_stations, |  	  hostapd_complete_stations, | ||||||
|  	  "<addr> = disassociate a station" }, |  	  "<addr> = disassociate a station" }, | ||||||
| @@ -46,7 +46,7 @@ | |||||||
|  	{ "wps_pin", hostapd_cli_cmd_wps_pin, NULL, |  	{ "wps_pin", hostapd_cli_cmd_wps_pin, NULL, | ||||||
|  	  "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" }, |  	  "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" }, | ||||||
|  	{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL, |  	{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL, | ||||||
| @@ -1610,7 +1603,6 @@ static const struct hostapd_cli_cmd host | @@ -1602,7 +1595,6 @@ static const struct hostapd_cli_cmd host | ||||||
|  	  "<SSID> <auth> <encr> <key> = configure AP" }, |  	  "<SSID> <auth> <encr> <key> = configure AP" }, | ||||||
|  	{ "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL, |  	{ "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL, | ||||||
|  	  "= show current WPS status" }, |  	  "= show current WPS status" }, | ||||||
|   | |||||||
| @@ -1,73 +0,0 @@ | |||||||
| --- a/hostapd/main.c |  | ||||||
| +++ b/hostapd/main.c |  | ||||||
| @@ -39,6 +39,8 @@ struct hapd_global { |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  static struct hapd_global global; |  | ||||||
| +static int daemonize = 0; |  | ||||||
| +static char *pid_file = NULL; |  | ||||||
|   |  | ||||||
|   |  | ||||||
|  #ifndef CONFIG_NO_HOSTAPD_LOGGER |  | ||||||
| @@ -146,6 +148,14 @@ static void hostapd_logger_cb(void *ctx, |  | ||||||
|  } |  | ||||||
|  #endif /* CONFIG_NO_HOSTAPD_LOGGER */ |  | ||||||
|   |  | ||||||
| +static void hostapd_setup_complete_cb(void *ctx) |  | ||||||
| +{ |  | ||||||
| +	if (daemonize && os_daemonize(pid_file)) { |  | ||||||
| +		perror("daemon"); |  | ||||||
| +		return; |  | ||||||
| +	} |  | ||||||
| +	daemonize = 0; |  | ||||||
| +} |  | ||||||
|   |  | ||||||
|  /** |  | ||||||
|   * hostapd_driver_init - Preparate driver interface |  | ||||||
| @@ -164,6 +174,8 @@ static int hostapd_driver_init(struct ho |  | ||||||
|  		return -1; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| +	hapd->setup_complete_cb = hostapd_setup_complete_cb; |  | ||||||
| + |  | ||||||
|  	/* Initialize the driver interface */ |  | ||||||
|  	if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) |  | ||||||
|  		b = NULL; |  | ||||||
| @@ -404,8 +416,6 @@ static void hostapd_global_deinit(const |  | ||||||
|  #endif /* CONFIG_NATIVE_WINDOWS */ |  | ||||||
|   |  | ||||||
|  	eap_server_unregister_methods(); |  | ||||||
| - |  | ||||||
| -	os_daemonize_terminate(pid_file); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|   |  | ||||||
| @@ -431,18 +441,6 @@ static int hostapd_global_run(struct hap |  | ||||||
|  	} |  | ||||||
|  #endif /* EAP_SERVER_TNC */ |  | ||||||
|   |  | ||||||
| -	if (daemonize) { |  | ||||||
| -		if (os_daemonize(pid_file)) { |  | ||||||
| -			wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno)); |  | ||||||
| -			return -1; |  | ||||||
| -		} |  | ||||||
| -		if (eloop_sock_requeue()) { |  | ||||||
| -			wpa_printf(MSG_ERROR, "eloop_sock_requeue: %s", |  | ||||||
| -				   strerror(errno)); |  | ||||||
| -			return -1; |  | ||||||
| -		} |  | ||||||
| -	} |  | ||||||
| - |  | ||||||
|  	eloop_run(); |  | ||||||
|   |  | ||||||
|  	return 0; |  | ||||||
| @@ -645,8 +643,7 @@ int main(int argc, char *argv[]) |  | ||||||
|  	struct hapd_interfaces interfaces; |  | ||||||
|  	int ret = 1; |  | ||||||
|  	size_t i, j; |  | ||||||
| -	int c, debug = 0, daemonize = 0; |  | ||||||
| -	char *pid_file = NULL; |  | ||||||
| +	int c, debug = 0; |  | ||||||
|  	const char *log_file = NULL; |  | ||||||
|  	const char *entropy_file = NULL; |  | ||||||
|  	char **bss_config = NULL, **tmp_bss; |  | ||||||
| @@ -174,7 +174,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org> | |||||||
|  	 * macsec_policy - Determines the policy for MACsec secure session |  	 * macsec_policy - Determines the policy for MACsec secure session | ||||||
| --- a/wpa_supplicant/wpa_supplicant.c | --- a/wpa_supplicant/wpa_supplicant.c | ||||||
| +++ b/wpa_supplicant/wpa_supplicant.c | +++ b/wpa_supplicant/wpa_supplicant.c | ||||||
| @@ -3726,6 +3726,12 @@ static void wpas_start_assoc_cb(struct w | @@ -3673,6 +3673,12 @@ static void wpas_start_assoc_cb(struct w | ||||||
|  			params.beacon_int = ssid->beacon_int; |  			params.beacon_int = ssid->beacon_int; | ||||||
|  		else |  		else | ||||||
|  			params.beacon_int = wpa_s->conf->beacon_int; |  			params.beacon_int = wpa_s->conf->beacon_int; | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org> | |||||||
|  |  | ||||||
| --- a/src/drivers/driver_nl80211.c | --- a/src/drivers/driver_nl80211.c | ||||||
| +++ b/src/drivers/driver_nl80211.c | +++ b/src/drivers/driver_nl80211.c | ||||||
| @@ -5951,7 +5951,7 @@ static int wpa_driver_nl80211_ibss(struc | @@ -5886,7 +5886,7 @@ static int wpa_driver_nl80211_ibss(struc | ||||||
|  				   struct wpa_driver_associate_params *params) |  				   struct wpa_driver_associate_params *params) | ||||||
|  { |  { | ||||||
|  	struct nl_msg *msg; |  	struct nl_msg *msg; | ||||||
| @@ -19,7 +19,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org> | |||||||
|  	int count = 0; |  	int count = 0; | ||||||
|   |   | ||||||
|  	wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); |  	wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); | ||||||
| @@ -5978,6 +5978,37 @@ retry: | @@ -5913,6 +5913,37 @@ retry: | ||||||
|  	    nl80211_put_beacon_int(msg, params->beacon_int)) |  	    nl80211_put_beacon_int(msg, params->beacon_int)) | ||||||
|  		goto fail; |  		goto fail; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com> | |||||||
|  struct wpa_driver_set_key_params { |  struct wpa_driver_set_key_params { | ||||||
| --- a/src/drivers/driver_nl80211.c | --- a/src/drivers/driver_nl80211.c | ||||||
| +++ b/src/drivers/driver_nl80211.c | +++ b/src/drivers/driver_nl80211.c | ||||||
| @@ -10476,6 +10476,18 @@ static int nl80211_put_mesh_id(struct nl | @@ -10398,6 +10398,18 @@ static int nl80211_put_mesh_id(struct nl | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -48,7 +48,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com> | |||||||
|  static int nl80211_put_mesh_config(struct nl_msg *msg, |  static int nl80211_put_mesh_config(struct nl_msg *msg, | ||||||
|  				   struct wpa_driver_mesh_bss_params *params) |  				   struct wpa_driver_mesh_bss_params *params) | ||||||
|  { |  { | ||||||
| @@ -10537,6 +10549,7 @@ static int nl80211_join_mesh(struct i802 | @@ -10459,6 +10471,7 @@ static int nl80211_join_mesh(struct i802 | ||||||
|  	    nl80211_put_basic_rates(msg, params->basic_rates) || |  	    nl80211_put_basic_rates(msg, params->basic_rates) || | ||||||
|  	    nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) || |  	    nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) || | ||||||
|  	    nl80211_put_beacon_int(msg, params->beacon_int) || |  	    nl80211_put_beacon_int(msg, params->beacon_int) || | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/wpa_supplicant/wpa_supplicant.c | --- a/wpa_supplicant/wpa_supplicant.c | ||||||
| +++ b/wpa_supplicant/wpa_supplicant.c | +++ b/wpa_supplicant/wpa_supplicant.c | ||||||
| @@ -2457,11 +2457,13 @@ void ibss_mesh_setup_freq(struct wpa_sup | @@ -2403,11 +2403,13 @@ void ibss_mesh_setup_freq(struct wpa_sup | ||||||
|  	for (j = 0; j < wpa_s->last_scan_res_used; j++) { |  	for (j = 0; j < wpa_s->last_scan_res_used; j++) { | ||||||
|  		struct wpa_bss *bss = wpa_s->last_scan_res[j]; |  		struct wpa_bss *bss = wpa_s->last_scan_res[j]; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
|  NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) |  NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) | ||||||
| --- a/wpa_supplicant/Makefile | --- a/wpa_supplicant/Makefile | ||||||
| +++ b/wpa_supplicant/Makefile | +++ b/wpa_supplicant/Makefile | ||||||
| @@ -1918,31 +1918,31 @@ wpa_supplicant_multi.a: .config $(BCHECK | @@ -1905,31 +1905,31 @@ wpa_supplicant_multi.a: .config $(BCHECK | ||||||
|  	@$(AR) cr $@ wpa_supplicant_multi.o $(OBJS) |  	@$(AR) cr $@ wpa_supplicant_multi.o $(OBJS) | ||||||
|   |   | ||||||
|  wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) |  wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/src/ap/hostapd.h | --- a/src/ap/hostapd.h | ||||||
| +++ b/src/ap/hostapd.h | +++ b/src/ap/hostapd.h | ||||||
| @@ -150,6 +150,21 @@ struct hostapd_sae_commit_queue { | @@ -148,6 +148,21 @@ struct hostapd_sae_commit_queue { | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
|  /** |  /** | ||||||
| @@ -22,7 +22,7 @@ | |||||||
|   * struct hostapd_data - hostapd per-BSS data structure |   * struct hostapd_data - hostapd per-BSS data structure | ||||||
|   */ |   */ | ||||||
|  struct hostapd_data { |  struct hostapd_data { | ||||||
| @@ -163,6 +178,9 @@ struct hostapd_data { | @@ -161,6 +176,9 @@ struct hostapd_data { | ||||||
|   |   | ||||||
|  	u8 own_addr[ETH_ALEN]; |  	u8 own_addr[ETH_ALEN]; | ||||||
|   |   | ||||||
| @@ -71,7 +71,7 @@ | |||||||
|  	if (disassoc_timer) { |  	if (disassoc_timer) { | ||||||
|  		/* send disassociation frame after time-out */ |  		/* send disassociation frame after time-out */ | ||||||
|  		set_disassoc_timer(hapd, sta, disassoc_timer); |  		set_disassoc_timer(hapd, sta, disassoc_timer); | ||||||
| @@ -857,6 +862,7 @@ int wnm_send_bss_tm_req(struct hostapd_d | @@ -856,6 +861,7 @@ int wnm_send_bss_tm_req(struct hostapd_d | ||||||
|  	} |  	} | ||||||
|  	os_free(buf); |  	os_free(buf); | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,19 +1,24 @@ | |||||||
| --- a/hostapd/Makefile | Index: hostapd-2021-02-20-59e9794c/hostapd/Makefile | ||||||
| +++ b/hostapd/Makefile | =================================================================== | ||||||
| @@ -166,6 +166,11 @@ OBJS += ../src/common/hw_features_common | --- hostapd-2021-02-20-59e9794c.orig/hostapd/Makefile | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/hostapd/Makefile | ||||||
|  | @@ -166,6 +166,12 @@ OBJS += ../src/common/hw_features_common | ||||||
|   |   | ||||||
|  OBJS += ../src/eapol_auth/eapol_auth_sm.o |  OBJS += ../src/eapol_auth/eapol_auth_sm.o | ||||||
|   |   | ||||||
| +ifdef CONFIG_UBUS | +ifdef CONFIG_UBUS | ||||||
| +CFLAGS += -DUBUS_SUPPORT | +CFLAGS += -DUBUS_SUPPORT | ||||||
|  | +OBJS += ../src/utils/uloop.o | ||||||
| +OBJS += ../src/ap/ubus.o | +OBJS += ../src/ap/ubus.o | ||||||
| +LIBS += -lubox -lubus | +LIBS += -lubox -lubus | ||||||
| +endif | +endif | ||||||
|   |   | ||||||
|  ifdef CONFIG_CODE_COVERAGE |  ifdef CONFIG_CODE_COVERAGE | ||||||
|  CFLAGS += -O0 -fprofile-arcs -ftest-coverage |  CFLAGS += -O0 -fprofile-arcs -ftest-coverage | ||||||
| --- a/src/ap/hostapd.h | Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.h | ||||||
| +++ b/src/ap/hostapd.h | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.h | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.h | ||||||
| @@ -17,6 +17,7 @@ | @@ -17,6 +17,7 @@ | ||||||
|  #include "utils/list.h" |  #include "utils/list.h" | ||||||
|  #include "ap_config.h" |  #include "ap_config.h" | ||||||
| @@ -22,16 +27,7 @@ | |||||||
|   |   | ||||||
|  #define OCE_STA_CFON_ENABLED(hapd) \ |  #define OCE_STA_CFON_ENABLED(hapd) \ | ||||||
|  	((hapd->conf->oce & OCE_STA_CFON) && \ |  	((hapd->conf->oce & OCE_STA_CFON) && \ | ||||||
| @@ -80,7 +81,7 @@ struct hapd_interfaces { | @@ -169,6 +170,7 @@ struct hostapd_data { | ||||||
|  #ifdef CONFIG_CTRL_IFACE_UDP |  | ||||||
|         unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; |  | ||||||
|  #endif /* CONFIG_CTRL_IFACE_UDP */ |  | ||||||
| - |  | ||||||
| +	struct ubus_object ubus; |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  enum hostapd_chan_status { |  | ||||||
| @@ -171,6 +172,7 @@ struct hostapd_data { |  | ||||||
|  	struct hostapd_iface *iface; |  	struct hostapd_iface *iface; | ||||||
|  	struct hostapd_config *iconf; |  	struct hostapd_config *iconf; | ||||||
|  	struct hostapd_bss_config *conf; |  	struct hostapd_bss_config *conf; | ||||||
| @@ -39,7 +35,7 @@ | |||||||
|  	int interface_added; /* virtual interface added for this BSS */ |  	int interface_added; /* virtual interface added for this BSS */ | ||||||
|  	unsigned int started:1; |  	unsigned int started:1; | ||||||
|  	unsigned int disabled:1; |  	unsigned int disabled:1; | ||||||
| @@ -630,6 +632,7 @@ hostapd_alloc_bss_data(struct hostapd_if | @@ -626,6 +628,7 @@ hostapd_alloc_bss_data(struct hostapd_if | ||||||
|  		       struct hostapd_bss_config *bss); |  		       struct hostapd_bss_config *bss); | ||||||
|  int hostapd_setup_interface(struct hostapd_iface *iface); |  int hostapd_setup_interface(struct hostapd_iface *iface); | ||||||
|  int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); |  int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); | ||||||
| @@ -47,9 +43,11 @@ | |||||||
|  void hostapd_interface_deinit(struct hostapd_iface *iface); |  void hostapd_interface_deinit(struct hostapd_iface *iface); | ||||||
|  void hostapd_interface_free(struct hostapd_iface *iface); |  void hostapd_interface_free(struct hostapd_iface *iface); | ||||||
|  struct hostapd_iface * hostapd_alloc_iface(void); |  struct hostapd_iface * hostapd_alloc_iface(void); | ||||||
| --- a/src/ap/hostapd.c | Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c | ||||||
| +++ b/src/ap/hostapd.c | =================================================================== | ||||||
| @@ -396,6 +396,7 @@ void hostapd_free_hapd_data(struct hosta | --- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.c | ||||||
|  | @@ -376,6 +376,7 @@ void hostapd_free_hapd_data(struct hosta | ||||||
|  	hapd->beacon_set_done = 0; |  	hapd->beacon_set_done = 0; | ||||||
|   |   | ||||||
|  	wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); |  	wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); | ||||||
| @@ -57,7 +55,7 @@ | |||||||
|  	accounting_deinit(hapd); |  	accounting_deinit(hapd); | ||||||
|  	hostapd_deinit_wpa(hapd); |  	hostapd_deinit_wpa(hapd); | ||||||
|  	vlan_deinit(hapd); |  	vlan_deinit(hapd); | ||||||
| @@ -1422,6 +1423,8 @@ static int hostapd_setup_bss(struct host | @@ -1398,6 +1399,8 @@ static int hostapd_setup_bss(struct host | ||||||
|  	if (hapd->driver && hapd->driver->set_operstate) |  	if (hapd->driver && hapd->driver->set_operstate) | ||||||
|  		hapd->driver->set_operstate(hapd->drv_priv, 1); |  		hapd->driver->set_operstate(hapd->drv_priv, 1); | ||||||
|   |   | ||||||
| @@ -66,7 +64,7 @@ | |||||||
|  	return 0; |  	return 0; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -2028,6 +2031,7 @@ static int hostapd_setup_interface_compl | @@ -1983,6 +1986,7 @@ static int hostapd_setup_interface_compl | ||||||
|  	if (err) |  	if (err) | ||||||
|  		goto fail; |  		goto fail; | ||||||
|   |   | ||||||
| @@ -74,7 +72,7 @@ | |||||||
|  	wpa_printf(MSG_DEBUG, "Completing interface initialization"); |  	wpa_printf(MSG_DEBUG, "Completing interface initialization"); | ||||||
|  	if (iface->freq) { |  	if (iface->freq) { | ||||||
|  #ifdef NEED_AP_MLME |  #ifdef NEED_AP_MLME | ||||||
| @@ -2225,6 +2229,7 @@ dfs_offload: | @@ -2180,6 +2184,7 @@ dfs_offload: | ||||||
|   |   | ||||||
|  fail: |  fail: | ||||||
|  	wpa_printf(MSG_ERROR, "Interface initialization failed"); |  	wpa_printf(MSG_ERROR, "Interface initialization failed"); | ||||||
| @@ -82,7 +80,7 @@ | |||||||
|  	hostapd_set_state(iface, HAPD_IFACE_DISABLED); |  	hostapd_set_state(iface, HAPD_IFACE_DISABLED); | ||||||
|  	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); |  	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); | ||||||
|  #ifdef CONFIG_FST |  #ifdef CONFIG_FST | ||||||
| @@ -2700,6 +2705,7 @@ void hostapd_interface_deinit_free(struc | @@ -2653,6 +2658,7 @@ void hostapd_interface_deinit_free(struc | ||||||
|  		   (unsigned int) iface->conf->num_bss); |  		   (unsigned int) iface->conf->num_bss); | ||||||
|  	driver = iface->bss[0]->driver; |  	driver = iface->bss[0]->driver; | ||||||
|  	drv_priv = iface->bss[0]->drv_priv; |  	drv_priv = iface->bss[0]->drv_priv; | ||||||
| @@ -90,9 +88,11 @@ | |||||||
|  	hostapd_interface_deinit(iface); |  	hostapd_interface_deinit(iface); | ||||||
|  	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", |  	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", | ||||||
|  		   __func__, driver, drv_priv); |  		   __func__, driver, drv_priv); | ||||||
| --- a/src/ap/ieee802_11.c | Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c | ||||||
| +++ b/src/ap/ieee802_11.c | =================================================================== | ||||||
| @@ -3553,13 +3553,18 @@ static void handle_auth(struct hostapd_d | --- hostapd-2021-02-20-59e9794c.orig/src/ap/ieee802_11.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c | ||||||
|  | @@ -3421,13 +3421,18 @@ static void handle_auth(struct hostapd_d | ||||||
|  	u16 auth_alg, auth_transaction, status_code; |  	u16 auth_alg, auth_transaction, status_code; | ||||||
|  	u16 resp = WLAN_STATUS_SUCCESS; |  	u16 resp = WLAN_STATUS_SUCCESS; | ||||||
|  	struct sta_info *sta = NULL; |  	struct sta_info *sta = NULL; | ||||||
| @@ -112,7 +112,7 @@ | |||||||
|   |   | ||||||
|  	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { |  	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { | ||||||
|  		wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)", |  		wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)", | ||||||
| @@ -3727,6 +3732,13 @@ static void handle_auth(struct hostapd_d | @@ -3595,6 +3600,13 @@ static void handle_auth(struct hostapd_d | ||||||
|  		resp = WLAN_STATUS_UNSPECIFIED_FAILURE; |  		resp = WLAN_STATUS_UNSPECIFIED_FAILURE; | ||||||
|  		goto fail; |  		goto fail; | ||||||
|  	} |  	} | ||||||
| @@ -126,7 +126,7 @@ | |||||||
|  	if (res == HOSTAPD_ACL_PENDING) |  	if (res == HOSTAPD_ACL_PENDING) | ||||||
|  		return; |  		return; | ||||||
|   |   | ||||||
| @@ -5447,7 +5459,7 @@ static void handle_assoc(struct hostapd_ | @@ -5322,7 +5334,7 @@ static void handle_assoc(struct hostapd_ | ||||||
|  	int resp = WLAN_STATUS_SUCCESS; |  	int resp = WLAN_STATUS_SUCCESS; | ||||||
|  	u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE; |  	u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE; | ||||||
|  	const u8 *pos; |  	const u8 *pos; | ||||||
| @@ -135,7 +135,7 @@ | |||||||
|  	struct sta_info *sta; |  	struct sta_info *sta; | ||||||
|  	u8 *tmp = NULL; |  	u8 *tmp = NULL; | ||||||
|  #ifdef CONFIG_FILS |  #ifdef CONFIG_FILS | ||||||
| @@ -5660,6 +5672,11 @@ static void handle_assoc(struct hostapd_ | @@ -5535,6 +5547,11 @@ static void handle_assoc(struct hostapd_ | ||||||
|  		left = res; |  		left = res; | ||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_FILS */ |  #endif /* CONFIG_FILS */ | ||||||
| @@ -147,7 +147,7 @@ | |||||||
|   |   | ||||||
|  	/* followed by SSID and Supported rates; and HT capabilities if 802.11n |  	/* followed by SSID and Supported rates; and HT capabilities if 802.11n | ||||||
|  	 * is used */ |  	 * is used */ | ||||||
| @@ -5758,6 +5775,13 @@ static void handle_assoc(struct hostapd_ | @@ -5633,6 +5650,13 @@ static void handle_assoc(struct hostapd_ | ||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_FILS */ |  #endif /* CONFIG_FILS */ | ||||||
|   |   | ||||||
| @@ -161,7 +161,7 @@ | |||||||
|   fail: |   fail: | ||||||
|   |   | ||||||
|  	/* |  	/* | ||||||
| @@ -5851,6 +5875,7 @@ static void handle_disassoc(struct hosta | @@ -5726,6 +5750,7 @@ static void handle_disassoc(struct hosta | ||||||
|  	wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d", |  	wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d", | ||||||
|  		   MAC2STR(mgmt->sa), |  		   MAC2STR(mgmt->sa), | ||||||
|  		   le_to_host16(mgmt->u.disassoc.reason_code)); |  		   le_to_host16(mgmt->u.disassoc.reason_code)); | ||||||
| @@ -169,18 +169,20 @@ | |||||||
|   |   | ||||||
|  	sta = ap_get_sta(hapd, mgmt->sa); |  	sta = ap_get_sta(hapd, mgmt->sa); | ||||||
|  	if (sta == NULL) { |  	if (sta == NULL) { | ||||||
| @@ -5920,6 +5945,8 @@ static void handle_deauth(struct hostapd | @@ -5792,6 +5817,8 @@ static void handle_deauth(struct hostapd | ||||||
|  	/* Clear the PTKSA cache entries for PASN */ |  		" reason_code=%d", | ||||||
|  	ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE); |  		MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); | ||||||
|   |   | ||||||
| +	hostapd_ubus_notify(hapd, "deauth", mgmt->sa); | +	hostapd_ubus_notify(hapd, "deauth", mgmt->sa); | ||||||
| + | + | ||||||
|  	sta = ap_get_sta(hapd, mgmt->sa); |  	sta = ap_get_sta(hapd, mgmt->sa); | ||||||
|  	if (sta == NULL) { |  	if (sta == NULL) { | ||||||
|  		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying " |  		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying " | ||||||
| --- a/src/ap/beacon.c | Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c | ||||||
| +++ b/src/ap/beacon.c | =================================================================== | ||||||
| @@ -852,6 +852,12 @@ void handle_probe_req(struct hostapd_dat | --- hostapd-2021-02-20-59e9794c.orig/src/ap/beacon.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/beacon.c | ||||||
|  | @@ -823,6 +823,12 @@ void handle_probe_req(struct hostapd_dat | ||||||
|  	u16 csa_offs[2]; |  	u16 csa_offs[2]; | ||||||
|  	size_t csa_offs_len; |  	size_t csa_offs_len; | ||||||
|  	struct radius_sta rad_info; |  	struct radius_sta rad_info; | ||||||
| @@ -193,7 +195,7 @@ | |||||||
|   |   | ||||||
|  	if (hapd->iconf->rssi_ignore_probe_request && ssi_signal && |  	if (hapd->iconf->rssi_ignore_probe_request && ssi_signal && | ||||||
|  	    ssi_signal < hapd->iconf->rssi_ignore_probe_request) |  	    ssi_signal < hapd->iconf->rssi_ignore_probe_request) | ||||||
| @@ -1038,6 +1044,12 @@ void handle_probe_req(struct hostapd_dat | @@ -1009,6 +1015,12 @@ void handle_probe_req(struct hostapd_dat | ||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_P2P */ |  #endif /* CONFIG_P2P */ | ||||||
|   |   | ||||||
| @@ -206,8 +208,10 @@ | |||||||
|  	/* TODO: verify that supp_rates contains at least one matching rate |  	/* TODO: verify that supp_rates contains at least one matching rate | ||||||
|  	 * with AP configuration */ |  	 * with AP configuration */ | ||||||
|   |   | ||||||
| --- a/src/ap/drv_callbacks.c | Index: hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c | ||||||
| +++ b/src/ap/drv_callbacks.c | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/drv_callbacks.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c | ||||||
| @@ -145,6 +145,10 @@ int hostapd_notif_assoc(struct hostapd_d | @@ -145,6 +145,10 @@ int hostapd_notif_assoc(struct hostapd_d | ||||||
|  	u16 reason = WLAN_REASON_UNSPECIFIED; |  	u16 reason = WLAN_REASON_UNSPECIFIED; | ||||||
|  	int status = WLAN_STATUS_SUCCESS; |  	int status = WLAN_STATUS_SUCCESS; | ||||||
| @@ -232,8 +236,22 @@ | |||||||
|  #ifdef CONFIG_P2P |  #ifdef CONFIG_P2P | ||||||
|  	if (elems.p2p) { |  	if (elems.p2p) { | ||||||
|  		wpabuf_free(sta->p2p_ie); |  		wpabuf_free(sta->p2p_ie); | ||||||
| --- a/src/ap/sta_info.c | @@ -981,9 +991,11 @@ void hostapd_event_ch_switch(struct host | ||||||
| +++ b/src/ap/sta_info.c |   | ||||||
|  |  		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED | ||||||
|  |  			"freq=%d dfs=%d", freq, is_dfs); | ||||||
|  | +		hostapd_ubus_notify_csa(hapd, freq); | ||||||
|  |  	} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { | ||||||
|  |  		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED | ||||||
|  |  			"freq=%d dfs=%d", freq, is_dfs); | ||||||
|  | +		hostapd_ubus_notify_csa(hapd, freq); | ||||||
|  |  	} else if (is_dfs && | ||||||
|  |  		   hostapd_is_dfs_required(hapd->iface) && | ||||||
|  |  		   !hostapd_is_dfs_chan_available(hapd->iface) && | ||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.c | ||||||
| @@ -458,6 +458,7 @@ void ap_handle_timer(void *eloop_ctx, vo | @@ -458,6 +458,7 @@ void ap_handle_timer(void *eloop_ctx, vo | ||||||
|  		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |  		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, | ||||||
|  			       HOSTAPD_LEVEL_INFO, "deauthenticated due to " |  			       HOSTAPD_LEVEL_INFO, "deauthenticated due to " | ||||||
| @@ -250,16 +268,72 @@ | |||||||
|  		ap_free_sta(hapd, sta); |  		ap_free_sta(hapd, sta); | ||||||
|  		break; |  		break; | ||||||
|  	} |  	} | ||||||
| @@ -1329,6 +1331,7 @@ void ap_sta_set_authorized(struct hostap | @@ -1298,12 +1300,25 @@ void ap_sta_set_authorized(struct hostap | ||||||
|  					  buf, ip_addr, keyid_buf); |  					sta->addr, authorized, dev_addr); | ||||||
|  |   | ||||||
|  |  	if (authorized) { | ||||||
|  | +		static const char * const auth_algs[] = { | ||||||
|  | +			[WLAN_AUTH_OPEN] = "open", | ||||||
|  | +			[WLAN_AUTH_SHARED_KEY] = "shared", | ||||||
|  | +			[WLAN_AUTH_FT] = "ft", | ||||||
|  | +			[WLAN_AUTH_SAE] = "sae", | ||||||
|  | +			[WLAN_AUTH_FILS_SK] = "fils-sk", | ||||||
|  | +			[WLAN_AUTH_FILS_SK_PFS] = "fils-sk-pfs", | ||||||
|  | +			[WLAN_AUTH_FILS_PK] = "fils-pk", | ||||||
|  | +			[WLAN_AUTH_PASN] = "pasn", | ||||||
|  | +		}; | ||||||
|  | +		const char *auth_alg = NULL; | ||||||
|  |  		const char *keyid; | ||||||
|  |  		char keyid_buf[100]; | ||||||
|  |  		char ip_addr[100]; | ||||||
|  | +		char alg_buf[100]; | ||||||
|  |   | ||||||
|  |  		keyid_buf[0] = '\0'; | ||||||
|  |  		ip_addr[0] = '\0'; | ||||||
|  | +		alg_buf[0] = '\0'; | ||||||
|  |  #ifdef CONFIG_P2P | ||||||
|  |  		if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { | ||||||
|  |  			os_snprintf(ip_addr, sizeof(ip_addr), | ||||||
|  | @@ -1313,22 +1328,31 @@ void ap_sta_set_authorized(struct hostap | ||||||
|  |  		} | ||||||
|  |  #endif /* CONFIG_P2P */ | ||||||
|  |   | ||||||
|  | +		if (sta->auth_alg < ARRAY_SIZE(auth_algs)) | ||||||
|  | +			auth_alg = auth_algs[sta->auth_alg]; | ||||||
|  | + | ||||||
|  | +		if (auth_alg) | ||||||
|  | +			os_snprintf(alg_buf, sizeof(alg_buf), | ||||||
|  | +				" auth_alg=%s", auth_alg); | ||||||
|  | + | ||||||
|  |  		keyid = ap_sta_wpa_get_keyid(hapd, sta); | ||||||
|  |  		if (keyid) { | ||||||
|  |  			os_snprintf(keyid_buf, sizeof(keyid_buf), | ||||||
|  |  				    " keyid=%s", keyid); | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  | -		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s", | ||||||
|  | -			buf, ip_addr, keyid_buf); | ||||||
|  | +		hostapd_ubus_notify_authorized(hapd, sta); | ||||||
|  | +		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s", | ||||||
|  | +			buf, ip_addr, keyid_buf, alg_buf); | ||||||
|  |   | ||||||
|  |  		if (hapd->msg_ctx_parent && | ||||||
|  |  		    hapd->msg_ctx_parent != hapd->msg_ctx) | ||||||
|  |  			wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, | ||||||
|  | -					  AP_STA_CONNECTED "%s%s%s", | ||||||
|  | -					  buf, ip_addr, keyid_buf); | ||||||
|  | +					  AP_STA_CONNECTED "%s%s%s%s", | ||||||
|  | +					  buf, ip_addr, keyid_buf, alg_buf); | ||||||
|  	} else { |  	} else { | ||||||
|  		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); |  		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); | ||||||
| +		hostapd_ubus_notify(hapd, "disassoc", sta->addr); | +		hostapd_ubus_notify(hapd, "disassoc", sta->addr); | ||||||
|   |   | ||||||
|  		if (hapd->msg_ctx_parent && |  		if (hapd->msg_ctx_parent && | ||||||
|  		    hapd->msg_ctx_parent != hapd->msg_ctx) |  		    hapd->msg_ctx_parent != hapd->msg_ctx) | ||||||
| --- a/src/ap/wpa_auth_glue.c | Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c | ||||||
| +++ b/src/ap/wpa_auth_glue.c | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_glue.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c | ||||||
| @@ -265,6 +265,7 @@ static void hostapd_wpa_auth_psk_failure | @@ -265,6 +265,7 @@ static void hostapd_wpa_auth_psk_failure | ||||||
|  	struct hostapd_data *hapd = ctx; |  	struct hostapd_data *hapd = ctx; | ||||||
|  	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR, |  	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR, | ||||||
| @@ -268,22 +342,25 @@ | |||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| --- a/wpa_supplicant/Makefile | Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile | ||||||
| +++ b/wpa_supplicant/Makefile | =================================================================== | ||||||
| @@ -176,6 +176,12 @@ ifdef CONFIG_EAPOL_TEST | --- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/Makefile | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile | ||||||
|  | @@ -169,6 +169,13 @@ ifdef CONFIG_EAPOL_TEST | ||||||
|  CFLAGS += -Werror -DEAPOL_TEST |  CFLAGS += -Werror -DEAPOL_TEST | ||||||
|  endif |  endif | ||||||
|   |   | ||||||
| +ifdef CONFIG_UBUS | +ifdef CONFIG_UBUS | ||||||
| +CFLAGS += -DUBUS_SUPPORT | +CFLAGS += -DUBUS_SUPPORT | ||||||
| +OBJS += ubus.o | +OBJS += ubus.o | ||||||
|  | +OBJS += ../src/utils/uloop.o | ||||||
| +LIBS += -lubox -lubus | +LIBS += -lubox -lubus | ||||||
| +endif | +endif | ||||||
| + | + | ||||||
|  ifdef CONFIG_CODE_COVERAGE |  ifdef CONFIG_CODE_COVERAGE | ||||||
|  CFLAGS += -O0 -fprofile-arcs -ftest-coverage |  CFLAGS += -O0 -fprofile-arcs -ftest-coverage | ||||||
|  LIBS += -lgcov |  LIBS += -lgcov | ||||||
| @@ -962,6 +968,9 @@ ifdef CONFIG_CTRL_IFACE_MIB | @@ -946,6 +953,9 @@ ifdef CONFIG_CTRL_IFACE_MIB | ||||||
|  CFLAGS += -DCONFIG_CTRL_IFACE_MIB |  CFLAGS += -DCONFIG_CTRL_IFACE_MIB | ||||||
|  endif |  endif | ||||||
|  OBJS += ../src/ap/ctrl_iface_ap.o |  OBJS += ../src/ap/ctrl_iface_ap.o | ||||||
| @@ -293,9 +370,11 @@ | |||||||
|  endif |  endif | ||||||
|   |   | ||||||
|  CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY |  CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY | ||||||
| --- a/wpa_supplicant/wpa_supplicant.c | Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c | ||||||
| +++ b/wpa_supplicant/wpa_supplicant.c | =================================================================== | ||||||
| @@ -7241,6 +7241,8 @@ struct wpa_supplicant * wpa_supplicant_a | --- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wpa_supplicant.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c | ||||||
|  | @@ -6943,6 +6943,8 @@ struct wpa_supplicant * wpa_supplicant_a | ||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_P2P */ |  #endif /* CONFIG_P2P */ | ||||||
|   |   | ||||||
| @@ -304,7 +383,7 @@ | |||||||
|  	return wpa_s; |  	return wpa_s; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -7267,6 +7269,8 @@ int wpa_supplicant_remove_iface(struct w | @@ -6969,6 +6971,8 @@ int wpa_supplicant_remove_iface(struct w | ||||||
|  	struct wpa_supplicant *parent = wpa_s->parent; |  	struct wpa_supplicant *parent = wpa_s->parent; | ||||||
|  #endif /* CONFIG_MESH */ |  #endif /* CONFIG_MESH */ | ||||||
|   |   | ||||||
| @@ -313,7 +392,7 @@ | |||||||
|  	/* Remove interface from the global list of interfaces */ |  	/* Remove interface from the global list of interfaces */ | ||||||
|  	prev = global->ifaces; |  	prev = global->ifaces; | ||||||
|  	if (prev == wpa_s) { |  	if (prev == wpa_s) { | ||||||
| @@ -7570,8 +7574,12 @@ int wpa_supplicant_run(struct wpa_global | @@ -7272,8 +7276,12 @@ int wpa_supplicant_run(struct wpa_global | ||||||
|  	eloop_register_signal_terminate(wpa_supplicant_terminate, global); |  	eloop_register_signal_terminate(wpa_supplicant_terminate, global); | ||||||
|  	eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); |  	eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); | ||||||
|   |   | ||||||
| @@ -326,8 +405,10 @@ | |||||||
|  	return 0; |  	return 0; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| --- a/wpa_supplicant/wpa_supplicant_i.h | Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h | ||||||
| +++ b/wpa_supplicant/wpa_supplicant_i.h | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wpa_supplicant_i.h | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h | ||||||
| @@ -19,6 +19,7 @@ | @@ -19,6 +19,7 @@ | ||||||
|  #include "wps/wps_defs.h" |  #include "wps/wps_defs.h" | ||||||
|  #include "config_ssid.h" |  #include "config_ssid.h" | ||||||
| @@ -336,7 +417,7 @@ | |||||||
|   |   | ||||||
|  extern const char *const wpa_supplicant_version; |  extern const char *const wpa_supplicant_version; | ||||||
|  extern const char *const wpa_supplicant_license; |  extern const char *const wpa_supplicant_license; | ||||||
| @@ -322,6 +323,8 @@ struct wpa_global { | @@ -316,6 +317,8 @@ struct wpa_global { | ||||||
|  #endif /* CONFIG_WIFI_DISPLAY */ |  #endif /* CONFIG_WIFI_DISPLAY */ | ||||||
|   |   | ||||||
|  	struct psk_list_entry *add_psk; /* From group formation */ |  	struct psk_list_entry *add_psk; /* From group formation */ | ||||||
| @@ -345,7 +426,7 @@ | |||||||
|  }; |  }; | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -708,6 +711,7 @@ struct wpa_supplicant { | @@ -596,6 +599,7 @@ struct wpa_supplicant { | ||||||
|  	unsigned char own_addr[ETH_ALEN]; |  	unsigned char own_addr[ETH_ALEN]; | ||||||
|  	unsigned char perm_addr[ETH_ALEN]; |  	unsigned char perm_addr[ETH_ALEN]; | ||||||
|  	char ifname[100]; |  	char ifname[100]; | ||||||
| @@ -353,8 +434,10 @@ | |||||||
|  #ifdef CONFIG_MATCH_IFACE |  #ifdef CONFIG_MATCH_IFACE | ||||||
|  	int matched; |  	int matched; | ||||||
|  #endif /* CONFIG_MATCH_IFACE */ |  #endif /* CONFIG_MATCH_IFACE */ | ||||||
| --- a/wpa_supplicant/wps_supplicant.c | Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c | ||||||
| +++ b/wpa_supplicant/wps_supplicant.c | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wps_supplicant.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c | ||||||
| @@ -33,6 +33,7 @@ | @@ -33,6 +33,7 @@ | ||||||
|  #include "p2p/p2p.h" |  #include "p2p/p2p.h" | ||||||
|  #include "p2p_supplicant.h" |  #include "p2p_supplicant.h" | ||||||
| @@ -363,7 +446,7 @@ | |||||||
|   |   | ||||||
|   |   | ||||||
|  #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG |  #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG | ||||||
| @@ -393,6 +394,8 @@ static int wpa_supplicant_wps_cred(void | @@ -392,6 +393,8 @@ static int wpa_supplicant_wps_cred(void | ||||||
|  	wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", |  	wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", | ||||||
|  			cred->cred_attr, cred->cred_attr_len); |  			cred->cred_attr, cred->cred_attr_len); | ||||||
|   |   | ||||||
| @@ -372,36 +455,20 @@ | |||||||
|  	if (wpa_s->conf->wps_cred_processing == 1) |  	if (wpa_s->conf->wps_cred_processing == 1) | ||||||
|  		return 0; |  		return 0; | ||||||
|   |   | ||||||
| --- a/hostapd/main.c | Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c | ||||||
| +++ b/hostapd/main.c | =================================================================== | ||||||
| @@ -895,6 +895,7 @@ int main(int argc, char *argv[]) | --- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/main.c | ||||||
|  	} | +++ hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c | ||||||
|   | @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) | ||||||
|  	hostapd_global_ctrl_iface_init(&interfaces); |  | ||||||
| +	hostapd_ubus_add(&interfaces); |  | ||||||
|   |  | ||||||
|  	if (hostapd_global_run(&interfaces, daemonize, pid_file)) { |  | ||||||
|  		wpa_printf(MSG_ERROR, "Failed to start eloop"); |  | ||||||
| @@ -904,6 +905,7 @@ int main(int argc, char *argv[]) |  | ||||||
|  	ret = 0; |  | ||||||
|   |  | ||||||
|   out: |  | ||||||
| +	hostapd_ubus_free(&interfaces); |  | ||||||
|  	hostapd_global_ctrl_iface_deinit(&interfaces); |  | ||||||
|  	/* Deinitialize all interfaces */ |  | ||||||
|  	for (i = 0; i < interfaces.count; i++) { |  | ||||||
| --- a/wpa_supplicant/main.c |  | ||||||
| +++ b/wpa_supplicant/main.c |  | ||||||
| @@ -203,7 +203,7 @@ int main(int argc, char *argv[]) |  | ||||||
|   |   | ||||||
|  	for (;;) { |  	for (;;) { | ||||||
|  		c = getopt(argc, argv, |  		c = getopt(argc, argv, | ||||||
| -			   "b:Bc:C:D:de:f:g:G:hH:i:I:KLMm:No:O:p:P:qsTtuv::W"); | -			   "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuv::W"); | ||||||
| +			   "b:Bc:C:D:de:f:g:G:hH:i:I:KLMm:nNo:O:p:P:qsTtuv::W"); | +			   "b:Bc:C:D:de:f:g:G:hi:I:KLMm:nNo:O:p:P:qsTtuv::W"); | ||||||
|  		if (c < 0) |  		if (c < 0) | ||||||
|  			break; |  			break; | ||||||
|  		switch (c) { |  		switch (c) { | ||||||
| @@ -271,6 +271,9 @@ int main(int argc, char *argv[]) | @@ -267,6 +267,9 @@ int main(int argc, char *argv[]) | ||||||
|  			params.conf_p2p_dev = optarg; |  			params.conf_p2p_dev = optarg; | ||||||
|  			break; |  			break; | ||||||
|  #endif /* CONFIG_P2P */ |  #endif /* CONFIG_P2P */ | ||||||
| @@ -411,8 +478,10 @@ | |||||||
|  		case 'o': |  		case 'o': | ||||||
|  			params.override_driver = optarg; |  			params.override_driver = optarg; | ||||||
|  			break; |  			break; | ||||||
| --- a/src/ap/rrm.c | Index: hostapd-2021-02-20-59e9794c/src/ap/rrm.c | ||||||
| +++ b/src/ap/rrm.c | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/rrm.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/rrm.c | ||||||
| @@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report | @@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report | ||||||
|  		return; |  		return; | ||||||
|  	wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s", |  	wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s", | ||||||
| @@ -423,8 +492,10 @@ | |||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| --- a/src/ap/vlan_init.c | Index: hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c | ||||||
| +++ b/src/ap/vlan_init.c | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/vlan_init.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c | ||||||
| @@ -22,6 +22,7 @@ | @@ -22,6 +22,7 @@ | ||||||
|  static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan, |  static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan, | ||||||
|  		       int existsok) |  		       int existsok) | ||||||
| @@ -461,9 +532,11 @@ | |||||||
|  	return hostapd_vlan_if_remove(hapd, vlan->ifname); |  	return hostapd_vlan_if_remove(hapd, vlan->ifname); | ||||||
|  } |  } | ||||||
|   |   | ||||||
| --- a/src/ap/dfs.c | Index: hostapd-2021-02-20-59e9794c/src/ap/dfs.c | ||||||
| +++ b/src/ap/dfs.c | =================================================================== | ||||||
| @@ -1196,6 +1196,8 @@ int hostapd_dfs_radar_detected(struct ho | --- hostapd-2021-02-20-59e9794c.orig/src/ap/dfs.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/dfs.c | ||||||
|  | @@ -1226,6 +1226,8 @@ int hostapd_dfs_nop_finished(struct host | ||||||
|  		"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", |  		"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", | ||||||
|  		freq, ht_enabled, chan_offset, chan_width, cf1, cf2); |  		freq, ht_enabled, chan_offset, chan_width, cf1, cf2); | ||||||
|   |   | ||||||
| @@ -472,9 +545,11 @@ | |||||||
|  	/* Proceed only if DFS is not offloaded to the driver */ |  	/* Proceed only if DFS is not offloaded to the driver */ | ||||||
|  	if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) |  	if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) | ||||||
|  		return 0; |  		return 0; | ||||||
| --- a/src/ap/airtime_policy.c | Index: hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c | ||||||
| +++ b/src/ap/airtime_policy.c | =================================================================== | ||||||
| @@ -112,8 +112,14 @@ static void set_sta_weights(struct hosta | --- hostapd-2021-02-20-59e9794c.orig/src/ap/airtime_policy.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c | ||||||
|  | @@ -108,8 +108,14 @@ static void set_sta_weights(struct hosta | ||||||
|  { |  { | ||||||
|  	struct sta_info *sta; |  	struct sta_info *sta; | ||||||
|   |   | ||||||
| @@ -491,7 +566,7 @@ | |||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -244,7 +250,10 @@ int airtime_policy_new_sta(struct hostap | @@ -240,7 +246,10 @@ int airtime_policy_new_sta(struct hostap | ||||||
|  	unsigned int weight; |  	unsigned int weight; | ||||||
|   |   | ||||||
|  	if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) { |  	if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) { | ||||||
| @@ -503,9 +578,11 @@ | |||||||
|  		if (weight) |  		if (weight) | ||||||
|  			return sta_set_airtime_weight(hapd, sta, weight); |  			return sta_set_airtime_weight(hapd, sta, weight); | ||||||
|  	} |  	} | ||||||
| --- a/src/ap/sta_info.h | Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h | ||||||
| +++ b/src/ap/sta_info.h | =================================================================== | ||||||
| @@ -324,6 +324,7 @@ struct sta_info { | --- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.h | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.h | ||||||
|  | @@ -323,6 +323,7 @@ struct sta_info { | ||||||
|  #endif /* CONFIG_TESTING_OPTIONS */ |  #endif /* CONFIG_TESTING_OPTIONS */ | ||||||
|  #ifdef CONFIG_AIRTIME_POLICY |  #ifdef CONFIG_AIRTIME_POLICY | ||||||
|  	unsigned int airtime_weight; |  	unsigned int airtime_weight; | ||||||
| @@ -513,8 +590,10 @@ | |||||||
|  	struct os_reltime backlogged_until; |  	struct os_reltime backlogged_until; | ||||||
|  #endif /* CONFIG_AIRTIME_POLICY */ |  #endif /* CONFIG_AIRTIME_POLICY */ | ||||||
|   |   | ||||||
| --- a/src/ap/wnm_ap.c | Index: hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c | ||||||
| +++ b/src/ap/wnm_ap.c | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/wnm_ap.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c | ||||||
| @@ -442,7 +442,8 @@ static void ieee802_11_rx_bss_trans_mgmt | @@ -442,7 +442,8 @@ static void ieee802_11_rx_bss_trans_mgmt | ||||||
|  	wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", |  	wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", | ||||||
|  		    pos, end - pos); |  		    pos, end - pos); | ||||||
| @@ -553,3 +632,157 @@ | |||||||
|  	wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", |  	wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", | ||||||
|  		    pos, end - pos); |  		    pos, end - pos); | ||||||
|  } |  } | ||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/utils/eloop.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/utils/eloop.c | ||||||
|  | @@ -77,6 +77,9 @@ struct eloop_sock_table { | ||||||
|  |  struct eloop_data { | ||||||
|  |  	int max_sock; | ||||||
|  |   | ||||||
|  | +	eloop_timeout_poll_handler timeout_poll_cb; | ||||||
|  | +	eloop_poll_handler poll_cb; | ||||||
|  | + | ||||||
|  |  	size_t count; /* sum of all table counts */ | ||||||
|  |  #ifdef CONFIG_ELOOP_POLL | ||||||
|  |  	size_t max_pollfd_map; /* number of pollfds_map currently allocated */ | ||||||
|  | @@ -1116,6 +1119,12 @@ void eloop_run(void) | ||||||
|  |  				os_reltime_sub(&timeout->time, &now, &tv); | ||||||
|  |  			else | ||||||
|  |  				tv.sec = tv.usec = 0; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		if (eloop.timeout_poll_cb && eloop.timeout_poll_cb(&tv, !!timeout)) | ||||||
|  | +			timeout = (void *)1; | ||||||
|  | + | ||||||
|  | +		if (timeout) { | ||||||
|  |  #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) | ||||||
|  |  			timeout_ms = tv.sec * 1000 + tv.usec / 1000; | ||||||
|  |  #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */ | ||||||
|  | @@ -1185,7 +1194,8 @@ void eloop_run(void) | ||||||
|  |  		eloop.exceptions.changed = 0; | ||||||
|  |   | ||||||
|  |  		eloop_process_pending_signals(); | ||||||
|  | - | ||||||
|  | +		if (eloop.poll_cb) | ||||||
|  | +			eloop.poll_cb(); | ||||||
|  |   | ||||||
|  |  		/* check if some registered timeouts have occurred */ | ||||||
|  |  		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, | ||||||
|  | @@ -1247,6 +1257,14 @@ out: | ||||||
|  |  	return; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int eloop_register_cb(eloop_poll_handler poll_cb, | ||||||
|  | +		      eloop_timeout_poll_handler timeout_cb) | ||||||
|  | +{ | ||||||
|  | +	eloop.poll_cb = poll_cb; | ||||||
|  | +	eloop.timeout_poll_cb = timeout_cb; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  |   | ||||||
|  |  void eloop_terminate(void) | ||||||
|  |  { | ||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.h | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/utils/eloop.h | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/utils/eloop.h | ||||||
|  | @@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(vo | ||||||
|  |   */ | ||||||
|  |  typedef void (*eloop_signal_handler)(int sig, void *signal_ctx); | ||||||
|  |   | ||||||
|  | +typedef bool (*eloop_timeout_poll_handler)(struct os_reltime *tv, bool tv_set); | ||||||
|  | +typedef void (*eloop_poll_handler)(void); | ||||||
|  | + | ||||||
|  |  /** | ||||||
|  |   * eloop_init() - Initialize global event loop data | ||||||
|  |   * Returns: 0 on success, -1 on failure | ||||||
|  | @@ -73,6 +76,9 @@ typedef void (*eloop_signal_handler)(int | ||||||
|  |   */ | ||||||
|  |  int eloop_init(void); | ||||||
|  |   | ||||||
|  | +int eloop_register_cb(eloop_poll_handler poll_cb, | ||||||
|  | +		      eloop_timeout_poll_handler timeout_cb); | ||||||
|  | + | ||||||
|  |  /** | ||||||
|  |   * eloop_register_read_sock - Register handler for read events | ||||||
|  |   * @sock: File descriptor number for the socket | ||||||
|  | @@ -320,6 +326,8 @@ int eloop_register_signal_reconfig(eloop | ||||||
|  |   */ | ||||||
|  |  int eloop_sock_requeue(void); | ||||||
|  |   | ||||||
|  | +void eloop_add_uloop(void); | ||||||
|  | + | ||||||
|  |  /** | ||||||
|  |   * eloop_run - Start the event loop | ||||||
|  |   * | ||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/utils/uloop.c | ||||||
|  | =================================================================== | ||||||
|  | --- /dev/null | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/utils/uloop.c | ||||||
|  | @@ -0,0 +1,64 @@ | ||||||
|  | +#include <libubox/uloop.h> | ||||||
|  | +#include "includes.h" | ||||||
|  | +#include "common.h" | ||||||
|  | +#include "eloop.h" | ||||||
|  | + | ||||||
|  | +static void eloop_uloop_event_cb(int sock, void *eloop_ctx, void *sock_ctx) | ||||||
|  | +{ | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void eloop_uloop_fd_cb(struct uloop_fd *fd, unsigned int events) | ||||||
|  | +{ | ||||||
|  | +	unsigned int changed = events ^ fd->flags; | ||||||
|  | + | ||||||
|  | +	if (changed & ULOOP_READ) { | ||||||
|  | +		if (events & ULOOP_READ) | ||||||
|  | +			eloop_register_sock(fd->fd, EVENT_TYPE_READ, eloop_uloop_event_cb, fd, fd); | ||||||
|  | +		else | ||||||
|  | +			eloop_unregister_sock(fd->fd, EVENT_TYPE_READ); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (changed & ULOOP_WRITE) { | ||||||
|  | +		if (events & ULOOP_WRITE) | ||||||
|  | +			eloop_register_sock(fd->fd, EVENT_TYPE_WRITE, eloop_uloop_event_cb, fd, fd); | ||||||
|  | +		else | ||||||
|  | +			eloop_unregister_sock(fd->fd, EVENT_TYPE_WRITE); | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static bool uloop_timeout_poll_handler(struct os_reltime *tv, bool tv_set) | ||||||
|  | +{ | ||||||
|  | +	struct os_reltime tv_uloop; | ||||||
|  | +	int timeout_ms = uloop_get_next_timeout(); | ||||||
|  | + | ||||||
|  | +	if (timeout_ms < 0) | ||||||
|  | +		return false; | ||||||
|  | + | ||||||
|  | +	tv_uloop.sec = timeout_ms / 1000; | ||||||
|  | +	tv_uloop.usec = (timeout_ms % 1000) * 1000; | ||||||
|  | + | ||||||
|  | +	if (!tv_set || os_reltime_before(&tv_uloop, tv)) { | ||||||
|  | +		*tv = tv_uloop; | ||||||
|  | +		return true; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return false; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void uloop_poll_handler(void) | ||||||
|  | +{ | ||||||
|  | +	uloop_run_timeout(0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +void eloop_add_uloop(void) | ||||||
|  | +{ | ||||||
|  | +	static bool init_done = false; | ||||||
|  | + | ||||||
|  | +	if (!init_done) { | ||||||
|  | +		uloop_init(); | ||||||
|  | +		uloop_fd_set_cb = eloop_uloop_fd_cb; | ||||||
|  | +		init_done = true; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	eloop_register_cb(uloop_poll_handler, uloop_timeout_poll_handler); | ||||||
|  | +} | ||||||
|   | |||||||
							
								
								
									
										596
									
								
								feeds/ipq95xx/hostapd/patches/601-ucode_support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										596
									
								
								feeds/ipq95xx/hostapd/patches/601-ucode_support.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,596 @@ | |||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/hostapd/Makefile | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/hostapd/Makefile | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/hostapd/Makefile | ||||||
|  | @@ -168,9 +168,21 @@ OBJS += ../src/eapol_auth/eapol_auth_sm. | ||||||
|  |   | ||||||
|  |  ifdef CONFIG_UBUS | ||||||
|  |  CFLAGS += -DUBUS_SUPPORT | ||||||
|  | -OBJS += ../src/utils/uloop.o | ||||||
|  |  OBJS += ../src/ap/ubus.o | ||||||
|  | -LIBS += -lubox -lubus | ||||||
|  | +LIBS += -lubus | ||||||
|  | +NEED_ULOOP:=y | ||||||
|  | +endif | ||||||
|  | + | ||||||
|  | +ifdef CONFIG_UCODE | ||||||
|  | +CFLAGS += -DUCODE_SUPPORT | ||||||
|  | +OBJS += ../src/utils/ucode.o | ||||||
|  | +OBJS += ../src/ap/ucode.o | ||||||
|  | +NEED_ULOOP:=y | ||||||
|  | +endif | ||||||
|  | + | ||||||
|  | +ifdef NEED_ULOOP | ||||||
|  | +OBJS += ../src/utils/uloop.o | ||||||
|  | +LIBS += -lubox | ||||||
|  |  endif | ||||||
|  |   | ||||||
|  |  ifdef CONFIG_CODE_COVERAGE | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/hostapd/main.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/hostapd/main.c | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/hostapd/main.c | ||||||
|  | @@ -898,6 +898,7 @@ int main(int argc, char *argv[]) | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	hostapd_global_ctrl_iface_init(&interfaces); | ||||||
|  | +	hostapd_ucode_init(&interfaces); | ||||||
|  |   | ||||||
|  |  	if (hostapd_global_run(&interfaces, daemonize, pid_file)) { | ||||||
|  |  		wpa_printf(MSG_ERROR, "Failed to start eloop"); | ||||||
|  | @@ -907,6 +908,7 @@ int main(int argc, char *argv[]) | ||||||
|  |  	ret = 0; | ||||||
|  |   | ||||||
|  |   out: | ||||||
|  | +	hostapd_ucode_free(); | ||||||
|  |  	hostapd_global_ctrl_iface_deinit(&interfaces); | ||||||
|  |  	/* Deinitialize all interfaces */ | ||||||
|  |  	for (i = 0; i < interfaces.count; i++) { | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.h | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h | ||||||
|  | @@ -18,6 +18,7 @@ | ||||||
|  |  #include "ap_config.h" | ||||||
|  |  #include "drivers/driver.h" | ||||||
|  |  #include "ubus.h" | ||||||
|  | +#include "ucode.h" | ||||||
|  |   | ||||||
|  |  #define OCE_STA_CFON_ENABLED(hapd) \ | ||||||
|  |  	((hapd->conf->oce & OCE_STA_CFON) && \ | ||||||
|  | @@ -50,6 +51,10 @@ struct hapd_interfaces { | ||||||
|  |  	struct hostapd_config * (*config_read_cb)(const char *config_fname); | ||||||
|  |  	int (*ctrl_iface_init)(struct hostapd_data *hapd); | ||||||
|  |  	void (*ctrl_iface_deinit)(struct hostapd_data *hapd); | ||||||
|  | +	int (*ctrl_iface_recv)(struct hostapd_data *hapd, | ||||||
|  | +			       char *buf, char *reply, int reply_size, | ||||||
|  | +			       struct sockaddr_storage *from, | ||||||
|  | +			       socklen_t fromlen); | ||||||
|  |  	int (*for_each_interface)(struct hapd_interfaces *interfaces, | ||||||
|  |  				  int (*cb)(struct hostapd_iface *iface, | ||||||
|  |  					    void *ctx), void *ctx); | ||||||
|  | @@ -173,6 +178,7 @@ struct hostapd_data { | ||||||
|  |  	struct hostapd_config *iconf; | ||||||
|  |  	struct hostapd_bss_config *conf; | ||||||
|  |  	struct hostapd_ubus_bss ubus; | ||||||
|  | +	struct hostapd_ucode_bss ucode; | ||||||
|  |  	int interface_added; /* virtual interface added for this BSS */ | ||||||
|  |  	unsigned int started:1; | ||||||
|  |  	unsigned int disabled:1; | ||||||
|  | @@ -467,6 +473,7 @@ struct hostapd_sta_info { | ||||||
|  |   */ | ||||||
|  |  struct hostapd_iface { | ||||||
|  |  	struct hapd_interfaces *interfaces; | ||||||
|  | +	struct hostapd_ucode_iface ucode; | ||||||
|  |  	void *owner; | ||||||
|  |  	char *config_fname; | ||||||
|  |  	struct hostapd_config *conf; | ||||||
|  | @@ -641,6 +648,8 @@ struct hostapd_iface * hostapd_init(stru | ||||||
|  |  struct hostapd_iface * | ||||||
|  |  hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, | ||||||
|  |  			   const char *config_fname, int debug); | ||||||
|  | +int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon); | ||||||
|  | +void hostapd_bss_deinit(struct hostapd_data *hapd); | ||||||
|  |  void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, | ||||||
|  |  			   int reassoc); | ||||||
|  |  void hostapd_interface_deinit_free(struct hostapd_iface *iface); | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.c | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c | ||||||
|  | @@ -217,6 +217,8 @@ int hostapd_reload_config(struct hostapd | ||||||
|  |  	struct hostapd_config *newconf, *oldconf; | ||||||
|  |  	size_t j; | ||||||
|  |   | ||||||
|  | +	hostapd_ucode_reload_bss(hapd); | ||||||
|  | + | ||||||
|  |  	if (iface->config_fname == NULL) { | ||||||
|  |  		/* Only in-memory config in use - assume it has been updated */ | ||||||
|  |  		hostapd_clear_old(iface); | ||||||
|  | @@ -377,6 +379,7 @@ void hostapd_free_hapd_data(struct hosta | ||||||
|  |  	hapd->beacon_set_done = 0; | ||||||
|  |   | ||||||
|  |  	wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); | ||||||
|  | +	hostapd_ucode_free_bss(hapd); | ||||||
|  |  	hostapd_ubus_free_bss(hapd); | ||||||
|  |  	accounting_deinit(hapd); | ||||||
|  |  	hostapd_deinit_wpa(hapd); | ||||||
|  | @@ -534,6 +537,7 @@ void hostapd_cleanup_iface_partial(struc | ||||||
|  |  static void hostapd_cleanup_iface(struct hostapd_iface *iface) | ||||||
|  |  { | ||||||
|  |  	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); | ||||||
|  | +	hostapd_ucode_free_iface(iface); | ||||||
|  |  	eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); | ||||||
|  |  	eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface, | ||||||
|  |  			     NULL); | ||||||
|  | @@ -1108,7 +1112,7 @@ static int db_table_create_radius_attrib | ||||||
|  |   * initialized. Most of the modules that are initialized here will be | ||||||
|  |   * deinitialized in hostapd_cleanup(). | ||||||
|  |   */ | ||||||
|  | -static int hostapd_setup_bss(struct hostapd_data *hapd, int first) | ||||||
|  | +int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool set_beacon) | ||||||
|  |  { | ||||||
|  |  	struct hostapd_bss_config *conf = hapd->conf; | ||||||
|  |  	u8 ssid[SSID_MAX_LEN + 1]; | ||||||
|  | @@ -1405,6 +1409,7 @@ static int hostapd_setup_bss(struct host | ||||||
|  |  		hapd->driver->set_operstate(hapd->drv_priv, 1); | ||||||
|  |   | ||||||
|  |  	hostapd_ubus_add_bss(hapd); | ||||||
|  | +	hostapd_ucode_add_bss(hapd); | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | @@ -2116,7 +2121,7 @@ static int hostapd_setup_interface_compl | ||||||
|  |  		hapd = iface->bss[j]; | ||||||
|  |  		if (j) | ||||||
|  |  			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); | ||||||
|  | -		if (hostapd_setup_bss(hapd, j == 0)) { | ||||||
|  | +		if (hostapd_setup_bss(hapd, j == 0, true)) { | ||||||
|  |  			for (;;) { | ||||||
|  |  				hapd = iface->bss[j]; | ||||||
|  |  				hostapd_bss_deinit_no_free(hapd); | ||||||
|  | @@ -2396,7 +2401,7 @@ hostapd_alloc_bss_data(struct hostapd_if | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -static void hostapd_bss_deinit(struct hostapd_data *hapd) | ||||||
|  | +void hostapd_bss_deinit(struct hostapd_data *hapd) | ||||||
|  |  { | ||||||
|  |  	if (!hapd) | ||||||
|  |  		return; | ||||||
|  | @@ -3013,7 +3018,7 @@ int hostapd_add_iface(struct hapd_interf | ||||||
|  |   | ||||||
|  |  			if (start_ctrl_iface_bss(hapd) < 0 || | ||||||
|  |  			    (hapd_iface->state == HAPD_IFACE_ENABLED && | ||||||
|  | -			     hostapd_setup_bss(hapd, -1))) { | ||||||
|  | +			     hostapd_setup_bss(hapd, -1, true))) { | ||||||
|  |  				hostapd_cleanup(hapd); | ||||||
|  |  				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL; | ||||||
|  |  				hapd_iface->conf->num_bss--; | ||||||
|  | @@ -3165,7 +3170,8 @@ int hostapd_remove_iface(struct hapd_int | ||||||
|  |  		hapd_iface = interfaces->iface[i]; | ||||||
|  |  		if (hapd_iface == NULL) | ||||||
|  |  			return -1; | ||||||
|  | -		if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) { | ||||||
|  | +		if (!os_strcmp(hapd_iface->phy, buf) || | ||||||
|  | +		    !os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) { | ||||||
|  |  			wpa_printf(MSG_INFO, "Remove interface '%s'", buf); | ||||||
|  |  			hapd_iface->driver_ap_teardown = | ||||||
|  |  				!!(hapd_iface->drv_flags & | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/Makefile | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/Makefile | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/Makefile | ||||||
|  | @@ -177,8 +177,20 @@ endif | ||||||
|  |  ifdef CONFIG_UBUS | ||||||
|  |  CFLAGS += -DUBUS_SUPPORT | ||||||
|  |  OBJS += ubus.o | ||||||
|  | +LIBS += -lubus | ||||||
|  | +NEED_ULOOP:=y | ||||||
|  | +endif | ||||||
|  | + | ||||||
|  | +ifdef CONFIG_UCODE | ||||||
|  | +CFLAGS += -DUCODE_SUPPORT | ||||||
|  | +OBJS += ../src/utils/ucode.o | ||||||
|  | +OBJS += ucode.o | ||||||
|  | +NEED_ULOOP:=y | ||||||
|  | +endif | ||||||
|  | + | ||||||
|  | +ifdef NEED_ULOOP | ||||||
|  |  OBJS += ../src/utils/uloop.o | ||||||
|  | -LIBS += -lubox -lubus | ||||||
|  | +LIBS += -lubox | ||||||
|  |  endif | ||||||
|  |   | ||||||
|  |  ifdef CONFIG_CODE_COVERAGE | ||||||
|  | @@ -969,6 +981,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o | ||||||
|  |  ifdef CONFIG_UBUS | ||||||
|  |  OBJS += ../src/ap/ubus.o | ||||||
|  |  endif | ||||||
|  | +ifdef CONFIG_UCODE | ||||||
|  | +OBJS += ../src/ap/ucode.o | ||||||
|  | +endif | ||||||
|  |  endif | ||||||
|  |   | ||||||
|  |  CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.c | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c | ||||||
|  | @@ -1033,6 +1033,7 @@ void wpa_supplicant_set_state(struct wpa | ||||||
|  |  		sme_sched_obss_scan(wpa_s, 0); | ||||||
|  |  	} | ||||||
|  |  	wpa_s->wpa_state = state; | ||||||
|  | +	wpas_ucode_update_state(wpa_s); | ||||||
|  |   | ||||||
|  |  #ifdef CONFIG_BGSCAN | ||||||
|  |  	if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid) | ||||||
|  | @@ -7155,6 +7156,7 @@ struct wpa_supplicant * wpa_supplicant_a | ||||||
|  |  #endif /* CONFIG_P2P */ | ||||||
|  |   | ||||||
|  |  	wpas_ubus_add_bss(wpa_s); | ||||||
|  | +	wpas_ucode_add_bss(wpa_s); | ||||||
|  |   | ||||||
|  |  	return wpa_s; | ||||||
|  |  } | ||||||
|  | @@ -7182,6 +7184,7 @@ int wpa_supplicant_remove_iface(struct w | ||||||
|  |  	struct wpa_supplicant *parent = wpa_s->parent; | ||||||
|  |  #endif /* CONFIG_MESH */ | ||||||
|  |   | ||||||
|  | +	wpas_ucode_free_bss(wpa_s); | ||||||
|  |  	wpas_ubus_free_bss(wpa_s); | ||||||
|  |   | ||||||
|  |  	/* Remove interface from the global list of interfaces */ | ||||||
|  | @@ -7449,6 +7452,7 @@ struct wpa_global * wpa_supplicant_init( | ||||||
|  |   | ||||||
|  |  	eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0, | ||||||
|  |  			       wpas_periodic, global, NULL); | ||||||
|  | +	wpas_ucode_init(global); | ||||||
|  |   | ||||||
|  |  	return global; | ||||||
|  |  } | ||||||
|  | @@ -7487,12 +7491,8 @@ int wpa_supplicant_run(struct wpa_global | ||||||
|  |  	eloop_register_signal_terminate(wpa_supplicant_terminate, global); | ||||||
|  |  	eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); | ||||||
|  |   | ||||||
|  | -	wpas_ubus_add(global); | ||||||
|  | - | ||||||
|  |  	eloop_run(); | ||||||
|  |   | ||||||
|  | -	wpas_ubus_free(global); | ||||||
|  | - | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -7525,6 +7525,8 @@ void wpa_supplicant_deinit(struct wpa_gl | ||||||
|  |   | ||||||
|  |  	wpas_notify_supplicant_deinitialized(global); | ||||||
|  |   | ||||||
|  | +	wpas_ucode_free(); | ||||||
|  | + | ||||||
|  |  	eap_peer_unregister_methods(); | ||||||
|  |  #ifdef CONFIG_AP | ||||||
|  |  	eap_server_unregister_methods(); | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant_i.h | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant_i.h | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant_i.h | ||||||
|  | @@ -20,6 +20,7 @@ | ||||||
|  |  #include "config_ssid.h" | ||||||
|  |  #include "wmm_ac.h" | ||||||
|  |  #include "ubus.h" | ||||||
|  | +#include "ucode.h" | ||||||
|  |   | ||||||
|  |  extern const char *const wpa_supplicant_version; | ||||||
|  |  extern const char *const wpa_supplicant_license; | ||||||
|  | @@ -707,6 +708,7 @@ struct wpa_supplicant { | ||||||
|  |  	unsigned char perm_addr[ETH_ALEN]; | ||||||
|  |  	char ifname[100]; | ||||||
|  |  	struct wpas_ubus_bss ubus; | ||||||
|  | +	struct wpas_ucode_bss ucode; | ||||||
|  |  #ifdef CONFIG_MATCH_IFACE | ||||||
|  |  	int matched; | ||||||
|  |  #endif /* CONFIG_MATCH_IFACE */ | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/hostapd/ctrl_iface.c | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c | ||||||
|  | @@ -5023,6 +5023,7 @@ try_again: | ||||||
|  |  		return -1; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process; | ||||||
|  |  	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  | @@ -5124,6 +5125,7 @@ fail: | ||||||
|  |  	os_free(fname); | ||||||
|  |   | ||||||
|  |  	interface->global_ctrl_sock = s; | ||||||
|  | +	interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process; | ||||||
|  |  	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, | ||||||
|  |  				 interface, NULL); | ||||||
|  |   | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h | ||||||
|  | @@ -3366,6 +3366,25 @@ struct wpa_driver_ops { | ||||||
|  |  			 const char *ifname); | ||||||
|  |   | ||||||
|  |  	/** | ||||||
|  | +	 * if_rename - Rename a virtual interface | ||||||
|  | +	 * @priv: Private driver interface data | ||||||
|  | +	 * @type: Interface type | ||||||
|  | +	 * @ifname: Interface name of the virtual interface to be renamed | ||||||
|  | +	 *	    (NULL when renaming the AP BSS interface) | ||||||
|  | +	 * @new_name: New interface name of the virtual interface | ||||||
|  | +	 * Returns: 0 on success, -1 on failure | ||||||
|  | +	 */ | ||||||
|  | +	int (*if_rename)(void *priv, enum wpa_driver_if_type type, | ||||||
|  | +			 const char *ifname, const char *new_name); | ||||||
|  | + | ||||||
|  | +	/** | ||||||
|  | +	 * set_first_bss - Make a virtual interface the first (primary) bss | ||||||
|  | +	 * @priv: Private driver interface data | ||||||
|  | +	 * Returns: 0 on success, -1 on failure | ||||||
|  | +	 */ | ||||||
|  | +	int (*set_first_bss)(void *priv); | ||||||
|  | + | ||||||
|  | +	/** | ||||||
|  |  	 * set_sta_vlan - Bind a station into a specific interface (AP only) | ||||||
|  |  	 * @priv: Private driver interface data | ||||||
|  |  	 * @ifname: Interface (main or virtual BSS or VLAN) | ||||||
|  | @@ -5842,6 +5861,7 @@ union wpa_event_data { | ||||||
|  |   | ||||||
|  |  	/** | ||||||
|  |  	 * struct ch_switch | ||||||
|  | +	 * @count: Count until channel switch activates | ||||||
|  |  	 * @freq: Frequency of new channel in MHz | ||||||
|  |  	 * @ht_enabled: Whether this is an HT channel | ||||||
|  |  	 * @ch_offset: Secondary channel offset | ||||||
|  | @@ -5850,6 +5870,7 @@ union wpa_event_data { | ||||||
|  |  	 * @cf2: Center frequency 2 | ||||||
|  |  	 */ | ||||||
|  |  	struct ch_switch { | ||||||
|  | +		int count; | ||||||
|  |  		int freq; | ||||||
|  |  		int ht_enabled; | ||||||
|  |  		int ch_offset; | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211_event.c | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c | ||||||
|  | @@ -684,6 +684,7 @@ static void mlme_event_ch_switch(struct | ||||||
|  |  				 struct nlattr *ifindex, struct nlattr *freq, | ||||||
|  |  				 struct nlattr *type, struct nlattr *bw, | ||||||
|  |  				 struct nlattr *cf1, struct nlattr *cf2, | ||||||
|  | +				 struct nlattr *count, | ||||||
|  |  				 int finished) | ||||||
|  |  { | ||||||
|  |  	struct i802_bss *bss; | ||||||
|  | @@ -745,6 +746,8 @@ static void mlme_event_ch_switch(struct | ||||||
|  |  		data.ch_switch.cf1 = nla_get_u32(cf1); | ||||||
|  |  	if (cf2) | ||||||
|  |  		data.ch_switch.cf2 = nla_get_u32(cf2); | ||||||
|  | +	if (count) | ||||||
|  | +		data.ch_switch.count = nla_get_u32(count); | ||||||
|  |   | ||||||
|  |  	if (finished) | ||||||
|  |  		bss->freq = data.ch_switch.freq; | ||||||
|  | @@ -3003,6 +3006,7 @@ static void do_process_drv_event(struct | ||||||
|  |  				     tb[NL80211_ATTR_CHANNEL_WIDTH], | ||||||
|  |  				     tb[NL80211_ATTR_CENTER_FREQ1], | ||||||
|  |  				     tb[NL80211_ATTR_CENTER_FREQ2], | ||||||
|  | +				     tb[NL80211_ATTR_CH_SWITCH_COUNT], | ||||||
|  |  				     0); | ||||||
|  |  		break; | ||||||
|  |  	case NL80211_CMD_CH_SWITCH_NOTIFY: | ||||||
|  | @@ -3013,6 +3017,7 @@ static void do_process_drv_event(struct | ||||||
|  |  				     tb[NL80211_ATTR_CHANNEL_WIDTH], | ||||||
|  |  				     tb[NL80211_ATTR_CENTER_FREQ1], | ||||||
|  |  				     tb[NL80211_ATTR_CENTER_FREQ2], | ||||||
|  | +					 NULL, | ||||||
|  |  				     1); | ||||||
|  |  		break; | ||||||
|  |  	case NL80211_CMD_DISCONNECT: | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/events.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/events.c | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/events.c | ||||||
|  | @@ -4927,6 +4927,7 @@ void supplicant_event(void *ctx, enum wp | ||||||
|  |  		event_to_string(event), event); | ||||||
|  |  #endif /* CONFIG_NO_STDOUT_DEBUG */ | ||||||
|  |   | ||||||
|  | +	wpas_ucode_event(wpa_s, event, data); | ||||||
|  |  	switch (event) { | ||||||
|  |  	case EVENT_AUTH: | ||||||
|  |  #ifdef CONFIG_FST | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_drv_ops.h | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h | ||||||
|  | @@ -367,6 +367,23 @@ static inline int hostapd_drv_stop_ap(st | ||||||
|  |  	return hapd->driver->stop_ap(hapd->drv_priv); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static inline int hostapd_drv_if_rename(struct hostapd_data *hapd, | ||||||
|  | +					enum wpa_driver_if_type type, | ||||||
|  | +					const char *ifname, | ||||||
|  | +					const char *new_name) | ||||||
|  | +{ | ||||||
|  | +	if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv) | ||||||
|  | +		return -1; | ||||||
|  | +	return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd) | ||||||
|  | +{ | ||||||
|  | +	if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv) | ||||||
|  | +		return 0; | ||||||
|  | +	return hapd->driver->set_first_bss(hapd->drv_priv); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static inline int hostapd_drv_channel_info(struct hostapd_data *hapd, | ||||||
|  |  					   struct wpa_channel_info *ci) | ||||||
|  |  { | ||||||
|  | Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c | ||||||
|  | @@ -1249,7 +1249,7 @@ static void wpa_driver_nl80211_event_rtm | ||||||
|  |  		} | ||||||
|  |  		wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)", | ||||||
|  |  			   namebuf, ifname); | ||||||
|  | -		if (os_strcmp(drv->first_bss->ifname, ifname) != 0) { | ||||||
|  | +		if (drv->first_bss->ifindex != ifi->ifi_index) { | ||||||
|  |  			wpa_printf(MSG_DEBUG, | ||||||
|  |  				   "nl80211: Not the main interface (%s) - do not indicate interface down", | ||||||
|  |  				   drv->first_bss->ifname); | ||||||
|  | @@ -1285,7 +1285,7 @@ static void wpa_driver_nl80211_event_rtm | ||||||
|  |  		} | ||||||
|  |  		wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)", | ||||||
|  |  			   namebuf, ifname); | ||||||
|  | -		if (os_strcmp(drv->first_bss->ifname, ifname) != 0) { | ||||||
|  | +		if (drv->first_bss->ifindex != ifi->ifi_index) { | ||||||
|  |  			wpa_printf(MSG_DEBUG, | ||||||
|  |  				   "nl80211: Not the main interface (%s) - do not indicate interface up", | ||||||
|  |  				   drv->first_bss->ifname); | ||||||
|  | @@ -7691,6 +7691,7 @@ static void *i802_init(struct hostapd_da | ||||||
|  |  	char master_ifname[IFNAMSIZ]; | ||||||
|  |  	int ifindex, br_ifindex = 0; | ||||||
|  |  	int br_added = 0; | ||||||
|  | +	int err; | ||||||
|  |   | ||||||
|  |  	bss = wpa_driver_nl80211_drv_init(hapd, params->ifname, | ||||||
|  |  					  params->global_priv, 1, | ||||||
|  | @@ -7751,21 +7752,17 @@ static void *i802_init(struct hostapd_da | ||||||
|  |  		add_ifidx(drv, br_ifindex, drv->ifindex); | ||||||
|  |   | ||||||
|  |  #ifdef CONFIG_LIBNL3_ROUTE | ||||||
|  | -	if (bss->added_if_into_bridge || bss->already_in_bridge) { | ||||||
|  | -		int err; | ||||||
|  | - | ||||||
|  | -		drv->rtnl_sk = nl_socket_alloc(); | ||||||
|  | -		if (drv->rtnl_sk == NULL) { | ||||||
|  | -			wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock"); | ||||||
|  | -			goto failed; | ||||||
|  | -		} | ||||||
|  | +	drv->rtnl_sk = nl_socket_alloc(); | ||||||
|  | +	if (drv->rtnl_sk == NULL) { | ||||||
|  | +		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock"); | ||||||
|  | +		goto failed; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  | -		err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE); | ||||||
|  | -		if (err) { | ||||||
|  | -			wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s", | ||||||
|  | -				   nl_geterror(err)); | ||||||
|  | -			goto failed; | ||||||
|  | -		} | ||||||
|  | +	err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE); | ||||||
|  | +	if (err) { | ||||||
|  | +		wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s", | ||||||
|  | +			   nl_geterror(err)); | ||||||
|  | +		goto failed; | ||||||
|  |  	} | ||||||
|  |  #endif /* CONFIG_LIBNL3_ROUTE */ | ||||||
|  |   | ||||||
|  | @@ -8125,6 +8122,50 @@ static int wpa_driver_nl80211_if_remove( | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int wpa_driver_nl80211_if_rename(struct i802_bss *bss, | ||||||
|  | +					enum wpa_driver_if_type type, | ||||||
|  | +					const char *ifname, const char *new_name) | ||||||
|  | +{ | ||||||
|  | +	struct wpa_driver_nl80211_data *drv = bss->drv; | ||||||
|  | +	struct ifinfomsg ifi = { | ||||||
|  | +		.ifi_family = AF_UNSPEC, | ||||||
|  | +		.ifi_index = bss->ifindex, | ||||||
|  | +	}; | ||||||
|  | +	struct nl_msg *msg; | ||||||
|  | +	int res = -ENOMEM; | ||||||
|  | + | ||||||
|  | +	if (ifname) | ||||||
|  | +		ifi.ifi_index = if_nametoindex(ifname); | ||||||
|  | + | ||||||
|  | +	msg = nlmsg_alloc_simple(RTM_SETLINK, 0); | ||||||
|  | +	if (!msg) | ||||||
|  | +		return res; | ||||||
|  | + | ||||||
|  | +	if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) | ||||||
|  | +		goto out; | ||||||
|  | + | ||||||
|  | +	if (nla_put_string(msg, IFLA_IFNAME, new_name)) | ||||||
|  | +		goto out; | ||||||
|  | + | ||||||
|  | +	res = nl_send_auto_complete(drv->rtnl_sk, msg); | ||||||
|  | +	if (res < 0) | ||||||
|  | +		goto out; | ||||||
|  | + | ||||||
|  | +	res = nl_wait_for_ack(drv->rtnl_sk); | ||||||
|  | +	if (res) { | ||||||
|  | +		wpa_printf(MSG_INFO, | ||||||
|  | +			   "nl80211: Renaming device %s to %s failed: %s", | ||||||
|  | +			   ifname ? ifname : bss->ifname, new_name, nl_geterror(res)); | ||||||
|  | +		goto out; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (type == WPA_IF_AP_BSS && !ifname) | ||||||
|  | +		os_strlcpy(bss->ifname, new_name, sizeof(bss->ifname)); | ||||||
|  | + | ||||||
|  | +out: | ||||||
|  | +	nlmsg_free(msg); | ||||||
|  | +	return res; | ||||||
|  | +} | ||||||
|  |   | ||||||
|  |  static int cookie_handler(struct nl_msg *msg, void *arg) | ||||||
|  |  { | ||||||
|  | @@ -9479,6 +9520,37 @@ static int driver_nl80211_if_remove(void | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +static int driver_nl80211_if_rename(void *priv, enum wpa_driver_if_type type, | ||||||
|  | +				    const char *ifname, const char *new_name) | ||||||
|  | +{ | ||||||
|  | +	struct i802_bss *bss = priv; | ||||||
|  | +	return wpa_driver_nl80211_if_rename(bss, type, ifname, new_name); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +static int driver_nl80211_set_first_bss(void *priv) | ||||||
|  | +{ | ||||||
|  | +	struct i802_bss *bss = priv, *tbss; | ||||||
|  | +	struct wpa_driver_nl80211_data *drv = bss->drv; | ||||||
|  | + | ||||||
|  | +	if (drv->first_bss == bss) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	for (tbss = drv->first_bss; tbss; tbss = tbss->next) { | ||||||
|  | +		if (tbss->next != bss) | ||||||
|  | +			continue; | ||||||
|  | + | ||||||
|  | +		tbss->next = bss->next; | ||||||
|  | +		bss->next = drv->first_bss; | ||||||
|  | +		drv->first_bss = bss; | ||||||
|  | +		drv->ctx = bss->ctx; | ||||||
|  | +		return 0; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return -1; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | + | ||||||
|  |  static int driver_nl80211_send_mlme(void *priv, const u8 *data, | ||||||
|  |  				    size_t data_len, int noack, | ||||||
|  |  				    unsigned int freq, | ||||||
|  | @@ -12183,6 +12255,8 @@ const struct wpa_driver_ops wpa_driver_n | ||||||
|  |  	.set_acl = wpa_driver_nl80211_set_acl, | ||||||
|  |  	.if_add = wpa_driver_nl80211_if_add, | ||||||
|  |  	.if_remove = driver_nl80211_if_remove, | ||||||
|  | +	.if_rename = driver_nl80211_if_rename, | ||||||
|  | +	.set_first_bss = driver_nl80211_set_first_bss, | ||||||
|  |  	.send_mlme = driver_nl80211_send_mlme, | ||||||
|  |  	.get_hw_feature_data = nl80211_get_hw_feature_data, | ||||||
|  |  	.sta_add = wpa_driver_nl80211_sta_add, | ||||||
| @@ -1,220 +0,0 @@ | |||||||
| --- a/hostapd/config_file.c |  | ||||||
| +++ b/hostapd/config_file.c |  | ||||||
| @@ -2453,6 +2453,8 @@ static int hostapd_config_fill(struct ho |  | ||||||
|  		bss->isolate = atoi(pos); |  | ||||||
|  	} else if (os_strcmp(buf, "ap_max_inactivity") == 0) { |  | ||||||
|  		bss->ap_max_inactivity = atoi(pos); |  | ||||||
| +	} else if (os_strcmp(buf, "config_id") == 0) { |  | ||||||
| +		bss->config_id = os_strdup(pos); |  | ||||||
|  	} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) { |  | ||||||
|  		bss->skip_inactivity_poll = atoi(pos); |  | ||||||
|  	} else if (os_strcmp(buf, "country_code") == 0) { |  | ||||||
| @@ -3153,6 +3155,8 @@ static int hostapd_config_fill(struct ho |  | ||||||
|  		} |  | ||||||
|  	} else if (os_strcmp(buf, "acs_exclude_dfs") == 0) { |  | ||||||
|  		conf->acs_exclude_dfs = atoi(pos); |  | ||||||
| +	} else if (os_strcmp(buf, "radio_config_id") == 0) { |  | ||||||
| +			conf->config_id = os_strdup(pos); |  | ||||||
|  	} else if (os_strcmp(buf, "op_class") == 0) { |  | ||||||
|  		conf->op_class = atoi(pos); |  | ||||||
|  	} else if (os_strcmp(buf, "channel") == 0) { |  | ||||||
| --- a/src/ap/ap_config.c |  | ||||||
| +++ b/src/ap/ap_config.c |  | ||||||
| @@ -791,6 +791,7 @@ void hostapd_config_free_bss(struct host |  | ||||||
|  	os_free(conf->radius_req_attr_sqlite); |  | ||||||
|  	os_free(conf->rsn_preauth_interfaces); |  | ||||||
|  	os_free(conf->ctrl_interface); |  | ||||||
| +	os_free(conf->config_id); |  | ||||||
|  	os_free(conf->ca_cert); |  | ||||||
|  	os_free(conf->server_cert); |  | ||||||
|  	os_free(conf->server_cert2); |  | ||||||
| @@ -987,6 +988,7 @@ void hostapd_config_free(struct hostapd_ |  | ||||||
|   |  | ||||||
|  	for (i = 0; i < conf->num_bss; i++) |  | ||||||
|  		hostapd_config_free_bss(conf->bss[i]); |  | ||||||
| +	os_free(conf->config_id); |  | ||||||
|  	os_free(conf->bss); |  | ||||||
|  	os_free(conf->supported_rates); |  | ||||||
|  	os_free(conf->basic_rates); |  | ||||||
| --- a/src/ap/ap_config.h |  | ||||||
| +++ b/src/ap/ap_config.h |  | ||||||
| @@ -279,6 +279,8 @@ struct hostapd_bss_config { |  | ||||||
|  	char vlan_bridge[IFNAMSIZ + 1]; |  | ||||||
|  	char wds_bridge[IFNAMSIZ + 1]; |  | ||||||
|   |  | ||||||
| +	char *config_id; |  | ||||||
| + |  | ||||||
|  	enum hostapd_logger_level logger_syslog_level, logger_stdout_level; |  | ||||||
|   |  | ||||||
|  	unsigned int logger_syslog; /* module bitfield */ |  | ||||||
| @@ -938,6 +940,7 @@ struct spatial_reuse { |  | ||||||
|  struct hostapd_config { |  | ||||||
|  	struct hostapd_bss_config **bss, *last_bss; |  | ||||||
|  	size_t num_bss; |  | ||||||
| +	char *config_id; |  | ||||||
|   |  | ||||||
|  	u16 beacon_int; |  | ||||||
|  	int rts_threshold; |  | ||||||
| --- a/src/ap/hostapd.c |  | ||||||
| +++ b/src/ap/hostapd.c |  | ||||||
| @@ -219,6 +219,10 @@ static int hostapd_iface_conf_changed(st |  | ||||||
|  { |  | ||||||
|  	size_t i; |  | ||||||
|   |  | ||||||
| +	if (newconf->config_id != oldconf->config_id) |  | ||||||
| +		if (strcmp(newconf->config_id, oldconf->config_id)) |  | ||||||
| +			return 1; |  | ||||||
| + |  | ||||||
|  	if (newconf->num_bss != oldconf->num_bss) |  | ||||||
|  		return 1; |  | ||||||
|   |  | ||||||
| @@ -232,7 +236,7 @@ static int hostapd_iface_conf_changed(st |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|   |  | ||||||
| -int hostapd_reload_config(struct hostapd_iface *iface) |  | ||||||
| +int hostapd_reload_config(struct hostapd_iface *iface, int reconf) |  | ||||||
|  { |  | ||||||
|  	struct hapd_interfaces *interfaces = iface->interfaces; |  | ||||||
|  	struct hostapd_data *hapd = iface->bss[0]; |  | ||||||
| @@ -255,13 +259,16 @@ int hostapd_reload_config(struct hostapd |  | ||||||
|  	if (newconf == NULL) |  | ||||||
|  		return -1; |  | ||||||
|   |  | ||||||
| -	hostapd_clear_old(iface); |  | ||||||
| - |  | ||||||
|  	oldconf = hapd->iconf; |  | ||||||
|  	if (hostapd_iface_conf_changed(newconf, oldconf)) { |  | ||||||
|  		char *fname; |  | ||||||
|  		int res; |  | ||||||
|   |  | ||||||
| +		if (reconf) |  | ||||||
| +			return -1; |  | ||||||
| + |  | ||||||
| +		hostapd_clear_old(iface); |  | ||||||
| + |  | ||||||
|  		wpa_printf(MSG_DEBUG, |  | ||||||
|  			   "Configuration changes include interface/BSS modification - force full disable+enable sequence"); |  | ||||||
|  		fname = os_strdup(iface->config_fname); |  | ||||||
| @@ -286,6 +293,24 @@ int hostapd_reload_config(struct hostapd |  | ||||||
|  			wpa_printf(MSG_ERROR, |  | ||||||
|  				   "Failed to enable interface on config reload"); |  | ||||||
|  		return res; |  | ||||||
| +	} else { |  | ||||||
| +		for (j = 0; j < iface->num_bss; j++) { |  | ||||||
| +			hapd = iface->bss[j]; |  | ||||||
| +			if (!hapd->config_id || strcmp(hapd->config_id, newconf->bss[j]->config_id)) { |  | ||||||
| +				hostapd_flush_old_stations(iface->bss[j], |  | ||||||
| +							   WLAN_REASON_PREV_AUTH_NOT_VALID); |  | ||||||
| +#ifdef CONFIG_WEP |  | ||||||
| +				hostapd_broadcast_wep_clear(iface->bss[j]); |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
| +#ifndef CONFIG_NO_RADIUS |  | ||||||
| +				/* TODO: update dynamic data based on changed configuration |  | ||||||
| +				 * items (e.g., open/close sockets, etc.) */ |  | ||||||
| +				radius_client_flush(iface->bss[j]->radius, 0); |  | ||||||
| +#endif /* CONFIG_NO_RADIUS */ |  | ||||||
| +				wpa_printf(MSG_INFO, "bss %zu changed", j); |  | ||||||
| +			} |  | ||||||
| +		} |  | ||||||
|  	} |  | ||||||
|  	iface->conf = newconf; |  | ||||||
|   |  | ||||||
| @@ -302,6 +327,12 @@ int hostapd_reload_config(struct hostapd |  | ||||||
|   |  | ||||||
|  	for (j = 0; j < iface->num_bss; j++) { |  | ||||||
|  		hapd = iface->bss[j]; |  | ||||||
| +		if (hapd->config_id) { |  | ||||||
| +			os_free(hapd->config_id); |  | ||||||
| +			hapd->config_id = NULL; |  | ||||||
| +		} |  | ||||||
| +		if (newconf->bss[j]->config_id) |  | ||||||
| +			hapd->config_id = strdup(newconf->bss[j]->config_id); |  | ||||||
|  		hapd->iconf = newconf; |  | ||||||
|  		hapd->conf = newconf->bss[j]; |  | ||||||
|  		hostapd_reload_bss(hapd); |  | ||||||
| @@ -2397,6 +2428,10 @@ hostapd_alloc_bss_data(struct hostapd_if |  | ||||||
|  	hapd->iconf = conf; |  | ||||||
|  	hapd->conf = bss; |  | ||||||
|  	hapd->iface = hapd_iface; |  | ||||||
| +	if (bss && bss->config_id) |  | ||||||
| +		hapd->config_id = strdup(bss->config_id); |  | ||||||
| +	else |  | ||||||
| +		hapd->config_id = NULL; |  | ||||||
|  	if (conf) |  | ||||||
|  		hapd->driver = conf->driver; |  | ||||||
|  	hapd->ctrl_sock = -1; |  | ||||||
| --- a/src/ap/hostapd.h |  | ||||||
| +++ b/src/ap/hostapd.h |  | ||||||
| @@ -46,7 +46,7 @@ struct mesh_conf; |  | ||||||
|  struct hostapd_iface; |  | ||||||
|   |  | ||||||
|  struct hapd_interfaces { |  | ||||||
| -	int (*reload_config)(struct hostapd_iface *iface); |  | ||||||
| +	int (*reload_config)(struct hostapd_iface *iface, int reconf); |  | ||||||
|  	struct hostapd_config * (*config_read_cb)(const char *config_fname); |  | ||||||
|  	int (*ctrl_iface_init)(struct hostapd_data *hapd); |  | ||||||
|  	void (*ctrl_iface_deinit)(struct hostapd_data *hapd); |  | ||||||
| @@ -156,6 +156,7 @@ struct hostapd_data { |  | ||||||
|  	struct hostapd_config *iconf; |  | ||||||
|  	struct hostapd_bss_config *conf; |  | ||||||
|  	struct hostapd_ubus_bss ubus; |  | ||||||
| +	char *config_id; |  | ||||||
|  	int interface_added; /* virtual interface added for this BSS */ |  | ||||||
|  	unsigned int started:1; |  | ||||||
|  	unsigned int disabled:1; |  | ||||||
| @@ -604,7 +605,7 @@ struct hostapd_iface { |  | ||||||
|  int hostapd_for_each_interface(struct hapd_interfaces *interfaces, |  | ||||||
|  			       int (*cb)(struct hostapd_iface *iface, |  | ||||||
|  					 void *ctx), void *ctx); |  | ||||||
| -int hostapd_reload_config(struct hostapd_iface *iface); |  | ||||||
| +int hostapd_reload_config(struct hostapd_iface *iface, int reconf); |  | ||||||
|  void hostapd_reconfig_encryption(struct hostapd_data *hapd); |  | ||||||
|  struct hostapd_data * |  | ||||||
|  hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, |  | ||||||
| --- a/src/drivers/driver_nl80211.c |  | ||||||
| +++ b/src/drivers/driver_nl80211.c |  | ||||||
| @@ -4820,6 +4820,9 @@ static int wpa_driver_nl80211_set_ap(voi |  | ||||||
|  	if (ret) { |  | ||||||
|  		wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", |  | ||||||
|  			   ret, strerror(-ret)); |  | ||||||
| +		if (!bss->beacon_set) |  | ||||||
| +			ret = 0; |  | ||||||
| +		bss->beacon_set = 0; |  | ||||||
|  	} else { |  | ||||||
|  		bss->beacon_set = 1; |  | ||||||
|  		nl80211_set_bss(bss, params->cts_protect, params->preamble, |  | ||||||
| --- a/hostapd/ctrl_iface.c |  | ||||||
| +++ b/hostapd/ctrl_iface.c |  | ||||||
| @@ -186,7 +186,7 @@ static int hostapd_ctrl_iface_update(str |  | ||||||
|  	iface->interfaces->config_read_cb = hostapd_ctrl_iface_config_read; |  | ||||||
|  	reload_opts = txt; |  | ||||||
|   |  | ||||||
| -	hostapd_reload_config(iface); |  | ||||||
| +	hostapd_reload_config(iface, 0); |  | ||||||
|   |  | ||||||
|  	iface->interfaces->config_read_cb = config_read_cb; |  | ||||||
|  } |  | ||||||
| --- a/hostapd/main.c |  | ||||||
| +++ b/hostapd/main.c |  | ||||||
| @@ -317,7 +317,7 @@ static void handle_term(int sig, void *s |  | ||||||
|   |  | ||||||
|  static int handle_reload_iface(struct hostapd_iface *iface, void *ctx) |  | ||||||
|  { |  | ||||||
| -	if (hostapd_reload_config(iface) < 0) { |  | ||||||
| +	if (hostapd_reload_config(iface, 0) < 0) { |  | ||||||
|  		wpa_printf(MSG_WARNING, "Failed to read new configuration " |  | ||||||
|  			   "file - continuing with old."); |  | ||||||
|  	} |  | ||||||
| --- a/src/ap/wps_hostapd.c |  | ||||||
| +++ b/src/ap/wps_hostapd.c |  | ||||||
| @@ -315,7 +315,7 @@ static void wps_reload_config(void *eloo |  | ||||||
|   |  | ||||||
|  	wpa_printf(MSG_DEBUG, "WPS: Reload configuration data"); |  | ||||||
|  	if (iface->interfaces == NULL || |  | ||||||
| -	    iface->interfaces->reload_config(iface) < 0) { |  | ||||||
| +	    iface->interfaces->reload_config(iface, 1) < 0) { |  | ||||||
|  		wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated " |  | ||||||
|  			   "configuration"); |  | ||||||
|  	} |  | ||||||
							
								
								
									
										33
									
								
								feeds/ipq95xx/hostapd/patches/701-reload_config_inline.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								feeds/ipq95xx/hostapd/patches/701-reload_config_inline.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | --- a/hostapd/config_file.c | ||||||
|  | +++ b/hostapd/config_file.c | ||||||
|  | @@ -4699,7 +4699,12 @@ struct hostapd_config * hostapd_config_r | ||||||
|  |  	int errors = 0; | ||||||
|  |  	size_t i; | ||||||
|  |   | ||||||
|  | -	f = fopen(fname, "r"); | ||||||
|  | +	if (!strncmp(fname, "data:", 5)) { | ||||||
|  | +		f = fmemopen((void *)(fname + 5), strlen(fname + 5), "r"); | ||||||
|  | +		fname = "<inline>"; | ||||||
|  | +	} else { | ||||||
|  | +		f = fopen(fname, "r"); | ||||||
|  | +	} | ||||||
|  |  	if (f == NULL) { | ||||||
|  |  		wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " | ||||||
|  |  			   "for reading.", fname); | ||||||
|  | --- a/wpa_supplicant/config_file.c | ||||||
|  | +++ b/wpa_supplicant/config_file.c | ||||||
|  | @@ -318,8 +318,13 @@ struct wpa_config * wpa_config_read(cons | ||||||
|  |  	while (cred_tail && cred_tail->next) | ||||||
|  |  		cred_tail = cred_tail->next; | ||||||
|  |   | ||||||
|  | +	if (!strncmp(name, "data:", 5)) { | ||||||
|  | +		f = fmemopen((void *)(name + 5), strlen(name + 5), "r"); | ||||||
|  | +		name = "<inline>"; | ||||||
|  | +	} else { | ||||||
|  | +		f = fopen(name, "r"); | ||||||
|  | +	} | ||||||
|  |  	wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); | ||||||
|  | -	f = fopen(name, "r"); | ||||||
|  |  	if (f == NULL) { | ||||||
|  |  		wpa_printf(MSG_ERROR, "Failed to open config file '%s', " | ||||||
|  |  			   "error: %s", name, strerror(errno)); | ||||||
| @@ -30,7 +30,7 @@ | |||||||
|   |   | ||||||
| --- a/hostapd/config_file.c | --- a/hostapd/config_file.c | ||||||
| +++ b/hostapd/config_file.c | +++ b/hostapd/config_file.c | ||||||
| @@ -3366,6 +3366,8 @@ static int hostapd_config_fill(struct ho | @@ -3342,6 +3342,8 @@ static int hostapd_config_fill(struct ho | ||||||
|  #ifndef CONFIG_NO_VLAN |  #ifndef CONFIG_NO_VLAN | ||||||
|  	} else if (os_strcmp(buf, "dynamic_vlan") == 0) { |  	} else if (os_strcmp(buf, "dynamic_vlan") == 0) { | ||||||
|  		bss->ssid.dynamic_vlan = atoi(pos); |  		bss->ssid.dynamic_vlan = atoi(pos); | ||||||
|   | |||||||
| @@ -1,8 +1,6 @@ | |||||||
| Index: hostapd-2021-05-22-b102f19b/hostapd/config_file.c | --- a/hostapd/config_file.c | ||||||
| =================================================================== | +++ b/hostapd/config_file.c | ||||||
| --- hostapd-2021-05-22-b102f19b.orig/hostapd/config_file.c | @@ -2341,6 +2341,8 @@ static int hostapd_config_fill(struct ho | ||||||
| +++ hostapd-2021-05-22-b102f19b/hostapd/config_file.c |  | ||||||
| @@ -2357,6 +2357,8 @@ static int hostapd_config_fill(struct ho |  | ||||||
|  			   sizeof(conf->bss[0]->iface)); |  			   sizeof(conf->bss[0]->iface)); | ||||||
|  	} else if (os_strcmp(buf, "bridge") == 0) { |  	} else if (os_strcmp(buf, "bridge") == 0) { | ||||||
|  		os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); |  		os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); | ||||||
| @@ -11,10 +9,8 @@ Index: hostapd-2021-05-22-b102f19b/hostapd/config_file.c | |||||||
|  	} else if (os_strcmp(buf, "vlan_bridge") == 0) { |  	} else if (os_strcmp(buf, "vlan_bridge") == 0) { | ||||||
|  		os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge)); |  		os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge)); | ||||||
|  	} else if (os_strcmp(buf, "wds_bridge") == 0) { |  	} else if (os_strcmp(buf, "wds_bridge") == 0) { | ||||||
| Index: hostapd-2021-05-22-b102f19b/src/ap/ap_drv_ops.c | --- a/src/ap/ap_drv_ops.c | ||||||
| =================================================================== | +++ b/src/ap/ap_drv_ops.c | ||||||
| --- hostapd-2021-05-22-b102f19b.orig/src/ap/ap_drv_ops.c |  | ||||||
| +++ hostapd-2021-05-22-b102f19b/src/ap/ap_drv_ops.c |  | ||||||
| @@ -340,8 +340,6 @@ int hostapd_set_wds_sta(struct hostapd_d | @@ -340,8 +340,6 @@ int hostapd_set_wds_sta(struct hostapd_d | ||||||
|  		return -1; |  		return -1; | ||||||
|  	if (hapd->conf->wds_bridge[0]) |  	if (hapd->conf->wds_bridge[0]) | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/hostapd/config_file.c | --- a/hostapd/config_file.c | ||||||
| +++ b/hostapd/config_file.c | +++ b/hostapd/config_file.c | ||||||
| @@ -2873,6 +2873,14 @@ static int hostapd_config_fill(struct ho | @@ -2853,6 +2853,14 @@ static int hostapd_config_fill(struct ho | ||||||
|  				   line, bss->max_num_sta, MAX_STA_COUNT); |  				   line, bss->max_num_sta, MAX_STA_COUNT); | ||||||
|  			return 1; |  			return 1; | ||||||
|  		} |  		} | ||||||
| @@ -17,7 +17,7 @@ | |||||||
|  	} else if (os_strcmp(buf, "extended_key_id") == 0) { |  	} else if (os_strcmp(buf, "extended_key_id") == 0) { | ||||||
| --- a/src/ap/hostapd.h | --- a/src/ap/hostapd.h | ||||||
| +++ b/src/ap/hostapd.h | +++ b/src/ap/hostapd.h | ||||||
| @@ -648,6 +648,7 @@ void hostapd_cleanup_cs_params(struct ho | @@ -672,6 +672,7 @@ void hostapd_cleanup_cs_params(struct ho | ||||||
|  void hostapd_periodic_iface(struct hostapd_iface *iface); |  void hostapd_periodic_iface(struct hostapd_iface *iface); | ||||||
|  int hostapd_owe_trans_get_info(struct hostapd_data *hapd); |  int hostapd_owe_trans_get_info(struct hostapd_data *hapd); | ||||||
|  void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); |  void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); | ||||||
| @@ -27,7 +27,7 @@ | |||||||
|  int hostapd_register_probereq_cb(struct hostapd_data *hapd, |  int hostapd_register_probereq_cb(struct hostapd_data *hapd, | ||||||
| --- a/src/ap/hostapd.c | --- a/src/ap/hostapd.c | ||||||
| +++ b/src/ap/hostapd.c | +++ b/src/ap/hostapd.c | ||||||
| @@ -236,6 +236,30 @@ static int hostapd_iface_conf_changed(st | @@ -209,6 +209,30 @@ static int hostapd_iface_conf_changed(st | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -55,7 +55,7 @@ | |||||||
| +	return 0; | +	return 0; | ||||||
| +} | +} | ||||||
| + | + | ||||||
|  int hostapd_reload_config(struct hostapd_iface *iface, int reconf) |  int hostapd_reload_config(struct hostapd_iface *iface) | ||||||
|  { |  { | ||||||
|  	struct hapd_interfaces *interfaces = iface->interfaces; |  	struct hapd_interfaces *interfaces = iface->interfaces; | ||||||
| --- a/src/ap/beacon.c | --- a/src/ap/beacon.c | ||||||
| @@ -71,7 +71,7 @@ | |||||||
|  			   " since no room for additional STA", |  			   " since no room for additional STA", | ||||||
| --- a/src/ap/ap_config.h | --- a/src/ap/ap_config.h | ||||||
| +++ b/src/ap/ap_config.h | +++ b/src/ap/ap_config.h | ||||||
| @@ -976,6 +976,8 @@ struct hostapd_config { | @@ -959,6 +959,8 @@ struct hostapd_config { | ||||||
|  	unsigned int track_sta_max_num; |  	unsigned int track_sta_max_num; | ||||||
|  	unsigned int track_sta_max_age; |  	unsigned int track_sta_max_age; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/hostapd/config_file.c | --- a/hostapd/config_file.c | ||||||
| +++ b/hostapd/config_file.c | +++ b/hostapd/config_file.c | ||||||
| @@ -3031,6 +3031,8 @@ static int hostapd_config_fill(struct ho | @@ -3011,6 +3011,8 @@ static int hostapd_config_fill(struct ho | ||||||
|  		wpa_printf(MSG_INFO, |  		wpa_printf(MSG_INFO, | ||||||
|  			   "Line %d: Obsolete peerkey parameter ignored", line); |  			   "Line %d: Obsolete peerkey parameter ignored", line); | ||||||
|  #ifdef CONFIG_IEEE80211R_AP |  #ifdef CONFIG_IEEE80211R_AP | ||||||
| @@ -11,7 +11,7 @@ | |||||||
|  		    hexstr2bin(pos, bss->mobility_domain, |  		    hexstr2bin(pos, bss->mobility_domain, | ||||||
| --- a/src/ap/ap_config.h | --- a/src/ap/ap_config.h | ||||||
| +++ b/src/ap/ap_config.h | +++ b/src/ap/ap_config.h | ||||||
| @@ -277,6 +277,7 @@ struct airtime_sta_weight { | @@ -275,6 +275,7 @@ struct airtime_sta_weight { | ||||||
|  struct hostapd_bss_config { |  struct hostapd_bss_config { | ||||||
|  	char iface[IFNAMSIZ + 1]; |  	char iface[IFNAMSIZ + 1]; | ||||||
|  	char bridge[IFNAMSIZ + 1]; |  	char bridge[IFNAMSIZ + 1]; | ||||||
|   | |||||||
| @@ -1,8 +1,6 @@ | |||||||
| Index: hostapd-2021-05-22-b102f19b/src/ap/ap_config.h | --- a/src/ap/ap_config.h | ||||||
| =================================================================== | +++ b/src/ap/ap_config.h | ||||||
| --- hostapd-2021-05-22-b102f19b.orig/src/ap/ap_config.h | @@ -276,6 +276,7 @@ struct hostapd_bss_config { | ||||||
| +++ hostapd-2021-05-22-b102f19b/src/ap/ap_config.h |  | ||||||
| @@ -278,6 +278,7 @@ struct hostapd_bss_config { |  | ||||||
|  	char iface[IFNAMSIZ + 1]; |  	char iface[IFNAMSIZ + 1]; | ||||||
|  	char bridge[IFNAMSIZ + 1]; |  	char bridge[IFNAMSIZ + 1]; | ||||||
|  	char ft_iface[IFNAMSIZ + 1]; |  	char ft_iface[IFNAMSIZ + 1]; | ||||||
| @@ -10,11 +8,9 @@ Index: hostapd-2021-05-22-b102f19b/src/ap/ap_config.h | |||||||
|  	char vlan_bridge[IFNAMSIZ + 1]; |  	char vlan_bridge[IFNAMSIZ + 1]; | ||||||
|  	char wds_bridge[IFNAMSIZ + 1]; |  	char wds_bridge[IFNAMSIZ + 1]; | ||||||
|   |   | ||||||
| Index: hostapd-2021-05-22-b102f19b/src/ap/x_snoop.c | --- a/src/ap/x_snoop.c | ||||||
| =================================================================== | +++ b/src/ap/x_snoop.c | ||||||
| --- hostapd-2021-05-22-b102f19b.orig/src/ap/x_snoop.c | @@ -31,28 +31,31 @@ int x_snoop_init(struct hostapd_data *ha | ||||||
| +++ hostapd-2021-05-22-b102f19b/src/ap/x_snoop.c |  | ||||||
| @@ -31,14 +31,16 @@ int x_snoop_init(struct hostapd_data *ha |  | ||||||
|  		return -1; |  		return -1; | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
| @@ -33,13 +29,20 @@ Index: hostapd-2021-05-22-b102f19b/src/ap/x_snoop.c | |||||||
|  		wpa_printf(MSG_DEBUG, |  		wpa_printf(MSG_DEBUG, | ||||||
|  			   "x_snoop: Failed to enable proxyarp on the bridge port"); |  			   "x_snoop: Failed to enable proxyarp on the bridge port"); | ||||||
|  		return -1; |  		return -1; | ||||||
| @@ -52,7 +54,8 @@ int x_snoop_init(struct hostapd_data *ha |  	} | ||||||
|  |   | ||||||
|  |  	if (hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, | ||||||
|  | -					 1)) { | ||||||
|  | +					 conf->snoop_iface[0] ? conf->snoop_iface : NULL, 1)) { | ||||||
|  |  		wpa_printf(MSG_DEBUG, | ||||||
|  |  			   "x_snoop: Failed to enable accepting gratuitous ARP on the bridge"); | ||||||
|  |  		return -1; | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
|  #ifdef CONFIG_IPV6 |  #ifdef CONFIG_IPV6 | ||||||
| -	if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) { | -	if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) { | ||||||
| +	if (!conf->snoop_iface[0] && | +	if (!conf->snoop_iface[0] && | ||||||
| +	    hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) { | +	    hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, NULL, 1)) { | ||||||
|  		wpa_printf(MSG_DEBUG, |  		wpa_printf(MSG_DEBUG, | ||||||
|  			   "x_snoop: Failed to enable multicast snooping on the bridge"); |  			   "x_snoop: Failed to enable multicast snooping on the bridge"); | ||||||
|  		return -1; |  		return -1; | ||||||
| @@ -48,20 +51,30 @@ Index: hostapd-2021-05-22-b102f19b/src/ap/x_snoop.c | |||||||
|  	struct hostapd_bss_config *conf = hapd->conf; |  	struct hostapd_bss_config *conf = hapd->conf; | ||||||
|  	struct l2_packet_data *l2; |  	struct l2_packet_data *l2; | ||||||
| +	const char *ifname = conf->bridge; | +	const char *ifname = conf->bridge; | ||||||
|   | + | ||||||
| -	l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1); |  | ||||||
| +	if (conf->snoop_iface[0]) | +	if (conf->snoop_iface[0]) | ||||||
| +		ifname = conf->snoop_iface; | +		ifname = conf->snoop_iface; | ||||||
| + |   | ||||||
|  | -	l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1); | ||||||
| +	l2 = l2_packet_init(ifname, NULL, ETH_P_ALL, handler, hapd, 1); | +	l2 = l2_packet_init(ifname, NULL, ETH_P_ALL, handler, hapd, 1); | ||||||
|  	if (l2 == NULL) { |  	if (l2 == NULL) { | ||||||
|  		wpa_printf(MSG_DEBUG, |  		wpa_printf(MSG_DEBUG, | ||||||
|  			   "x_snoop: Failed to initialize L2 packet processing %s", |  			   "x_snoop: Failed to initialize L2 packet processing %s", | ||||||
| Index: hostapd-2021-05-22-b102f19b/hostapd/config_file.c | @@ -125,7 +132,10 @@ void x_snoop_mcast_to_ucast_convert_send | ||||||
| =================================================================== |   | ||||||
| --- hostapd-2021-05-22-b102f19b.orig/hostapd/config_file.c |  void x_snoop_deinit(struct hostapd_data *hapd) | ||||||
| +++ hostapd-2021-05-22-b102f19b/hostapd/config_file.c |  { | ||||||
| @@ -2359,6 +2359,8 @@ static int hostapd_config_fill(struct ho | -	hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0); | ||||||
|  | +	struct hostapd_bss_config *conf = hapd->conf; | ||||||
|  | + | ||||||
|  | +	hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, | ||||||
|  | +				     conf->snoop_iface[0] ? conf->snoop_iface : NULL, 0); | ||||||
|  |  	hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0); | ||||||
|  |  	hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0); | ||||||
|  |  } | ||||||
|  | --- a/hostapd/config_file.c | ||||||
|  | +++ b/hostapd/config_file.c | ||||||
|  | @@ -2343,6 +2343,8 @@ static int hostapd_config_fill(struct ho | ||||||
|  		os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); |  		os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); | ||||||
|  		if (!bss->wds_bridge[0]) |  		if (!bss->wds_bridge[0]) | ||||||
|  			os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge)); |  			os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge)); | ||||||
| @@ -70,3 +83,55 @@ Index: hostapd-2021-05-22-b102f19b/hostapd/config_file.c | |||||||
|  	} else if (os_strcmp(buf, "vlan_bridge") == 0) { |  	} else if (os_strcmp(buf, "vlan_bridge") == 0) { | ||||||
|  		os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge)); |  		os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge)); | ||||||
|  	} else if (os_strcmp(buf, "wds_bridge") == 0) { |  	} else if (os_strcmp(buf, "wds_bridge") == 0) { | ||||||
|  | --- a/src/ap/ap_drv_ops.h | ||||||
|  | +++ b/src/ap/ap_drv_ops.h | ||||||
|  | @@ -340,12 +340,12 @@ static inline int hostapd_drv_br_port_se | ||||||
|  |   | ||||||
|  |  static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd, | ||||||
|  |  					       enum drv_br_net_param param, | ||||||
|  | -					       unsigned int val) | ||||||
|  | +					       const char *ifname, unsigned int val) | ||||||
|  |  { | ||||||
|  |  	if (hapd->driver == NULL || hapd->drv_priv == NULL || | ||||||
|  |  	    hapd->driver->br_set_net_param == NULL) | ||||||
|  |  		return -1; | ||||||
|  | -	return hapd->driver->br_set_net_param(hapd->drv_priv, param, val); | ||||||
|  | +	return hapd->driver->br_set_net_param(hapd->drv_priv, param, ifname, val); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd, | ||||||
|  | --- a/src/drivers/driver.h | ||||||
|  | +++ b/src/drivers/driver.h | ||||||
|  | @@ -3756,7 +3756,7 @@ struct wpa_driver_ops { | ||||||
|  |  	 * Returns: 0 on success, negative (<0) on failure | ||||||
|  |  	 */ | ||||||
|  |  	int (*br_set_net_param)(void *priv, enum drv_br_net_param param, | ||||||
|  | -				unsigned int val); | ||||||
|  | +				const char *ifname, unsigned int val); | ||||||
|  |   | ||||||
|  |  	/** | ||||||
|  |  	 * get_wowlan - Get wake-on-wireless status | ||||||
|  | --- a/src/drivers/driver_nl80211.c | ||||||
|  | +++ b/src/drivers/driver_nl80211.c | ||||||
|  | @@ -10825,7 +10825,7 @@ static const char * drv_br_net_param_str | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param, | ||||||
|  | -				       unsigned int val) | ||||||
|  | +				       const char *ifname, unsigned int val) | ||||||
|  |  { | ||||||
|  |  	struct i802_bss *bss = priv; | ||||||
|  |  	char path[128]; | ||||||
|  | @@ -10851,8 +10851,11 @@ static int wpa_driver_br_set_net_param(v | ||||||
|  |  			return -EINVAL; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (!ifname) | ||||||
|  | +		ifname = bss->brname; | ||||||
|  | + | ||||||
|  |  	os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s", | ||||||
|  | -		    ip_version, bss->brname, param_txt); | ||||||
|  | +		    ip_version, ifname, param_txt); | ||||||
|  |   | ||||||
|  |  set_val: | ||||||
|  |  	if (linux_write_system_file(path, val)) | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_1x.c | --- a/src/ap/ieee802_1x.c | ||||||
| =================================================================== | +++ b/src/ap/ieee802_1x.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/ieee802_1x.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/ieee802_1x.c |  | ||||||
| @@ -1904,6 +1904,25 @@ static int ieee802_1x_update_vlan(struct | @@ -1904,6 +1904,25 @@ static int ieee802_1x_update_vlan(struct | ||||||
|  } |  } | ||||||
|  #endif /* CONFIG_NO_VLAN */ |  #endif /* CONFIG_NO_VLAN */ | ||||||
| @@ -36,11 +34,9 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_1x.c | |||||||
|  		break; |  		break; | ||||||
|  	case RADIUS_CODE_ACCESS_REJECT: |  	case RADIUS_CODE_ACCESS_REJECT: | ||||||
|  		sm->eap_if->aaaFail = true; |  		sm->eap_if->aaaFail = true; | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h | --- a/src/ap/sta_info.h | ||||||
| =================================================================== | +++ b/src/ap/sta_info.h | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.h | @@ -116,6 +116,7 @@ struct sta_info { | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.h |  | ||||||
| @@ -117,6 +117,7 @@ struct sta_info { |  | ||||||
|  	u8 supported_rates[WLAN_SUPP_RATES_MAX]; |  	u8 supported_rates[WLAN_SUPP_RATES_MAX]; | ||||||
|  	int supported_rates_len; |  	int supported_rates_len; | ||||||
|  	u8 qosinfo; /* Valid when WLAN_STA_WMM is set */ |  	u8 qosinfo; /* Valid when WLAN_STA_WMM is set */ | ||||||
| @@ -48,10 +44,8 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h | |||||||
|   |   | ||||||
|  #ifdef CONFIG_MESH |  #ifdef CONFIG_MESH | ||||||
|  	enum mesh_plink_state plink_state; |  	enum mesh_plink_state plink_state; | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/radius/radius.c | --- a/src/radius/radius.c | ||||||
| =================================================================== | +++ b/src/radius/radius.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/radius/radius.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/radius/radius.c |  | ||||||
| @@ -1182,6 +1182,35 @@ radius_msg_get_cisco_keys(struct radius_ | @@ -1182,6 +1182,35 @@ radius_msg_get_cisco_keys(struct radius_ | ||||||
|  	return keys; |  	return keys; | ||||||
|  } |  } | ||||||
| @@ -88,10 +82,8 @@ Index: hostapd-2021-02-20-59e9794c/src/radius/radius.c | |||||||
|   |   | ||||||
|  int radius_msg_add_mppe_keys(struct radius_msg *msg, |  int radius_msg_add_mppe_keys(struct radius_msg *msg, | ||||||
|  			     const u8 *req_authenticator, |  			     const u8 *req_authenticator, | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/radius/radius.h | --- a/src/radius/radius.h | ||||||
| =================================================================== | +++ b/src/radius/radius.h | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/radius/radius.h |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/radius/radius.h |  | ||||||
| @@ -205,6 +205,10 @@ enum { | @@ -205,6 +205,10 @@ enum { | ||||||
|  	RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10, |  	RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10, | ||||||
|  }; |  }; | ||||||
| @@ -111,16 +103,3 @@ Index: hostapd-2021-02-20-59e9794c/src/radius/radius.h | |||||||
|  int radius_msg_add_mppe_keys(struct radius_msg *msg, |  int radius_msg_add_mppe_keys(struct radius_msg *msg, | ||||||
|  			     const u8 *req_authenticator, |  			     const u8 *req_authenticator, | ||||||
|  			     const u8 *secret, size_t secret_len, |  			     const u8 *secret, size_t secret_len, | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.c |  | ||||||
| @@ -1292,7 +1292,7 @@ void ap_sta_set_authorized(struct hostap |  | ||||||
|  			    MAC2STR(sta->addr), MAC2STR(dev_addr)); |  | ||||||
|  	else |  | ||||||
|  #endif /* CONFIG_P2P */ |  | ||||||
| -		os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); |  | ||||||
| +		os_snprintf(buf, sizeof(buf), MACSTR " %d %d", MAC2STR(sta->addr), sta->bandwidth[0] / 1000000, sta->bandwidth[1] / 1000000); |  | ||||||
|   |  | ||||||
|  	if (hapd->sta_authorized_cb) |  | ||||||
|  		hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, |  | ||||||
|   | |||||||
| @@ -1,8 +1,6 @@ | |||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/acs.c | --- a/src/ap/acs.c | ||||||
| =================================================================== | +++ b/src/ap/acs.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/acs.c | @@ -668,6 +668,10 @@ acs_find_ideal_chan_mode(struct hostapd_ | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/acs.c |  | ||||||
| @@ -672,6 +672,10 @@ acs_find_ideal_chan_mode(struct hostapd_ |  | ||||||
|  			continue; |  			continue; | ||||||
|  		} |  		} | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/src/ap/ap_config.h | --- a/src/ap/ap_config.h | ||||||
| +++ b/src/ap/ap_config.h | +++ b/src/ap/ap_config.h | ||||||
| @@ -311,6 +311,7 @@ struct hostapd_bss_config { | @@ -301,6 +301,7 @@ struct hostapd_bss_config { | ||||||
|  	unsigned int eap_sim_db_timeout; |  	unsigned int eap_sim_db_timeout; | ||||||
|  	int eap_server_erp; /* Whether ERP is enabled on internal EAP server */ |  	int eap_server_erp; /* Whether ERP is enabled on internal EAP server */ | ||||||
|  	struct hostapd_ip_addr own_ip_addr; |  	struct hostapd_ip_addr own_ip_addr; | ||||||
| @@ -10,7 +10,7 @@ | |||||||
|  	int acct_interim_interval; |  	int acct_interim_interval; | ||||||
| --- a/src/radius/radius_client.c | --- a/src/radius/radius_client.c | ||||||
| +++ b/src/radius/radius_client.c | +++ b/src/radius/radius_client.c | ||||||
| @@ -163,6 +163,8 @@ struct radius_client_data { | @@ -162,6 +162,8 @@ struct radius_client_data { | ||||||
|  	 */ |  	 */ | ||||||
|  	void *ctx; |  	void *ctx; | ||||||
|   |   | ||||||
| @@ -19,7 +19,7 @@ | |||||||
|  	/** |  	/** | ||||||
|  	 * conf - RADIUS client configuration (list of RADIUS servers to use) |  	 * conf - RADIUS client configuration (list of RADIUS servers to use) | ||||||
|  	 */ |  	 */ | ||||||
| @@ -720,6 +722,30 @@ static void radius_client_list_add(struc | @@ -719,6 +721,30 @@ static void radius_client_list_add(struc | ||||||
|   |   | ||||||
|   |   | ||||||
|  /** |  /** | ||||||
| @@ -50,7 +50,7 @@ | |||||||
|   * radius_client_send - Send a RADIUS request |   * radius_client_send - Send a RADIUS request | ||||||
|   * @radius: RADIUS client context from radius_client_init() |   * @radius: RADIUS client context from radius_client_init() | ||||||
|   * @msg: RADIUS message to be sent |   * @msg: RADIUS message to be sent | ||||||
| @@ -1238,6 +1264,10 @@ radius_change_server(struct radius_clien | @@ -1219,6 +1245,10 @@ radius_change_server(struct radius_clien | ||||||
|  			wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", |  			wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", | ||||||
|  				   inet_ntoa(claddr.sin_addr), |  				   inet_ntoa(claddr.sin_addr), | ||||||
|  				   ntohs(claddr.sin_port)); |  				   ntohs(claddr.sin_port)); | ||||||
| @@ -61,7 +61,7 @@ | |||||||
|  		} |  		} | ||||||
|  		break; |  		break; | ||||||
|  #ifdef CONFIG_IPV6 |  #ifdef CONFIG_IPV6 | ||||||
| @@ -1249,6 +1279,10 @@ radius_change_server(struct radius_clien | @@ -1230,6 +1260,10 @@ radius_change_server(struct radius_clien | ||||||
|  				   inet_ntop(AF_INET6, &claddr6.sin6_addr, |  				   inet_ntop(AF_INET6, &claddr6.sin6_addr, | ||||||
|  					     abuf, sizeof(abuf)), |  					     abuf, sizeof(abuf)), | ||||||
|  				   ntohs(claddr6.sin6_port)); |  				   ntohs(claddr6.sin6_port)); | ||||||
| @@ -74,7 +74,7 @@ | |||||||
|  	} |  	} | ||||||
| --- a/src/radius/radius_client.h | --- a/src/radius/radius_client.h | ||||||
| +++ b/src/radius/radius_client.h | +++ b/src/radius/radius_client.h | ||||||
| @@ -249,6 +249,8 @@ int radius_client_register(struct radius | @@ -244,6 +244,8 @@ int radius_client_register(struct radius | ||||||
|  void radius_client_set_interim_error_cb(struct radius_client_data *radius, |  void radius_client_set_interim_error_cb(struct radius_client_data *radius, | ||||||
|  					void (*cb)(const u8 *addr, void *ctx), |  					void (*cb)(const u8 *addr, void *ctx), | ||||||
|  					void *ctx); |  					void *ctx); | ||||||
| @@ -98,7 +98,7 @@ | |||||||
|  	    hapd->conf->own_ip_addr.af == AF_INET && |  	    hapd->conf->own_ip_addr.af == AF_INET && | ||||||
| --- a/hostapd/config_file.c | --- a/hostapd/config_file.c | ||||||
| +++ b/hostapd/config_file.c | +++ b/hostapd/config_file.c | ||||||
| @@ -2681,6 +2681,8 @@ static int hostapd_config_fill(struct ho | @@ -2696,6 +2696,8 @@ static int hostapd_config_fill(struct ho | ||||||
|  	} else if (os_strcmp(buf, "iapp_interface") == 0) { |  	} else if (os_strcmp(buf, "iapp_interface") == 0) { | ||||||
|  		wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used"); |  		wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used"); | ||||||
|  #endif /* CONFIG_IAPP */ |  #endif /* CONFIG_IAPP */ | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c | --- a/src/ap/hostapd.c | ||||||
| =================================================================== | +++ b/src/ap/hostapd.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.c |  | ||||||
| @@ -11,6 +11,8 @@ | @@ -11,6 +11,8 @@ | ||||||
|  #include <sqlite3.h> |  #include <sqlite3.h> | ||||||
|  #endif /* CONFIG_SQLITE */ |  #endif /* CONFIG_SQLITE */ | ||||||
| @@ -10,8 +8,8 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c | |||||||
| + | + | ||||||
|  #include "utils/common.h" |  #include "utils/common.h" | ||||||
|  #include "utils/eloop.h" |  #include "utils/eloop.h" | ||||||
|  #include "common/ieee802_11_defs.h" |  #include "utils/crc32.h" | ||||||
| @@ -1316,6 +1318,22 @@ static int hostapd_setup_bss(struct host | @@ -1198,6 +1200,22 @@ int hostapd_setup_bss(struct hostapd_dat | ||||||
|  			os_memcpy(hapd->own_addr, if_addr, ETH_ALEN); |  			os_memcpy(hapd->own_addr, if_addr, ETH_ALEN); | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
| @@ -32,5 +30,5 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c | |||||||
| +	} | +	} | ||||||
| + | + | ||||||
|  	if (conf->wmm_enabled < 0) |  	if (conf->wmm_enabled < 0) | ||||||
|  		conf->wmm_enabled = hapd->iconf->ieee80211n | hapd->iconf->ieee80211ax; |  		conf->wmm_enabled = hapd->iconf->ieee80211n; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c | --- a/src/ap/sta_info.c | ||||||
| =================================================================== | +++ b/src/ap/sta_info.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.c |  | ||||||
| @@ -717,7 +717,7 @@ struct sta_info * ap_sta_add(struct host | @@ -717,7 +717,7 @@ struct sta_info * ap_sta_add(struct host | ||||||
|  		return sta; |  		return sta; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,8 +1,6 @@ | |||||||
| diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c |  | ||||||
| index ad2aebf..355b4a8 100644 |  | ||||||
| --- a/src/common/hw_features_common.c | --- a/src/common/hw_features_common.c | ||||||
| +++ b/src/common/hw_features_common.c | +++ b/src/common/hw_features_common.c | ||||||
| @@ -615,9 +615,21 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, | @@ -609,9 +609,21 @@ int hostapd_set_freq_params(struct hosta | ||||||
|  			    center_segment0 == channel - 6) |  			    center_segment0 == channel - 6) | ||||||
|  				data->center_freq1 = 5000 + center_segment0 * 5; |  				data->center_freq1 = 5000 + center_segment0 * 5; | ||||||
|  			else { |  			else { | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| Index: hostapd-2021-02-20-59e9794c/src/radius/radius_das.c | --- a/src/radius/radius_das.c | ||||||
| =================================================================== | +++ b/src/radius/radius_das.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/radius/radius_das.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/radius/radius_das.c |  | ||||||
| @@ -48,6 +48,8 @@ static struct radius_msg * radius_das_di | @@ -48,6 +48,8 @@ static struct radius_msg * radius_das_di | ||||||
|  		RADIUS_ATTR_EVENT_TIMESTAMP, |  		RADIUS_ATTR_EVENT_TIMESTAMP, | ||||||
|  		RADIUS_ATTR_MESSAGE_AUTHENTICATOR, |  		RADIUS_ATTR_MESSAGE_AUTHENTICATOR, | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  	unsigned int time_window; |  	unsigned int time_window; | ||||||
| --- a/src/ap/hostapd.c | --- a/src/ap/hostapd.c | ||||||
| +++ b/src/ap/hostapd.c | +++ b/src/ap/hostapd.c | ||||||
| @@ -1367,6 +1367,7 @@ static int hostapd_setup_bss(struct host | @@ -1325,6 +1325,7 @@ int hostapd_setup_bss(struct hostapd_dat | ||||||
|  		struct radius_das_conf das_conf; |  		struct radius_das_conf das_conf; | ||||||
|  		os_memset(&das_conf, 0, sizeof(das_conf)); |  		os_memset(&das_conf, 0, sizeof(das_conf)); | ||||||
|  		das_conf.port = conf->radius_das_port; |  		das_conf.port = conf->radius_das_port; | ||||||
| @@ -48,7 +48,7 @@ | |||||||
|  	size_t shared_secret_len; |  	size_t shared_secret_len; | ||||||
|  	struct hostapd_ip_addr client_addr; |  	struct hostapd_ip_addr client_addr; | ||||||
|  	unsigned int time_window; |  	unsigned int time_window; | ||||||
| @@ -378,56 +391,17 @@ fail: | @@ -379,56 +392,17 @@ fail: | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -111,7 +111,7 @@ | |||||||
|   |   | ||||||
|  	if (radius_msg_verify_das_req(msg, das->shared_secret, |  	if (radius_msg_verify_das_req(msg, das->shared_secret, | ||||||
|  				       das->shared_secret_len, |  				       das->shared_secret_len, | ||||||
| @@ -494,9 +468,8 @@ static void radius_das_receive(int sock, | @@ -495,9 +469,8 @@ static void radius_das_receive(int sock, | ||||||
|  			radius_msg_dump(reply); |  			radius_msg_dump(reply); | ||||||
|   |   | ||||||
|  		rbuf = radius_msg_get_buf(reply); |  		rbuf = radius_msg_get_buf(reply); | ||||||
| @@ -123,7 +123,11 @@ | |||||||
|  		if (res < 0) { |  		if (res < 0) { | ||||||
|  			wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s", |  			wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s", | ||||||
|  				   abuf, from_port, strerror(errno)); |  				   abuf, from_port, strerror(errno)); | ||||||
| @@ -508,6 +481,72 @@ fail: | @@ -505,10 +478,76 @@ static void radius_das_receive(int sock, | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  fail: | ||||||
|  | -	radius_msg_free(msg); | ||||||
|  	radius_msg_free(reply); |  	radius_msg_free(reply); | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -189,6 +193,7 @@ | |||||||
| +				       fromlen, abuf, from_port); | +				       fromlen, abuf, from_port); | ||||||
| +	} | +	} | ||||||
| + | + | ||||||
|  | +	radius_msg_free(msg); | ||||||
| +	if (!found) | +	if (!found) | ||||||
| +		wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client"); | +		wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client"); | ||||||
| +} | +} | ||||||
| @@ -196,7 +201,7 @@ | |||||||
|   |   | ||||||
|  static int radius_das_open_socket(int port) |  static int radius_das_open_socket(int port) | ||||||
|  { |  { | ||||||
| @@ -533,6 +572,49 @@ static int radius_das_open_socket(int po | @@ -534,6 +573,49 @@ static int radius_das_open_socket(int po | ||||||
|  } |  } | ||||||
|   |   | ||||||
|   |   | ||||||
| @@ -246,7 +251,7 @@ | |||||||
|  struct radius_das_data * |  struct radius_das_data * | ||||||
|  radius_das_init(struct radius_das_conf *conf) |  radius_das_init(struct radius_das_conf *conf) | ||||||
|  { |  { | ||||||
| @@ -553,6 +635,8 @@ radius_das_init(struct radius_das_conf * | @@ -554,6 +636,8 @@ radius_das_init(struct radius_das_conf * | ||||||
|  	das->ctx = conf->ctx; |  	das->ctx = conf->ctx; | ||||||
|  	das->disconnect = conf->disconnect; |  	das->disconnect = conf->disconnect; | ||||||
|  	das->coa = conf->coa; |  	das->coa = conf->coa; | ||||||
| @@ -255,7 +260,7 @@ | |||||||
|   |   | ||||||
|  	os_memcpy(&das->client_addr, conf->client_addr, |  	os_memcpy(&das->client_addr, conf->client_addr, | ||||||
|  		  sizeof(das->client_addr)); |  		  sizeof(das->client_addr)); | ||||||
| @@ -565,19 +649,15 @@ radius_das_init(struct radius_das_conf * | @@ -566,19 +650,15 @@ radius_das_init(struct radius_das_conf * | ||||||
|  	} |  	} | ||||||
|  	das->shared_secret_len = conf->shared_secret_len; |  	das->shared_secret_len = conf->shared_secret_len; | ||||||
|   |   | ||||||
| @@ -278,7 +283,7 @@ | |||||||
|   |   | ||||||
|  	return das; |  	return das; | ||||||
|  } |  } | ||||||
| @@ -588,11 +668,14 @@ void radius_das_deinit(struct radius_das | @@ -589,11 +669,14 @@ void radius_das_deinit(struct radius_das | ||||||
|  	if (das == NULL) |  	if (das == NULL) | ||||||
|  		return; |  		return; | ||||||
|   |   | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c | --- a/hostapd/config_file.c | ||||||
| =================================================================== | +++ b/hostapd/config_file.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/hostapd/config_file.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/hostapd/config_file.c |  | ||||||
| @@ -2366,6 +2366,8 @@ static int hostapd_config_fill(struct ho | @@ -2366,6 +2366,8 @@ static int hostapd_config_fill(struct ho | ||||||
|  			return 1; |  			return 1; | ||||||
|  		} |  		} | ||||||
| @@ -11,41 +9,23 @@ Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c | |||||||
|  	} else if (os_strcmp(buf, "driver_params") == 0) { |  	} else if (os_strcmp(buf, "driver_params") == 0) { | ||||||
|  		os_free(conf->driver_params); |  		os_free(conf->driver_params); | ||||||
|  		conf->driver_params = os_strdup(pos); |  		conf->driver_params = os_strdup(pos); | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/ap_config.h | --- a/src/ap/ap_config.h | ||||||
| =================================================================== | +++ b/src/ap/ap_config.h | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/ap_config.h |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/ap_config.h |  | ||||||
| @@ -279,6 +279,7 @@ struct hostapd_bss_config { | @@ -279,6 +279,7 @@ struct hostapd_bss_config { | ||||||
|  	char snoop_iface[IFNAMSIZ + 1]; |  	char snoop_iface[IFNAMSIZ + 1]; | ||||||
|  	char vlan_bridge[IFNAMSIZ + 1]; |  	char vlan_bridge[IFNAMSIZ + 1]; | ||||||
|  	char wds_bridge[IFNAMSIZ + 1]; |  	char wds_bridge[IFNAMSIZ + 1]; | ||||||
| +	char *uci_section; | +	char *uci_section; | ||||||
|   |   | ||||||
|  	char *config_id; |  	enum hostapd_logger_level logger_syslog_level, logger_stdout_level; | ||||||
|   |   | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/ubus.c | --- a/src/ap/ap_config.c | ||||||
| =================================================================== | +++ b/src/ap/ap_config.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/ubus.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/ubus.c |  | ||||||
| @@ -467,6 +467,9 @@ hostapd_bss_get_status(struct ubus_conte |  | ||||||
|  			hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0); |  | ||||||
|  	blobmsg_close_table(&b, dfs_table); |  | ||||||
|   |  | ||||||
| +	if (hapd->conf->uci_section) |  | ||||||
| +		blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section); |  | ||||||
| + |  | ||||||
|  	ubus_send_reply(ctx, req, b.head); |  | ||||||
|   |  | ||||||
|  	return 0; |  | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/ap_config.c |  | ||||||
| =================================================================== |  | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/ap_config.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/ap_config.c |  | ||||||
| @@ -785,6 +785,7 @@ void hostapd_config_free_bss(struct host | @@ -785,6 +785,7 @@ void hostapd_config_free_bss(struct host | ||||||
|  	os_free(conf->radius_req_attr_sqlite); |  	os_free(conf->radius_req_attr_sqlite); | ||||||
|  	os_free(conf->rsn_preauth_interfaces); |  	os_free(conf->rsn_preauth_interfaces); | ||||||
|  	os_free(conf->ctrl_interface); |  	os_free(conf->ctrl_interface); | ||||||
| +	os_free(conf->uci_section); | +	os_free(conf->uci_section); | ||||||
|  	os_free(conf->config_id); |  | ||||||
|  	os_free(conf->ca_cert); |  	os_free(conf->ca_cert); | ||||||
|  	os_free(conf->server_cert); |  	os_free(conf->server_cert); | ||||||
|  |  	os_free(conf->server_cert2); | ||||||
|   | |||||||
							
								
								
									
										53
									
								
								feeds/ipq95xx/hostapd/patches/920-sta_driver_data.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								feeds/ipq95xx/hostapd/patches/920-sta_driver_data.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | --- a/src/drivers/driver.h | ||||||
|  | +++ b/src/drivers/driver.h | ||||||
|  | @@ -2175,6 +2175,10 @@ struct hostap_sta_driver_data { | ||||||
|  |  	u8 tx_mcs; | ||||||
|  |  	u8 rx_vht_nss; | ||||||
|  |  	u8 tx_vht_nss; | ||||||
|  | +	u8 rx_hemcs; | ||||||
|  | +	u8 tx_hemcs; | ||||||
|  | +	u8 rx_he_nss; | ||||||
|  | +	u8 tx_he_nss; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  struct hostapd_sta_add_params { | ||||||
|  | --- a/src/drivers/driver_nl80211.c | ||||||
|  | +++ b/src/drivers/driver_nl80211.c | ||||||
|  | @@ -7010,6 +7010,8 @@ static int get_sta_handler(struct nl_msg | ||||||
|  |  		[NL80211_RATE_INFO_VHT_MCS] = { .type = NLA_U8 }, | ||||||
|  |  		[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, | ||||||
|  |  		[NL80211_RATE_INFO_VHT_NSS] = { .type = NLA_U8 }, | ||||||
|  | +		[NL80211_RATE_INFO_HE_NSS] = { .type = NLA_U8 }, | ||||||
|  | +		[NL80211_RATE_INFO_HE_MCS] = { .type = NLA_U8 }, | ||||||
|  |  	}; | ||||||
|  |   | ||||||
|  |  	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), | ||||||
|  | @@ -7102,6 +7104,10 @@ static int get_sta_handler(struct nl_msg | ||||||
|  |  				nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]); | ||||||
|  |  			data->flags |= STA_DRV_DATA_TX_VHT_NSS; | ||||||
|  |  		} | ||||||
|  | +		if (rate[NL80211_RATE_INFO_HE_MCS]) | ||||||
|  | +			data->tx_hemcs = nla_get_u8(rate[NL80211_RATE_INFO_HE_MCS]); | ||||||
|  | +		if (rate[NL80211_RATE_INFO_HE_NSS]) | ||||||
|  | +			data->tx_he_nss = nla_get_u8(rate[NL80211_RATE_INFO_HE_NSS]); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (stats[NL80211_STA_INFO_RX_BITRATE] && | ||||||
|  | @@ -7132,11 +7138,16 @@ static int get_sta_handler(struct nl_msg | ||||||
|  |  				nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]); | ||||||
|  |  			data->flags |= STA_DRV_DATA_RX_VHT_NSS; | ||||||
|  |  		} | ||||||
|  | +		if (rate[NL80211_RATE_INFO_HE_MCS]) | ||||||
|  | +			data->rx_hemcs = nla_get_u8(rate[NL80211_RATE_INFO_HE_MCS]); | ||||||
|  | +		if (rate[NL80211_RATE_INFO_HE_NSS]) | ||||||
|  | +			data->rx_he_nss = nla_get_u8(rate[NL80211_RATE_INFO_HE_NSS]); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (stats[NL80211_STA_INFO_TID_STATS]) | ||||||
|  |  		get_sta_tid_stats(data, stats[NL80211_STA_INFO_TID_STATS]); | ||||||
|  |   | ||||||
|  | + | ||||||
|  |  	return NL_SKIP; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  | ||||||
							
								
								
									
										95
									
								
								feeds/ipq95xx/hostapd/patches/999-das-proxy-state.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								feeds/ipq95xx/hostapd/patches/999-das-proxy-state.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | |||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/radius/radius_das.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/radius/radius_das.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/radius/radius_das.c | ||||||
|  | @@ -63,6 +63,7 @@ static struct radius_msg * radius_das_di | ||||||
|  |  		RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, | ||||||
|  |  		RADIUS_ATTR_VENDOR_SPECIFIC, | ||||||
|  |  		RADIUS_ATTR_CALLED_STATION_ID, | ||||||
|  | +		RADIUS_ATTR_PROXY_STATE, | ||||||
|  |  #ifdef CONFIG_IPV6 | ||||||
|  |  		RADIUS_ATTR_NAS_IPV6_ADDRESS, | ||||||
|  |  #endif /* CONFIG_IPV6 */ | ||||||
|  | @@ -159,6 +160,12 @@ static struct radius_msg * radius_das_di | ||||||
|  |  		attrs.cui_len = len; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_PROXY_STATE, | ||||||
|  | +				    &buf, &len, NULL) == 0) { | ||||||
|  | +		attrs.proxy = buf; | ||||||
|  | +		attrs.proxy_len = len; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	res = das->disconnect(das->ctx, &attrs); | ||||||
|  |  	switch (res) { | ||||||
|  |  	case RADIUS_DAS_NAS_MISMATCH: | ||||||
|  | @@ -167,10 +174,11 @@ static struct radius_msg * radius_das_di | ||||||
|  |  		error = 403; | ||||||
|  |  		break; | ||||||
|  |  	case RADIUS_DAS_SESSION_NOT_FOUND: | ||||||
|  | -		wpa_printf(MSG_INFO, "DAS: Session not found for request from " | ||||||
|  | -			   "%s:%d", abuf, from_port); | ||||||
|  | -		error = 503; | ||||||
|  | -		break; | ||||||
|  | +		return NULL; | ||||||
|  | +//		wpa_printf(MSG_INFO, "DAS: Session not found for request from " | ||||||
|  | +//			   "%s:%d", abuf, from_port); | ||||||
|  | +//		error = 503; | ||||||
|  | +//		break; | ||||||
|  |  	case RADIUS_DAS_MULTI_SESSION_MATCH: | ||||||
|  |  		wpa_printf(MSG_INFO, | ||||||
|  |  			   "DAS: Multiple sessions match for request from %s:%d", | ||||||
|  | @@ -192,6 +200,9 @@ fail: | ||||||
|  |  	if (reply == NULL) | ||||||
|  |  		return NULL; | ||||||
|  |   | ||||||
|  | +	if (attrs.proxy) | ||||||
|  | +		radius_msg_add_attr(reply, RADIUS_ATTR_PROXY_STATE, attrs.proxy, attrs.proxy_len); | ||||||
|  | + | ||||||
|  |  	if (error) { | ||||||
|  |  		if (!radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, | ||||||
|  |  					       error)) { | ||||||
|  | @@ -222,6 +233,7 @@ static struct radius_msg * radius_das_co | ||||||
|  |  		RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, | ||||||
|  |  		RADIUS_ATTR_VENDOR_SPECIFIC, | ||||||
|  |  		RADIUS_ATTR_CALLED_STATION_ID, | ||||||
|  | +		RADIUS_ATTR_PROXY_STATE, | ||||||
|  |  #ifdef CONFIG_IPV6 | ||||||
|  |  		RADIUS_ATTR_NAS_IPV6_ADDRESS, | ||||||
|  |  #endif /* CONFIG_IPV6 */ | ||||||
|  | @@ -347,6 +359,12 @@ static struct radius_msg * radius_das_co | ||||||
|  |  	} | ||||||
|  |  #endif /* CONFIG_HS20 */ | ||||||
|  |   | ||||||
|  | +	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_PROXY_STATE, | ||||||
|  | +				    &buf, &len, NULL) == 0) { | ||||||
|  | +		attrs.proxy = buf; | ||||||
|  | +		attrs.proxy_len = len; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	res = das->coa(das->ctx, &attrs); | ||||||
|  |  	switch (res) { | ||||||
|  |  	case RADIUS_DAS_NAS_MISMATCH: | ||||||
|  | @@ -382,6 +400,9 @@ fail: | ||||||
|  |  	if (!reply) | ||||||
|  |  		return NULL; | ||||||
|  |   | ||||||
|  | +	if (attrs.proxy) | ||||||
|  | +		radius_msg_add_attr(reply, RADIUS_ATTR_PROXY_STATE, attrs.proxy, attrs.proxy_len); | ||||||
|  | + | ||||||
|  |  	if (error && | ||||||
|  |  	    !radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, error)) { | ||||||
|  |  		radius_msg_free(reply); | ||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/radius/radius_das.h | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/radius/radius_das.h | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/radius/radius_das.h | ||||||
|  | @@ -36,6 +36,8 @@ struct radius_das_attrs { | ||||||
|  |  	size_t acct_multi_session_id_len; | ||||||
|  |  	const u8 *cui; | ||||||
|  |  	size_t cui_len; | ||||||
|  | +	const u8 *proxy; | ||||||
|  | +	size_t proxy_len; | ||||||
|  |   | ||||||
|  |  	/* Authorization changes */ | ||||||
|  |  	const u8 *hs20_t_c_filtering; | ||||||
							
								
								
									
										48
									
								
								feeds/ipq95xx/hostapd/patches/999-ft-anonce.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								feeds/ipq95xx/hostapd/patches/999-ft-anonce.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_ft.c | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_ft.c | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_ft.c | ||||||
|  | @@ -3067,6 +3067,7 @@ static int wpa_ft_process_auth_req(struc | ||||||
|  |  	size_t identity_len = 0, radius_cui_len = 0; | ||||||
|  |  	int use_sha384; | ||||||
|  |  	size_t pmk_r1_len, kdk_len; | ||||||
|  | +	struct os_reltime now; | ||||||
|  |   | ||||||
|  |  	*resp_ies = NULL; | ||||||
|  |  	*resp_ies_len = 0; | ||||||
|  | @@ -3185,10 +3186,19 @@ pmk_r1_derived: | ||||||
|  |  	os_memcpy(sm->pmk_r1, pmk_r1, pmk_r1_len); | ||||||
|  |  	sm->pmk_r1_len = pmk_r1_len; | ||||||
|  |   | ||||||
|  | -	if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { | ||||||
|  | -		wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " | ||||||
|  | -			   "ANonce"); | ||||||
|  | -		return WLAN_STATUS_UNSPECIFIED_FAILURE; | ||||||
|  | +	if (os_get_reltime(&now) < 0 || | ||||||
|  | +	    os_reltime_expired(&now, &sm->ANonce_time, 1)) { | ||||||
|  | +		if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { | ||||||
|  | +			wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " | ||||||
|  | +				   "ANonce"); | ||||||
|  | +			return WLAN_STATUS_UNSPECIFIED_FAILURE; | ||||||
|  | +		} | ||||||
|  | +		sm->ANonce_time.sec = now.sec; | ||||||
|  | +		sm->ANonce_time.usec = now.usec; | ||||||
|  | +		wpa_printf(MSG_INFO, "FT: ANonce was randomized"); | ||||||
|  | +	} else { | ||||||
|  | +		wpa_printf(MSG_INFO, "FT: ANonce has not expired"); | ||||||
|  | +		 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", | ||||||
|  | Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_i.h | ||||||
|  | =================================================================== | ||||||
|  | --- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_i.h | ||||||
|  | +++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_i.h | ||||||
|  | @@ -54,6 +54,7 @@ struct wpa_state_machine { | ||||||
|  |  	bool MICVerified; | ||||||
|  |  	bool GUpdateStationKeys; | ||||||
|  |  	u8 ANonce[WPA_NONCE_LEN]; | ||||||
|  | +	struct os_reltime ANonce_time; | ||||||
|  |  	u8 SNonce[WPA_NONCE_LEN]; | ||||||
|  |  	u8 alt_SNonce[WPA_NONCE_LEN]; | ||||||
|  |  	u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN]; | ||||||
| @@ -1,8 +1,6 @@ | |||||||
| Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c | --- a/hostapd/config_file.c | ||||||
| =================================================================== | +++ b/hostapd/config_file.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/hostapd/config_file.c | @@ -3337,6 +3337,8 @@ static int hostapd_config_fill(struct ho | ||||||
| +++ hostapd-2021-02-20-59e9794c/hostapd/config_file.c |  | ||||||
| @@ -3339,6 +3339,8 @@ static int hostapd_config_fill(struct ho |  | ||||||
|  		bss->ignore_broadcast_ssid = atoi(pos); |  		bss->ignore_broadcast_ssid = atoi(pos); | ||||||
|  	} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) { |  	} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) { | ||||||
|  		bss->no_probe_resp_if_max_sta = atoi(pos); |  		bss->no_probe_resp_if_max_sta = atoi(pos); | ||||||
| @@ -11,11 +9,9 @@ Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c | |||||||
|  #ifdef CONFIG_WEP |  #ifdef CONFIG_WEP | ||||||
|  	} else if (os_strcmp(buf, "wep_default_key") == 0) { |  	} else if (os_strcmp(buf, "wep_default_key") == 0) { | ||||||
|  		bss->ssid.wep.idx = atoi(pos); |  		bss->ssid.wep.idx = atoi(pos); | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/ap_config.h | --- a/src/ap/ap_config.h | ||||||
| =================================================================== | +++ b/src/ap/ap_config.h | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/ap_config.h | @@ -459,6 +459,7 @@ struct hostapd_bss_config { | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/ap_config.h |  | ||||||
| @@ -460,6 +460,7 @@ struct hostapd_bss_config { |  | ||||||
|  	int ap_max_inactivity; |  	int ap_max_inactivity; | ||||||
|  	int ignore_broadcast_ssid; |  	int ignore_broadcast_ssid; | ||||||
|  	int no_probe_resp_if_max_sta; |  	int no_probe_resp_if_max_sta; | ||||||
| @@ -23,10 +19,8 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ap_config.h | |||||||
|   |   | ||||||
|  	int wmm_enabled; |  	int wmm_enabled; | ||||||
|  	int wmm_uapsd; |  	int wmm_uapsd; | ||||||
| Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c | --- a/src/ap/beacon.c | ||||||
| =================================================================== | +++ b/src/ap/beacon.c | ||||||
| --- hostapd-2021-02-20-59e9794c.orig/src/ap/beacon.c |  | ||||||
| +++ hostapd-2021-02-20-59e9794c/src/ap/beacon.c |  | ||||||
| @@ -920,7 +920,8 @@ void handle_probe_req(struct hostapd_dat | @@ -920,7 +920,8 @@ void handle_probe_req(struct hostapd_dat | ||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_P2P */ |  #endif /* CONFIG_P2P */ | ||||||
|   | |||||||
							
								
								
									
										75
									
								
								feeds/ipq95xx/hostapd/patches/999-ssi_signal.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								feeds/ipq95xx/hostapd/patches/999-ssi_signal.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | |||||||
|  | --- a/src/ap/ieee802_11.c | ||||||
|  | +++ b/src/ap/ieee802_11.c | ||||||
|  | @@ -57,6 +57,17 @@ | ||||||
|  |  #include "gas_query_ap.h" | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +static int | ||||||
|  | +ewma(int new, int old) | ||||||
|  | +{ | ||||||
|  | +	#define ALPHA	10 | ||||||
|  | +	if (!old) | ||||||
|  | +		return new; | ||||||
|  | +	if (new >= 0) | ||||||
|  | +		return old; | ||||||
|  | +	return ((ALPHA * new) + ((100 - ALPHA) * old)) / 100; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  #ifdef CONFIG_FILS | ||||||
|  |  static struct wpabuf * | ||||||
|  |  prepare_auth_resp_fils(struct hostapd_data *hapd, | ||||||
|  | @@ -5873,7 +5882,7 @@ static int robust_action_frame(u8 catego | ||||||
|  |   | ||||||
|  |  static int handle_action(struct hostapd_data *hapd, | ||||||
|  |  			 const struct ieee80211_mgmt *mgmt, size_t len, | ||||||
|  | -			 unsigned int freq) | ||||||
|  | +			 unsigned int freq, int ssi_signal) | ||||||
|  |  { | ||||||
|  |  	struct sta_info *sta; | ||||||
|  |  	u8 *action __maybe_unused; | ||||||
|  | @@ -5930,6 +5939,7 @@ static int handle_action(struct hostapd_ | ||||||
|  |   | ||||||
|  |  		sta->last_seq_ctrl = seq_ctrl; | ||||||
|  |  		sta->last_subtype = WLAN_FC_STYPE_ACTION; | ||||||
|  | +		sta->signal_mgmt = ewma(ssi_signal, sta->signal_mgmt);; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	switch (mgmt->u.action.category) { | ||||||
|  | @@ -6109,6 +6119,8 @@ int ieee802_11_mgmt(struct hostapd_data | ||||||
|  |  	unsigned int freq; | ||||||
|  |  	int ssi_signal = fi ? fi->ssi_signal : 0; | ||||||
|  |   | ||||||
|  | +	hapd->signal_mgmt = ewma(ssi_signal, hapd->signal_mgmt);; | ||||||
|  | + | ||||||
|  |  	if (len < 24) | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  | @@ -6208,7 +6220,7 @@ int ieee802_11_mgmt(struct hostapd_data | ||||||
|  |  		break; | ||||||
|  |  	case WLAN_FC_STYPE_ACTION: | ||||||
|  |  		wpa_printf(MSG_DEBUG, "mgmt::action"); | ||||||
|  | -		ret = handle_action(hapd, mgmt, len, freq); | ||||||
|  | +		ret = handle_action(hapd, mgmt, len, freq, ssi_signal); | ||||||
|  |  		break; | ||||||
|  |  	default: | ||||||
|  |  		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, | ||||||
|  | --- a/src/ap/sta_info.h | ||||||
|  | +++ b/src/ap/sta_info.h | ||||||
|  | @@ -331,6 +331,7 @@ struct sta_info { | ||||||
|  |  #ifdef CONFIG_PASN | ||||||
|  |  	struct pasn_data *pasn; | ||||||
|  |  #endif /* CONFIG_PASN */ | ||||||
|  | +	int signal_mgmt; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |   | ||||||
|  | --- a/src/ap/hostapd.h | ||||||
|  | +++ b/src/ap/hostapd.h | ||||||
|  | @@ -451,6 +451,7 @@ struct hostapd_data { | ||||||
|  |  #ifdef CONFIG_CTRL_IFACE_UDP | ||||||
|  |         unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; | ||||||
|  |  #endif /* CONFIG_CTRL_IFACE_UDP */ | ||||||
|  | +       int signal_mgmt; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |   | ||||||
| @@ -17,9 +17,11 @@ Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> | |||||||
|  src/ap/hostapd.c | 93 +++++++++++++++++++++++++++++++++--------------- |  src/ap/hostapd.c | 93 +++++++++++++++++++++++++++++++++--------------- | ||||||
|  1 file changed, 65 insertions(+), 28 deletions(-) |  1 file changed, 65 insertions(+), 28 deletions(-) | ||||||
|  |  | ||||||
| --- a/src/ap/hostapd.c | Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c | ||||||
| +++ b/src/ap/hostapd.c | =================================================================== | ||||||
| @@ -1101,19 +1101,60 @@ static int db_table_create_radius_attrib | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.c | ||||||
|  | +++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c | ||||||
|  | @@ -1131,6 +1131,47 @@ static int db_table_create_radius_attrib | ||||||
|   |   | ||||||
|  #endif /* CONFIG_NO_RADIUS */ |  #endif /* CONFIG_NO_RADIUS */ | ||||||
|   |   | ||||||
| @@ -58,30 +60,16 @@ Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> | |||||||
| +	if (hapd->driver && hapd->driver->set_operstate) | +	if (hapd->driver && hapd->driver->set_operstate) | ||||||
| +		hapd->driver->set_operstate(hapd->drv_priv, 1); | +		hapd->driver->set_operstate(hapd->drv_priv, 1); | ||||||
| + | + | ||||||
|  | +	hostapd_ubus_add_bss(hapd); | ||||||
|  | +	hostapd_ucode_add_bss(hapd); | ||||||
|  | +	 | ||||||
| +	return 0; | +	return 0; | ||||||
| +} | +} | ||||||
|  | +  | ||||||
|   |   | ||||||
|  /** |  /** | ||||||
|   * hostapd_setup_bss - Per-BSS setup (initialization) |   * hostapd_setup_bss - Per-BSS setup (initialization) | ||||||
|   * @hapd: Pointer to BSS data | @@ -1432,32 +1473,8 @@ int hostapd_setup_bss(struct hostapd_dat | ||||||
|   * @first: Whether this BSS is the first BSS of an interface; -1 = not first, |  | ||||||
|   *	but interface may exist |  | ||||||
| + * @set_beacon: Whether beacon should be set. When MBSSID IE is enabled, |  | ||||||
| + *	information regarding all BSSes should be retrieved before setting |  | ||||||
| + *	beacons. |  | ||||||
|   * |  | ||||||
|   * This function is used to initialize all per-BSS data structures and |  | ||||||
|   * resources. This gets called in a loop for each BSS when an interface is |  | ||||||
|   * initialized. Most of the modules that are initialized here will be |  | ||||||
|   * deinitialized in hostapd_cleanup(). |  | ||||||
|   */ |  | ||||||
| -static int hostapd_setup_bss(struct hostapd_data *hapd, int first) |  | ||||||
| +static int hostapd_setup_bss(struct hostapd_data *hapd, int first, |  | ||||||
| +			     bool set_beacon) |  | ||||||
|  { |  | ||||||
|  	struct hostapd_bss_config *conf = hapd->conf; |  | ||||||
|  	u8 ssid[SSID_MAX_LEN + 1]; |  | ||||||
| @@ -1385,31 +1426,8 @@ static int hostapd_setup_bss(struct host |  | ||||||
|  		return -1; |  		return -1; | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
| @@ -110,22 +98,22 @@ Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> | |||||||
| -		hapd->driver->set_operstate(hapd->drv_priv, 1); | -		hapd->driver->set_operstate(hapd->drv_priv, 1); | ||||||
| - | - | ||||||
| -	hostapd_ubus_add_bss(hapd); | -	hostapd_ubus_add_bss(hapd); | ||||||
|  | -	hostapd_ucode_add_bss(hapd); | ||||||
| +	if (set_beacon) | +	if (set_beacon) | ||||||
| +		return hostapd_set_beacon(hapd); | +		return hostapd_set_beacon(hapd); | ||||||
|   |   | ||||||
|  	return 0; |  	return 0; | ||||||
|  } |  } | ||||||
| @@ -2121,7 +2139,8 @@ static int hostapd_setup_interface_compl | @@ -2169,7 +2186,7 @@ static int hostapd_setup_interface_compl | ||||||
|  		hapd = iface->bss[j]; |  		hapd = iface->bss[j]; | ||||||
|  		if (j) |  		if (j) | ||||||
|  			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); |  			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); | ||||||
| -		if (hostapd_setup_bss(hapd, j == 0)) { | -		if (hostapd_setup_bss(hapd, j == 0, true)) { | ||||||
| +		if (hostapd_setup_bss(hapd, j == 0, | +		if (hostapd_setup_bss(hapd, j == 0, (hapd->iconf->mbssid? 0 : 1))) { | ||||||
| +				      (hapd->iconf->mbssid? 0 : 1))) { |  | ||||||
|  			for (;;) { |  			for (;;) { | ||||||
|  				hapd = iface->bss[j]; |  				hapd = iface->bss[j]; | ||||||
|  				hostapd_bss_deinit_no_free(hapd); |  				hostapd_bss_deinit_no_free(hapd); | ||||||
| @@ -2135,6 +2154,24 @@ static int hostapd_setup_interface_compl | @@ -2183,6 +2200,24 @@ static int hostapd_setup_interface_compl | ||||||
|  		if (is_zero_ether_addr(hapd->conf->bssid)) |  		if (is_zero_ether_addr(hapd->conf->bssid)) | ||||||
|  			prev_addr = hapd->own_addr; |  			prev_addr = hapd->own_addr; | ||||||
|  	} |  	} | ||||||
| @@ -150,12 +138,3 @@ Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> | |||||||
|  	hapd = iface->bss[0]; |  	hapd = iface->bss[0]; | ||||||
|   |   | ||||||
|  	hostapd_tx_queue_params(iface); |  	hostapd_tx_queue_params(iface); | ||||||
| @@ -3019,7 +3056,7 @@ int hostapd_add_iface(struct hapd_interf |  | ||||||
|   |  | ||||||
|  			if (start_ctrl_iface_bss(hapd) < 0 || |  | ||||||
|  			    (hapd_iface->state == HAPD_IFACE_ENABLED && |  | ||||||
| -			     hostapd_setup_bss(hapd, -1))) { |  | ||||||
| +			     hostapd_setup_bss(hapd, -1, 1))) { |  | ||||||
|  				hostapd_cleanup(hapd); |  | ||||||
|  				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL; |  | ||||||
|  				hapd_iface->conf->num_bss--; |  | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c | |||||||
|  #ifdef CONFIG_DPP |  #ifdef CONFIG_DPP | ||||||
|  #include "common/dpp.h" |  #include "common/dpp.h" | ||||||
|  #endif /* CONFIG_DPP */ |  #endif /* CONFIG_DPP */ | ||||||
| @@ -2694,6 +2695,7 @@ static int hostapd_ctrl_register_frame(s | @@ -2637,6 +2638,7 @@ static int hostapd_ctrl_register_frame(s | ||||||
|  static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) |  static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) | ||||||
|  { |  { | ||||||
|  	int idx, bw, bw_idx[] = { 20, 40, 80, 160 }; |  	int idx, bw, bw_idx[] = { 20, 40, 80, 160 }; | ||||||
| @@ -39,7 +39,7 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c | |||||||
|   |   | ||||||
|  	if (is_6ghz_freq(params->freq)) { |  	if (is_6ghz_freq(params->freq)) { | ||||||
|  		/* Verify if HE was enabled by user or not. 6 GHz does not |  		/* Verify if HE was enabled by user or not. 6 GHz does not | ||||||
| @@ -2726,11 +2728,17 @@ static int hostapd_ctrl_check_freq_param | @@ -2669,11 +2671,17 @@ static int hostapd_ctrl_check_freq_param | ||||||
|   |   | ||||||
|  		if (params->center_freq2 || params->sec_channel_offset) |  		if (params->center_freq2 || params->sec_channel_offset) | ||||||
|  			return -1; |  			return -1; | ||||||
| @@ -57,7 +57,7 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c | |||||||
|  		if (!params->center_freq1) |  		if (!params->center_freq1) | ||||||
|  			break; |  			break; | ||||||
|  		switch (params->sec_channel_offset) { |  		switch (params->sec_channel_offset) { | ||||||
| @@ -2765,6 +2773,9 @@ static int hostapd_ctrl_check_freq_param | @@ -2708,6 +2716,9 @@ static int hostapd_ctrl_check_freq_param | ||||||
|  			return -1; |  			return -1; | ||||||
|  		} |  		} | ||||||
|   |   | ||||||
| @@ -67,7 +67,7 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c | |||||||
|  		/* Adjacent and overlapped are not allowed for 80+80 */ |  		/* Adjacent and overlapped are not allowed for 80+80 */ | ||||||
|  		if (params->center_freq2 && |  		if (params->center_freq2 && | ||||||
|  		    params->center_freq1 - params->center_freq2 <= 80 && |  		    params->center_freq1 - params->center_freq2 <= 80 && | ||||||
| @@ -2799,6 +2810,32 @@ static int hostapd_ctrl_check_freq_param | @@ -2742,6 +2753,32 @@ static int hostapd_ctrl_check_freq_param | ||||||
|  		return -1; |  		return -1; | ||||||
|  	} |  	} | ||||||
|   |   | ||||||
| @@ -169,7 +169,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/drv_callbacks.c | |||||||
|  	if (!finished) |  	if (!finished) | ||||||
|  		return; |  		return; | ||||||
|   |   | ||||||
| @@ -2088,6 +2092,8 @@ void hostapd_wpa_event(void *ctx, enum w | @@ -2090,6 +2094,8 @@ void hostapd_wpa_event(void *ctx, enum w | ||||||
|  					data->ch_switch.ch_width, |  					data->ch_switch.ch_width, | ||||||
|  					data->ch_switch.cf1, |  					data->ch_switch.cf1, | ||||||
|  					data->ch_switch.cf2, |  					data->ch_switch.cf2, | ||||||
| @@ -182,7 +182,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c | |||||||
| =================================================================== | =================================================================== | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.c | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.c | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c | +++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c | ||||||
| @@ -3674,6 +3674,8 @@ static int hostapd_change_config_freq(st | @@ -3624,6 +3624,8 @@ static int hostapd_change_config_freq(st | ||||||
|  	conf->ieee80211n = params->ht_enabled; |  	conf->ieee80211n = params->ht_enabled; | ||||||
|  	conf->ieee80211ac = params->vht_enabled; |  	conf->ieee80211ac = params->vht_enabled; | ||||||
|  	conf->secondary_channel = params->sec_channel_offset; |  	conf->secondary_channel = params->sec_channel_offset; | ||||||
| @@ -191,7 +191,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c | |||||||
|  	ieee80211_freq_to_chan(params->center_freq1, |  	ieee80211_freq_to_chan(params->center_freq1, | ||||||
|  			       &seg0); |  			       &seg0); | ||||||
|  	ieee80211_freq_to_chan(params->center_freq2, |  	ieee80211_freq_to_chan(params->center_freq2, | ||||||
| @@ -3887,6 +3889,8 @@ hostapd_switch_channel_fallback(struct h | @@ -3837,6 +3839,8 @@ hostapd_switch_channel_fallback(struct h | ||||||
|  	hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); |  	hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); | ||||||
|  	hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); |  	hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); | ||||||
|  	hostapd_set_oper_chwidth(iface->conf, bw); |  	hostapd_set_oper_chwidth(iface->conf, bw); | ||||||
| @@ -204,7 +204,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h | |||||||
| =================================================================== | =================================================================== | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.h | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.h | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h | +++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h | ||||||
| @@ -721,6 +721,7 @@ int hostapd_probe_req_rx(struct hostapd_ | @@ -730,6 +730,7 @@ int hostapd_probe_req_rx(struct hostapd_ | ||||||
|  			 int ssi_signal); |  			 int ssi_signal); | ||||||
|  void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, |  void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, | ||||||
|  			     int offset, int width, int cf1, int cf2, |  			     int offset, int width, int cf1, int cf2, | ||||||
| @@ -216,7 +216,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h | |||||||
| =================================================================== | =================================================================== | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h | --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h | +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h | ||||||
| @@ -6088,6 +6088,8 @@ union wpa_event_data { | @@ -6111,6 +6111,8 @@ union wpa_event_data { | ||||||
|  		enum chan_width ch_width; |  		enum chan_width ch_width; | ||||||
|  		int cf1; |  		int cf1; | ||||||
|  		int cf2; |  		int cf2; | ||||||
| @@ -229,7 +229,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c | |||||||
| =================================================================== | =================================================================== | ||||||
| --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c | --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c | ||||||
| +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c | +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c | ||||||
| @@ -9984,7 +9984,7 @@ static int nl80211_switch_channel(void * | @@ -10064,7 +10064,7 @@ static int nl80211_switch_channel(void * | ||||||
|  	int i; |  	int i; | ||||||
|   |   | ||||||
|  	wpa_printf(MSG_DEBUG, |  	wpa_printf(MSG_DEBUG, | ||||||
| @@ -238,7 +238,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c | |||||||
|  		   settings->cs_count, settings->block_tx, |  		   settings->cs_count, settings->block_tx, | ||||||
|  		   settings->freq_params.freq, |  		   settings->freq_params.freq, | ||||||
|  		   settings->freq_params.channel, |  		   settings->freq_params.channel, | ||||||
| @@ -9994,7 +9994,9 @@ static int nl80211_switch_channel(void * | @@ -10074,7 +10074,9 @@ static int nl80211_switch_channel(void * | ||||||
|  		   settings->freq_params.center_freq2, |  		   settings->freq_params.center_freq2, | ||||||
|  		   settings->freq_params.ht_enabled ? " ht" : "", |  		   settings->freq_params.ht_enabled ? " ht" : "", | ||||||
|  		   settings->freq_params.vht_enabled ? " vht" : "", |  		   settings->freq_params.vht_enabled ? " vht" : "", | ||||||
| @@ -259,10 +259,10 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c | |||||||
|  				 struct nlattr *cf1, struct nlattr *cf2, |  				 struct nlattr *cf1, struct nlattr *cf2, | ||||||
| +				 struct nlattr *ru_punct_bitmap, | +				 struct nlattr *ru_punct_bitmap, | ||||||
| +				 struct nlattr *ru_punct_ofdma, | +				 struct nlattr *ru_punct_ofdma, | ||||||
|  				 struct nlattr *count, int finished) |  				 struct nlattr *count, | ||||||
|  |  				 int finished) | ||||||
|  { |  { | ||||||
|  	struct i802_bss *bss; | @@ -754,6 +756,11 @@ static void mlme_event_ch_switch(struct | ||||||
| @@ -753,6 +755,11 @@ static void mlme_event_ch_switch(struct |  | ||||||
|  		data.ch_switch.cf1 = nla_get_u32(cf1); |  		data.ch_switch.cf1 = nla_get_u32(cf1); | ||||||
|  	if (cf2) |  	if (cf2) | ||||||
|  		data.ch_switch.cf2 = nla_get_u32(cf2); |  		data.ch_switch.cf2 = nla_get_u32(cf2); | ||||||
| @@ -274,7 +274,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c | |||||||
|  	if (count) |  	if (count) | ||||||
|  		data.ch_switch.count = nla_get_u32(count); |  		data.ch_switch.count = nla_get_u32(count); | ||||||
|   |   | ||||||
| @@ -3112,6 +3119,8 @@ static void do_process_drv_event(struct | @@ -3113,6 +3120,8 @@ static void do_process_drv_event(struct | ||||||
|  				     tb[NL80211_ATTR_CHANNEL_WIDTH], |  				     tb[NL80211_ATTR_CHANNEL_WIDTH], | ||||||
|  				     tb[NL80211_ATTR_CENTER_FREQ1], |  				     tb[NL80211_ATTR_CENTER_FREQ1], | ||||||
|  				     tb[NL80211_ATTR_CENTER_FREQ2], |  				     tb[NL80211_ATTR_CENTER_FREQ2], | ||||||
| @@ -283,7 +283,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c | |||||||
|  				     tb[NL80211_ATTR_CH_SWITCH_COUNT], |  				     tb[NL80211_ATTR_CH_SWITCH_COUNT], | ||||||
|  				     0); |  				     0); | ||||||
|  		break; |  		break; | ||||||
| @@ -3123,6 +3132,8 @@ static void do_process_drv_event(struct | @@ -3124,6 +3133,8 @@ static void do_process_drv_event(struct | ||||||
|  				     tb[NL80211_ATTR_CHANNEL_WIDTH], |  				     tb[NL80211_ATTR_CHANNEL_WIDTH], | ||||||
|  				     tb[NL80211_ATTR_CENTER_FREQ1], |  				     tb[NL80211_ATTR_CENTER_FREQ1], | ||||||
|  				     tb[NL80211_ATTR_CENTER_FREQ2], |  				     tb[NL80211_ATTR_CENTER_FREQ2], | ||||||
|   | |||||||
| @@ -12,11 +12,11 @@ advertised to mac80211 through NL attribute. | |||||||
|  |  | ||||||
| Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> | Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> | ||||||
|  |  | ||||||
| Index: b/src/ap/ap_drv_ops.c | Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.c | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/ap/ap_drv_ops.c	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_drv_ops.c | ||||||
| +++ b/src/ap/ap_drv_ops.c	2022-11-07 22:32:28.150487226 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.c | ||||||
| @@ -421,6 +421,8 @@ int hostapd_sta_add(struct hostapd_data | @@ -419,6 +419,8 @@ int hostapd_sta_add(struct hostapd_data | ||||||
|  		    size_t he_capab_len, size_t eht_capab_len, |  		    size_t he_capab_len, size_t eht_capab_len, | ||||||
|  		    const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, |  		    const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, | ||||||
|  		    u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, |  		    u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, | ||||||
| @@ -25,7 +25,7 @@ Index: b/src/ap/ap_drv_ops.c | |||||||
|  		    int set) |  		    int set) | ||||||
|  { |  { | ||||||
|  	struct hostapd_sta_add_params params; |  	struct hostapd_sta_add_params params; | ||||||
| @@ -450,6 +452,8 @@ int hostapd_sta_add(struct hostapd_data | @@ -448,6 +450,8 @@ int hostapd_sta_add(struct hostapd_data | ||||||
|  	params.qosinfo = qosinfo; |  	params.qosinfo = qosinfo; | ||||||
|  	params.support_p2p_ps = supp_p2p_ps; |  	params.support_p2p_ps = supp_p2p_ps; | ||||||
|  	params.set = set; |  	params.set = set; | ||||||
| @@ -34,10 +34,10 @@ Index: b/src/ap/ap_drv_ops.c | |||||||
|  	return hapd->driver->sta_add(hapd->drv_priv, ¶ms); |  	return hapd->driver->sta_add(hapd->drv_priv, ¶ms); | ||||||
|  } |  } | ||||||
|   |   | ||||||
| Index: b/src/ap/ap_drv_ops.h | Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/ap/ap_drv_ops.h	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_drv_ops.h | ||||||
| +++ b/src/ap/ap_drv_ops.h	2022-11-07 22:32:28.150487226 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h | ||||||
| @@ -46,6 +46,8 @@ int hostapd_sta_add(struct hostapd_data | @@ -46,6 +46,8 @@ int hostapd_sta_add(struct hostapd_data | ||||||
|  		    size_t he_capab_len, size_t eht_capab_len, |  		    size_t he_capab_len, size_t eht_capab_len, | ||||||
|  		    const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, |  		    const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, | ||||||
| @@ -47,10 +47,10 @@ Index: b/src/ap/ap_drv_ops.h | |||||||
|  		    int set); |  		    int set); | ||||||
|  int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); |  int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); | ||||||
|  int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, |  int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, | ||||||
| Index: b/src/ap/beacon.c | Index: hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/ap/beacon.c	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/beacon.c | ||||||
| +++ b/src/ap/beacon.c	2022-11-07 22:32:28.150487226 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c | ||||||
| @@ -651,6 +651,10 @@ static u8 * hostapd_gen_probe_resp(struc | @@ -651,6 +651,10 @@ static u8 * hostapd_gen_probe_resp(struc | ||||||
|  		buflen += (3 + sizeof(struct ieee80211_eht_operation)); |  		buflen += (3 + sizeof(struct ieee80211_eht_operation)); | ||||||
|  		if (hapd->iconf->ru_punct_bitmap) |  		if (hapd->iconf->ru_punct_bitmap) | ||||||
| @@ -70,7 +70,7 @@ Index: b/src/ap/beacon.c | |||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_IEEE80211BE */ |  #endif /* CONFIG_IEEE80211BE */ | ||||||
|   |   | ||||||
| @@ -1776,6 +1781,9 @@ int ieee802_11_build_ap_params(struct ho | @@ -1802,6 +1807,9 @@ int ieee802_11_build_ap_params(struct ho | ||||||
|  		tail_len += (3 + sizeof(struct ieee80211_eht_operation)); |  		tail_len += (3 + sizeof(struct ieee80211_eht_operation)); | ||||||
|  		if (hapd->iconf->ru_punct_bitmap) |  		if (hapd->iconf->ru_punct_bitmap) | ||||||
|  			tail_len +=  DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; |  			tail_len +=  DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; | ||||||
| @@ -80,7 +80,7 @@ Index: b/src/ap/beacon.c | |||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_IEEE80211BE */ |  #endif /* CONFIG_IEEE80211BE */ | ||||||
|   |   | ||||||
| @@ -1939,6 +1947,8 @@ int ieee802_11_build_ap_params(struct ho | @@ -1965,6 +1973,8 @@ int ieee802_11_build_ap_params(struct ho | ||||||
|  						IEEE80211_MODE_AP); |  						IEEE80211_MODE_AP); | ||||||
|  		tailpos = hostapd_eid_eht_operation(hapd, tailpos, |  		tailpos = hostapd_eid_eht_operation(hapd, tailpos, | ||||||
|  						IEEE80211_MODE_AP); |  						IEEE80211_MODE_AP); | ||||||
| @@ -89,11 +89,11 @@ Index: b/src/ap/beacon.c | |||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_IEEE80211BE */ |  #endif /* CONFIG_IEEE80211BE */ | ||||||
|   |   | ||||||
| Index: b/src/ap/ieee802_11.c | Index: hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.c | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/ap/ieee802_11.c	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11.c | ||||||
| +++ b/src/ap/ieee802_11.c	2022-11-07 22:32:28.150487226 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.c | ||||||
| @@ -4599,6 +4599,9 @@ static int check_assoc_ies(struct hostap | @@ -4607,6 +4607,9 @@ static int check_assoc_ies(struct hostap | ||||||
|  					  elems.he_capabilities, |  					  elems.he_capabilities, | ||||||
|  					  elems.eht_capabilities, |  					  elems.eht_capabilities, | ||||||
|  					  elems.eht_capabilities_len); |  					  elems.eht_capabilities_len); | ||||||
| @@ -103,7 +103,7 @@ Index: b/src/ap/ieee802_11.c | |||||||
|  		if (resp != WLAN_STATUS_SUCCESS) |  		if (resp != WLAN_STATUS_SUCCESS) | ||||||
|  			return resp; |  			return resp; | ||||||
|  	} |  	} | ||||||
| @@ -4975,6 +4978,7 @@ static int add_associated_sta(struct hos | @@ -4983,6 +4986,7 @@ static int add_associated_sta(struct hos | ||||||
|  	struct ieee80211_vht_capabilities vht_cap; |  	struct ieee80211_vht_capabilities vht_cap; | ||||||
|  	struct ieee80211_he_capabilities he_cap; |  	struct ieee80211_he_capabilities he_cap; | ||||||
|  	struct ieee80211_eht_capabilities eht_cap; |  	struct ieee80211_eht_capabilities eht_cap; | ||||||
| @@ -111,7 +111,7 @@ Index: b/src/ap/ieee802_11.c | |||||||
|  	int set = 1; |  	int set = 1; | ||||||
|   |   | ||||||
|  	/* |  	/* | ||||||
| @@ -5035,6 +5039,8 @@ static int add_associated_sta(struct hos | @@ -5043,6 +5047,8 @@ static int add_associated_sta(struct hos | ||||||
|  	if (sta->flags & WLAN_STA_EXT_EHT) { |  	if (sta->flags & WLAN_STA_EXT_EHT) { | ||||||
|  		hostapd_get_eht_capab(hapd, sta->eht_capab, &eht_cap, |  		hostapd_get_eht_capab(hapd, sta->eht_capab, &eht_cap, | ||||||
|  				      sta->eht_capab_len); |  				      sta->eht_capab_len); | ||||||
| @@ -120,7 +120,7 @@ Index: b/src/ap/ieee802_11.c | |||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_IEEE80211BE */ |  #endif /* CONFIG_IEEE80211BE */ | ||||||
|   |   | ||||||
| @@ -5055,6 +5061,8 @@ static int add_associated_sta(struct hos | @@ -5063,6 +5069,8 @@ static int add_associated_sta(struct hos | ||||||
|  			    sta->he_6ghz_capab, |  			    sta->he_6ghz_capab, | ||||||
|  			    sta->flags | WLAN_STA_ASSOC, sta->qosinfo, |  			    sta->flags | WLAN_STA_ASSOC, sta->qosinfo, | ||||||
|  			    sta->vht_opmode, sta->p2p_ie ? 1 : 0, |  			    sta->vht_opmode, sta->p2p_ie ? 1 : 0, | ||||||
| @@ -129,7 +129,7 @@ Index: b/src/ap/ieee802_11.c | |||||||
|  			    set)) { |  			    set)) { | ||||||
|  		hostapd_logger(hapd, sta->addr, |  		hostapd_logger(hapd, sta->addr, | ||||||
|  			       HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, |  			       HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, | ||||||
| @@ -5108,6 +5116,9 @@ static u16 send_assoc_resp(struct hostap | @@ -5116,6 +5124,9 @@ static u16 send_assoc_resp(struct hostap | ||||||
|  		buflen += (3 + sizeof(struct ieee80211_eht_operation)); |  		buflen += (3 + sizeof(struct ieee80211_eht_operation)); | ||||||
|  		if (hapd->iconf->ru_punct_bitmap) |  		if (hapd->iconf->ru_punct_bitmap) | ||||||
|  			buflen +=  DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; |  			buflen +=  DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; | ||||||
| @@ -139,7 +139,7 @@ Index: b/src/ap/ieee802_11.c | |||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_IEEE80211BE */ |  #endif /* CONFIG_IEEE80211BE */ | ||||||
|   |   | ||||||
| @@ -5229,6 +5240,7 @@ static u16 send_assoc_resp(struct hostap | @@ -5237,6 +5248,7 @@ static u16 send_assoc_resp(struct hostap | ||||||
|  	if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { |  	if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { | ||||||
|  		p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP); |  		p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP); | ||||||
|  		p = hostapd_eid_eht_operation(hapd, p, IEEE80211_MODE_AP); |  		p = hostapd_eid_eht_operation(hapd, p, IEEE80211_MODE_AP); | ||||||
| @@ -147,11 +147,11 @@ Index: b/src/ap/ieee802_11.c | |||||||
|  	} |  	} | ||||||
|  #endif /* CONFIG_IEEE80211BE */ |  #endif /* CONFIG_IEEE80211BE */ | ||||||
|   |   | ||||||
| Index: b/src/ap/ieee802_11.h | Index: hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.h | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/ap/ieee802_11.h	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11.h | ||||||
| +++ b/src/ap/ieee802_11.h	2022-11-07 22:32:28.150487226 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.h | ||||||
| @@ -91,6 +91,10 @@ void hostapd_get_eht_capab(struct hostap | @@ -97,6 +97,10 @@ void hostapd_get_eht_capab(struct hostap | ||||||
|  			   const struct ieee80211_eht_capabilities *src, |  			   const struct ieee80211_eht_capabilities *src, | ||||||
|  			   struct ieee80211_eht_capabilities *dest, |  			   struct ieee80211_eht_capabilities *dest, | ||||||
|  			   size_t len); |  			   size_t len); | ||||||
| @@ -162,7 +162,7 @@ Index: b/src/ap/ieee802_11.h | |||||||
|  int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta); |  int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta); | ||||||
|  u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, |  u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, | ||||||
|  		      const u8 *ht_capab); |  		      const u8 *ht_capab); | ||||||
| @@ -225,8 +229,13 @@ u8 * hostapd_eid_eht_capab(struct hostap | @@ -231,8 +235,13 @@ u8 * hostapd_eid_eht_capab(struct hostap | ||||||
|  			   enum ieee80211_op_mode opmode); |  			   enum ieee80211_op_mode opmode); | ||||||
|  u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, |  u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, | ||||||
|  			       enum ieee80211_op_mode opmode); |  			       enum ieee80211_op_mode opmode); | ||||||
| @@ -176,10 +176,10 @@ Index: b/src/ap/ieee802_11.h | |||||||
| +			      const u8 *eht_240mhz_capab, size_t eht_240mhz_len); | +			      const u8 *eht_240mhz_capab, size_t eht_240mhz_len); | ||||||
|  void ru_punct_update_bw(u16 bitmap, u8 pri_chan, u8 *width, u8 *seg0, u8 *seg1); |  void ru_punct_update_bw(u16 bitmap, u8 pri_chan, u8 *width, u8 *seg0, u8 *seg1); | ||||||
|  #endif /* IEEE802_11_H */ |  #endif /* IEEE802_11_H */ | ||||||
| Index: b/src/ap/ieee802_11_eht.c | Index: hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11_eht.c | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/ap/ieee802_11_eht.c	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11_eht.c | ||||||
| +++ b/src/ap/ieee802_11_eht.c	2022-11-07 22:32:42.142383632 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11_eht.c | ||||||
| @@ -18,6 +18,7 @@ | @@ -18,6 +18,7 @@ | ||||||
|   |   | ||||||
|  #include "utils/includes.h" |  #include "utils/includes.h" | ||||||
| @@ -322,10 +322,10 @@ Index: b/src/ap/ieee802_11_eht.c | |||||||
| + | + | ||||||
| +	os_memcpy(dest, src, len); | +	os_memcpy(dest, src, len); | ||||||
| +} | +} | ||||||
| Index: b/src/ap/sta_info.c | Index: hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.c | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/ap/sta_info.c	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/sta_info.c | ||||||
| +++ b/src/ap/sta_info.c	2022-11-07 22:32:28.150487226 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.c | ||||||
| @@ -359,6 +359,7 @@ void ap_free_sta(struct hostapd_data *ha | @@ -359,6 +359,7 @@ void ap_free_sta(struct hostapd_data *ha | ||||||
|  	os_free(sta->he_capab); |  	os_free(sta->he_capab); | ||||||
|  	os_free(sta->he_6ghz_capab); |  	os_free(sta->he_6ghz_capab); | ||||||
| @@ -334,7 +334,7 @@ Index: b/src/ap/sta_info.c | |||||||
|  	hostapd_free_psk_list(sta->psk); |  	hostapd_free_psk_list(sta->psk); | ||||||
|  	os_free(sta->identity); |  	os_free(sta->identity); | ||||||
|  	os_free(sta->radius_cui); |  	os_free(sta->radius_cui); | ||||||
| @@ -1555,7 +1556,7 @@ int ap_sta_re_add(struct hostapd_data *h | @@ -1579,7 +1580,7 @@ int ap_sta_re_add(struct hostapd_data *h | ||||||
|  			    sta->supported_rates, |  			    sta->supported_rates, | ||||||
|  			    sta->supported_rates_len, |  			    sta->supported_rates_len, | ||||||
|  			    0, NULL, NULL, NULL, NULL, 0, 0, NULL, |  			    0, NULL, NULL, NULL, NULL, 0, 0, NULL, | ||||||
| @@ -343,23 +343,23 @@ Index: b/src/ap/sta_info.c | |||||||
|  		hostapd_logger(hapd, sta->addr, |  		hostapd_logger(hapd, sta->addr, | ||||||
|  			       HOSTAPD_MODULE_IEEE80211, |  			       HOSTAPD_MODULE_IEEE80211, | ||||||
|  			       HOSTAPD_LEVEL_NOTICE, |  			       HOSTAPD_LEVEL_NOTICE, | ||||||
| Index: b/src/ap/sta_info.h | Index: hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.h | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/ap/sta_info.h	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/ap/sta_info.h | ||||||
| +++ b/src/ap/sta_info.h	2022-11-07 22:32:28.154487197 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.h | ||||||
| @@ -337,6 +337,8 @@ struct sta_info { | @@ -340,6 +340,8 @@ struct sta_info { | ||||||
|  #ifdef CONFIG_PASN |  | ||||||
|  	struct pasn_data *pasn; |  	struct pasn_data *pasn; | ||||||
|  #endif /* CONFIG_PASN */ |  #endif /* CONFIG_PASN */ | ||||||
|  |  	int signal_mgmt; | ||||||
| +	struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab; | +	struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab; | ||||||
| +	size_t eht_240mhz_len; | +	size_t eht_240mhz_len; | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
|   |   | ||||||
| Index: b/src/common/ieee802_11_common.c | Index: hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.c | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/common/ieee802_11_common.c	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_common.c | ||||||
| +++ b/src/common/ieee802_11_common.c	2022-11-07 22:32:28.154487197 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.c | ||||||
| @@ -22,6 +22,7 @@ static int ieee802_11_parse_vendor_speci | @@ -22,6 +22,7 @@ static int ieee802_11_parse_vendor_speci | ||||||
|  					    int show_errors) |  					    int show_errors) | ||||||
|  { |  { | ||||||
| @@ -413,10 +413,10 @@ Index: b/src/common/ieee802_11_common.c | |||||||
|  			if (ieee802_11_parse_vendor_specific(pos, elen, |  			if (ieee802_11_parse_vendor_specific(pos, elen, | ||||||
|  							     elems, |  							     elems, | ||||||
|  							     show_errors)) |  							     show_errors)) | ||||||
| Index: b/src/common/ieee802_11_common.h | Index: hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.h | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/common/ieee802_11_common.h	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_common.h | ||||||
| +++ b/src/common/ieee802_11_common.h	2022-11-07 22:32:28.154487197 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.h | ||||||
| @@ -121,6 +121,7 @@ struct ieee802_11_elems { | @@ -121,6 +121,7 @@ struct ieee802_11_elems { | ||||||
|  	const u8 *mbssid_known_bss; |  	const u8 *mbssid_known_bss; | ||||||
|  	const u8 *eht_capabilities; |  	const u8 *eht_capabilities; | ||||||
| @@ -433,10 +433,10 @@ Index: b/src/common/ieee802_11_common.h | |||||||
|   |   | ||||||
|  	struct mb_ies_info mb_ies; |  	struct mb_ies_info mb_ies; | ||||||
|  	struct frag_ies_info frag_ies; |  	struct frag_ies_info frag_ies; | ||||||
| Index: b/src/common/ieee802_11_defs.h | Index: hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_defs.h | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/common/ieee802_11_defs.h	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_defs.h | ||||||
| +++ b/src/common/ieee802_11_defs.h	2022-11-07 22:32:28.154487197 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_defs.h | ||||||
| @@ -2494,6 +2494,13 @@ struct ieee80211_eht_operation { | @@ -2494,6 +2494,13 @@ struct ieee80211_eht_operation { | ||||||
|  	le16 disabled_subchannel_bitmap[0]; |  	le16 disabled_subchannel_bitmap[0]; | ||||||
|  } STRUCT_PACKED; |  } STRUCT_PACKED; | ||||||
| @@ -471,10 +471,10 @@ Index: b/src/common/ieee802_11_defs.h | |||||||
|  /* |  /* | ||||||
|   * IEEE P802.11be/D1.0, May 2021, |   * IEEE P802.11be/D1.0, May 2021, | ||||||
|   * section 9.4.2.295c.4 Supported EHT-MCS And NSS Set field |   * section 9.4.2.295c.4 Supported EHT-MCS And NSS Set field | ||||||
| Index: b/src/common/qca-vendor.h | Index: hostapd-2021-12-13-b26f5c0f/src/common/qca-vendor.h | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/common/qca-vendor.h	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/common/qca-vendor.h | ||||||
| +++ b/src/common/qca-vendor.h	2022-11-07 22:32:28.154487197 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/common/qca-vendor.h | ||||||
| @@ -18,6 +18,10 @@ | @@ -18,6 +18,10 @@ | ||||||
|   */ |   */ | ||||||
|   |   | ||||||
| @@ -486,11 +486,11 @@ Index: b/src/common/qca-vendor.h | |||||||
|   |   | ||||||
|  #ifndef BIT |  #ifndef BIT | ||||||
|  #define BIT(x) (1U << (x)) |  #define BIT(x) (1U << (x)) | ||||||
| Index: b/src/drivers/driver.h | Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/drivers/driver.h	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h | ||||||
| +++ b/src/drivers/driver.h	2022-11-07 22:32:28.154487197 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h | ||||||
| @@ -2394,6 +2394,8 @@ struct hostapd_sta_add_params { | @@ -2398,6 +2398,8 @@ struct hostapd_sta_add_params { | ||||||
|  	size_t supp_oper_classes_len; |  	size_t supp_oper_classes_len; | ||||||
|  	int support_p2p_ps; |  	int support_p2p_ps; | ||||||
|  	u16 ru_punct_bitmap; |  	u16 ru_punct_bitmap; | ||||||
| @@ -499,11 +499,11 @@ Index: b/src/drivers/driver.h | |||||||
|  }; |  }; | ||||||
|   |   | ||||||
|  struct mac_address { |  struct mac_address { | ||||||
| Index: b/src/drivers/driver_nl80211.c | Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/drivers/driver_nl80211.c	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c | ||||||
| +++ b/src/drivers/driver_nl80211.c	2022-11-07 22:32:28.154487197 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c | ||||||
| @@ -5278,6 +5278,14 @@ static int wpa_driver_nl80211_sta_add(vo | @@ -5285,6 +5285,14 @@ static int wpa_driver_nl80211_sta_add(vo | ||||||
|  				goto fail; |  				goto fail; | ||||||
|  		} |  		} | ||||||
|   |   | ||||||
| @@ -518,10 +518,10 @@ Index: b/src/drivers/driver_nl80211.c | |||||||
|  		if (params->ext_capab) { |  		if (params->ext_capab) { | ||||||
|  			wpa_hexdump(MSG_DEBUG, "  * ext_capab", |  			wpa_hexdump(MSG_DEBUG, "  * ext_capab", | ||||||
|  				    params->ext_capab, params->ext_capab_len); |  				    params->ext_capab, params->ext_capab_len); | ||||||
| Index: b/src/drivers/nl80211_copy.h | Index: hostapd-2021-12-13-b26f5c0f/src/drivers/nl80211_copy.h | ||||||
| =================================================================== | =================================================================== | ||||||
| --- a/src/drivers/nl80211_copy.h	2022-11-07 22:32:28.158487168 +0530 | --- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/nl80211_copy.h | ||||||
| +++ b/src/drivers/nl80211_copy.h	2022-11-07 22:32:28.154487197 +0530 | +++ hostapd-2021-12-13-b26f5c0f/src/drivers/nl80211_copy.h | ||||||
| @@ -3137,6 +3137,7 @@ enum nl80211_attrs { | @@ -3137,6 +3137,7 @@ enum nl80211_attrs { | ||||||
|  	NL80211_ATTR_RU_PUNCT_BITMAP, |  	NL80211_ATTR_RU_PUNCT_BITMAP, | ||||||
|  	 |  	 | ||||||
|   | |||||||
| @@ -29,11 +29,6 @@ static struct ubus_context *ctx; | |||||||
| static struct blob_buf b; | static struct blob_buf b; | ||||||
| static int ctx_ref; | static int ctx_ref; | ||||||
|  |  | ||||||
| static inline struct hapd_interfaces *get_hapd_interfaces_from_object(struct ubus_object *obj) |  | ||||||
| { |  | ||||||
| 	return container_of(obj, struct hapd_interfaces, ubus); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj) | static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj) | ||||||
| { | { | ||||||
| 	return container_of(obj, struct hostapd_data, ubus.obj); | 	return container_of(obj, struct hostapd_data, ubus.obj); | ||||||
| @@ -44,12 +39,6 @@ struct ubus_banned_client { | |||||||
| 	u8 addr[ETH_ALEN]; | 	u8 addr[ETH_ALEN]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void ubus_receive(int sock, void *eloop_ctx, void *sock_ctx) |  | ||||||
| { |  | ||||||
| 	struct ubus_context *ctx = eloop_ctx; |  | ||||||
| 	ubus_handle_event(ctx); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) | static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) | ||||||
| { | { | ||||||
| 	if (ubus_reconnect(ctx, NULL)) { | 	if (ubus_reconnect(ctx, NULL)) { | ||||||
| @@ -57,12 +46,12 @@ static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) | |||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL); | 	ubus_add_uloop(ctx); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void hostapd_ubus_connection_lost(struct ubus_context *ctx) | static void hostapd_ubus_connection_lost(struct ubus_context *ctx) | ||||||
| { | { | ||||||
| 	eloop_unregister_read_sock(ctx->sock.fd); | 	uloop_fd_delete(&ctx->sock); | ||||||
| 	eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); | 	eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -71,12 +60,14 @@ static bool hostapd_ubus_init(void) | |||||||
| 	if (ctx) | 	if (ctx) | ||||||
| 		return true; | 		return true; | ||||||
|  |  | ||||||
|  | 	eloop_add_uloop(); | ||||||
| 	ctx = ubus_connect(NULL); | 	ctx = ubus_connect(NULL); | ||||||
| 	if (!ctx) | 	if (!ctx) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 	ctx->connection_lost = hostapd_ubus_connection_lost; | 	ctx->connection_lost = hostapd_ubus_connection_lost; | ||||||
| 	eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL); | 	ubus_add_uloop(ctx); | ||||||
|  |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -94,7 +85,7 @@ static void hostapd_ubus_ref_dec(void) | |||||||
| 	if (ctx_ref) | 	if (ctx_ref) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	eloop_unregister_read_sock(ctx->sock.fd); | 	uloop_fd_delete(&ctx->sock); | ||||||
| 	ubus_free(ctx); | 	ubus_free(ctx); | ||||||
| 	ctx = NULL; | 	ctx = NULL; | ||||||
| } | } | ||||||
| @@ -127,38 +118,6 @@ static void hostapd_notify_ubus(struct ubus_object *obj, char *bssname, char *ev | |||||||
| 	free(event_type); | 	free(event_type); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void hostapd_send_procd_event(char *bssname, char *event) |  | ||||||
| { |  | ||||||
| 	char *name, *s; |  | ||||||
| 	uint32_t id; |  | ||||||
| 	void *v; |  | ||||||
|  |  | ||||||
| 	if (!ctx || ubus_lookup_id(ctx, "service", &id)) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	if (asprintf(&name, "hostapd.%s.%s", bssname, event) < 0) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	blob_buf_init(&b, 0); |  | ||||||
|  |  | ||||||
| 	s = blobmsg_alloc_string_buffer(&b, "type", strlen(name) + 1); |  | ||||||
| 	sprintf(s, "%s", name); |  | ||||||
| 	blobmsg_add_string_buffer(&b); |  | ||||||
|  |  | ||||||
| 	v = blobmsg_open_table(&b, "data"); |  | ||||||
| 	blobmsg_close_table(&b, v); |  | ||||||
|  |  | ||||||
| 	ubus_invoke(ctx, id, "event", b.head, NULL, NULL, 1000); |  | ||||||
|  |  | ||||||
| 	free(name); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void hostapd_send_shared_event(struct ubus_object *obj, char *bssname, char *event) |  | ||||||
| { |  | ||||||
| 	hostapd_send_procd_event(bssname, event); |  | ||||||
| 	hostapd_notify_ubus(obj, bssname, event); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void | static void | ||||||
| hostapd_bss_del_ban(void *eloop_data, void *user_ctx) | hostapd_bss_del_ban(void *eloop_data, void *user_ctx) | ||||||
| { | { | ||||||
| @@ -194,7 +153,7 @@ hostapd_bss_ban_client(struct hostapd_data *hapd, u8 *addr, int time) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	eloop_register_timeout(0, time * 1000, hostapd_bss_del_ban, ban, hapd); | 	eloop_register_timeout(time, 0, hostapd_bss_del_ban, ban, hapd); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int | static int | ||||||
| @@ -203,10 +162,8 @@ hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj, | |||||||
| 		   struct blob_attr *msg) | 		   struct blob_attr *msg) | ||||||
| { | { | ||||||
| 	struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); | 	struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); | ||||||
| 	int ret = hostapd_reload_config(hapd->iface, 1); |  | ||||||
|  |  | ||||||
| 	hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "reload"); | 	return hostapd_reload_config(hapd->iface); | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -348,7 +305,42 @@ hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj, | |||||||
| 			blobmsg_add_u32(&b, "rx", sta_driver_data.current_rx_rate * 100); | 			blobmsg_add_u32(&b, "rx", sta_driver_data.current_rx_rate * 100); | ||||||
| 			blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100); | 			blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100); | ||||||
| 			blobmsg_close_table(&b, r); | 			blobmsg_close_table(&b, r); | ||||||
|  | 			blobmsg_add_u32(&b, "retries", sta_driver_data.tx_retry_count); | ||||||
|  | 			blobmsg_add_u32(&b, "failed", sta_driver_data.tx_retry_failed); | ||||||
| 			blobmsg_add_u32(&b, "signal", sta_driver_data.signal); | 			blobmsg_add_u32(&b, "signal", sta_driver_data.signal); | ||||||
|  | 		 | ||||||
|  | 			r = blobmsg_open_table(&b, "mcs"); | ||||||
|  | 			if (sta_driver_data.rx_hemcs) { | ||||||
|  | 				blobmsg_add_u32(&b, "he", 1); | ||||||
|  | 				blobmsg_add_u32(&b, "rx", sta_driver_data.rx_hemcs); | ||||||
|  | 				blobmsg_add_u32(&b, "tx", sta_driver_data.tx_hemcs); | ||||||
|  | 			} else if (sta_driver_data.rx_vhtmcs) { | ||||||
|  | 				blobmsg_add_u32(&b, "vht", 1); | ||||||
|  | 				blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vhtmcs); | ||||||
|  | 				blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vhtmcs); | ||||||
|  | 			} else { | ||||||
|  | 				blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs); | ||||||
|  | 				blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs); | ||||||
|  | 			} | ||||||
|  | 			blobmsg_close_table(&b, r); | ||||||
|  |  | ||||||
|  | 			r = blobmsg_open_table(&b, "nss"); | ||||||
|  | 			if (sta_driver_data.rx_he_nss) { | ||||||
|  | 				blobmsg_add_u32(&b, "he", 1); | ||||||
|  | 				blobmsg_add_u32(&b, "rx", sta_driver_data.rx_he_nss); | ||||||
|  | 				blobmsg_add_u32(&b, "tx", sta_driver_data.tx_he_nss); | ||||||
|  | 			} else if (sta_driver_data.rx_vht_nss) { | ||||||
|  | 				blobmsg_add_u32(&b, "vht", 1); | ||||||
|  | 				blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vht_nss); | ||||||
|  | 				blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vht_nss); | ||||||
|  | 			} else { | ||||||
|  | 				blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs); | ||||||
|  | 				blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs); | ||||||
|  | 			} | ||||||
|  | 			blobmsg_close_table(&b, r); | ||||||
|  | 		 | ||||||
|  | 			if (sta->signal_mgmt) | ||||||
|  | 				blobmsg_add_u32(&b, "signal_mgmt", sta->signal_mgmt); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		hostapd_parse_capab_blobmsg(sta); | 		hostapd_parse_capab_blobmsg(sta); | ||||||
| @@ -467,6 +459,12 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj, | |||||||
| 			hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0); | 			hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0); | ||||||
| 	blobmsg_close_table(&b, dfs_table); | 	blobmsg_close_table(&b, dfs_table); | ||||||
|  |  | ||||||
|  | 	if (hapd->conf->uci_section) | ||||||
|  | 		blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section); | ||||||
|  |  | ||||||
|  | 	if (hapd->signal_mgmt) | ||||||
|  | 		blobmsg_add_u32(&b, "signal_mgmt", hapd->signal_mgmt); | ||||||
|  |  | ||||||
| 	ubus_send_reply(ctx, req, b.head); | 	ubus_send_reply(ctx, req, b.head); | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| @@ -693,68 +691,6 @@ enum { | |||||||
| 	__CONFIG_MAX | 	__CONFIG_MAX | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static const struct blobmsg_policy config_add_policy[__CONFIG_MAX] = { |  | ||||||
| 	[CONFIG_IFACE] = { "iface", BLOBMSG_TYPE_STRING }, |  | ||||||
| 	[CONFIG_FILE] = { "config", BLOBMSG_TYPE_STRING }, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| hostapd_config_add(struct ubus_context *ctx, struct ubus_object *obj, |  | ||||||
| 		   struct ubus_request_data *req, const char *method, |  | ||||||
| 		   struct blob_attr *msg) |  | ||||||
| { |  | ||||||
| 	struct blob_attr *tb[__CONFIG_MAX]; |  | ||||||
| 	struct hapd_interfaces *interfaces = get_hapd_interfaces_from_object(obj); |  | ||||||
| 	char buf[128]; |  | ||||||
|  |  | ||||||
| 	blobmsg_parse(config_add_policy, __CONFIG_MAX, tb, blob_data(msg), blob_len(msg)); |  | ||||||
|  |  | ||||||
| 	if (!tb[CONFIG_FILE] || !tb[CONFIG_IFACE]) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	snprintf(buf, sizeof(buf), "bss_config=%s:%s", |  | ||||||
| 		blobmsg_get_string(tb[CONFIG_IFACE]), |  | ||||||
| 		blobmsg_get_string(tb[CONFIG_FILE])); |  | ||||||
|  |  | ||||||
| 	if (hostapd_add_iface(interfaces, buf)) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	blob_buf_init(&b, 0); |  | ||||||
| 	blobmsg_add_u32(&b, "pid", getpid()); |  | ||||||
| 	ubus_send_reply(ctx, req, b.head); |  | ||||||
|  |  | ||||||
| 	return UBUS_STATUS_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| enum { |  | ||||||
| 	CONFIG_REM_IFACE, |  | ||||||
| 	__CONFIG_REM_MAX |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static const struct blobmsg_policy config_remove_policy[__CONFIG_REM_MAX] = { |  | ||||||
| 	[CONFIG_REM_IFACE] = { "iface", BLOBMSG_TYPE_STRING }, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| hostapd_config_remove(struct ubus_context *ctx, struct ubus_object *obj, |  | ||||||
| 		      struct ubus_request_data *req, const char *method, |  | ||||||
| 		      struct blob_attr *msg) |  | ||||||
| { |  | ||||||
| 	struct blob_attr *tb[__CONFIG_REM_MAX]; |  | ||||||
| 	struct hapd_interfaces *interfaces = get_hapd_interfaces_from_object(obj); |  | ||||||
| 	char buf[128]; |  | ||||||
|  |  | ||||||
| 	blobmsg_parse(config_remove_policy, __CONFIG_REM_MAX, tb, blob_data(msg), blob_len(msg)); |  | ||||||
|  |  | ||||||
| 	if (!tb[CONFIG_REM_IFACE]) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	if (hostapd_remove_iface(interfaces, blobmsg_get_string(tb[CONFIG_REM_IFACE]))) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	return UBUS_STATUS_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| enum { | enum { | ||||||
| 	CSA_FREQ, | 	CSA_FREQ, | ||||||
| 	CSA_BCN_COUNT, | 	CSA_BCN_COUNT, | ||||||
| @@ -882,8 +818,8 @@ hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, | |||||||
| 				css.freq_params.sec_channel_offset, | 				css.freq_params.sec_channel_offset, | ||||||
| 				chwidth, seg0, seg1, | 				chwidth, seg0, seg1, | ||||||
| 				iconf->vht_capab, | 				iconf->vht_capab, | ||||||
| 				mode ? &mode->he_capab[IEEE80211_MODE_AP] : | 				mode ? &mode->he_capab[IEEE80211_MODE_AP] : 0, | ||||||
| 				NULL, NULL, 0,0,0); | 				0, 0, 0, 0); | ||||||
|  |  | ||||||
| 	for (i = 0; i < hapd->iface->num_bss; i++) { | 	for (i = 0; i < hapd->iface->num_bss; i++) { | ||||||
| 		struct hostapd_data *bss = hapd->iface->bss[i]; | 		struct hostapd_data *bss = hapd->iface->bss[i]; | ||||||
| @@ -1623,8 +1559,6 @@ void hostapd_ubus_add_bss(struct hostapd_data *hapd) | |||||||
| 	obj->n_methods = bss_object_type.n_methods; | 	obj->n_methods = bss_object_type.n_methods; | ||||||
| 	ret = ubus_add_object(ctx, obj); | 	ret = ubus_add_object(ctx, obj); | ||||||
| 	hostapd_ubus_ref_inc(); | 	hostapd_ubus_ref_inc(); | ||||||
|  |  | ||||||
| 	hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "add"); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void hostapd_ubus_free_bss(struct hostapd_data *hapd) | void hostapd_ubus_free_bss(struct hostapd_data *hapd) | ||||||
| @@ -1640,8 +1574,6 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd) | |||||||
| 	if (!ctx) | 	if (!ctx) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "remove"); |  | ||||||
|  |  | ||||||
| 	if (obj->id) { | 	if (obj->id) { | ||||||
| 		ubus_remove_object(ctx, obj); | 		ubus_remove_object(ctx, obj); | ||||||
| 		hostapd_ubus_ref_dec(); | 		hostapd_ubus_ref_dec(); | ||||||
| @@ -1687,47 +1619,6 @@ void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vl | |||||||
| 	hostapd_ubus_vlan_action(hapd, vlan, "vlan_remove"); | 	hostapd_ubus_vlan_action(hapd, vlan, "vlan_remove"); | ||||||
| } | } | ||||||
|  |  | ||||||
| static const struct ubus_method daemon_methods[] = { |  | ||||||
| 	UBUS_METHOD("config_add", hostapd_config_add, config_add_policy), |  | ||||||
| 	UBUS_METHOD("config_remove", hostapd_config_remove, config_remove_policy), |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static struct ubus_object_type daemon_object_type = |  | ||||||
| 	UBUS_OBJECT_TYPE("hostapd", daemon_methods); |  | ||||||
|  |  | ||||||
| void hostapd_ubus_add(struct hapd_interfaces *interfaces) |  | ||||||
| { |  | ||||||
| 	struct ubus_object *obj = &interfaces->ubus; |  | ||||||
| 	int ret; |  | ||||||
|  |  | ||||||
| 	if (!hostapd_ubus_init()) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	obj->name = strdup("hostapd"); |  | ||||||
|  |  | ||||||
| 	obj->type = &daemon_object_type; |  | ||||||
| 	obj->methods = daemon_object_type.methods; |  | ||||||
| 	obj->n_methods = daemon_object_type.n_methods; |  | ||||||
| 	ret = ubus_add_object(ctx, obj); |  | ||||||
| 	hostapd_ubus_ref_inc(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hostapd_ubus_free(struct hapd_interfaces *interfaces) |  | ||||||
| { |  | ||||||
| 	struct ubus_object *obj = &interfaces->ubus; |  | ||||||
| 	char *name = (char *) obj->name; |  | ||||||
|  |  | ||||||
| 	if (!ctx) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	if (obj->id) { |  | ||||||
| 		ubus_remove_object(ctx, obj); |  | ||||||
| 		hostapd_ubus_ref_dec(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	free(name); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct ubus_event_req { | struct ubus_event_req { | ||||||
| 	struct ubus_notify_request nreq; | 	struct ubus_notify_request nreq; | ||||||
| 	int resp; | 	int resp; | ||||||
| @@ -1844,10 +1735,44 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 * | |||||||
|  |  | ||||||
| 	blob_buf_init(&b, 0); | 	blob_buf_init(&b, 0); | ||||||
| 	blobmsg_add_macaddr(&b, "address", addr); | 	blobmsg_add_macaddr(&b, "address", addr); | ||||||
|  | 	blobmsg_add_string(&b, "ifname", hapd->conf->iface); | ||||||
|  |  | ||||||
| 	ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); | 	ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq) | ||||||
|  | { | ||||||
|  | 	if (!hapd->ubus.obj.has_subscribers) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	blob_buf_init(&b, 0); | ||||||
|  | 	blobmsg_add_string(&b, "ifname", hapd->conf->iface); | ||||||
|  | 	blobmsg_add_u32(&b, "freq", freq); | ||||||
|  | 	blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid)); | ||||||
|  |  | ||||||
|  | 	ubus_notify(ctx, &hapd->ubus.obj, "channel-switch", b.head, -1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta) | ||||||
|  | { | ||||||
|  | 	if (!hapd->ubus.obj.has_subscribers) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	blob_buf_init(&b, 0); | ||||||
|  | 	blobmsg_add_macaddr(&b, "address", sta->addr); | ||||||
|  | 	blobmsg_add_string(&b, "ifname", hapd->conf->iface); | ||||||
|  | 	if (sta->bandwidth[0] || sta->bandwidth[1]) { | ||||||
|  | 		void *r = blobmsg_open_array(&b, "rate-limit"); | ||||||
|  |  | ||||||
|  | 		blobmsg_add_u32(&b, "", sta->bandwidth[0]); | ||||||
|  | 		blobmsg_add_u32(&b, "", sta->bandwidth[1]); | ||||||
|  | 		blobmsg_close_array(&b, r); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ubus_notify(ctx, &hapd->ubus.obj, "sta-authorized", b.head, -1); | ||||||
|  | } | ||||||
|  |  | ||||||
| void hostapd_ubus_notify_beacon_report( | void hostapd_ubus_notify_beacon_report( | ||||||
| 	struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode, | 	struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode, | ||||||
| 	struct rrm_measurement_beacon_report *rep, size_t len) | 	struct rrm_measurement_beacon_report *rep, size_t len) | ||||||
|   | |||||||
							
								
								
									
										1845
									
								
								feeds/ipq95xx/hostapd/src/src/ap/ubus.c.orig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1845
									
								
								feeds/ipq95xx/hostapd/src/src/ap/ubus.c.orig
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -48,6 +48,7 @@ void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vl | |||||||
|  |  | ||||||
| int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req); | int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req); | ||||||
| void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac); | void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac); | ||||||
|  | void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta); | ||||||
| void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd, | void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd, | ||||||
| 				       const u8 *addr, u8 token, u8 rep_mode, | 				       const u8 *addr, u8 token, u8 rep_mode, | ||||||
| 				       struct rrm_measurement_beacon_report *rep, | 				       struct rrm_measurement_beacon_report *rep, | ||||||
| @@ -64,6 +65,7 @@ void hostapd_ubus_free(struct hapd_interfaces *interfaces); | |||||||
| int hostapd_ubus_notify_bss_transition_query( | int hostapd_ubus_notify_bss_transition_query( | ||||||
| 	struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason, | 	struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason, | ||||||
| 	const u8 *candidate_list, u16 candidate_list_len); | 	const u8 *candidate_list, u16 candidate_list_len); | ||||||
|  | void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq); | ||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										813
									
								
								feeds/ipq95xx/hostapd/src/src/ap/ucode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										813
									
								
								feeds/ipq95xx/hostapd/src/src/ap/ucode.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,813 @@ | |||||||
|  | #include <sys/un.h> | ||||||
|  |  | ||||||
|  | #include "utils/includes.h" | ||||||
|  | #include "utils/common.h" | ||||||
|  | #include "utils/ucode.h" | ||||||
|  | #include "hostapd.h" | ||||||
|  | #include "beacon.h" | ||||||
|  | #include "hw_features.h" | ||||||
|  | #include "ap_drv_ops.h" | ||||||
|  | #include "dfs.h" | ||||||
|  | #include "acs.h" | ||||||
|  | #include <libubox/uloop.h> | ||||||
|  |  | ||||||
|  | static uc_resource_type_t *global_type, *bss_type, *iface_type; | ||||||
|  | static struct hapd_interfaces *interfaces; | ||||||
|  | static uc_value_t *global, *bss_registry, *iface_registry; | ||||||
|  | static uc_vm_t *vm; | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | hostapd_ucode_bss_get_uval(struct hostapd_data *hapd) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	if (hapd->ucode.idx) | ||||||
|  | 		return wpa_ucode_registry_get(bss_registry, hapd->ucode.idx); | ||||||
|  |  | ||||||
|  | 	val = uc_resource_new(bss_type, hapd); | ||||||
|  | 	hapd->ucode.idx = wpa_ucode_registry_add(bss_registry, val); | ||||||
|  |  | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | hostapd_ucode_iface_get_uval(struct hostapd_iface *hapd) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	if (hapd->ucode.idx) | ||||||
|  | 		return wpa_ucode_registry_get(iface_registry, hapd->ucode.idx); | ||||||
|  |  | ||||||
|  | 	val = uc_resource_new(iface_type, hapd); | ||||||
|  | 	hapd->ucode.idx = wpa_ucode_registry_add(iface_registry, val); | ||||||
|  |  | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | hostapd_ucode_update_bss_list(struct hostapd_iface *iface, uc_value_t *if_bss, uc_value_t *bss) | ||||||
|  | { | ||||||
|  | 	uc_value_t *list; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	list = ucv_array_new(vm); | ||||||
|  | 	for (i = 0; i < iface->num_bss; i++) { | ||||||
|  | 		struct hostapd_data *hapd = iface->bss[i]; | ||||||
|  | 		uc_value_t *val = hostapd_ucode_bss_get_uval(hapd); | ||||||
|  |  | ||||||
|  | 		ucv_array_set(list, i, ucv_get(ucv_string_new(hapd->conf->iface))); | ||||||
|  | 		ucv_object_add(bss, hapd->conf->iface, ucv_get(val)); | ||||||
|  | 	} | ||||||
|  | 	ucv_object_add(if_bss, iface->phy, ucv_get(list)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | hostapd_ucode_update_interfaces(void) | ||||||
|  | { | ||||||
|  | 	uc_value_t *ifs = ucv_object_new(vm); | ||||||
|  | 	uc_value_t *if_bss = ucv_array_new(vm); | ||||||
|  | 	uc_value_t *bss = ucv_object_new(vm); | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < interfaces->count; i++) { | ||||||
|  | 		struct hostapd_iface *iface = interfaces->iface[i]; | ||||||
|  |  | ||||||
|  | 		ucv_object_add(ifs, iface->phy, ucv_get(hostapd_ucode_iface_get_uval(iface))); | ||||||
|  | 		hostapd_ucode_update_bss_list(iface, if_bss, bss); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ucv_object_add(ucv_prototype_get(global), "interfaces", ucv_get(ifs)); | ||||||
|  | 	ucv_object_add(ucv_prototype_get(global), "interface_bss", ucv_get(if_bss)); | ||||||
|  | 	ucv_object_add(ucv_prototype_get(global), "bss", ucv_get(bss)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_add_iface(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	uc_value_t *iface = uc_fn_arg(0); | ||||||
|  | 	int ret; | ||||||
|  |  | ||||||
|  | 	if (ucv_type(iface) != UC_STRING) | ||||||
|  | 		return ucv_int64_new(-1); | ||||||
|  |  | ||||||
|  | 	ret = hostapd_add_iface(interfaces, ucv_string_get(iface)); | ||||||
|  | 	hostapd_ucode_update_interfaces(); | ||||||
|  |  | ||||||
|  | 	return ucv_int64_new(ret); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_remove_iface(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	uc_value_t *iface = uc_fn_arg(0); | ||||||
|  |  | ||||||
|  | 	if (ucv_type(iface) != UC_STRING) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	hostapd_remove_iface(interfaces, ucv_string_get(iface)); | ||||||
|  | 	hostapd_ucode_update_interfaces(); | ||||||
|  |  | ||||||
|  | 	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) | ||||||
|  | { | ||||||
|  | 	struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss"); | ||||||
|  | 	struct hostapd_bss_config *old_bss; | ||||||
|  | 	struct hostapd_iface *iface; | ||||||
|  | 	struct hostapd_config *conf; | ||||||
|  | 	uc_value_t *file = uc_fn_arg(0); | ||||||
|  | 	uc_value_t *index = uc_fn_arg(1); | ||||||
|  | 	uc_value_t *files_only = uc_fn_arg(2); | ||||||
|  | 	unsigned int i, idx = 0; | ||||||
|  | 	int ret = -1; | ||||||
|  |  | ||||||
|  | 	if (!hapd || ucv_type(file) != UC_STRING) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	if (ucv_type(index) == UC_INTEGER) | ||||||
|  | 		idx = ucv_int64_get(index); | ||||||
|  |  | ||||||
|  | 	iface = hapd->iface; | ||||||
|  | 	conf = interfaces->config_read_cb(ucv_string_get(file)); | ||||||
|  | 	if (!conf) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	if (idx > conf->num_bss || !conf->bss[idx]) | ||||||
|  | 		goto free; | ||||||
|  |  | ||||||
|  | 	if (ucv_boolean_get(files_only)) { | ||||||
|  | 		struct hostapd_bss_config *bss = conf->bss[idx]; | ||||||
|  | 		struct hostapd_bss_config *old_bss = hapd->conf; | ||||||
|  |  | ||||||
|  | #define swap_field(name)				\ | ||||||
|  | 	do {								\ | ||||||
|  | 		void *ptr = old_bss->name;		\ | ||||||
|  | 		old_bss->name = bss->name;		\ | ||||||
|  | 		bss->name = ptr;				\ | ||||||
|  | 	} while (0) | ||||||
|  |  | ||||||
|  | 		swap_field(ssid.wpa_psk_file); | ||||||
|  | 		ret = bss_reload_vlans(hapd, bss); | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hostapd_bss_deinit_no_free(hapd); | ||||||
|  | 	hostapd_drv_stop_ap(hapd); | ||||||
|  | 	hostapd_free_hapd_data(hapd); | ||||||
|  |  | ||||||
|  | 	old_bss = hapd->conf; | ||||||
|  | 	for (i = 0; i < iface->conf->num_bss; i++) | ||||||
|  | 		if (iface->conf->bss[i] == hapd->conf) | ||||||
|  | 			iface->conf->bss[i] = conf->bss[idx]; | ||||||
|  | 	hapd->conf = conf->bss[idx]; | ||||||
|  | 	conf->bss[idx] = old_bss; | ||||||
|  |  | ||||||
|  | 	hostapd_setup_bss(hapd, hapd == iface->bss[0], true); | ||||||
|  | 	hostapd_ucode_update_interfaces(); | ||||||
|  |  | ||||||
|  | done: | ||||||
|  | 	ret = 0; | ||||||
|  | free: | ||||||
|  | 	hostapd_config_free(conf); | ||||||
|  | out: | ||||||
|  | 	return ucv_int64_new(ret); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | hostapd_remove_iface_bss_conf(struct hostapd_config *iconf, | ||||||
|  | 			      struct hostapd_bss_config *conf) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < iconf->num_bss; i++) | ||||||
|  | 		if (iconf->bss[i] == conf) | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 	if (i == iconf->num_bss) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	for (i++; i < iconf->num_bss; i++) | ||||||
|  | 		iconf->bss[i - 1] = iconf->bss[i]; | ||||||
|  | 	iconf->num_bss--; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_bss_delete(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss"); | ||||||
|  | 	struct hostapd_iface *iface; | ||||||
|  | 	int i, idx; | ||||||
|  |  | ||||||
|  | 	if (!hapd) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	iface = hapd->iface; | ||||||
|  | 	if (iface->num_bss == 1) { | ||||||
|  | 		wpa_printf(MSG_ERROR, "trying to delete last bss of an iface: %s\n", hapd->conf->iface); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (idx = 0; idx < iface->num_bss; idx++) | ||||||
|  | 		if (iface->bss[idx] == hapd) | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 	if (idx == iface->num_bss) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	for (i = idx + 1; i < iface->num_bss; i++) | ||||||
|  | 		iface->bss[i - 1] = iface->bss[i]; | ||||||
|  |  | ||||||
|  | 	iface->num_bss--; | ||||||
|  |  | ||||||
|  | 	iface->bss[0]->interface_added = 0; | ||||||
|  | 	hostapd_drv_set_first_bss(iface->bss[0]); | ||||||
|  | 	hapd->interface_added = 1; | ||||||
|  |  | ||||||
|  | 	hostapd_drv_stop_ap(hapd); | ||||||
|  | 	hostapd_bss_deinit(hapd); | ||||||
|  | 	hostapd_remove_iface_bss_conf(iface->conf, hapd->conf); | ||||||
|  | 	hostapd_config_free_bss(hapd->conf); | ||||||
|  | 	os_free(hapd); | ||||||
|  |  | ||||||
|  | 	hostapd_ucode_update_interfaces(); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  |  | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_iface_add_bss(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); | ||||||
|  | 	struct hostapd_bss_config *bss; | ||||||
|  | 	struct hostapd_config *conf; | ||||||
|  | 	struct hostapd_data *hapd; | ||||||
|  | 	uc_value_t *file = uc_fn_arg(0); | ||||||
|  | 	uc_value_t *index = uc_fn_arg(1); | ||||||
|  | 	unsigned int idx = 0; | ||||||
|  | 	uc_value_t *ret = NULL; | ||||||
|  |  | ||||||
|  | 	if (!iface || ucv_type(file) != UC_STRING) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	if (ucv_type(index) == UC_INTEGER) | ||||||
|  | 		idx = ucv_int64_get(index); | ||||||
|  |  | ||||||
|  | 	conf = interfaces->config_read_cb(ucv_string_get(file)); | ||||||
|  | 	if (!conf || idx > conf->num_bss || !conf->bss[idx]) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	bss = conf->bss[idx]; | ||||||
|  | 	hapd = hostapd_alloc_bss_data(iface, iface->conf, bss); | ||||||
|  | 	if (!hapd) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	hapd->driver = iface->bss[0]->driver; | ||||||
|  | 	hapd->drv_priv = iface->bss[0]->drv_priv; | ||||||
|  | 	if (interfaces->ctrl_iface_init && | ||||||
|  | 	    interfaces->ctrl_iface_init(hapd) < 0) | ||||||
|  | 		goto free_hapd; | ||||||
|  |  | ||||||
|  | 	if (iface->state == HAPD_IFACE_ENABLED && | ||||||
|  | 	    hostapd_setup_bss(hapd, -1, true)) | ||||||
|  | 		goto deinit_ctrl; | ||||||
|  |  | ||||||
|  | 	iface->bss = os_realloc_array(iface->bss, iface->num_bss + 1, | ||||||
|  | 				      sizeof(*iface->bss)); | ||||||
|  | 	iface->bss[iface->num_bss++] = hapd; | ||||||
|  |  | ||||||
|  | 	iface->conf->bss = os_realloc_array(iface->conf->bss, | ||||||
|  | 					    iface->conf->num_bss + 1, | ||||||
|  | 					    sizeof(*iface->conf->bss)); | ||||||
|  | 	iface->conf->bss[iface->conf->num_bss] = bss; | ||||||
|  | 	conf->bss[idx] = NULL; | ||||||
|  | 	ret = hostapd_ucode_bss_get_uval(hapd); | ||||||
|  | 	hostapd_ucode_update_interfaces(); | ||||||
|  | 	goto out; | ||||||
|  |  | ||||||
|  | deinit_ctrl: | ||||||
|  | 	if (interfaces->ctrl_iface_deinit) | ||||||
|  | 		interfaces->ctrl_iface_deinit(hapd); | ||||||
|  | free_hapd: | ||||||
|  | 	hostapd_free_hapd_data(hapd); | ||||||
|  | 	os_free(hapd); | ||||||
|  | out: | ||||||
|  | 	hostapd_config_free(conf); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_iface_set_bss_order(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); | ||||||
|  | 	uc_value_t *bss_list = uc_fn_arg(0); | ||||||
|  | 	struct hostapd_data **new_bss; | ||||||
|  | 	struct hostapd_bss_config **new_conf; | ||||||
|  |  | ||||||
|  | 	if (!iface) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	if (ucv_type(bss_list) != UC_ARRAY || | ||||||
|  | 	    ucv_array_length(bss_list) != iface->num_bss) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	new_bss = calloc(iface->num_bss, sizeof(*new_bss)); | ||||||
|  | 	new_conf = calloc(iface->num_bss, sizeof(*new_conf)); | ||||||
|  | 	for (size_t i = 0; i < iface->num_bss; i++) { | ||||||
|  | 		struct hostapd_data *bss; | ||||||
|  |  | ||||||
|  | 		bss = ucv_resource_data(ucv_array_get(bss_list, i), "hostapd.bss"); | ||||||
|  | 		if (bss->iface != iface) | ||||||
|  | 			goto free; | ||||||
|  |  | ||||||
|  | 		for (size_t k = 0; k < i; k++) | ||||||
|  | 			if (new_bss[k] == bss) | ||||||
|  | 				goto free; | ||||||
|  |  | ||||||
|  | 		new_bss[i] = bss; | ||||||
|  | 		new_conf[i] = bss->conf; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	new_bss[0]->interface_added = 0; | ||||||
|  | 	for (size_t i = 1; i < iface->num_bss; i++) | ||||||
|  | 		new_bss[i]->interface_added = 1; | ||||||
|  |  | ||||||
|  | 	free(iface->bss); | ||||||
|  | 	iface->bss = new_bss; | ||||||
|  |  | ||||||
|  | 	free(iface->conf->bss); | ||||||
|  | 	iface->conf->bss = new_conf; | ||||||
|  | 	iface->conf->num_bss = iface->num_bss; | ||||||
|  | 	hostapd_drv_set_first_bss(iface->bss[0]); | ||||||
|  |  | ||||||
|  | 	return ucv_boolean_new(true); | ||||||
|  |  | ||||||
|  | free: | ||||||
|  | 	free(new_bss); | ||||||
|  | 	free(new_conf); | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_bss_ctrl(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss"); | ||||||
|  | 	uc_value_t *arg = uc_fn_arg(0); | ||||||
|  | 	struct sockaddr_storage from = {}; | ||||||
|  | 	static char reply[4096]; | ||||||
|  | 	int reply_len; | ||||||
|  |  | ||||||
|  | 	if (!hapd || !interfaces->ctrl_iface_recv || | ||||||
|  | 	    ucv_type(arg) != UC_STRING) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	reply_len = interfaces->ctrl_iface_recv(hapd, ucv_string_get(arg), | ||||||
|  | 						reply, sizeof(reply), | ||||||
|  | 						&from, sizeof(from)); | ||||||
|  | 	if (reply_len < 0) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	if (reply_len && reply[reply_len - 1] == '\n') | ||||||
|  | 		reply_len--; | ||||||
|  |  | ||||||
|  | 	return ucv_string_new_length(reply, reply_len); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	if (!iface) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	switch (iface->state) { | ||||||
|  | 	case HAPD_IFACE_ENABLED: | ||||||
|  | 	case HAPD_IFACE_DISABLED: | ||||||
|  | 		break; | ||||||
|  | #ifdef CONFIG_ACS | ||||||
|  | 	case HAPD_IFACE_ACS: | ||||||
|  | 		acs_cleanup(iface); | ||||||
|  | 		iface->scan_cb = NULL; | ||||||
|  | 		/* 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]; | ||||||
|  |  | ||||||
|  | 		hostapd_drv_stop_ap(hapd); | ||||||
|  | 		hapd->beacon_set_done = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | 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; | ||||||
|  | 		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; | ||||||
|  | 	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) | ||||||
|  | 		hostapd_set_oper_centr_freq_seg0_idx(conf, intval); | ||||||
|  |  | ||||||
|  | 	intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL)); | ||||||
|  | 	if (!errno) | ||||||
|  | 		hostapd_set_oper_centr_freq_seg1_idx(conf, intval); | ||||||
|  |  | ||||||
|  | 	intval = ucv_int64_get(ucv_object_get(info, "oper_chwidth", NULL)); | ||||||
|  | 	if (!errno) | ||||||
|  | 		hostapd_set_oper_chwidth(conf, intval); | ||||||
|  |  | ||||||
|  | 	intval = ucv_int64_get(ucv_object_get(info, "frequency", NULL)); | ||||||
|  | 	if (!errno) | ||||||
|  | 		iface->freq = intval; | ||||||
|  | 	else | ||||||
|  | 		iface->freq = 0; | ||||||
|  | 	conf->acs = 0; | ||||||
|  |  | ||||||
|  | out: | ||||||
|  | 	switch (iface->state) { | ||||||
|  | 	case HAPD_IFACE_DISABLED: | ||||||
|  | 		break; | ||||||
|  | 	case HAPD_IFACE_ENABLED: | ||||||
|  | 		if (!hostapd_is_dfs_required(iface) || | ||||||
|  | 			hostapd_is_dfs_chan_available(iface)) | ||||||
|  | 			break; | ||||||
|  | 		wpa_printf(MSG_INFO, "DFS CAC required on new channel, restart interface"); | ||||||
|  | 		/* fallthrough */ | ||||||
|  | 	default: | ||||||
|  | 		hostapd_disable_iface(iface); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (conf->channel && !iface->freq) | ||||||
|  | 		iface->freq = hostapd_hw_get_freq(iface->bss[0], conf->channel); | ||||||
|  |  | ||||||
|  | 	if (iface->state != HAPD_IFACE_ENABLED) { | ||||||
|  | 		hostapd_enable_iface(iface); | ||||||
|  | 		return ucv_boolean_new(true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < iface->num_bss; i++) { | ||||||
|  | 		struct hostapd_data *hapd = iface->bss[i]; | ||||||
|  | 		int ret; | ||||||
|  |  | ||||||
|  | 		hapd->conf->start_disabled = 0; | ||||||
|  | 		hostapd_set_freq(hapd, conf->hw_mode, iface->freq, | ||||||
|  | 				 conf->channel, | ||||||
|  | 				 conf->enable_edmg, | ||||||
|  | 				 conf->edmg_channel, | ||||||
|  | 				 conf->ieee80211n, | ||||||
|  | 				 conf->ieee80211ac, | ||||||
|  | 				 conf->ieee80211ax, | ||||||
|  | 				 conf->ieee80211be, | ||||||
|  | 				 conf->secondary_channel, | ||||||
|  | 				 hostapd_get_oper_chwidth(conf), | ||||||
|  | 				 hostapd_get_oper_centr_freq_seg0_idx(conf), | ||||||
|  | 				 hostapd_get_oper_centr_freq_seg1_idx(conf), | ||||||
|  | 				 conf->ru_punct_bitmap, | ||||||
|  | 				 conf->ru_punct_ofdma); | ||||||
|  |  | ||||||
|  | 		ieee802_11_set_beacon(hapd); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return ucv_boolean_new(true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_iface_switch_channel(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; | ||||||
|  | 	struct csa_settings csa = {}; | ||||||
|  | 	uint64_t intval; | ||||||
|  | 	int i, ret = 0; | ||||||
|  |  | ||||||
|  | 	if (!iface || ucv_type(info) != UC_OBJECT) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	conf = iface->conf; | ||||||
|  | 	if ((intval = ucv_int64_get(ucv_object_get(info, "csa_count", NULL))) && !errno) | ||||||
|  | 		csa.cs_count = intval; | ||||||
|  | 	if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno) | ||||||
|  | 		csa.freq_params.sec_channel_offset = intval; | ||||||
|  |  | ||||||
|  | 	csa.freq_params.ht_enabled = conf->ieee80211n; | ||||||
|  | 	csa.freq_params.vht_enabled = conf->ieee80211ac; | ||||||
|  | 	csa.freq_params.he_enabled = conf->ieee80211ax; | ||||||
|  | #ifdef CONFIG_IEEE80211BE | ||||||
|  | 	csa.freq_params.eht_enabled = conf->ieee80211be; | ||||||
|  | #endif | ||||||
|  | 	intval = ucv_int64_get(ucv_object_get(info, "oper_chwidth", NULL)); | ||||||
|  | 	if (errno) | ||||||
|  | 		intval = hostapd_get_oper_chwidth(conf); | ||||||
|  | 	if (intval) | ||||||
|  | 		csa.freq_params.bandwidth = 40 << intval; | ||||||
|  | 	else | ||||||
|  | 		csa.freq_params.bandwidth = csa.freq_params.sec_channel_offset ? 40 : 20; | ||||||
|  |  | ||||||
|  | 	if ((intval = ucv_int64_get(ucv_object_get(info, "frequency", NULL))) && !errno) | ||||||
|  | 		csa.freq_params.freq = intval; | ||||||
|  | 	if ((intval = ucv_int64_get(ucv_object_get(info, "center_freq1", NULL))) && !errno) | ||||||
|  | 		csa.freq_params.center_freq1 = intval; | ||||||
|  | 	if ((intval = ucv_int64_get(ucv_object_get(info, "center_freq2", NULL))) && !errno) | ||||||
|  | 		csa.freq_params.center_freq2 = intval; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < iface->num_bss; i++) | ||||||
|  | 		ret = hostapd_switch_channel(iface->bss[i], &csa); | ||||||
|  |  | ||||||
|  | 	return ucv_boolean_new(!ret); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_hostapd_bss_rename(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss"); | ||||||
|  | 	uc_value_t *ifname_arg = uc_fn_arg(0); | ||||||
|  | 	char prev_ifname[IFNAMSIZ + 1]; | ||||||
|  | 	struct sta_info *sta; | ||||||
|  | 	const char *ifname; | ||||||
|  | 	int ret; | ||||||
|  |  | ||||||
|  | 	if (!hapd || ucv_type(ifname_arg) != UC_STRING) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	os_strlcpy(prev_ifname, hapd->conf->iface, sizeof(prev_ifname)); | ||||||
|  | 	ifname = ucv_string_get(ifname_arg); | ||||||
|  |  | ||||||
|  | 	hostapd_ubus_free_bss(hapd); | ||||||
|  | 	if (interfaces->ctrl_iface_deinit) | ||||||
|  | 		interfaces->ctrl_iface_deinit(hapd); | ||||||
|  |  | ||||||
|  | 	ret = hostapd_drv_if_rename(hapd, WPA_IF_AP_BSS, NULL, ifname); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	for (sta = hapd->sta_list; sta; sta = sta->next) { | ||||||
|  | 		char cur_name[IFNAMSIZ + 1], new_name[IFNAMSIZ + 1]; | ||||||
|  |  | ||||||
|  | 		if (!(sta->flags & WLAN_STA_WDS) || sta->pending_wds_enable) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		snprintf(cur_name, sizeof(cur_name), "%s.sta%d", prev_ifname, sta->aid); | ||||||
|  | 		snprintf(new_name, sizeof(new_name), "%s.sta%d", ifname, sta->aid); | ||||||
|  | 		hostapd_drv_if_rename(hapd, WPA_IF_AP_VLAN, cur_name, new_name); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!strncmp(hapd->conf->ssid.vlan, hapd->conf->iface, sizeof(hapd->conf->ssid.vlan))) | ||||||
|  | 		os_strlcpy(hapd->conf->ssid.vlan, ifname, sizeof(hapd->conf->ssid.vlan)); | ||||||
|  | 	os_strlcpy(hapd->conf->iface, ifname, sizeof(hapd->conf->iface)); | ||||||
|  | 	hostapd_ubus_add_bss(hapd); | ||||||
|  |  | ||||||
|  | 	hostapd_ucode_update_interfaces(); | ||||||
|  | out: | ||||||
|  | 	if (interfaces->ctrl_iface_init) | ||||||
|  | 		interfaces->ctrl_iface_init(hapd); | ||||||
|  |  | ||||||
|  | 	return ret ? NULL : ucv_boolean_new(true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int hostapd_ucode_init(struct hapd_interfaces *ifaces) | ||||||
|  | { | ||||||
|  | 	static const uc_function_list_t global_fns[] = { | ||||||
|  | 		{ "printf",	uc_wpa_printf }, | ||||||
|  | 		{ "getpid", uc_wpa_getpid }, | ||||||
|  | 		{ "sha1", uc_wpa_sha1 }, | ||||||
|  | 		{ "freq_info", uc_wpa_freq_info }, | ||||||
|  | 		{ "add_iface", uc_hostapd_add_iface }, | ||||||
|  | 		{ "remove_iface", uc_hostapd_remove_iface }, | ||||||
|  | 	}; | ||||||
|  | 	static const uc_function_list_t bss_fns[] = { | ||||||
|  | 		{ "ctrl", uc_hostapd_bss_ctrl }, | ||||||
|  | 		{ "set_config", uc_hostapd_bss_set_config }, | ||||||
|  | 		{ "rename", uc_hostapd_bss_rename }, | ||||||
|  | 		{ "delete", uc_hostapd_bss_delete }, | ||||||
|  | 	}; | ||||||
|  | 	static const uc_function_list_t iface_fns[] = { | ||||||
|  | 		{ "set_bss_order", uc_hostapd_iface_set_bss_order }, | ||||||
|  | 		{ "add_bss", uc_hostapd_iface_add_bss }, | ||||||
|  | 		{ "stop", uc_hostapd_iface_stop }, | ||||||
|  | 		{ "start", uc_hostapd_iface_start }, | ||||||
|  | 		{ "switch_channel", uc_hostapd_iface_switch_channel }, | ||||||
|  | 	}; | ||||||
|  | 	uc_value_t *data, *proto; | ||||||
|  |  | ||||||
|  | 	interfaces = ifaces; | ||||||
|  | 	vm = wpa_ucode_create_vm(); | ||||||
|  |  | ||||||
|  | 	global_type = uc_type_declare(vm, "hostapd.global", global_fns, NULL); | ||||||
|  | 	bss_type = uc_type_declare(vm, "hostapd.bss", bss_fns, NULL); | ||||||
|  | 	iface_type = uc_type_declare(vm, "hostapd.iface", iface_fns, NULL); | ||||||
|  |  | ||||||
|  | 	bss_registry = ucv_array_new(vm); | ||||||
|  | 	uc_vm_registry_set(vm, "hostap.bss_registry", bss_registry); | ||||||
|  |  | ||||||
|  | 	iface_registry = ucv_array_new(vm); | ||||||
|  | 	uc_vm_registry_set(vm, "hostap.iface_registry", iface_registry); | ||||||
|  |  | ||||||
|  | 	global = wpa_ucode_global_init("hostapd", global_type); | ||||||
|  |  | ||||||
|  | 	if (wpa_ucode_run(HOSTAPD_UC_PATH "hostapd.uc")) | ||||||
|  | 		goto free_vm; | ||||||
|  | 	ucv_gc(vm); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  |  | ||||||
|  | free_vm: | ||||||
|  | 	wpa_ucode_free_vm(); | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void hostapd_ucode_free(void) | ||||||
|  | { | ||||||
|  | 	if (wpa_ucode_call_prepare("shutdown") == 0) | ||||||
|  | 		ucv_put(wpa_ucode_call(0)); | ||||||
|  | 	wpa_ucode_free_vm(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void hostapd_ucode_free_iface(struct hostapd_iface *iface) | ||||||
|  | { | ||||||
|  | 	wpa_ucode_registry_remove(iface_registry, iface->ucode.idx); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void hostapd_ucode_add_bss(struct hostapd_data *hapd) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	if (wpa_ucode_call_prepare("bss_add")) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	val = hostapd_ucode_bss_get_uval(hapd); | ||||||
|  | 	uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); | ||||||
|  | 	uc_value_push(ucv_get(val)); | ||||||
|  | 	ucv_put(wpa_ucode_call(2)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void hostapd_ucode_reload_bss(struct hostapd_data *hapd) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	if (wpa_ucode_call_prepare("bss_reload")) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	val = hostapd_ucode_bss_get_uval(hapd); | ||||||
|  | 	uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); | ||||||
|  | 	uc_value_push(ucv_get(val)); | ||||||
|  | 	ucv_put(wpa_ucode_call(2)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void hostapd_ucode_free_bss(struct hostapd_data *hapd) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	val = wpa_ucode_registry_remove(bss_registry, hapd->ucode.idx); | ||||||
|  | 	if (!val) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	hapd->ucode.idx = 0; | ||||||
|  | 	if (wpa_ucode_call_prepare("bss_remove")) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	uc_value_push(ucv_string_new(hapd->conf->iface)); | ||||||
|  | 	uc_value_push(ucv_get(val)); | ||||||
|  | 	ucv_put(wpa_ucode_call(2)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								feeds/ipq95xx/hostapd/src/src/ap/ucode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								feeds/ipq95xx/hostapd/src/src/ap/ucode.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | #ifndef __HOSTAPD_AP_UCODE_H | ||||||
|  | #define __HOSTAPD_AP_UCODE_H | ||||||
|  |  | ||||||
|  | #include "utils/ucode.h" | ||||||
|  |  | ||||||
|  | struct hostapd_data; | ||||||
|  |  | ||||||
|  | struct hostapd_ucode_bss { | ||||||
|  | #ifdef UCODE_SUPPORT | ||||||
|  | 	int idx; | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct hostapd_ucode_iface { | ||||||
|  | #ifdef UCODE_SUPPORT | ||||||
|  | 	int idx; | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #ifdef UCODE_SUPPORT | ||||||
|  |  | ||||||
|  | int hostapd_ucode_init(struct hapd_interfaces *ifaces); | ||||||
|  |  | ||||||
|  | void hostapd_ucode_free(void); | ||||||
|  | void hostapd_ucode_free_iface(struct hostapd_iface *iface); | ||||||
|  | void hostapd_ucode_add_bss(struct hostapd_data *hapd); | ||||||
|  | void hostapd_ucode_free_bss(struct hostapd_data *hapd); | ||||||
|  | void hostapd_ucode_reload_bss(struct hostapd_data *hapd); | ||||||
|  |  | ||||||
|  | #else | ||||||
|  |  | ||||||
|  | static inline int hostapd_ucode_init(struct hapd_interfaces *ifaces) | ||||||
|  | { | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
|  | static inline void hostapd_ucode_free(void) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | static inline void hostapd_ucode_free_iface(struct hostapd_iface *iface) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | static inline void hostapd_ucode_reload_bss(struct hostapd_data *hapd) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | static inline void hostapd_ucode_add_bss(struct hostapd_data *hapd) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | static inline void hostapd_ucode_free_bss(struct hostapd_data *hapd) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -7,10 +7,6 @@ static inline int has_feature(const char *feat) | |||||||
| 	if (!strcmp(feat, "eap")) | 	if (!strcmp(feat, "eap")) | ||||||
| 		return 1; | 		return 1; | ||||||
| #endif | #endif | ||||||
| #ifdef CONFIG_IEEE80211N |  | ||||||
| 	if (!strcmp(feat, "11n")) |  | ||||||
| 		return 1; |  | ||||||
| #endif |  | ||||||
| #ifdef CONFIG_IEEE80211AC | #ifdef CONFIG_IEEE80211AC | ||||||
| 	if (!strcmp(feat, "11ac")) | 	if (!strcmp(feat, "11ac")) | ||||||
| 		return 1; | 		return 1; | ||||||
| @@ -50,6 +46,18 @@ static inline int has_feature(const char *feat) | |||||||
| #ifdef CONFIG_WPS | #ifdef CONFIG_WPS | ||||||
| 	if (!strcmp(feat, "wps")) | 	if (!strcmp(feat, "wps")) | ||||||
| 		return 1; | 		return 1; | ||||||
|  | #endif | ||||||
|  | #ifdef CONFIG_FILS | ||||||
|  | 	if (!strcmp(feat, "fils")) | ||||||
|  | 		return 1; | ||||||
|  | #endif | ||||||
|  | #ifdef CONFIG_OCV | ||||||
|  | 	if (!strcmp(feat, "ocv")) | ||||||
|  | 		return 1; | ||||||
|  | #endif | ||||||
|  | #ifdef CONFIG_MESH | ||||||
|  | 	if (!strcmp(feat, "mesh")) | ||||||
|  | 		return 1; | ||||||
| #endif | #endif | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										335
									
								
								feeds/ipq95xx/hostapd/src/src/utils/ucode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								feeds/ipq95xx/hostapd/src/src/utils/ucode.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,335 @@ | |||||||
|  | #include <unistd.h> | ||||||
|  | #include "ucode.h" | ||||||
|  | #include "utils/eloop.h" | ||||||
|  | #include "crypto/crypto.h" | ||||||
|  | #include "crypto/sha1.h" | ||||||
|  | #include "common/ieee802_11_common.h" | ||||||
|  | #include <libubox/uloop.h> | ||||||
|  | #include <ucode/compiler.h> | ||||||
|  |  | ||||||
|  | static uc_value_t *registry; | ||||||
|  | static uc_vm_t vm; | ||||||
|  | static struct uloop_timeout gc_timer; | ||||||
|  |  | ||||||
|  | static void uc_gc_timer(struct uloop_timeout *timeout) | ||||||
|  | { | ||||||
|  | 	ucv_gc(&vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uc_value_t *uc_wpa_printf(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	uc_value_t *level = uc_fn_arg(0); | ||||||
|  | 	uc_value_t *ret, **args; | ||||||
|  | 	uc_cfn_ptr_t _sprintf; | ||||||
|  | 	int l = MSG_INFO; | ||||||
|  | 	int i, start = 0; | ||||||
|  |  | ||||||
|  | 	_sprintf = uc_stdlib_function("sprintf"); | ||||||
|  | 	if (!sprintf) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	if (ucv_type(level) == UC_INTEGER) { | ||||||
|  | 		l = ucv_int64_get(level); | ||||||
|  | 		start++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (nargs <= start) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	ret = _sprintf(vm, nargs - start); | ||||||
|  | 	if (ucv_type(ret) != UC_STRING) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	wpa_printf(l, "%s", ucv_string_get(ret)); | ||||||
|  | 	ucv_put(ret); | ||||||
|  |  | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	uc_value_t *freq = uc_fn_arg(0); | ||||||
|  | 	uc_value_t *sec = uc_fn_arg(1); | ||||||
|  | 	int width = ucv_uint64_get(uc_fn_arg(2)); | ||||||
|  | 	int freq_val, center_idx, center_ofs; | ||||||
|  | 	enum hostapd_hw_mode hw_mode; | ||||||
|  | 	u8 op_class, channel, tmp_channel; | ||||||
|  | 	const char *modestr; | ||||||
|  | 	int sec_channel = 0; | ||||||
|  | 	uc_value_t *ret; | ||||||
|  | 	int chanwidth; | ||||||
|  |  | ||||||
|  | 	if (ucv_type(freq) != UC_INTEGER) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	freq_val = ucv_int64_get(freq); | ||||||
|  | 	if (ucv_type(sec) == UC_INTEGER) | ||||||
|  | 		sec_channel = ucv_int64_get(sec); | ||||||
|  | 	else if (sec) | ||||||
|  | 		return NULL; | ||||||
|  | 	else if (freq_val > 4000) | ||||||
|  | 		sec_channel = (freq_val / 20) & 1 ? 1 : -1; | ||||||
|  | 	else | ||||||
|  | 		sec_channel = freq_val < 2442 ? 1 : -1; | ||||||
|  |  | ||||||
|  | 	if (sec_channel != -1 && sec_channel != 1 && sec_channel != 0) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	switch (width) { | ||||||
|  | 	case 0: | ||||||
|  | 		chanwidth = CHANWIDTH_USE_HT; | ||||||
|  | 		break; | ||||||
|  | 	case 1: | ||||||
|  | 		chanwidth = CHANWIDTH_80MHZ; | ||||||
|  | 		break; | ||||||
|  | 	case 2: | ||||||
|  | 		chanwidth = CHANWIDTH_160MHZ; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hw_mode = ieee80211_freq_to_channel_ext(freq_val, sec_channel, | ||||||
|  | 						chanwidth, &op_class, &channel); | ||||||
|  | 	switch (hw_mode) { | ||||||
|  | 	case HOSTAPD_MODE_IEEE80211B: | ||||||
|  | 		modestr = "b"; | ||||||
|  | 		break; | ||||||
|  | 	case HOSTAPD_MODE_IEEE80211G: | ||||||
|  | 		modestr = "g"; | ||||||
|  | 		break; | ||||||
|  | 	case HOSTAPD_MODE_IEEE80211A: | ||||||
|  | 		modestr = "a"; | ||||||
|  | 		break; | ||||||
|  | 	case HOSTAPD_MODE_IEEE80211AD: | ||||||
|  | 		modestr = "ad"; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ret = ucv_object_new(vm); | ||||||
|  | 	ucv_object_add(ret, "op_class", ucv_int64_new(op_class)); | ||||||
|  | 	ucv_object_add(ret, "channel", ucv_int64_new(channel)); | ||||||
|  | 	ucv_object_add(ret, "hw_mode", ucv_int64_new(hw_mode)); | ||||||
|  | 	ucv_object_add(ret, "hw_mode_str", ucv_get(ucv_string_new(modestr))); | ||||||
|  | 	ucv_object_add(ret, "sec_channel", ucv_int64_new(sec_channel)); | ||||||
|  | 	ucv_object_add(ret, "frequency", ucv_int64_new(freq_val)); | ||||||
|  |  | ||||||
|  | 	if (!sec_channel) | ||||||
|  | 		return ret; | ||||||
|  |  | ||||||
|  | 	if (freq_val >= 5900) | ||||||
|  | 		center_ofs = 0; | ||||||
|  | 	else if (freq_val >= 5745) | ||||||
|  | 		center_ofs = 20; | ||||||
|  | 	else | ||||||
|  | 		center_ofs = 35; | ||||||
|  | 	tmp_channel = channel - center_ofs; | ||||||
|  | 	tmp_channel &= ~((8 << width) - 1); | ||||||
|  | 	center_idx = tmp_channel + center_ofs + (4 << width) - 1; | ||||||
|  |  | ||||||
|  | 	if (freq_val < 3000) | ||||||
|  | 		ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(0)); | ||||||
|  | 	else | ||||||
|  | 		ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(center_idx)); | ||||||
|  | 	center_idx = (center_idx - channel) * 5 + freq_val; | ||||||
|  | 	ucv_object_add(ret, "center_freq1", ucv_int64_new(center_idx)); | ||||||
|  |  | ||||||
|  | out: | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uc_value_t *uc_wpa_getpid(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	return ucv_int64_new(getpid()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uc_value_t *uc_wpa_sha1(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	u8 hash[SHA1_MAC_LEN]; | ||||||
|  | 	char hash_hex[2 * ARRAY_SIZE(hash) + 1]; | ||||||
|  | 	uc_value_t *val; | ||||||
|  | 	size_t *lens; | ||||||
|  | 	const u8 **args; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	if (!nargs) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	args = alloca(nargs * sizeof(*args)); | ||||||
|  | 	lens = alloca(nargs * sizeof(*lens)); | ||||||
|  | 	for (i = 0; i < nargs; i++) { | ||||||
|  | 		val = uc_fn_arg(i); | ||||||
|  | 		if (ucv_type(val) != UC_STRING) | ||||||
|  | 			return NULL; | ||||||
|  |  | ||||||
|  | 		args[i] = ucv_string_get(val); | ||||||
|  | 		lens[i] = ucv_string_length(val); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (sha1_vector(nargs, args, lens, hash)) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < ARRAY_SIZE(hash); i++) | ||||||
|  | 		sprintf(hash_hex + 2 * i, "%02x", hash[i]); | ||||||
|  |  | ||||||
|  | 	return ucv_string_new_length(hash_hex, 2 * ARRAY_SIZE(hash)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uc_vm_t *wpa_ucode_create_vm(void) | ||||||
|  | { | ||||||
|  | 	static uc_parse_config_t config = { | ||||||
|  | 		.strict_declarations = true, | ||||||
|  | 		.lstrip_blocks = true, | ||||||
|  | 		.trim_blocks = true, | ||||||
|  | 		.raw_mode = true | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	uc_search_path_init(&config.module_search_path); | ||||||
|  | 	uc_search_path_add(&config.module_search_path, HOSTAPD_UC_PATH "*.so"); | ||||||
|  | 	uc_search_path_add(&config.module_search_path, HOSTAPD_UC_PATH "*.uc"); | ||||||
|  |  | ||||||
|  | 	uc_vm_init(&vm, &config); | ||||||
|  |  | ||||||
|  | 	uc_stdlib_load(uc_vm_scope_get(&vm)); | ||||||
|  | 	eloop_add_uloop(); | ||||||
|  | 	gc_timer.cb = uc_gc_timer; | ||||||
|  |  | ||||||
|  | 	return &vm; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int wpa_ucode_run(const char *script) | ||||||
|  | { | ||||||
|  | 	uc_source_t *source; | ||||||
|  | 	uc_program_t *prog; | ||||||
|  | 	uc_value_t *ops; | ||||||
|  | 	char *err; | ||||||
|  | 	int ret; | ||||||
|  |  | ||||||
|  | 	source = uc_source_new_file(script); | ||||||
|  | 	if (!source) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	prog = uc_compile(vm.config, source, &err); | ||||||
|  | 	uc_source_put(source); | ||||||
|  | 	if (!prog) { | ||||||
|  | 		wpa_printf(MSG_ERROR, "Error loading ucode: %s\n", err); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ret = uc_vm_execute(&vm, prog, &ops); | ||||||
|  | 	uc_program_put(prog); | ||||||
|  | 	if (ret || !ops) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	registry = ucv_array_new(&vm); | ||||||
|  | 	uc_vm_registry_set(&vm, "hostap.registry", registry); | ||||||
|  | 	ucv_array_set(registry, 0, ucv_get(ops)); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int wpa_ucode_call_prepare(const char *fname) | ||||||
|  | { | ||||||
|  | 	uc_value_t *obj, *func; | ||||||
|  |  | ||||||
|  | 	if (!registry) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	obj = ucv_array_get(registry, 0); | ||||||
|  | 	if (!obj) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	func = ucv_object_get(obj, fname, NULL); | ||||||
|  | 	if (!ucv_is_callable(func)) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	uc_vm_stack_push(&vm, ucv_get(obj)); | ||||||
|  | 	uc_vm_stack_push(&vm, ucv_get(func)); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uc_value_t *wpa_ucode_global_init(const char *name, uc_resource_type_t *global_type) | ||||||
|  | { | ||||||
|  | 	uc_value_t *global = uc_resource_new(global_type, NULL); | ||||||
|  | 	uc_value_t *proto; | ||||||
|  |  | ||||||
|  | 	uc_vm_registry_set(&vm, "hostap.global", global); | ||||||
|  | 	proto = ucv_prototype_get(global); | ||||||
|  | 	ucv_object_add(proto, "data", ucv_get(ucv_object_new(&vm))); | ||||||
|  |  | ||||||
|  | #define ADD_CONST(x) ucv_object_add(proto, #x, ucv_int64_new(x)) | ||||||
|  | 	ADD_CONST(MSG_EXCESSIVE); | ||||||
|  | 	ADD_CONST(MSG_MSGDUMP); | ||||||
|  | 	ADD_CONST(MSG_DEBUG); | ||||||
|  | 	ADD_CONST(MSG_INFO); | ||||||
|  | 	ADD_CONST(MSG_WARNING); | ||||||
|  | 	ADD_CONST(MSG_ERROR); | ||||||
|  | #undef ADD_CONST | ||||||
|  |  | ||||||
|  | 	ucv_object_add(uc_vm_scope_get(&vm), name, ucv_get(global)); | ||||||
|  |  | ||||||
|  | 	return global; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val) | ||||||
|  | { | ||||||
|  | 	uc_value_t *data; | ||||||
|  | 	int i = 0; | ||||||
|  |  | ||||||
|  | 	while (ucv_array_get(reg, i)) | ||||||
|  | 		i++; | ||||||
|  |  | ||||||
|  | 	ucv_array_set(reg, i, ucv_get(val)); | ||||||
|  |  | ||||||
|  | 	return i + 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx) | ||||||
|  | { | ||||||
|  | 	if (!idx) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	return ucv_array_get(reg, idx - 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val = wpa_ucode_registry_get(reg, idx); | ||||||
|  | 	void **dataptr; | ||||||
|  |  | ||||||
|  | 	if (!val) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	ucv_array_set(reg, idx - 1, NULL); | ||||||
|  | 	dataptr = ucv_resource_dataptr(val, NULL); | ||||||
|  | 	if (dataptr) | ||||||
|  | 		*dataptr = NULL; | ||||||
|  |  | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | uc_value_t *wpa_ucode_call(size_t nargs) | ||||||
|  | { | ||||||
|  | 	if (uc_vm_call(&vm, true, nargs) != EXCEPTION_NONE) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	if (!gc_timer.pending) | ||||||
|  | 		uloop_timeout_set(&gc_timer, 10); | ||||||
|  |  | ||||||
|  | 	return uc_vm_stack_pop(&vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void wpa_ucode_free_vm(void) | ||||||
|  | { | ||||||
|  | 	if (!vm.config) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	uc_search_path_free(&vm.config->module_search_path); | ||||||
|  | 	uc_vm_free(&vm); | ||||||
|  | 	registry = NULL; | ||||||
|  | 	vm = (uc_vm_t){}; | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								feeds/ipq95xx/hostapd/src/src/utils/ucode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								feeds/ipq95xx/hostapd/src/src/utils/ucode.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | #ifndef __HOSTAPD_UTILS_UCODE_H | ||||||
|  | #define __HOSTAPD_UTILS_UCODE_H | ||||||
|  |  | ||||||
|  | #include "utils/includes.h" | ||||||
|  | #include "utils/common.h" | ||||||
|  | #include <ucode/lib.h> | ||||||
|  | #include <ucode/vm.h> | ||||||
|  |  | ||||||
|  | #define HOSTAPD_UC_PATH	"/usr/share/hostap/" | ||||||
|  |  | ||||||
|  | extern uc_value_t *uc_registry; | ||||||
|  | uc_vm_t *wpa_ucode_create_vm(void); | ||||||
|  | int wpa_ucode_run(const char *script); | ||||||
|  | int wpa_ucode_call_prepare(const char *fname); | ||||||
|  | uc_value_t *wpa_ucode_call(size_t nargs); | ||||||
|  | void wpa_ucode_free_vm(void); | ||||||
|  |  | ||||||
|  | uc_value_t *wpa_ucode_global_init(const char *name, uc_resource_type_t *global_type); | ||||||
|  |  | ||||||
|  | int wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val); | ||||||
|  | uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx); | ||||||
|  | uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx); | ||||||
|  |  | ||||||
|  | uc_value_t *uc_wpa_printf(uc_vm_t *vm, size_t nargs); | ||||||
|  | uc_value_t *uc_wpa_getpid(uc_vm_t *vm, size_t nargs); | ||||||
|  | uc_value_t *uc_wpa_sha1(uc_vm_t *vm, size_t nargs); | ||||||
|  | uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -30,12 +30,6 @@ static inline struct wpa_supplicant *get_wpas_from_object(struct ubus_object *ob | |||||||
| 	return container_of(obj, struct wpa_supplicant, ubus.obj); | 	return container_of(obj, struct wpa_supplicant, ubus.obj); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ubus_receive(int sock, void *eloop_ctx, void *sock_ctx) |  | ||||||
| { |  | ||||||
| 	struct ubus_context *ctx = eloop_ctx; |  | ||||||
| 	ubus_handle_event(ctx); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) | static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) | ||||||
| { | { | ||||||
| 	if (ubus_reconnect(ctx, NULL)) { | 	if (ubus_reconnect(ctx, NULL)) { | ||||||
| @@ -43,12 +37,12 @@ static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) | |||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL); | 	ubus_add_uloop(ctx); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void wpas_ubus_connection_lost(struct ubus_context *ctx) | static void wpas_ubus_connection_lost(struct ubus_context *ctx) | ||||||
| { | { | ||||||
| 	eloop_unregister_read_sock(ctx->sock.fd); | 	uloop_fd_delete(&ctx->sock); | ||||||
| 	eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); | 	eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -57,12 +51,14 @@ static bool wpas_ubus_init(void) | |||||||
| 	if (ctx) | 	if (ctx) | ||||||
| 		return true; | 		return true; | ||||||
|  |  | ||||||
|  | 	eloop_add_uloop(); | ||||||
| 	ctx = ubus_connect(NULL); | 	ctx = ubus_connect(NULL); | ||||||
| 	if (!ctx) | 	if (!ctx) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 	ctx->connection_lost = wpas_ubus_connection_lost; | 	ctx->connection_lost = wpas_ubus_connection_lost; | ||||||
| 	eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL); | 	ubus_add_uloop(ctx); | ||||||
|  |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -80,7 +76,7 @@ static void wpas_ubus_ref_dec(void) | |||||||
| 	if (ctx_ref) | 	if (ctx_ref) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	eloop_unregister_read_sock(ctx->sock.fd); | 	uloop_fd_delete(&ctx->sock); | ||||||
| 	ubus_free(ctx); | 	ubus_free(ctx); | ||||||
| 	ctx = NULL; | 	ctx = NULL; | ||||||
| } | } | ||||||
| @@ -211,152 +207,6 @@ void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s) | |||||||
| 	free(name); | 	free(name); | ||||||
| } | } | ||||||
|  |  | ||||||
| enum { |  | ||||||
| 	WPAS_CONFIG_DRIVER, |  | ||||||
| 	WPAS_CONFIG_IFACE, |  | ||||||
| 	WPAS_CONFIG_BRIDGE, |  | ||||||
| 	WPAS_CONFIG_HOSTAPD_CTRL, |  | ||||||
| 	WPAS_CONFIG_CTRL, |  | ||||||
| 	WPAS_CONFIG_FILE, |  | ||||||
| 	__WPAS_CONFIG_MAX |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static const struct blobmsg_policy wpas_config_add_policy[__WPAS_CONFIG_MAX] = { |  | ||||||
| 	[WPAS_CONFIG_DRIVER] = { "driver", BLOBMSG_TYPE_STRING }, |  | ||||||
| 	[WPAS_CONFIG_IFACE] = { "iface", BLOBMSG_TYPE_STRING }, |  | ||||||
| 	[WPAS_CONFIG_BRIDGE] = { "bridge", BLOBMSG_TYPE_STRING }, |  | ||||||
| 	[WPAS_CONFIG_HOSTAPD_CTRL] = { "hostapd_ctrl", BLOBMSG_TYPE_STRING }, |  | ||||||
| 	[WPAS_CONFIG_CTRL] = { "ctrl", BLOBMSG_TYPE_STRING }, |  | ||||||
| 	[WPAS_CONFIG_FILE] = { "config", BLOBMSG_TYPE_STRING }, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| wpas_config_add(struct ubus_context *ctx, struct ubus_object *obj, |  | ||||||
| 		struct ubus_request_data *req, const char *method, |  | ||||||
| 		struct blob_attr *msg) |  | ||||||
| { |  | ||||||
| 	struct blob_attr *tb[__WPAS_CONFIG_MAX]; |  | ||||||
| 	struct wpa_global *global = get_wpa_global_from_object(obj); |  | ||||||
| 	struct wpa_interface *iface; |  | ||||||
|  |  | ||||||
| 	blobmsg_parse(wpas_config_add_policy, __WPAS_CONFIG_MAX, tb, blob_data(msg), blob_len(msg)); |  | ||||||
|  |  | ||||||
| 	if (!tb[WPAS_CONFIG_FILE] || !tb[WPAS_CONFIG_IFACE] || !tb[WPAS_CONFIG_DRIVER]) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	iface = os_zalloc(sizeof(struct wpa_interface)); |  | ||||||
| 	if (iface == NULL) |  | ||||||
| 		return UBUS_STATUS_UNKNOWN_ERROR; |  | ||||||
|  |  | ||||||
| 	iface->driver = blobmsg_get_string(tb[WPAS_CONFIG_DRIVER]); |  | ||||||
| 	iface->ifname = blobmsg_get_string(tb[WPAS_CONFIG_IFACE]); |  | ||||||
| 	iface->confname = blobmsg_get_string(tb[WPAS_CONFIG_FILE]); |  | ||||||
|  |  | ||||||
| 	if (tb[WPAS_CONFIG_BRIDGE]) |  | ||||||
| 		iface->bridge_ifname = blobmsg_get_string(tb[WPAS_CONFIG_BRIDGE]); |  | ||||||
|  |  | ||||||
| 	if (tb[WPAS_CONFIG_CTRL]) |  | ||||||
| 		iface->ctrl_interface = blobmsg_get_string(tb[WPAS_CONFIG_CTRL]); |  | ||||||
|  |  | ||||||
| 	if (tb[WPAS_CONFIG_HOSTAPD_CTRL]) |  | ||||||
| 		iface->hostapd_ctrl = blobmsg_get_string(tb[WPAS_CONFIG_HOSTAPD_CTRL]); |  | ||||||
|  |  | ||||||
| 	if (!wpa_supplicant_add_iface(global, iface, NULL)) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	blob_buf_init(&b, 0); |  | ||||||
| 	blobmsg_add_u32(&b, "pid", getpid()); |  | ||||||
| 	ubus_send_reply(ctx, req, b.head); |  | ||||||
|  |  | ||||||
| 	return UBUS_STATUS_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| enum { |  | ||||||
| 	WPAS_CONFIG_REM_IFACE, |  | ||||||
| 	__WPAS_CONFIG_REM_MAX |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static const struct blobmsg_policy wpas_config_remove_policy[__WPAS_CONFIG_REM_MAX] = { |  | ||||||
| 	[WPAS_CONFIG_REM_IFACE] = { "iface", BLOBMSG_TYPE_STRING }, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| wpas_config_remove(struct ubus_context *ctx, struct ubus_object *obj, |  | ||||||
| 		   struct ubus_request_data *req, const char *method, |  | ||||||
| 		   struct blob_attr *msg) |  | ||||||
| { |  | ||||||
| 	struct blob_attr *tb[__WPAS_CONFIG_REM_MAX]; |  | ||||||
| 	struct wpa_global *global = get_wpa_global_from_object(obj); |  | ||||||
| 	struct wpa_supplicant *wpa_s = NULL; |  | ||||||
| 	unsigned int found = 0; |  | ||||||
|  |  | ||||||
| 	blobmsg_parse(wpas_config_remove_policy, __WPAS_CONFIG_REM_MAX, tb, blob_data(msg), blob_len(msg)); |  | ||||||
|  |  | ||||||
| 	if (!tb[WPAS_CONFIG_REM_IFACE]) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	/* find wpa_s object for to-be-removed interface */ |  | ||||||
| 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { |  | ||||||
| 		if (!strncmp(wpa_s->ifname, |  | ||||||
| 			     blobmsg_get_string(tb[WPAS_CONFIG_REM_IFACE]), |  | ||||||
| 			     sizeof(wpa_s->ifname))) |  | ||||||
| 		{ |  | ||||||
| 			found = 1; |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (!found) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	if (wpa_supplicant_remove_iface(global, wpa_s, 0)) |  | ||||||
| 		return UBUS_STATUS_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
| 	return UBUS_STATUS_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static const struct ubus_method wpas_daemon_methods[] = { |  | ||||||
| 	UBUS_METHOD("config_add", wpas_config_add, wpas_config_add_policy), |  | ||||||
| 	UBUS_METHOD("config_remove", wpas_config_remove, wpas_config_remove_policy), |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static struct ubus_object_type wpas_daemon_object_type = |  | ||||||
| 	UBUS_OBJECT_TYPE("wpa_supplicant", wpas_daemon_methods); |  | ||||||
|  |  | ||||||
| void wpas_ubus_add(struct wpa_global *global) |  | ||||||
| { |  | ||||||
| 	struct ubus_object *obj = &global->ubus_global; |  | ||||||
| 	int ret; |  | ||||||
|  |  | ||||||
| 	if (!wpas_ubus_init()) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	obj->name = strdup("wpa_supplicant"); |  | ||||||
|  |  | ||||||
| 	obj->type = &wpas_daemon_object_type; |  | ||||||
| 	obj->methods = wpas_daemon_object_type.methods; |  | ||||||
| 	obj->n_methods = wpas_daemon_object_type.n_methods; |  | ||||||
| 	ret = ubus_add_object(ctx, obj); |  | ||||||
| 	wpas_ubus_ref_inc(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void wpas_ubus_free(struct wpa_global *global) |  | ||||||
| { |  | ||||||
| 	struct ubus_object *obj = &global->ubus_global; |  | ||||||
| 	char *name = (char *) obj->name; |  | ||||||
|  |  | ||||||
| 	if (!ctx) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	if (obj->id) { |  | ||||||
| 		ubus_remove_object(ctx, obj); |  | ||||||
| 		wpas_ubus_ref_dec(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	free(name); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef CONFIG_WPS | #ifdef CONFIG_WPS | ||||||
| void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred) | void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -24,9 +24,6 @@ struct wpas_ubus_bss { | |||||||
| void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s); | void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s); | ||||||
| void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s); | void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s); | ||||||
|  |  | ||||||
| void wpas_ubus_add(struct wpa_global *global); |  | ||||||
| void wpas_ubus_free(struct wpa_global *global); |  | ||||||
|  |  | ||||||
| #ifdef CONFIG_WPS | #ifdef CONFIG_WPS | ||||||
| void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred); | void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred); | ||||||
| #endif | #endif | ||||||
| @@ -34,14 +31,6 @@ void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential | |||||||
| #else | #else | ||||||
| struct wpas_ubus_bss {}; | struct wpas_ubus_bss {}; | ||||||
|  |  | ||||||
| static inline void wpas_ubus_add_iface(struct wpa_supplicant *wpa_s) |  | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline void wpas_ubus_free_iface(struct wpa_supplicant *wpa_s) |  | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s) | static inline void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s) | ||||||
| { | { | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										281
									
								
								feeds/ipq95xx/hostapd/src/wpa_supplicant/ucode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								feeds/ipq95xx/hostapd/src/wpa_supplicant/ucode.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,281 @@ | |||||||
|  | #include "utils/includes.h" | ||||||
|  | #include "utils/common.h" | ||||||
|  | #include "utils/ucode.h" | ||||||
|  | #include "drivers/driver.h" | ||||||
|  | #include "ap/hostapd.h" | ||||||
|  | #include "wpa_supplicant_i.h" | ||||||
|  | #include "wps_supplicant.h" | ||||||
|  | #include "bss.h" | ||||||
|  | #include "ucode.h" | ||||||
|  |  | ||||||
|  | static struct wpa_global *wpa_global; | ||||||
|  | static uc_resource_type_t *global_type, *iface_type; | ||||||
|  | static uc_value_t *global, *iface_registry; | ||||||
|  | static uc_vm_t *vm; | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | wpas_ucode_iface_get_uval(struct wpa_supplicant *wpa_s) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	if (wpa_s->ucode.idx) | ||||||
|  | 		return wpa_ucode_registry_get(iface_registry, wpa_s->ucode.idx); | ||||||
|  |  | ||||||
|  | 	val = uc_resource_new(iface_type, wpa_s); | ||||||
|  | 	wpa_s->ucode.idx = wpa_ucode_registry_add(iface_registry, val); | ||||||
|  |  | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | wpas_ucode_update_interfaces(void) | ||||||
|  | { | ||||||
|  | 	uc_value_t *ifs = ucv_object_new(vm); | ||||||
|  | 	struct wpa_supplicant *wpa_s; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	for (wpa_s = wpa_global->ifaces; wpa_s; wpa_s = wpa_s->next) | ||||||
|  | 		ucv_object_add(ifs, wpa_s->ifname, ucv_get(wpas_ucode_iface_get_uval(wpa_s))); | ||||||
|  |  | ||||||
|  | 	ucv_object_add(ucv_prototype_get(global), "interfaces", ucv_get(ifs)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	if (wpa_ucode_call_prepare("iface_add")) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); | ||||||
|  | 	uc_value_push(ucv_get(wpas_ucode_iface_get_uval(wpa_s))); | ||||||
|  | 	ucv_put(wpa_ucode_call(2)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	val = wpa_ucode_registry_remove(iface_registry, wpa_s->ucode.idx); | ||||||
|  | 	if (!val) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	wpa_s->ucode.idx = 0; | ||||||
|  | 	if (wpa_ucode_call_prepare("iface_remove")) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); | ||||||
|  | 	uc_value_push(ucv_get(val)); | ||||||
|  | 	ucv_put(wpa_ucode_call(2)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void wpas_ucode_update_state(struct wpa_supplicant *wpa_s) | ||||||
|  | { | ||||||
|  | 	const char *state; | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	val = wpa_ucode_registry_get(iface_registry, wpa_s->ucode.idx); | ||||||
|  | 	if (!val) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	if (wpa_ucode_call_prepare("state")) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	state = wpa_supplicant_state_txt(wpa_s->wpa_state); | ||||||
|  | 	uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); | ||||||
|  | 	uc_value_push(ucv_get(val)); | ||||||
|  | 	uc_value_push(ucv_get(ucv_string_new(state))); | ||||||
|  | 	ucv_put(wpa_ucode_call(3)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_data *data) | ||||||
|  | { | ||||||
|  | 	const char *state; | ||||||
|  | 	uc_value_t *val; | ||||||
|  |  | ||||||
|  | 	if (event != EVENT_CH_SWITCH_STARTED) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	val = wpa_ucode_registry_get(iface_registry, wpa_s->ucode.idx); | ||||||
|  | 	if (!val) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	if (wpa_ucode_call_prepare("event")) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); | ||||||
|  | 	uc_value_push(ucv_get(val)); | ||||||
|  | 	uc_value_push(ucv_get(ucv_string_new(event_to_string(event)))); | ||||||
|  | 	val = ucv_object_new(vm); | ||||||
|  | 	uc_value_push(ucv_get(val)); | ||||||
|  |  | ||||||
|  | 	if (event == EVENT_CH_SWITCH_STARTED) { | ||||||
|  | 		ucv_object_add(val, "csa_count", ucv_int64_new(data->ch_switch.count)); | ||||||
|  | 		ucv_object_add(val, "frequency", ucv_int64_new(data->ch_switch.freq)); | ||||||
|  | 		ucv_object_add(val, "sec_chan_offset", ucv_int64_new(data->ch_switch.ch_offset)); | ||||||
|  | 		ucv_object_add(val, "center_freq1", ucv_int64_new(data->ch_switch.cf1)); | ||||||
|  | 		ucv_object_add(val, "center_freq2", ucv_int64_new(data->ch_switch.cf2)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ucv_put(wpa_ucode_call(4)); | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const char *obj_stringval(uc_value_t *obj, const char *name) | ||||||
|  | { | ||||||
|  | 	uc_value_t *val = ucv_object_get(obj, name, NULL); | ||||||
|  |  | ||||||
|  | 	return ucv_string_get(val); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_wpas_add_iface(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	uc_value_t *info = uc_fn_arg(0); | ||||||
|  | 	uc_value_t *ifname = ucv_object_get(info, "iface", NULL); | ||||||
|  | 	uc_value_t *bridge = ucv_object_get(info, "bridge", NULL); | ||||||
|  | 	uc_value_t *config = ucv_object_get(info, "config", NULL); | ||||||
|  | 	uc_value_t *ctrl = ucv_object_get(info, "ctrl", NULL); | ||||||
|  | 	struct wpa_interface iface; | ||||||
|  | 	int ret = -1; | ||||||
|  |  | ||||||
|  | 	if (ucv_type(info) != UC_OBJECT) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	iface = (struct wpa_interface){ | ||||||
|  | 		.driver = "nl80211", | ||||||
|  | 		.ifname = ucv_string_get(ifname), | ||||||
|  | 		.bridge_ifname = ucv_string_get(bridge), | ||||||
|  | 		.confname = ucv_string_get(config), | ||||||
|  | 		.ctrl_interface = ucv_string_get(ctrl), | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	if (!iface.ifname || !iface.confname) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	ret = wpa_supplicant_add_iface(wpa_global, &iface, 0) ? 0 : -1; | ||||||
|  | 	wpas_ucode_update_interfaces(); | ||||||
|  |  | ||||||
|  | out: | ||||||
|  | 	return ucv_int64_new(ret); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_wpas_remove_iface(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	struct wpa_supplicant *wpa_s = NULL; | ||||||
|  | 	uc_value_t *ifname_arg = uc_fn_arg(0); | ||||||
|  | 	const char *ifname = ucv_string_get(ifname_arg); | ||||||
|  | 	int ret = -1; | ||||||
|  |  | ||||||
|  | 	if (!ifname) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	for (wpa_s = wpa_global->ifaces; wpa_s; wpa_s = wpa_s->next) | ||||||
|  | 		if (!strcmp(wpa_s->ifname, ifname)) | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 	if (!wpa_s) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	ret = wpa_supplicant_remove_iface(wpa_global, wpa_s, 0); | ||||||
|  | 	wpas_ucode_update_interfaces(); | ||||||
|  |  | ||||||
|  | out: | ||||||
|  | 	return ucv_int64_new(ret); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static uc_value_t * | ||||||
|  | uc_wpas_iface_status(uc_vm_t *vm, size_t nargs) | ||||||
|  | { | ||||||
|  | 	struct wpa_supplicant *wpa_s = uc_fn_thisval("wpas.iface"); | ||||||
|  | 	struct wpa_bss *bss; | ||||||
|  | 	uc_value_t *ret, *val; | ||||||
|  |  | ||||||
|  | 	if (!wpa_s) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	ret = ucv_object_new(vm); | ||||||
|  |  | ||||||
|  | 	val = ucv_string_new(wpa_supplicant_state_txt(wpa_s->wpa_state)); | ||||||
|  | 	ucv_object_add(ret, "state", ucv_get(val)); | ||||||
|  |  | ||||||
|  | 	bss = wpa_s->current_bss; | ||||||
|  | 	if (bss) { | ||||||
|  | 		int sec_chan = 0; | ||||||
|  | 		const u8 *ie; | ||||||
|  |  | ||||||
|  | 		ie = wpa_bss_get_ie(bss, WLAN_EID_HT_OPERATION); | ||||||
|  | 		if (ie && ie[1] >= 2) { | ||||||
|  | 			const struct ieee80211_ht_operation *ht_oper; | ||||||
|  | 			int sec; | ||||||
|  |  | ||||||
|  | 			ht_oper = (const void *) (ie + 2); | ||||||
|  | 			sec = ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; | ||||||
|  | 			if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) | ||||||
|  | 				sec_chan = 1; | ||||||
|  | 			else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) | ||||||
|  | 				sec_chan = -1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		ucv_object_add(ret, "sec_chan_offset", ucv_int64_new(sec_chan)); | ||||||
|  | 		ucv_object_add(ret, "frequency", ucv_int64_new(bss->freq)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #ifdef CONFIG_MESH | ||||||
|  | 	if (wpa_s->ifmsh) { | ||||||
|  | 		struct hostapd_iface *ifmsh = wpa_s->ifmsh; | ||||||
|  |  | ||||||
|  | 		ucv_object_add(ret, "sec_chan_offset", ucv_int64_new(ifmsh->conf->secondary_channel)); | ||||||
|  | 		ucv_object_add(ret, "frequency", ucv_int64_new(ifmsh->freq)); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int wpas_ucode_init(struct wpa_global *gl) | ||||||
|  | { | ||||||
|  | 	static const uc_function_list_t global_fns[] = { | ||||||
|  | 		{ "printf",	uc_wpa_printf }, | ||||||
|  | 		{ "getpid", uc_wpa_getpid }, | ||||||
|  | 		{ "add_iface", uc_wpas_add_iface }, | ||||||
|  | 		{ "remove_iface", uc_wpas_remove_iface }, | ||||||
|  | 	}; | ||||||
|  | 	static const uc_function_list_t iface_fns[] = { | ||||||
|  | 		{ "status", uc_wpas_iface_status }, | ||||||
|  | 	}; | ||||||
|  | 	uc_value_t *data, *proto; | ||||||
|  |  | ||||||
|  | 	wpa_global = gl; | ||||||
|  | 	vm = wpa_ucode_create_vm(); | ||||||
|  |  | ||||||
|  | 	global_type = uc_type_declare(vm, "wpas.global", global_fns, NULL); | ||||||
|  | 	iface_type = uc_type_declare(vm, "wpas.iface", iface_fns, NULL); | ||||||
|  |  | ||||||
|  | 	iface_registry = ucv_array_new(vm); | ||||||
|  | 	uc_vm_registry_set(vm, "wpas.iface_registry", iface_registry); | ||||||
|  |  | ||||||
|  | 	global = wpa_ucode_global_init("wpas", global_type); | ||||||
|  |  | ||||||
|  | 	if (wpa_ucode_run(HOSTAPD_UC_PATH "wpa_supplicant.uc")) | ||||||
|  | 		goto free_vm; | ||||||
|  |  | ||||||
|  | 	ucv_gc(vm); | ||||||
|  | 	return 0; | ||||||
|  |  | ||||||
|  | free_vm: | ||||||
|  | 	wpa_ucode_free_vm(); | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void wpas_ucode_free(void) | ||||||
|  | { | ||||||
|  | 	if (wpa_ucode_call_prepare("shutdown") == 0) | ||||||
|  | 		ucv_put(wpa_ucode_call(0)); | ||||||
|  | 	wpa_ucode_free_vm(); | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								feeds/ipq95xx/hostapd/src/wpa_supplicant/ucode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								feeds/ipq95xx/hostapd/src/wpa_supplicant/ucode.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | #ifndef __WPAS_UCODE_H | ||||||
|  | #define __WPAS_UCODE_H | ||||||
|  |  | ||||||
|  | #include "utils/ucode.h" | ||||||
|  |  | ||||||
|  | struct wpa_global; | ||||||
|  | union wpa_event_data; | ||||||
|  | struct wpa_supplicant; | ||||||
|  |  | ||||||
|  | struct wpas_ucode_bss { | ||||||
|  | #ifdef UCODE_SUPPORT | ||||||
|  | 	unsigned int idx; | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #ifdef UCODE_SUPPORT | ||||||
|  | int wpas_ucode_init(struct wpa_global *gl); | ||||||
|  | void wpas_ucode_free(void); | ||||||
|  | void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s); | ||||||
|  | void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s); | ||||||
|  | void wpas_ucode_update_state(struct wpa_supplicant *wpa_s); | ||||||
|  | void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_data *data); | ||||||
|  | #else | ||||||
|  | static inline int wpas_ucode_init(struct wpa_global *gl) | ||||||
|  | { | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
|  | static inline void wpas_ucode_free(void) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | static inline void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void wpas_ucode_update_state(struct wpa_supplicant *wpa_s) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_data *data) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -17,11 +17,11 @@ KERNEL_NAME_SUFFIX=-qsdk-879aa8d1f540d2357674beed0069e4450946b831 | |||||||
| include $(INCLUDE_DIR)/target.mk | include $(INCLUDE_DIR)/target.mk | ||||||
| DEFAULT_PACKAGES += \ | DEFAULT_PACKAGES += \ | ||||||
| 	uboot-envtools kmod-leds-gpio kmod-gpio-button-hotplug kmod-button-hotplug \ | 	uboot-envtools kmod-leds-gpio kmod-gpio-button-hotplug kmod-button-hotplug \ | ||||||
| 	kmod-ata-core kmod-ata-ahci kmod-ata-ahci-platform kmod-usb3 swconfig \ | 	kmod-usb3 swconfig \ | ||||||
| 	kmod-usb-phy-ipq807x kmod-usb-dwc3-qcom-internal \ | 	kmod-usb-phy-ipq807x kmod-usb-dwc3-qcom-internal \ | ||||||
| 	kmod-qca-nss-ppe kmod-qca-ssdk-nohnat kmod-qca-psdk \ | 	kmod-qca-nss-ppe kmod-qca-ssdk-nohnat kmod-qca-psdk kmod-qca-nss-dp \ | ||||||
| 	kmod-qca-nss-dp kmod-qca-nss-ppe-bridge-mgr kmod-qca-nss-ppe-vlan-mgr \ |  | ||||||
| 	kmod-gpio-button-hotplug iwinfo uboot-envtools swconfig \ | 	kmod-gpio-button-hotplug iwinfo uboot-envtools swconfig \ | ||||||
| 	kmod-ath12k ath12k-firmware-qcn92xx wpad-openssl | 	kmod-ath12k ath12k-firmware-qcn92xx wpad-openssl \ | ||||||
|  | 	-procd-ujail | ||||||
|  |  | ||||||
| $(eval $(call BuildTarget)) | $(eval $(call BuildTarget)) | ||||||
|   | |||||||
| @@ -1262,3 +1262,6 @@ CONFIG_ZLIB_INFLATE=y | |||||||
| CONFIG_ZONE_DMA_FLAG=0 | CONFIG_ZONE_DMA_FLAG=0 | ||||||
| # CONFIG_DEBUG_MEM_USAGE is not set | # CONFIG_DEBUG_MEM_USAGE is not set | ||||||
| # CONFIG_DIAG_CHAR is not set | # CONFIG_DIAG_CHAR is not set | ||||||
|  | # CONFIG_NF_CONNTRACK_RTCACHE is not set | ||||||
|  | CONFIG_INIT_STACK_NONE=y | ||||||
|  | # CONFIG_INIT_STACK_ALL is not set | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								feeds/ipq95xx/ipq95xx/patches/001-ip6mr.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								feeds/ipq95xx/ipq95xx/patches/001-ip6mr.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/ipv6/ip6mr.c | ||||||
|  | =================================================================== | ||||||
|  | --- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/net/ipv6/ip6mr.c | ||||||
|  | +++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/ipv6/ip6mr.c | ||||||
|  | @@ -105,7 +105,7 @@ static ip6mr_mfc_event_offload_callback_ | ||||||
|  |   | ||||||
|  |  #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | ||||||
|  |  #define ip6mr_for_each_table(mrt, net) \ | ||||||
|  | -	list_for_each_entry_rcu(mrt, &net->ipv6.mr_tables, list) | ||||||
|  | +	list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list) | ||||||
|  |   | ||||||
|  |  static struct mr_table *ip6mr_mr_table_iter(struct net *net, | ||||||
|  |  					    struct mr_table *mrt) | ||||||
| @@ -0,0 +1,165 @@ | |||||||
|  | From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Tue, 12 Aug 2014 20:49:27 +0200 | ||||||
|  | Subject: [PATCH 24/53] GPIO: add named gpio exports | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/gpio/gpiolib-of.c     |   68 +++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  drivers/gpio/gpiolib-sysfs.c  |   10 +++++- | ||||||
|  |  include/asm-generic/gpio.h    |    6 ++++ | ||||||
|  |  include/linux/gpio/consumer.h |    8 +++++ | ||||||
|  |  4 files changed, 91 insertions(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/gpio/gpiolib-of.c | ||||||
|  | +++ b/drivers/gpio/gpiolib-of.c | ||||||
|  | @@ -19,6 +19,8 @@ | ||||||
|  |  #include <linux/pinctrl/pinctrl.h> | ||||||
|  |  #include <linux/slab.h> | ||||||
|  |  #include <linux/gpio/machine.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  |   | ||||||
|  |  #include "gpiolib.h" | ||||||
|  |  #include "gpiolib-of.h" | ||||||
|  | @@ -917,3 +919,68 @@ void of_gpiochip_remove(struct gpio_chip | ||||||
|  |  { | ||||||
|  |  	of_node_put(chip->of_node); | ||||||
|  |  } | ||||||
|  | + | ||||||
|  | +static struct of_device_id gpio_export_ids[] = { | ||||||
|  | +	{ .compatible = "gpio-export" }, | ||||||
|  | +	{ /* sentinel */ } | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int of_gpio_export_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct device_node *np = pdev->dev.of_node; | ||||||
|  | +	struct device_node *cnp; | ||||||
|  | +	u32 val; | ||||||
|  | +	int nb = 0; | ||||||
|  | + | ||||||
|  | +	for_each_child_of_node(np, cnp) { | ||||||
|  | +		const char *name = NULL; | ||||||
|  | +		int gpio; | ||||||
|  | +		bool dmc; | ||||||
|  | +		int max_gpio = 1; | ||||||
|  | +		int i; | ||||||
|  | + | ||||||
|  | +		of_property_read_string(cnp, "gpio-export,name", &name); | ||||||
|  | + | ||||||
|  | +		if (!name) | ||||||
|  | +			max_gpio = of_gpio_count(cnp); | ||||||
|  | + | ||||||
|  | +		for (i = 0; i < max_gpio; i++) { | ||||||
|  | +			unsigned flags = 0; | ||||||
|  | +			enum of_gpio_flags of_flags; | ||||||
|  | + | ||||||
|  | +			gpio = of_get_gpio_flags(cnp, i, &of_flags); | ||||||
|  | +			if (!gpio_is_valid(gpio)) | ||||||
|  | +				return gpio; | ||||||
|  | + | ||||||
|  | +			if (of_flags == OF_GPIO_ACTIVE_LOW) | ||||||
|  | +				flags |= GPIOF_ACTIVE_LOW; | ||||||
|  | + | ||||||
|  | +			if (!of_property_read_u32(cnp, "gpio-export,output", &val)) | ||||||
|  | +				flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; | ||||||
|  | +			else | ||||||
|  | +				flags |= GPIOF_IN; | ||||||
|  | + | ||||||
|  | +			if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) | ||||||
|  | +				continue; | ||||||
|  | + | ||||||
|  | +			dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); | ||||||
|  | +			gpio_export_with_name(gpio, dmc, name); | ||||||
|  | +			nb++; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver gpio_export_driver = { | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name		= "gpio-export", | ||||||
|  | +		.owner	= THIS_MODULE, | ||||||
|  | +		.of_match_table	= of_match_ptr(gpio_export_ids), | ||||||
|  | +	}, | ||||||
|  | +	.probe		= of_gpio_export_probe, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +module_platform_driver(gpio_export_driver); | ||||||
|  | --- a/drivers/gpio/gpiolib-sysfs.c | ||||||
|  | +++ b/drivers/gpio/gpiolib-sysfs.c | ||||||
|  | @@ -571,7 +571,7 @@ static struct class gpio_class = { | ||||||
|  |   * | ||||||
|  |   * Returns zero on success, else an error. | ||||||
|  |   */ | ||||||
|  | -int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | ||||||
|  | +int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) | ||||||
|  |  { | ||||||
|  |  	struct gpio_chip	*chip; | ||||||
|  |  	struct gpio_device	*gdev; | ||||||
|  | @@ -633,6 +633,8 @@ int gpiod_export(struct gpio_desc *desc, | ||||||
|  |  	offset = gpio_chip_hwgpio(desc); | ||||||
|  |  	if (chip->names && chip->names[offset]) | ||||||
|  |  		ioname = chip->names[offset]; | ||||||
|  | +	if (name) | ||||||
|  | +		ioname = name; | ||||||
|  |   | ||||||
|  |  	dev = device_create_with_groups(&gpio_class, &gdev->dev, | ||||||
|  |  					MKDEV(0, 0), data, gpio_groups, | ||||||
|  | @@ -654,6 +656,12 @@ err_unlock: | ||||||
|  |  	gpiod_dbg(desc, "%s: status %d\n", __func__, status); | ||||||
|  |  	return status; | ||||||
|  |  } | ||||||
|  | +EXPORT_SYMBOL_GPL(__gpiod_export); | ||||||
|  | + | ||||||
|  | +int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | ||||||
|  | +{ | ||||||
|  | +	return __gpiod_export(desc, direction_may_change, NULL); | ||||||
|  | +} | ||||||
|  |  EXPORT_SYMBOL_GPL(gpiod_export); | ||||||
|  |   | ||||||
|  |  static int match_export(struct device *dev, const void *desc) | ||||||
|  | --- a/include/asm-generic/gpio.h | ||||||
|  | +++ b/include/asm-generic/gpio.h | ||||||
|  | @@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g | ||||||
|  |  	return gpiod_export(gpio_to_desc(gpio), direction_may_change); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); | ||||||
|  | +static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) | ||||||
|  | +{ | ||||||
|  | +	return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static inline int gpio_export_link(struct device *dev, const char *name, | ||||||
|  |  				   unsigned gpio) | ||||||
|  |  { | ||||||
|  | --- a/include/linux/gpio/consumer.h | ||||||
|  | +++ b/include/linux/gpio/consumer.h | ||||||
|  | @@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_ | ||||||
|  |   | ||||||
|  |  #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) | ||||||
|  |   | ||||||
|  | +int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); | ||||||
|  |  int gpiod_export(struct gpio_desc *desc, bool direction_may_change); | ||||||
|  |  int gpiod_export_link(struct device *dev, const char *name, | ||||||
|  |  		      struct gpio_desc *desc); | ||||||
|  | @@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de | ||||||
|  |   | ||||||
|  |  #else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ | ||||||
|  |   | ||||||
|  | +static inline int _gpiod_export(struct gpio_desc *desc, | ||||||
|  | +			       bool direction_may_change, | ||||||
|  | +			       const char *name) | ||||||
|  | +{ | ||||||
|  | +	return -ENOSYS; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static inline int gpiod_export(struct gpio_desc *desc, | ||||||
|  |  			       bool direction_may_change) | ||||||
|  |  { | ||||||
| @@ -0,0 +1,160 @@ | |||||||
|  | From: Maxim Mikityanskiy <maximmi@nvidia.com> | ||||||
|  | Date: Tue, 30 Nov 2021 20:16:07 +0200 | ||||||
|  | Subject: [PATCH] bpf: Fix the off-by-two error in range markings | ||||||
|  |  | ||||||
|  | commit 2fa7d94afc1afbb4d702760c058dc2d7ed30f226 upstream. | ||||||
|  |  | ||||||
|  | The first commit cited below attempts to fix the off-by-one error that | ||||||
|  | appeared in some comparisons with an open range. Due to this error, | ||||||
|  | arithmetically equivalent pieces of code could get different verdicts | ||||||
|  | from the verifier, for example (pseudocode): | ||||||
|  |  | ||||||
|  |   // 1. Passes the verifier: | ||||||
|  |   if (data + 8 > data_end) | ||||||
|  |       return early | ||||||
|  |   read *(u64 *)data, i.e. [data; data+7] | ||||||
|  |  | ||||||
|  |   // 2. Rejected by the verifier (should still pass): | ||||||
|  |   if (data + 7 >= data_end) | ||||||
|  |       return early | ||||||
|  |   read *(u64 *)data, i.e. [data; data+7] | ||||||
|  |  | ||||||
|  | The attempted fix, however, shifts the range by one in a wrong | ||||||
|  | direction, so the bug not only remains, but also such piece of code | ||||||
|  | starts failing in the verifier: | ||||||
|  |  | ||||||
|  |   // 3. Rejected by the verifier, but the check is stricter than in #1. | ||||||
|  |   if (data + 8 >= data_end) | ||||||
|  |       return early | ||||||
|  |   read *(u64 *)data, i.e. [data; data+7] | ||||||
|  |  | ||||||
|  | The change performed by that fix converted an off-by-one bug into | ||||||
|  | off-by-two. The second commit cited below added the BPF selftests | ||||||
|  | written to ensure than code chunks like #3 are rejected, however, | ||||||
|  | they should be accepted. | ||||||
|  |  | ||||||
|  | This commit fixes the off-by-two error by adjusting new_range in the | ||||||
|  | right direction and fixes the tests by changing the range into the | ||||||
|  | one that should actually fail. | ||||||
|  |  | ||||||
|  | Fixes: fb2a311a31d3 ("bpf: fix off by one for range markings with L{T, E} patterns") | ||||||
|  | Fixes: b37242c773b2 ("bpf: add test cases to bpf selftests to cover all access tests") | ||||||
|  | Signed-off-by: Maxim Mikityanskiy <maximmi@nvidia.com> | ||||||
|  | Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> | ||||||
|  | Link: https://lore.kernel.org/bpf/20211130181607.593149-1-maximmi@nvidia.com | ||||||
|  | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/kernel/bpf/verifier.c | ||||||
|  | +++ b/kernel/bpf/verifier.c | ||||||
|  | @@ -5372,7 +5372,7 @@ static void find_good_pkt_pointers(struc | ||||||
|  |   | ||||||
|  |  	new_range = dst_reg->off; | ||||||
|  |  	if (range_right_open) | ||||||
|  | -		new_range--; | ||||||
|  | +		new_range++; | ||||||
|  |   | ||||||
|  |  	/* Examples for register markings: | ||||||
|  |  	 * | ||||||
|  | --- a/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c | ||||||
|  | +++ b/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c | ||||||
|  | @@ -112,10 +112,10 @@ | ||||||
|  |  	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | ||||||
|  |  		    offsetof(struct xdp_md, data_end)), | ||||||
|  |  	BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||||||
|  | -	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||||||
|  | +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | ||||||
|  |  	BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), | ||||||
|  |  	BPF_JMP_IMM(BPF_JA, 0, 0, 1), | ||||||
|  | -	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | ||||||
|  | +	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | ||||||
|  |  	BPF_MOV64_IMM(BPF_REG_0, 0), | ||||||
|  |  	BPF_EXIT_INSN(), | ||||||
|  |  	}, | ||||||
|  | @@ -167,10 +167,10 @@ | ||||||
|  |  	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | ||||||
|  |  		    offsetof(struct xdp_md, data_end)), | ||||||
|  |  	BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||||||
|  | -	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||||||
|  | +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | ||||||
|  |  	BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), | ||||||
|  |  	BPF_JMP_IMM(BPF_JA, 0, 0, 1), | ||||||
|  | -	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | ||||||
|  | +	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | ||||||
|  |  	BPF_MOV64_IMM(BPF_REG_0, 0), | ||||||
|  |  	BPF_EXIT_INSN(), | ||||||
|  |  	}, | ||||||
|  | @@ -274,9 +274,9 @@ | ||||||
|  |  	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | ||||||
|  |  		    offsetof(struct xdp_md, data_end)), | ||||||
|  |  	BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||||||
|  | -	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||||||
|  | +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | ||||||
|  |  	BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), | ||||||
|  | -	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | ||||||
|  | +	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | ||||||
|  |  	BPF_MOV64_IMM(BPF_REG_0, 0), | ||||||
|  |  	BPF_EXIT_INSN(), | ||||||
|  |  	}, | ||||||
|  | @@ -437,9 +437,9 @@ | ||||||
|  |  	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | ||||||
|  |  		    offsetof(struct xdp_md, data_end)), | ||||||
|  |  	BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||||||
|  | -	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||||||
|  | +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | ||||||
|  |  	BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), | ||||||
|  | -	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | ||||||
|  | +	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | ||||||
|  |  	BPF_MOV64_IMM(BPF_REG_0, 0), | ||||||
|  |  	BPF_EXIT_INSN(), | ||||||
|  |  	}, | ||||||
|  | @@ -544,10 +544,10 @@ | ||||||
|  |  		    offsetof(struct xdp_md, data_meta)), | ||||||
|  |  	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | ||||||
|  |  	BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||||||
|  | -	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||||||
|  | +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | ||||||
|  |  	BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), | ||||||
|  |  	BPF_JMP_IMM(BPF_JA, 0, 0, 1), | ||||||
|  | -	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | ||||||
|  | +	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | ||||||
|  |  	BPF_MOV64_IMM(BPF_REG_0, 0), | ||||||
|  |  	BPF_EXIT_INSN(), | ||||||
|  |  	}, | ||||||
|  | @@ -599,10 +599,10 @@ | ||||||
|  |  		    offsetof(struct xdp_md, data_meta)), | ||||||
|  |  	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | ||||||
|  |  	BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||||||
|  | -	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||||||
|  | +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | ||||||
|  |  	BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), | ||||||
|  |  	BPF_JMP_IMM(BPF_JA, 0, 0, 1), | ||||||
|  | -	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | ||||||
|  | +	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | ||||||
|  |  	BPF_MOV64_IMM(BPF_REG_0, 0), | ||||||
|  |  	BPF_EXIT_INSN(), | ||||||
|  |  	}, | ||||||
|  | @@ -706,9 +706,9 @@ | ||||||
|  |  		    offsetof(struct xdp_md, data_meta)), | ||||||
|  |  	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | ||||||
|  |  	BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||||||
|  | -	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||||||
|  | +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | ||||||
|  |  	BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), | ||||||
|  | -	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | ||||||
|  | +	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | ||||||
|  |  	BPF_MOV64_IMM(BPF_REG_0, 0), | ||||||
|  |  	BPF_EXIT_INSN(), | ||||||
|  |  	}, | ||||||
|  | @@ -869,9 +869,9 @@ | ||||||
|  |  		    offsetof(struct xdp_md, data_meta)), | ||||||
|  |  	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | ||||||
|  |  	BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | ||||||
|  | -	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | ||||||
|  | +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | ||||||
|  |  	BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), | ||||||
|  | -	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | ||||||
|  | +	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | ||||||
|  |  	BPF_MOV64_IMM(BPF_REG_0, 0), | ||||||
|  |  	BPF_EXIT_INSN(), | ||||||
|  |  	}, | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/scripts/mod/modpost.c |  | ||||||
| =================================================================== |  | ||||||
| --- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/scripts/mod/modpost.c |  | ||||||
| +++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/scripts/mod/modpost.c |  | ||||||
| @@ -32,7 +32,7 @@ static int external_module = 0; |  | ||||||
|  /* Warn about section mismatch in vmlinux if set to 1 */ |  | ||||||
|  static int vmlinux_section_warnings = 1; |  | ||||||
|  /* Only warn about unresolved symbols */ |  | ||||||
| -static int warn_unresolved = 0; |  | ||||||
| +static int warn_unresolved = 1; |  | ||||||
|  /* How a symbol is exported */ |  | ||||||
|  static int sec_mismatch_count = 0; |  | ||||||
|  static int sec_mismatch_fatal = 0; |  | ||||||
| @@ -0,0 +1,33 @@ | |||||||
|  | From: Xiongwei Song <sxwjean@gmail.com> | ||||||
|  | Date: Fri, 14 Jan 2022 14:07:24 -0800 | ||||||
|  | Subject: [PATCH] mm: page_alloc: fix building error on -Werror=array-compare | ||||||
|  |  | ||||||
|  | Arthur Marsh reported we would hit the error below when building kernel | ||||||
|  | with gcc-12: | ||||||
|  |  | ||||||
|  |   CC      mm/page_alloc.o | ||||||
|  |   mm/page_alloc.c: In function `mem_init_print_info': | ||||||
|  |   mm/page_alloc.c:8173:27: error: comparison between two arrays [-Werror=array-compare] | ||||||
|  |    8173 |                 if (start <= pos && pos < end && size > adj) \ | ||||||
|  |         | | ||||||
|  |  | ||||||
|  | In C++20, the comparision between arrays should be warned. | ||||||
|  |  | ||||||
|  | Link: https://lkml.kernel.org/r/20211125130928.32465-1-sxwjean@me.com | ||||||
|  | Signed-off-by: Xiongwei Song <sxwjean@gmail.com> | ||||||
|  | Reported-by: Arthur Marsh <arthur.marsh@internode.on.net> | ||||||
|  | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | ||||||
|  | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/mm/page_alloc.c | ||||||
|  | +++ b/mm/page_alloc.c | ||||||
|  | @@ -7579,7 +7579,7 @@ void __init mem_init_print_info(const ch | ||||||
|  |  	 */ | ||||||
|  |  #define adj_init_size(start, end, size, pos, adj) \ | ||||||
|  |  	do { \ | ||||||
|  | -		if (start <= pos && pos < end && size > adj) \ | ||||||
|  | +		if (&start[0] <= &pos[0] && &pos[0] < &end[0] && size > adj) \ | ||||||
|  |  			size -= adj; \ | ||||||
|  |  	} while (0) | ||||||
|  |   | ||||||
| @@ -0,0 +1,38 @@ | |||||||
|  | From: Nathan Chancellor <natechancellor@gmail.com> | ||||||
|  | Date: Mon, 6 Apr 2020 20:09:27 -0700 | ||||||
|  | Subject: [PATCH] kernel/extable.c: use address-of operator on section symbols | ||||||
|  |  | ||||||
|  | Clang warns: | ||||||
|  |  | ||||||
|  | ../kernel/extable.c:37:52: warning: array comparison always evaluates to | ||||||
|  | a constant [-Wtautological-compare] | ||||||
|  |         if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) { | ||||||
|  |                                                           ^ | ||||||
|  | 1 warning generated. | ||||||
|  |  | ||||||
|  | These are not true arrays, they are linker defined symbols, which are just | ||||||
|  | addresses.  Using the address of operator silences the warning and does | ||||||
|  | not change the resulting assembly with either clang/ld.lld or gcc/ld | ||||||
|  | (tested with diff + objdump -Dr). | ||||||
|  |  | ||||||
|  | Suggested-by: Nick Desaulniers <ndesaulniers@google.com> | ||||||
|  | Signed-off-by: Nathan Chancellor <natechancellor@gmail.com> | ||||||
|  | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | ||||||
|  | Reviewed-by: Andrew Morton <akpm@linux-foundation.org> | ||||||
|  | Link: https://github.com/ClangBuiltLinux/linux/issues/892 | ||||||
|  | Link: http://lkml.kernel.org/r/20200219202036.45702-1-natechancellor@gmail.com | ||||||
|  | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/kernel/extable.c | ||||||
|  | +++ b/kernel/extable.c | ||||||
|  | @@ -34,7 +34,8 @@ u32 __initdata __visible main_extable_so | ||||||
|  |  /* Sort the kernel's built-in exception table */ | ||||||
|  |  void __init sort_main_extable(void) | ||||||
|  |  { | ||||||
|  | -	if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) { | ||||||
|  | +	if (main_extable_sort_needed && | ||||||
|  | +	    &__stop___ex_table > &__start___ex_table) { | ||||||
|  |  		pr_notice("Sorting __ex_table...\n"); | ||||||
|  |  		sort_extable(__start___ex_table, __stop___ex_table); | ||||||
|  |  	} | ||||||
							
								
								
									
										14
									
								
								feeds/ipq95xx/ipq95xx/patches/103-fix_mhi_bus_test.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								feeds/ipq95xx/ipq95xx/patches/103-fix_mhi_bus_test.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | --- a/drivers/bus/mhi/test/mhitest_pci.c | ||||||
|  | +++ b/drivers/bus/mhi/test/mhitest_pci.c | ||||||
|  | @@ -547,11 +547,6 @@ int mhitest_pci_register_mhi(struct mhit | ||||||
|  |  	mplat->mhi_ctrl = mhi_ctrl; | ||||||
|  |  	dev_set_drvdata(&pci_dev->dev, mplat); | ||||||
|  |  	mhi_ctrl->cntrl_dev = &pci_dev->dev; | ||||||
|  | - | ||||||
|  | -	if (!mplat->fw_name) { | ||||||
|  | -		MHITEST_ERR("fw_name is NULLL\n"); | ||||||
|  | -		return -EINVAL; | ||||||
|  | -	} | ||||||
|  |  	mhi_ctrl->fw_image = mplat->fw_name; | ||||||
|  |   | ||||||
|  |  	mhi_ctrl->regs = mplat->bar; | ||||||
							
								
								
									
										14
									
								
								feeds/ipq95xx/ipq95xx/patches/130-proxy-arp.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								feeds/ipq95xx/ipq95xx/patches/130-proxy-arp.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/bridge/br_arp_nd_proxy.c | ||||||
|  | =================================================================== | ||||||
|  | --- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/net/bridge/br_arp_nd_proxy.c | ||||||
|  | +++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/bridge/br_arp_nd_proxy.c | ||||||
|  | @@ -198,7 +198,8 @@ void br_do_proxy_suppress_arp(struct sk_ | ||||||
|  |   | ||||||
|  |  			if ((p && (p->flags & BR_PROXYARP)) || | ||||||
|  |  			    (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | | ||||||
|  | -							 BR_NEIGH_SUPPRESS)))) { | ||||||
|  | +							 BR_NEIGH_SUPPRESS)) | ||||||
|  | +			     && memcmp(sha, n->ha, 6))) { | ||||||
|  |  				if (!vid) | ||||||
|  |  					br_arp_send(br, p, skb->dev, sip, tip, | ||||||
|  |  						    sha, n->ha, sha, 0, 0); | ||||||
							
								
								
									
										15
									
								
								feeds/ipq95xx/ipq95xx/patches/140-gcc12-fixes.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								feeds/ipq95xx/ipq95xx/patches/140-gcc12-fixes.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/soc/qcom/ctx-save.c | ||||||
|  | =================================================================== | ||||||
|  | --- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/drivers/soc/qcom/ctx-save.c | ||||||
|  | +++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/soc/qcom/ctx-save.c | ||||||
|  | @@ -1509,8 +1509,8 @@ static int ctx_save_probe(struct platfor | ||||||
|  |   | ||||||
|  |  #ifdef CONFIG_QCA_MINIDUMP | ||||||
|  |  	ret = register_module_notifier(&wlan_module_exit_nb); | ||||||
|  | -    if (ret) | ||||||
|  | -        dev_err(&pdev->dev, "Failed to register WLAN  module exit notifier\n"); | ||||||
|  | +    	if (ret) | ||||||
|  | +        	dev_err(&pdev->dev, "Failed to register WLAN  module exit notifier\n"); | ||||||
|  |   | ||||||
|  |  	ret = atomic_notifier_chain_register(&panic_notifier_list, | ||||||
|  |  				&wlan_panic_nb); | ||||||
							
								
								
									
										42
									
								
								feeds/ipq95xx/ipq95xx/patches/200-pstore.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								feeds/ipq95xx/ipq95xx/patches/200-pstore.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/arch/arm64/boot/dts/qcom/ipq8074-memory.dtsi | ||||||
|  | =================================================================== | ||||||
|  | --- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/arch/arm64/boot/dts/qcom/ipq8074-memory.dtsi | ||||||
|  | +++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/arch/arm64/boot/dts/qcom/ipq8074-memory.dtsi | ||||||
|  | @@ -129,6 +129,12 @@ | ||||||
|  |  			no-map; | ||||||
|  |  			reg = <0x0 0x4d900000 0x0 0x100000>; | ||||||
|  |  		}; | ||||||
|  | + | ||||||
|  | +		ramoops@4da00000 { | ||||||
|  | +			compatible = "ramoops"; | ||||||
|  | +			reg = <0x0 0x4da00000 0x0 0x100000>; | ||||||
|  | +			record-size = <0x1000>; | ||||||
|  | +		}; | ||||||
|  |  	}; | ||||||
|  |  	#elif __IPQ_MEM_PROFILE_512_MB__ | ||||||
|  |  	/*                      512 MB Profile | ||||||
|  | @@ -249,6 +255,12 @@ | ||||||
|  |  			no-map; | ||||||
|  |  			reg = <0x0 0x4e800000 0x0 0x100000>; | ||||||
|  |  		}; | ||||||
|  | + | ||||||
|  | +		ramoops@4e900000 { | ||||||
|  | +			compatible = "ramoops"; | ||||||
|  | +			reg = <0x0 0x4e900000 0x0 0x100000>; | ||||||
|  | +			record-size = <0x1000>; | ||||||
|  | +		}; | ||||||
|  |  	}; | ||||||
|  |  	#else | ||||||
|  |  	/*                   Default Profile | ||||||
|  | @@ -371,6 +383,11 @@ | ||||||
|  |  			reg = <0x0 0x51000000 0x0 0x100000>; | ||||||
|  |  		}; | ||||||
|  |   | ||||||
|  | +		ramoops@51200000 { | ||||||
|  | +			compatible = "ramoops"; | ||||||
|  | +			reg = <0x0 0x51200000 0x0 0x100000>; | ||||||
|  | +			record-size = <0x1000>; | ||||||
|  | +		}; | ||||||
|  |  	}; | ||||||
|  |  	#endif | ||||||
|  |  }; | ||||||
							
								
								
									
										306
									
								
								feeds/ipq95xx/ipq95xx/patches/200-revert_napi_threaded.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								feeds/ipq95xx/ipq95xx/patches/200-revert_napi_threaded.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,306 @@ | |||||||
|  | --- a/include/linux/netdevice.h | ||||||
|  | +++ b/include/linux/netdevice.h | ||||||
|  | @@ -338,7 +338,6 @@ struct napi_struct { | ||||||
|  |  	struct list_head	dev_list; | ||||||
|  |  	struct hlist_node	napi_hash_node; | ||||||
|  |  	unsigned int		napi_id; | ||||||
|  | -	struct work_struct	work; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum { | ||||||
|  | @@ -349,7 +348,6 @@ enum { | ||||||
|  |  	NAPI_STATE_HASHED,	/* In NAPI hash (busy polling possible) */ | ||||||
|  |  	NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ | ||||||
|  |  	NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ | ||||||
|  | -	NAPI_STATE_THREADED,	/* Use threaded NAPI */ | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum { | ||||||
|  | @@ -360,7 +358,6 @@ enum { | ||||||
|  |  	NAPIF_STATE_HASHED	 = BIT(NAPI_STATE_HASHED), | ||||||
|  |  	NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), | ||||||
|  |  	NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), | ||||||
|  | -	NAPIF_STATE_THREADED	 = BIT(NAPI_STATE_THREADED), | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum gro_result { | ||||||
|  | @@ -2320,26 +2317,6 @@ void netif_napi_add(struct net_device *d | ||||||
|  |  		    int (*poll)(struct napi_struct *, int), int weight); | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | - *	netif_threaded_napi_add - initialize a NAPI context | ||||||
|  | - *	@dev:  network device | ||||||
|  | - *	@napi: NAPI context | ||||||
|  | - *	@poll: polling function | ||||||
|  | - *	@weight: default weight | ||||||
|  | - * | ||||||
|  | - * This variant of netif_napi_add() should be used from drivers using NAPI | ||||||
|  | - * with CPU intensive poll functions. | ||||||
|  | - * This will schedule polling from a high priority workqueue | ||||||
|  | - */ | ||||||
|  | -static inline void netif_threaded_napi_add(struct net_device *dev, | ||||||
|  | -					   struct napi_struct *napi, | ||||||
|  | -					   int (*poll)(struct napi_struct *, int), | ||||||
|  | -					   int weight) | ||||||
|  | -{ | ||||||
|  | -	set_bit(NAPI_STATE_THREADED, &napi->state); | ||||||
|  | -	netif_napi_add(dev, napi, poll, weight); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -/** | ||||||
|  |   *	netif_tx_napi_add - initialize a NAPI context | ||||||
|  |   *	@dev:  network device | ||||||
|  |   *	@napi: NAPI context | ||||||
|  | --- a/net/core/dev.c | ||||||
|  | +++ b/net/core/dev.c | ||||||
|  | @@ -157,7 +157,6 @@ static DEFINE_SPINLOCK(offload_lock); | ||||||
|  |  struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; | ||||||
|  |  struct list_head ptype_all __read_mostly;	/* Taps */ | ||||||
|  |  static struct list_head offload_base __read_mostly; | ||||||
|  | -static struct workqueue_struct *napi_workq __read_mostly; | ||||||
|  |   | ||||||
|  |  static int netif_rx_internal(struct sk_buff *skb); | ||||||
|  |  static int call_netdevice_notifiers_info(unsigned long val, | ||||||
|  | @@ -6042,11 +6041,6 @@ void __napi_schedule(struct napi_struct | ||||||
|  |  { | ||||||
|  |  	unsigned long flags; | ||||||
|  |   | ||||||
|  | -	if (test_bit(NAPI_STATE_THREADED, &n->state)) { | ||||||
|  | -		queue_work(napi_workq, &n->work); | ||||||
|  | -		return; | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  |  	local_irq_save(flags); | ||||||
|  |  	____napi_schedule(this_cpu_ptr(&softnet_data), n); | ||||||
|  |  	local_irq_restore(flags); | ||||||
|  | @@ -6362,84 +6356,6 @@ static void init_gro_hash(struct napi_st | ||||||
|  |  	napi->gro_bitmask = 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int __napi_poll(struct napi_struct *n, bool *repoll) | ||||||
|  | -{ | ||||||
|  | -	int work, weight; | ||||||
|  | - | ||||||
|  | -	weight = n->weight; | ||||||
|  | - | ||||||
|  | -	/* This NAPI_STATE_SCHED test is for avoiding a race | ||||||
|  | -	 * with netpoll's poll_napi().  Only the entity which | ||||||
|  | -	 * obtains the lock and sees NAPI_STATE_SCHED set will | ||||||
|  | -	 * actually make the ->poll() call.  Therefore we avoid | ||||||
|  | -	 * accidentally calling ->poll() when NAPI is not scheduled. | ||||||
|  | -	 */ | ||||||
|  | -	work = 0; | ||||||
|  | -	if (test_bit(NAPI_STATE_SCHED, &n->state)) { | ||||||
|  | -		work = n->poll(n, weight); | ||||||
|  | -		trace_napi_poll(n, work, weight); | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  | -	WARN_ON_ONCE(work > weight); | ||||||
|  | - | ||||||
|  | -	if (likely(work < weight)) | ||||||
|  | -		return work; | ||||||
|  | - | ||||||
|  | -	/* Drivers must not modify the NAPI state if they | ||||||
|  | -	 * consume the entire weight.  In such cases this code | ||||||
|  | -	 * still "owns" the NAPI instance and therefore can | ||||||
|  | -	 * move the instance around on the list at-will. | ||||||
|  | -	 */ | ||||||
|  | -	if (unlikely(napi_disable_pending(n))) { | ||||||
|  | -		napi_complete(n); | ||||||
|  | -		return work; | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  | -	if (n->gro_bitmask) { | ||||||
|  | -		/* flush too old packets | ||||||
|  | -		 * If HZ < 1000, flush all packets. | ||||||
|  | -		 */ | ||||||
|  | -		napi_gro_flush(n, HZ >= 1000); | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  | -	gro_normal_list(n); | ||||||
|  | - | ||||||
|  | -	*repoll = true; | ||||||
|  | - | ||||||
|  | -	return work; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static void napi_workfn(struct work_struct *work) | ||||||
|  | -{ | ||||||
|  | -	struct napi_struct *n = container_of(work, struct napi_struct, work); | ||||||
|  | -	void *have; | ||||||
|  | - | ||||||
|  | -	for (;;) { | ||||||
|  | -		bool repoll = false; | ||||||
|  | - | ||||||
|  | -		local_bh_disable(); | ||||||
|  | - | ||||||
|  | -		have = netpoll_poll_lock(n); | ||||||
|  | -		__napi_poll(n, &repoll); | ||||||
|  | -		netpoll_poll_unlock(have); | ||||||
|  | - | ||||||
|  | -		local_bh_enable(); | ||||||
|  | - | ||||||
|  | -		if (!repoll) | ||||||
|  | -			return; | ||||||
|  | - | ||||||
|  | -		if (!need_resched()) | ||||||
|  | -			continue; | ||||||
|  | - | ||||||
|  | -		/* | ||||||
|  | -		 * have to pay for the latency of task switch even if | ||||||
|  | -		 * napi is scheduled | ||||||
|  | -		 */ | ||||||
|  | -		queue_work(napi_workq, work); | ||||||
|  | -		return; | ||||||
|  | -	} | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  void netif_napi_add(struct net_device *dev, struct napi_struct *napi, | ||||||
|  |  		    int (*poll)(struct napi_struct *, int), int weight) | ||||||
|  |  { | ||||||
|  | @@ -6459,7 +6375,6 @@ void netif_napi_add(struct net_device *d | ||||||
|  |  #ifdef CONFIG_NETPOLL | ||||||
|  |  	napi->poll_owner = -1; | ||||||
|  |  #endif | ||||||
|  | -	INIT_WORK(&napi->work, napi_workfn); | ||||||
|  |  	set_bit(NAPI_STATE_SCHED, &napi->state); | ||||||
|  |  	set_bit(NAPI_STATE_NPSVC, &napi->state); | ||||||
|  |  	list_add_rcu(&napi->dev_list, &dev->napi_list); | ||||||
|  | @@ -6500,7 +6415,6 @@ static void flush_gro_hash(struct napi_s | ||||||
|  |  void netif_napi_del(struct napi_struct *napi) | ||||||
|  |  { | ||||||
|  |  	might_sleep(); | ||||||
|  | -	cancel_work_sync(&napi->work); | ||||||
|  |  	if (napi_hash_del(napi)) | ||||||
|  |  		synchronize_net(); | ||||||
|  |  	list_del_init(&napi->dev_list); | ||||||
|  | @@ -6513,19 +6427,51 @@ EXPORT_SYMBOL(netif_napi_del); | ||||||
|  |   | ||||||
|  |  static int napi_poll(struct napi_struct *n, struct list_head *repoll) | ||||||
|  |  { | ||||||
|  | -	bool do_repoll = false; | ||||||
|  |  	void *have; | ||||||
|  | -	int work; | ||||||
|  | +	int work, weight; | ||||||
|  |   | ||||||
|  |  	list_del_init(&n->poll_list); | ||||||
|  |   | ||||||
|  |  	have = netpoll_poll_lock(n); | ||||||
|  |   | ||||||
|  | -	work = __napi_poll(n, &do_repoll); | ||||||
|  | +	weight = n->weight; | ||||||
|  |   | ||||||
|  | -	if (!do_repoll) | ||||||
|  | +	/* This NAPI_STATE_SCHED test is for avoiding a race | ||||||
|  | +	 * with netpoll's poll_napi().  Only the entity which | ||||||
|  | +	 * obtains the lock and sees NAPI_STATE_SCHED set will | ||||||
|  | +	 * actually make the ->poll() call.  Therefore we avoid | ||||||
|  | +	 * accidentally calling ->poll() when NAPI is not scheduled. | ||||||
|  | +	 */ | ||||||
|  | +	work = 0; | ||||||
|  | +	if (test_bit(NAPI_STATE_SCHED, &n->state)) { | ||||||
|  | +		work = n->poll(n, weight); | ||||||
|  | +		trace_napi_poll(n, work, weight); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	WARN_ON_ONCE(work > weight); | ||||||
|  | + | ||||||
|  | +	if (likely(work < weight)) | ||||||
|  |  		goto out_unlock; | ||||||
|  |   | ||||||
|  | +	/* Drivers must not modify the NAPI state if they | ||||||
|  | +	 * consume the entire weight.  In such cases this code | ||||||
|  | +	 * still "owns" the NAPI instance and therefore can | ||||||
|  | +	 * move the instance around on the list at-will. | ||||||
|  | +	 */ | ||||||
|  | +	if (unlikely(napi_disable_pending(n))) { | ||||||
|  | +		napi_complete(n); | ||||||
|  | +		goto out_unlock; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (n->gro_bitmask) { | ||||||
|  | +		/* flush too old packets | ||||||
|  | +		 * If HZ < 1000, flush all packets. | ||||||
|  | +		 */ | ||||||
|  | +		napi_gro_flush(n, HZ >= 1000); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	gro_normal_list(n); | ||||||
|  | + | ||||||
|  |  	/* Some drivers may have called napi_schedule | ||||||
|  |  	 * prior to exhausting their budget. | ||||||
|  |  	 */ | ||||||
|  | @@ -10501,10 +10447,6 @@ static int __init net_dev_init(void) | ||||||
|  |  		sd->backlog.weight = weight_p; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	napi_workq = alloc_workqueue("napi_workq", WQ_UNBOUND | WQ_HIGHPRI, | ||||||
|  | -				     WQ_UNBOUND_MAX_ACTIVE | WQ_SYSFS); | ||||||
|  | -	BUG_ON(!napi_workq); | ||||||
|  | - | ||||||
|  |  	dev_boot_phase = 0; | ||||||
|  |   | ||||||
|  |  	/* The loopback device is special if any other network devices | ||||||
|  | --- a/net/core/net-sysfs.c | ||||||
|  | +++ b/net/core/net-sysfs.c | ||||||
|  | @@ -470,52 +470,6 @@ static ssize_t proto_down_store(struct d | ||||||
|  |  } | ||||||
|  |  NETDEVICE_SHOW_RW(proto_down, fmt_dec); | ||||||
|  |   | ||||||
|  | -static int change_napi_threaded(struct net_device *dev, unsigned long val) | ||||||
|  | -{ | ||||||
|  | -	struct napi_struct *napi; | ||||||
|  | - | ||||||
|  | -	if (list_empty(&dev->napi_list)) | ||||||
|  | -		return -EOPNOTSUPP; | ||||||
|  | - | ||||||
|  | -	list_for_each_entry(napi, &dev->napi_list, dev_list) { | ||||||
|  | -		if (val) | ||||||
|  | -			set_bit(NAPI_STATE_THREADED, &napi->state); | ||||||
|  | -		else | ||||||
|  | -			clear_bit(NAPI_STATE_THREADED, &napi->state); | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  | -	return 0; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static ssize_t napi_threaded_store(struct device *dev, | ||||||
|  | -				struct device_attribute *attr, | ||||||
|  | -				const char *buf, size_t len) | ||||||
|  | -{ | ||||||
|  | -	return netdev_store(dev, attr, buf, len, change_napi_threaded); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static ssize_t napi_threaded_show(struct device *dev, | ||||||
|  | -				  struct device_attribute *attr, | ||||||
|  | -				  char *buf) | ||||||
|  | -{ | ||||||
|  | -	struct net_device *netdev = to_net_dev(dev); | ||||||
|  | -	struct napi_struct *napi; | ||||||
|  | -	bool enabled = false; | ||||||
|  | - | ||||||
|  | -	if (!rtnl_trylock()) | ||||||
|  | -		return restart_syscall(); | ||||||
|  | - | ||||||
|  | -	list_for_each_entry(napi, &netdev->napi_list, dev_list) { | ||||||
|  | -		if (test_bit(NAPI_STATE_THREADED, &napi->state)) | ||||||
|  | -			enabled = true; | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  | -	rtnl_unlock(); | ||||||
|  | - | ||||||
|  | -	return sprintf(buf, fmt_dec, enabled); | ||||||
|  | -} | ||||||
|  | -static DEVICE_ATTR_RW(napi_threaded); | ||||||
|  | - | ||||||
|  |  static ssize_t phys_port_id_show(struct device *dev, | ||||||
|  |  				 struct device_attribute *attr, char *buf) | ||||||
|  |  { | ||||||
|  | @@ -627,7 +581,6 @@ static struct attribute *net_class_attrs | ||||||
|  |  	&dev_attr_flags.attr, | ||||||
|  |  	&dev_attr_tx_queue_len.attr, | ||||||
|  |  	&dev_attr_gro_flush_timeout.attr, | ||||||
|  | -	&dev_attr_napi_threaded.attr, | ||||||
|  |  	&dev_attr_phys_port_id.attr, | ||||||
|  |  	&dev_attr_phys_port_name.attr, | ||||||
|  |  	&dev_attr_phys_switch_id.attr, | ||||||
| @@ -0,0 +1,88 @@ | |||||||
|  | From: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Date: Mon, 8 Feb 2021 11:34:08 -0800 | ||||||
|  | Subject: [PATCH] net: extract napi poll functionality to __napi_poll() | ||||||
|  |  | ||||||
|  | This commit introduces a new function __napi_poll() which does the main | ||||||
|  | logic of the existing napi_poll() function, and will be called by other | ||||||
|  | functions in later commits. | ||||||
|  | This idea and implementation is done by Felix Fietkau <nbd@nbd.name> and | ||||||
|  | is proposed as part of the patch to move napi work to work_queue | ||||||
|  | context. | ||||||
|  | This commit by itself is a code restructure. | ||||||
|  |  | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Signed-off-by: Wei Wang <weiwan@google.com> | ||||||
|  | Reviewed-by: Alexander Duyck <alexanderduyck@fb.com> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/core/dev.c | ||||||
|  | +++ b/net/core/dev.c | ||||||
|  | @@ -6425,15 +6425,10 @@ void netif_napi_del(struct napi_struct * | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(netif_napi_del); | ||||||
|  |   | ||||||
|  | -static int napi_poll(struct napi_struct *n, struct list_head *repoll) | ||||||
|  | +static int __napi_poll(struct napi_struct *n, bool *repoll) | ||||||
|  |  { | ||||||
|  | -	void *have; | ||||||
|  |  	int work, weight; | ||||||
|  |   | ||||||
|  | -	list_del_init(&n->poll_list); | ||||||
|  | - | ||||||
|  | -	have = netpoll_poll_lock(n); | ||||||
|  | - | ||||||
|  |  	weight = n->weight; | ||||||
|  |   | ||||||
|  |  	/* This NAPI_STATE_SCHED test is for avoiding a race | ||||||
|  | @@ -6451,7 +6446,7 @@ static int napi_poll(struct napi_struct | ||||||
|  |  	WARN_ON_ONCE(work > weight); | ||||||
|  |   | ||||||
|  |  	if (likely(work < weight)) | ||||||
|  | -		goto out_unlock; | ||||||
|  | +		return work; | ||||||
|  |   | ||||||
|  |  	/* Drivers must not modify the NAPI state if they | ||||||
|  |  	 * consume the entire weight.  In such cases this code | ||||||
|  | @@ -6460,7 +6455,7 @@ static int napi_poll(struct napi_struct | ||||||
|  |  	 */ | ||||||
|  |  	if (unlikely(napi_disable_pending(n))) { | ||||||
|  |  		napi_complete(n); | ||||||
|  | -		goto out_unlock; | ||||||
|  | +		return work; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (n->gro_bitmask) { | ||||||
|  | @@ -6478,12 +6473,29 @@ static int napi_poll(struct napi_struct | ||||||
|  |  	if (unlikely(!list_empty(&n->poll_list))) { | ||||||
|  |  		pr_warn_once("%s: Budget exhausted after napi rescheduled\n", | ||||||
|  |  			     n->dev ? n->dev->name : "backlog"); | ||||||
|  | -		goto out_unlock; | ||||||
|  | +		return work; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	list_add_tail(&n->poll_list, repoll); | ||||||
|  | +	*repoll = true; | ||||||
|  | + | ||||||
|  | +	return work; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int napi_poll(struct napi_struct *n, struct list_head *repoll) | ||||||
|  | +{ | ||||||
|  | +	bool do_repoll = false; | ||||||
|  | +	void *have; | ||||||
|  | +	int work; | ||||||
|  | + | ||||||
|  | +	list_del_init(&n->poll_list); | ||||||
|  | + | ||||||
|  | +	have = netpoll_poll_lock(n); | ||||||
|  | + | ||||||
|  | +	work = __napi_poll(n, &do_repoll); | ||||||
|  | + | ||||||
|  | +	if (do_repoll) | ||||||
|  | +		list_add_tail(&n->poll_list, repoll); | ||||||
|  |   | ||||||
|  | -out_unlock: | ||||||
|  |  	netpoll_poll_unlock(have); | ||||||
|  |   | ||||||
|  |  	return work; | ||||||
| @@ -0,0 +1,261 @@ | |||||||
|  | From: Wei Wang <weiwan@google.com> | ||||||
|  | Date: Mon, 8 Feb 2021 11:34:09 -0800 | ||||||
|  | Subject: [PATCH] net: implement threaded-able napi poll loop support | ||||||
|  |  | ||||||
|  | This patch allows running each napi poll loop inside its own | ||||||
|  | kernel thread. | ||||||
|  | The kthread is created during netif_napi_add() if dev->threaded | ||||||
|  | is set. And threaded mode is enabled in napi_enable(). We will | ||||||
|  | provide a way to set dev->threaded and enable threaded mode | ||||||
|  | without a device up/down in the following patch. | ||||||
|  |  | ||||||
|  | Once that threaded mode is enabled and the kthread is | ||||||
|  | started, napi_schedule() will wake-up such thread instead | ||||||
|  | of scheduling the softirq. | ||||||
|  |  | ||||||
|  | The threaded poll loop behaves quite likely the net_rx_action, | ||||||
|  | but it does not have to manipulate local irqs and uses | ||||||
|  | an explicit scheduling point based on netdev_budget. | ||||||
|  |  | ||||||
|  | Co-developed-by: Paolo Abeni <pabeni@redhat.com> | ||||||
|  | Signed-off-by: Paolo Abeni <pabeni@redhat.com> | ||||||
|  | Co-developed-by: Hannes Frederic Sowa <hannes@stressinduktion.org> | ||||||
|  | Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> | ||||||
|  | Co-developed-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | Signed-off-by: Wei Wang <weiwan@google.com> | ||||||
|  | Reviewed-by: Alexander Duyck <alexanderduyck@fb.com> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/include/linux/netdevice.h | ||||||
|  | +++ b/include/linux/netdevice.h | ||||||
|  | @@ -338,6 +338,7 @@ struct napi_struct { | ||||||
|  |  	struct list_head	dev_list; | ||||||
|  |  	struct hlist_node	napi_hash_node; | ||||||
|  |  	unsigned int		napi_id; | ||||||
|  | +	struct task_struct	*thread; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum { | ||||||
|  | @@ -348,6 +349,7 @@ enum { | ||||||
|  |  	NAPI_STATE_HASHED,	/* In NAPI hash (busy polling possible) */ | ||||||
|  |  	NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ | ||||||
|  |  	NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ | ||||||
|  | +	NAPI_STATE_THREADED,		/* The poll is performed inside its own thread*/ | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum { | ||||||
|  | @@ -358,6 +360,7 @@ enum { | ||||||
|  |  	NAPIF_STATE_HASHED	 = BIT(NAPI_STATE_HASHED), | ||||||
|  |  	NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), | ||||||
|  |  	NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), | ||||||
|  | +	NAPIF_STATE_THREADED	 = BIT(NAPI_STATE_THREADED), | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum gro_result { | ||||||
|  | @@ -502,20 +505,7 @@ bool napi_hash_del(struct napi_struct *n | ||||||
|  |   */ | ||||||
|  |  void napi_disable(struct napi_struct *n); | ||||||
|  |   | ||||||
|  | -/** | ||||||
|  | - *	napi_enable - enable NAPI scheduling | ||||||
|  | - *	@n: NAPI context | ||||||
|  | - * | ||||||
|  | - * Resume NAPI from being scheduled on this context. | ||||||
|  | - * Must be paired with napi_disable. | ||||||
|  | - */ | ||||||
|  | -static inline void napi_enable(struct napi_struct *n) | ||||||
|  | -{ | ||||||
|  | -	BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); | ||||||
|  | -	smp_mb__before_atomic(); | ||||||
|  | -	clear_bit(NAPI_STATE_SCHED, &n->state); | ||||||
|  | -	clear_bit(NAPI_STATE_NPSVC, &n->state); | ||||||
|  | -} | ||||||
|  | +void napi_enable(struct napi_struct *n); | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  |   *	napi_synchronize - wait until NAPI is not running | ||||||
|  | @@ -1834,6 +1824,8 @@ enum netdev_ml_priv_type { | ||||||
|  |   * | ||||||
|  |   *	@wol_enabled:	Wake-on-LAN is enabled | ||||||
|  |   * | ||||||
|  | + *	@threaded:	napi threaded mode is enabled | ||||||
|  | + * | ||||||
|  |   *	FIXME: cleanup struct net_device such that network protocol info | ||||||
|  |   *	moves out. | ||||||
|  |   */ | ||||||
|  | @@ -2137,6 +2129,7 @@ struct net_device { | ||||||
|  |  	struct lock_class_key	addr_list_lock_key; | ||||||
|  |  	bool			proto_down; | ||||||
|  |  	unsigned		wol_enabled:1; | ||||||
|  | +	unsigned		threaded:1; | ||||||
|  |  }; | ||||||
|  |  #define to_net_dev(d) container_of(d, struct net_device, dev) | ||||||
|  |   | ||||||
|  | --- a/net/core/dev.c | ||||||
|  | +++ b/net/core/dev.c | ||||||
|  | @@ -91,6 +91,7 @@ | ||||||
|  |  #include <linux/etherdevice.h> | ||||||
|  |  #include <linux/ethtool.h> | ||||||
|  |  #include <linux/skbuff.h> | ||||||
|  | +#include <linux/kthread.h> | ||||||
|  |  #include <linux/bpf.h> | ||||||
|  |  #include <linux/bpf_trace.h> | ||||||
|  |  #include <net/net_namespace.h> | ||||||
|  | @@ -1286,6 +1287,27 @@ void netdev_notify_peers(struct net_devi | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(netdev_notify_peers); | ||||||
|  |   | ||||||
|  | +static int napi_threaded_poll(void *data); | ||||||
|  | + | ||||||
|  | +static int napi_kthread_create(struct napi_struct *n) | ||||||
|  | +{ | ||||||
|  | +	int err = 0; | ||||||
|  | + | ||||||
|  | +	/* Create and wake up the kthread once to put it in | ||||||
|  | +	 * TASK_INTERRUPTIBLE mode to avoid the blocked task | ||||||
|  | +	 * warning and work with loadavg. | ||||||
|  | +	 */ | ||||||
|  | +	n->thread = kthread_run(napi_threaded_poll, n, "napi/%s-%d", | ||||||
|  | +				n->dev->name, n->napi_id); | ||||||
|  | +	if (IS_ERR(n->thread)) { | ||||||
|  | +		err = PTR_ERR(n->thread); | ||||||
|  | +		pr_err("kthread_run failed with err %d\n", err); | ||||||
|  | +		n->thread = NULL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack) | ||||||
|  |  { | ||||||
|  |  	const struct net_device_ops *ops = dev->netdev_ops; | ||||||
|  | @@ -3971,6 +3993,21 @@ int gro_normal_batch __read_mostly = 8; | ||||||
|  |  static inline void ____napi_schedule(struct softnet_data *sd, | ||||||
|  |  				     struct napi_struct *napi) | ||||||
|  |  { | ||||||
|  | +	struct task_struct *thread; | ||||||
|  | + | ||||||
|  | +	if (test_bit(NAPI_STATE_THREADED, &napi->state)) { | ||||||
|  | +		/* Paired with smp_mb__before_atomic() in | ||||||
|  | +		 * napi_enable(). Use READ_ONCE() to guarantee | ||||||
|  | +		 * a complete read on napi->thread. Only call | ||||||
|  | +		 * wake_up_process() when it's not NULL. | ||||||
|  | +		 */ | ||||||
|  | +		thread = READ_ONCE(napi->thread); | ||||||
|  | +		if (thread) { | ||||||
|  | +			wake_up_process(thread); | ||||||
|  | +			return; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	list_add_tail(&napi->poll_list, &sd->poll_list); | ||||||
|  |  	__raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||||||
|  |  } | ||||||
|  | @@ -6379,6 +6416,12 @@ void netif_napi_add(struct net_device *d | ||||||
|  |  	set_bit(NAPI_STATE_NPSVC, &napi->state); | ||||||
|  |  	list_add_rcu(&napi->dev_list, &dev->napi_list); | ||||||
|  |  	napi_hash_add(napi); | ||||||
|  | +	/* Create kthread for this napi if dev->threaded is set. | ||||||
|  | +	 * Clear dev->threaded if kthread creation failed so that | ||||||
|  | +	 * threaded mode will not be enabled in napi_enable(). | ||||||
|  | +	 */ | ||||||
|  | +	if (dev->threaded && napi_kthread_create(napi)) | ||||||
|  | +		dev->threaded = 0; | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(netif_napi_add); | ||||||
|  |   | ||||||
|  | @@ -6395,9 +6438,28 @@ void napi_disable(struct napi_struct *n) | ||||||
|  |  	hrtimer_cancel(&n->timer); | ||||||
|  |   | ||||||
|  |  	clear_bit(NAPI_STATE_DISABLE, &n->state); | ||||||
|  | +	clear_bit(NAPI_STATE_THREADED, &n->state); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(napi_disable); | ||||||
|  |   | ||||||
|  | +/** | ||||||
|  | + *	napi_enable - enable NAPI scheduling | ||||||
|  | + *	@n: NAPI context | ||||||
|  | + * | ||||||
|  | + * Resume NAPI from being scheduled on this context. | ||||||
|  | + * Must be paired with napi_disable. | ||||||
|  | + */ | ||||||
|  | +void napi_enable(struct napi_struct *n) | ||||||
|  | +{ | ||||||
|  | +	BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); | ||||||
|  | +	smp_mb__before_atomic(); | ||||||
|  | +	clear_bit(NAPI_STATE_SCHED, &n->state); | ||||||
|  | +	clear_bit(NAPI_STATE_NPSVC, &n->state); | ||||||
|  | +	if (n->dev->threaded && n->thread) | ||||||
|  | +		set_bit(NAPI_STATE_THREADED, &n->state); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(napi_enable); | ||||||
|  | + | ||||||
|  |  static void flush_gro_hash(struct napi_struct *napi) | ||||||
|  |  { | ||||||
|  |  	int i; | ||||||
|  | @@ -6422,6 +6484,11 @@ void netif_napi_del(struct napi_struct * | ||||||
|  |   | ||||||
|  |  	flush_gro_hash(napi); | ||||||
|  |  	napi->gro_bitmask = 0; | ||||||
|  | + | ||||||
|  | +	if (napi->thread) { | ||||||
|  | +		kthread_stop(napi->thread); | ||||||
|  | +		napi->thread = NULL; | ||||||
|  | +	} | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(netif_napi_del); | ||||||
|  |   | ||||||
|  | @@ -6501,6 +6568,51 @@ static int napi_poll(struct napi_struct | ||||||
|  |  	return work; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int napi_thread_wait(struct napi_struct *napi) | ||||||
|  | +{ | ||||||
|  | +	set_current_state(TASK_INTERRUPTIBLE); | ||||||
|  | + | ||||||
|  | +	while (!kthread_should_stop() && !napi_disable_pending(napi)) { | ||||||
|  | +		if (test_bit(NAPI_STATE_SCHED, &napi->state)) { | ||||||
|  | +			WARN_ON(!list_empty(&napi->poll_list)); | ||||||
|  | +			__set_current_state(TASK_RUNNING); | ||||||
|  | +			return 0; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		schedule(); | ||||||
|  | +		set_current_state(TASK_INTERRUPTIBLE); | ||||||
|  | +	} | ||||||
|  | +	__set_current_state(TASK_RUNNING); | ||||||
|  | +	return -1; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int napi_threaded_poll(void *data) | ||||||
|  | +{ | ||||||
|  | +	struct napi_struct *napi = data; | ||||||
|  | +	void *have; | ||||||
|  | + | ||||||
|  | +	while (!napi_thread_wait(napi)) { | ||||||
|  | +		for (;;) { | ||||||
|  | +			bool repoll = false; | ||||||
|  | + | ||||||
|  | +			local_bh_disable(); | ||||||
|  | + | ||||||
|  | +			have = netpoll_poll_lock(napi); | ||||||
|  | +			__napi_poll(napi, &repoll); | ||||||
|  | +			netpoll_poll_unlock(have); | ||||||
|  | + | ||||||
|  | +			__kfree_skb_flush(); | ||||||
|  | +			local_bh_enable(); | ||||||
|  | + | ||||||
|  | +			if (!repoll) | ||||||
|  | +				break; | ||||||
|  | + | ||||||
|  | +			cond_resched(); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static __latent_entropy void net_rx_action(struct softirq_action *h) | ||||||
|  |  { | ||||||
|  |  	struct softnet_data *sd = this_cpu_ptr(&softnet_data); | ||||||
| @@ -0,0 +1,177 @@ | |||||||
|  | From: Wei Wang <weiwan@google.com> | ||||||
|  | Date: Mon, 8 Feb 2021 11:34:10 -0800 | ||||||
|  | Subject: [PATCH] net: add sysfs attribute to control napi threaded mode | ||||||
|  |  | ||||||
|  | This patch adds a new sysfs attribute to the network device class. | ||||||
|  | Said attribute provides a per-device control to enable/disable the | ||||||
|  | threaded mode for all the napi instances of the given network device, | ||||||
|  | without the need for a device up/down. | ||||||
|  | User sets it to 1 or 0 to enable or disable threaded mode. | ||||||
|  | Note: when switching between threaded and the current softirq based mode | ||||||
|  | for a napi instance, it will not immediately take effect if the napi is | ||||||
|  | currently being polled. The mode switch will happen for the next time | ||||||
|  | napi_schedule() is called. | ||||||
|  |  | ||||||
|  | Co-developed-by: Paolo Abeni <pabeni@redhat.com> | ||||||
|  | Signed-off-by: Paolo Abeni <pabeni@redhat.com> | ||||||
|  | Co-developed-by: Hannes Frederic Sowa <hannes@stressinduktion.org> | ||||||
|  | Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> | ||||||
|  | Co-developed-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Signed-off-by: Wei Wang <weiwan@google.com> | ||||||
|  | Reviewed-by: Alexander Duyck <alexanderduyck@fb.com> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/Documentation/ABI/testing/sysfs-class-net | ||||||
|  | +++ b/Documentation/ABI/testing/sysfs-class-net | ||||||
|  | @@ -301,3 +301,18 @@ Contact:	netdev@vger.kernel.org | ||||||
|  |  Description: | ||||||
|  |  		32-bit unsigned integer counting the number of times the link has | ||||||
|  |  		been down | ||||||
|  | + | ||||||
|  | +What:		/sys/class/net/<iface>/threaded | ||||||
|  | +Date:		Jan 2021 | ||||||
|  | +KernelVersion:	5.12 | ||||||
|  | +Contact:	netdev@vger.kernel.org | ||||||
|  | +Description: | ||||||
|  | +		Boolean value to control the threaded mode per device. User could | ||||||
|  | +		set this value to enable/disable threaded mode for all napi | ||||||
|  | +		belonging to this device, without the need to do device up/down. | ||||||
|  | + | ||||||
|  | +		Possible values: | ||||||
|  | +		== ================================== | ||||||
|  | +		0  threaded mode disabled for this dev | ||||||
|  | +		1  threaded mode enabled for this dev | ||||||
|  | +		== ================================== | ||||||
|  | --- a/include/linux/netdevice.h | ||||||
|  | +++ b/include/linux/netdevice.h | ||||||
|  | @@ -496,6 +496,8 @@ static inline bool napi_complete(struct | ||||||
|  |   */ | ||||||
|  |  bool napi_hash_del(struct napi_struct *napi); | ||||||
|  |   | ||||||
|  | +int dev_set_threaded(struct net_device *dev, bool threaded); | ||||||
|  | + | ||||||
|  |  /** | ||||||
|  |   *	napi_disable - prevent NAPI from scheduling | ||||||
|  |   *	@n: NAPI context | ||||||
|  | --- a/net/core/dev.c | ||||||
|  | +++ b/net/core/dev.c | ||||||
|  | @@ -3997,8 +3997,9 @@ static inline void ____napi_schedule(str | ||||||
|  |   | ||||||
|  |  	if (test_bit(NAPI_STATE_THREADED, &napi->state)) { | ||||||
|  |  		/* Paired with smp_mb__before_atomic() in | ||||||
|  | -		 * napi_enable(). Use READ_ONCE() to guarantee | ||||||
|  | -		 * a complete read on napi->thread. Only call | ||||||
|  | +		 * napi_enable()/dev_set_threaded(). | ||||||
|  | +		 * Use READ_ONCE() to guarantee a complete | ||||||
|  | +		 * read on napi->thread. Only call | ||||||
|  |  		 * wake_up_process() when it's not NULL. | ||||||
|  |  		 */ | ||||||
|  |  		thread = READ_ONCE(napi->thread); | ||||||
|  | @@ -6393,6 +6394,49 @@ static void init_gro_hash(struct napi_st | ||||||
|  |  	napi->gro_bitmask = 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int dev_set_threaded(struct net_device *dev, bool threaded) | ||||||
|  | +{ | ||||||
|  | +	struct napi_struct *napi; | ||||||
|  | +	int err = 0; | ||||||
|  | + | ||||||
|  | +	if (dev->threaded == threaded) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	if (threaded) { | ||||||
|  | +		list_for_each_entry(napi, &dev->napi_list, dev_list) { | ||||||
|  | +			if (!napi->thread) { | ||||||
|  | +				err = napi_kthread_create(napi); | ||||||
|  | +				if (err) { | ||||||
|  | +					threaded = false; | ||||||
|  | +					break; | ||||||
|  | +				} | ||||||
|  | +			} | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	dev->threaded = threaded; | ||||||
|  | + | ||||||
|  | +	/* Make sure kthread is created before THREADED bit | ||||||
|  | +	 * is set. | ||||||
|  | +	 */ | ||||||
|  | +	smp_mb__before_atomic(); | ||||||
|  | + | ||||||
|  | +	/* Setting/unsetting threaded mode on a napi might not immediately | ||||||
|  | +	 * take effect, if the current napi instance is actively being | ||||||
|  | +	 * polled. In this case, the switch between threaded mode and | ||||||
|  | +	 * softirq mode will happen in the next round of napi_schedule(). | ||||||
|  | +	 * This should not cause hiccups/stalls to the live traffic. | ||||||
|  | +	 */ | ||||||
|  | +	list_for_each_entry(napi, &dev->napi_list, dev_list) { | ||||||
|  | +		if (threaded) | ||||||
|  | +			set_bit(NAPI_STATE_THREADED, &napi->state); | ||||||
|  | +		else | ||||||
|  | +			clear_bit(NAPI_STATE_THREADED, &napi->state); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  void netif_napi_add(struct net_device *dev, struct napi_struct *napi, | ||||||
|  |  		    int (*poll)(struct napi_struct *, int), int weight) | ||||||
|  |  { | ||||||
|  | --- a/net/core/net-sysfs.c | ||||||
|  | +++ b/net/core/net-sysfs.c | ||||||
|  | @@ -557,6 +557,45 @@ static ssize_t phys_switch_id_show(struc | ||||||
|  |  } | ||||||
|  |  static DEVICE_ATTR_RO(phys_switch_id); | ||||||
|  |   | ||||||
|  | +static ssize_t threaded_show(struct device *dev, | ||||||
|  | +			     struct device_attribute *attr, char *buf) | ||||||
|  | +{ | ||||||
|  | +	struct net_device *netdev = to_net_dev(dev); | ||||||
|  | +	ssize_t ret = -EINVAL; | ||||||
|  | + | ||||||
|  | +	if (!rtnl_trylock()) | ||||||
|  | +		return restart_syscall(); | ||||||
|  | + | ||||||
|  | +	if (dev_isalive(netdev)) | ||||||
|  | +		ret = sprintf(buf, fmt_dec, netdev->threaded); | ||||||
|  | + | ||||||
|  | +	rtnl_unlock(); | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int modify_napi_threaded(struct net_device *dev, unsigned long val) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	if (list_empty(&dev->napi_list)) | ||||||
|  | +		return -EOPNOTSUPP; | ||||||
|  | + | ||||||
|  | +	if (val != 0 && val != 1) | ||||||
|  | +		return -EOPNOTSUPP; | ||||||
|  | + | ||||||
|  | +	ret = dev_set_threaded(dev, val); | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static ssize_t threaded_store(struct device *dev, | ||||||
|  | +			      struct device_attribute *attr, | ||||||
|  | +			      const char *buf, size_t len) | ||||||
|  | +{ | ||||||
|  | +	return netdev_store(dev, attr, buf, len, modify_napi_threaded); | ||||||
|  | +} | ||||||
|  | +static DEVICE_ATTR_RW(threaded); | ||||||
|  | + | ||||||
|  |  static struct attribute *net_class_attrs[] __ro_after_init = { | ||||||
|  |  	&dev_attr_netdev_group.attr, | ||||||
|  |  	&dev_attr_type.attr, | ||||||
|  | @@ -587,6 +626,7 @@ static struct attribute *net_class_attrs | ||||||
|  |  	&dev_attr_proto_down.attr, | ||||||
|  |  	&dev_attr_carrier_up_count.attr, | ||||||
|  |  	&dev_attr_carrier_down_count.attr, | ||||||
|  | +	&dev_attr_threaded.attr, | ||||||
|  |  	NULL, | ||||||
|  |  }; | ||||||
|  |  ATTRIBUTE_GROUPS(net_class); | ||||||
| @@ -0,0 +1,93 @@ | |||||||
|  | From: Wei Wang <weiwan@google.com> | ||||||
|  | Date: Mon, 1 Mar 2021 17:21:13 -0800 | ||||||
|  | Subject: [PATCH] net: fix race between napi kthread mode and busy poll | ||||||
|  |  | ||||||
|  | Currently, napi_thread_wait() checks for NAPI_STATE_SCHED bit to | ||||||
|  | determine if the kthread owns this napi and could call napi->poll() on | ||||||
|  | it. However, if socket busy poll is enabled, it is possible that the | ||||||
|  | busy poll thread grabs this SCHED bit (after the previous napi->poll() | ||||||
|  | invokes napi_complete_done() and clears SCHED bit) and tries to poll | ||||||
|  | on the same napi. napi_disable() could grab the SCHED bit as well. | ||||||
|  | This patch tries to fix this race by adding a new bit | ||||||
|  | NAPI_STATE_SCHED_THREADED in napi->state. This bit gets set in | ||||||
|  | ____napi_schedule() if the threaded mode is enabled, and gets cleared | ||||||
|  | in napi_complete_done(), and we only poll the napi in kthread if this | ||||||
|  | bit is set. This helps distinguish the ownership of the napi between | ||||||
|  | kthread and other scenarios and fixes the race issue. | ||||||
|  |  | ||||||
|  | Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") | ||||||
|  | Reported-by: Martin Zaharinov <micron10@gmail.com> | ||||||
|  | Suggested-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | Signed-off-by: Wei Wang <weiwan@google.com> | ||||||
|  | Cc: Alexander Duyck <alexanderduyck@fb.com> | ||||||
|  | Cc: Eric Dumazet <edumazet@google.com> | ||||||
|  | Cc: Paolo Abeni <pabeni@redhat.com> | ||||||
|  | Cc: Hannes Frederic Sowa <hannes@stressinduktion.org> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/include/linux/netdevice.h | ||||||
|  | +++ b/include/linux/netdevice.h | ||||||
|  | @@ -350,6 +350,7 @@ enum { | ||||||
|  |  	NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ | ||||||
|  |  	NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ | ||||||
|  |  	NAPI_STATE_THREADED,		/* The poll is performed inside its own thread*/ | ||||||
|  | +	NAPI_STATE_SCHED_THREADED,	/* Napi is currently scheduled in threaded mode */ | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum { | ||||||
|  | @@ -361,6 +362,7 @@ enum { | ||||||
|  |  	NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), | ||||||
|  |  	NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), | ||||||
|  |  	NAPIF_STATE_THREADED	 = BIT(NAPI_STATE_THREADED), | ||||||
|  | +	NAPIF_STATE_SCHED_THREADED	= BIT(NAPI_STATE_SCHED_THREADED), | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum gro_result { | ||||||
|  | --- a/net/core/dev.c | ||||||
|  | +++ b/net/core/dev.c | ||||||
|  | @@ -4004,6 +4004,8 @@ static inline void ____napi_schedule(str | ||||||
|  |  		 */ | ||||||
|  |  		thread = READ_ONCE(napi->thread); | ||||||
|  |  		if (thread) { | ||||||
|  | +			if (thread->state != TASK_INTERRUPTIBLE) | ||||||
|  | +				set_bit(NAPI_STATE_SCHED_THREADED, &napi->state); | ||||||
|  |  			wake_up_process(thread); | ||||||
|  |  			return; | ||||||
|  |  		} | ||||||
|  | @@ -6181,7 +6183,8 @@ bool napi_complete_done(struct napi_stru | ||||||
|  |   | ||||||
|  |  		WARN_ON_ONCE(!(val & NAPIF_STATE_SCHED)); | ||||||
|  |   | ||||||
|  | -		new = val & ~(NAPIF_STATE_MISSED | NAPIF_STATE_SCHED); | ||||||
|  | +		new = val & ~(NAPIF_STATE_MISSED | NAPIF_STATE_SCHED | | ||||||
|  | +			      NAPIF_STATE_SCHED_THREADED); | ||||||
|  |   | ||||||
|  |  		/* If STATE_MISSED was set, leave STATE_SCHED set, | ||||||
|  |  		 * because we will call napi->poll() one more time. | ||||||
|  | @@ -6614,16 +6617,25 @@ static int napi_poll(struct napi_struct | ||||||
|  |   | ||||||
|  |  static int napi_thread_wait(struct napi_struct *napi) | ||||||
|  |  { | ||||||
|  | +	bool woken = false; | ||||||
|  | + | ||||||
|  |  	set_current_state(TASK_INTERRUPTIBLE); | ||||||
|  |   | ||||||
|  |  	while (!kthread_should_stop() && !napi_disable_pending(napi)) { | ||||||
|  | -		if (test_bit(NAPI_STATE_SCHED, &napi->state)) { | ||||||
|  | +		/* Testing SCHED_THREADED bit here to make sure the current | ||||||
|  | +		 * kthread owns this napi and could poll on this napi. | ||||||
|  | +		 * Testing SCHED bit is not enough because SCHED bit might be | ||||||
|  | +		 * set by some other busy poll thread or by napi_disable(). | ||||||
|  | +		 */ | ||||||
|  | +		if (test_bit(NAPI_STATE_SCHED_THREADED, &napi->state) || woken) { | ||||||
|  |  			WARN_ON(!list_empty(&napi->poll_list)); | ||||||
|  |  			__set_current_state(TASK_RUNNING); | ||||||
|  |  			return 0; | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  |  		schedule(); | ||||||
|  | +		/* woken being true indicates this thread owns this napi. */ | ||||||
|  | +		woken = true; | ||||||
|  |  		set_current_state(TASK_INTERRUPTIBLE); | ||||||
|  |  	} | ||||||
|  |  	__set_current_state(TASK_RUNNING); | ||||||
| @@ -0,0 +1,53 @@ | |||||||
|  | From: Paolo Abeni <pabeni@redhat.com> | ||||||
|  | Date: Fri, 9 Apr 2021 17:24:17 +0200 | ||||||
|  | Subject: [PATCH] net: fix hangup on napi_disable for threaded napi | ||||||
|  |  | ||||||
|  | napi_disable() is subject to an hangup, when the threaded | ||||||
|  | mode is enabled and the napi is under heavy traffic. | ||||||
|  |  | ||||||
|  | If the relevant napi has been scheduled and the napi_disable() | ||||||
|  | kicks in before the next napi_threaded_wait() completes - so | ||||||
|  | that the latter quits due to the napi_disable_pending() condition, | ||||||
|  | the existing code leaves the NAPI_STATE_SCHED bit set and the | ||||||
|  | napi_disable() loop waiting for such bit will hang. | ||||||
|  |  | ||||||
|  | This patch addresses the issue by dropping the NAPI_STATE_DISABLE | ||||||
|  | bit test in napi_thread_wait(). The later napi_threaded_poll() | ||||||
|  | iteration will take care of clearing the NAPI_STATE_SCHED. | ||||||
|  |  | ||||||
|  | This also addresses a related problem reported by Jakub: | ||||||
|  | before this patch a napi_disable()/napi_enable() pair killed | ||||||
|  | the napi thread, effectively disabling the threaded mode. | ||||||
|  | On the patched kernel napi_disable() simply stops scheduling | ||||||
|  | the relevant thread. | ||||||
|  |  | ||||||
|  | v1 -> v2: | ||||||
|  |   - let the main napi_thread_poll() loop clear the SCHED bit | ||||||
|  |  | ||||||
|  | Reported-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") | ||||||
|  | Signed-off-by: Paolo Abeni <pabeni@redhat.com> | ||||||
|  | Reviewed-by: Eric Dumazet <edumazet@google.com> | ||||||
|  | Link: https://lore.kernel.org/r/883923fa22745a9589e8610962b7dc59df09fb1f.1617981844.git.pabeni@redhat.com | ||||||
|  | Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/core/dev.c | ||||||
|  | +++ b/net/core/dev.c | ||||||
|  | @@ -6621,7 +6621,7 @@ static int napi_thread_wait(struct napi_ | ||||||
|  |   | ||||||
|  |  	set_current_state(TASK_INTERRUPTIBLE); | ||||||
|  |   | ||||||
|  | -	while (!kthread_should_stop() && !napi_disable_pending(napi)) { | ||||||
|  | +	while (!kthread_should_stop()) { | ||||||
|  |  		/* Testing SCHED_THREADED bit here to make sure the current | ||||||
|  |  		 * kthread owns this napi and could poll on this napi. | ||||||
|  |  		 * Testing SCHED bit is not enough because SCHED bit might be | ||||||
|  | @@ -6639,6 +6639,7 @@ static int napi_thread_wait(struct napi_ | ||||||
|  |  		set_current_state(TASK_INTERRUPTIBLE); | ||||||
|  |  	} | ||||||
|  |  	__set_current_state(TASK_RUNNING); | ||||||
|  | + | ||||||
|  |  	return -1; | ||||||
|  |  } | ||||||
|  |   | ||||||
| @@ -0,0 +1,136 @@ | |||||||
|  | From: Andy Ren <andy.ren@getcruise.com> | ||||||
|  | Date: Mon, 7 Nov 2022 09:42:42 -0800 | ||||||
|  | Subject: [PATCH] net/core: Allow live renaming when an interface is up | ||||||
|  |  | ||||||
|  | Allow a network interface to be renamed when the interface | ||||||
|  | is up. | ||||||
|  |  | ||||||
|  | As described in the netconsole documentation [1], when netconsole is | ||||||
|  | used as a built-in, it will bring up the specified interface as soon as | ||||||
|  | possible. As a result, user space will not be able to rename the | ||||||
|  | interface since the kernel disallows renaming of interfaces that are | ||||||
|  | administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set | ||||||
|  | by the kernel. | ||||||
|  |  | ||||||
|  | The original solution [2] to this problem was to add a new parameter to | ||||||
|  | the netconsole configuration parameters that allows renaming of | ||||||
|  | the interface used by netconsole while it is administratively up. | ||||||
|  | However, during the discussion that followed, it became apparent that we | ||||||
|  | have no reason to keep the current restriction and instead we should | ||||||
|  | allow user space to rename interfaces regardless of their administrative | ||||||
|  | state: | ||||||
|  |  | ||||||
|  | 1. The restriction was put in place over 20 years ago when renaming was | ||||||
|  | only possible via IOCTL and before rtnetlink started notifying user | ||||||
|  | space about such changes like it does today. | ||||||
|  |  | ||||||
|  | 2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version | ||||||
|  | 5.2 and no regressions were reported. | ||||||
|  |  | ||||||
|  | 3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about | ||||||
|  | the administrative state of interface. | ||||||
|  |  | ||||||
|  | Therefore, allow user space to rename running interfaces by removing the | ||||||
|  | restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in | ||||||
|  | possible triage by emitting a message to the kernel log that an | ||||||
|  | interface was renamed while UP. | ||||||
|  |  | ||||||
|  | [1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst | ||||||
|  | [2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/ | ||||||
|  |  | ||||||
|  | Signed-off-by: Andy Ren <andy.ren@getcruise.com> | ||||||
|  | Reviewed-by: Ido Schimmel <idosch@nvidia.com> | ||||||
|  | Reviewed-by: David Ahern <dsahern@kernel.org> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/include/linux/netdevice.h | ||||||
|  | +++ b/include/linux/netdevice.h | ||||||
|  | @@ -1503,7 +1503,6 @@ struct net_device_ops { | ||||||
|  |   * @IFF_FAILOVER: device is a failover master device | ||||||
|  |   * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device | ||||||
|  |   * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device | ||||||
|  | - * @IFF_LIVE_RENAME_OK: rename is allowed while device is up and running | ||||||
|  |   */ | ||||||
|  |  enum netdev_priv_flags { | ||||||
|  |  	IFF_802_1Q_VLAN			= 1<<0, | ||||||
|  | @@ -1536,7 +1535,7 @@ enum netdev_priv_flags { | ||||||
|  |  	IFF_FAILOVER			= 1<<27, | ||||||
|  |  	IFF_FAILOVER_SLAVE		= 1<<28, | ||||||
|  |  	IFF_L3MDEV_RX_HANDLER		= 1<<29, | ||||||
|  | -	IFF_LIVE_RENAME_OK		= 1<<30, | ||||||
|  | +	/* was IFF_LIVE_RENAME_OK */ | ||||||
|  |  	IFF_NO_IP_ALIGN			= 1<<31, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | @@ -1595,7 +1594,6 @@ enum netdev_priv_flags_ext { | ||||||
|  |  #define IFF_FAILOVER			IFF_FAILOVER | ||||||
|  |  #define IFF_FAILOVER_SLAVE		IFF_FAILOVER_SLAVE | ||||||
|  |  #define IFF_L3MDEV_RX_HANDLER		IFF_L3MDEV_RX_HANDLER | ||||||
|  | -#define IFF_LIVE_RENAME_OK		IFF_LIVE_RENAME_OK | ||||||
|  |  #define IFF_NO_IP_ALIGN			IFF_NO_IP_ALIGN | ||||||
|  |   | ||||||
|  |  /* Specifies the type of the struct net_device::ml_priv pointer */ | ||||||
|  | --- a/net/core/dev.c | ||||||
|  | +++ b/net/core/dev.c | ||||||
|  | @@ -1093,22 +1093,6 @@ int dev_change_name(struct net_device *d | ||||||
|  |   | ||||||
|  |  	net = dev_net(dev); | ||||||
|  |   | ||||||
|  | -	/* Some auto-enslaved devices e.g. failover slaves are | ||||||
|  | -	 * special, as userspace might rename the device after | ||||||
|  | -	 * the interface had been brought up and running since | ||||||
|  | -	 * the point kernel initiated auto-enslavement. Allow | ||||||
|  | -	 * live name change even when these slave devices are | ||||||
|  | -	 * up and running. | ||||||
|  | -	 * | ||||||
|  | -	 * Typically, users of these auto-enslaving devices | ||||||
|  | -	 * don't actually care about slave name change, as | ||||||
|  | -	 * they are supposed to operate on master interface | ||||||
|  | -	 * directly. | ||||||
|  | -	 */ | ||||||
|  | -	if (dev->flags & IFF_UP && | ||||||
|  | -	    likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK))) | ||||||
|  | -		return -EBUSY; | ||||||
|  | - | ||||||
|  |  	down_write(&devnet_rename_sem); | ||||||
|  |   | ||||||
|  |  	if (strncmp(newname, dev->name, IFNAMSIZ) == 0) { | ||||||
|  | @@ -1125,7 +1109,8 @@ int dev_change_name(struct net_device *d | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (oldname[0] && !strchr(oldname, '%')) | ||||||
|  | -		netdev_info(dev, "renamed from %s\n", oldname); | ||||||
|  | +		netdev_info(dev, "renamed from %s%s\n", oldname, | ||||||
|  | +			    dev->flags & IFF_UP ? " (while UP)" : ""); | ||||||
|  |   | ||||||
|  |  	old_assign_type = dev->name_assign_type; | ||||||
|  |  	dev->name_assign_type = NET_NAME_RENAMED; | ||||||
|  | --- a/net/core/failover.c | ||||||
|  | +++ b/net/core/failover.c | ||||||
|  | @@ -80,14 +80,14 @@ static int failover_slave_register(struc | ||||||
|  |  		goto err_upper_link; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	slave_dev->priv_flags |= (IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); | ||||||
|  | +	slave_dev->priv_flags |= IFF_FAILOVER_SLAVE; | ||||||
|  |   | ||||||
|  |  	if (fops && fops->slave_register && | ||||||
|  |  	    !fops->slave_register(slave_dev, failover_dev)) | ||||||
|  |  		return NOTIFY_OK; | ||||||
|  |   | ||||||
|  |  	netdev_upper_dev_unlink(slave_dev, failover_dev); | ||||||
|  | -	slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); | ||||||
|  | +	slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; | ||||||
|  |  err_upper_link: | ||||||
|  |  	netdev_rx_handler_unregister(slave_dev); | ||||||
|  |  done: | ||||||
|  | @@ -121,7 +121,7 @@ int failover_slave_unregister(struct net | ||||||
|  |   | ||||||
|  |  	netdev_rx_handler_unregister(slave_dev); | ||||||
|  |  	netdev_upper_dev_unlink(slave_dev, failover_dev); | ||||||
|  | -	slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); | ||||||
|  | +	slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; | ||||||
|  |   | ||||||
|  |  	if (fops && fops->slave_unregister && | ||||||
|  |  	    !fops->slave_unregister(slave_dev, failover_dev)) | ||||||
| @@ -179,7 +179,7 @@ config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM | |||||||
| MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \ | MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \ | ||||||
| 	CROSS_COMPILE="$(KERNEL_CROSS)" \ | 	CROSS_COMPILE="$(KERNEL_CROSS)" \ | ||||||
|         ARCH="$(LINUX_KARCH)" \ |         ARCH="$(LINUX_KARCH)" \ | ||||||
| 	EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) -I$(STAGING_DIR)/usr/include/qca-nss-drv -I$(STAGING_DIR)/usr/include/qca-nss-clients -Wno-incompatible-pointer-types -Wno-discarded-qualifiers -Wno-int-conversion -Wno-unused-function -Wno-implicit-fallthrough" \ | 	EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) -I$(STAGING_DIR)/usr/include/qca-nss-drv -I$(STAGING_DIR)/usr/include/qca-nss-clients -Wno-incompatible-pointer-types -Wno-discarded-qualifiers -Wno-int-conversion -Wno-unused-function -Wno-implicit-fallthrough -Wno-error=array-parameter -Wno-stringop-overread -Wno-address -Wno-array-parameter" \ | ||||||
| 	KLIB_BUILD="$(LINUX_DIR)" \ | 	KLIB_BUILD="$(LINUX_DIR)" \ | ||||||
| 	MODPROBE=true \ | 	MODPROBE=true \ | ||||||
| 	KLIB=$(TARGET_MODULES_DIR) \ | 	KLIB=$(TARGET_MODULES_DIR) \ | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| #!/bin/sh | #!/bin/sh | ||||||
| . /lib/netifd/netifd-wireless.sh | . /lib/netifd/netifd-wireless.sh | ||||||
| . /lib/netifd/hostapd.sh | . /lib/netifd/hostapd.sh | ||||||
|  | . /lib/functions/system.sh | ||||||
|  |  | ||||||
| init_wireless_driver "$@" | init_wireless_driver "$@" | ||||||
|  |  | ||||||
| @@ -14,12 +15,9 @@ MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh | |||||||
| MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding" | MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding" | ||||||
| MP_CONFIG_STRING="mesh_power_mode" | MP_CONFIG_STRING="mesh_power_mode" | ||||||
|  |  | ||||||
| NEWAPLIST= | wdev_tool() { | ||||||
| OLDAPLIST= | 	ucode /usr/share/hostap/wdev.uc "$@" | ||||||
| NEWSPLIST= | } | ||||||
| OLDSPLIST= |  | ||||||
| NEWUMLIST= |  | ||||||
| OLDUMLIST= |  | ||||||
|  |  | ||||||
| drv_mac80211_init_device_config() { | drv_mac80211_init_device_config() { | ||||||
| 	hostapd_common_add_device_config | 	hostapd_common_add_device_config | ||||||
| @@ -28,9 +26,9 @@ drv_mac80211_init_device_config() { | |||||||
| 	config_add_string tx_burst | 	config_add_string tx_burst | ||||||
| 	config_add_string distance | 	config_add_string distance | ||||||
| 	config_add_int beacon_int chanbw frag rts | 	config_add_int beacon_int chanbw frag rts | ||||||
| 	config_add_int rxantenna txantenna antenna_gain txpower | 	config_add_int rxantenna txantenna antenna_gain txpower min_tx_power | ||||||
| 	config_add_int num_global_macaddr | 	config_add_int num_global_macaddr | ||||||
| 	config_add_boolean noscan ht_coex acs_exclude_dfs | 	config_add_boolean noscan ht_coex acs_exclude_dfs background_radar | ||||||
| 	config_add_array ht_capab | 	config_add_array ht_capab | ||||||
| 	config_add_array channels | 	config_add_array channels | ||||||
| 	config_add_array scan_list | 	config_add_array scan_list | ||||||
| @@ -153,13 +151,15 @@ mac80211_hostapd_setup_base() { | |||||||
| 	[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] && | 	[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] && | ||||||
| 		append base_cfg "acs_exclude_dfs=1" "$N" | 		append base_cfg "acs_exclude_dfs=1" "$N" | ||||||
|  |  | ||||||
| 	json_get_vars noscan ht_coex | 	json_get_vars noscan ht_coex min_tx_power:0 tx_burst | ||||||
| 	json_get_values ht_capab_list ht_capab tx_burst | 	json_get_values ht_capab_list ht_capab | ||||||
| 	json_get_values channel_list channels | 	json_get_values channel_list channels | ||||||
|  |  | ||||||
| 	[ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \ | 	[ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \ | ||||||
| 		channel_list="$channel" | 		channel_list="$channel" | ||||||
|  |  | ||||||
|  | 	[ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" | ||||||
|  |  | ||||||
| 	set_default noscan 0 | 	set_default noscan 0 | ||||||
|  |  | ||||||
| 	[ "$noscan" -gt 0 ] && hostapd_noscan=1 | 	[ "$noscan" -gt 0 ] && hostapd_noscan=1 | ||||||
| @@ -172,7 +172,7 @@ mac80211_hostapd_setup_base() { | |||||||
| 	ht_capab= | 	ht_capab= | ||||||
| 	case "$htmode" in | 	case "$htmode" in | ||||||
| 		VHT20|HT20|HE20) ;; | 		VHT20|HT20|HE20) ;; | ||||||
| 		HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160|EHT40|EHT80|EHT320) | 		HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160|EHT40|EHT80|EHT160|EHT320) | ||||||
| 			case "$hwmode" in | 			case "$hwmode" in | ||||||
| 				a) | 				a) | ||||||
| 					case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in | 					case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in | ||||||
| @@ -289,10 +289,16 @@ mac80211_hostapd_setup_base() { | |||||||
| 			vht_center_seg0=$idx | 			vht_center_seg0=$idx | ||||||
| 		;; | 		;; | ||||||
| 		esac | 		esac | ||||||
|  | 	[ "$band" = "5g" ] && { | ||||||
|  | 		json_get_vars background_radar:0 | ||||||
|  |  | ||||||
|  | 		[ "$background_radar" -eq 1 ] && append base_cfg "enable_background_radar=1" "$N" | ||||||
|  | 	} | ||||||
| 	[ "$band" = "6g" ] && { | 	[ "$band" = "6g" ] && { | ||||||
| 		op_class= | 		op_class= | ||||||
| 		case "$htmode" in | 		case "$htmode" in | ||||||
| 			HE20) op_class=131;; | 			HE20) op_class=131;; | ||||||
|  | 			EHT320) op_class=137;; | ||||||
| 			HE*|EHT*) op_class=$((132 + $vht_oper_chwidth)) | 			HE*|EHT*) op_class=$((132 + $vht_oper_chwidth)) | ||||||
| 		esac | 		esac | ||||||
| 		[ -n "$op_class" ] && append base_cfg "op_class=$op_class" "$N" | 		[ -n "$op_class" ] && append base_cfg "op_class=$op_class" "$N" | ||||||
| @@ -418,7 +424,7 @@ mac80211_hostapd_setup_base() { | |||||||
| 	enable_be=0 | 	enable_be=0 | ||||||
| 	case "$htmode" in | 	case "$htmode" in | ||||||
| 		HE*) enable_ax=1 ;; | 		HE*) enable_ax=1 ;; | ||||||
| 		HE*|EHT*) | 		EHT*) | ||||||
| 			enable_ax=1 | 			enable_ax=1 | ||||||
| 			enable_be=1 | 			enable_be=1 | ||||||
| 			;; | 			;; | ||||||
| @@ -427,26 +433,46 @@ mac80211_hostapd_setup_base() { | |||||||
| 	if [ "$enable_ax" != "0" ]; then | 	if [ "$enable_ax" != "0" ]; then | ||||||
| 		json_get_vars \ | 		json_get_vars \ | ||||||
| 			he_su_beamformer:1 \ | 			he_su_beamformer:1 \ | ||||||
| 			he_su_beamformee:0 \ | 			he_su_beamformee:1 \ | ||||||
| 			he_mu_beamformer:1 \ | 			he_mu_beamformer:1 \ | ||||||
| 			he_twt_required:0 \ | 			he_twt_required:0 \ | ||||||
| 			he_spr_sr_control:0 \ | 			he_spr_sr_control:3 \ | ||||||
| 			he_spr_non_srg_obss_pd_max_offset:1 \ | 			he_spr_psr_enabled:0 \ | ||||||
| 			he_bss_color | 			he_spr_non_srg_obss_pd_max_offset:0 \ | ||||||
|  | 			he_bss_color:128 \ | ||||||
|  | 			he_bss_color_enabled:1 | ||||||
|  |  | ||||||
| 		he_phy_cap=$(iw phy "$phy" info | awk -F "[()]" '/HE PHY Capabilities/ { print $2 }' | head -1) | 		he_phy_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE PHY Capabilities/ { print $2 }' | head -1) | ||||||
| 		he_phy_cap=${he_phy_cap:2} | 		he_phy_cap=${he_phy_cap:2} | ||||||
| 		he_mac_cap=$(iw phy "$phy" info | awk -F "[()]" '/HE MAC Capabilities/ { print $2 }' | head -1) | 		he_mac_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE MAC Capabilities/ { print $2 }' | head -1) | ||||||
| 		he_mac_cap=${he_mac_cap:2} | 		he_mac_cap=${he_mac_cap:2} | ||||||
|  |  | ||||||
| 		append base_cfg "ieee80211ax=1" "$N" | 		append base_cfg "ieee80211ax=1" "$N" | ||||||
| 		[ -n "$he_bss_color" ] && append base_cfg "he_bss_color=$he_bss_color" "$N" |  | ||||||
| 		[ "$hwmode" = "a" ] && { | 		[ "$hwmode" = "a" ] && { | ||||||
| 			append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N" | 			append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N" | ||||||
| 			append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N" | 			append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N" | ||||||
| 			 [ "$enable_be" != "0" ] && { | 			 [ "$enable_be" != "0" ] && { | ||||||
|  | 				case "$htmode" in | ||||||
|  | 				EHT320) | ||||||
|  | 					local eht_idx=130 | ||||||
|  | 					if [ "$band" = "6g" ]; then | ||||||
|  | 						case "$channel" in | ||||||
|  | 						1|5|9|13|17|21|25|29|33|37|41|45) idx=31;; | ||||||
|  | 						49|53|57|61|65|69|73|77) idx=63;; | ||||||
|  | 						81|85|89|93|97|101|105|109) idx=95;; | ||||||
|  | 						113|117|121|125|129|133|137|141) idx=127;; | ||||||
|  | 						145|149|153|157|161|165|169|173) idx=159;; | ||||||
|  | 						177|181|185|189|193|197|201|205|209|213|217|221) idx=191;; | ||||||
|  | 						esac | ||||||
|  | 					fi | ||||||
|  | 					append base_cfg "eht_oper_chwidth=9" "$N" | ||||||
|  | 					append base_cfg "eht_oper_centr_freq_seg0_idx=$eht_idx" "$N" | ||||||
|  | 					;; | ||||||
|  | 				*) | ||||||
| 					append base_cfg "eht_oper_chwidth=$vht_oper_chwidth" "$N" | 					append base_cfg "eht_oper_chwidth=$vht_oper_chwidth" "$N" | ||||||
| 					append base_cfg "eht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N" | 					append base_cfg "eht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N" | ||||||
|  | 					;; | ||||||
|  | 				esac | ||||||
| 			 } | 			 } | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -454,10 +480,21 @@ mac80211_hostapd_setup_base() { | |||||||
| 			he_su_beamformer:${he_phy_cap:6:2}:0x80:$he_su_beamformer \ | 			he_su_beamformer:${he_phy_cap:6:2}:0x80:$he_su_beamformer \ | ||||||
| 			he_su_beamformee:${he_phy_cap:8:2}:0x1:$he_su_beamformee \ | 			he_su_beamformee:${he_phy_cap:8:2}:0x1:$he_su_beamformee \ | ||||||
| 			he_mu_beamformer:${he_phy_cap:8:2}:0x2:$he_mu_beamformer \ | 			he_mu_beamformer:${he_phy_cap:8:2}:0x2:$he_mu_beamformer \ | ||||||
| 			he_spr_sr_control:${he_phy_cap:14:2}:0x1:$he_spr_sr_control \ | 			he_spr_psr_enabled:${he_phy_cap:14:2}:0x1:$he_spr_psr_enabled \ | ||||||
| 			he_twt_required:${he_mac_cap:0:2}:0x6:$he_twt_required | 			he_twt_required:${he_mac_cap:0:2}:0x6:$he_twt_required | ||||||
|  |  | ||||||
| 		[ "$he_spr_sr_control" -gt 0 ] && append base_cfg "he_spr_non_srg_obss_pd_max_offset=$he_spr_non_srg_obss_pd_max_offset" "$N" | 		if [ "$he_bss_color_enabled" -gt 0 ]; then | ||||||
|  | 			append base_cfg "he_bss_color=$he_bss_color" "$N" | ||||||
|  | 			[ "$he_spr_non_srg_obss_pd_max_offset" -gt 0 ] && { \ | ||||||
|  | 				append base_cfg "he_spr_non_srg_obss_pd_max_offset=$he_spr_non_srg_obss_pd_max_offset" "$N" | ||||||
|  | 				he_spr_sr_control=$((he_spr_sr_control | (1 << 2))) | ||||||
|  | 			} | ||||||
|  | 			[ "$he_spr_psr_enabled" -gt 0 ] || he_spr_sr_control=$((he_spr_sr_control | (1 << 0))) | ||||||
|  | 			append base_cfg "he_spr_sr_control=$he_spr_sr_control" "$N" | ||||||
|  | 		else | ||||||
|  | 			append base_cfg "he_bss_color_disabled=1" "$N" | ||||||
|  | 		fi | ||||||
|  |  | ||||||
|  |  | ||||||
| 		append base_cfg "he_default_pe_duration=4" "$N" | 		append base_cfg "he_default_pe_duration=4" "$N" | ||||||
| 		append base_cfg "he_rts_threshold=1023" "$N" | 		append base_cfg "he_rts_threshold=1023" "$N" | ||||||
| @@ -569,8 +606,6 @@ $base_cfg | |||||||
|  |  | ||||||
| EOF | EOF | ||||||
| 	json_select .. | 	json_select .. | ||||||
| 	radio_md5sum=$(md5sum $hostapd_conf_file | cut -d" " -f1) |  | ||||||
| 	echo "radio_config_id=${radio_md5sum}" >> $hostapd_conf_file |  | ||||||
| } | } | ||||||
|  |  | ||||||
| mac80211_hostapd_setup_bss() { | mac80211_hostapd_setup_bss() { | ||||||
| @@ -607,6 +642,7 @@ mac80211_hostapd_setup_bss() { | |||||||
| 	cat >> /var/run/hostapd-$phy.conf <<EOF | 	cat >> /var/run/hostapd-$phy.conf <<EOF | ||||||
| $hostapd_cfg | $hostapd_cfg | ||||||
| bssid=$macaddr | bssid=$macaddr | ||||||
|  | ${default_macaddr:+#default_macaddr} | ||||||
| ${dtim_period:+dtim_period=$dtim_period} | ${dtim_period:+dtim_period=$dtim_period} | ||||||
| ${max_listen_int:+max_listen_interval=$max_listen_int} | ${max_listen_int:+max_listen_interval=$max_listen_int} | ||||||
| EOF | EOF | ||||||
| @@ -621,57 +657,9 @@ mac80211_get_addr() { | |||||||
|  |  | ||||||
| mac80211_generate_mac() { | mac80211_generate_mac() { | ||||||
| 	local phy="$1" | 	local phy="$1" | ||||||
| 	local multiple_bssid="$2" |  | ||||||
| 	local id="${macidx:-0}" | 	local id="${macidx:-0}" | ||||||
|  |  | ||||||
| 	local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)" | 	wdev_tool "$phy" get_macaddr id=$id num_global=$num_global_macaddr mbssid=$multiple_bssid | ||||||
| 	local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)" |  | ||||||
|  |  | ||||||
| 	[ "$mask" = "00:00:00:00:00:00" -a "$multiple_bssid" != 1 ] && { |  | ||||||
| 		mask="ff:ff:ff:ff:ff:ff"; |  | ||||||
|  |  | ||||||
| 		[ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt $id ] && { |  | ||||||
| 			addr="$(mac80211_get_addr "$phy" "$id")" |  | ||||||
| 			[ -n "$addr" ] && { |  | ||||||
| 				echo "$addr" |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS" |  | ||||||
|  |  | ||||||
| 	local mask1=$1 |  | ||||||
| 	local mask6=$6 |  | ||||||
|  |  | ||||||
| 	local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS" |  | ||||||
| 	[ "$multiple_bssid" -eq 1 ] && { |  | ||||||
|                printf "02:%s:%s:%s:%s:%02x" $b1 $2 $3 $4 $5 $macidx |  | ||||||
|                return |  | ||||||
|     } |  | ||||||
| 	macidx=$(($id + 1)) |  | ||||||
|  |  | ||||||
| 	local use_global=0 |  | ||||||
| 	[ "$id" -gt 0 -a "$macidx" -le "$num_global_macaddr" ] && use_global=1 |  | ||||||
|  |  | ||||||
| 	[ "$((0x$mask1))" -gt 0 -a "$use_global" -lt 1 ] && { |  | ||||||
| 		b1="0x$1" |  | ||||||
| 		[ "$id" -gt 0 ] && \ |  | ||||||
| 			b1=$(($b1 ^ ((($id - !($b1 & 2)) << 2)) | 0x2)) |  | ||||||
| 		printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6 |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	[ "$((0x$mask6))" -lt 255 -a "$use_global" -gt 0 ] && { |  | ||||||
| 		printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id )) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	off2=$(( (0x$6 + $id) / 0x100 )) |  | ||||||
| 	printf "%s:%s:%s:%s:%02x:%02x" \ |  | ||||||
| 		$1 $2 $3 $4 \ |  | ||||||
| 		$(( (0x$5 + $off2) % 0x100 )) \ |  | ||||||
| 		$(( (0x$6 + $id) % 0x100 )) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| find_phy() { | find_phy() { | ||||||
| @@ -692,76 +680,7 @@ mac80211_check_ap() { | |||||||
| 	has_ap=1 | 	has_ap=1 | ||||||
| } | } | ||||||
|  |  | ||||||
| mac80211_iw_interface_add() { |  | ||||||
| 	local phy="$1" |  | ||||||
| 	local ifname="$2" |  | ||||||
| 	local type="$3" |  | ||||||
| 	local wdsflag="$4" |  | ||||||
| 	local rc |  | ||||||
| 	local oldifname |  | ||||||
|  |  | ||||||
| 	iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 |  | ||||||
| 	rc="$?" |  | ||||||
|  |  | ||||||
| 	[ "$rc" = 233 ] && { |  | ||||||
| 		# Device might have just been deleted, give the kernel some time to finish cleaning it up |  | ||||||
| 		sleep 1 |  | ||||||
|  |  | ||||||
| 		iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 |  | ||||||
| 		rc="$?" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	[ "$rc" = 233 ] && { |  | ||||||
| 		# Keep matching pre-existing interface |  | ||||||
| 		[ -d "/sys/class/ieee80211/${phy}/device/net/${ifname}" ] && \ |  | ||||||
| 		case "$(iw dev $ifname info | grep "^\ttype" | cut -d' ' -f2- 2>/dev/null)" in |  | ||||||
| 			"AP") |  | ||||||
| 				[ "$type" = "__ap" ] && rc=0 |  | ||||||
| 				;; |  | ||||||
| 			"IBSS") |  | ||||||
| 				[ "$type" = "adhoc" ] && rc=0 |  | ||||||
| 				;; |  | ||||||
| 			"managed") |  | ||||||
| 				[ "$type" = "managed" ] && rc=0 |  | ||||||
| 				;; |  | ||||||
| 			"mesh point") |  | ||||||
| 				[ "$type" = "mp" ] && rc=0 |  | ||||||
| 				;; |  | ||||||
| 			"monitor") |  | ||||||
| 				[ "$type" = "monitor" ] && rc=0 |  | ||||||
| 				;; |  | ||||||
| 		esac |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	[ "$rc" = 233 ] && { |  | ||||||
| 		iw dev "$ifname" del >/dev/null 2>&1 |  | ||||||
| 		[ "$?" = 0 ] && { |  | ||||||
| 			sleep 1 |  | ||||||
|  |  | ||||||
| 			iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 |  | ||||||
| 			rc="$?" |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	[ "$rc" != 0 ] && { |  | ||||||
| 		# Device might not support virtual interfaces, so the interface never got deleted in the first place. |  | ||||||
| 		# Check if the interface already exists, and avoid failing in this case. |  | ||||||
| 		[ -d "/sys/class/ieee80211/${phy}/device/net/${ifname}" ] && rc=0 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	[ "$rc" != 0 ] && { |  | ||||||
| 		# Device doesn't support virtual interfaces and may have existing interface other than ifname. |  | ||||||
| 		oldifname="$(basename "/sys/class/ieee80211/${phy}/device/net"/* 2>/dev/null)" |  | ||||||
| 		[ "$oldifname" ] && ip link set "$oldifname" name "$ifname" 1>/dev/null 2>&1 |  | ||||||
| 		rc="$?" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	[ "$rc" != 0 ] && echo "Failed to create interface $ifname" |  | ||||||
| 	return $rc |  | ||||||
| } |  | ||||||
|  |  | ||||||
| mac80211_prepare_vif() { | mac80211_prepare_vif() { | ||||||
| 	local multiple_bssid=$1 |  | ||||||
| 	json_select config | 	json_select config | ||||||
|  |  | ||||||
| 	json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file | 	json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file | ||||||
| @@ -769,19 +688,21 @@ mac80211_prepare_vif() { | |||||||
| 	[ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}" | 	[ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}" | ||||||
| 	if_idx=$((${if_idx:-0} + 1)) | 	if_idx=$((${if_idx:-0} + 1)) | ||||||
|  |  | ||||||
|  | 	append active_ifnames "$ifname" | ||||||
| 	set_default wds 0 | 	set_default wds 0 | ||||||
| 	set_default powersave 0 | 	set_default powersave 0 | ||||||
|  | 	json_add_string _ifname "$ifname" | ||||||
|  |  | ||||||
|  | 	default_macaddr= | ||||||
|  | 	[ -n "$macaddr" ] || { | ||||||
|  | 		macaddr="$(mac80211_generate_mac $phy)" | ||||||
|  |  		macidx="$(($macidx + 1))" | ||||||
|  | 		default_macaddr=1 | ||||||
|  | 	} | ||||||
|  | 	json_add_string _macaddr "$macaddr" | ||||||
|  | 	json_add_string _default_macaddr "$default_macaddr" | ||||||
| 	json_select .. | 	json_select .. | ||||||
|  |  | ||||||
| 	[ -n "$macaddr" ] || { |  | ||||||
| 		macaddr="$(mac80211_generate_mac $phy $multiple_bssid)" |  | ||||||
| 		macidx="$(($macidx + 1))" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	json_add_object data |  | ||||||
| 	json_add_string ifname "$ifname" |  | ||||||
| 	json_close_object |  | ||||||
|  |  | ||||||
| 	[ "$mode" == "ap" ] && { | 	[ "$mode" == "ap" ] && { | ||||||
| 		[ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" | 		[ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" | ||||||
| @@ -792,9 +713,6 @@ mac80211_prepare_vif() { | |||||||
|  |  | ||||||
| 	# It is far easier to delete and create the desired interface | 	# It is far easier to delete and create the desired interface | ||||||
| 	case "$mode" in | 	case "$mode" in | ||||||
| 		adhoc) |  | ||||||
| 			mac80211_iw_interface_add "$phy" "$ifname" adhoc || return |  | ||||||
| 		;; |  | ||||||
| 		ap) | 		ap) | ||||||
| 			# Hostapd will handle recreating the interface and | 			# Hostapd will handle recreating the interface and | ||||||
| 			# subsequent virtual APs belonging to the same PHY | 			# subsequent virtual APs belonging to the same PHY | ||||||
| @@ -806,119 +724,20 @@ mac80211_prepare_vif() { | |||||||
|  |  | ||||||
| 			mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return | 			mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return | ||||||
|  |  | ||||||
| 			NEWAPLIST="${NEWAPLIST}$ifname " |  | ||||||
| 			[ -n "$hostapd_ctrl" ] || { | 			[ -n "$hostapd_ctrl" ] || { | ||||||
| 				ap_ifname="${ifname}" | 				ap_ifname="${ifname}" | ||||||
| 				hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" | 				hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" | ||||||
| 			} | 			} | ||||||
| 		;; | 		;; | ||||||
| 		mesh) |  | ||||||
| 			mac80211_iw_interface_add "$phy" "$ifname" mp || return |  | ||||||
| 		;; |  | ||||||
| 		monitor) |  | ||||||
| 			mac80211_iw_interface_add "$phy" "$ifname" monitor || return |  | ||||||
| 		;; |  | ||||||
| 		sta) |  | ||||||
| 			local wdsflag= |  | ||||||
| 			[ "$enable" = 0 ] || staidx="$(($staidx + 1))" |  | ||||||
| 			[ "$wds" -gt 0 ] && wdsflag="4addr on" |  | ||||||
| 			mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return |  | ||||||
| 			if [ "$wds" -gt 0 ]; then |  | ||||||
| 				echo 1 > /sys/kernel/debug/ieee80211/$phy/netdev\:$ifname/disable_offload |  | ||||||
| 				iw "$ifname" set 4addr on |  | ||||||
| 			else |  | ||||||
| 				iw "$ifname" set 4addr off |  | ||||||
| 			fi |  | ||||||
| 			[ "$powersave" -gt 0 ] && powersave="on" || powersave="off" |  | ||||||
| 			iw "$ifname" set power_save "$powersave" |  | ||||||
| 		;; |  | ||||||
| 	esac | 	esac | ||||||
|  |  | ||||||
| 	case "$mode" in |  | ||||||
| 		monitor|mesh) |  | ||||||
| 			[ "$auto_channel" -gt 0 ] || iw dev "$ifname" set channel "$channel" $iw_htmode |  | ||||||
| 		;; |  | ||||||
| 	esac |  | ||||||
|  |  | ||||||
| 	if [ "$mode" != "ap" ]; then |  | ||||||
| 		# ALL ap functionality will be passed to hostapd |  | ||||||
| 		# All interfaces must have unique mac addresses |  | ||||||
| 		# which can either be explicitly set in the device |  | ||||||
| 		# section, or automatically generated |  | ||||||
| 		ip link set dev "$ifname" address "$macaddr" |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| 	json_select .. | 	json_select .. | ||||||
| } | } | ||||||
|  |  | ||||||
| mac80211_setup_supplicant() { |  | ||||||
| 	local enable=$1 |  | ||||||
| 	local add_sp=0 |  | ||||||
| 	local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})" |  | ||||||
|  |  | ||||||
| 	[ "$enable" = 0 ] && { |  | ||||||
| 		ubus call wpa_supplicant.${phy} config_remove "{\"iface\":\"$ifname\"}" |  | ||||||
| 		ip link set dev "$ifname" down |  | ||||||
| 		iw dev "$ifname" del |  | ||||||
| 		return 0 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	wpa_supplicant_prepare_interface "$ifname" nl80211 || { |  | ||||||
| 		iw dev "$ifname" del |  | ||||||
| 		return 1 |  | ||||||
| 	} |  | ||||||
| 	if [ "$mode" = "sta" ]; then |  | ||||||
| 		wpa_supplicant_add_network "$ifname" |  | ||||||
| 	else |  | ||||||
| 		wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| 	NEWSPLIST="${NEWSPLIST}$ifname " |  | ||||||
|  |  | ||||||
| 	if [ "${NEWAPLIST%% *}" != "${OLDAPLIST%% *}" ]; then |  | ||||||
| 		[ "$spobj" ] && ubus call wpa_supplicant config_remove "{\"iface\":\"$ifname\"}" |  | ||||||
| 		add_sp=1 |  | ||||||
| 	fi |  | ||||||
| 	[ -z "$spobj" ] && add_sp=1 |  | ||||||
|  |  | ||||||
| 	NEW_MD5_SP=$(test -e "${_config}" && md5sum ${_config}) |  | ||||||
| 	OLD_MD5_SP=$(uci -q -P /var/state get wireless._${phy}.md5_${ifname}) |  | ||||||
| 	if [ "$add_sp" = "1" ]; then |  | ||||||
| 		wpa_supplicant_run "$ifname" "$hostapd_ctrl" |  | ||||||
| 	else |  | ||||||
| 		[ "${NEW_MD5_SP}" == "${OLD_MD5_SP}" ] || ubus call $spobj reload |  | ||||||
| 	fi |  | ||||||
| 	uci -q -P /var/state set wireless._${phy}.md5_${ifname}="${NEW_MD5_SP}" |  | ||||||
| 	return 0 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| mac80211_setup_supplicant_noctl() { |  | ||||||
| 	local enable=$1 |  | ||||||
| 	local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})" |  | ||||||
| 	wpa_supplicant_prepare_interface "$ifname" nl80211 || { |  | ||||||
| 		iw dev "$ifname" del |  | ||||||
| 		return 1 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" |  | ||||||
|  |  | ||||||
| 	NEWSPLIST="${NEWSPLIST}$ifname " |  | ||||||
| 	[ "$enable" = 0 ] && { |  | ||||||
| 		ubus call wpa_supplicant config_remove "{\"iface\":\"$ifname\"}" |  | ||||||
| 		ip link set dev "$ifname" down |  | ||||||
| 		return 0 |  | ||||||
| 	} |  | ||||||
| 	if [ -z "$spobj" ]; then |  | ||||||
| 		wpa_supplicant_run "$ifname" |  | ||||||
| 	else |  | ||||||
| 		ubus call $spobj reload |  | ||||||
| 	fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| mac80211_prepare_iw_htmode() { | mac80211_prepare_iw_htmode() { | ||||||
| 	case "$htmode" in | 	case "$htmode" in | ||||||
| 		VHT20|HT20) iw_htmode=HT20;; | 		VHT20|HT20|HE20) iw_htmode=HT20;; | ||||||
| 		HT40*|VHT40|VHT160) | 		HT40*|VHT40|VHT160|HE40) | ||||||
| 			case "$band" in | 			case "$band" in | ||||||
| 				2g) | 				2g) | ||||||
| 					case "$htmode" in | 					case "$htmode" in | ||||||
| @@ -942,7 +761,7 @@ mac80211_prepare_iw_htmode() { | |||||||
| 			esac | 			esac | ||||||
| 			[ "$auto_channel" -gt 0 ] && iw_htmode="HT40+" | 			[ "$auto_channel" -gt 0 ] && iw_htmode="HT40+" | ||||||
| 		;; | 		;; | ||||||
| 		VHT80) | 		VHT80|HE80) | ||||||
| 			iw_htmode="80MHZ" | 			iw_htmode="80MHZ" | ||||||
| 		;; | 		;; | ||||||
| 		NONE|NOHT) | 		NONE|NOHT) | ||||||
| @@ -952,6 +771,13 @@ mac80211_prepare_iw_htmode() { | |||||||
| 	esac | 	esac | ||||||
| } | } | ||||||
|  |  | ||||||
|  | mac80211_add_mesh_params() { | ||||||
|  | 	for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do | ||||||
|  | 		eval "mp_val=\"\$$var\"" | ||||||
|  | 		[ -n "$mp_val" ] && json_add_string "$var" "$mp_val" | ||||||
|  | 	done | ||||||
|  | } | ||||||
|  |  | ||||||
| mac80211_setup_adhoc() { | mac80211_setup_adhoc() { | ||||||
| 	local enable=$1 | 	local enable=$1 | ||||||
| 	json_get_vars bssid ssid key mcast_rate | 	json_get_vars bssid ssid key mcast_rate | ||||||
| @@ -993,81 +819,217 @@ mac80211_setup_adhoc() { | |||||||
| 	mcval= | 	mcval= | ||||||
| 	[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" | 	[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" | ||||||
|  |  | ||||||
| 	iw dev "$ifname" ibss join "$ssid" $freq $iw_htmode fixed-freq $bssid \ | 	local prev | ||||||
| 		beacon-interval $beacon_int \ | 	json_set_namespace wdev_uc prev | ||||||
| 		${brstr:+basic-rates $brstr} \ |  | ||||||
| 		${mcval:+mcast-rate $mcval} \ | 	json_add_object "$ifname" | ||||||
| 		${keyspec:+keys $keyspec} | 	json_add_string mode adhoc | ||||||
|  | 	[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr" | ||||||
|  | 	json_add_string ssid "$ssid" | ||||||
|  | 	json_add_string freq "$freq" | ||||||
|  | 	json_add_string htmode "$iw_htmode" | ||||||
|  | 	[ -n "$bssid" ] && json_add_string bssid "$bssid" | ||||||
|  | 	json_add_int beacon-interval "$beacon_int" | ||||||
|  | 	[ -n "$brstr" ] && json_add_string basic-rates "$brstr" | ||||||
|  | 	[ -n "$mcval" ] && json_add_string mcast-rate "$mcval" | ||||||
|  | 	[ -n "$keyspec" ] && json_add_string keys "$keyspec" | ||||||
|  | 	json_close_object | ||||||
|  |  | ||||||
|  | 	json_set_namespace "$prev" | ||||||
| } | } | ||||||
|  |  | ||||||
| mac80211_setup_mesh() { | mac80211_setup_mesh() { | ||||||
| 	local enable=$1 |  | ||||||
| 	json_get_vars ssid mesh_id mcast_rate | 	json_get_vars ssid mesh_id mcast_rate | ||||||
|  |  | ||||||
| 	NEWUMLIST="${NEWUMLIST}$ifname " |  | ||||||
|  |  | ||||||
| 	[ "$enable" = 0 ] && { |  | ||||||
| 		ip link set dev "$ifname" down |  | ||||||
| 		return 0 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	mcval= | 	mcval= | ||||||
| 	[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" | 	[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" | ||||||
| 	[ -n "$mesh_id" ] && ssid="$mesh_id" | 	[ -n "$mesh_id" ] && ssid="$mesh_id" | ||||||
|  |  | ||||||
| 	iw dev "$ifname" mesh join "$ssid" freq $freq $iw_htmode \ | 	local prev | ||||||
| 		${mcval:+mcast-rate $mcval} \ | 	json_set_namespace wdev_uc prev | ||||||
| 		beacon-interval $beacon_int |  | ||||||
|  | 	json_add_object "$ifname" | ||||||
|  | 	json_add_string mode mesh | ||||||
|  | 	[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr" | ||||||
|  | 	json_add_string ssid "$ssid" | ||||||
|  | 	json_add_string freq "$freq" | ||||||
|  | 	json_add_string htmode "$iw_htmode" | ||||||
|  | 	[ -n "$mcval" ] && json_add_string mcast-rate "$mcval" | ||||||
|  | 	json_add_int beacon-interval "$beacon_int" | ||||||
|  | 	mac80211_add_mesh_params | ||||||
|  |  | ||||||
|  | 	json_close_object | ||||||
|  |  | ||||||
|  | 	json_set_namespace "$prev" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | mac80211_setup_monitor() { | ||||||
|  | 	local prev | ||||||
|  | 	json_set_namespace wdev_uc prev | ||||||
|  |  | ||||||
|  | 	json_add_object "$ifname" | ||||||
|  | 	json_add_string mode monitor | ||||||
|  | 	[ -n "$freq" ] && json_add_string freq "$freq" | ||||||
|  | 	json_add_string htmode "$iw_htmode" | ||||||
|  | 	json_close_object | ||||||
|  |  | ||||||
|  | 	json_set_namespace "$prev" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | mac80211_set_vif_txpower() { | ||||||
|  | 	local name="$1" | ||||||
|  |  | ||||||
|  | 	json_select config | ||||||
|  | 	json_get_var ifname _ifname | ||||||
|  | 	json_get_vars vif_txpower wds | ||||||
|  | 	json_select .. | ||||||
|  |  | ||||||
|  | 	set_default wds 0 | ||||||
|  | 	[ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" | ||||||
|  | 	[ "$wds" -gt 0 ] && echo 1 > /sys/kernel/debug/ieee80211/$phy/netdev\:$ifname/disable_offload | ||||||
|  | } | ||||||
|  |  | ||||||
|  | wpa_supplicant_init_config() { | ||||||
|  | 	json_set_namespace wpa_supp prev | ||||||
|  |  | ||||||
|  | 	json_init | ||||||
|  | 	json_add_array config | ||||||
|  |  | ||||||
|  | 	json_set_namespace "$prev" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | wpa_supplicant_add_interface() { | ||||||
|  | 	local ifname="$1" | ||||||
|  | 	local mode="$2" | ||||||
|  | 	local prev | ||||||
|  |  | ||||||
|  | 	_wpa_supplicant_common "$ifname" | ||||||
|  |  | ||||||
|  | 	json_set_namespace wpa_supp prev | ||||||
|  |  | ||||||
|  | 	json_add_object | ||||||
|  | 	json_add_string ctrl "$_rpath" | ||||||
|  | 	json_add_string iface "$ifname" | ||||||
|  | 	json_add_string mode "$mode" | ||||||
|  | 	json_add_string config "$_config" | ||||||
|  | 	[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr" | ||||||
|  | 	[ -n "$network_bridge" ] && json_add_string bridge "$network_bridge" | ||||||
|  | 	[ -n "$wds" ] && json_add_boolean 4addr "$wds" | ||||||
|  | 	json_add_boolean powersave "$powersave" | ||||||
|  | 	[ "$mode" = "mesh" ] && mac80211_add_mesh_params | ||||||
|  | 	json_close_object | ||||||
|  |  | ||||||
|  | 	json_set_namespace "$prev" | ||||||
|  |  | ||||||
|  | 	wpa_supp_init=1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | wpa_supplicant_set_config() { | ||||||
|  | 	local phy="$1" | ||||||
|  | 	local prev | ||||||
|  |  | ||||||
|  | 	json_set_namespace wpa_supp prev | ||||||
|  | 	json_close_array | ||||||
|  | 	json_add_string phy "$phy" | ||||||
|  | 	json_add_boolean defer 1 | ||||||
|  | 	local data="$(json_dump)" | ||||||
|  |  | ||||||
|  | 	json_cleanup | ||||||
|  | 	json_set_namespace "$prev" | ||||||
|  |  | ||||||
|  | 	ubus -S -t 0 wait_for wpa_supplicant || { | ||||||
|  | 		[ -n "$wpa_supp_init" ] || return 0 | ||||||
|  |  | ||||||
|  | 		ubus wait_for wpa_supplicant | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	local supplicant_res="$(ubus call wpa_supplicant config_set "$data")" | ||||||
|  | 	ret="$?" | ||||||
|  | 	[ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED | ||||||
|  |  | ||||||
|  | 	wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1 | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | hostapd_set_config() { | ||||||
|  | 	[ -n "$hostapd_ctrl" ] || { | ||||||
|  | 		ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ubus wait_for hostapd | ||||||
|  | 	local hostapd_res="$(ubus call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" | ||||||
|  | 	ret="$?" | ||||||
|  | 	[ "$ret" != 0 -o -z "$hostapd_res" ] && { | ||||||
|  | 		wireless_setup_failed HOSTAPD_START_FAILED | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | wpa_supplicant_start() { | ||||||
|  | 	local phy="$1" | ||||||
|  |  | ||||||
|  | 	[ -n "$wpa_supp_init" ] || return 0 | ||||||
|  |  | ||||||
|  | 	ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | mac80211_setup_supplicant() { | ||||||
|  | 	local enable=$1 | ||||||
|  | 	local add_sp=0 | ||||||
|  |  | ||||||
|  | 	wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1 | ||||||
|  |  | ||||||
|  | 	if [ "$mode" = "sta" ]; then | ||||||
|  | 		wpa_supplicant_add_network "$ifname" | ||||||
|  | 	else | ||||||
|  | 		wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" | ||||||
|  | 	fi | ||||||
|  |  | ||||||
|  | 	wpa_supplicant_add_interface "$ifname" "$mode" | ||||||
|  |  | ||||||
|  | 	return 0 | ||||||
| } | } | ||||||
|  |  | ||||||
| mac80211_setup_vif() { | mac80211_setup_vif() { | ||||||
| 	local name="$1" | 	local name="$1" | ||||||
| 	local failed | 	local failed | ||||||
| 	local action=up |  | ||||||
|  |  | ||||||
| 	json_select data |  | ||||||
| 	json_get_vars ifname |  | ||||||
| 	json_select .. |  | ||||||
|  |  | ||||||
| 	json_select config | 	json_select config | ||||||
| 	json_get_vars mode | 	json_get_var ifname _ifname | ||||||
| 	json_get_var vif_txpower | 	json_get_var macaddr _macaddr | ||||||
| 	json_get_var vif_enable enable 1 | 	json_get_var default_macaddr _default_macaddr | ||||||
|  | 	json_get_vars mode wds powersave | ||||||
|  |  | ||||||
| 	[ "$vif_enable" = 1 ] || action=down | 	set_default powersave 0 | ||||||
| 	if [ "$mode" != "ap" ] || [ "$ifname" = "$ap_ifname" ]; then | 	set_default wds 0 | ||||||
| 		ip link set dev "$ifname" "$action" || { |  | ||||||
| 			wireless_setup_vif_failed IFUP_ERROR |  | ||||||
| 			json_select .. |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		[ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| 	case "$mode" in | 	case "$mode" in | ||||||
| 		mesh) | 		mesh) | ||||||
|  | 			json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING | ||||||
| 			wireless_vif_parse_encryption | 			wireless_vif_parse_encryption | ||||||
| 			[ -z "$htmode" ] && htmode="NOHT"; | 			[ -z "$htmode" ] && htmode="NOHT"; | ||||||
| 			if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ] || chan_is_dfs "$phy" "$channel"; then | 			if wpa_supplicant -vmesh; then | ||||||
| 				mac80211_setup_supplicant $vif_enable || failed=1 | 				mac80211_setup_supplicant || failed=1 | ||||||
| 			else | 			else | ||||||
| 				mac80211_setup_mesh $vif_enable | 				mac80211_setup_mesh | ||||||
| 			fi | 			fi | ||||||
| 			for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do |  | ||||||
| 				json_get_var mp_val "$var" |  | ||||||
| 				[ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val" |  | ||||||
| 			done |  | ||||||
| 		;; | 		;; | ||||||
| 		adhoc) | 		adhoc) | ||||||
| 			wireless_vif_parse_encryption | 			wireless_vif_parse_encryption | ||||||
| 			if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then | 			if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then | ||||||
| 				mac80211_setup_supplicant_noctl $vif_enable || failed=1 | 				mac80211_setup_supplicant || failed=1 | ||||||
| 			else | 			else | ||||||
| 				mac80211_setup_adhoc $vif_enable | 				mac80211_setup_adhoc | ||||||
| 			fi | 			fi | ||||||
| 		;; | 		;; | ||||||
| 		sta) | 		sta) | ||||||
| 			mac80211_setup_supplicant $vif_enable || failed=1 | 			mac80211_setup_supplicant || failed=1 | ||||||
|  | 		;; | ||||||
|  | 		monitor) | ||||||
|  | 			mac80211_setup_monitor | ||||||
| 		;; | 		;; | ||||||
| 	esac | 	esac | ||||||
|  |  | ||||||
| @@ -1100,7 +1062,6 @@ band_match && $3 == "MHz" && $4 == channel { | |||||||
| ' | ' | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| chan_is_dfs() { | chan_is_dfs() { | ||||||
| 	local phy="$1" | 	local phy="$1" | ||||||
| 	local chan="$2" | 	local chan="$2" | ||||||
| @@ -1108,27 +1069,6 @@ chan_is_dfs() { | |||||||
| 	return $! | 	return $! | ||||||
| } | } | ||||||
|  |  | ||||||
| mac80211_vap_cleanup() { |  | ||||||
| 	local service="$1" |  | ||||||
| 	local vaps="$2" |  | ||||||
|  |  | ||||||
| 	for wdev in $vaps; do |  | ||||||
| 		[ "$service" != "none" ] && ubus call ${service} config_remove "{\"iface\":\"$wdev\"}" |  | ||||||
| 		ip link set dev "$wdev" down 2>/dev/null |  | ||||||
| 		iw dev "$wdev" del |  | ||||||
| 	done |  | ||||||
| } |  | ||||||
|  |  | ||||||
| mac80211_interface_cleanup() { |  | ||||||
| 	local phy="$1" |  | ||||||
| 	local primary_ap=$(uci -q -P /var/state get wireless._${phy}.aplist) |  | ||||||
| 	primary_ap=${primary_ap%% *} |  | ||||||
|  |  | ||||||
| 	mac80211_vap_cleanup hostapd "${primary_ap}" |  | ||||||
| 	mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)" |  | ||||||
| 	mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| mac80211_set_noscan() { | mac80211_set_noscan() { | ||||||
| 	hostapd_noscan=1 | 	hostapd_noscan=1 | ||||||
| } | } | ||||||
| @@ -1137,6 +1077,15 @@ drv_mac80211_cleanup() { | |||||||
| 	hostapd_common_cleanup | 	hostapd_common_cleanup | ||||||
| } | } | ||||||
|  |  | ||||||
|  | mac80211_reset_config() { | ||||||
|  | 	local phy="$1" | ||||||
|  |  | ||||||
|  | 	hostapd_conf_file="/var/run/hostapd-$phy.conf" | ||||||
|  | 	ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null | ||||||
|  | 	ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null | ||||||
|  | 	wdev_tool "$phy" set_config '{}' | ||||||
|  | } | ||||||
|  |  | ||||||
| drv_mac80211_setup() { | drv_mac80211_setup() { | ||||||
| 	json_select config | 	json_select config | ||||||
| 	json_get_vars \ | 	json_get_vars \ | ||||||
| @@ -1151,6 +1100,12 @@ drv_mac80211_setup() { | |||||||
| 	json_get_values scan_list scan_list | 	json_get_values scan_list scan_list | ||||||
| 	json_select .. | 	json_select .. | ||||||
|  |  | ||||||
|  | 	json_select data && { | ||||||
|  | 		json_get_var prev_rxantenna rxantenna | ||||||
|  | 		json_get_var prev_txantenna txantenna | ||||||
|  | 		json_select .. | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	find_phy || { | 	find_phy || { | ||||||
| 		echo "Could not find PHY for device '$1'" | 		echo "Could not find PHY for device '$1'" | ||||||
| 		wireless_set_retry 0 | 		wireless_set_retry 0 | ||||||
| @@ -1159,31 +1114,10 @@ drv_mac80211_setup() { | |||||||
| 	 | 	 | ||||||
| 	[ "$band" = "6g" ] && set_default multiple_bssid 1 | 	[ "$band" = "6g" ] && set_default multiple_bssid 1 | ||||||
|  |  | ||||||
| 	wireless_set_data phy="$phy" |  | ||||||
| 	[ -z "$(uci -q -P /var/state show wireless._${phy})" ] && uci -q -P /var/state set wireless._${phy}=phy |  | ||||||
|  |  | ||||||
| 	OLDAPLIST=$(uci -q -P /var/state get wireless._${phy}.aplist) |  | ||||||
| 	OLDSPLIST=$(uci -q -P /var/state get wireless._${phy}.splist) |  | ||||||
| 	OLDUMLIST=$(uci -q -P /var/state get wireless._${phy}.umlist) |  | ||||||
|  |  | ||||||
| 	local wdev | 	local wdev | ||||||
| 	local cwdev | 	local cwdev | ||||||
| 	local found | 	local found | ||||||
|  |  | ||||||
| 	for wdev in $(list_phy_interfaces "$phy"); do |  | ||||||
| 		found=0 |  | ||||||
| 		for cwdev in $OLDAPLIST $OLDSPLIST $OLDUMLIST; do |  | ||||||
| 			if [ "$wdev" = "$cwdev" ]; then |  | ||||||
| 				found=1 |  | ||||||
| 				break |  | ||||||
| 			fi |  | ||||||
| 		done |  | ||||||
| 		if [ "$found" = "0" ]; then |  | ||||||
| 			ip link set dev "$wdev" down |  | ||||||
| 			iw dev "$wdev" del |  | ||||||
| 		fi |  | ||||||
| 	done |  | ||||||
|  |  | ||||||
| 	# convert channel to frequency | 	# convert channel to frequency | ||||||
| 	[ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel" "$band")" | 	[ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel" "$band")" | ||||||
|  |  | ||||||
| @@ -1196,7 +1130,6 @@ drv_mac80211_setup() { | |||||||
|  |  | ||||||
| 	hostapd_conf_file="/var/run/hostapd-$phy.conf" | 	hostapd_conf_file="/var/run/hostapd-$phy.conf" | ||||||
|  |  | ||||||
| 	no_ap=1 |  | ||||||
| 	macidx=0 | 	macidx=0 | ||||||
| 	staidx=0 | 	staidx=0 | ||||||
|  |  | ||||||
| @@ -1215,6 +1148,9 @@ drv_mac80211_setup() { | |||||||
| 	[ "$txantenna" = "all" ] && txantenna=0xffffffff | 	[ "$txantenna" = "all" ] && txantenna=0xffffffff | ||||||
| 	[ "$rxantenna" = "all" ] && rxantenna=0xffffffff | 	[ "$rxantenna" = "all" ] && rxantenna=0xffffffff | ||||||
|  |  | ||||||
|  | 	[ "$rxantenna" = "$prev_rxantenna" -a "$txantenna" = "$prev_txantenna" ] || mac80211_reset_config "$phy" | ||||||
|  | 	wireless_set_data phy="$phy" txantenna="$txantenna" rxantenna="$rxantenna" | ||||||
|  |  | ||||||
| 	iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1 | 	iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1 | ||||||
| 	iw phy "$phy" set antenna_gain $antenna_gain >/dev/null 2>&1 | 	iw phy "$phy" set antenna_gain $antenna_gain >/dev/null 2>&1 | ||||||
| 	iw phy "$phy" set distance "$distance" >/dev/null 2>&1 | 	iw phy "$phy" set distance "$distance" >/dev/null 2>&1 | ||||||
| @@ -1232,81 +1168,36 @@ drv_mac80211_setup() { | |||||||
| 	hostapd_ctrl= | 	hostapd_ctrl= | ||||||
| 	ap_ifname= | 	ap_ifname= | ||||||
| 	hostapd_noscan= | 	hostapd_noscan= | ||||||
|  | 	wpa_supp_init= | ||||||
| 	for_each_interface "ap" mac80211_check_ap | 	for_each_interface "ap" mac80211_check_ap | ||||||
|  |  | ||||||
| 	rm -f "$hostapd_conf_file" | 	[ -f "$hostapd_conf_file" ] && mv "$hostapd_conf_file" "$hostapd_conf_file.prev" | ||||||
|  |  | ||||||
| 	for_each_interface "sta adhoc mesh" mac80211_set_noscan | 	for_each_interface "sta adhoc mesh" mac80211_set_noscan | ||||||
| 	[ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy" | 	[ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy" | ||||||
|  |  | ||||||
|  | 	local prev | ||||||
|  | 	json_set_namespace wdev_uc prev | ||||||
|  | 	json_init | ||||||
|  | 	json_set_namespace "$prev" | ||||||
|  |  | ||||||
|  | 	wpa_supplicant_init_config | ||||||
|  |  | ||||||
| 	mac80211_prepare_iw_htmode | 	mac80211_prepare_iw_htmode | ||||||
| 	for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif | 	active_ifnames= | ||||||
| 	NEWAPLIST= | 	for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif | ||||||
| 	for_each_interface "ap" mac80211_prepare_vif ${multiple_bssid} | 	for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif | ||||||
| 	NEW_MD5=$(test -e "${hostapd_conf_file}" && md5sum ${hostapd_conf_file}) |  | ||||||
| 	OLD_MD5=$(uci -q -P /var/state get wireless._${phy}.md5) |  | ||||||
| 	if [ "${NEWAPLIST}" != "${OLDAPLIST}" ]; then |  | ||||||
| 		mac80211_vap_cleanup hostapd "${OLDAPLIST}" |  | ||||||
| 	fi |  | ||||||
| 	[ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap |  | ||||||
| 	local add_ap=0 |  | ||||||
| 	local primary_ap=${NEWAPLIST%% *} |  | ||||||
| 	[ -n "$hostapd_ctrl" ] && { |  | ||||||
| 		local no_reload=1 |  | ||||||
| 		if [ -n "$(ubus list | grep hostapd.$primary_ap)" ]; then |  | ||||||
| 			no_reload=0 |  | ||||||
| 			[ "${NEW_MD5}" = "${OLD_MD5}" ] || { |  | ||||||
| 				ubus call hostapd.$primary_ap reload |  | ||||||
| 				no_reload=$? |  | ||||||
| 				if [ "$no_reload" != "0" ]; then |  | ||||||
| 					mac80211_vap_cleanup hostapd "${OLDAPLIST}" |  | ||||||
| 					mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)" |  | ||||||
| 					mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)" |  | ||||||
| 					sleep 2 |  | ||||||
| 					mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap |  | ||||||
| 					for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif |  | ||||||
| 				fi |  | ||||||
| 			} |  | ||||||
| 		fi |  | ||||||
| 		if [ "$no_reload" != "0" ]; then |  | ||||||
| 			add_ap=1 |  | ||||||
| 			ubus wait_for hostapd |  | ||||||
| 			local hostapd_res |  | ||||||
| 			[ -f /tmp/wifi_fail_test ] || hostapd_res="$(ubus call hostapd config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}")" |  | ||||||
| 			ret="$?" |  | ||||||
| 			rm -f /tmp/wifi_fail_test |  | ||||||
| 			[ "$ret" != 0 -o -z "$hostapd_res" ] && { |  | ||||||
| 				logger failed to start wifi trying again |  | ||||||
| 			#	wireless_setup_failed HOSTAPD_START_FAILED |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 			wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 |  | ||||||
| 		fi |  | ||||||
| 	} |  | ||||||
| 	uci -q -P /var/state set wireless._${phy}.aplist="${NEWAPLIST}" |  | ||||||
| 	uci -q -P /var/state set wireless._${phy}.md5="${NEW_MD5}" |  | ||||||
|  |  | ||||||
| 	[ "${add_ap}" = 1 ] && sleep 1 | 	[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" | ||||||
| 	for_each_interface "ap" mac80211_setup_vif | 	[ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" | ||||||
|  |  | ||||||
| 	NEWSPLIST= | 	[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy" | ||||||
| 	NEWUMLIST= |  | ||||||
|  |  | ||||||
| 	for_each_interface "sta adhoc mesh monitor" mac80211_setup_vif | 	json_set_namespace wdev_uc prev | ||||||
|  | 	wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames | ||||||
|  | 	json_set_namespace "$prev" | ||||||
|  |  | ||||||
| 	uci -q -P /var/state set wireless._${phy}.splist="${NEWSPLIST}" | 	for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower | ||||||
| 	uci -q -P /var/state set wireless._${phy}.umlist="${NEWUMLIST}" |  | ||||||
|  |  | ||||||
| 	local foundvap |  | ||||||
| 	local dropvap="" |  | ||||||
| 	for oldvap in $OLDSPLIST; do |  | ||||||
| 		foundvap=0 |  | ||||||
| 		for newvap in $NEWSPLIST; do |  | ||||||
| 			[ "$oldvap" = "$newvap" ] && foundvap=1 |  | ||||||
| 		done |  | ||||||
| 		[ "$foundvap" = "0" ] && dropvap="$dropvap $oldvap" |  | ||||||
| 	done |  | ||||||
| 	[ -n "$dropvap" ] && mac80211_vap_cleanup wpa_supplicant "$dropvap" |  | ||||||
| 	wireless_set_up | 	wireless_set_up | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1337,8 +1228,12 @@ drv_mac80211_teardown() { | |||||||
| 		return 1 | 		return 1 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	mac80211_interface_cleanup "$phy" | 	mac80211_reset_config "$phy" | ||||||
| 	uci -q -P /var/state revert wireless._${phy} |  | ||||||
|  | 	for wdev in $(list_phy_interfaces "$phy"); do | ||||||
|  | 		ip link set dev "$wdev" down | ||||||
|  | 		iw dev "$wdev" del | ||||||
|  | 	done | ||||||
| } | } | ||||||
|  |  | ||||||
| add_driver mac80211 | add_driver mac80211 | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ define KernelPackage/nat46 | |||||||
|   SECTION:=kernel |   SECTION:=kernel | ||||||
|   SUBMENU:=Network Support |   SUBMENU:=Network Support | ||||||
|   FILES:=$(PKG_BUILD_DIR)/nat46/modules/nat46.ko |   FILES:=$(PKG_BUILD_DIR)/nat46/modules/nat46.ko | ||||||
|   AUTOLOAD:=$(call AutoLoad,33,nat46) |   AUTOLOAD:=$(call AutoLoad,29,nat46) | ||||||
| endef | endef | ||||||
|  |  | ||||||
| include $(INCLUDE_DIR)/kernel-defaults.mk | include $(INCLUDE_DIR)/kernel-defaults.mk | ||||||
|   | |||||||
| @@ -25,8 +25,7 @@ define KernelPackage/qca-nss-dp | |||||||
| 		+TARGET_ipq53xx:kmod-qca-nss-ppe | 		+TARGET_ipq53xx:kmod-qca-nss-ppe | ||||||
|   TITLE:=Kernel driver for NSS data plane |   TITLE:=Kernel driver for NSS data plane | ||||||
|   FILES:=$(PKG_BUILD_DIR)/qca-nss-dp.ko |   FILES:=$(PKG_BUILD_DIR)/qca-nss-dp.ko | ||||||
| #  AUTOLOAD:=$(call AutoLoad,31,qca-nss-dp) |   AUTOLOAD:=$(call AutoLoad,60,qca-nss-dp) | ||||||
|   AUTOLOAD:=$(call AutoProbe,qca-nss-dp) |  | ||||||
| endef | endef | ||||||
|  |  | ||||||
| define KernelPackage/qca-nss-dp/Description | define KernelPackage/qca-nss-dp/Description | ||||||
| @@ -92,6 +91,7 @@ define Build/Compile | |||||||
| 		ARCH="$(LINUX_KARCH)" \ | 		ARCH="$(LINUX_KARCH)" \ | ||||||
| 		M="$(PKG_BUILD_DIR)" \ | 		M="$(PKG_BUILD_DIR)" \ | ||||||
| 		EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(hal_arch)" \ | 		EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(hal_arch)" \ | ||||||
|  | 		KBUILD_MODPOST_WARN=1 \ | ||||||
| 		modules | 		modules | ||||||
| endef | endef | ||||||
|  |  | ||||||
|   | |||||||
| @@ -148,7 +148,7 @@ define Build/Compile | |||||||
| 		M="$(PKG_BUILD_DIR)" \ | 		M="$(PKG_BUILD_DIR)" \ | ||||||
| 		EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ | 		EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ | ||||||
| 		SoC="$(subtarget)" \ | 		SoC="$(subtarget)" \ | ||||||
| 		BUILD_MODPOST_WARN=1 \ | 		KBUILD_MODPOST_WARN=1 \ | ||||||
| 		modules | 		modules | ||||||
| endef | endef | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								feeds/ipq95xx/qca-ssdk/patches/100-compile.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								feeds/ipq95xx/qca-ssdk/patches/100-compile.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | Index: qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed/src/adpt/appe/adpt_appe_vxlan.c | ||||||
|  | =================================================================== | ||||||
|  | --- qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed.orig/src/adpt/appe/adpt_appe_vxlan.c | ||||||
|  | +++ qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed/src/adpt/appe/adpt_appe_vxlan.c | ||||||
|  | @@ -150,7 +150,7 @@ sw_error_t | ||||||
|  |  adpt_appe_vxlan_entry_add(a_uint32_t dev_id, fal_vxlan_type_t type, | ||||||
|  |  						fal_tunnel_udp_entry_t * entry) | ||||||
|  |  { | ||||||
|  | -	a_uint32_t idx, entry_idx, entry_sign; | ||||||
|  | +	a_uint32_t idx, entry_idx = 0, entry_sign; | ||||||
|  |  	a_bool_t entry_inuse; | ||||||
|  |  	a_int32_t vxlan_port_bitmap; | ||||||
|  |  	fal_tunnel_udp_entry_t temp_entry; | ||||||
|  | Index: qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed/src/adpt/appe/adpt_appe_geneve.c | ||||||
|  | =================================================================== | ||||||
|  | --- qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed.orig/src/adpt/appe/adpt_appe_geneve.c | ||||||
|  | +++ qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed/src/adpt/appe/adpt_appe_geneve.c | ||||||
|  | @@ -30,7 +30,7 @@ | ||||||
|  |  sw_error_t | ||||||
|  |  adpt_appe_geneve_entry_add(a_uint32_t dev_id, fal_tunnel_udp_entry_t * entry) | ||||||
|  |  { | ||||||
|  | -	a_uint32_t idx, entry_idx, entry_sign; | ||||||
|  | +	a_uint32_t idx, entry_idx = 0, entry_sign; | ||||||
|  |  	a_bool_t entry_inuse; | ||||||
|  |  	a_int32_t geneve_port_bitmap; | ||||||
|  |  	fal_tunnel_udp_entry_t temp_entry; | ||||||
|  | Index: qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed/src/adpt/appe/adpt_appe_tunnel_program.c | ||||||
|  | =================================================================== | ||||||
|  | --- qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed.orig/src/adpt/appe/adpt_appe_tunnel_program.c | ||||||
|  | +++ qca-ssdk-9e687f44ee13ce0904f291c9771172b488b7f9ed/src/adpt/appe/adpt_appe_tunnel_program.c | ||||||
|  | @@ -502,7 +502,7 @@ sw_error_t | ||||||
|  |  adpt_appe_tunnel_program_entry_add(a_uint32_t dev_id, | ||||||
|  |  		fal_tunnel_program_type_t type, fal_tunnel_program_entry_t * entry) | ||||||
|  |  { | ||||||
|  | -	a_uint32_t idx, entry_idx, entry_sign; | ||||||
|  | +	a_uint32_t idx, entry_idx = 0, entry_sign; | ||||||
|  |  	a_int32_t program_port_bitmap, program_id; | ||||||
|  |  	fal_tunnel_program_entry_t temp_entry = {0}; | ||||||
|  |   | ||||||
|  | @@ -746,7 +746,7 @@ sw_error_t | ||||||
|  |  adpt_appe_tunnel_program_udf_add(a_uint32_t dev_id, | ||||||
|  |  		fal_tunnel_program_type_t type, fal_tunnel_program_udf_t * udf) | ||||||
|  |  { | ||||||
|  | -	a_uint32_t idx, entry_idx; | ||||||
|  | +	a_uint32_t idx, entry_idx = 0; | ||||||
|  |  	a_int32_t program_id, temp_program_id; | ||||||
|  |  	fal_tunnel_program_udf_t temp_udf = {0}; | ||||||
|  |  	a_bool_t entry_sign = A_FALSE; | ||||||
		Reference in New Issue
	
	Block a user
	 John Crispin
					John Crispin