* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "../config.h"
#include "../wpa_supplicant_i.h"
#include "../wps_supplicant.h"
+#include "../driver_i.h"
+#include "../ap.h"
#include "dbus_new_helpers.h"
#include "dbus_new.h"
#include "dbus_new_handlers.h"
#include "dbus_dict_helpers.h"
+
+struct wps_start_params {
+ int role; /* 0 - not set, 1 - enrollee, 2 - registrar */
+ int type; /* 0 - not set, 1 - pin, 2 - pbc */
+ u8 *bssid;
+ char *pin;
+ u8 *p2p_dev_addr;
+};
+
+
+static int wpas_dbus_handler_wps_role(DBusMessage *message,
+ DBusMessageIter *entry_iter,
+ struct wps_start_params *params,
+ DBusMessage **reply)
+{
+ DBusMessageIter variant_iter;
+ char *val;
+
+ dbus_message_iter_recurse(entry_iter, &variant_iter);
+ if (dbus_message_iter_get_arg_type(&variant_iter) !=
+ DBUS_TYPE_STRING) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start - Wrong Role type, string required");
+ *reply = wpas_dbus_error_invalid_args(message,
+ "Role must be a string");
+ return -1;
+ }
+ dbus_message_iter_get_basic(&variant_iter, &val);
+ if (os_strcmp(val, "enrollee") == 0)
+ params->role = 1;
+ else if (os_strcmp(val, "registrar") == 0)
+ params->role = 2;
+ else {
+ wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown role %s", val);
+ *reply = wpas_dbus_error_invalid_args(message, val);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int wpas_dbus_handler_wps_type(DBusMessage *message,
+ DBusMessageIter *entry_iter,
+ struct wps_start_params *params,
+ DBusMessage **reply)
+{
+ DBusMessageIter variant_iter;
+ char *val;
+
+ dbus_message_iter_recurse(entry_iter, &variant_iter);
+ if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_STRING) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start - Wrong Type type, string required");
+ *reply = wpas_dbus_error_invalid_args(message,
+ "Type must be a string");
+ return -1;
+ }
+ dbus_message_iter_get_basic(&variant_iter, &val);
+ if (os_strcmp(val, "pin") == 0)
+ params->type = 1;
+ else if (os_strcmp(val, "pbc") == 0)
+ params->type = 2;
+ else {
+ wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown type %s",
+ val);
+ *reply = wpas_dbus_error_invalid_args(message, val);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int wpas_dbus_handler_wps_bssid(DBusMessage *message,
+ DBusMessageIter *entry_iter,
+ struct wps_start_params *params,
+ DBusMessage **reply)
+{
+ DBusMessageIter variant_iter, array_iter;
+ int len;
+
+ dbus_message_iter_recurse(entry_iter, &variant_iter);
+ if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&variant_iter) !=
+ DBUS_TYPE_BYTE) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start - Wrong Bssid type, byte array required");
+ *reply = wpas_dbus_error_invalid_args(
+ message, "Bssid must be a byte array");
+ return -1;
+ }
+ dbus_message_iter_recurse(&variant_iter, &array_iter);
+ dbus_message_iter_get_fixed_array(&array_iter, ¶ms->bssid, &len);
+ if (len != ETH_ALEN) {
+ wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Bssid length %d",
+ len);
+ *reply = wpas_dbus_error_invalid_args(message,
+ "Bssid is wrong length");
+ return -1;
+ }
+ return 0;
+}
+
+
+static int wpas_dbus_handler_wps_pin(DBusMessage *message,
+ DBusMessageIter *entry_iter,
+ struct wps_start_params *params,
+ DBusMessage **reply)
+{
+ DBusMessageIter variant_iter;
+
+ dbus_message_iter_recurse(entry_iter, &variant_iter);
+ if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_STRING) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start - Wrong Pin type, string required");
+ *reply = wpas_dbus_error_invalid_args(message,
+ "Pin must be a string");
+ return -1;
+ }
+ dbus_message_iter_get_basic(&variant_iter, ¶ms->pin);
+ return 0;
+}
+
+
+#ifdef CONFIG_P2P
+static int wpas_dbus_handler_wps_p2p_dev_addr(DBusMessage *message,
+ DBusMessageIter *entry_iter,
+ struct wps_start_params *params,
+ DBusMessage **reply)
+{
+ DBusMessageIter variant_iter, array_iter;
+ int len;
+
+ dbus_message_iter_recurse(entry_iter, &variant_iter);
+ if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&variant_iter) !=
+ DBUS_TYPE_BYTE) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start - Wrong P2PDeviceAddress type, byte array required");
+ *reply = wpas_dbus_error_invalid_args(
+ message, "P2PDeviceAddress must be a byte array");
+ return -1;
+ }
+ dbus_message_iter_recurse(&variant_iter, &array_iter);
+ dbus_message_iter_get_fixed_array(&array_iter, ¶ms->p2p_dev_addr,
+ &len);
+ if (len != ETH_ALEN) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start - Wrong P2PDeviceAddress length %d",
+ len);
+ *reply = wpas_dbus_error_invalid_args(
+ message, "P2PDeviceAddress has wrong length");
+ return -1;
+ }
+ return 0;
+}
+#endif /* CONFIG_P2P */
+
+
+static int wpas_dbus_handler_wps_start_entry(DBusMessage *message, char *key,
+ DBusMessageIter *entry_iter,
+ struct wps_start_params *params,
+ DBusMessage **reply)
+{
+ if (os_strcmp(key, "Role") == 0)
+ return wpas_dbus_handler_wps_role(message, entry_iter,
+ params, reply);
+ else if (os_strcmp(key, "Type") == 0)
+ return wpas_dbus_handler_wps_type(message, entry_iter,
+ params, reply);
+ else if (os_strcmp(key, "Bssid") == 0)
+ return wpas_dbus_handler_wps_bssid(message, entry_iter,
+ params, reply);
+ else if (os_strcmp(key, "Pin") == 0)
+ return wpas_dbus_handler_wps_pin(message, entry_iter,
+ params, reply);
+#ifdef CONFIG_P2P
+ else if (os_strcmp(key, "P2PDeviceAddress") == 0)
+ return wpas_dbus_handler_wps_p2p_dev_addr(message, entry_iter,
+ params, reply);
+#endif /* CONFIG_P2P */
+
+ wpa_printf(MSG_DEBUG, "dbus: WPS.Start - unknown key %s", key);
+ *reply = wpas_dbus_error_invalid_args(message, key);
+ return -1;
+}
+
+
/**
* wpas_dbus_handler_wps_start - Start WPS configuration
* @message: Pointer to incoming dbus message
DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
struct wpa_supplicant *wpa_s)
{
- DBusMessage * reply = NULL;
- DBusMessageIter iter, dict_iter, entry_iter, variant_iter, array_iter;
-
- char *key, *val;
-
- int role = 0; /* 0 - not set, 1 - enrollee, 2 - registrar */
- int type = 0; /* 0 - not set, 1 - pin, 2 - pbc */
- u8 *bssid = NULL;
- char *pin = NULL, npin[9] = { '\0' };
- int len, ret;
+ DBusMessage *reply = NULL;
+ DBusMessageIter iter, dict_iter, entry_iter;
+ struct wps_start_params params;
+ char *key;
+ char npin[9] = { '\0' };
+ int ret;
+ os_memset(¶ms, 0, sizeof(params));
dbus_message_iter_init(message, &iter);
dbus_message_iter_recurse(&iter, &dict_iter);
dbus_message_iter_get_basic(&entry_iter, &key);
dbus_message_iter_next(&entry_iter);
- if (os_strcmp(key, "Role") == 0) {
- dbus_message_iter_recurse(&entry_iter, &variant_iter);
- if (dbus_message_iter_get_arg_type(&variant_iter) !=
- DBUS_TYPE_STRING) {
- wpa_printf(MSG_DEBUG,
- "wpas_dbus_handler_wps_start"
- "[dbus]: "
- "wrong Role type. string required");
- return wpas_dbus_error_invald_args(
- message, "Role must be a string");
- }
- dbus_message_iter_get_basic(&variant_iter, &val);
- if (os_strcmp(val, "enrollee") == 0)
- role = 1;
- else if (os_strcmp(val, "registrar") == 0)
- role = 2;
- else {
- wpa_printf(MSG_DEBUG,
- "wpas_dbus_handler_wps_start[dbus]: "
- "unknown role %s", val);
- return wpas_dbus_error_invald_args(message,
- val);
- }
- } else if (strcmp(key, "Type") == 0) {
- dbus_message_iter_recurse(&entry_iter, &variant_iter);
- if (dbus_message_iter_get_arg_type(&variant_iter) !=
- DBUS_TYPE_STRING) {
- wpa_printf(MSG_DEBUG,
- "wpas_dbus_handler_wps_start[dbus]: "
- "wrong Type type. string required");
- return wpas_dbus_error_invald_args(
- message, "Type must be a string");
- }
- dbus_message_iter_get_basic(&variant_iter, &val);
- if (os_strcmp(val, "pin") == 0)
- type = 1;
- else if (os_strcmp(val, "pbc") == 0)
- type = 2;
- else {
- wpa_printf(MSG_DEBUG,
- "wpas_dbus_handler_wps_start[dbus]: "
- "unknown type %s", val);
- return wpas_dbus_error_invald_args(message,
- val);
- }
- } else if (strcmp(key, "Bssid") == 0) {
- dbus_message_iter_recurse(&entry_iter, &variant_iter);
- if (dbus_message_iter_get_arg_type(&variant_iter) !=
- DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&variant_iter) !=
- DBUS_TYPE_ARRAY) {
- wpa_printf(MSG_DEBUG,
- "wpas_dbus_handler_wps_start[dbus]: "
- "wrong Bssid type. byte array required");
- return wpas_dbus_error_invald_args(
- message, "Bssid must be a byte array");
- }
- dbus_message_iter_recurse(&variant_iter, &array_iter);
- dbus_message_iter_get_fixed_array(&array_iter, &bssid,
- &len);
- if (len != ETH_ALEN) {
- wpa_printf(MSG_DEBUG,
- "wpas_dbus_handler_wps_start[dbus]: "
- "wrong Bssid length %d", len);
- return wpas_dbus_error_invald_args(
- message, "Bssid is wrong length");
- }
- }
- else if (os_strcmp(key, "Pin") == 0) {
- dbus_message_iter_recurse(&entry_iter, &variant_iter);
- if (dbus_message_iter_get_arg_type(&variant_iter) !=
- DBUS_TYPE_STRING) {
- wpa_printf(MSG_DEBUG,
- "wpas_dbus_handler_wps_start[dbus]: "
- "wrong Pin type. string required");
- return wpas_dbus_error_invald_args(
- message, "Pin must be a string");
- }
- dbus_message_iter_get_basic(&variant_iter, &pin);
- } else {
- wpa_printf(MSG_DEBUG,
- "wpas_dbus_handler_wps_start[dbus]: "
- "unknown key %s", key);
- return wpas_dbus_error_invald_args(message, key);
- }
+ if (wpas_dbus_handler_wps_start_entry(message, key,
+ &entry_iter,
+ ¶ms, &reply))
+ return reply;
dbus_message_iter_next(&dict_iter);
}
- if (role == 0) {
- wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
- "Role not specified");
- return wpas_dbus_error_invald_args(message,
- "Role not specified");
- }
- else if (role == 1 && type == 0) {
- wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
- "Type not specified");
- return wpas_dbus_error_invald_args(message,
- "Type not specified");
- }
- else if (role == 2 && pin == NULL) {
- wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
- "Pin required for registrar role.");
- return wpas_dbus_error_invald_args(
- message, "Pin required for registrar role.");
- }
-
- if (role == 2)
- ret = wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
- else if (type == 1) {
- ret = wpas_wps_start_pin(wpa_s, bssid, pin);
+#ifdef CONFIG_AP
+ if (wpa_s->ap_iface && params.type == 1) {
+ if (params.pin == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start - Pin required for registrar role");
+ return wpas_dbus_error_invalid_args(
+ message, "Pin required for registrar role.");
+ }
+ ret = wpa_supplicant_ap_wps_pin(wpa_s,
+ params.bssid,
+ params.pin,
+ npin, sizeof(npin), 0);
+ } else if (wpa_s->ap_iface) {
+ ret = wpa_supplicant_ap_wps_pbc(wpa_s,
+ params.bssid,
+ params.p2p_dev_addr);
+ } else
+#endif /* CONFIG_AP */
+ if (params.role == 0) {
+ wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Role not specified");
+ return wpas_dbus_error_invalid_args(message,
+ "Role not specified");
+ } else if (params.role == 2) {
+ if (params.pin == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start - Pin required for registrar role");
+ return wpas_dbus_error_invalid_args(
+ message, "Pin required for registrar role.");
+ }
+ ret = wpas_wps_start_reg(wpa_s, params.bssid, params.pin,
+ NULL);
+ } else if (params.type == 0) {
+ wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Type not specified");
+ return wpas_dbus_error_invalid_args(message,
+ "Type not specified");
+ } else if (params.type == 1) {
+ ret = wpas_wps_start_pin(wpa_s, params.bssid,
+ params.pin, 0,
+ DEV_PW_DEFAULT);
if (ret > 0)
os_snprintf(npin, sizeof(npin), "%08d", ret);
- } else
- ret = wpas_wps_start_pbc(wpa_s, bssid);
+ } else {
+ ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0);
+ }
if (ret < 0) {
- wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
- "wpas_wps_failed in role %s and key %s.",
- (role == 1 ? "enrollee" : "registrar"),
- (type == 0 ? "" : (type == 1 ? "pin" : "pbc")));
+ wpa_printf(MSG_DEBUG,
+ "dbus: WPS.Start wpas_wps_failed in role %s and key %s",
+ (params.role == 1 ? "enrollee" : "registrar"),
+ (params.type == 0 ? "" :
+ (params.type == 1 ? "pin" : "pbc")));
return wpas_dbus_error_unknown_error(message,
- "wps start failed");
+ "WPS start failed");
}
reply = dbus_message_new_method_return(message);
- if (!reply) {
- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
- NULL);
- }
+ if (!reply)
+ return wpas_dbus_error_no_memory(message);
dbus_message_iter_init_append(reply, &iter);
- if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
+ if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+ (os_strlen(npin) > 0 &&
+ !wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) ||
+ !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
dbus_message_unref(reply);
- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
- NULL);
+ return wpas_dbus_error_no_memory(message);
}
- if (os_strlen(npin) > 0) {
- if (!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) {
- dbus_message_unref(reply);
- return dbus_message_new_error(message,
- DBUS_ERROR_NO_MEMORY,
- NULL);
- }
- }
+ return reply;
+}
- if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
- dbus_message_unref(reply);
- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
- NULL);
- }
- return reply;
+/**
+ * wpas_dbus_handler_wps_cancel - Cancel ongoing WPS configuration
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: NULL on success or DBus error on failure
+ *
+ * Handler for "Cancel" method call. Returns NULL if WPS cancel successfull
+ * or DBus error on WPS cancel failure
+ */
+DBusMessage * wpas_dbus_handler_wps_cancel(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ if (wpas_wps_cancel(wpa_s))
+ return wpas_dbus_error_unknown_error(message,
+ "WPS cancel failed");
+
+ return NULL;
}
* wpas_dbus_getter_process_credentials - Check if credentials are processed
* @message: Pointer to incoming dbus message
* @wpa_s: %wpa_supplicant data structure
- * Returns: DBus message with a boolean on success or DBus error on failure
+ * Returns: TRUE on success, FALSE on failure
*
* Getter for "ProcessCredentials" property. Returns returned boolean will be
* true if wps_cred_processing configuration field is not equal to 1 or false
* if otherwise.
*/
-DBusMessage * wpas_dbus_getter_process_credentials(
- DBusMessage *message, struct wpa_supplicant *wpa_s)
+dbus_bool_t wpas_dbus_getter_process_credentials(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
- dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1);
- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
- &process);
+ struct wpa_supplicant *wpa_s = user_data;
+ dbus_bool_t process = wpa_s->conf->wps_cred_processing != 1;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
+ &process, error);
}
/**
* wpas_dbus_setter_process_credentials - Set credentials_processed conf param
- * @message: Pointer to incoming dbus message
- * @wpa_s: %wpa_supplicant data structure
- * Returns: NULL on success or DBus error on failure
+ * @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
*
* Setter for "ProcessCredentials" property. Sets credentials_processed on 2
* if boolean argument is true or on 1 if otherwise.
*/
-DBusMessage * wpas_dbus_setter_process_credentials(
- DBusMessage *message, struct wpa_supplicant *wpa_s)
+dbus_bool_t wpas_dbus_setter_process_credentials(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
- DBusMessage *reply = NULL;
+ struct wpa_supplicant *wpa_s = user_data;
dbus_bool_t process_credentials, old_pc;
- reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
- &process_credentials);
- if (reply)
- return reply;
+ if (!wpa_s->dbus_new_path)
+ return FALSE;
+ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
+ &process_credentials))
+ return FALSE;
- old_pc = (wpa_s->conf->wps_cred_processing != 1);
+ old_pc = wpa_s->conf->wps_cred_processing != 1;
wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
- wpa_dbus_signal_property_changed(
- wpa_s->global->dbus,
- (WPADBusPropertyAccessor)
- wpas_dbus_getter_process_credentials,
- wpa_s, wpa_s->dbus_new_path,
- WPAS_DBUS_NEW_IFACE_WPS,
- "ProcessCredentials");
+ wpa_dbus_mark_property_changed(wpa_s->global->dbus,
+ wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_WPS,
+ "ProcessCredentials");
- return NULL;
+ return TRUE;
+}
+
+
+/**
+ * wpas_dbus_getter_config_methods - Get current WPS configuration methods
+ * @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 "ConfigMethods" property. Returned boolean will be true if
+ * providing the relevant string worked, or false otherwise.
+ */
+dbus_bool_t wpas_dbus_getter_config_methods(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ char *methods = wpa_s->conf->config_methods;
+
+ if (methods == NULL)
+ methods = "";
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
+ &methods, error);
+}
+
+
+/**
+ * wpas_dbus_setter_config_methods - Set WPS configuration methods
+ * @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
+ *
+ * Setter for "ConfigMethods" property. Sets the methods string, apply such
+ * change and returns true on success. Returns false otherwise.
+ */
+dbus_bool_t wpas_dbus_setter_config_methods(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ char *methods, *new_methods;
+
+ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+ &methods))
+ return FALSE;
+
+ new_methods = os_strdup(methods);
+ if (!new_methods)
+ return FALSE;
+
+ os_free(wpa_s->conf->config_methods);
+ wpa_s->conf->config_methods = new_methods;
+
+ wpa_s->conf->changed_parameters |= CFG_CHANGED_CONFIG_METHODS;
+ wpa_supplicant_update_config(wpa_s);
+
+ return TRUE;
}