Add wpa_supplicant notification calls
[mech_eap.git] / wpa_supplicant / ctrl_iface_dbus_handlers.c
index 3c29804..458dbf7 100644 (file)
 #include "common.h"
 #include "config.h"
 #include "wpa_supplicant_i.h"
+#include "driver_i.h"
 #include "ctrl_iface_dbus.h"
 #include "ctrl_iface_dbus_handlers.h"
+#include "notify.h"
 #include "eap_peer/eap_methods.h"
 #include "dbus_dict_helpers.h"
 #include "ieee802_11_defs.h"
 #include "wpas_glue.h"
 #include "eapol_supp/eapol_supp_sm.h"
+#include "wps_supplicant.h"
 
+extern int wpa_debug_level;
+extern int wpa_debug_show_keys;
+extern int wpa_debug_timestamp;
 
 /**
  * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
@@ -277,6 +283,51 @@ out:
        return reply;
 }
 
+/**
+ * wpas_dbus_global_set_debugparams- Set the debug params
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global 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 "setDebugParams" method call. Handles requests
+ * by dbus clients for the object path of an specific network interface.
+ */
+DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message,
+                                              struct wpa_global *global)
+{
+       DBusMessage *reply = NULL;
+       int debug_level;
+       dbus_bool_t debug_timestamp;
+       dbus_bool_t debug_show_keys;
+
+       if (!dbus_message_get_args(message, NULL,
+                                  DBUS_TYPE_INT32, &debug_level,
+                                  DBUS_TYPE_BOOLEAN, &debug_timestamp,
+                                  DBUS_TYPE_BOOLEAN, &debug_show_keys,
+                                  DBUS_TYPE_INVALID)) {
+               reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+               goto out;
+       }
+
+       /* check for allowed debuglevels */
+       if (debug_level != MSG_MSGDUMP &&
+           debug_level != MSG_DEBUG &&
+           debug_level != MSG_INFO &&
+           debug_level != MSG_WARNING &&
+           debug_level != MSG_ERROR) {
+               reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+               goto out;
+       }
+
+       wpa_debug_level = debug_level;
+       wpa_debug_timestamp = debug_timestamp ? 1 : 0;
+       wpa_debug_show_keys = debug_show_keys ? 1 : 0;
+       reply = wpas_dbus_new_success_reply(message);
+
+out:
+       return reply;
+}
 
 /**
  * wpas_dbus_iface_scan - Request a wireless scan on an interface
@@ -436,11 +487,14 @@ DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
        if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
                                         res->caps))
                goto error;
-       if (!wpa_dbus_dict_append_int32(&iter_dict, "quality", res->qual))
+       if (!(res->flags & WPA_SCAN_QUAL_INVALID) &&
+           !wpa_dbus_dict_append_int32(&iter_dict, "quality", res->qual))
                goto error;
-       if (!wpa_dbus_dict_append_int32(&iter_dict, "noise", res->noise))
+       if (!(res->flags & WPA_SCAN_NOISE_INVALID) &&
+           !wpa_dbus_dict_append_int32(&iter_dict, "noise", res->noise))
                goto error;
-       if (!wpa_dbus_dict_append_int32(&iter_dict, "level", res->level))
+       if (!(res->flags & WPA_SCAN_LEVEL_INVALID) &&
+           !wpa_dbus_dict_append_int32(&iter_dict, "level", res->level))
                goto error;
        if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate",
                                        wpa_scan_get_max_rate(res) * 500000))
@@ -781,6 +835,7 @@ DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
                                               "a network on this interface.");
                goto out;
        }
+       wpas_notify_network_added(wpa_s, ssid);
        ssid->disabled = 1;
        wpa_config_set_network_defaults(ssid);
 
@@ -844,6 +899,8 @@ DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
                goto out;
        }
 
+       wpas_notify_network_removed(wpa_s, ssid);
+
        if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
                reply = dbus_message_new_error(message,
                                               WPAS_ERROR_REMOVE_NETWORK_ERROR,
@@ -1285,6 +1342,35 @@ DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
 
 
 /**
+ * wpas_dbus_iface_get_scanning - Get interface scanning state
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing whether the interface is scanning
+ *
+ * Handler function for "scanning" method call.
+ */
+DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
+                                          struct wpa_supplicant *wpa_s)
+{
+       DBusMessage *reply = NULL;
+       dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
+
+       reply = dbus_message_new_method_return(message);
+       if (reply != NULL) {
+               dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning,
+                                        DBUS_TYPE_INVALID);
+       } else {
+               perror("wpas_dbus_iface_get_scanning[dbus]: out of "
+                      "memory.");
+               wpa_printf(MSG_ERROR, "dbus control interface: not enough "
+                          "memory to return scanning state.");
+       }
+
+       return reply;
+}
+
+
+/**
  * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates)
  * @message: Pointer to incoming dbus message
  * @wpa_s: %wpa_supplicant data structure
@@ -1357,8 +1443,11 @@ DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message,
                }
 
                /* Success */
-               wpa_config_remove_blob(wpa_s->conf, blob->name);
+               if (!wpa_config_remove_blob(wpa_s->conf, blob->name))
+                       wpas_notify_blob_removed(wpa_s, blob->name);
                wpa_config_set_blob(wpa_s->conf, blob);
