ipq9574: add wifi hot-reload

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2023-09-29 13:22:13 +02:00
parent 171607a03d
commit aa245da361
87 changed files with 8713 additions and 2012 deletions

View File

@@ -85,6 +85,8 @@ ifneq ($(CONFIG_DRIVER_11AX_SUPPORT),)
HOSTAPD_IEEE80211BE:=y
endif
CORE_DEPENDS = +libubus +libucode +ucode-mod-fs +ucode-mod-nl80211 +ucode-mod-ubus +ucode-mod-uloop +ucode-mod-rtnl +libblobmsg-json
DRIVER_MAKEOPTS= \
CONFIG_ACS=$(CONFIG_PACKAGE_kmod-cfg80211) \
CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-cfg80211) \
@@ -93,6 +95,7 @@ DRIVER_MAKEOPTS= \
CONFIG_IEEE80211AX=$(HOSTAPD_IEEE80211AX) \
CONFIG_IEEE80211BE=$(HOSTAPD_IEEE80211BE) \
CONFIG_DRIVER_WEXT=$(CONFIG_DRIVER_WEXT_SUPPORT) \
CONFIG_UCODE=y
ifeq ($(SSL_VARIANT),openssl)
DRIVER_MAKEOPTS += CONFIG_TLS=openssl CONFIG_SAE=y
@@ -144,7 +147,7 @@ define Package/hostapd/Default
SUBMENU:=WirelessAPD
TITLE:=IEEE 802.1x Authenticator
URL:=http://hostap.epitest.fi/
DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus
DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
USERID:=network=101:network=101
PROVIDES:=hostapd
CONFLICTS:=$(HOSTAPD_PROVIDERS)
@@ -228,7 +231,7 @@ define Package/wpad/Default
CATEGORY:=Network
SUBMENU:=WirelessAPD
TITLE:=IEEE 802.1x Auth/Supplicant
DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus
DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
USERID:=network=101:network=101
URL:=http://hostap.epitest.fi/
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))
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
TARGET_LDFLAGS += -lm -lnl-tiny
@@ -589,20 +592,24 @@ define Build/Compile
endef
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
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
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_BIN) ./files/wpad.init $(1)/etc/init.d/wpad
$(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.json $(1)/etc/capabilities
$(INSTALL_DATA) ./files/common.uc $(1)/usr/share/hostap/
$(INSTALL_DATA) ./files/wdev.uc $(1)/usr/share/hostap/
endef
define Package/hostapd/install

View 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 };

View File

@@ -725,8 +725,7 @@ hostapd_set_bss_options() {
[ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N"
}
set_default nasid "${macaddr//\:}"
append bss_conf "nas_identifier=$nasid" "$N"
[ -n "$nasid" ] && append bss_conf "nas_identifier=$nasid" "$N"
[ -n "$acct_server" ] && {
append bss_conf "acct_server_addr=$acct_server" "$N"
@@ -771,8 +770,8 @@ hostapd_set_bss_options() {
wps_possible=1
# Here we make the assumption that if we're in open mode
# with WPS enabled, we got to be in unconfigured state.
vlan_possible=1
wps_not_configured=1
vlan_possible=1
[ "$macfilter" = radius ] && {
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"
set_default dynamic_vlan 0
[ "$macfilter" = radius ] && {
append_radius_server
}
vlan_possible=1
wps_possible=1
;;
@@ -1203,9 +1205,6 @@ hostapd_set_bss_options() {
append bss_conf "$val" "$N"
done
bss_md5sum=$(echo $bss_conf | md5sum | cut -d" " -f1)
append bss_conf "config_id=$bss_md5sum" "$N"
append "$var" "$bss_conf" "$N"
return 0
}

View 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);
}
};

View 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);

View 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);
}
};

View File

@@ -72,7 +72,7 @@
include ../src/build.rules
ifdef LIBS
@@ -359,7 +360,9 @@ endif
@@ -354,7 +355,9 @@ endif
ifdef CONFIG_IBSS_RSN
NEED_RSN_AUTHENTICATOR=y
CFLAGS += -DCONFIG_IBSS_RSN
@@ -82,7 +82,7 @@
OBJS += ibss_rsn.o
endif
@@ -897,6 +900,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
@@ -886,6 +889,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
LIBS += -ldl -rdynamic
endif
@@ -93,7 +93,7 @@
endif
ifdef CONFIG_AP
@@ -904,9 +911,11 @@ NEED_EAP_COMMON=y
@@ -893,9 +900,11 @@ NEED_EAP_COMMON=y
NEED_RSN_AUTHENTICATOR=y
CFLAGS += -DCONFIG_AP
OBJS += ap.o
@@ -105,7 +105,7 @@
OBJS += ../src/ap/hostapd.o
OBJS += ../src/ap/wpa_auth_glue.o
OBJS += ../src/ap/utils.o
@@ -986,6 +995,12 @@ endif
@@ -975,6 +984,12 @@ endif
ifdef CONFIG_HS20
OBJS += ../src/ap/hs20.o
endif
@@ -118,7 +118,7 @@
endif
ifdef CONFIG_MBO
@@ -994,7 +1009,9 @@ CFLAGS += -DCONFIG_MBO
@@ -983,7 +998,9 @@ CFLAGS += -DCONFIG_MBO
endif
ifdef NEED_RSN_AUTHENTICATOR
@@ -128,7 +128,7 @@
NEED_AES_WRAP=y
OBJS += ../src/ap/wpa_auth.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
include ../src/objs.mk
@@ -141,7 +141,7 @@
wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
$(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
@$(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' $< >$@
@$(E) " sed" $<
@@ -156,7 +156,7 @@
wpa_cli.exe: wpa_cli
--- a/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
* from the driver.
*/
@@ -167,7 +167,7 @@
/**
* 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
* wpa_global.
*/
@@ -178,7 +178,7 @@
/*
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -1836,8 +1836,8 @@ err:
@@ -1827,8 +1827,8 @@ err:
#endif /* CONFIG_OWE */
@@ -189,7 +189,7 @@
{
struct hostapd_data *hapd = ctx;
#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));
--- a/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;
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;
--- a/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;
}
@@ -261,7 +261,7 @@
/**
* wpa_supplicant_match_existing - Match existing interfaces
* @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 */
@@ -273,7 +273,7 @@
/**
* 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
wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
#endif /* CONFIG_NO_WPA_MSG */
@@ -333,7 +333,7 @@
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");
}
@@ -344,7 +344,7 @@
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())
return -1;

View File

@@ -1,6 +1,6 @@
--- a/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)
bss->ieee80211w = 1;
#endif /* CONFIG_OCV */
@@ -13,7 +13,7 @@
} else if (os_strcmp(buf, "ht_capab") == 0) {
--- a/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;
u16 ht_capab;

View File

@@ -1,6 +1,6 @@
--- a/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)
return NULL;
wpa_s->scan_req = INITIAL_SCAN_REQ;

View File

@@ -1,6 +1,6 @@
--- a/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_NETLINK=y
NEED_LINUX_IOCTL=y
@@ -8,7 +8,7 @@
NEED_RADIOTAP=y
NEED_LIBNL=y
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
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
@@ -16,7 +16,7 @@
endif
ifdef CONFIG_DRIVER_NDIS
@@ -137,7 +135,6 @@ endif
@@ -133,7 +131,6 @@ endif
ifdef CONFIG_WIRELESS_EXTENSION
DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION
DRV_WPA_OBJS += ../src/drivers/driver_wext.o
@@ -24,7 +24,7 @@
endif
ifdef NEED_NETLINK
@@ -146,6 +143,7 @@ endif
@@ -142,6 +139,7 @@ endif
ifdef NEED_RFKILL
DRV_OBJS += ../src/drivers/rfkill.o

