hostapd: reimplement AP/STA support via ucode

Drop obsolete control interface patches.
This fixes some corner cases in the previous code where the segment 0 center
frequency was not adjusted properly, leading to logspam and non-working AP
interfaces.
Additionally, shutting down the AP was broken, because the next beacon update
would re-enable it, leading to a race condition on assoc.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2023-08-10 18:33:04 +02:00
parent ed0ad7759c
commit 847984c773
30 changed files with 643 additions and 958 deletions

View File

@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=hostapd
PKG_RELEASE:=1.2
PKG_RELEASE:=2
PKG_SOURCE_URL:=http://w1.fi/hostap.git
PKG_SOURCE_PROTO:=git

View File

@ -305,6 +305,78 @@ let main_obj = {
return 0;
}
},
apsta_state: {
args: {
phy: "",
up: true,
frequency: 0,
sec_chan_offset: 0,
csa: true,
csa_count: 0,
},
call: 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[config.bss[0].ifname];
if (!iface)
return 0;
if (!req.args.up) {
iface.stop();
return 0;
}
let freq = req.args.frequency;
if (!freq)
return libubus.STATUS_INVALID_ARGUMENT;
let sec_offset = req.args.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;
let freq_info = hostapd.freq_info(freq, sec_offset, width);
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 {
iface.stop();
ret = iface.start(freq_info);
}
if (!ret)
return libubus.STATUS_UNKNOWN_ERROR;
return 0;
}
},
config_set: {
args: {
phy: "",

View File

@ -5,11 +5,13 @@ import { wdev_create, wdev_remove, is_equal, vlist_new } from "common";
let ubus = libubus.connect();
wpas.data.config = {};
wpas.data.iface_phy = {};
function iface_stop(iface)
{
let ifname = iface.config.iface;
delete wpas.data.iface_phy[ifname];
wpas.remove_iface(ifname);
wdev_remove(ifname);
iface.running = false;
@ -22,6 +24,7 @@ function iface_start(phy, iface)
let ifname = iface.config.iface;
wpas.data.iface_phy[ifname] = phy;
wdev_remove(ifname);
let ret = wdev_create(phy, ifname, iface.config);
if (ret)
@ -146,6 +149,46 @@ function iface_event(type, name, data) {
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":
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)
@ -153,9 +196,31 @@ return {
wpas.ubus.disconnect();
},
iface_add: function(name, obj) {
obj.data.name = name;
iface_event("add", name);
},
iface_remove: function(name, obj) {
iface_event("remove", name);
},
state: function(iface, state) {
let ifname = iface.data.name;
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(iface, ev, info) {
let ifname = iface.data.name;
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

@ -1,80 +0,0 @@
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -143,6 +143,29 @@ static void hostapd_reload_bss(struct ho
#endif /* CONFIG_NO_RADIUS */
ssid = &hapd->conf->ssid;
+
+ hostapd_set_freq(hapd, hapd->iconf->hw_mode, hapd->iface->freq,
+ hapd->iconf->channel,
+ hapd->iconf->enable_edmg,
+ hapd->iconf->edmg_channel,
+ hapd->iconf->ieee80211n,
+ hapd->iconf->ieee80211ac,
+ hapd->iconf->ieee80211ax,
+ hapd->iconf->ieee80211be,
+ hapd->iconf->secondary_channel,
+ hostapd_get_oper_chwidth(hapd->iconf),
+ hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf),
+ hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf));
+
+ if (hapd->iface->current_mode) {
+ if (hostapd_prepare_rates(hapd->iface, hapd->iface->current_mode)) {
+ wpa_printf(MSG_ERROR, "Failed to prepare rates table.");
+ hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_WARNING,
+ "Failed to prepare rates table.");
+ }
+ }
+
if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next &&
ssid->wpa_passphrase_set && ssid->wpa_passphrase) {
/*
@@ -251,6 +274,7 @@ int hostapd_reload_config(struct hostapd
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_config *newconf, *oldconf;
size_t j;
+ int i;
if (iface->config_fname == NULL) {
/* Only in-memory config in use - assume it has been updated */
@@ -301,6 +325,17 @@ int hostapd_reload_config(struct hostapd
}
iface->conf = newconf;
+ for (i = 0; i < iface->num_hw_features; i++) {
+ struct hostapd_hw_modes *mode = &iface->hw_features[i];
+ if (mode->mode == iface->conf->hw_mode) {
+ iface->current_mode = mode;
+ break;
+ }
+ }
+
+ if (iface->conf->channel)
+ iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel);
+
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
if (!hapd->conf->config_id || !newconf->bss[j]->config_id ||
@@ -308,21 +343,6 @@ int hostapd_reload_config(struct hostapd
newconf->bss[j]->config_id) != 0)
hostapd_clear_old_bss(hapd);
hapd->iconf = newconf;
- hapd->iconf->channel = oldconf->channel;
- hapd->iconf->acs = oldconf->acs;
- hapd->iconf->secondary_channel = oldconf->secondary_channel;
- hapd->iconf->ieee80211n = oldconf->ieee80211n;
- hapd->iconf->ieee80211ac = oldconf->ieee80211ac;
- hapd->iconf->ht_capab = oldconf->ht_capab;
- hapd->iconf->vht_capab = oldconf->vht_capab;
- hostapd_set_oper_chwidth(hapd->iconf,
- hostapd_get_oper_chwidth(oldconf));
- hostapd_set_oper_centr_freq_seg0_idx(
- hapd->iconf,
- hostapd_get_oper_centr_freq_seg0_idx(oldconf));
- hostapd_set_oper_centr_freq_seg1_idx(
- hapd->iconf,
- hostapd_get_oper_centr_freq_seg1_idx(oldconf));
hapd->conf = newconf->bss[j];
hostapd_reload_bss(hapd);
}

View File

@ -1,106 +0,0 @@
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -68,6 +68,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
@@ -83,6 +84,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,
@@ -134,6 +136,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,
@@ -3564,6 +3621,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
@@ -1023,7 +1023,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,392 +0,0 @@
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -126,6 +126,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
--- a/wpa_supplicant/bss.c
+++ b/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"
@@ -283,6 +284,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;
@@ -296,6 +301,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);
}
--- a/wpa_supplicant/bss.h
+++ b/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) */
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -35,7 +35,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
@@ -75,6 +75,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"
@@ -202,7 +203,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) {
@@ -249,6 +250,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;
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -131,6 +131,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 */
@@ -1026,6 +1074,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;
@@ -1036,6 +1086,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
@@ -2537,6 +2589,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");
@@ -7037,6 +7091,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);
@@ -7379,6 +7443,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;
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -106,6 +106,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
@@ -665,6 +670,8 @@ struct wpa_supplicant {
#endif /* CONFIG_CTRL_IFACE_BINDER */
char bridge_ifname[16];
+ struct wpa_ctrl *hostapd;
+
char *confname;
char *confanother;
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2751,6 +2751,12 @@ 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;
+ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+ }
+
for (i = 0; i < iface->num_bss; i++) {
/* Save CHAN_SWITCH VHT, HE, and EHT config */
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -2108,11 +2108,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)
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -5345,6 +5345,60 @@ static void wpas_link_reconfig(struct wp
}
+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)
{
@@ -5697,8 +5751,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;
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -6421,6 +6421,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
@@ -6431,6 +6432,7 @@ union wpa_event_data {
* @punct_bitmap: Puncturing bitmap
*/
struct ch_switch {
+ int count;
int freq;
int ht_enabled;
int ch_offset;
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1202,6 +1202,7 @@ static void mlme_event_ch_switch(struct
struct nlattr *bw, struct nlattr *cf1,
struct nlattr *cf2,
struct nlattr *punct_bitmap,
+ struct nlattr *count,
int finished)
{
struct i802_bss *bss;
@@ -1265,6 +1266,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->flink->freq = data.ch_switch.freq;
@@ -3848,6 +3851,7 @@ static void do_process_drv_event(struct
tb[NL80211_ATTR_CENTER_FREQ1],
tb[NL80211_ATTR_CENTER_FREQ2],
tb[NL80211_ATTR_PUNCT_BITMAP],
+ tb[NL80211_ATTR_CH_SWITCH_COUNT],
0);
break;
case NL80211_CMD_CH_SWITCH_NOTIFY:
@@ -3860,6 +3864,7 @@ static void do_process_drv_event(struct
tb[NL80211_ATTR_CENTER_FREQ1],
tb[NL80211_ATTR_CENTER_FREQ2],
tb[NL80211_ATTR_PUNCT_BITMAP],
+ NULL,
1);
break;
case NL80211_CMD_DISCONNECT:

View File

@ -12,7 +12,7 @@
else
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -3377,6 +3377,7 @@ static int hostapd_ctrl_iface_receive_pr
@@ -3314,6 +3314,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) {
@@ -3418,6 +3419,7 @@ static int hostapd_ctrl_iface_receive_pr
@@ -3355,6 +3356,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
@@ -985,6 +985,9 @@ ifdef CONFIG_FILS
@@ -983,6 +983,9 @@ ifdef CONFIG_FILS
OBJS += ../src/ap/fils_hlp.o
endif
ifdef CONFIG_CTRL_IFACE

View File

@ -37,16 +37,16 @@
#include "crypto/crypto.h"
#include "fst/fst.h"
#include "wpa_supplicant_i.h"
@@ -203,7 +204,7 @@ int main(int argc, char *argv[])
@@ -202,7 +203,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) {
@@ -306,8 +307,12 @@ int main(int argc, char *argv[])
@@ -302,8 +303,12 @@ int main(int argc, char *argv[])
break;
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
case 'v':

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
@@ -217,6 +227,8 @@ static int hostapd_driver_init(struct ho
}
#endif /* CONFIG_IEEE80211BE */
+ 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;
@@ -497,8 +509,6 @@ static void hostapd_global_deinit(const
#endif /* CONFIG_NATIVE_WINDOWS */
eap_server_unregister_methods();
-
- os_daemonize_terminate(pid_file);
}
@@ -524,18 +534,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;
@@ -739,8 +737,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
@@ -4203,6 +4203,12 @@ static void wpas_start_assoc_cb(struct w
@@ -4149,6 +4149,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

@ -1,6 +1,6 @@
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3094,6 +3094,10 @@ void ibss_mesh_setup_freq(struct wpa_sup
@@ -3040,6 +3040,10 @@ void ibss_mesh_setup_freq(struct wpa_sup
freq->freq = ssid->frequency;

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
@@ -2039,31 +2039,31 @@ wpa_supplicant_multi.a: .config $(BCHECK
@@ -2037,31 +2037,31 @@ wpa_supplicant_multi.a: .config $(BCHECK
@$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)
wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)

View File

@ -41,7 +41,7 @@
struct hostapd_iface * hostapd_alloc_iface(void);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -455,6 +455,7 @@ void hostapd_free_hapd_data(struct hosta
@@ -435,6 +435,7 @@ void hostapd_free_hapd_data(struct hosta
hapd->beacon_set_done = 0;
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
@ -49,7 +49,7 @@
accounting_deinit(hapd);
hostapd_deinit_wpa(hapd);
vlan_deinit(hapd);
@@ -1207,6 +1208,8 @@ static int hostapd_start_beacon(struct h
@@ -1187,6 +1188,8 @@ static int hostapd_start_beacon(struct h
if (hapd->driver && hapd->driver->set_operstate)
hapd->driver->set_operstate(hapd->drv_priv, 1);
@ -58,7 +58,7 @@
return 0;
}
@@ -2295,6 +2298,7 @@ static int hostapd_setup_interface_compl
@@ -2275,6 +2278,7 @@ static int hostapd_setup_interface_compl
if (err)
goto fail;
@ -66,7 +66,7 @@
wpa_printf(MSG_DEBUG, "Completing interface initialization");
if (iface->freq) {
#ifdef NEED_AP_MLME
@@ -2514,6 +2518,7 @@ dfs_offload:
@@ -2494,6 +2498,7 @@ dfs_offload:
fail:
wpa_printf(MSG_ERROR, "Interface initialization failed");
@ -74,7 +74,7 @@
if (iface->is_no_ir) {
hostapd_set_state(iface, HAPD_IFACE_NO_IR);
@@ -3004,6 +3009,7 @@ void hostapd_interface_deinit_free(struc
@@ -2984,6 +2989,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;
@ -322,7 +322,7 @@
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -194,6 +194,13 @@ ifdef CONFIG_EAPOL_TEST
@@ -192,6 +192,13 @@ ifdef CONFIG_EAPOL_TEST
CFLAGS += -Werror -DEAPOL_TEST
endif
@ -336,7 +336,7 @@
ifdef CONFIG_CODE_COVERAGE
CFLAGS += -O0 -fprofile-arcs -ftest-coverage
LIBS += -lgcov
@@ -989,6 +996,9 @@ ifdef CONFIG_CTRL_IFACE_MIB
@@ -987,6 +994,9 @@ ifdef CONFIG_CTRL_IFACE_MIB
CFLAGS += -DCONFIG_CTRL_IFACE_MIB
endif
OBJS += ../src/ap/ctrl_iface_ap.o
@ -348,7 +348,7 @@
CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -7635,6 +7635,8 @@ struct wpa_supplicant * wpa_supplicant_a
@@ -7566,6 +7566,8 @@ struct wpa_supplicant * wpa_supplicant_a
}
#endif /* CONFIG_P2P */
@ -357,7 +357,7 @@
return wpa_s;
}
@@ -7661,6 +7663,8 @@ int wpa_supplicant_remove_iface(struct w
@@ -7592,6 +7594,8 @@ int wpa_supplicant_remove_iface(struct w
struct wpa_supplicant *parent = wpa_s->parent;
#endif /* CONFIG_MESH */
@ -366,7 +366,7 @@
/* Remove interface from the global list of interfaces */
prev = global->ifaces;
if (prev == wpa_s) {
@@ -8007,8 +8011,12 @@ int wpa_supplicant_run(struct wpa_global
@@ -7938,8 +7942,12 @@ int wpa_supplicant_run(struct wpa_global
eloop_register_signal_terminate(wpa_supplicant_terminate, global);
eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
@ -389,7 +389,7 @@
extern const char *const wpa_supplicant_version;
extern const char *const wpa_supplicant_license;
@@ -324,6 +325,8 @@ struct wpa_global {
@@ -319,6 +320,8 @@ struct wpa_global {
#endif /* CONFIG_WIFI_DISPLAY */
struct psk_list_entry *add_psk; /* From group formation */
@ -398,7 +398,7 @@
};
@@ -655,6 +658,7 @@ struct wpa_supplicant {
@@ -650,6 +653,7 @@ struct wpa_supplicant {
unsigned char own_addr[ETH_ALEN];
unsigned char perm_addr[ETH_ALEN];
char ifname[100];
@ -427,16 +427,16 @@
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -204,7 +204,7 @@ int main(int argc, char *argv[])
@@ -203,7 +203,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) {
@@ -272,6 +272,9 @@ int main(int argc, char *argv[])
@@ -268,6 +268,9 @@ int main(int argc, char *argv[])
params.conf_p2p_dev = optarg;
break;
#endif /* CONFIG_P2P */

View File

@ -26,7 +26,7 @@
ifdef CONFIG_CODE_COVERAGE
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -991,6 +991,7 @@ int main(int argc, char *argv[])
@@ -994,6 +994,7 @@ int main(int argc, char *argv[])
}
hostapd_global_ctrl_iface_init(&interfaces);
@ -34,7 +34,7 @@
if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
wpa_printf(MSG_ERROR, "Failed to start eloop");
@@ -1000,6 +1001,7 @@ int main(int argc, char *argv[])
@@ -1003,6 +1004,7 @@ int main(int argc, char *argv[])
ret = 0;
out:
@ -79,18 +79,27 @@
void *owner;
char *config_fname;
struct hostapd_config *conf;
@@ -706,6 +713,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);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -276,6 +276,8 @@ int hostapd_reload_config(struct hostapd
@@ -252,6 +252,8 @@ int hostapd_reload_config(struct hostapd
struct hostapd_config *newconf, *oldconf;
size_t j;
int i;
+ hostapd_ucode_reload_bss(hapd, reconf);
+ 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);
@@ -455,6 +457,7 @@ void hostapd_free_hapd_data(struct hosta
@@ -435,6 +437,7 @@ void hostapd_free_hapd_data(struct hosta
hapd->beacon_set_done = 0;
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
@ -98,7 +107,7 @@
hostapd_ubus_free_bss(hapd);
accounting_deinit(hapd);
hostapd_deinit_wpa(hapd);
@@ -619,6 +622,7 @@ void hostapd_cleanup_iface_partial(struc
@@ -599,6 +602,7 @@ void hostapd_cleanup_iface_partial(struc
static void hostapd_cleanup_iface(struct hostapd_iface *iface)
{
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
@ -106,7 +115,7 @@
eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface,
NULL);
@@ -1209,6 +1213,7 @@ static int hostapd_start_beacon(struct h
@@ -1189,6 +1193,7 @@ static int hostapd_start_beacon(struct h
hapd->driver->set_operstate(hapd->drv_priv, 1);
hostapd_ubus_add_bss(hapd);
@ -114,9 +123,28 @@
return 0;
}
@@ -1211,8 +1216,7 @@ static int hostapd_start_beacon(struct h
* 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,
- bool start_beacon)
+int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon)
{
struct hostapd_bss_config *conf = hapd->conf;
u8 ssid[SSID_MAX_LEN + 1];
@@ -2698,7 +2702,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;
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -197,8 +197,20 @@ endif
@@ -195,8 +195,20 @@ endif
ifdef CONFIG_UBUS
CFLAGS += -DUBUS_SUPPORT
OBJS += ubus.o
@ -138,7 +166,7 @@
endif
ifdef CONFIG_CODE_COVERAGE
@@ -999,6 +1011,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o
@@ -997,6 +1009,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o
ifdef CONFIG_UBUS
OBJS += ../src/ap/ubus.o
endif
@ -150,7 +178,15 @@
CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -7636,6 +7636,7 @@ struct wpa_supplicant * wpa_supplicant_a
@@ -1044,6 +1044,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)
@@ -7567,6 +7568,7 @@ struct wpa_supplicant * wpa_supplicant_a
#endif /* CONFIG_P2P */
wpas_ubus_add_bss(wpa_s);
@ -158,7 +194,7 @@
return wpa_s;
}
@@ -7663,6 +7664,7 @@ int wpa_supplicant_remove_iface(struct w
@@ -7594,6 +7596,7 @@ int wpa_supplicant_remove_iface(struct w
struct wpa_supplicant *parent = wpa_s->parent;
#endif /* CONFIG_MESH */
@ -166,7 +202,7 @@
wpas_ubus_free_bss(wpa_s);
/* Remove interface from the global list of interfaces */
@@ -7973,6 +7975,7 @@ struct wpa_global * wpa_supplicant_init(
@@ -7904,6 +7907,7 @@ struct wpa_global * wpa_supplicant_init(
eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
wpas_periodic, global, NULL);
@ -174,7 +210,7 @@
return global;
}
@@ -8011,12 +8014,8 @@ int wpa_supplicant_run(struct wpa_global
@@ -7942,12 +7946,8 @@ int wpa_supplicant_run(struct wpa_global
eloop_register_signal_terminate(wpa_supplicant_terminate, global);
eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
@ -187,7 +223,7 @@
return 0;
}
@@ -8049,6 +8048,8 @@ void wpa_supplicant_deinit(struct wpa_gl
@@ -7980,6 +7980,8 @@ void wpa_supplicant_deinit(struct wpa_gl
wpas_notify_supplicant_deinitialized(global);
@ -206,7 +242,7 @@
extern const char *const wpa_supplicant_version;
extern const char *const wpa_supplicant_license;
@@ -659,6 +660,7 @@ struct wpa_supplicant {
@@ -654,6 +655,7 @@ struct wpa_supplicant {
unsigned char perm_addr[ETH_ALEN];
char ifname[100];
struct wpas_ubus_bss ubus;
@ -216,7 +252,7 @@
#endif /* CONFIG_MATCH_IFACE */
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -4921,6 +4921,7 @@ try_again:
@@ -4856,6 +4856,7 @@ try_again:
return -1;
}
@ -224,7 +260,7 @@
wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
return 0;
@@ -5022,6 +5023,7 @@ fail:
@@ -4957,6 +4958,7 @@ fail:
os_free(fname);
interface->global_ctrl_sock = s;
@ -232,3 +268,66 @@
eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
interface, NULL);
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -6426,6 +6426,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
@@ -6436,6 +6437,7 @@ union wpa_event_data {
* @punct_bitmap: Puncturing bitmap
*/
struct ch_switch {
+ int count;
int freq;
int ht_enabled;
int ch_offset;
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1202,6 +1202,7 @@ static void mlme_event_ch_switch(struct
struct nlattr *bw, struct nlattr *cf1,
struct nlattr *cf2,
struct nlattr *punct_bitmap,
+ struct nlattr *count,
int finished)
{
struct i802_bss *bss;
@@ -1265,6 +1266,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->flink->freq = data.ch_switch.freq;
@@ -3848,6 +3851,7 @@ static void do_process_drv_event(struct
tb[NL80211_ATTR_CENTER_FREQ1],
tb[NL80211_ATTR_CENTER_FREQ2],
tb[NL80211_ATTR_PUNCT_BITMAP],
+ tb[NL80211_ATTR_CH_SWITCH_COUNT],
0);
break;
case NL80211_CMD_CH_SWITCH_NOTIFY:
@@ -3860,6 +3864,7 @@ static void do_process_drv_event(struct
tb[NL80211_ATTR_CENTER_FREQ1],
tb[NL80211_ATTR_CENTER_FREQ2],
tb[NL80211_ATTR_PUNCT_BITMAP],
+ NULL,
1);
break;
case NL80211_CMD_DISCONNECT:
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -5381,6 +5381,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

View File

@ -1,232 +0,0 @@
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2420,6 +2420,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, "config_id") == 0) {
@@ -3130,6 +3132,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
@@ -998,6 +998,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
@@ -998,6 +998,7 @@ struct eht_phy_capabilities_info {
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
@@ -127,7 +127,7 @@ void hostapd_reconfig_encryption(struct
}
-static void hostapd_reload_bss(struct hostapd_data *hapd)
+void hostapd_reload_bss(struct hostapd_data *hapd)
{
struct hostapd_ssid *ssid;
@@ -255,6 +255,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;
@@ -268,7 +272,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];
@@ -298,6 +302,9 @@ int hostapd_reload_config(struct hostapd
char *fname;
int res;
+ if (reconf)
+ return -1;
+
hostapd_clear_old(iface);
wpa_printf(MSG_DEBUG,
@@ -324,6 +331,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;
@@ -340,6 +365,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);
if (!hapd->conf->config_id || !newconf->bss[j]->config_id ||
os_strcmp(hapd->conf->config_id,
newconf->bss[j]->config_id) != 0)
@@ -1236,8 +1267,7 @@ static int hostapd_start_beacon(struct h
* 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,
- bool start_beacon)
+int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon)
{
struct hostapd_bss_config *conf = hapd->conf;
u8 ssid[SSID_MAX_LEN + 1];
@@ -2705,6 +2735,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;
@@ -2723,7 +2757,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;
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -48,7 +48,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);
@@ -192,6 +192,7 @@ struct hostapd_data {
struct hostapd_bss_config *conf;
struct hostapd_ubus_bss ubus;
struct hostapd_ucode_bss ucode;
+ char *config_id;
int interface_added; /* virtual interface added for this BSS */
unsigned int started:1;
unsigned int disabled:1;
@@ -696,7 +697,9 @@ 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_reload_bss(struct hostapd_data *hapd);
+void hostapd_bss_deinit(struct hostapd_data *hapd);
void hostapd_reconfig_encryption(struct hostapd_data *hapd);
struct hostapd_data *
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
@@ -713,6 +716,7 @@ 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_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
int reassoc);
void hostapd_interface_deinit_free(struct hostapd_iface *iface);
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5322,6 +5322,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->flink->beacon_set)
+ ret = 0;
+ bss->flink->beacon_set = 0;
} else {
link->beacon_set = 1;
nl80211_set_bss(bss, params->cts_protect, params->preamble,
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -187,7 +187,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
@@ -410,7 +410,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

@ -1,6 +1,6 @@
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4814,7 +4814,12 @@ struct hostapd_config * hostapd_config_r
@@ -4810,7 +4810,12 @@ struct hostapd_config * hostapd_config_r
int errors = 0;
size_t i;

View File

@ -30,7 +30,7 @@
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3355,6 +3355,8 @@ static int hostapd_config_fill(struct ho
@@ -3351,6 +3351,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,6 +1,6 @@
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2850,6 +2850,14 @@ static int hostapd_config_fill(struct ho
@@ -2848,6 +2848,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
@@ -744,6 +744,7 @@ void hostapd_cleanup_cs_params(struct ho
@@ -742,6 +742,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,10 +27,10 @@
void hostapd_cleanup_cca_params(struct hostapd_data *hapd);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -272,6 +272,30 @@ static int hostapd_iface_conf_changed(st
@@ -244,6 +244,29 @@ static int hostapd_iface_conf_changed(st
return 0;
}
+static inline int hostapd_iface_num_sta(struct hostapd_iface *iface)
+{
+ int num_sta = 0;
@ -54,10 +54,9 @@
+
+ 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
+++ b/src/ap/beacon.c
@@ -1252,7 +1252,7 @@ void handle_probe_req(struct hostapd_dat
@ -71,7 +70,7 @@
" since no room for additional STA",
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1037,6 +1037,8 @@ struct hostapd_config {
@@ -1036,6 +1036,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
@@ -3009,6 +3009,8 @@ static int hostapd_config_fill(struct ho
@@ -3007,6 +3007,8 @@ static int hostapd_config_fill(struct ho
wpa_printf(MSG_INFO,
"Line %d: Obsolete peerkey parameter ignored", line);
#ifdef CONFIG_IEEE80211R_AP

View File

@ -18,7 +18,7 @@
#ifdef CONFIG_HS20
static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
@@ -4066,10 +4066,10 @@ static int hostapd_config_fill(struct ho
@@ -4062,10 +4062,10 @@ static int hostapd_config_fill(struct ho
bss->gas_frag_limit = val;
} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
bss->gas_comeback_delay = atoi(pos);
@ -32,7 +32,7 @@
os_free(bss->dump_msk_file);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1538,6 +1538,7 @@ int hostapd_setup_bss(struct hostapd_dat
@@ -1486,6 +1486,7 @@ int hostapd_setup_bss(struct hostapd_dat
wpa_printf(MSG_ERROR, "GAS server initialization failed");
return -1;
}
@ -40,7 +40,7 @@
if (conf->qos_map_set_len &&
hostapd_drv_set_qos_map(hapd, conf->qos_map_set,
@@ -1545,7 +1546,6 @@ int hostapd_setup_bss(struct hostapd_dat
@@ -1493,7 +1494,6 @@ int hostapd_setup_bss(struct hostapd_dat
wpa_printf(MSG_ERROR, "Failed to initialize QoS Map");
return -1;
}

View File

@ -98,7 +98,7 @@
hapd->conf->own_ip_addr.af == AF_INET &&
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2690,6 +2690,8 @@ static int hostapd_config_fill(struct ho
@@ -2688,6 +2688,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

@ -10,7 +10,7 @@
unsigned int time_window;
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1475,6 +1475,7 @@ int hostapd_setup_bss(struct hostapd_dat
@@ -1423,6 +1423,7 @@ int hostapd_setup_bss(struct hostapd_dat
os_memset(&das_conf, 0, sizeof(das_conf));
das_conf.port = conf->radius_das_port;

View File

@ -13,15 +13,15 @@
OBJS += ../src/ap/drv_callbacks.o
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -42,6 +42,7 @@ static struct hapd_global global;
static int daemonize = 0;
static char *pid_file = NULL;
@@ -40,6 +40,7 @@ struct hapd_global {
static struct hapd_global global;
+extern int radius_main(int argc, char **argv);
#ifndef CONFIG_NO_HOSTAPD_LOGGER
static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
@@ -755,6 +756,11 @@ int main(int argc, char *argv[])
@@ -758,6 +759,11 @@ int main(int argc, char *argv[])
if (os_program_init())
return -1;

View File

@ -163,7 +163,7 @@ hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj,
{
struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
return hostapd_reload_config(hapd->iface, 1);
return hostapd_reload_config(hapd->iface);
}

View File

@ -4,6 +4,8 @@
#include "utils/common.h"
#include "utils/ucode.h"
#include "hostapd.h"
#include "beacon.h"
#include "hw_features.h"
#include "ap_drv_ops.h"
#include <libubox/uloop.h>
@ -289,12 +291,151 @@ uc_hostapd_bss_ctrl(uc_vm_t *vm, size_t nargs)
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;
for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *hapd = iface->bss[i];
hostapd_drv_stop_ap(hapd);
hapd->started = 0;
}
}
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;
uint64_t intval;
int i;
if (!iface)
return NULL;
if (!info)
goto out;
if (ucv_type(info) != UC_OBJECT)
return NULL;
conf = iface->conf;
if ((intval = ucv_int64_get(ucv_object_get(info, "op_class", NULL))) && !errno)
conf->op_class = intval;
if ((intval = ucv_int64_get(ucv_object_get(info, "hw_mode", NULL))) && !errno)
conf->hw_mode = intval;
if ((intval = ucv_int64_get(ucv_object_get(info, "channel", NULL))) && !errno)
conf->channel = intval;
if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno)
conf->secondary_channel = intval;
if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL))) && !errno) {
conf->vht_oper_centr_freq_seg0_idx = intval;
conf->he_oper_centr_freq_seg0_idx = intval;
#ifdef CONFIG_IEEE80211BE
conf->eht_oper_centr_freq_seg0_idx = intval;
#endif
}
if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL))) && !errno) {
conf->vht_oper_centr_freq_seg1_idx = intval;
conf->he_oper_centr_freq_seg1_idx = intval;
#ifdef CONFIG_IEEE80211BE
conf->eht_oper_centr_freq_seg1_idx = intval;
#endif
}
intval = ucv_int64_get(ucv_object_get(info, "oper_chwidth", NULL));
if (!errno) {
conf->vht_oper_chwidth = intval;
conf->he_oper_chwidth = intval;
#ifdef CONFIG_IEEE80211BE
conf->eht_oper_chwidth = intval;
#endif
}
out:
if (conf->channel)
iface->freq = hostapd_hw_get_freq(iface->bss[0], conf->channel);
for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *hapd = iface->bss[i];
int ret;
hapd->started = 1;
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));
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);
}
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 },
};
@ -304,7 +445,10 @@ int hostapd_ucode_init(struct hapd_interfaces *ifaces)
{ "delete", uc_hostapd_bss_delete },
};
static const uc_function_list_t iface_fns[] = {
{ "add_bss", uc_hostapd_iface_add_bss }
{ "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;
@ -360,7 +504,7 @@ void hostapd_ucode_add_bss(struct hostapd_data *hapd)
ucv_gc(vm);
}
void hostapd_ucode_reload_bss(struct hostapd_data *hapd, int reconf)
void hostapd_ucode_reload_bss(struct hostapd_data *hapd)
{
uc_value_t *val;
@ -370,8 +514,7 @@ void hostapd_ucode_reload_bss(struct hostapd_data *hapd, int reconf)
val = hostapd_ucode_bss_get_uval(hapd);
uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface)));
uc_value_push(ucv_get(val));
uc_value_push(ucv_int64_new(reconf));
ucv_put(wpa_ucode_call(3));
ucv_put(wpa_ucode_call(2));
ucv_gc(vm);
}

View File

@ -25,7 +25,7 @@ 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, int reconf);
void hostapd_ucode_reload_bss(struct hostapd_data *hapd);
#else
@ -39,7 +39,7 @@ 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, int reconf)
static inline void hostapd_ucode_reload_bss(struct hostapd_data *hapd)
{
}
static inline void hostapd_ucode_add_bss(struct hostapd_data *hapd)

View File

@ -3,6 +3,7 @@
#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>
@ -45,6 +46,92 @@ uc_value_t *uc_wpa_printf(uc_vm_t *vm, size_t nargs)
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 oper_chan_width chanwidth;
enum hostapd_hw_mode hw_mode;
u8 op_class, channel, tmp_channel;
const char *modestr;
int sec_channel = 0;
uc_value_t *ret;
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 = CONF_OPER_CHWIDTH_USE_HT;
break;
case 1:
chanwidth = CONF_OPER_CHWIDTH_80MHZ;
break;
case 2:
chanwidth = CONF_OPER_CHWIDTH_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;
center_ofs = freq_val >= 5900 ? 0 : 3;
tmp_channel = channel - center_ofs;
tmp_channel &= ~((8 << width) - 1);
center_idx = tmp_channel + center_ofs + (4 << width) - 1;
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());

View File

@ -24,5 +24,6 @@ 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

@ -1,8 +1,10 @@
#include "utils/includes.h"
#include "utils/common.h"
#include "utils/ucode.h"
#include "drivers/driver.h"
#include "wpa_supplicant_i.h"
#include "wps_supplicant.h"
#include "bss.h"
#include "ucode.h"
static struct wpa_global *wpa_global;
@ -69,6 +71,57 @@ void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s)
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(val));
uc_value_push(ucv_get(ucv_string_new(state)));
ucv_put(wpa_ucode_call(2));
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(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(3));
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);
@ -84,7 +137,6 @@ uc_wpas_add_iface(uc_vm_t *vm, size_t nargs)
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);
uc_value_t *hapd_ctrl = ucv_object_get(info, "hostapd_ctrl", NULL);
struct wpa_interface iface;
int ret = -1;
@ -97,7 +149,6 @@ uc_wpas_add_iface(uc_vm_t *vm, size_t nargs)
.bridge_ifname = ucv_string_get(bridge),
.confname = ucv_string_get(config),
.ctrl_interface = ucv_string_get(ctrl),
.hostapd_ctrl = ucv_string_get(hapd_ctrl),
};
if (!iface.ifname || !iface.confname)
@ -135,6 +186,45 @@ 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;
ht_oper = (const void *) (ie + 2);
if (ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
sec_chan = 1;
else if (ht_oper->ht_param &
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));
}
return ret;
}
int wpas_ucode_init(struct wpa_global *gl)
{
static const uc_function_list_t global_fns[] = {
@ -144,6 +234,7 @@ int wpas_ucode_init(struct wpa_global *gl)
{ "remove_iface", uc_wpas_remove_iface },
};
static const uc_function_list_t iface_fns[] = {
{ "status", uc_wpas_iface_status },
};
uc_value_t *data, *proto;
@ -151,7 +242,7 @@ int wpas_ucode_init(struct 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, "hostapd.iface", iface_fns, NULL);
iface_type = uc_type_declare(vm, "wpas.iface", iface_fns, NULL);
iface_registry = ucv_array_new(vm);
uc_vm_registry_set(vm, "hostap.iface_registry", iface_registry);

View File

@ -4,6 +4,7 @@
#include "utils/ucode.h"
struct wpa_global;
union wpa_event_data;
struct wpa_supplicant;
struct wpas_ucode_bss {
@ -17,6 +18,8 @@ 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)
{
@ -33,6 +36,14 @@ 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