dbus: Add BSS property change notifications
authorWitold Sowa <witold.sowa@gmail.com>
Wed, 6 Jan 2010 18:03:01 +0000 (20:03 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 6 Jan 2010 18:03:01 +0000 (20:03 +0200)
wpa_supplicant/bss.c
wpa_supplicant/dbus/dbus_new.c
wpa_supplicant/dbus/dbus_new.h
wpa_supplicant/notify.c
wpa_supplicant/notify.h

index bd8d061..e2846b7 100644 (file)
  */
 #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);
 }
 
 
index 7cde113..05e6936 100644 (file)
@@ -701,6 +701,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
  *
index e20ab76..cc8fc6e 100644 (file)
@@ -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)
 {
index 970ba9b..fff0e4e 100644 (file)
@@ -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);
index 4cdd255..878d705 100644 (file)
@@ -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);