View File

@@ -1,6 +1,6 @@
--- a/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->bandwidth, freq->center_freq1, freq->center_freq2);

View File

@@ -1,6 +1,6 @@
--- a/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 wpa_driver_nl80211_data *drv = bss->drv;
@@ -18,7 +18,7 @@
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_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 {
wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
nl80211_teardown_ap(bss);
@@ -36,7 +36,7 @@
nl80211_destroy_bss(bss);
if (!bss->added_if)
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))
return -1;
wpa_driver_nl80211_del_beacon(bss);
@@ -44,7 +44,7 @@
/*
* 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))
return -1;
wpa_driver_nl80211_del_beacon(bss);

View File

@@ -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;
}

View File

@@ -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, &params) < 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:

View File

@@ -12,7 +12,7 @@
else
--- a/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);
} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
reply_len = hostapd_drv_status(hapd, reply, reply_size);
@@ -20,7 +20,7 @@
} else if (os_strcmp(buf, "MIB") == 0) {
reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
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) {
reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
reply_size);
@@ -30,7 +30,7 @@
reply_len = -1;
--- a/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
endif
ifdef CONFIG_CTRL_IFACE
@@ -42,7 +42,7 @@
--- a/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;
}
@@ -51,7 +51,7 @@
if (wpa_s->ap_iface) {
pos += ap_ctrl_iface_wpa_get_status(wpa_s, 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;
} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
@@ -59,7 +59,7 @@
} else if (os_strcmp(buf, "MIB") == 0) {
reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
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);
#endif /* CONFIG_MACSEC */
}
@@ -67,7 +67,7 @@
} else if (os_strncmp(buf, "STATUS", 6) == 0) {
reply_len = wpa_supplicant_ctrl_iface_status(
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(
wpa_s, buf + 4, reply, reply_size);
#ifdef CONFIG_AP
@@ -75,7 +75,7 @@
} else if (os_strcmp(buf, "STA-FIRST") == 0) {
reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
} 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) {
reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
reply_size);
@@ -144,7 +144,7 @@
static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
--- a/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";
}
@@ -152,7 +152,7 @@
#define RSN_SUITE "%02x-%02x-%02x-%d"
#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;
}
@@ -163,7 +163,7 @@
{
--- a/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_ARG(s) \
((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;
}

View File

@@ -36,16 +36,16 @@
#include "fst/fst.h"
#include "wpa_supplicant_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 (;;) {
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: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:qsTtuvW");
+ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuv::W");
if (c < 0)
break;
switch (c) {
@@ -305,8 +306,12 @@ int main(int argc, char *argv[])
@@ -301,8 +302,12 @@ int main(int argc, char *argv[])
break;
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
case 'v':

View File

@@ -32,7 +32,7 @@
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,
hostapd_complete_stations,
"<addr> = disassociate a station" },
@@ -46,7 +46,7 @@
{ "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
"<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
{ "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" },
{ "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
"= show current WPS status" },

View File

@@ -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;

View File

@@ -174,7 +174,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
* macsec_policy - Determines the policy for MACsec secure session
--- a/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;
else
params.beacon_int = wpa_s->conf->beacon_int;

View File

@@ -10,7 +10,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
--- a/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 nl_msg *msg;
@@ -19,7 +19,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
int count = 0;
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))
goto fail;

View File

@@ -29,7 +29,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
struct wpa_driver_set_key_params {
--- a/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,
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_mesh_id(msg, params->meshid, params->meshid_len) ||
nl80211_put_beacon_int(msg, params->beacon_int) ||

View File

@@ -1,6 +1,6 @@
--- a/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++) {
struct wpa_bss *bss = wpa_s->last_scan_res[j];

View File

@@ -20,7 +20,7 @@
NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS)
--- a/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)
wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)

View File

