[PATCH] supplicant: add dbus getter method for nl80211 iftype

Avinash Patil avinashapatil
Wed Nov 5 23:14:14 PST 2014


This patch adds dbus getter method for nl80211 iftype.
This is required by certain applications which intend to start
AP operations only if current interface type is AP.
Getter method for capabilities cannot be used for this purpose as
this enumarates all the supported interface types.

Patch also adds notification handlers for interface type change
events.

Reviewed-by: Dan Williams <dcbw at redhat.com>
Signed-off-by: Avinash Patil <avinashapatil at gmail.com>
---
 src/common/defs.h                       | 18 ++++++++++++
 src/drivers/driver.h                    | 12 ++++++++
 src/drivers/driver_nl80211.c            | 11 +++++++
 wpa_supplicant/dbus/dbus_new.c          | 16 ++++++++++
 wpa_supplicant/dbus/dbus_new.h          |  6 ++++
 wpa_supplicant/dbus/dbus_new_handlers.c | 38 ++++++++++++++++++++++++
 wpa_supplicant/dbus/dbus_new_handlers.h |  3 ++
 wpa_supplicant/driver_i.h               |  8 +++++
 wpa_supplicant/events.c                 | 11 ++++++-
 wpa_supplicant/notify.c                 |  6 ++++
 wpa_supplicant/notify.h                 |  1 +
 wpa_supplicant/p2p_supplicant.c         |  9 ++++++
 wpa_supplicant/wpa_supplicant.c         | 52 +++++++++++++++++++++++++++++++++
 wpa_supplicant/wpa_supplicant_i.h       |  1 +
 14 files changed, 191 insertions(+), 1 deletion(-)

diff --git a/src/common/defs.h b/src/common/defs.h
index bf992e0..8f51e3c 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -297,6 +297,24 @@ enum wpa_ctrl_req_type {
        NUM_WPA_CTRL_REQS
 };

