diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 07f92f1ea..580928433 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -421,9 +421,8 @@ void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info, } -static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx) +void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age) { - struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_bss *bss, *n; struct os_time t; @@ -431,7 +430,7 @@ static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx) return; os_get_time(&t); - t.sec -= WPA_BSS_EXPIRATION_AGE; + t.sec -= age; dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) { if (wpa_bss_in_use(wpa_s, bss)) @@ -444,6 +443,14 @@ static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx) } else break; } +} + + +static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + wpa_bss_flush_by_age(wpa_s, WPA_BSS_EXPIRATION_AGE); eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0, wpa_bss_timeout, wpa_s, NULL); } @@ -459,14 +466,25 @@ int wpa_bss_init(struct wpa_supplicant *wpa_s) } -void wpa_bss_deinit(struct wpa_supplicant *wpa_s) +void wpa_bss_flush(struct wpa_supplicant *wpa_s) { struct wpa_bss *bss, *n; - eloop_cancel_timeout(wpa_bss_timeout, wpa_s, NULL); + if (wpa_s->bss.next == NULL) return; /* BSS table not yet initialized */ - dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) + + dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) { + if (wpa_bss_in_use(wpa_s, bss)) + continue; wpa_bss_remove(wpa_s, bss); + } +} + + +void wpa_bss_deinit(struct wpa_supplicant *wpa_s) +{ + eloop_cancel_timeout(wpa_bss_timeout, wpa_s, NULL); + wpa_bss_flush(wpa_s); } diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 1de4722a6..992b9c03c 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -78,6 +78,8 @@ void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info, int new_scan); int wpa_bss_init(struct wpa_supplicant *wpa_s); void wpa_bss_deinit(struct wpa_supplicant *wpa_s); +void wpa_bss_flush(struct wpa_supplicant *wpa_s); +void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age); struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid, const u8 *ssid, size_t ssid_len); struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index f85fedfb4..d86552fad 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -1352,6 +1352,13 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { } }, #endif /* CONFIG_WPS */ + { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss, + { + { "age", "u", ARG_IN }, + END_ARGS + } + }, { NULL, NULL, NULL, { END_ARGS } } }; diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 02ace9b5e..b590d6216 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1684,6 +1684,30 @@ DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message, } +/* + * wpas_dbus_handler_flush_bss - Flush the BSS cache + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NULL + * + * Handler function for "FlushBSS" method call of network interface. + */ +DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + dbus_uint32_t age; + + dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age, + DBUS_TYPE_INVALID); + + if (age == 0) + wpa_bss_flush(wpa_s); + else + wpa_bss_flush_by_age(wpa_s, age); + + return NULL; +} + /** * wpas_dbus_getter_capabilities - Return interface capabilities diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index 119d15d76..dcac3520a 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -95,6 +95,9 @@ DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message, DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message, + struct wpa_supplicant *wpa_s); + DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message, struct wpa_supplicant *wpa_s); diff --git a/wpa_supplicant/dbus/dbus_old.c b/wpa_supplicant/dbus/dbus_old.c index 7f25bf03a..6a00f3e57 100644 --- a/wpa_supplicant/dbus/dbus_old.c +++ b/wpa_supplicant/dbus/dbus_old.c @@ -287,6 +287,8 @@ static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection, else if (!os_strcmp(method, "wpsReg")) reply = wpas_dbus_iface_wps_reg(message, wpa_s); #endif /* CONFIG_WPS */ + else if (!os_strcmp(method, "flush")) + reply = wpas_dbus_iface_flush(message, wpa_s); } /* If the message was handled, send back the reply */ diff --git a/wpa_supplicant/dbus/dbus_old_handlers.c b/wpa_supplicant/dbus/dbus_old_handlers.c index d914697d9..de6614077 100644 --- a/wpa_supplicant/dbus/dbus_old_handlers.c +++ b/wpa_supplicant/dbus/dbus_old_handlers.c @@ -1434,3 +1434,35 @@ DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, return wpas_dbus_new_success_reply(message); } + + +/** + * wpas_dbus_iface_flush - Clear BSS of old or all inactive entries + * @message: Pointer to incoming dbus message + * @wpa_s: %wpa_supplicant data structure + * Returns: a dbus message containing a UINT32 indicating success (1) or + * failure (0), or returns a dbus error message with more information + * + * Handler function for "flush" method call. Handles requests for an + * interface with an optional "age" parameter that specifies the minimum + * age of a BSS to be flushed. + */ +DBusMessage * wpas_dbus_iface_flush(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + int flush_age = 0; + + if (os_strlen(dbus_message_get_signature(message)) != 0 && + !dbus_message_get_args(message, NULL, + DBUS_TYPE_INT32, &flush_age, + DBUS_TYPE_INVALID)) { + return wpas_dbus_new_invalid_opts_error(message, NULL); + } + + if (flush_age == 0) + wpa_bss_flush(wpa_s); + else + wpa_bss_flush_by_age(wpa_s, flush_age); + + return wpas_dbus_new_success_reply(message); +} diff --git a/wpa_supplicant/dbus/dbus_old_handlers.h b/wpa_supplicant/dbus/dbus_old_handlers.h index 65e876f80..009e807e3 100644 --- a/wpa_supplicant/dbus/dbus_old_handlers.h +++ b/wpa_supplicant/dbus/dbus_old_handlers.h @@ -96,6 +96,9 @@ DBusMessage * wpas_dbus_iface_wps_pin(DBusMessage *message, DBusMessage * wpas_dbus_iface_wps_reg(DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_iface_flush(DBusMessage *message, + struct wpa_supplicant *wpa_s); + DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message); DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message, const char *arg);