@@ -1,6 +1,6 @@
--- a/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 {
@@ -163,6 +178,9 @@ struct hostapd_data {
@@ -161,6 +176,9 @@ struct hostapd_data {
u8 own_addr[ETH_ALEN];
@@ -71,7 +71,7 @@
if (disassoc_timer) {
/* send disassociation frame after time-out */
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);

View File

@@ -1,19 +1,24 @@
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -166,6 +166,11 @@ OBJS += ../src/common/hw_features_common
Index: hostapd-2021-02-20-59e9794c/hostapd/Makefile
===================================================================
--- 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
+ifdef CONFIG_UBUS
+CFLAGS += -DUBUS_SUPPORT
+OBJS += ../src/utils/uloop.o
+OBJS += ../src/ap/ubus.o
+LIBS += -lubox -lubus
+endif
ifdef CONFIG_CODE_COVERAGE
CFLAGS += -O0 -fprofile-arcs -ftest-coverage
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
Index: hostapd-2021-02-20-59e9794c/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 @@
#include "utils/list.h"
#include "ap_config.h"
@@ -22,16 +27,7 @@
#define OCE_STA_CFON_ENABLED(hapd) \
((hapd->conf->oce & OCE_STA_CFON) && \
@@ -80,7 +81,7 @@ struct hapd_interfaces {
#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 {
@@ -169,6 +170,7 @@ struct hostapd_data {
struct hostapd_iface *iface;
struct hostapd_config *iconf;
struct hostapd_bss_config *conf;
@@ -39,7 +35,7 @@
int interface_added; /* virtual interface added for this BSS */
unsigned int started: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);
int hostapd_setup_interface(struct hostapd_iface *iface);
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_free(struct hostapd_iface *iface);
struct hostapd_iface * hostapd_alloc_iface(void);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -396,6 +396,7 @@ void hostapd_free_hapd_data(struct hosta
Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
===================================================================
--- 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;
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
@@ -57,7 +55,7 @@
accounting_deinit(hapd);
hostapd_deinit_wpa(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)
hapd->driver->set_operstate(hapd->drv_priv, 1);
@@ -66,7 +64,7 @@
return 0;
}
@@ -2028,6 +2031,7 @@ static int hostapd_setup_interface_compl
@@ -1983,6 +1986,7 @@ static int hostapd_setup_interface_compl
if (err)
goto fail;
@@ -74,7 +72,7 @@
wpa_printf(MSG_DEBUG, "Completing interface initialization");
if (iface->freq) {
#ifdef NEED_AP_MLME
@@ -2225,6 +2229,7 @@ dfs_offload:
@@ -2180,6 +2184,7 @@ dfs_offload:
fail:
wpa_printf(MSG_ERROR, "Interface initialization failed");
@@ -82,7 +80,7 @@
hostapd_set_state(iface, HAPD_IFACE_DISABLED);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
#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);
driver = iface->bss[0]->driver;
drv_priv = iface->bss[0]->drv_priv;
@@ -90,9 +88,11 @@
hostapd_interface_deinit(iface);
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
__func__, driver, drv_priv);
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -3553,13 +3553,18 @@ static void handle_auth(struct hostapd_d
Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c
===================================================================
--- 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 resp = WLAN_STATUS_SUCCESS;
struct sta_info *sta = NULL;
@@ -112,7 +112,7 @@
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
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;
goto fail;
}
@@ -126,7 +126,7 @@
if (res == HOSTAPD_ACL_PENDING)
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;
u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
const u8 *pos;
@@ -135,7 +135,7 @@
struct sta_info *sta;
u8 *tmp = NULL;
#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;
}
#endif /* CONFIG_FILS */
@@ -147,7 +147,7 @@
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
* 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 */
@@ -161,7 +161,7 @@
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",
MAC2STR(mgmt->sa),
le_to_host16(mgmt->u.disassoc.reason_code));
@@ -169,18 +169,20 @@
sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL) {
@@ -5920,6 +5945,8 @@ static void handle_deauth(struct hostapd
/* Clear the PTKSA cache entries for PASN */
ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
@@ -5792,6 +5817,8 @@ static void handle_deauth(struct hostapd
" reason_code=%d",
MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
+ hostapd_ubus_notify(hapd, "deauth", mgmt->sa);
+
sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -852,6 +852,12 @@ void handle_probe_req(struct hostapd_dat
Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c
===================================================================
--- 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];
size_t csa_offs_len;
struct radius_sta rad_info;
@@ -193,7 +195,7 @@
if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
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 */
@@ -206,8 +208,10 @@
/* TODO: verify that supp_rates contains at least one matching rate
* with AP configuration */
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
Index: hostapd-2021-02-20-59e9794c/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
u16 reason = WLAN_REASON_UNSPECIFIED;
int status = WLAN_STATUS_SUCCESS;
@@ -232,8 +236,22 @@
#ifdef CONFIG_P2P
if (elems.p2p) {
wpabuf_free(sta->p2p_ie);
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -981,9 +991,11 @@ void hostapd_event_ch_switch(struct host
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
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
@@ -250,16 +268,72 @@
ap_free_sta(hapd, sta);
break;
}
@@ -1329,6 +1331,7 @@ void ap_sta_set_authorized(struct hostap
buf, ip_addr, keyid_buf);
@@ -1298,12 +1300,25 @@ void ap_sta_set_authorized(struct hostap
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 {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
+ hostapd_ubus_notify(hapd, "disassoc", sta->addr);
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
Index: hostapd-2021-02-20-59e9794c/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
struct hostapd_data *hapd = ctx;
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
@@ -268,22 +342,25 @@
}
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -176,6 +176,12 @@ ifdef CONFIG_EAPOL_TEST
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile
===================================================================
--- 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
endif
+ifdef CONFIG_UBUS
+CFLAGS += -DUBUS_SUPPORT
+OBJS += ubus.o
+OBJS += ../src/utils/uloop.o
+LIBS += -lubox -lubus
+endif
+
ifdef CONFIG_CODE_COVERAGE
CFLAGS += -O0 -fprofile-arcs -ftest-coverage
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
endif
OBJS += ../src/ap/ctrl_iface_ap.o
@@ -293,9 +370,11 @@
endif
CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -7241,6 +7241,8 @@ struct wpa_supplicant * wpa_supplicant_a
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c
===================================================================
--- 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 */
@@ -304,7 +383,7 @@
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;
#endif /* CONFIG_MESH */
@@ -313,7 +392,7 @@
/* Remove interface from the global list of interfaces */
prev = global->ifaces;
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_reconfig(wpa_supplicant_reconfig, global);
@@ -326,8 +405,10 @@
return 0;
}
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
Index: hostapd-2021-02-20-59e9794c/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 @@
#include "wps/wps_defs.h"
#include "config_ssid.h"
@@ -336,7 +417,7 @@
extern const char *const wpa_supplicant_version;
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 */
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 perm_addr[ETH_ALEN];
char ifname[100];
@@ -353,8 +434,10 @@
#ifdef CONFIG_MATCH_IFACE
int matched;
#endif /* CONFIG_MATCH_IFACE */
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
Index: hostapd-2021-02-20-59e9794c/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 @@
#include "p2p/p2p.h"
#include "p2p_supplicant.h"
@@ -363,7 +446,7 @@
#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",
cred->cred_attr, cred->cred_attr_len);
@@ -372,36 +455,20 @@
if (wpa_s->conf->wps_cred_processing == 1)
return 0;
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -895,6 +895,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[])
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c
===================================================================
--- 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[])
for (;;) {
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:hH:i:I:KLMm:nNo: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:hi:I:KLMm:nNo:O:p:P:qsTtuv::W");
if (c < 0)
break;
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;
break;
#endif /* CONFIG_P2P */
@@ -411,8 +478,10 @@
case 'o':
params.override_driver = optarg;
break;
--- a/src/ap/rrm.c
+++ b/src/ap/rrm.c
Index: hostapd-2021-02-20-59e9794c/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
return;
wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
@@ -423,8 +492,10 @@
}
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
Index: hostapd-2021-02-20-59e9794c/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 @@
static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
int existsok)
@@ -461,9 +532,11 @@
return hostapd_vlan_if_remove(hapd, vlan->ifname);
}
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1196,6 +1196,8 @@ int hostapd_dfs_radar_detected(struct ho
Index: hostapd-2021-02-20-59e9794c/src/ap/dfs.c
===================================================================
--- 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, ht_enabled, chan_offset, chan_width, cf1, cf2);
@@ -472,9 +545,11 @@
/* Proceed only if DFS is not offloaded to the driver */
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
return 0;
--- a/src/ap/airtime_policy.c
+++ b/src/ap/airtime_policy.c
@@ -112,8 +112,14 @@ static void set_sta_weights(struct hosta
Index: hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c
===================================================================
--- 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;
@@ -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;
if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) {
@@ -503,9 +578,11 @@
if (weight)
return sta_set_airtime_weight(hapd, sta, weight);
}
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -324,6 +324,7 @@ struct sta_info {
Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
===================================================================
--- 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 */
#ifdef CONFIG_AIRTIME_POLICY
unsigned int airtime_weight;
@@ -513,8 +590,10 @@
struct os_reltime backlogged_until;
#endif /* CONFIG_AIRTIME_POLICY */
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
Index: hostapd-2021-02-20-59e9794c/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
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
pos, end - pos);
@@ -553,3 +632,157 @@
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
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);
+}

View 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,

View File

@@ -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");
}

View 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));

View File

@@ -30,7 +30,7 @@
--- a/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
} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
bss->ssid.dynamic_vlan = atoi(pos);

View File

@@ -1,8 +1,6 @@
Index: hostapd-2021-05-22-b102f19b/hostapd/config_file.c
===================================================================
--- hostapd-2021-05-22-b102f19b.orig/hostapd/config_file.c
+++ hostapd-2021-05-22-b102f19b/hostapd/config_file.c
@@ -2357,6 +2357,8 @@ static int hostapd_config_fill(struct ho
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2341,6 +2341,8 @@ static int hostapd_config_fill(struct ho
sizeof(conf->bss[0]->iface));
} else if (os_strcmp(buf, "bridge") == 0) {
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) {
os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
} else if (os_strcmp(buf, "wds_bridge") == 0) {
Index: hostapd-2021-05-22-b102f19b/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
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -340,8 +340,6 @@ int hostapd_set_wds_sta(struct hostapd_d
return -1;
if (hapd->conf->wds_bridge[0])

View File

@@ -1,6 +1,6 @@
--- a/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);
return 1;
}
@@ -17,7 +17,7 @@
} else if (os_strcmp(buf, "extended_key_id") == 0) {
--- a/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);
int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
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,
--- a/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;
+}
+
int hostapd_reload_config(struct hostapd_iface *iface, int reconf)
int hostapd_reload_config(struct hostapd_iface *iface)
{
struct hapd_interfaces *interfaces = iface->interfaces;
--- a/src/ap/beacon.c
@@ -71,7 +71,7 @@
" since no room for additional STA",
--- a/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_age;

View File

@@ -1,6 +1,6 @@
--- a/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,
"Line %d: Obsolete peerkey parameter ignored", line);
#ifdef CONFIG_IEEE80211R_AP
@@ -11,7 +11,7 @@
hexstr2bin(pos, bss->mobility_domain,
--- a/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 {
char iface[IFNAMSIZ + 1];
char bridge[IFNAMSIZ + 1];

View File

@@ -1,8 +1,6 @@
Index: hostapd-2021-05-22-b102f19b/src/ap/ap_config.h
===================================================================
--- hostapd-2021-05-22-b102f19b.orig/src/ap/ap_config.h
+++ hostapd-2021-05-22-b102f19b/src/ap/ap_config.h
@@ -278,6 +278,7 @@ struct hostapd_bss_config {
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -276,6 +276,7 @@ struct hostapd_bss_config {
char iface[IFNAMSIZ + 1];
char bridge[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 wds_bridge[IFNAMSIZ + 1];
Index: hostapd-2021-05-22-b102f19b/src/ap/x_snoop.c
===================================================================
--- hostapd-2021-05-22-b102f19b.orig/src/ap/x_snoop.c
+++ hostapd-2021-05-22-b102f19b/src/ap/x_snoop.c
@@ -31,14 +31,16 @@ int x_snoop_init(struct hostapd_data *ha
--- a/src/ap/x_snoop.c
+++ b/src/ap/x_snoop.c
@@ -31,28 +31,31 @@ int x_snoop_init(struct hostapd_data *ha
return -1;
}
@@ -33,13 +29,20 @@ Index: hostapd-2021-05-22-b102f19b/src/ap/x_snoop.c
wpa_printf(MSG_DEBUG,
"x_snoop: Failed to enable proxyarp on the bridge port");
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
- if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
+ 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,
"x_snoop: Failed to enable multicast snooping on the bridge");
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 l2_packet_data *l2;
+ const char *ifname = conf->bridge;
- l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
+
+ if (conf->snoop_iface[0])
+ 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);
if (l2 == NULL) {
wpa_printf(MSG_DEBUG,
"x_snoop: Failed to initialize L2 packet processing %s",
Index: hostapd-2021-05-22-b102f19b/hostapd/config_file.c
===================================================================
--- hostapd-2021-05-22-b102f19b.orig/hostapd/config_file.c
+++ hostapd-2021-05-22-b102f19b/hostapd/config_file.c
@@ -2359,6 +2359,8 @@ static int hostapd_config_fill(struct ho
@@ -125,7 +132,10 @@ void x_snoop_mcast_to_ucast_convert_send
void x_snoop_deinit(struct hostapd_data *hapd)
{
- 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));
if (!bss->wds_bridge[0])
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) {
os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
} 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))

View File

@@ -1,7 +1,5 @@
Index: hostapd-2021-02-20-59e9794c/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
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1904,6 +1904,25 @@ static int ieee802_1x_update_vlan(struct
}
#endif /* CONFIG_NO_VLAN */
@@ -36,11 +34,9 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_1x.c
break;
case RADIUS_CODE_ACCESS_REJECT:
sm->eap_if->aaaFail = true;
Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.h
+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
@@ -117,6 +117,7 @@ struct sta_info {
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -116,6 +116,7 @@ struct sta_info {
u8 supported_rates[WLAN_SUPP_RATES_MAX];
int supported_rates_len;
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
enum mesh_plink_state plink_state;
Index: hostapd-2021-02-20-59e9794c/src/radius/radius.c
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/src/radius/radius.c
+++ hostapd-2021-02-20-59e9794c/src/radius/radius.c
--- a/src/radius/radius.c
+++ b/src/radius/radius.c
@@ -1182,6 +1182,35 @@ radius_msg_get_cisco_keys(struct radius_
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,
const u8 *req_authenticator,
Index: hostapd-2021-02-20-59e9794c/src/radius/radius.h
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/src/radius/radius.h
+++ hostapd-2021-02-20-59e9794c/src/radius/radius.h
--- a/src/radius/radius.h
+++ b/src/radius/radius.h
@@ -205,6 +205,10 @@ enum {
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,
const u8 *req_authenticator,
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,

View File

@@ -1,8 +1,6 @@
Index: hostapd-2021-02-20-59e9794c/src/ap/acs.c
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/src/ap/acs.c
+++ hostapd-2021-02-20-59e9794c/src/ap/acs.c
@@ -672,6 +672,10 @@ acs_find_ideal_chan_mode(struct hostapd_
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -668,6 +668,10 @@ acs_find_ideal_chan_mode(struct hostapd_
continue;
}

View File

@@ -1,6 +1,6 @@
--- a/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;
int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
struct hostapd_ip_addr own_ip_addr;
@@ -10,7 +10,7 @@
int acct_interim_interval;
--- a/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;
@@ -19,7 +19,7 @@
/**
* 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: RADIUS client context from radius_client_init()
* @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",
inet_ntoa(claddr.sin_addr),
ntohs(claddr.sin_port));
@@ -61,7 +61,7 @@
}
break;
#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,
abuf, sizeof(abuf)),
ntohs(claddr6.sin6_port));
@@ -74,7 +74,7 @@
}
--- a/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 (*cb)(const u8 *addr, void *ctx),
void *ctx);
@@ -98,7 +98,7 @@
hapd->conf->own_ip_addr.af == AF_INET &&
--- a/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) {
wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
#endif /* CONFIG_IAPP */

View File

@@ -1,7 +1,5 @@
Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.c
+++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -11,6 +11,8 @@
#include <sqlite3.h>
#endif /* CONFIG_SQLITE */
@@ -10,8 +8,8 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
+
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
@@ -1316,6 +1318,22 @@ static int hostapd_setup_bss(struct host
#include "utils/crc32.h"
@@ -1198,6 +1200,22 @@ int hostapd_setup_bss(struct hostapd_dat
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)
conf->wmm_enabled = hapd->iconf->ieee80211n | hapd->iconf->ieee80211ax;
conf->wmm_enabled = hapd->iconf->ieee80211n;

View File

@@ -1,7 +1,5 @@
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
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -717,7 +717,7 @@ struct sta_info * ap_sta_add(struct host
return sta;

View File

@@ -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
+++ 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)
data->center_freq1 = 5000 + center_segment0 * 5;
else {

View File

@@ -1,7 +1,5 @@
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
--- a/src/radius/radius_das.c
+++ b/src/radius/radius_das.c
@@ -48,6 +48,8 @@ static struct radius_msg * radius_das_di
RADIUS_ATTR_EVENT_TIMESTAMP,
RADIUS_ATTR_MESSAGE_AUTHENTICATOR,

View File

@@ -10,7 +10,7 @@
unsigned int time_window;
--- a/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;
os_memset(&das_conf, 0, sizeof(das_conf));
das_conf.port = conf->radius_das_port;
@@ -48,7 +48,7 @@
size_t shared_secret_len;
struct hostapd_ip_addr client_addr;
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,
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);
rbuf = radius_msg_get_buf(reply);
@@ -123,7 +123,11 @@
if (res < 0) {
wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s",
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);
}
@@ -189,6 +193,7 @@
+ fromlen, abuf, from_port);
+ }
+
+ radius_msg_free(msg);
+ if (!found)
+ wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
+}
@@ -196,7 +201,7 @@
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 *
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->disconnect = conf->disconnect;
das->coa = conf->coa;
@@ -255,7 +260,7 @@
os_memcpy(&das->client_addr, conf->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;
@@ -278,7 +283,7 @@
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)
return;

View File

@@ -1,7 +1,5 @@
Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/hostapd/config_file.c
+++ hostapd-2021-02-20-59e9794c/hostapd/config_file.c
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2366,6 +2366,8 @@ static int hostapd_config_fill(struct ho
return 1;
}
@@ -11,41 +9,23 @@ Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c
} else if (os_strcmp(buf, "driver_params") == 0) {
os_free(conf->driver_params);
conf->driver_params = os_strdup(pos);
Index: hostapd-2021-02-20-59e9794c/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
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -279,6 +279,7 @@ struct hostapd_bss_config {
char snoop_iface[IFNAMSIZ + 1];
char vlan_bridge[IFNAMSIZ + 1];
char wds_bridge[IFNAMSIZ + 1];
+ 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
===================================================================
--- 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
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -785,6 +785,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->uci_section);
os_free(conf->config_id);
os_free(conf->ca_cert);
os_free(conf->server_cert);
os_free(conf->server_cert2);

View 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;
}

View 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;

View 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];

View File

@@ -1,8 +1,6 @@
Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/hostapd/config_file.c
+++ hostapd-2021-02-20-59e9794c/hostapd/config_file.c
@@ -3339,6 +3339,8 @@ static int hostapd_config_fill(struct ho
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3337,6 +3337,8 @@ static int hostapd_config_fill(struct ho
bss->ignore_broadcast_ssid = atoi(pos);
} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
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
} else if (os_strcmp(buf, "wep_default_key") == 0) {
bss->ssid.wep.idx = atoi(pos);
Index: hostapd-2021-02-20-59e9794c/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
@@ -460,6 +460,7 @@ struct hostapd_bss_config {
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -459,6 +459,7 @@ struct hostapd_bss_config {
int ap_max_inactivity;
int ignore_broadcast_ssid;
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_uapsd;
Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c
===================================================================
--- hostapd-2021-02-20-59e9794c.orig/src/ap/beacon.c
+++ hostapd-2021-02-20-59e9794c/src/ap/beacon.c
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -920,7 +920,8 @@ void handle_probe_req(struct hostapd_dat
}
#endif /* CONFIG_P2P */

View 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;
};

View File

@@ -17,9 +17,11 @@ Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
src/ap/hostapd.c | 93 +++++++++++++++++++++++++++++++++---------------
1 file changed, 65 insertions(+), 28 deletions(-)
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1101,19 +1101,60 @@ static int db_table_create_radius_attrib
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
@@ -1131,6 +1131,47 @@ static int db_table_create_radius_attrib
#endif /* CONFIG_NO_RADIUS */
@@ -58,30 +60,16 @@ Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
+ if (hapd->driver && hapd->driver->set_operstate)
+ hapd->driver->set_operstate(hapd->drv_priv, 1);
+
+ hostapd_ubus_add_bss(hapd);
+ hostapd_ucode_add_bss(hapd);
+
+ return 0;
+}
+
/**
* hostapd_setup_bss - Per-BSS setup (initialization)
* @hapd: Pointer to BSS data
* @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
@@ -1432,32 +1473,8 @@ int hostapd_setup_bss(struct hostapd_dat
return -1;
}
@@ -110,22 +98,22 @@ Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
- hapd->driver->set_operstate(hapd->drv_priv, 1);
-
- hostapd_ubus_add_bss(hapd);
- hostapd_ucode_add_bss(hapd);
+ if (set_beacon)
+ return hostapd_set_beacon(hapd);
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];
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,
+ (hapd->iconf->mbssid? 0 : 1))) {
- if (hostapd_setup_bss(hapd, j == 0, true)) {
+ if (hostapd_setup_bss(hapd, j == 0, (hapd->iconf->mbssid? 0 : 1))) {
for (;;) {
hapd = iface->bss[j];
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))
prev_addr = hapd->own_addr;
}
@@ -150,12 +138,3 @@ Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
hapd = iface->bss[0];
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--;

View File

@@ -31,7 +31,7 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c
#ifdef CONFIG_DPP
#include "common/dpp.h"
#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)
{
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)) {
/* 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)
return -1;
@@ -57,7 +57,7 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c
if (!params->center_freq1)
break;
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;
}
@@ -67,7 +67,7 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c
/* Adjacent and overlapped are not allowed for 80+80 */
if (params->center_freq2 &&
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;
}
@@ -169,7 +169,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/drv_callbacks.c
if (!finished)
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.cf1,
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/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->ieee80211ac = params->vht_enabled;
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,
&seg0);
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_seg1_idx(iface->conf, seg1_idx);
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/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);
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
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/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;
int cf1;
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/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;
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->freq_params.freq,
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.ht_enabled ? " ht" : "",
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 *ru_punct_bitmap,
+ struct nlattr *ru_punct_ofdma,
struct nlattr *count, int finished)
struct nlattr *count,
int finished)
{
struct i802_bss *bss;
@@ -753,6 +755,11 @@ static void mlme_event_ch_switch(struct
@@ -754,6 +756,11 @@ 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);
@@ -274,7 +274,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c
if (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_CENTER_FREQ1],
tb[NL80211_ATTR_CENTER_FREQ2],
@@ -283,13 +283,13 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c
tb[NL80211_ATTR_CH_SWITCH_COUNT],
0);
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_CENTER_FREQ1],
tb[NL80211_ATTR_CENTER_FREQ2],
+ tb[NL80211_ATTR_RU_PUNCT_BITMAP],
+ tb[NL80211_ATTR_RU_PUNCT_SUPP_HE],
NULL,
NULL,
1);
break;
Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/ap.c