+enum wpa_nl80211_iftype {
+       WPA_IFTYPE_UNSPECIFIED,
+       WPA_IFTYPE_ADHOC,
+       WPA_IFTYPE_STATION,
+       WPA_IFTYPE_AP,
+       WPA_IFTYPE_AP_VLAN,
+       WPA_IFTYPE_WDS,
+       WPA_IFTYPE_MONITOR,
+       WPA_IFTYPE_MESH_POINT,
+       WPA_IFTYPE_P2P_CLIENT,
+       WPA_IFTYPE_P2P_GO,
+       WPA_IFTYPE_P2P_DEVICE,
+
+       /* keep last */
+       WPA_NL80211_IFTYPES,
+       WPA_IFTYPE_MAX = WPA_NL80211_IFTYPES - 1
+};
+
 /* Maximum number of EAP methods to store for EAP server user information */
 #define EAP_MAX_METHODS 8

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 8420a56..a2a2331 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1427,6 +1427,18 @@ struct wpa_driver_ops {
        int (*get_ssid)(void *priv, u8 *ssid);

        /**
+        * get_iftype - Get the current NL80211 iftype
+        * @priv: private driver interface data
+        * @iftype: buffer for storing iftype
+        *
+        * Returns: 0 on success, -1 on failure
+        *
+        * Query kernel driver for the current NL80211 mode and copy it to
+        * iftype.
+        */
+       int (*get_iftype)(void *priv, u8 *iftype);
+
+       /**
         * set_key - Configure encryption key
         * @ifname: Interface name (for multi-SSID/VLAN support)
         * @priv: private driver interface data
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 68afcf0..0909ff2 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -737,6 +737,16 @@ static int wpa_driver_nl80211_get_bssid(void
*priv, u8 *bssid)
        return 0;
 }

+static int wpa_driver_nl80211_get_nl80211_iftype(void *priv, u8 *iftype)
+{
+       struct i802_bss *bss = priv;
+       if (!bss)
+               return -1;
+
+       *iftype = (u8)nl80211_get_ifmode(bss);
+
+       return 0;
+}

 static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
 {
@@ -9081,6 +9091,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .desc = "Linux nl80211/cfg80211",
        .get_bssid = wpa_driver_nl80211_get_bssid,
        .get_ssid = wpa_driver_nl80211_get_ssid,
+       .get_iftype = wpa_driver_nl80211_get_nl80211_iftype,
        .set_key = driver_nl80211_set_key,
        .scan2 = driver_nl80211_scan2,
        .sched_scan = wpa_driver_nl80211_sched_scan,
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index cbf9d32..966709d 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2037,6 +2037,18 @@ void
wpas_dbus_signal_debug_level_changed(struct wpa_global *global)


 /**
+ * wpas_dbus_signal_interface_type_changed - Signals change of interface type
+ * @global: wpa_global structure
+ *
+ * Sends PropertyChanged signals informing that debug level has changed.
+ */
+void wpas_dbus_signal_interface_type_changed(struct wpa_global *global)
+{
+       wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+                                      WPAS_DBUS_NEW_INTERFACE,
+                                      "IfType");
+}
+/**
  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
  * @global: wpa_global structure
  *
@@ -2956,6 +2968,10 @@ static const struct wpa_dbus_property_desc
wpas_dbus_interface_properties[] = {
          wpas_dbus_getter_driver,
          NULL
        },
+       { "IfType", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+         wpas_dbus_getter_iftype,
+         NULL
+       },
        { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_bridge_ifname,
          NULL
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 5f32bbf..dcb444f 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -164,6 +164,7 @@ void wpas_dbus_signal_blob_added(struct
wpa_supplicant *wpa_s,
 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
                                   const char *name);
 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global);
+void wpas_dbus_signal_interface_type_changed(struct wpa_global *global);
 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global);
 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global);

@@ -332,6 +333,11 @@ static inline void wpas_dbus_signal_debug_level_changed(
 {
 }

+static inline void wpas_dbus_signal_interface_type_changed(
+       struct wpa_global *global)
+{
+}
+
 static inline void wpas_dbus_signal_debug_timestamp_changed(
        struct wpa_global *global)
 {
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c
b/wpa_supplicant/dbus/dbus_new_handlers.c
index aaaf4f0..25a5c30 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -3166,6 +3166,44 @@ dbus_bool_t
wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
                                                &driver, error);
 }

+/**
+ * wpas_dbus_getter_current_mode -
+ * Get current NL mode
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "Current IF type" property.
+ */
+dbus_bool_t wpas_dbus_getter_iftype(DBusMessageIter *iter, DBusError *error,
+                                   void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       u8 iftype;
+       const char *char_iftype;
+
+       if (wpa_s->driver == NULL) {
+               wpa_printf(MSG_DEBUG, "wpas_dbus_getter_iftype[dbus]: "
+                          "wpa_s has no driver set");
+               dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
+                              __func__);
+               return FALSE;
+       }
+
+       if(wpa_drv_get_iftype(wpa_s, &iftype)) {
+               wpa_printf(MSG_DEBUG, "wpas_dbus_getter_iftype[dbus]: "
+                          "failed");
+               dbus_set_error(error, DBUS_ERROR_FAILED, "%s: failed",
+                              __func__);
+               return FALSE;
+       }
+       char_iftype =  wpa_supplicant_iftype_txt(iftype);
+
+       wpa_printf(MSG_DEBUG, "dbus: Get interface type: %s", char_iftype);
+       return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
+                                               &char_iftype, error);
+}

 /**
  * wpas_dbus_getter_current_bss - Get current bss object path
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h
b/wpa_supplicant/dbus/dbus_new_handlers.h
index f6a83cd..cd350f7 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -205,6 +205,9 @@ dbus_bool_t
wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
                                    void *user_data);

+dbus_bool_t wpas_dbus_getter_iftype(DBusMessageIter *iter, DBusError *error,
+                                   void *user_data);
+
 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
                                           DBusError *error,
                                           void *user_data);
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 18a5457..3e87c85 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -136,6 +136,14 @@ static inline int wpa_drv_get_ssid(struct
wpa_supplicant *wpa_s, u8 *ssid)
        return -1;
 }

+static inline int wpa_drv_get_iftype(struct wpa_supplicant *wpa_s, u8 *iftype)
+{
+       if (wpa_s->driver->get_iftype) {
+               return wpa_s->driver->get_iftype(wpa_s->drv_priv, iftype);
+       }
+       return -1;
+}
+
 static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s,
                                  enum wpa_alg alg, const u8 *addr,
                                  int key_idx, int set_tx,
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 6761c1a..3a075c8 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -182,9 +182,12 @@ void wpa_supplicant_stop_countermeasures(void
*eloop_ctx, void *sock_ctx)
 void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
 {
        int bssid_changed;
-
+       u8 old_iftype = 0, new_iftype = 0;
        wnm_bss_keep_alive_deinit(wpa_s);

+       if(wpa_drv_get_iftype(wpa_s, &old_iftype)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get old iftype!");
+       }
 #ifdef CONFIG_IBSS_RSN
        ibss_rsn_deinit(wpa_s->ibss_rsn);
        wpa_s->ibss_rsn = NULL;
@@ -227,6 +230,12 @@ void wpa_supplicant_mark_disassoc(struct
wpa_supplicant *wpa_s)
        wpa_s->current_ssid = NULL;
        eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
        wpa_s->key_mgmt = 0;
+
+       if(wpa_drv_get_iftype(wpa_s, &new_iftype)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get new iftype!");
+       }
+       if (new_iftype != old_iftype)
+               wpas_notify_interface_type_changed(wpa_s->global);
 }


diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index c8cfa47..66cc49c 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -471,6 +471,12 @@ void wpas_notify_debug_level_changed(struct
wpa_global *global)
 }


+void wpas_notify_interface_type_changed(struct wpa_global *global)
+{
+       wpas_dbus_signal_interface_type_changed(global);
+}
+
+
 void wpas_notify_debug_timestamp_changed(struct wpa_global *global)
 {
        wpas_dbus_signal_debug_timestamp_changed(global);
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 7feb530..41555c1 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -78,6 +78,7 @@ void wpas_notify_blob_removed(struct wpa_supplicant
*wpa_s, const char *name);
 void wpas_notify_debug_level_changed(struct wpa_global *global);
 void wpas_notify_debug_timestamp_changed(struct wpa_global *global);
 void wpas_notify_debug_show_keys_changed(struct wpa_global *global);
+void wpas_notify_interface_type_changed(struct wpa_global *global);
 void wpas_notify_suspend(struct wpa_global *global);
 void wpas_notify_resume(struct wpa_global *global);

diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index aac3a10..bf690b0 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -480,6 +480,7 @@ static int wpas_p2p_group_delete(struct
wpa_supplicant *wpa_s,
 {
        struct wpa_ssid *ssid;
        char *gtype;
+       u8 old_iftype = 0, new_iftype = 0;
        const char *reason;

        ssid = wpa_s->current_ssid;
@@ -528,6 +529,9 @@ static int wpas_p2p_group_delete(struct
wpa_supplicant *wpa_s,
                }
        }

+       if(wpa_drv_get_iftype(wpa_s, &old_iftype)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get old iftype!");
+       }
        if (wpa_s->cross_connect_in_use) {
                wpa_s->cross_connect_in_use = 0;
                wpa_msg_global(wpa_s->parent, MSG_INFO,
@@ -649,6 +653,11 @@ static int wpas_p2p_group_delete(struct
wpa_supplicant *wpa_s,
        else
                wpa_drv_deinit_p2p_cli(wpa_s);

+       if(wpa_drv_get_iftype(wpa_s, &new_iftype)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get new iftype!");
+       }
+       if (new_iftype != old_iftype)
+               wpas_notify_interface_type_changed(wpa_s->global);
        return 0;
 }

diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 5a4d8dc..f325a28 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -597,6 +597,39 @@ const char * wpa_supplicant_state_txt(enum
wpa_states state)
        }
 }

+/**
+ * wpa_supplicant_iftype_txt - Get the NL80211 iftype as a text string
+ * Returns: The iftype name as a printable text string
+ */
+const char * wpa_supplicant_iftype_txt(u8 iftype)
+{
+       switch (iftype) {
+       case WPA_IFTYPE_UNSPECIFIED:
+               return "UNSPECIFIED";
+       case WPA_IFTYPE_ADHOC:
+               return "ADHOC";
+       case WPA_IFTYPE_STATION:
+               return "STATION";
+       case WPA_IFTYPE_AP:
+               return "AP";
+       case WPA_IFTYPE_AP_VLAN:
+               return "AP_VLAN";
+       case WPA_IFTYPE_WDS:
+               return "WDS";
+       case WPA_IFTYPE_MONITOR:
+               return "MONITOR";
+       case WPA_IFTYPE_MESH_POINT:
+               return "MESH_POINT";
+       case WPA_IFTYPE_P2P_CLIENT:
+               return "P2P_CLIENT";
+       case WPA_IFTYPE_P2P_GO:
+               return "P2P_GO";
+       case WPA_IFTYPE_P2P_DEVICE:
+               return "P2P_DEVICE";
+       default:
+               return "UNKNOWN";
+       }
+}

 #ifdef CONFIG_BGSCAN

