From 158c6c746785104c090f2bb24001ea34903da708 Mon Sep 17 00:00:00 2001 From: Witold Sowa Date: Wed, 6 Jan 2010 20:03:01 +0200 Subject: [PATCH] dbus: Add BSS property change notifications --- wpa_supplicant/bss.c | 131 +++++++++++++++++++++++++++++++++ wpa_supplicant/dbus/dbus_new.c | 56 ++++++++++++++ wpa_supplicant/dbus/dbus_new.h | 20 +++++ wpa_supplicant/notify.c | 58 +++++++++++++++ wpa_supplicant/notify.h | 16 ++++ 5 files changed, 281 insertions(+) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index bd8d06195..e2846b7f4 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -52,6 +52,15 @@ */ #define WPA_BSS_EXPIRATION_SCAN_COUNT 2 +#define WPA_BSS_FREQ_CHANGED_FLAG BIT(0) +#define WPA_BSS_SIGNAL_CHANGED_FLAG BIT(1) +#define WPA_BSS_PRIVACY_CHANGED_FLAG BIT(2) +#define WPA_BSS_MODE_CHANGED_FLAG BIT(3) +#define WPA_BSS_WPAIE_CHANGED_FLAG BIT(4) +#define WPA_BSS_RSNIE_CHANGED_FLAG BIT(5) +#define WPA_BSS_WPS_CHANGED_FLAG BIT(6) +#define WPA_BSS_RATES_CHANGED_FLAG BIT(7) + static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { @@ -136,9 +145,129 @@ static void wpa_bss_add(struct wpa_supplicant *wpa_s, } +static int are_ies_equal(const struct wpa_bss *old, + const struct wpa_scan_res *new, u32 ie) +{ + const u8 *old_ie, *new_ie; + struct wpabuf *old_ie_buff = NULL; + struct wpabuf *new_ie_buff = NULL; + int new_ie_len, old_ie_len, ret, is_multi; + + switch (ie) { + case WPA_IE_VENDOR_TYPE: + old_ie = wpa_bss_get_vendor_ie(old, ie); + new_ie = wpa_scan_get_vendor_ie(new, ie); + is_multi = 0; + break; + case WPS_IE_VENDOR_TYPE: + old_ie_buff = wpa_bss_get_vendor_ie_multi(old, ie); + new_ie_buff = wpa_scan_get_vendor_ie_multi(new, ie); + is_multi = 1; + break; + case WLAN_EID_RSN: + case WLAN_EID_SUPP_RATES: + case WLAN_EID_EXT_SUPP_RATES: + old_ie = wpa_bss_get_ie(old, ie); + new_ie = wpa_scan_get_ie(new, ie); + is_multi = 0; + break; + default: + wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__); + return 0; + } + + if (is_multi) { + /* in case of multiple IEs stored in buffer */ + old_ie = old_ie_buff ? wpabuf_head_u8(old_ie_buff) : NULL; + new_ie = new_ie_buff ? wpabuf_head_u8(new_ie_buff) : NULL; + old_ie_len = old_ie_buff ? wpabuf_len(old_ie_buff) : 0; + new_ie_len = new_ie_buff ? wpabuf_len(new_ie_buff) : 0; + } else { + /* in case of single IE */ + old_ie_len = old_ie ? old_ie[1] + 2 : 0; + new_ie_len = new_ie ? new_ie[1] + 2 : 0; + } + + ret = (old_ie_len == new_ie_len && + os_memcmp(old_ie, new_ie, old_ie_len) == 0); + + wpabuf_free(old_ie_buff); + wpabuf_free(new_ie_buff); + + return ret; +} + + +static u32 wpa_bss_compare_res(const struct wpa_bss *old, + const struct wpa_scan_res *new) +{ + u32 changes = 0; + int caps_diff = old->caps ^ new->caps; + + if (old->freq != new->freq) + changes |= WPA_BSS_FREQ_CHANGED_FLAG; + + if (old->level != new->level) + changes |= WPA_BSS_SIGNAL_CHANGED_FLAG; + + if (caps_diff & IEEE80211_CAP_PRIVACY) + changes |= WPA_BSS_PRIVACY_CHANGED_FLAG; + + if (caps_diff & IEEE80211_CAP_IBSS) + changes |= WPA_BSS_MODE_CHANGED_FLAG; + + if (!are_ies_equal(old, new, WPA_IE_VENDOR_TYPE)) + changes |= WPA_BSS_WPAIE_CHANGED_FLAG; + + if (!are_ies_equal(old, new, WLAN_EID_RSN)) + changes |= WPA_BSS_RSNIE_CHANGED_FLAG; + + if (!are_ies_equal(old, new, WPS_IE_VENDOR_TYPE)) + changes |= WPA_BSS_WPS_CHANGED_FLAG; + + if (!are_ies_equal(old, new, WLAN_EID_SUPP_RATES) || + !are_ies_equal(old, new, WLAN_EID_EXT_SUPP_RATES)) + changes |= WPA_BSS_RATES_CHANGED_FLAG; + + return changes; +} + + +static void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes, + const struct wpa_bss *bss) +{ + if (changes & WPA_BSS_FREQ_CHANGED_FLAG) + wpas_notify_bss_freq_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_SIGNAL_CHANGED_FLAG) + wpas_notify_bss_signal_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_PRIVACY_CHANGED_FLAG) + wpas_notify_bss_privacy_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_MODE_CHANGED_FLAG) + wpas_notify_bss_mode_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_WPAIE_CHANGED_FLAG) + wpas_notify_bss_wpaie_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_RSNIE_CHANGED_FLAG) + wpas_notify_bss_rsnie_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_WPS_CHANGED_FLAG) + wpas_notify_bss_wps_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_RATES_CHANGED_FLAG) + wpas_notify_bss_rates_changed(wpa_s, bss->id); +} + + static void wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_scan_res *res) { + u32 changes; + + changes = wpa_bss_compare_res(bss, res); bss->scan_miss_count = 0; bss->last_update_idx = wpa_s->bss_update_idx; wpa_bss_copy_res(bss, res); @@ -160,6 +289,8 @@ static void wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, dl_list_add(prev, &bss->list_id); } dl_list_add_tail(&wpa_s->bss, &bss->list); + + notify_bss_changes(wpa_s, changes, bss); } diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 7cde1134d..05e693632 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -700,6 +700,62 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, } +/** + * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property + * @wpa_s: %wpa_supplicant network interface data + * @property: indicates which property has changed + * @id: unique BSS identifier + * + * Sends PropertyChanged signals with path, interface, and arguments depending + * on which property has changed. + */ +void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s, + enum wpas_dbus_bss_prop property, + unsigned int id) +{ + char path[WPAS_DBUS_OBJECT_PATH_MAX]; + char *prop; + + switch (property) { + case WPAS_DBUS_BSS_PROP_SIGNAL: + prop = "Signal"; + break; + case WPAS_DBUS_BSS_PROP_FREQ: + prop = "Frequency"; + break; + case WPAS_DBUS_BSS_PROP_MODE: + prop = "Mode"; + break; + case WPAS_DBUS_BSS_PROP_PRIVACY: + prop = "Privacy"; + break; + case WPAS_DBUS_BSS_PROP_RATES: + prop = "Rates"; + break; + case WPAS_DBUS_BSS_PROP_WPAIE: + prop = "WPAIE"; + break; + case WPAS_DBUS_BSS_PROP_RSNIE: + prop = "RSNIE"; + break; + case WPAS_DBUS_BSS_PROP_WPSIE: + prop = "WPSIE"; + break; + default: + wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", + __func__, property); + return; + } + + os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", + wpa_s->dbus_new_path, id); + + wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, + WPAS_DBUS_NEW_IFACE_BSSID, prop); +} + + /** * wpas_dbus_signal_debug_level_changed - Signals change of debug param * @global: wpa_global structure diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h index e20ab7654..cc8fc6e36 100644 --- a/wpa_supplicant/dbus/dbus_new.h +++ b/wpa_supplicant/dbus/dbus_new.h @@ -32,6 +32,17 @@ enum wpas_dbus_prop { WPAS_DBUS_PROP_CURRENT_NETWORK, }; +enum wpas_dbus_bss_prop { + WPAS_DBUS_BSS_PROP_SIGNAL, + WPAS_DBUS_BSS_PROP_FREQ, + WPAS_DBUS_BSS_PROP_MODE, + WPAS_DBUS_BSS_PROP_PRIVACY, + WPAS_DBUS_BSS_PROP_RATES, + WPAS_DBUS_BSS_PROP_WPAIE, + WPAS_DBUS_BSS_PROP_RSNIE, + WPAS_DBUS_BSS_PROP_WPSIE, +}; + #define WPAS_DBUS_OBJECT_PATH_MAX 150 #define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1" @@ -80,6 +91,9 @@ int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s); int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s); void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, enum wpas_dbus_prop property); +void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s, + enum wpas_dbus_bss_prop property, + unsigned int id); void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id); @@ -125,6 +139,12 @@ static inline void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, { } +static inline void wpas_dbus_bss_signal_prop_changed( + struct wpa_supplicant *wpa_s, enum wpas_dbus_bss_prop property, + unsigned int id) +{ +} + static inline void wpas_dbus_signal_network_enabled_changed( struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index 970ba9b4f..fff0e4e52 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -209,6 +209,64 @@ void wpas_notify_bss_removed(struct wpa_supplicant *wpa_s, } +void wpas_notify_bss_freq_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_FREQ, id); +} + + +void wpas_notify_bss_signal_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_SIGNAL, + id); +} + + +void wpas_notify_bss_privacy_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_PRIVACY, + id); +} + + +void wpas_notify_bss_mode_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_MODE, id); +} + + +void wpas_notify_bss_wpaie_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_WPAIE, id); +} + + +void wpas_notify_bss_rsnie_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_RSNIE, id); +} + + +void wpas_notify_bss_wps_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_WPSIE, id); +} + + +void wpas_notify_bss_rates_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_RATES, id); +} + + void wpas_notify_blob_added(struct wpa_supplicant *wpa_s, const char *name) { wpas_dbus_signal_blob_added(wpa_s, name); diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h index 4cdd2554e..878d70500 100644 --- a/wpa_supplicant/notify.h +++ b/wpa_supplicant/notify.h @@ -51,6 +51,22 @@ void wpas_notify_bss_added(struct wpa_supplicant *wpa_s, u8 bssid[], unsigned int id); void wpas_notify_bss_removed(struct wpa_supplicant *wpa_s, u8 bssid[], unsigned int id); +void wpas_notify_bss_freq_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_signal_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_privacy_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_mode_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_wpaie_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_rsnie_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_wps_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_rates_changed(struct wpa_supplicant *wpa_s, + unsigned int id); void wpas_notify_blob_added(struct wpa_supplicant *wpa_s, const char *name); void wpas_notify_blob_removed(struct wpa_supplicant *wpa_s, const char *name);