View File

@@ -12,11 +12,11 @@ advertised to mac80211 through NL attribute.
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
+++ b/src/ap/ap_drv_ops.c 2022-11-07 22:32:28.150487226 +0530
@@ -421,6 +421,8 @@ int hostapd_sta_add(struct hostapd_data
--- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_drv_ops.c
+++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.c
@@ -419,6 +419,8 @@ int hostapd_sta_add(struct hostapd_data
size_t he_capab_len, size_t eht_capab_len,
const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
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)
{
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.support_p2p_ps = supp_p2p_ps;
params.set = set;
@@ -34,10 +34,10 @@ Index: b/src/ap/ap_drv_ops.c
return hapd->driver->sta_add(hapd->drv_priv, &params);
}
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
+++ b/src/ap/ap_drv_ops.h 2022-11-07 22:32:28.150487226 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_drv_ops.h
+++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h
@@ -46,6 +46,8 @@ int hostapd_sta_add(struct hostapd_data
size_t he_capab_len, size_t eht_capab_len,
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 hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
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
+++ b/src/ap/beacon.c 2022-11-07 22:32:28.150487226 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/ap/beacon.c
+++ hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c
@@ -651,6 +651,10 @@ static u8 * hostapd_gen_probe_resp(struc
buflen += (3 + sizeof(struct ieee80211_eht_operation));
if (hapd->iconf->ru_punct_bitmap)
@@ -70,7 +70,7 @@ Index: b/src/ap/beacon.c
}
#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));
if (hapd->iconf->ru_punct_bitmap)
tail_len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE;
@@ -80,7 +80,7 @@ Index: b/src/ap/beacon.c
}
#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);
tailpos = hostapd_eid_eht_operation(hapd, tailpos,
IEEE80211_MODE_AP);
@@ -89,11 +89,11 @@ Index: b/src/ap/beacon.c
}
#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
+++ b/src/ap/ieee802_11.c 2022-11-07 22:32:28.150487226 +0530
@@ -4599,6 +4599,9 @@ static int check_assoc_ies(struct hostap
--- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11.c
+++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.c
@@ -4607,6 +4607,9 @@ static int check_assoc_ies(struct hostap
elems.he_capabilities,
elems.eht_capabilities,
elems.eht_capabilities_len);
@@ -103,7 +103,7 @@ Index: b/src/ap/ieee802_11.c
if (resp != WLAN_STATUS_SUCCESS)
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_he_capabilities he_cap;
struct ieee80211_eht_capabilities eht_cap;
@@ -111,7 +111,7 @@ Index: b/src/ap/ieee802_11.c
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) {
hostapd_get_eht_capab(hapd, sta->eht_capab, &eht_cap,
sta->eht_capab_len);
@@ -120,7 +120,7 @@ Index: b/src/ap/ieee802_11.c
}
#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->flags | WLAN_STA_ASSOC, sta->qosinfo,
sta->vht_opmode, sta->p2p_ie ? 1 : 0,
@@ -129,7 +129,7 @@ Index: b/src/ap/ieee802_11.c
set)) {
hostapd_logger(hapd, sta->addr,
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));
if (hapd->iconf->ru_punct_bitmap)
buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE;
@@ -139,7 +139,7 @@ Index: b/src/ap/ieee802_11.c
}
#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) {
p = hostapd_eid_eht_capab(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 */
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
+++ b/src/ap/ieee802_11.h 2022-11-07 22:32:28.150487226 +0530
@@ -91,6 +91,10 @@ void hostapd_get_eht_capab(struct hostap
--- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11.h
+++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.h
@@ -97,6 +97,10 @@ void hostapd_get_eht_capab(struct hostap
const struct ieee80211_eht_capabilities *src,
struct ieee80211_eht_capabilities *dest,
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);
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
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);
u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid,
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);
void ru_punct_update_bw(u16 bitmap, u8 pri_chan, u8 *width, u8 *seg0, u8 *seg1);
#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
+++ b/src/ap/ieee802_11_eht.c 2022-11-07 22:32:42.142383632 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11_eht.c
+++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11_eht.c
@@ -18,6 +18,7 @@
#include "utils/includes.h"
@@ -322,10 +322,10 @@ Index: b/src/ap/ieee802_11_eht.c
+
+ 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
+++ b/src/ap/sta_info.c 2022-11-07 22:32:28.150487226 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/ap/sta_info.c
+++ hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.c
@@ -359,6 +359,7 @@ void ap_free_sta(struct hostapd_data *ha
os_free(sta->he_capab);
os_free(sta->he_6ghz_capab);
@@ -334,7 +334,7 @@ Index: b/src/ap/sta_info.c
hostapd_free_psk_list(sta->psk);
os_free(sta->identity);
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_len,
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_MODULE_IEEE80211,
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
+++ b/src/ap/sta_info.h 2022-11-07 22:32:28.154487197 +0530
@@ -337,6 +337,8 @@ struct sta_info {
#ifdef CONFIG_PASN
--- hostapd-2021-12-13-b26f5c0f.orig/src/ap/sta_info.h
+++ hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.h
@@ -340,6 +340,8 @@ struct sta_info {
struct pasn_data *pasn;
#endif /* CONFIG_PASN */
int signal_mgmt;
+ struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab;
+ 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
+++ b/src/common/ieee802_11_common.c 2022-11-07 22:32:28.154487197 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_common.c
+++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.c
@@ -22,6 +22,7 @@ static int ieee802_11_parse_vendor_speci
int show_errors)
{
@@ -413,10 +413,10 @@ Index: b/src/common/ieee802_11_common.c
if (ieee802_11_parse_vendor_specific(pos, elen,
elems,
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
+++ b/src/common/ieee802_11_common.h 2022-11-07 22:32:28.154487197 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_common.h
+++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.h
@@ -121,6 +121,7 @@ struct ieee802_11_elems {
const u8 *mbssid_known_bss;
const u8 *eht_capabilities;
@@ -433,10 +433,10 @@ Index: b/src/common/ieee802_11_common.h
struct mb_ies_info mb_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
+++ b/src/common/ieee802_11_defs.h 2022-11-07 22:32:28.154487197 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_defs.h
+++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_defs.h
@@ -2494,6 +2494,13 @@ struct ieee80211_eht_operation {
le16 disabled_subchannel_bitmap[0];
} STRUCT_PACKED;
@@ -471,10 +471,10 @@ Index: b/src/common/ieee802_11_defs.h
/*
* IEEE P802.11be/D1.0, May 2021,
* 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
+++ b/src/common/qca-vendor.h 2022-11-07 22:32:28.154487197 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/common/qca-vendor.h
+++ hostapd-2021-12-13-b26f5c0f/src/common/qca-vendor.h
@@ -18,6 +18,10 @@
*/
@@ -486,11 +486,11 @@ Index: b/src/common/qca-vendor.h
#ifndef BIT
#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
+++ b/src/drivers/driver.h 2022-11-07 22:32:28.154487197 +0530
@@ -2394,6 +2394,8 @@ struct hostapd_sta_add_params {
--- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h
+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h
@@ -2398,6 +2398,8 @@ struct hostapd_sta_add_params {
size_t supp_oper_classes_len;
int support_p2p_ps;
u16 ru_punct_bitmap;
@@ -499,11 +499,11 @@ Index: b/src/drivers/driver.h
};
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
+++ b/src/drivers/driver_nl80211.c 2022-11-07 22:32:28.154487197 +0530
@@ -5278,6 +5278,14 @@ static int wpa_driver_nl80211_sta_add(vo
--- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c
+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c
@@ -5285,6 +5285,14 @@ static int wpa_driver_nl80211_sta_add(vo
goto fail;
}
@@ -518,10 +518,10 @@ Index: b/src/drivers/driver_nl80211.c
if (params->ext_capab) {
wpa_hexdump(MSG_DEBUG, " * ext_capab",
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
+++ b/src/drivers/nl80211_copy.h 2022-11-07 22:32:28.154487197 +0530
--- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/nl80211_copy.h
+++ hostapd-2021-12-13-b26f5c0f/src/drivers/nl80211_copy.h
@@ -3137,6 +3137,7 @@ enum nl80211_attrs {
NL80211_ATTR_RU_PUNCT_BITMAP,

View File

@@ -29,11 +29,6 @@ static struct ubus_context *ctx;
static struct blob_buf b;
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)
{
return container_of(obj, struct hostapd_data, ubus.obj);
@@ -44,12 +39,6 @@ struct ubus_banned_client {
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)
{
if (ubus_reconnect(ctx, NULL)) {
@@ -57,12 +46,12 @@ static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
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)
{
eloop_unregister_read_sock(ctx->sock.fd);
uloop_fd_delete(&ctx->sock);
eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
}
@@ -71,12 +60,14 @@ static bool hostapd_ubus_init(void)
if (ctx)
return true;
eloop_add_uloop();
ctx = ubus_connect(NULL);
if (!ctx)
return false;
ctx->connection_lost = hostapd_ubus_connection_lost;
eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL);
ubus_add_uloop(ctx);
return true;
}
@@ -94,7 +85,7 @@ static void hostapd_ubus_ref_dec(void)
if (ctx_ref)
return;
eloop_unregister_read_sock(ctx->sock.fd);
uloop_fd_delete(&ctx->sock);
ubus_free(ctx);
ctx = NULL;
}
@@ -127,38 +118,6 @@ static void hostapd_notify_ubus(struct ubus_object *obj, char *bssname, char *ev
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
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
@@ -203,10 +162,8 @@ hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj,
struct blob_attr *msg)
{
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 ret;
return hostapd_reload_config(hapd->iface);
}
@@ -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, "tx", sta_driver_data.current_tx_rate * 100);
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);
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);
@@ -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);
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);
return 0;
@@ -693,68 +691,6 @@ enum {
__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 {
CSA_FREQ,
CSA_BCN_COUNT,
@@ -882,8 +818,8 @@ hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj,
css.freq_params.sec_channel_offset,
chwidth, seg0, seg1,
iconf->vht_capab,
mode ? &mode->he_capab[IEEE80211_MODE_AP] :
NULL, NULL, 0,0,0);
mode ? &mode->he_capab[IEEE80211_MODE_AP] : 0,
0, 0, 0, 0);
for (i = 0; i < hapd->iface->num_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;
ret = ubus_add_object(ctx, obj);
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)
@@ -1640,8 +1574,6 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd)
if (!ctx)
return;
hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "remove");
if (obj->id) {
ubus_remove_object(ctx, obj);
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");
}
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_notify_request nreq;
int resp;
@@ -1844,10 +1735,44 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *
blob_buf_init(&b, 0);
blobmsg_add_macaddr(&b, "address", addr);
blobmsg_add_string(&b, "ifname", hapd->conf->iface);
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(
struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode,
struct rrm_measurement_beacon_report *rep, size_t len)

File diff suppressed because it is too large Load Diff

View File

@@ -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);
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,
const u8 *addr, u8 token, u8 rep_mode,
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(
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
const u8 *candidate_list, u16 candidate_list_len);
void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq);
#else

View 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);
}

View 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

View File

@@ -7,10 +7,6 @@ static inline int has_feature(const char *feat)
if (!strcmp(feat, "eap"))
return 1;
#endif
#ifdef CONFIG_IEEE80211N
if (!strcmp(feat, "11n"))
return 1;
#endif
#ifdef CONFIG_IEEE80211AC
if (!strcmp(feat, "11ac"))
return 1;
@@ -50,6 +46,18 @@ static inline int has_feature(const char *feat)
#ifdef CONFIG_WPS
if (!strcmp(feat, "wps"))
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
return 0;
}

View 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){};
}

View 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

View File

@@ -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);
}
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)
{
if (ubus_reconnect(ctx, NULL)) {
@@ -43,12 +37,12 @@ static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
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)
{
eloop_unregister_read_sock(ctx->sock.fd);
uloop_fd_delete(&ctx->sock);
eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
}
@@ -57,12 +51,14 @@ static bool wpas_ubus_init(void)
if (ctx)
return true;
eloop_add_uloop();
ctx = ubus_connect(NULL);
if (!ctx)
return false;
ctx->connection_lost = wpas_ubus_connection_lost;
eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL);
ubus_add_uloop(ctx);
return true;
}
@@ -80,7 +76,7 @@ static void wpas_ubus_ref_dec(void)
if (ctx_ref)
return;
eloop_unregister_read_sock(ctx->sock.fd);
uloop_fd_delete(&ctx->sock);
ubus_free(ctx);
ctx = NULL;
}
@@ -211,152 +207,6 @@ void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s)
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
void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred)
{

View File

@@ -24,9 +24,6 @@ struct wpas_ubus_bss {
void wpas_ubus_add_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
void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred);
#endif
@@ -34,14 +31,6 @@ void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential
#else
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)
{
}