@@ -1579,6 +1612,7 @@ static void wpas_start_assoc_cb(struct
wpa_radio_work *work, int deinit)
        int wep_keys_set = 0;
        int assoc_failed = 0;
        struct wpa_ssid *old_ssid;
+       u8 old_iftype = 0, new_iftype = 0;
 #ifdef CONFIG_HT_OVERRIDES
        struct ieee80211_ht_capabilities htcaps;
        struct ieee80211_ht_capabilities htcaps_mask;
@@ -1587,6 +1621,9 @@ static void wpas_start_assoc_cb(struct
wpa_radio_work *work, int deinit)
        struct ieee80211_vht_capabilities vhtcaps;
        struct ieee80211_vht_capabilities vhtcaps_mask;
 #endif /* CONFIG_VHT_OVERRIDES */
+       if(wpa_drv_get_iftype(wpa_s, &old_iftype)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get old iftype!");
+       }

        if (deinit) {
                if (work->started) {
@@ -2077,6 +2114,11 @@ static void wpas_start_assoc_cb(struct
wpa_radio_work *work, int deinit)
        wpa_supplicant_initiate_eapol(wpa_s);
        if (old_ssid != wpa_s->current_ssid)
                wpas_notify_network_changed(wpa_s);
+       if(wpa_drv_get_iftype(wpa_s, &new_iftype)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get new iftype!");
+       }
+       if (new_iftype != old_iftype)
+               wpas_notify_interface_type_changed(wpa_s->global);
 }


@@ -2111,12 +2153,17 @@ void wpa_supplicant_deauthenticate(struct
wpa_supplicant *wpa_s,
        u8 *addr = NULL;
        union wpa_event_data event;
        int zero_addr = 0;
+       u8 old_iftype = 0, new_iftype = 0;

        wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
                " pending_bssid=" MACSTR " reason=%d state=%s",
                MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
                reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));

+       if(wpa_drv_get_iftype(wpa_s, &old_iftype)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get old iftype!");
+       }
+
        if (!is_zero_ether_addr(wpa_s->bssid))
                addr = wpa_s->bssid;
        else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
@@ -2147,6 +2194,11 @@ void wpa_supplicant_deauthenticate(struct
wpa_supplicant *wpa_s,
                if (zero_addr)
                        addr = NULL;
        }
+       if(wpa_drv_get_iftype(wpa_s, &new_iftype)) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get new iftype!");
+       }
+       if (new_iftype != old_iftype)
+               wpas_notify_interface_type_changed(wpa_s->global);

        wpa_supplicant_clear_connection(wpa_s, addr);
 }
diff --git a/wpa_supplicant/wpa_supplicant_i.h
b/wpa_supplicant/wpa_supplicant_i.h
index cadf724..2bccb30 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -903,6 +903,7 @@ int wpa_supplicant_set_wpa_none_key(struct
wpa_supplicant *wpa_s,
 int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s);

 const char * wpa_supplicant_state_txt(enum wpa_states state);
+const char * wpa_supplicant_iftype_txt(u8 iftype);
 int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
--
1.8.1.4



More information about the Hostap mailing list