| --- a/hostapd/Makefile |
| +++ b/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 |
| @@ -18,6 +18,7 @@ |
| #include "utils/list.h" |
| #include "ap_config.h" |
| #include "drivers/driver.h" |
| +#include "ubus.h" |
| |
| #define OCE_STA_CFON_ENABLED(hapd) \ |
| ((hapd->conf->oce & OCE_STA_CFON) && \ |
| @@ -184,6 +185,7 @@ struct hostapd_data { |
| struct hostapd_iface *iface; |
| struct hostapd_config *iconf; |
| struct hostapd_bss_config *conf; |
| + struct hostapd_ubus_bss ubus; |
| int interface_added; /* virtual interface added for this BSS */ |
| unsigned int started:1; |
| unsigned int disabled:1; |
| @@ -695,6 +697,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); |
| +void hostapd_set_own_neighbor_report(struct hostapd_data *hapd); |
| 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 |
| @@ -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); |
| + hostapd_ubus_free_bss(hapd); |
| accounting_deinit(hapd); |
| hostapd_deinit_wpa(hapd); |
| vlan_deinit(hapd); |
| @@ -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); |
| |
| + hostapd_ubus_add_bss(hapd); |
| + |
| return 0; |
| } |
| |
| @@ -2275,6 +2278,7 @@ static int hostapd_setup_interface_compl |
| if (err) |
| goto fail; |
| |
| + hostapd_ubus_add_iface(iface); |
| wpa_printf(MSG_DEBUG, "Completing interface initialization"); |
| if (iface->freq) { |
| #ifdef NEED_AP_MLME |
| @@ -2494,6 +2498,7 @@ dfs_offload: |
| |
| fail: |
| wpa_printf(MSG_ERROR, "Interface initialization failed"); |
| + hostapd_ubus_free_iface(iface); |
| |
| if (iface->is_no_ir) { |
| hostapd_set_state(iface, HAPD_IFACE_NO_IR); |
| @@ -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; |
| + hostapd_ubus_free_iface(iface); |
| 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 |
| @@ -2786,7 +2786,7 @@ static void handle_auth(struct hostapd_d |
| u16 auth_alg, auth_transaction, status_code; |
| u16 resp = WLAN_STATUS_SUCCESS; |
| struct sta_info *sta = NULL; |
| - int res, reply_res; |
| + int res, reply_res, ubus_resp; |
| u16 fc; |
| const u8 *challenge = NULL; |
| u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; |
| @@ -2795,6 +2795,11 @@ static void handle_auth(struct hostapd_d |
| struct radius_sta rad_info; |
| const u8 *dst, *sa, *bssid; |
| bool mld_sta = false; |
| + struct hostapd_ubus_request req = { |
| + .type = HOSTAPD_UBUS_AUTH_REQ, |
| + .mgmt_frame = mgmt, |
| + .ssi_signal = rssi, |
| + }; |
| |
| if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { |
| wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)", |
| @@ -2986,6 +2991,13 @@ static void handle_auth(struct hostapd_d |
| resp = WLAN_STATUS_UNSPECIFIED_FAILURE; |
| goto fail; |
| } |
| + ubus_resp = hostapd_ubus_handle_event(hapd, &req); |
| + if (ubus_resp) { |
| + wpa_printf(MSG_DEBUG, "Station " MACSTR " rejected by ubus handler.\n", |
| + MAC2STR(mgmt->sa)); |
| + resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE; |
| + goto fail; |
| + } |
| if (res == HOSTAPD_ACL_PENDING) |
| return; |
| |
| @@ -5161,7 +5173,7 @@ static void handle_assoc(struct hostapd_ |
| int resp = WLAN_STATUS_SUCCESS; |
| u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE; |
| const u8 *pos; |
| - int left, i; |
| + int left, i, ubus_resp; |
| struct sta_info *sta; |
| u8 *tmp = NULL; |
| #ifdef CONFIG_FILS |
| @@ -5374,6 +5386,11 @@ static void handle_assoc(struct hostapd_ |
| left = res; |
| } |
| #endif /* CONFIG_FILS */ |
| + struct hostapd_ubus_request req = { |
| + .type = HOSTAPD_UBUS_ASSOC_REQ, |
| + .mgmt_frame = mgmt, |
| + .ssi_signal = rssi, |
| + }; |
| |
| /* followed by SSID and Supported rates; and HT capabilities if 802.11n |
| * is used */ |
| @@ -5472,6 +5489,13 @@ static void handle_assoc(struct hostapd_ |
| } |
| #endif /* CONFIG_FILS */ |
| |
| + ubus_resp = hostapd_ubus_handle_event(hapd, &req); |
| + if (ubus_resp) { |
| + wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n", |
| + MAC2STR(mgmt->sa)); |
| + resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE; |
| + goto fail; |
| + } |
| fail: |
| |
| /* |
| @@ -5753,6 +5777,7 @@ static void handle_disassoc(struct hosta |
| (unsigned long) len); |
| return; |
| } |
| + hostapd_ubus_notify(hapd, "disassoc", mgmt->sa); |
| |
| sta = ap_get_sta(hapd, mgmt->sa); |
| if (!sta) { |
| @@ -5784,6 +5809,8 @@ static void handle_deauth(struct hostapd |
| /* Clear the PTKSA cache entries for PASN */ |
| ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE); |
| |
| + hostapd_ubus_notify(hapd, "deauth", mgmt->sa); |
| + |
| sta = ap_get_sta(hapd, mgmt->sa); |
| if (!sta) { |
| wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR |
| --- a/src/ap/beacon.c |
| +++ b/src/ap/beacon.c |
| @@ -1036,6 +1036,12 @@ void handle_probe_req(struct hostapd_dat |
| u16 csa_offs[2]; |
| size_t csa_offs_len; |
| struct radius_sta rad_info; |
| + struct hostapd_ubus_request req = { |
| + .type = HOSTAPD_UBUS_PROBE_REQ, |
| + .mgmt_frame = mgmt, |
| + .ssi_signal = ssi_signal, |
| + .elems = &elems, |
| + }; |
| |
| if (hapd->iconf->rssi_ignore_probe_request && ssi_signal && |
| ssi_signal < hapd->iconf->rssi_ignore_probe_request) |
| @@ -1222,6 +1228,12 @@ void handle_probe_req(struct hostapd_dat |
| } |
| #endif /* CONFIG_P2P */ |
| |
| + if (hostapd_ubus_handle_event(hapd, &req)) { |
| + wpa_printf(MSG_DEBUG, "Probe request for " MACSTR " rejected by ubus handler.\n", |
| + MAC2STR(mgmt->sa)); |
| + return; |
| + } |
| + |
| /* 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 |
| @@ -260,6 +260,10 @@ int hostapd_notif_assoc(struct hostapd_d |
| u16 reason = WLAN_REASON_UNSPECIFIED; |
| int status = WLAN_STATUS_SUCCESS; |
| const u8 *p2p_dev_addr = NULL; |
| + struct hostapd_ubus_request req = { |
| + .type = HOSTAPD_UBUS_ASSOC_REQ, |
| + .addr = addr, |
| + }; |
| |
| if (addr == NULL) { |
| /* |
| @@ -396,6 +400,12 @@ int hostapd_notif_assoc(struct hostapd_d |
| goto fail; |
| } |
| |
| + if (hostapd_ubus_handle_event(hapd, &req)) { |
| + wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n", |
| + MAC2STR(req.addr)); |
| + goto fail; |
| + } |
| + |
| #ifdef CONFIG_P2P |
| if (elems.p2p) { |
| wpabuf_free(sta->p2p_ie); |
| --- a/src/ap/sta_info.c |
| +++ b/src/ap/sta_info.c |
| @@ -471,6 +471,7 @@ void ap_handle_timer(void *eloop_ctx, vo |
| hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
| HOSTAPD_LEVEL_INFO, "deauthenticated due to " |
| "local deauth request"); |
| + hostapd_ubus_notify(hapd, "local-deauth", sta->addr); |
| ap_free_sta(hapd, sta); |
| return; |
| } |
| @@ -626,6 +627,7 @@ skip_poll: |
| mlme_deauthenticate_indication( |
| hapd, sta, |
| WLAN_REASON_PREV_AUTH_NOT_VALID); |
| + hostapd_ubus_notify(hapd, "inactive-deauth", sta->addr); |
| ap_free_sta(hapd, sta); |
| break; |
| } |
| @@ -1344,15 +1346,28 @@ 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 u8 *dpp_pkhash; |
| const char *keyid; |
| char dpp_pkhash_buf[100]; |
| char keyid_buf[100]; |
| char ip_addr[100]; |
| + char alg_buf[100]; |
| |
| dpp_pkhash_buf[0] = '\0'; |
| 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), |
| @@ -1362,6 +1377,13 @@ 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), |
| @@ -1380,17 +1402,19 @@ void ap_sta_set_authorized(struct hostap |
| dpp_pkhash, SHA256_MAC_LEN); |
| } |
| |
| - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s", |
| - buf, ip_addr, keyid_buf, dpp_pkhash_buf); |
| + hostapd_ubus_notify_authorized(hapd, sta, auth_alg); |
| + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s%s", |
| + buf, ip_addr, keyid_buf, dpp_pkhash_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%s", |
| + AP_STA_CONNECTED "%s%s%s%s%s", |
| buf, ip_addr, keyid_buf, |
| - dpp_pkhash_buf); |
| + dpp_pkhash_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 |
| @@ -269,6 +269,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, |
| MAC2STR(addr)); |
| + hostapd_ubus_notify(hapd, "key-mismatch", addr); |
| } |
| |
| |
| --- a/wpa_supplicant/Makefile |
| +++ b/wpa_supplicant/Makefile |
| @@ -192,6 +192,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 |
| @@ -987,6 +994,9 @@ ifdef CONFIG_CTRL_IFACE_MIB |
| CFLAGS += -DCONFIG_CTRL_IFACE_MIB |
| endif |
| OBJS += ../src/ap/ctrl_iface_ap.o |
| +ifdef CONFIG_UBUS |
| +OBJS += ../src/ap/ubus.o |
| +endif |
| endif |
| |
| CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY |
| --- a/wpa_supplicant/wpa_supplicant.c |
| +++ b/wpa_supplicant/wpa_supplicant.c |
| @@ -7595,6 +7595,8 @@ struct wpa_supplicant * wpa_supplicant_a |
| } |
| #endif /* CONFIG_P2P */ |
| |
| + wpas_ubus_add_bss(wpa_s); |
| + |
| return wpa_s; |
| } |
| |
| @@ -7621,6 +7623,8 @@ int wpa_supplicant_remove_iface(struct w |
| struct wpa_supplicant *parent = wpa_s->parent; |
| #endif /* CONFIG_MESH */ |
| |
| + wpas_ubus_free_bss(wpa_s); |
| + |
| /* Remove interface from the global list of interfaces */ |
| prev = global->ifaces; |
| if (prev == wpa_s) { |
| @@ -7967,8 +7971,12 @@ 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; |
| } |
| |
| --- a/wpa_supplicant/wpa_supplicant_i.h |
| +++ b/wpa_supplicant/wpa_supplicant_i.h |
| @@ -21,6 +21,7 @@ |
| #include "config_ssid.h" |
| #include "wmm_ac.h" |
| #include "pasn/pasn_common.h" |
| +#include "ubus.h" |
| |
| extern const char *const wpa_supplicant_version; |
| extern const char *const wpa_supplicant_license; |
| @@ -319,6 +320,8 @@ struct wpa_global { |
| #endif /* CONFIG_WIFI_DISPLAY */ |
| |
| struct psk_list_entry *add_psk; /* From group formation */ |
| + |
| + struct ubus_object ubus_global; |
| }; |
| |
| |
| @@ -685,6 +688,7 @@ struct wpa_supplicant { |
| unsigned char own_addr[ETH_ALEN]; |
| unsigned char perm_addr[ETH_ALEN]; |
| char ifname[100]; |
| + struct wpas_ubus_bss ubus; |
| #ifdef CONFIG_MATCH_IFACE |
| int matched; |
| #endif /* CONFIG_MATCH_IFACE */ |
| --- a/wpa_supplicant/wps_supplicant.c |
| +++ b/wpa_supplicant/wps_supplicant.c |
| @@ -33,6 +33,7 @@ |
| #include "p2p/p2p.h" |
| #include "p2p_supplicant.h" |
| #include "wps_supplicant.h" |
| +#include "ubus.h" |
| |
| |
| #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG |
| @@ -402,6 +403,8 @@ static int wpa_supplicant_wps_cred(void |
| wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", |
| cred->cred_attr, cred->cred_attr_len); |
| |
| + wpas_ubus_notify(wpa_s, cred); |
| + |
| if (wpa_s->conf->wps_cred_processing == 1) |
| return 0; |
| |
| --- a/wpa_supplicant/main.c |
| +++ b/wpa_supplicant/main.c |
| @@ -203,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: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) { |
| @@ -268,6 +268,9 @@ int main(int argc, char *argv[]) |
| params.conf_p2p_dev = optarg; |
| break; |
| #endif /* CONFIG_P2P */ |
| + case 'n': |
| + iface_count = 0; |
| + break; |
| case 'o': |
| params.override_driver = optarg; |
| break; |
| --- a/src/ap/rrm.c |
| +++ b/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", |
| MAC2STR(addr), token, rep_mode, report); |
| + if (len < sizeof(struct rrm_measurement_beacon_report)) |
| + return; |
| + hostapd_ubus_notify_beacon_report(hapd, addr, token, rep_mode, (struct rrm_measurement_beacon_report*) pos, len); |
| } |
| |
| |
| @@ -352,6 +355,9 @@ void hostapd_handle_radio_measurement(st |
| mgmt->u.action.u.rrm.action, MAC2STR(mgmt->sa)); |
| |
| switch (mgmt->u.action.u.rrm.action) { |
| + case WLAN_RRM_LINK_MEASUREMENT_REPORT: |
| + hostapd_ubus_handle_link_measurement(hapd, buf, len); |
| + break; |
| case WLAN_RRM_RADIO_MEASUREMENT_REPORT: |
| hostapd_handle_radio_msmt_report(hapd, buf, len); |
| break; |
| --- a/src/ap/vlan_init.c |
| +++ b/src/ap/vlan_init.c |
| @@ -22,6 +22,7 @@ |
| static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan, |
| int existsok) |
| { |
| + bool vlan_exists = iface_exists(vlan->ifname); |
| int ret; |
| #ifdef CONFIG_WEP |
| int i; |
| @@ -36,7 +37,7 @@ static int vlan_if_add(struct hostapd_da |
| } |
| #endif /* CONFIG_WEP */ |
| |
| - if (!iface_exists(vlan->ifname)) |
| + if (!vlan_exists) |
| ret = hostapd_vlan_if_add(hapd, vlan->ifname); |
| else if (!existsok) |
| return -1; |
| @@ -51,6 +52,9 @@ static int vlan_if_add(struct hostapd_da |
| if (hapd->wpa_auth) |
| ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id); |
| |
| + if (!ret && !vlan_exists) |
| + hostapd_ubus_add_vlan(hapd, vlan); |
| + |
| if (ret == 0) |
| return ret; |
| |
| @@ -77,6 +81,8 @@ int vlan_if_remove(struct hostapd_data * |
| "WPA deinitialization for VLAN %d failed (%d)", |
| vlan->vlan_id, ret); |
| |
| + hostapd_ubus_remove_vlan(hapd, vlan); |
| + |
| return hostapd_vlan_if_remove(hapd, vlan->ifname); |
| } |
| |
| --- a/src/ap/dfs.c |
| +++ b/src/ap/dfs.c |
| @@ -1216,6 +1216,8 @@ int hostapd_dfs_pre_cac_expired(struct h |
| "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", |
| freq, ht_enabled, chan_offset, chan_width, cf1, cf2); |
| |
| + hostapd_ubus_notify_radar_detected(iface, freq, chan_width, cf1, cf2); |
| + |
| /* 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 |
| { |
| struct sta_info *sta; |
| |
| - for (sta = hapd->sta_list; sta; sta = sta->next) |
| - sta_set_airtime_weight(hapd, sta, weight); |
| + for (sta = hapd->sta_list; sta; sta = sta->next) { |
| + unsigned int sta_weight = weight; |
| + |
| + if (sta->dyn_airtime_weight) |
| + sta_weight = (weight * sta->dyn_airtime_weight) / 256; |
| + |
| + sta_set_airtime_weight(hapd, sta, sta_weight); |
| + } |
| } |
| |
| |
| @@ -244,7 +250,10 @@ int airtime_policy_new_sta(struct hostap |
| unsigned int weight; |
| |
| if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) { |
| - weight = get_weight_for_sta(hapd, sta->addr); |
| + if (sta->dyn_airtime_weight) |
| + weight = sta->dyn_airtime_weight; |
| + else |
| + weight = get_weight_for_sta(hapd, sta->addr); |
| if (weight) |
| return sta_set_airtime_weight(hapd, sta, weight); |
| } |
| --- a/src/ap/sta_info.h |
| +++ b/src/ap/sta_info.h |
| @@ -322,6 +322,7 @@ struct sta_info { |
| #endif /* CONFIG_TESTING_OPTIONS */ |
| #ifdef CONFIG_AIRTIME_POLICY |
| unsigned int airtime_weight; |
| + unsigned int dyn_airtime_weight; |
| struct os_reltime backlogged_until; |
| #endif /* CONFIG_AIRTIME_POLICY */ |
| |
| --- a/src/ap/wnm_ap.c |
| +++ b/src/ap/wnm_ap.c |
| @@ -455,7 +455,8 @@ static void ieee802_11_rx_bss_trans_mgmt |
| MAC2STR(addr), reason, hex ? " neighbor=" : "", hex); |
| os_free(hex); |
| |
| - ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token); |
| + if (!hostapd_ubus_notify_bss_transition_query(hapd, addr, dialog_token, reason, pos, end - pos)) |
| + ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token); |
| } |
| |
| |
| @@ -477,7 +478,7 @@ static void ieee802_11_rx_bss_trans_mgmt |
| size_t len) |
| { |
| u8 dialog_token, status_code, bss_termination_delay; |
| - const u8 *pos, *end; |
| + const u8 *pos, *end, *target_bssid = NULL; |
| int enabled = hapd->conf->bss_transition; |
| struct sta_info *sta; |
| |
| @@ -524,6 +525,7 @@ static void ieee802_11_rx_bss_trans_mgmt |
| wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field"); |
| return; |
| } |
| + target_bssid = pos; |
| sta->agreed_to_steer = 1; |
| eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta); |
| eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer, |
| @@ -543,6 +545,10 @@ static void ieee802_11_rx_bss_trans_mgmt |
| MAC2STR(addr), status_code, bss_termination_delay); |
| } |
| |
| + hostapd_ubus_notify_bss_transition_response(hapd, sta->addr, dialog_token, |
| + status_code, bss_termination_delay, |
| + target_bssid, pos, end - pos); |
| + |
| wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", |
| pos, end - pos); |
| } |
| --- a/src/utils/eloop.c |
| +++ b/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 */ |
| @@ -1121,6 +1124,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) */ |
| @@ -1190,7 +1199,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, |
| @@ -1252,6 +1262,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) |
| { |
| --- a/src/utils/eloop.h |
| +++ b/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 |
| * |
| --- /dev/null |
| +++ b/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); |
| +} |