Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 11e9ffc61037f15ce3161f80c660dfcf5f7dc2c3 Mon Sep 17 00:00:00 2001
- From: Robert Marko <robimarko@gmail.com>
- Date: Fri, 10 May 2019 20:38:20 +0200
- Subject: [PATCH] Add low RSSI features for OpenWrt
- Still WIP and depends on ubus.
- ---
- hostapd/config_file.c | 20 ++++++++++++++++++++
- src/ap/ap_config.c | 7 +++++++
- src/ap/ap_config.h | 6 ++++++
- src/ap/sta_info.c | 4 ++++
- src/ap/sta_info.h | 4 ++++
- src/drivers/driver_nl80211.c | 4 ++++
- 6 files changed, 45 insertions(+)
- --- a/hostapd/config_file.c
- +++ b/hostapd/config_file.c
- @@ -3149,6 +3149,26 @@ static int hostapd_config_fill(struct ho
- return 1;
- }
- conf->send_probe_response = val;
- +#ifdef UBUS_SUPPORT
- + } else if (os_strcmp(buf, "signal_connect") == 0) {
- + bss->signal_auth_min = atoi(pos);
- + } else if (os_strcmp(buf, "signal_stay") == 0) {
- + bss->signal_stay_min = atoi(pos);
- + } else if (os_strcmp(buf, "signal_poll_time") == 0) {
- + bss->signal_poll_time = atoi(pos);
- + if (bss->signal_poll_time < 2) {
- + wpa_printf(MSG_ERROR, "Line %d: invalid signal poll time", line);
- + return 1;
- + }
- + } else if (os_strcmp(buf, "signal_strikes") == 0) {
- + bss->signal_strikes = atoi(pos);
- + } else if (os_strcmp(buf, "signal_drop_reason") == 0) {
- + bss->signal_drop_reason = atoi(pos);
- + if (bss->signal_drop_reason < 1 || bss->signal_drop_reason > 54) {
- + wpa_printf(MSG_ERROR, "Line %d: invalid signal drop reason", line);
- + return 1;
- + }
- +#endif /* UBUS_SUPPORT */
- } else if (os_strcmp(buf, "supported_rates") == 0) {
- if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
- --- a/src/ap/ap_config.c
- +++ b/src/ap/ap_config.c
- @@ -80,6 +80,13 @@ void hostapd_config_defaults_bss(struct
- bss->eapol_version = EAPOL_VERSION;
- bss->max_listen_interval = 65535;
- +#ifdef UBUS_SUPPORT
- + bss->signal_auth_min = -128; /* this is lower than any real signal, so all stations will be accepted */
- + bss->signal_stay_min = -128;
- + bss->signal_strikes = 3;
- + bss->signal_poll_time = 10;
- + bss->signal_drop_reason = 3; /* "Local choice" */
- +#endif /* UBUS_SUPPORT */
- bss->pwd_group = 19; /* ECC: GF(p=256) */
- --- a/src/ap/ap_config.h
- +++ b/src/ap/ap_config.h
- @@ -322,6 +322,12 @@ struct hostapd_bss_config {
- int wds_sta;
- int isolate;
- int start_disabled;
- + int signal_auth_min; /* Minimum signal a STA needs to authenticate */
- + int signal_stay_min; /* Minimum signal needed to stay connected. */
- + int signal_poll_time; /* Time in seconds between checks of connected STAs */
- + int signal_strikes; /* Number of consecutive times signal can be low
- + before dropping the STA. */
- + int signal_drop_reason; /* IEEE802.11 reason code transmitted when dropping a STA. */
- int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
- * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
- --- a/src/ap/sta_info.c
- +++ b/src/ap/sta_info.c
- @@ -706,6 +706,10 @@ struct sta_info * ap_sta_add(struct host
- &sta->probe_ie_taxonomy);
- #endif /* CONFIG_TAXONOMY */
- +#ifdef UBUS_SUPPORT
- + sta->sig_drop_strikes = 0;
- +#endif /* UBUS_SUPPORT */
- +
- return sta;
- }
- --- a/src/ap/sta_info.h
- +++ b/src/ap/sta_info.h
- @@ -252,6 +252,10 @@ struct sta_info {
- struct wpabuf *fils_g_sta;
- #endif /* CONFIG_FILS */
- +#ifdef UBUS_SUPPORT
- + int sig_drop_strikes; /* Number of times signal was below threshold. */
- +#endif /* UBUS_SUPPORT */
- +
- #ifdef CONFIG_OWE
- u8 *owe_pmk;
- size_t owe_pmk_len;
- --- a/src/drivers/driver_nl80211.c
- +++ b/src/drivers/driver_nl80211.c
- @@ -6179,6 +6179,7 @@ static int get_sta_handler(struct nl_msg
- [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
- [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
- [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
- + [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
- [NL80211_STA_INFO_ACK_SIGNAL] = { .type = NLA_U8 },
- };
- struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
- @@ -6242,6 +6243,9 @@ static int get_sta_handler(struct nl_msg
- nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
- if (stats[NL80211_STA_INFO_SIGNAL])
- data->signal = nla_get_u8(stats[NL80211_STA_INFO_SIGNAL]);
- + if (stats[NL80211_STA_INFO_SIGNAL_AVG])
- + data->last_ack_rssi =
- + (int) (s8) nla_get_u8(stats[NL80211_STA_INFO_SIGNAL_AVG]);
- if (stats[NL80211_STA_INFO_ACK_SIGNAL]) {
- data->last_ack_rssi =
- nla_get_u8(stats[NL80211_STA_INFO_ACK_SIGNAL]);
- --- a/src/ap/ubus.c
- +++ b/src/ap/ubus.c
- @@ -142,6 +142,59 @@ hostapd_bss_ban_client(struct hostapd_da
- eloop_register_timeout(0, time * 1000, hostapd_bss_del_ban, ban, hapd);
- }
- +static void
- +hostapd_bss_signal_check(void *eloop_data, void *user_ctx)
- +/* This is called by an eloop timeout. All stations in the list are checked
- + * for signal level. This requires calling the driver, since hostapd doesn't
- + * see packets from a station once it is fully authorized.
- + * Stations with signal level below the threshold will be dropped.
- + * Cases where the last RSSI is significantly less than the average are usually
- + * a bad reading and should not lead to a drop.
- + */
- +{
- + struct hostapd_data *hapd = user_ctx;
- + struct hostap_sta_driver_data data;
- + struct sta_info *sta, *sta_next;
- + u8 addr[ETH_ALEN]; // Buffer the address for logging purposes, in case it is destroyed while dropping
- + int strikes; // same with strike count on this station.
- + int num_sta = 0;
- + int num_drop = 0;
- + int signal_inst;
- + int signal_avg;
- +
- +
- + for (sta = hapd->sta_list; sta; sta = sta_next) {
- + sta_next = sta->next;
- + memcpy(addr, sta->addr, ETH_ALEN);
- + if (!hostapd_drv_read_sta_data(hapd, &data, addr)) {
- + signal_inst = data.signal;
- + signal_avg = data.last_ack_rssi;
- + num_sta++;
- + strikes = sta->sig_drop_strikes;
- + if (signal_inst > signal_avg)
- + signal_avg = signal_inst;
- + if (signal_inst > (signal_avg - 5)) { // ignore unusually low instantaneous signal.
- + if (signal_avg < hapd->conf->signal_stay_min) { // signal bad.
- + strikes = ++sta->sig_drop_strikes;
- + if (strikes >= hapd->conf->signal_strikes) { // Struck out--, drop.
- + ap_sta_deauthenticate(hapd, sta, hapd->conf->signal_drop_reason);
- + num_drop++;
- + }
- + }
- + else {
- + sta->sig_drop_strikes = 0; // signal OK, reset the strike counter.
- + strikes = 0;
- + }
- + }
- + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IAPP, HOSTAPD_LEVEL_DEBUG, "%i %i (%i)",
- + data.signal, data.last_ack_rssi, strikes);
- + }
- + }
- + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IAPP, HOSTAPD_LEVEL_INFO, "signal poll: %i STAs, %i dropped", num_sta, num_drop);
- +
- + eloop_register_timeout(hapd->conf->signal_poll_time, 0, hostapd_bss_signal_check, eloop_data, hapd);
- +}
- +
- static int
- hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- @@ -503,6 +556,72 @@ hostapd_vendor_elements(struct ubus_cont
- return UBUS_STATUS_OK;
- }
- +enum {
- + SIGNAL_CONNECT,
- + SIGNAL_STAY,
- + SIGNAL_STRIKES,
- + SIGNAL_POLL,
- + SIGNAL_DROP_REASON,
- + __SIGNAL_SETTINGS_MAX
- +};
- +
- +static const struct blobmsg_policy sig_policy[__SIGNAL_SETTINGS_MAX] = {
- + [SIGNAL_CONNECT] = {"connect", BLOBMSG_TYPE_INT32},
- + [SIGNAL_STAY] = {"stay", BLOBMSG_TYPE_INT32},
- + [SIGNAL_STRIKES] = {"strikes", BLOBMSG_TYPE_INT32},
- + [SIGNAL_POLL] = {"poll_time", BLOBMSG_TYPE_INT32},
- + [SIGNAL_DROP_REASON] = {"reason", BLOBMSG_TYPE_INT32}
- +};
- +
- +static int
- +hostapd_bss_set_signal(struct ubus_context *ctx, struct ubus_object *obj,
- + struct ubus_request_data *req, const char *method,
- + struct blob_attr *msg)
- +{
- + struct blob_attr *tb[__SIGNAL_SETTINGS_MAX];
- + struct hostapd_data *hapd = get_hapd_from_object(obj);
- + int sig_stay;
- +
- + blobmsg_parse(sig_policy, __SIGNAL_SETTINGS_MAX, tb, blob_data(msg), blob_len(msg));
- +
- + if (!tb[SIGNAL_CONNECT])
- + return UBUS_STATUS_INVALID_ARGUMENT;
- + hapd->conf->signal_auth_min = blobmsg_get_u32(tb[SIGNAL_CONNECT]);
- + if (tb[SIGNAL_STAY]) {
- + sig_stay = blobmsg_get_u32(tb[SIGNAL_STAY]);
- +
- + }
- + else
- + sig_stay = hapd->conf->signal_auth_min - 5; // Default is 5 dB lower to stay.
- + hapd->conf->signal_stay_min = sig_stay;
- + if (tb[SIGNAL_STRIKES]) {
- + hapd->conf->signal_strikes = blobmsg_get_u32(tb[SIGNAL_STRIKES]);
- + if (hapd->conf->signal_strikes < 1)
- + return UBUS_STATUS_INVALID_ARGUMENT;
- + }
- + else
- + hapd->conf->signal_strikes = 3;
- + if (tb[SIGNAL_POLL]) {
- + hapd->conf->signal_poll_time = blobmsg_get_u32(tb[SIGNAL_POLL]);
- + if (hapd->conf->signal_poll_time < 3)
- + return UBUS_STATUS_INVALID_ARGUMENT;
- + }
- + else
- + hapd->conf->signal_poll_time = 10;
- + if (tb[SIGNAL_DROP_REASON]) {
- + hapd->conf->signal_drop_reason = blobmsg_get_u32(tb[SIGNAL_DROP_REASON]);
- + if ((hapd->conf->signal_drop_reason < 1) || (hapd->conf->signal_drop_reason > 35)) // XXX -- look up real limit
- + return UBUS_STATUS_INVALID_ARGUMENT;
- + }
- + else
- + hapd->conf->signal_drop_reason = 3; // Local choice. 5 (AP too busy) is also a good one.
- +
- + eloop_cancel_timeout(hostapd_bss_signal_check, ELOOP_ALL_CTX, ELOOP_ALL_CTX);
- + eloop_register_timeout(3, 0, hostapd_bss_signal_check, NULL, hapd); // Start up the poll timer.
- +
- + return UBUS_STATUS_OK;
- +}
- +
- static void
- hostapd_rrm_print_nr(struct hostapd_neighbor_entry *nr)
- {
- @@ -960,6 +1079,7 @@ static const struct ubus_method bss_meth
- UBUS_METHOD("switch_chan", hostapd_switch_chan, csa_policy),
- #endif
- UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy),
- + UBUS_METHOD("set_required_signal", hostapd_bss_set_signal, sig_policy),
- UBUS_METHOD("notify_response", hostapd_notify_response, notify_policy),
- UBUS_METHOD("bss_mgmt_enable", hostapd_bss_mgmt_enable, bss_mgmt_enable_policy),
- UBUS_METHOD_NOARG("rrm_nr_get_own", hostapd_rrm_nr_get_own),
- @@ -1003,6 +1123,9 @@ void hostapd_ubus_add_bss(struct hostapd
- obj->n_methods = bss_object_type.n_methods;
- ret = ubus_add_object(ctx, obj);
- hostapd_ubus_ref_inc();
- + /* This should run after the config file has been read, I hope. */
- + if (hapd->conf->signal_stay_min > -128)
- + eloop_register_timeout(3, 0, hostapd_bss_signal_check, NULL, hapd); // Start up the poll timer.
- }
- void hostapd_ubus_free_bss(struct hostapd_data *hapd)
- @@ -1051,6 +1174,19 @@ int hostapd_ubus_handle_event(struct hos
- else
- addr = req->addr;
- + if (req->type < ARRAY_SIZE(types))
- + type = types[req->type];
- +
- + if (req->frame_info && req->type != HOSTAPD_UBUS_PROBE_REQ) // don't clutter the log with probes.
- + hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME, HOSTAPD_LEVEL_INFO, "%s request, signal %i %s",
- + type, req->frame_info->ssi_signal,
- + (req->frame_info->ssi_signal >= hapd->conf->signal_auth_min) ? "(Accepted)" : "(DENIED)");
- + // reject weak signals.
- + if (req->frame_info && req->frame_info->ssi_signal < hapd->conf->signal_auth_min)
- + return -2;
- +
- + // reject banned MACs.
- +
- ban = avl_find_element(&hapd->ubus.banned, addr, ban, avl);
- if (ban)
- return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
- @@ -1058,9 +1194,6 @@ int hostapd_ubus_handle_event(struct hos
- if (!hapd->ubus.obj.has_subscribers)
- return WLAN_STATUS_SUCCESS;
- - if (req->type < ARRAY_SIZE(types))
- - type = types[req->type];
- -
- blob_buf_init(&b, 0);
- blobmsg_add_macaddr(&b, "address", addr);
- if (req->mgmt_frame)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement