[PATCH] dbus: add BSS changes notifications

Jouni Malinen j at w1.fi
Tue Jan 5 18:35:20 EST 2010


On Tue, Jan 05, 2010 at 11:36:42PM +0100, Witold Sowa wrote:
> > This call happens before the BSS entry is updated. This sounds a bit
> > racy, i.e., none of the notification handlers would be able to fetch the
> > new data from the BSS entry when processing the notification. That may
> > work with the current D-Bus code due to the aggregation of signals, but
> > it would not work some other things that I would expect to be using the
> > notify.c callbacks. In other words, this should most likely do the
> > comparison first (and say, store a bitfield of changed values) and then
> > call the notification functions only after having updated the BSS entry.
> > 
> Agreed. I didn't take under consideration the fact that DBus won't be
> the only beneficent of notifications callbacks forever.
> 
> Do you want me to resend the patch corrected?

Yes, please. I started cleaning up some things while reviewing the
changes (the version I ended up with is included below; there was the ie
copy-paste thing and a small typo in a comment somewhere if I remember
correctly), but I did not yet do anything to move the notification call
(but I do have a to-do item to handle RSN pre-authentication updates
from that new RSN IE changed notifications once it gets called with the
BSS entry updated ;-).



diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index bd8d061..a2e3faf 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -136,9 +136,74 @@ 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;
+	int new_ie_len, old_ie_len;
+
+	switch (ie) {
+	case WPA_IE_VENDOR_TYPE:
+	case WPS_IE_VENDOR_TYPE:
+		old_ie = wpa_bss_get_vendor_ie(old, ie);
+		new_ie = wpa_scan_get_vendor_ie(new, ie);
+		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);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__);
+		return 0;
+	}
+
+	old_ie_len = old_ie ? old_ie[1] + 2 : 0;
+	new_ie_len = new_ie ? new_ie[1] + 2 : 0;
+
+	return old_ie_len == new_ie_len &&
+		os_memcmp(old_ie, new_ie, old_ie_len) == 0;
+}
+
+
+static void notify_bss_changes(struct wpa_supplicant *wpa_s,
+			       const struct wpa_bss *old,
+			       const struct wpa_scan_res *new)
+{
+	int caps = old->caps ^ new->caps;
+
+	if (old->freq != new->freq)
+		wpas_notify_bss_freq_changed(wpa_s, old->id);
+
+	if (old->level != new->level)
+		wpas_notify_bss_signal_changed(wpa_s, old->id);
+
+	if (caps & IEEE80211_CAP_PRIVACY)
+		wpas_notify_bss_privacy_changed(wpa_s, old->id);
+	if (caps & IEEE80211_CAP_IBSS)
+		wpas_notify_bss_mode_changed(wpa_s, old->id);
+
+	if (!are_ies_equal(old, new, WPA_IE_VENDOR_TYPE))
+		wpas_notify_bss_wpaie_changed(wpa_s, old->id);
+
+	if (!are_ies_equal(old, new, WLAN_EID_RSN))
+		wpas_notify_bss_rsnie_changed(wpa_s, old->id);
+
+	if (!are_ies_equal(old, new, WPS_IE_VENDOR_TYPE))
+		wpas_notify_bss_wpsie_changed(wpa_s, old->id);
+
+	if (!are_ies_equal(old, new, WLAN_EID_SUPP_RATES) ||
+	    !are_ies_equal(old, new, WLAN_EID_EXT_SUPP_RATES))
+		wpas_notify_bss_rates_changed(wpa_s, old->id);
+}
+
+
 static void wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 			   struct wpa_scan_res *res)
 {
+	notify_bss_changes(wpa_s, bss, res);
+
 	bss->scan_miss_count = 0;
 	bss->last_update_idx = wpa_s->bss_update_idx;
 	wpa_bss_copy_res(bss, res);
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 9fc496d..f43a280 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -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
  *
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index e20ab76..d00ae64 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);
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 970ba9b..1ec199b 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_wpsie_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 4cdd255..868a435 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_wpsie_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);
 

-- 
Jouni Malinen                                            PGP id EFC895FA


More information about the HostAP mailing list