+               wpas_notify_blob_added(wpa_s, blob->name);
+
                wpa_dbus_dict_entry_clear(&entry);
        }
        wpa_dbus_dict_entry_clear(&entry);
@@ -1398,6 +1487,8 @@ DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
 
                if (wpa_config_remove_blob(wpa_s->conf, name) != 0)
                        err_msg = "Error removing blob.";
+               else
+                       wpas_notify_blob_removed(wpa_s, name);
                dbus_message_iter_next(&array);
        }
 
@@ -1408,3 +1499,146 @@ DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
 
        return wpas_dbus_new_success_reply(message);
 }
+
+
+#ifdef CONFIG_WPS
+
+/**
+ * wpas_dbus_iface_wps_pbc - Request credentials using WPS PBC method
+ * @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)
+ *
+ * Handler function for "wpsPbc" method call
+ */
+DBusMessage * wpas_dbus_iface_wps_pbc(DBusMessage *message,
+                                     struct wpa_supplicant *wpa_s)
+{
+       char *arg_bssid = NULL;
+       u8 bssid[ETH_ALEN];
+       int ret = 0;
+
+       if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
+                                  DBUS_TYPE_INVALID))
+               return wpas_dbus_new_invalid_opts_error(message, NULL);
+
+       if (!os_strcmp(arg_bssid, "any"))
+               ret = wpas_wps_start_pbc(wpa_s, NULL);
+       else if (!hwaddr_aton(arg_bssid, bssid))
+               ret = wpas_wps_start_pbc(wpa_s, bssid);
+       else {
+               return wpas_dbus_new_invalid_opts_error(message,
+                                                       "Invalid BSSID");
+       }
+
+       if (ret < 0) {
+               return dbus_message_new_error(message,
+                                             WPAS_ERROR_WPS_PBC_ERROR,
+                                             "Could not start PBC "
+                                             "negotiation");
+       }
+
+       return wpas_dbus_new_success_reply(message);
+}
+
+
+/**
+ * wpas_dbus_iface_wps_pin - Establish the PIN number of the enrollee
+ * @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)
+ *
+ * Handler function for "wpsPin" method call
+ */
+DBusMessage * wpas_dbus_iface_wps_pin(DBusMessage *message,
+                                     struct wpa_supplicant *wpa_s)
+{
+       DBusMessage *reply = NULL;
+       char *arg_bssid;
+       char *pin = NULL;
+       u8 bssid[ETH_ALEN], *_bssid = NULL;
+       int ret = 0;
+
+       if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
+                                  DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID))
+               return wpas_dbus_new_invalid_opts_error(message, NULL);
+
+       if (!os_strcmp(arg_bssid, "any"))
+               _bssid = NULL;
+       else if (!hwaddr_aton(arg_bssid, bssid))
+               _bssid = bssid;
+       else {
+               return wpas_dbus_new_invalid_opts_error(message,
+                                                       "Invalid BSSID");
+       }
+
+       if (os_strlen(pin) > 0)
+               ret = wpas_wps_start_pin(wpa_s, _bssid, pin);
+       else
+               ret = wpas_wps_start_pin(wpa_s, _bssid, NULL);
+
+       if (ret < 0) {
+               return dbus_message_new_error(message,
+                                             WPAS_ERROR_WPS_PIN_ERROR,
+                                             "Could not init PIN");
+       }
+
+       reply = dbus_message_new_method_return(message);
+       if (reply == NULL)
+               return NULL;
+
+       if (ret == 0) {
+               dbus_message_append_args(reply, DBUS_TYPE_STRING, &pin,
+                                        DBUS_TYPE_INVALID);
+       } else {
+               char npin[9];
+               sprintf(npin, "%08d", ret);
+               dbus_message_append_args(reply, DBUS_TYPE_STRING, &npin,
+                                        DBUS_TYPE_INVALID);
+       }
+       return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_wps_reg - Request credentials using the PIN of the AP
+ * @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)
+ *
+ * Handler function for "wpsReg" method call
+ */
+DBusMessage * wpas_dbus_iface_wps_reg(DBusMessage *message,
+                                     struct wpa_supplicant *wpa_s)
+{
+       char *arg_bssid;
+       char *pin = NULL;
+       u8 bssid[ETH_ALEN];
+       int ret = 0;
+
+       if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
+                                  DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID))
+               return wpas_dbus_new_invalid_opts_error(message, NULL);
+
+       if (!os_strcmp(arg_bssid, "any"))
+               ret = wpas_wps_start_reg(wpa_s, NULL, pin, NULL);
+       else if (!hwaddr_aton(arg_bssid, bssid))
+               ret = wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
+       else {
+               return wpas_dbus_new_invalid_opts_error(message,
+                                                       "Invalid BSSID");
+       }
+
+       if (ret < 0) {
+               return dbus_message_new_error(message,
+                                             WPAS_ERROR_WPS_PBC_ERROR,
+                                             "Could not request credentials");
+       }
+
+       return wpas_dbus_new_success_reply(message);
+}
+
+#endif /* CONFIG_WPS */