View 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();
}

View 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

View File

@@ -17,11 +17,11 @@ KERNEL_NAME_SUFFIX=-qsdk-879aa8d1f540d2357674beed0069e4450946b831
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += \
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-qca-nss-ppe kmod-qca-ssdk-nohnat kmod-qca-psdk \
kmod-qca-nss-dp kmod-qca-nss-ppe-bridge-mgr kmod-qca-nss-ppe-vlan-mgr \
kmod-qca-nss-ppe kmod-qca-ssdk-nohnat kmod-qca-psdk kmod-qca-nss-dp \
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))

View File

@@ -1262,3 +1262,6 @@ CONFIG_ZLIB_INFLATE=y
CONFIG_ZONE_DMA_FLAG=0
# CONFIG_DEBUG_MEM_USAGE 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

View 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)

View File

@@ -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)
{

View File

@@ -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(),
},

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);
}

View 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;

View 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);

View 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);

View 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
};

View 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,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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))

View File

@@ -179,7 +179,7 @@ config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM
MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \
CROSS_COMPILE="$(KERNEL_CROSS)" \
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)" \
MODPROBE=true \
KLIB=$(TARGET_MODULES_DIR) \

View File

@@ -1,6 +1,7 @@
#!/bin/sh
. /lib/netifd/netifd-wireless.sh
. /lib/netifd/hostapd.sh
. /lib/functions/system.sh
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_STRING="mesh_power_mode"
NEWAPLIST=
OLDAPLIST=
NEWSPLIST=
OLDSPLIST=
NEWUMLIST=
OLDUMLIST=
wdev_tool() {
ucode /usr/share/hostap/wdev.uc "$@"
}
drv_mac80211_init_device_config() {
hostapd_common_add_device_config
@@ -28,9 +26,9 @@ drv_mac80211_init_device_config() {
config_add_string tx_burst
config_add_string distance
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_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 channels
config_add_array scan_list
@@ -153,13 +151,15 @@ mac80211_hostapd_setup_base() {
[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] &&
append base_cfg "acs_exclude_dfs=1" "$N"
json_get_vars noscan ht_coex
json_get_values ht_capab_list ht_capab tx_burst
json_get_vars noscan ht_coex min_tx_power:0 tx_burst
json_get_values ht_capab_list ht_capab
json_get_values channel_list channels
[ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \
channel_list="$channel"
[ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power"
set_default noscan 0
[ "$noscan" -gt 0 ] && hostapd_noscan=1
@@ -172,7 +172,7 @@ mac80211_hostapd_setup_base() {
ht_capab=
case "$htmode" in
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
a)
case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
@@ -288,11 +288,17 @@ mac80211_hostapd_setup_base() {
vht_oper_chwidth=2
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" ] && {
op_class=
case "$htmode" in
HE20) op_class=131;;
EHT320) op_class=137;;
HE*|EHT*) op_class=$((132 + $vht_oper_chwidth))
esac
[ -n "$op_class" ] && append base_cfg "op_class=$op_class" "$N"
@@ -418,7 +424,7 @@ mac80211_hostapd_setup_base() {
enable_be=0
case "$htmode" in
HE*) enable_ax=1 ;;
HE*|EHT*)
EHT*)
enable_ax=1
enable_be=1
;;
@@ -427,26 +433,46 @@ mac80211_hostapd_setup_base() {
if [ "$enable_ax" != "0" ]; then
json_get_vars \
he_su_beamformer:1 \
he_su_beamformee:0 \
he_su_beamformee:1 \
he_mu_beamformer:1 \
he_twt_required:0 \
he_spr_sr_control:0 \
he_spr_non_srg_obss_pd_max_offset:1 \
he_bss_color
he_spr_sr_control:3 \
he_spr_psr_enabled:0 \
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_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}
append base_cfg "ieee80211ax=1" "$N"
[ -n "$he_bss_color" ] && append base_cfg "he_bss_color=$he_bss_color" "$N"
[ "$hwmode" = "a" ] && {
append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N"
append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
[ "$enable_be" != "0" ] && {
append base_cfg "eht_oper_chwidth=$vht_oper_chwidth" "$N"
append base_cfg "eht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
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_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_beamformee:${he_phy_cap:8:2}:0x1:$he_su_beamformee \
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_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_rts_threshold=1023" "$N"
@@ -569,8 +606,6 @@ $base_cfg
EOF
json_select ..
radio_md5sum=$(md5sum $hostapd_conf_file | cut -d" " -f1)
echo "radio_config_id=${radio_md5sum}" >> $hostapd_conf_file
}
mac80211_hostapd_setup_bss() {
@@ -584,7 +619,7 @@ mac80211_hostapd_setup_bss() {
hostapd_set_bss_options hostapd_cfg "$phy" "$vif" || return 1
json_get_vars wds wds_bridge dtim_period max_listen_int start_disabled
json_get_vars fils_discovery_max_interval
json_get_vars fils_discovery_max_interval
set_default wds 0
set_default start_disabled 0
@@ -607,6 +642,7 @@ mac80211_hostapd_setup_bss() {
cat >> /var/run/hostapd-$phy.conf <<EOF
$hostapd_cfg
bssid=$macaddr
${default_macaddr:+#default_macaddr}
${dtim_period:+dtim_period=$dtim_period}
${max_listen_int:+max_listen_interval=$max_listen_int}
EOF
@@ -621,57 +657,9 @@ mac80211_get_addr() {
mac80211_generate_mac() {
local phy="$1"
local multiple_bssid="$2"
local id="${macidx:-0}"
local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
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 ))
wdev_tool "$phy" get_macaddr id=$id num_global=$num_global_macaddr mbssid=$multiple_bssid
}
find_phy() {
@@ -692,76 +680,7 @@ mac80211_check_ap() {
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() {
local multiple_bssid=$1
json_select config
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}"
if_idx=$((${if_idx:-0} + 1))
append active_ifnames "$ifname"
set_default wds 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 ..
[ -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" ] && {
[ -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
case "$mode" in
adhoc)
mac80211_iw_interface_add "$phy" "$ifname" adhoc || return
;;
ap)
# Hostapd will handle recreating the interface and
# subsequent virtual APs belonging to the same PHY
@@ -806,119 +724,20 @@ mac80211_prepare_vif() {
mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
NEWAPLIST="${NEWAPLIST}$ifname "
[ -n "$hostapd_ctrl" ] || {
ap_ifname="${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
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 ..
}
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() {
case "$htmode" in
VHT20|HT20) iw_htmode=HT20;;
HT40*|VHT40|VHT160)
VHT20|HT20|HE20) iw_htmode=HT20;;
HT40*|VHT40|VHT160|HE40)
case "$band" in
2g)
case "$htmode" in
@@ -942,7 +761,7 @@ mac80211_prepare_iw_htmode() {
esac
[ "$auto_channel" -gt 0 ] && iw_htmode="HT40+"
;;
VHT80)
VHT80|HE80)
iw_htmode="80MHZ"
;;
NONE|NOHT)
@@ -952,6 +771,13 @@ mac80211_prepare_iw_htmode() {
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() {
local enable=$1
json_get_vars bssid ssid key mcast_rate
@@ -993,81 +819,217 @@ mac80211_setup_adhoc() {
mcval=
[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
iw dev "$ifname" ibss join "$ssid" $freq $iw_htmode fixed-freq $bssid \
beacon-interval $beacon_int \
${brstr:+basic-rates $brstr} \
${mcval:+mcast-rate $mcval} \
${keyspec:+keys $keyspec}
local prev
json_set_namespace wdev_uc prev
json_add_object "$ifname"
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() {
local enable=$1
json_get_vars ssid mesh_id mcast_rate
NEWUMLIST="${NEWUMLIST}$ifname "
[ "$enable" = 0 ] && {
ip link set dev "$ifname" down
return 0
}
mcval=
[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
[ -n "$mesh_id" ] && ssid="$mesh_id"
iw dev "$ifname" mesh join "$ssid" freq $freq $iw_htmode \
${mcval:+mcast-rate $mcval} \
beacon-interval $beacon_int
local prev
json_set_namespace wdev_uc prev
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() {
local name="$1"
local failed
local action=up
json_select data
json_get_vars ifname
json_select ..
json_select config
json_get_vars mode
json_get_var vif_txpower
json_get_var vif_enable enable 1
json_get_var ifname _ifname
json_get_var macaddr _macaddr
json_get_var default_macaddr _default_macaddr
json_get_vars mode wds powersave
[ "$vif_enable" = 1 ] || action=down
if [ "$mode" != "ap" ] || [ "$ifname" = "$ap_ifname" ]; then
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
set_default powersave 0
set_default wds 0
case "$mode" in
mesh)
json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING
wireless_vif_parse_encryption
[ -z "$htmode" ] && htmode="NOHT";
if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ] || chan_is_dfs "$phy" "$channel"; then
mac80211_setup_supplicant $vif_enable || failed=1
if wpa_supplicant -vmesh; then
mac80211_setup_supplicant || failed=1
else
mac80211_setup_mesh $vif_enable
mac80211_setup_mesh
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)
wireless_vif_parse_encryption
if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
mac80211_setup_supplicant_noctl $vif_enable || failed=1
mac80211_setup_supplicant || failed=1
else
mac80211_setup_adhoc $vif_enable
mac80211_setup_adhoc
fi
;;
sta)
mac80211_setup_supplicant $vif_enable || failed=1
mac80211_setup_supplicant || failed=1
;;
monitor)
mac80211_setup_monitor
;;
esac
@@ -1100,7 +1062,6 @@ band_match && $3 == "MHz" && $4 == channel {
'
}
chan_is_dfs() {
local phy="$1"
local chan="$2"
@@ -1108,27 +1069,6 @@ chan_is_dfs() {
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() {
hostapd_noscan=1
}
@@ -1137,6 +1077,15 @@ drv_mac80211_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() {
json_select config
json_get_vars \
@@ -1151,6 +1100,12 @@ drv_mac80211_setup() {
json_get_values scan_list scan_list
json_select ..
json_select data && {
json_get_var prev_rxantenna rxantenna
json_get_var prev_txantenna txantenna
json_select ..
}
find_phy || {
echo "Could not find PHY for device '$1'"
wireless_set_retry 0
@@ -1159,31 +1114,10 @@ drv_mac80211_setup() {
[ "$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 cwdev
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
[ "$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"
no_ap=1
macidx=0
staidx=0
@@ -1215,6 +1148,9 @@ drv_mac80211_setup() {
[ "$txantenna" = "all" ] && txantenna=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_gain $antenna_gain >/dev/null 2>&1
iw phy "$phy" set distance "$distance" >/dev/null 2>&1
@@ -1232,81 +1168,36 @@ drv_mac80211_setup() {
hostapd_ctrl=
ap_ifname=
hostapd_noscan=
wpa_supp_init=
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
[ -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
for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif
NEWAPLIST=
for_each_interface "ap" mac80211_prepare_vif ${multiple_bssid}
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}"
active_ifnames=
for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif
for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
[ "${add_ap}" = 1 ] && sleep 1
for_each_interface "ap" mac80211_setup_vif
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy"
[ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy"
NEWSPLIST=
NEWUMLIST=
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
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}"
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"
for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower
wireless_set_up
}
@@ -1337,8 +1228,12 @@ drv_mac80211_teardown() {
return 1
}
mac80211_interface_cleanup "$phy"
uci -q -P /var/state revert wireless._${phy}
mac80211_reset_config "$phy"
for wdev in $(list_phy_interfaces "$phy"); do
ip link set dev "$wdev" down
iw dev "$wdev" del
done
}
add_driver mac80211

View File

@@ -20,7 +20,7 @@ define KernelPackage/nat46
SECTION:=kernel
SUBMENU:=Network Support
FILES:=$(PKG_BUILD_DIR)/nat46/modules/nat46.ko
AUTOLOAD:=$(call AutoLoad,33,nat46)
AUTOLOAD:=$(call AutoLoad,29,nat46)
endef
include $(INCLUDE_DIR)/kernel-defaults.mk

View File

@@ -25,8 +25,7 @@ define KernelPackage/qca-nss-dp
+TARGET_ipq53xx:kmod-qca-nss-ppe
TITLE:=Kernel driver for NSS data plane
FILES:=$(PKG_BUILD_DIR)/qca-nss-dp.ko
# AUTOLOAD:=$(call AutoLoad,31,qca-nss-dp)
AUTOLOAD:=$(call AutoProbe,qca-nss-dp)
AUTOLOAD:=$(call AutoLoad,60,qca-nss-dp)
endef
define KernelPackage/qca-nss-dp/Description
@@ -92,6 +91,7 @@ define Build/Compile
ARCH="$(LINUX_KARCH)" \
M="$(PKG_BUILD_DIR)" \
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" SoC="$(hal_arch)" \
KBUILD_MODPOST_WARN=1 \
modules
endef

View File

@@ -148,7 +148,7 @@ define Build/Compile
M="$(PKG_BUILD_DIR)" \
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
SoC="$(subtarget)" \
BUILD_MODPOST_WARN=1 \
KBUILD_MODPOST_WARN=1 \
modules
endef

View 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;