dbus_old_handlers.c revision 214501
1214501Srpaulo/* 2214501Srpaulo * WPA Supplicant / dbus-based control interface 3214501Srpaulo * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 4214501Srpaulo * 5214501Srpaulo * This program is free software; you can redistribute it and/or modify 6214501Srpaulo * it under the terms of the GNU General Public License version 2 as 7214501Srpaulo * published by the Free Software Foundation. 8214501Srpaulo * 9214501Srpaulo * Alternatively, this software may be distributed under the terms of BSD 10214501Srpaulo * license. 11214501Srpaulo * 12214501Srpaulo * See README and COPYING for more details. 13214501Srpaulo */ 14214501Srpaulo 15214501Srpaulo#include "includes.h" 16214501Srpaulo#include <dbus/dbus.h> 17214501Srpaulo 18214501Srpaulo#include "common.h" 19214501Srpaulo#include "eap_peer/eap_methods.h" 20214501Srpaulo#include "common/ieee802_11_defs.h" 21214501Srpaulo#include "eapol_supp/eapol_supp_sm.h" 22214501Srpaulo#include "rsn_supp/wpa.h" 23214501Srpaulo#include "../config.h" 24214501Srpaulo#include "../wpa_supplicant_i.h" 25214501Srpaulo#include "../driver_i.h" 26214501Srpaulo#include "../notify.h" 27214501Srpaulo#include "../wpas_glue.h" 28214501Srpaulo#include "../bss.h" 29214501Srpaulo#include "../scan.h" 30214501Srpaulo#include "dbus_old.h" 31214501Srpaulo#include "dbus_old_handlers.h" 32214501Srpaulo#include "dbus_dict_helpers.h" 33214501Srpaulo 34214501Srpauloextern int wpa_debug_level; 35214501Srpauloextern int wpa_debug_show_keys; 36214501Srpauloextern int wpa_debug_timestamp; 37214501Srpaulo 38214501Srpaulo/** 39214501Srpaulo * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message 40214501Srpaulo * @message: Pointer to incoming dbus message this error refers to 41214501Srpaulo * Returns: a dbus error message 42214501Srpaulo * 43214501Srpaulo * Convenience function to create and return an invalid options error 44214501Srpaulo */ 45214501SrpauloDBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message, 46214501Srpaulo const char *arg) 47214501Srpaulo{ 48214501Srpaulo DBusMessage *reply; 49214501Srpaulo 50214501Srpaulo reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS, 51214501Srpaulo "Did not receive correct message " 52214501Srpaulo "arguments."); 53214501Srpaulo if (arg != NULL) 54214501Srpaulo dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg, 55214501Srpaulo DBUS_TYPE_INVALID); 56214501Srpaulo 57214501Srpaulo return reply; 58214501Srpaulo} 59214501Srpaulo 60214501Srpaulo 61214501Srpaulo/** 62214501Srpaulo * wpas_dbus_new_success_reply - Return a new success reply message 63214501Srpaulo * @message: Pointer to incoming dbus message this reply refers to 64214501Srpaulo * Returns: a dbus message containing a single UINT32 that indicates 65214501Srpaulo * success (ie, a value of 1) 66214501Srpaulo * 67214501Srpaulo * Convenience function to create and return a success reply message 68214501Srpaulo */ 69214501SrpauloDBusMessage * wpas_dbus_new_success_reply(DBusMessage *message) 70214501Srpaulo{ 71214501Srpaulo DBusMessage *reply; 72214501Srpaulo unsigned int success = 1; 73214501Srpaulo 74214501Srpaulo reply = dbus_message_new_method_return(message); 75214501Srpaulo dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success, 76214501Srpaulo DBUS_TYPE_INVALID); 77214501Srpaulo return reply; 78214501Srpaulo} 79214501Srpaulo 80214501Srpaulo 81214501Srpaulo/** 82214501Srpaulo * wpas_dbus_global_add_interface - Request registration of a network interface 83214501Srpaulo * @message: Pointer to incoming dbus message 84214501Srpaulo * @global: %wpa_supplicant global data structure 85214501Srpaulo * Returns: The object path of the new interface object, 86214501Srpaulo * or a dbus error message with more information 87214501Srpaulo * 88214501Srpaulo * Handler function for "addInterface" method call. Handles requests 89214501Srpaulo * by dbus clients to register a network interface that wpa_supplicant 90214501Srpaulo * will manage. 91214501Srpaulo */ 92214501SrpauloDBusMessage * wpas_dbus_global_add_interface(DBusMessage *message, 93214501Srpaulo struct wpa_global *global) 94214501Srpaulo{ 95214501Srpaulo char *ifname = NULL; 96214501Srpaulo char *driver = NULL; 97214501Srpaulo char *driver_param = NULL; 98214501Srpaulo char *confname = NULL; 99214501Srpaulo char *bridge_ifname = NULL; 100214501Srpaulo DBusMessage *reply = NULL; 101214501Srpaulo DBusMessageIter iter; 102214501Srpaulo 103214501Srpaulo dbus_message_iter_init(message, &iter); 104214501Srpaulo 105214501Srpaulo /* First argument: interface name (DBUS_TYPE_STRING) 106214501Srpaulo * Required; must be non-zero length 107214501Srpaulo */ 108214501Srpaulo if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 109214501Srpaulo goto error; 110214501Srpaulo dbus_message_iter_get_basic(&iter, &ifname); 111214501Srpaulo if (!os_strlen(ifname)) 112214501Srpaulo goto error; 113214501Srpaulo 114214501Srpaulo /* Second argument: dict of options */ 115214501Srpaulo if (dbus_message_iter_next(&iter)) { 116214501Srpaulo DBusMessageIter iter_dict; 117214501Srpaulo struct wpa_dbus_dict_entry entry; 118214501Srpaulo 119214501Srpaulo if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) 120214501Srpaulo goto error; 121214501Srpaulo while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 122214501Srpaulo if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 123214501Srpaulo goto error; 124214501Srpaulo if (!strcmp(entry.key, "driver") && 125214501Srpaulo (entry.type == DBUS_TYPE_STRING)) { 126214501Srpaulo driver = os_strdup(entry.str_value); 127214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 128214501Srpaulo if (driver == NULL) 129214501Srpaulo goto error; 130214501Srpaulo } else if (!strcmp(entry.key, "driver-params") && 131214501Srpaulo (entry.type == DBUS_TYPE_STRING)) { 132214501Srpaulo driver_param = os_strdup(entry.str_value); 133214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 134214501Srpaulo if (driver_param == NULL) 135214501Srpaulo goto error; 136214501Srpaulo } else if (!strcmp(entry.key, "config-file") && 137214501Srpaulo (entry.type == DBUS_TYPE_STRING)) { 138214501Srpaulo confname = os_strdup(entry.str_value); 139214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 140214501Srpaulo if (confname == NULL) 141214501Srpaulo goto error; 142214501Srpaulo } else if (!strcmp(entry.key, "bridge-ifname") && 143214501Srpaulo (entry.type == DBUS_TYPE_STRING)) { 144214501Srpaulo bridge_ifname = os_strdup(entry.str_value); 145214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 146214501Srpaulo if (bridge_ifname == NULL) 147214501Srpaulo goto error; 148214501Srpaulo } else { 149214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 150214501Srpaulo goto error; 151214501Srpaulo } 152214501Srpaulo } 153214501Srpaulo } 154214501Srpaulo 155214501Srpaulo /* 156214501Srpaulo * Try to get the wpa_supplicant record for this iface, return 157214501Srpaulo * an error if we already control it. 158214501Srpaulo */ 159214501Srpaulo if (wpa_supplicant_get_iface(global, ifname) != NULL) { 160214501Srpaulo reply = dbus_message_new_error(message, 161214501Srpaulo WPAS_ERROR_EXISTS_ERROR, 162214501Srpaulo "wpa_supplicant already " 163214501Srpaulo "controls this interface."); 164214501Srpaulo } else { 165214501Srpaulo struct wpa_supplicant *wpa_s; 166214501Srpaulo struct wpa_interface iface; 167214501Srpaulo os_memset(&iface, 0, sizeof(iface)); 168214501Srpaulo iface.ifname = ifname; 169214501Srpaulo iface.driver = driver; 170214501Srpaulo iface.driver_param = driver_param; 171214501Srpaulo iface.confname = confname; 172214501Srpaulo iface.bridge_ifname = bridge_ifname; 173214501Srpaulo /* Otherwise, have wpa_supplicant attach to it. */ 174214501Srpaulo if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) { 175214501Srpaulo const char *path = wpa_s->dbus_path; 176214501Srpaulo reply = dbus_message_new_method_return(message); 177214501Srpaulo dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 178214501Srpaulo &path, DBUS_TYPE_INVALID); 179214501Srpaulo } else { 180214501Srpaulo reply = dbus_message_new_error(message, 181214501Srpaulo WPAS_ERROR_ADD_ERROR, 182214501Srpaulo "wpa_supplicant " 183214501Srpaulo "couldn't grab this " 184214501Srpaulo "interface."); 185214501Srpaulo } 186214501Srpaulo } 187214501Srpaulo 188214501Srpauloout: 189214501Srpaulo os_free(driver); 190214501Srpaulo os_free(driver_param); 191214501Srpaulo os_free(confname); 192214501Srpaulo os_free(bridge_ifname); 193214501Srpaulo return reply; 194214501Srpaulo 195214501Srpauloerror: 196214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, NULL); 197214501Srpaulo goto out; 198214501Srpaulo} 199214501Srpaulo 200214501Srpaulo 201214501Srpaulo/** 202214501Srpaulo * wpas_dbus_global_remove_interface - Request deregistration of an interface 203214501Srpaulo * @message: Pointer to incoming dbus message 204214501Srpaulo * @global: wpa_supplicant global data structure 205214501Srpaulo * Returns: a dbus message containing a UINT32 indicating success (1) or 206214501Srpaulo * failure (0), or returns a dbus error message with more information 207214501Srpaulo * 208214501Srpaulo * Handler function for "removeInterface" method call. Handles requests 209214501Srpaulo * by dbus clients to deregister a network interface that wpa_supplicant 210214501Srpaulo * currently manages. 211214501Srpaulo */ 212214501SrpauloDBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message, 213214501Srpaulo struct wpa_global *global) 214214501Srpaulo{ 215214501Srpaulo struct wpa_supplicant *wpa_s; 216214501Srpaulo char *path; 217214501Srpaulo DBusMessage *reply = NULL; 218214501Srpaulo 219214501Srpaulo if (!dbus_message_get_args(message, NULL, 220214501Srpaulo DBUS_TYPE_OBJECT_PATH, &path, 221214501Srpaulo DBUS_TYPE_INVALID)) { 222214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, NULL); 223214501Srpaulo goto out; 224214501Srpaulo } 225214501Srpaulo 226214501Srpaulo wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path); 227214501Srpaulo if (wpa_s == NULL) { 228214501Srpaulo reply = wpas_dbus_new_invalid_iface_error(message); 229214501Srpaulo goto out; 230214501Srpaulo } 231214501Srpaulo 232214501Srpaulo if (!wpa_supplicant_remove_iface(global, wpa_s)) { 233214501Srpaulo reply = wpas_dbus_new_success_reply(message); 234214501Srpaulo } else { 235214501Srpaulo reply = dbus_message_new_error(message, 236214501Srpaulo WPAS_ERROR_REMOVE_ERROR, 237214501Srpaulo "wpa_supplicant couldn't " 238214501Srpaulo "remove this interface."); 239214501Srpaulo } 240214501Srpaulo 241214501Srpauloout: 242214501Srpaulo return reply; 243214501Srpaulo} 244214501Srpaulo 245214501Srpaulo 246214501Srpaulo/** 247214501Srpaulo * wpas_dbus_global_get_interface - Get the object path for an interface name 248214501Srpaulo * @message: Pointer to incoming dbus message 249214501Srpaulo * @global: %wpa_supplicant global data structure 250214501Srpaulo * Returns: The object path of the interface object, 251214501Srpaulo * or a dbus error message with more information 252214501Srpaulo * 253214501Srpaulo * Handler function for "getInterface" method call. Handles requests 254214501Srpaulo * by dbus clients for the object path of an specific network interface. 255214501Srpaulo */ 256214501SrpauloDBusMessage * wpas_dbus_global_get_interface(DBusMessage *message, 257214501Srpaulo struct wpa_global *global) 258214501Srpaulo{ 259214501Srpaulo DBusMessage *reply = NULL; 260214501Srpaulo const char *ifname; 261214501Srpaulo const char *path; 262214501Srpaulo struct wpa_supplicant *wpa_s; 263214501Srpaulo 264214501Srpaulo if (!dbus_message_get_args(message, NULL, 265214501Srpaulo DBUS_TYPE_STRING, &ifname, 266214501Srpaulo DBUS_TYPE_INVALID)) { 267214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, NULL); 268214501Srpaulo goto out; 269214501Srpaulo } 270214501Srpaulo 271214501Srpaulo wpa_s = wpa_supplicant_get_iface(global, ifname); 272214501Srpaulo if (wpa_s == NULL) { 273214501Srpaulo reply = wpas_dbus_new_invalid_iface_error(message); 274214501Srpaulo goto out; 275214501Srpaulo } 276214501Srpaulo 277214501Srpaulo path = wpa_s->dbus_path; 278214501Srpaulo reply = dbus_message_new_method_return(message); 279214501Srpaulo dbus_message_append_args(reply, 280214501Srpaulo DBUS_TYPE_OBJECT_PATH, &path, 281214501Srpaulo DBUS_TYPE_INVALID); 282214501Srpaulo 283214501Srpauloout: 284214501Srpaulo return reply; 285214501Srpaulo} 286214501Srpaulo 287214501Srpaulo 288214501Srpaulo/** 289214501Srpaulo * wpas_dbus_global_set_debugparams- Set the debug params 290214501Srpaulo * @message: Pointer to incoming dbus message 291214501Srpaulo * @global: %wpa_supplicant global data structure 292214501Srpaulo * Returns: a dbus message containing a UINT32 indicating success (1) or 293214501Srpaulo * failure (0), or returns a dbus error message with more information 294214501Srpaulo * 295214501Srpaulo * Handler function for "setDebugParams" method call. Handles requests 296214501Srpaulo * by dbus clients for the object path of an specific network interface. 297214501Srpaulo */ 298214501SrpauloDBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message, 299214501Srpaulo struct wpa_global *global) 300214501Srpaulo{ 301214501Srpaulo DBusMessage *reply = NULL; 302214501Srpaulo int debug_level; 303214501Srpaulo dbus_bool_t debug_timestamp; 304214501Srpaulo dbus_bool_t debug_show_keys; 305214501Srpaulo 306214501Srpaulo if (!dbus_message_get_args(message, NULL, 307214501Srpaulo DBUS_TYPE_INT32, &debug_level, 308214501Srpaulo DBUS_TYPE_BOOLEAN, &debug_timestamp, 309214501Srpaulo DBUS_TYPE_BOOLEAN, &debug_show_keys, 310214501Srpaulo DBUS_TYPE_INVALID)) { 311214501Srpaulo return wpas_dbus_new_invalid_opts_error(message, NULL); 312214501Srpaulo } 313214501Srpaulo 314214501Srpaulo if (wpa_supplicant_set_debug_params(global, debug_level, 315214501Srpaulo debug_timestamp ? 1 : 0, 316214501Srpaulo debug_show_keys ? 1 : 0)) { 317214501Srpaulo return wpas_dbus_new_invalid_opts_error(message, NULL); 318214501Srpaulo } 319214501Srpaulo 320214501Srpaulo reply = wpas_dbus_new_success_reply(message); 321214501Srpaulo 322214501Srpaulo return reply; 323214501Srpaulo} 324214501Srpaulo 325214501Srpaulo 326214501Srpaulo/** 327214501Srpaulo * wpas_dbus_iface_scan - Request a wireless scan on an interface 328214501Srpaulo * @message: Pointer to incoming dbus message 329214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 330214501Srpaulo * Returns: a dbus message containing a UINT32 indicating success (1) or 331214501Srpaulo * failure (0) 332214501Srpaulo * 333214501Srpaulo * Handler function for "scan" method call of a network device. Requests 334214501Srpaulo * that wpa_supplicant perform a wireless scan as soon as possible 335214501Srpaulo * on a particular wireless interface. 336214501Srpaulo */ 337214501SrpauloDBusMessage * wpas_dbus_iface_scan(DBusMessage *message, 338214501Srpaulo struct wpa_supplicant *wpa_s) 339214501Srpaulo{ 340214501Srpaulo wpa_s->scan_req = 2; 341214501Srpaulo wpa_supplicant_req_scan(wpa_s, 0, 0); 342214501Srpaulo return wpas_dbus_new_success_reply(message); 343214501Srpaulo} 344214501Srpaulo 345214501Srpaulo 346214501Srpaulo/** 347214501Srpaulo * wpas_dbus_iface_scan_results - Get the results of a recent scan request 348214501Srpaulo * @message: Pointer to incoming dbus message 349214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 350214501Srpaulo * Returns: a dbus message containing a dbus array of objects paths, or returns 351214501Srpaulo * a dbus error message if not scan results could be found 352214501Srpaulo * 353214501Srpaulo * Handler function for "scanResults" method call of a network device. Returns 354214501Srpaulo * a dbus message containing the object paths of wireless networks found. 355214501Srpaulo */ 356214501SrpauloDBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message, 357214501Srpaulo struct wpa_supplicant *wpa_s) 358214501Srpaulo{ 359214501Srpaulo DBusMessage *reply = NULL; 360214501Srpaulo DBusMessageIter iter; 361214501Srpaulo DBusMessageIter sub_iter; 362214501Srpaulo struct wpa_bss *bss; 363214501Srpaulo 364214501Srpaulo /* Create and initialize the return message */ 365214501Srpaulo reply = dbus_message_new_method_return(message); 366214501Srpaulo dbus_message_iter_init_append(reply, &iter); 367214501Srpaulo dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 368214501Srpaulo DBUS_TYPE_OBJECT_PATH_AS_STRING, 369214501Srpaulo &sub_iter); 370214501Srpaulo 371214501Srpaulo /* Loop through scan results and append each result's object path */ 372214501Srpaulo dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 373214501Srpaulo char path_buf[WPAS_DBUS_OBJECT_PATH_MAX]; 374214501Srpaulo char *path = path_buf; 375214501Srpaulo 376214501Srpaulo /* Construct the object path for this network. Note that ':' 377214501Srpaulo * is not a valid character in dbus object paths. 378214501Srpaulo */ 379214501Srpaulo os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 380214501Srpaulo "%s/" WPAS_DBUS_BSSIDS_PART "/" 381214501Srpaulo WPAS_DBUS_BSSID_FORMAT, 382214501Srpaulo wpa_s->dbus_path, MAC2STR(bss->bssid)); 383214501Srpaulo dbus_message_iter_append_basic(&sub_iter, 384214501Srpaulo DBUS_TYPE_OBJECT_PATH, &path); 385214501Srpaulo } 386214501Srpaulo 387214501Srpaulo dbus_message_iter_close_container(&iter, &sub_iter); 388214501Srpaulo 389214501Srpaulo return reply; 390214501Srpaulo} 391214501Srpaulo 392214501Srpaulo 393214501Srpaulo/** 394214501Srpaulo * wpas_dbus_bssid_properties - Return the properties of a scanned network 395214501Srpaulo * @message: Pointer to incoming dbus message 396214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 397214501Srpaulo * @res: wpa_supplicant scan result for which to get properties 398214501Srpaulo * Returns: a dbus message containing the properties for the requested network 399214501Srpaulo * 400214501Srpaulo * Handler function for "properties" method call of a scanned network. 401214501Srpaulo * Returns a dbus message containing the the properties. 402214501Srpaulo */ 403214501SrpauloDBusMessage * wpas_dbus_bssid_properties(DBusMessage *message, 404214501Srpaulo struct wpa_supplicant *wpa_s, 405214501Srpaulo struct wpa_bss *bss) 406214501Srpaulo{ 407214501Srpaulo DBusMessage *reply; 408214501Srpaulo DBusMessageIter iter, iter_dict; 409214501Srpaulo const u8 *ie; 410214501Srpaulo 411214501Srpaulo /* Dump the properties into a dbus message */ 412214501Srpaulo reply = dbus_message_new_method_return(message); 413214501Srpaulo 414214501Srpaulo dbus_message_iter_init_append(reply, &iter); 415214501Srpaulo if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 416214501Srpaulo goto error; 417214501Srpaulo 418214501Srpaulo if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid", 419214501Srpaulo (const char *) bss->bssid, 420214501Srpaulo ETH_ALEN)) 421214501Srpaulo goto error; 422214501Srpaulo 423214501Srpaulo ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); 424214501Srpaulo if (ie) { 425214501Srpaulo if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid", 426214501Srpaulo (const char *) (ie + 2), 427214501Srpaulo ie[1])) 428214501Srpaulo goto error; 429214501Srpaulo } 430214501Srpaulo 431214501Srpaulo ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 432214501Srpaulo if (ie) { 433214501Srpaulo if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie", 434214501Srpaulo (const char *) ie, 435214501Srpaulo ie[1] + 2)) 436214501Srpaulo goto error; 437214501Srpaulo } 438214501Srpaulo 439214501Srpaulo ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); 440214501Srpaulo if (ie) { 441214501Srpaulo if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie", 442214501Srpaulo (const char *) ie, 443214501Srpaulo ie[1] + 2)) 444214501Srpaulo goto error; 445214501Srpaulo } 446214501Srpaulo 447214501Srpaulo ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE); 448214501Srpaulo if (ie) { 449214501Srpaulo if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie", 450214501Srpaulo (const char *) ie, 451214501Srpaulo ie[1] + 2)) 452214501Srpaulo goto error; 453214501Srpaulo } 454214501Srpaulo 455214501Srpaulo if (bss->freq) { 456214501Srpaulo if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency", 457214501Srpaulo bss->freq)) 458214501Srpaulo goto error; 459214501Srpaulo } 460214501Srpaulo if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities", 461214501Srpaulo bss->caps)) 462214501Srpaulo goto error; 463214501Srpaulo if (!(bss->flags & WPA_BSS_QUAL_INVALID) && 464214501Srpaulo !wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual)) 465214501Srpaulo goto error; 466214501Srpaulo if (!(bss->flags & WPA_BSS_NOISE_INVALID) && 467214501Srpaulo !wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise)) 468214501Srpaulo goto error; 469214501Srpaulo if (!(bss->flags & WPA_BSS_LEVEL_INVALID) && 470214501Srpaulo !wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level)) 471214501Srpaulo goto error; 472214501Srpaulo if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate", 473214501Srpaulo wpa_bss_get_max_rate(bss) * 500000)) 474214501Srpaulo goto error; 475214501Srpaulo 476214501Srpaulo if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 477214501Srpaulo goto error; 478214501Srpaulo 479214501Srpaulo return reply; 480214501Srpaulo 481214501Srpauloerror: 482214501Srpaulo if (reply) 483214501Srpaulo dbus_message_unref(reply); 484214501Srpaulo return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, 485214501Srpaulo "an internal error occurred returning " 486214501Srpaulo "BSSID properties."); 487214501Srpaulo} 488214501Srpaulo 489214501Srpaulo 490214501Srpaulo/** 491214501Srpaulo * wpas_dbus_iface_capabilities - Return interface capabilities 492214501Srpaulo * @message: Pointer to incoming dbus message 493214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 494214501Srpaulo * Returns: A dbus message containing a dict of strings 495214501Srpaulo * 496214501Srpaulo * Handler function for "capabilities" method call of an interface. 497214501Srpaulo */ 498214501SrpauloDBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message, 499214501Srpaulo struct wpa_supplicant *wpa_s) 500214501Srpaulo{ 501214501Srpaulo DBusMessage *reply = NULL; 502214501Srpaulo struct wpa_driver_capa capa; 503214501Srpaulo int res; 504214501Srpaulo DBusMessageIter iter, iter_dict; 505214501Srpaulo char **eap_methods; 506214501Srpaulo size_t num_items; 507214501Srpaulo dbus_bool_t strict = FALSE; 508214501Srpaulo DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; 509214501Srpaulo 510214501Srpaulo if (!dbus_message_get_args(message, NULL, 511214501Srpaulo DBUS_TYPE_BOOLEAN, &strict, 512214501Srpaulo DBUS_TYPE_INVALID)) 513214501Srpaulo strict = FALSE; 514214501Srpaulo 515214501Srpaulo reply = dbus_message_new_method_return(message); 516214501Srpaulo 517214501Srpaulo dbus_message_iter_init_append(reply, &iter); 518214501Srpaulo if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 519214501Srpaulo goto error; 520214501Srpaulo 521214501Srpaulo /* EAP methods */ 522214501Srpaulo eap_methods = eap_get_names_as_string_array(&num_items); 523214501Srpaulo if (eap_methods) { 524214501Srpaulo dbus_bool_t success = FALSE; 525214501Srpaulo size_t i = 0; 526214501Srpaulo 527214501Srpaulo success = wpa_dbus_dict_append_string_array( 528214501Srpaulo &iter_dict, "eap", (const char **) eap_methods, 529214501Srpaulo num_items); 530214501Srpaulo 531214501Srpaulo /* free returned method array */ 532214501Srpaulo while (eap_methods[i]) 533214501Srpaulo os_free(eap_methods[i++]); 534214501Srpaulo os_free(eap_methods); 535214501Srpaulo 536214501Srpaulo if (!success) 537214501Srpaulo goto error; 538214501Srpaulo } 539214501Srpaulo 540214501Srpaulo res = wpa_drv_get_capa(wpa_s, &capa); 541214501Srpaulo 542214501Srpaulo /***** pairwise cipher */ 543214501Srpaulo if (res < 0) { 544214501Srpaulo if (!strict) { 545214501Srpaulo const char *args[] = {"CCMP", "TKIP", "NONE"}; 546214501Srpaulo if (!wpa_dbus_dict_append_string_array( 547214501Srpaulo &iter_dict, "pairwise", args, 548214501Srpaulo sizeof(args) / sizeof(char*))) 549214501Srpaulo goto error; 550214501Srpaulo } 551214501Srpaulo } else { 552214501Srpaulo if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise", 553214501Srpaulo &iter_dict_entry, 554214501Srpaulo &iter_dict_val, 555214501Srpaulo &iter_array)) 556214501Srpaulo goto error; 557214501Srpaulo 558214501Srpaulo if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 559214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 560214501Srpaulo &iter_array, "CCMP")) 561214501Srpaulo goto error; 562214501Srpaulo } 563214501Srpaulo 564214501Srpaulo if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 565214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 566214501Srpaulo &iter_array, "TKIP")) 567214501Srpaulo goto error; 568214501Srpaulo } 569214501Srpaulo 570214501Srpaulo if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 571214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 572214501Srpaulo &iter_array, "NONE")) 573214501Srpaulo goto error; 574214501Srpaulo } 575214501Srpaulo 576214501Srpaulo if (!wpa_dbus_dict_end_string_array(&iter_dict, 577214501Srpaulo &iter_dict_entry, 578214501Srpaulo &iter_dict_val, 579214501Srpaulo &iter_array)) 580214501Srpaulo goto error; 581214501Srpaulo } 582214501Srpaulo 583214501Srpaulo /***** group cipher */ 584214501Srpaulo if (res < 0) { 585214501Srpaulo if (!strict) { 586214501Srpaulo const char *args[] = { 587214501Srpaulo "CCMP", "TKIP", "WEP104", "WEP40" 588214501Srpaulo }; 589214501Srpaulo if (!wpa_dbus_dict_append_string_array( 590214501Srpaulo &iter_dict, "group", args, 591214501Srpaulo sizeof(args) / sizeof(char*))) 592214501Srpaulo goto error; 593214501Srpaulo } 594214501Srpaulo } else { 595214501Srpaulo if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group", 596214501Srpaulo &iter_dict_entry, 597214501Srpaulo &iter_dict_val, 598214501Srpaulo &iter_array)) 599214501Srpaulo goto error; 600214501Srpaulo 601214501Srpaulo if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 602214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 603214501Srpaulo &iter_array, "CCMP")) 604214501Srpaulo goto error; 605214501Srpaulo } 606214501Srpaulo 607214501Srpaulo if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 608214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 609214501Srpaulo &iter_array, "TKIP")) 610214501Srpaulo goto error; 611214501Srpaulo } 612214501Srpaulo 613214501Srpaulo if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { 614214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 615214501Srpaulo &iter_array, "WEP104")) 616214501Srpaulo goto error; 617214501Srpaulo } 618214501Srpaulo 619214501Srpaulo if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { 620214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 621214501Srpaulo &iter_array, "WEP40")) 622214501Srpaulo goto error; 623214501Srpaulo } 624214501Srpaulo 625214501Srpaulo if (!wpa_dbus_dict_end_string_array(&iter_dict, 626214501Srpaulo &iter_dict_entry, 627214501Srpaulo &iter_dict_val, 628214501Srpaulo &iter_array)) 629214501Srpaulo goto error; 630214501Srpaulo } 631214501Srpaulo 632214501Srpaulo /***** key management */ 633214501Srpaulo if (res < 0) { 634214501Srpaulo if (!strict) { 635214501Srpaulo const char *args[] = { 636214501Srpaulo "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE", 637214501Srpaulo "NONE" 638214501Srpaulo }; 639214501Srpaulo if (!wpa_dbus_dict_append_string_array( 640214501Srpaulo &iter_dict, "key_mgmt", args, 641214501Srpaulo sizeof(args) / sizeof(char*))) 642214501Srpaulo goto error; 643214501Srpaulo } 644214501Srpaulo } else { 645214501Srpaulo if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt", 646214501Srpaulo &iter_dict_entry, 647214501Srpaulo &iter_dict_val, 648214501Srpaulo &iter_array)) 649214501Srpaulo goto error; 650214501Srpaulo 651214501Srpaulo if (!wpa_dbus_dict_string_array_add_element(&iter_array, 652214501Srpaulo "NONE")) 653214501Srpaulo goto error; 654214501Srpaulo 655214501Srpaulo if (!wpa_dbus_dict_string_array_add_element(&iter_array, 656214501Srpaulo "IEEE8021X")) 657214501Srpaulo goto error; 658214501Srpaulo 659214501Srpaulo if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 660214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 661214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 662214501Srpaulo &iter_array, "WPA-EAP")) 663214501Srpaulo goto error; 664214501Srpaulo } 665214501Srpaulo 666214501Srpaulo if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 667214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 668214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 669214501Srpaulo &iter_array, "WPA-PSK")) 670214501Srpaulo goto error; 671214501Srpaulo } 672214501Srpaulo 673214501Srpaulo if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 674214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 675214501Srpaulo &iter_array, "WPA-NONE")) 676214501Srpaulo goto error; 677214501Srpaulo } 678214501Srpaulo 679214501Srpaulo if (!wpa_dbus_dict_end_string_array(&iter_dict, 680214501Srpaulo &iter_dict_entry, 681214501Srpaulo &iter_dict_val, 682214501Srpaulo &iter_array)) 683214501Srpaulo goto error; 684214501Srpaulo } 685214501Srpaulo 686214501Srpaulo /***** WPA protocol */ 687214501Srpaulo if (res < 0) { 688214501Srpaulo if (!strict) { 689214501Srpaulo const char *args[] = { "RSN", "WPA" }; 690214501Srpaulo if (!wpa_dbus_dict_append_string_array( 691214501Srpaulo &iter_dict, "proto", args, 692214501Srpaulo sizeof(args) / sizeof(char*))) 693214501Srpaulo goto error; 694214501Srpaulo } 695214501Srpaulo } else { 696214501Srpaulo if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto", 697214501Srpaulo &iter_dict_entry, 698214501Srpaulo &iter_dict_val, 699214501Srpaulo &iter_array)) 700214501Srpaulo goto error; 701214501Srpaulo 702214501Srpaulo if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 703214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 704214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 705214501Srpaulo &iter_array, "RSN")) 706214501Srpaulo goto error; 707214501Srpaulo } 708214501Srpaulo 709214501Srpaulo if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 710214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 711214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 712214501Srpaulo &iter_array, "WPA")) 713214501Srpaulo goto error; 714214501Srpaulo } 715214501Srpaulo 716214501Srpaulo if (!wpa_dbus_dict_end_string_array(&iter_dict, 717214501Srpaulo &iter_dict_entry, 718214501Srpaulo &iter_dict_val, 719214501Srpaulo &iter_array)) 720214501Srpaulo goto error; 721214501Srpaulo } 722214501Srpaulo 723214501Srpaulo /***** auth alg */ 724214501Srpaulo if (res < 0) { 725214501Srpaulo if (!strict) { 726214501Srpaulo const char *args[] = { "OPEN", "SHARED", "LEAP" }; 727214501Srpaulo if (!wpa_dbus_dict_append_string_array( 728214501Srpaulo &iter_dict, "auth_alg", args, 729214501Srpaulo sizeof(args) / sizeof(char*))) 730214501Srpaulo goto error; 731214501Srpaulo } 732214501Srpaulo } else { 733214501Srpaulo if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg", 734214501Srpaulo &iter_dict_entry, 735214501Srpaulo &iter_dict_val, 736214501Srpaulo &iter_array)) 737214501Srpaulo goto error; 738214501Srpaulo 739214501Srpaulo if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { 740214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 741214501Srpaulo &iter_array, "OPEN")) 742214501Srpaulo goto error; 743214501Srpaulo } 744214501Srpaulo 745214501Srpaulo if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { 746214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 747214501Srpaulo &iter_array, "SHARED")) 748214501Srpaulo goto error; 749214501Srpaulo } 750214501Srpaulo 751214501Srpaulo if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { 752214501Srpaulo if (!wpa_dbus_dict_string_array_add_element( 753214501Srpaulo &iter_array, "LEAP")) 754214501Srpaulo goto error; 755214501Srpaulo } 756214501Srpaulo 757214501Srpaulo if (!wpa_dbus_dict_end_string_array(&iter_dict, 758214501Srpaulo &iter_dict_entry, 759214501Srpaulo &iter_dict_val, 760214501Srpaulo &iter_array)) 761214501Srpaulo goto error; 762214501Srpaulo } 763214501Srpaulo 764214501Srpaulo if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 765214501Srpaulo goto error; 766214501Srpaulo 767214501Srpaulo return reply; 768214501Srpaulo 769214501Srpauloerror: 770214501Srpaulo if (reply) 771214501Srpaulo dbus_message_unref(reply); 772214501Srpaulo return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, 773214501Srpaulo "an internal error occurred returning " 774214501Srpaulo "interface capabilities."); 775214501Srpaulo} 776214501Srpaulo 777214501Srpaulo 778214501Srpaulo/** 779214501Srpaulo * wpas_dbus_iface_add_network - Add a new configured network 780214501Srpaulo * @message: Pointer to incoming dbus message 781214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 782214501Srpaulo * Returns: A dbus message containing the object path of the new network 783214501Srpaulo * 784214501Srpaulo * Handler function for "addNetwork" method call of a network interface. 785214501Srpaulo */ 786214501SrpauloDBusMessage * wpas_dbus_iface_add_network(DBusMessage *message, 787214501Srpaulo struct wpa_supplicant *wpa_s) 788214501Srpaulo{ 789214501Srpaulo DBusMessage *reply = NULL; 790214501Srpaulo struct wpa_ssid *ssid; 791214501Srpaulo char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 792214501Srpaulo 793214501Srpaulo ssid = wpa_config_add_network(wpa_s->conf); 794214501Srpaulo if (ssid == NULL) { 795214501Srpaulo reply = dbus_message_new_error(message, 796214501Srpaulo WPAS_ERROR_ADD_NETWORK_ERROR, 797214501Srpaulo "wpa_supplicant could not add " 798214501Srpaulo "a network on this interface."); 799214501Srpaulo goto out; 800214501Srpaulo } 801214501Srpaulo wpas_notify_network_added(wpa_s, ssid); 802214501Srpaulo ssid->disabled = 1; 803214501Srpaulo wpa_config_set_network_defaults(ssid); 804214501Srpaulo 805214501Srpaulo /* Construct the object path for this network. */ 806214501Srpaulo os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 807214501Srpaulo "%s/" WPAS_DBUS_NETWORKS_PART "/%d", 808214501Srpaulo wpa_s->dbus_path, ssid->id); 809214501Srpaulo 810214501Srpaulo reply = dbus_message_new_method_return(message); 811214501Srpaulo dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 812214501Srpaulo &path, DBUS_TYPE_INVALID); 813214501Srpaulo 814214501Srpauloout: 815214501Srpaulo return reply; 816214501Srpaulo} 817214501Srpaulo 818214501Srpaulo 819214501Srpaulo/** 820214501Srpaulo * wpas_dbus_iface_remove_network - Remove a configured network 821214501Srpaulo * @message: Pointer to incoming dbus message 822214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 823214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 824214501Srpaulo * failure (0) 825214501Srpaulo * 826214501Srpaulo * Handler function for "removeNetwork" method call of a network interface. 827214501Srpaulo */ 828214501SrpauloDBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message, 829214501Srpaulo struct wpa_supplicant *wpa_s) 830214501Srpaulo{ 831214501Srpaulo DBusMessage *reply = NULL; 832214501Srpaulo const char *op; 833214501Srpaulo char *iface = NULL, *net_id = NULL; 834214501Srpaulo int id; 835214501Srpaulo struct wpa_ssid *ssid; 836214501Srpaulo 837214501Srpaulo if (!dbus_message_get_args(message, NULL, 838214501Srpaulo DBUS_TYPE_OBJECT_PATH, &op, 839214501Srpaulo DBUS_TYPE_INVALID)) { 840214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, NULL); 841214501Srpaulo goto out; 842214501Srpaulo } 843214501Srpaulo 844214501Srpaulo /* Extract the network ID */ 845214501Srpaulo iface = wpas_dbus_decompose_object_path(op, &net_id, NULL); 846214501Srpaulo if (iface == NULL) { 847214501Srpaulo reply = wpas_dbus_new_invalid_network_error(message); 848214501Srpaulo goto out; 849214501Srpaulo } 850214501Srpaulo 851214501Srpaulo /* Ensure the network is actually a child of this interface */ 852214501Srpaulo if (os_strcmp(iface, wpa_s->dbus_path) != 0) { 853214501Srpaulo reply = wpas_dbus_new_invalid_network_error(message); 854214501Srpaulo goto out; 855214501Srpaulo } 856214501Srpaulo 857214501Srpaulo id = strtoul(net_id, NULL, 10); 858214501Srpaulo ssid = wpa_config_get_network(wpa_s->conf, id); 859214501Srpaulo if (ssid == NULL) { 860214501Srpaulo reply = wpas_dbus_new_invalid_network_error(message); 861214501Srpaulo goto out; 862214501Srpaulo } 863214501Srpaulo 864214501Srpaulo wpas_notify_network_removed(wpa_s, ssid); 865214501Srpaulo 866214501Srpaulo if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 867214501Srpaulo reply = dbus_message_new_error(message, 868214501Srpaulo WPAS_ERROR_REMOVE_NETWORK_ERROR, 869214501Srpaulo "error removing the specified " 870214501Srpaulo "on this interface."); 871214501Srpaulo goto out; 872214501Srpaulo } 873214501Srpaulo 874214501Srpaulo if (ssid == wpa_s->current_ssid) 875214501Srpaulo wpa_supplicant_deauthenticate(wpa_s, 876214501Srpaulo WLAN_REASON_DEAUTH_LEAVING); 877214501Srpaulo reply = wpas_dbus_new_success_reply(message); 878214501Srpaulo 879214501Srpauloout: 880214501Srpaulo os_free(iface); 881214501Srpaulo os_free(net_id); 882214501Srpaulo return reply; 883214501Srpaulo} 884214501Srpaulo 885214501Srpaulo 886214501Srpaulostatic const char *dont_quote[] = { 887214501Srpaulo "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", 888214501Srpaulo "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path", 889214501Srpaulo "bssid", NULL 890214501Srpaulo}; 891214501Srpaulo 892214501Srpaulo 893214501Srpaulostatic dbus_bool_t should_quote_opt(const char *key) 894214501Srpaulo{ 895214501Srpaulo int i = 0; 896214501Srpaulo while (dont_quote[i] != NULL) { 897214501Srpaulo if (strcmp(key, dont_quote[i]) == 0) 898214501Srpaulo return FALSE; 899214501Srpaulo i++; 900214501Srpaulo } 901214501Srpaulo return TRUE; 902214501Srpaulo} 903214501Srpaulo 904214501Srpaulo 905214501Srpaulo/** 906214501Srpaulo * wpas_dbus_iface_set_network - Set options for a configured network 907214501Srpaulo * @message: Pointer to incoming dbus message 908214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 909214501Srpaulo * @ssid: wpa_ssid structure for a configured network 910214501Srpaulo * Returns: a dbus message containing a UINT32 indicating success (1) or 911214501Srpaulo * failure (0) 912214501Srpaulo * 913214501Srpaulo * Handler function for "set" method call of a configured network. 914214501Srpaulo */ 915214501SrpauloDBusMessage * wpas_dbus_iface_set_network(DBusMessage *message, 916214501Srpaulo struct wpa_supplicant *wpa_s, 917214501Srpaulo struct wpa_ssid *ssid) 918214501Srpaulo{ 919214501Srpaulo DBusMessage *reply = NULL; 920214501Srpaulo struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 921214501Srpaulo DBusMessageIter iter, iter_dict; 922214501Srpaulo 923214501Srpaulo dbus_message_iter_init(message, &iter); 924214501Srpaulo 925214501Srpaulo if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) { 926214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, NULL); 927214501Srpaulo goto out; 928214501Srpaulo } 929214501Srpaulo 930214501Srpaulo while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 931214501Srpaulo char *value = NULL; 932214501Srpaulo size_t size = 50; 933214501Srpaulo int ret; 934214501Srpaulo 935214501Srpaulo if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 936214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, 937214501Srpaulo NULL); 938214501Srpaulo goto out; 939214501Srpaulo } 940214501Srpaulo 941214501Srpaulo /* Type conversions, since wpa_supplicant wants strings */ 942214501Srpaulo if (entry.type == DBUS_TYPE_ARRAY && 943214501Srpaulo entry.array_type == DBUS_TYPE_BYTE) { 944214501Srpaulo if (entry.array_len <= 0) 945214501Srpaulo goto error; 946214501Srpaulo 947214501Srpaulo size = entry.array_len * 2 + 1; 948214501Srpaulo value = os_zalloc(size); 949214501Srpaulo if (value == NULL) 950214501Srpaulo goto error; 951214501Srpaulo ret = wpa_snprintf_hex(value, size, 952214501Srpaulo (u8 *) entry.bytearray_value, 953214501Srpaulo entry.array_len); 954214501Srpaulo if (ret <= 0) 955214501Srpaulo goto error; 956214501Srpaulo } else if (entry.type == DBUS_TYPE_STRING) { 957214501Srpaulo if (should_quote_opt(entry.key)) { 958214501Srpaulo size = os_strlen(entry.str_value); 959214501Srpaulo /* Zero-length option check */ 960214501Srpaulo if (size <= 0) 961214501Srpaulo goto error; 962214501Srpaulo size += 3; /* For quotes and terminator */ 963214501Srpaulo value = os_zalloc(size); 964214501Srpaulo if (value == NULL) 965214501Srpaulo goto error; 966214501Srpaulo ret = os_snprintf(value, size, "\"%s\"", 967214501Srpaulo entry.str_value); 968214501Srpaulo if (ret < 0 || (size_t) ret != (size - 1)) 969214501Srpaulo goto error; 970214501Srpaulo } else { 971214501Srpaulo value = os_strdup(entry.str_value); 972214501Srpaulo if (value == NULL) 973214501Srpaulo goto error; 974214501Srpaulo } 975214501Srpaulo } else if (entry.type == DBUS_TYPE_UINT32) { 976214501Srpaulo value = os_zalloc(size); 977214501Srpaulo if (value == NULL) 978214501Srpaulo goto error; 979214501Srpaulo ret = os_snprintf(value, size, "%u", 980214501Srpaulo entry.uint32_value); 981214501Srpaulo if (ret <= 0) 982214501Srpaulo goto error; 983214501Srpaulo } else if (entry.type == DBUS_TYPE_INT32) { 984214501Srpaulo value = os_zalloc(size); 985214501Srpaulo if (value == NULL) 986214501Srpaulo goto error; 987214501Srpaulo ret = os_snprintf(value, size, "%d", 988214501Srpaulo entry.int32_value); 989214501Srpaulo if (ret <= 0) 990214501Srpaulo goto error; 991214501Srpaulo } else 992214501Srpaulo goto error; 993214501Srpaulo 994214501Srpaulo if (wpa_config_set(ssid, entry.key, value, 0) < 0) 995214501Srpaulo goto error; 996214501Srpaulo 997214501Srpaulo if ((os_strcmp(entry.key, "psk") == 0 && 998214501Srpaulo value[0] == '"' && ssid->ssid_len) || 999214501Srpaulo (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase)) 1000214501Srpaulo wpa_config_update_psk(ssid); 1001214501Srpaulo else if (os_strcmp(entry.key, "priority") == 0) 1002214501Srpaulo wpa_config_update_prio_list(wpa_s->conf); 1003214501Srpaulo 1004214501Srpaulo os_free(value); 1005214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 1006214501Srpaulo continue; 1007214501Srpaulo 1008214501Srpaulo error: 1009214501Srpaulo os_free(value); 1010214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, entry.key); 1011214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 1012214501Srpaulo break; 1013214501Srpaulo } 1014214501Srpaulo 1015214501Srpaulo if (!reply) 1016214501Srpaulo reply = wpas_dbus_new_success_reply(message); 1017214501Srpaulo 1018214501Srpauloout: 1019214501Srpaulo return reply; 1020214501Srpaulo} 1021214501Srpaulo 1022214501Srpaulo 1023214501Srpaulo/** 1024214501Srpaulo * wpas_dbus_iface_enable_network - Mark a configured network as enabled 1025214501Srpaulo * @message: Pointer to incoming dbus message 1026214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1027214501Srpaulo * @ssid: wpa_ssid structure for a configured network 1028214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 1029214501Srpaulo * failure (0) 1030214501Srpaulo * 1031214501Srpaulo * Handler function for "enable" method call of a configured network. 1032214501Srpaulo */ 1033214501SrpauloDBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message, 1034214501Srpaulo struct wpa_supplicant *wpa_s, 1035214501Srpaulo struct wpa_ssid *ssid) 1036214501Srpaulo{ 1037214501Srpaulo wpa_supplicant_enable_network(wpa_s, ssid); 1038214501Srpaulo return wpas_dbus_new_success_reply(message); 1039214501Srpaulo} 1040214501Srpaulo 1041214501Srpaulo 1042214501Srpaulo/** 1043214501Srpaulo * wpas_dbus_iface_disable_network - Mark a configured network as disabled 1044214501Srpaulo * @message: Pointer to incoming dbus message 1045214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1046214501Srpaulo * @ssid: wpa_ssid structure for a configured network 1047214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 1048214501Srpaulo * failure (0) 1049214501Srpaulo * 1050214501Srpaulo * Handler function for "disable" method call of a configured network. 1051214501Srpaulo */ 1052214501SrpauloDBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message, 1053214501Srpaulo struct wpa_supplicant *wpa_s, 1054214501Srpaulo struct wpa_ssid *ssid) 1055214501Srpaulo{ 1056214501Srpaulo wpa_supplicant_disable_network(wpa_s, ssid); 1057214501Srpaulo return wpas_dbus_new_success_reply(message); 1058214501Srpaulo} 1059214501Srpaulo 1060214501Srpaulo 1061214501Srpaulo/** 1062214501Srpaulo * wpas_dbus_iface_select_network - Attempt association with a configured network 1063214501Srpaulo * @message: Pointer to incoming dbus message 1064214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1065214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 1066214501Srpaulo * failure (0) 1067214501Srpaulo * 1068214501Srpaulo * Handler function for "selectNetwork" method call of network interface. 1069214501Srpaulo */ 1070214501SrpauloDBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, 1071214501Srpaulo struct wpa_supplicant *wpa_s) 1072214501Srpaulo{ 1073214501Srpaulo DBusMessage *reply = NULL; 1074214501Srpaulo const char *op; 1075214501Srpaulo struct wpa_ssid *ssid; 1076214501Srpaulo char *iface_obj_path = NULL; 1077214501Srpaulo char *network = NULL; 1078214501Srpaulo 1079214501Srpaulo if (os_strlen(dbus_message_get_signature(message)) == 0) { 1080214501Srpaulo /* Any network */ 1081214501Srpaulo ssid = NULL; 1082214501Srpaulo } else { 1083214501Srpaulo int nid; 1084214501Srpaulo 1085214501Srpaulo if (!dbus_message_get_args(message, NULL, 1086214501Srpaulo DBUS_TYPE_OBJECT_PATH, &op, 1087214501Srpaulo DBUS_TYPE_INVALID)) { 1088214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, 1089214501Srpaulo NULL); 1090214501Srpaulo goto out; 1091214501Srpaulo } 1092214501Srpaulo 1093214501Srpaulo /* Extract the network number */ 1094214501Srpaulo iface_obj_path = wpas_dbus_decompose_object_path(op, 1095214501Srpaulo &network, 1096214501Srpaulo NULL); 1097214501Srpaulo if (iface_obj_path == NULL) { 1098214501Srpaulo reply = wpas_dbus_new_invalid_iface_error(message); 1099214501Srpaulo goto out; 1100214501Srpaulo } 1101214501Srpaulo /* Ensure the object path really points to this interface */ 1102214501Srpaulo if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) { 1103214501Srpaulo reply = wpas_dbus_new_invalid_network_error(message); 1104214501Srpaulo goto out; 1105214501Srpaulo } 1106214501Srpaulo 1107214501Srpaulo nid = strtoul(network, NULL, 10); 1108214501Srpaulo if (errno == EINVAL) { 1109214501Srpaulo reply = wpas_dbus_new_invalid_network_error(message); 1110214501Srpaulo goto out; 1111214501Srpaulo } 1112214501Srpaulo 1113214501Srpaulo ssid = wpa_config_get_network(wpa_s->conf, nid); 1114214501Srpaulo if (ssid == NULL) { 1115214501Srpaulo reply = wpas_dbus_new_invalid_network_error(message); 1116214501Srpaulo goto out; 1117214501Srpaulo } 1118214501Srpaulo } 1119214501Srpaulo 1120214501Srpaulo /* Finally, associate with the network */ 1121214501Srpaulo wpa_supplicant_select_network(wpa_s, ssid); 1122214501Srpaulo 1123214501Srpaulo reply = wpas_dbus_new_success_reply(message); 1124214501Srpaulo 1125214501Srpauloout: 1126214501Srpaulo os_free(iface_obj_path); 1127214501Srpaulo os_free(network); 1128214501Srpaulo return reply; 1129214501Srpaulo} 1130214501Srpaulo 1131214501Srpaulo 1132214501Srpaulo/** 1133214501Srpaulo * wpas_dbus_iface_disconnect - Terminate the current connection 1134214501Srpaulo * @message: Pointer to incoming dbus message 1135214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1136214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 1137214501Srpaulo * failure (0) 1138214501Srpaulo * 1139214501Srpaulo * Handler function for "disconnect" method call of network interface. 1140214501Srpaulo */ 1141214501SrpauloDBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message, 1142214501Srpaulo struct wpa_supplicant *wpa_s) 1143214501Srpaulo{ 1144214501Srpaulo wpa_s->disconnected = 1; 1145214501Srpaulo wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1146214501Srpaulo 1147214501Srpaulo return wpas_dbus_new_success_reply(message); 1148214501Srpaulo} 1149214501Srpaulo 1150214501Srpaulo 1151214501Srpaulo/** 1152214501Srpaulo * wpas_dbus_iface_set_ap_scan - Control roaming mode 1153214501Srpaulo * @message: Pointer to incoming dbus message 1154214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1155214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 1156214501Srpaulo * failure (0) 1157214501Srpaulo * 1158214501Srpaulo * Handler function for "setAPScan" method call. 1159214501Srpaulo */ 1160214501SrpauloDBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message, 1161214501Srpaulo struct wpa_supplicant *wpa_s) 1162214501Srpaulo{ 1163214501Srpaulo DBusMessage *reply = NULL; 1164214501Srpaulo dbus_uint32_t ap_scan = 1; 1165214501Srpaulo 1166214501Srpaulo if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan, 1167214501Srpaulo DBUS_TYPE_INVALID)) { 1168214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, NULL); 1169214501Srpaulo goto out; 1170214501Srpaulo } 1171214501Srpaulo 1172214501Srpaulo if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 1173214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, NULL); 1174214501Srpaulo goto out; 1175214501Srpaulo } 1176214501Srpaulo 1177214501Srpaulo reply = wpas_dbus_new_success_reply(message); 1178214501Srpaulo 1179214501Srpauloout: 1180214501Srpaulo return reply; 1181214501Srpaulo} 1182214501Srpaulo 1183214501Srpaulo 1184214501Srpaulo/** 1185214501Srpaulo * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths 1186214501Srpaulo * @message: Pointer to incoming dbus message 1187214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1188214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 1189214501Srpaulo * failure (0) 1190214501Srpaulo * 1191214501Srpaulo * Handler function for "setSmartcardModules" method call. 1192214501Srpaulo */ 1193214501SrpauloDBusMessage * wpas_dbus_iface_set_smartcard_modules( 1194214501Srpaulo DBusMessage *message, struct wpa_supplicant *wpa_s) 1195214501Srpaulo{ 1196214501Srpaulo DBusMessageIter iter, iter_dict; 1197214501Srpaulo char *opensc_engine_path = NULL; 1198214501Srpaulo char *pkcs11_engine_path = NULL; 1199214501Srpaulo char *pkcs11_module_path = NULL; 1200214501Srpaulo struct wpa_dbus_dict_entry entry; 1201214501Srpaulo 1202214501Srpaulo if (!dbus_message_iter_init(message, &iter)) 1203214501Srpaulo goto error; 1204214501Srpaulo 1205214501Srpaulo if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) 1206214501Srpaulo goto error; 1207214501Srpaulo 1208214501Srpaulo while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 1209214501Srpaulo if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 1210214501Srpaulo goto error; 1211214501Srpaulo if (!strcmp(entry.key, "opensc_engine_path") && 1212214501Srpaulo (entry.type == DBUS_TYPE_STRING)) { 1213214501Srpaulo opensc_engine_path = os_strdup(entry.str_value); 1214214501Srpaulo if (opensc_engine_path == NULL) 1215214501Srpaulo goto error; 1216214501Srpaulo } else if (!strcmp(entry.key, "pkcs11_engine_path") && 1217214501Srpaulo (entry.type == DBUS_TYPE_STRING)) { 1218214501Srpaulo pkcs11_engine_path = os_strdup(entry.str_value); 1219214501Srpaulo if (pkcs11_engine_path == NULL) 1220214501Srpaulo goto error; 1221214501Srpaulo } else if (!strcmp(entry.key, "pkcs11_module_path") && 1222214501Srpaulo (entry.type == DBUS_TYPE_STRING)) { 1223214501Srpaulo pkcs11_module_path = os_strdup(entry.str_value); 1224214501Srpaulo if (pkcs11_module_path == NULL) 1225214501Srpaulo goto error; 1226214501Srpaulo } else { 1227214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 1228214501Srpaulo goto error; 1229214501Srpaulo } 1230214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 1231214501Srpaulo } 1232214501Srpaulo 1233214501Srpaulo os_free(wpa_s->conf->opensc_engine_path); 1234214501Srpaulo wpa_s->conf->opensc_engine_path = opensc_engine_path; 1235214501Srpaulo os_free(wpa_s->conf->pkcs11_engine_path); 1236214501Srpaulo wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path; 1237214501Srpaulo os_free(wpa_s->conf->pkcs11_module_path); 1238214501Srpaulo wpa_s->conf->pkcs11_module_path = pkcs11_module_path; 1239214501Srpaulo 1240214501Srpaulo wpa_sm_set_eapol(wpa_s->wpa, NULL); 1241214501Srpaulo eapol_sm_deinit(wpa_s->eapol); 1242214501Srpaulo wpa_s->eapol = NULL; 1243214501Srpaulo wpa_supplicant_init_eapol(wpa_s); 1244214501Srpaulo wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); 1245214501Srpaulo 1246214501Srpaulo return wpas_dbus_new_success_reply(message); 1247214501Srpaulo 1248214501Srpauloerror: 1249214501Srpaulo os_free(opensc_engine_path); 1250214501Srpaulo os_free(pkcs11_engine_path); 1251214501Srpaulo os_free(pkcs11_module_path); 1252214501Srpaulo return wpas_dbus_new_invalid_opts_error(message, NULL); 1253214501Srpaulo} 1254214501Srpaulo 1255214501Srpaulo 1256214501Srpaulo/** 1257214501Srpaulo * wpas_dbus_iface_get_state - Get interface state 1258214501Srpaulo * @message: Pointer to incoming dbus message 1259214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1260214501Srpaulo * Returns: A dbus message containing a STRING representing the current 1261214501Srpaulo * interface state 1262214501Srpaulo * 1263214501Srpaulo * Handler function for "state" method call. 1264214501Srpaulo */ 1265214501SrpauloDBusMessage * wpas_dbus_iface_get_state(DBusMessage *message, 1266214501Srpaulo struct wpa_supplicant *wpa_s) 1267214501Srpaulo{ 1268214501Srpaulo DBusMessage *reply = NULL; 1269214501Srpaulo const char *str_state; 1270214501Srpaulo 1271214501Srpaulo reply = dbus_message_new_method_return(message); 1272214501Srpaulo if (reply != NULL) { 1273214501Srpaulo str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 1274214501Srpaulo dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state, 1275214501Srpaulo DBUS_TYPE_INVALID); 1276214501Srpaulo } 1277214501Srpaulo 1278214501Srpaulo return reply; 1279214501Srpaulo} 1280214501Srpaulo 1281214501Srpaulo 1282214501Srpaulo/** 1283214501Srpaulo * wpas_dbus_iface_get_scanning - Get interface scanning state 1284214501Srpaulo * @message: Pointer to incoming dbus message 1285214501Srpaulo * @wpa_s: wpa_supplicant structure for a network interface 1286214501Srpaulo * Returns: A dbus message containing whether the interface is scanning 1287214501Srpaulo * 1288214501Srpaulo * Handler function for "scanning" method call. 1289214501Srpaulo */ 1290214501SrpauloDBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message, 1291214501Srpaulo struct wpa_supplicant *wpa_s) 1292214501Srpaulo{ 1293214501Srpaulo DBusMessage *reply = NULL; 1294214501Srpaulo dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 1295214501Srpaulo 1296214501Srpaulo reply = dbus_message_new_method_return(message); 1297214501Srpaulo if (reply != NULL) { 1298214501Srpaulo dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning, 1299214501Srpaulo DBUS_TYPE_INVALID); 1300214501Srpaulo } else { 1301214501Srpaulo wpa_printf(MSG_ERROR, "dbus: Not enough memory to return " 1302214501Srpaulo "scanning state"); 1303214501Srpaulo } 1304214501Srpaulo 1305214501Srpaulo return reply; 1306214501Srpaulo} 1307214501Srpaulo 1308214501Srpaulo 1309214501Srpaulo/** 1310214501Srpaulo * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates) 1311214501Srpaulo * @message: Pointer to incoming dbus message 1312214501Srpaulo * @wpa_s: %wpa_supplicant data structure 1313214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 1314214501Srpaulo * failure (0) 1315214501Srpaulo * 1316214501Srpaulo * Asks wpa_supplicant to internally store a one or more binary blobs. 1317214501Srpaulo */ 1318214501SrpauloDBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, 1319214501Srpaulo struct wpa_supplicant *wpa_s) 1320214501Srpaulo{ 1321214501Srpaulo DBusMessage *reply = NULL; 1322214501Srpaulo struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 1323214501Srpaulo DBusMessageIter iter, iter_dict; 1324214501Srpaulo 1325214501Srpaulo dbus_message_iter_init(message, &iter); 1326214501Srpaulo 1327214501Srpaulo if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) 1328214501Srpaulo return wpas_dbus_new_invalid_opts_error(message, NULL); 1329214501Srpaulo 1330214501Srpaulo while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 1331214501Srpaulo struct wpa_config_blob *blob; 1332214501Srpaulo 1333214501Srpaulo if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 1334214501Srpaulo reply = wpas_dbus_new_invalid_opts_error(message, 1335214501Srpaulo NULL); 1336214501Srpaulo break; 1337214501Srpaulo } 1338214501Srpaulo 1339214501Srpaulo if (entry.type != DBUS_TYPE_ARRAY || 1340214501Srpaulo entry.array_type != DBUS_TYPE_BYTE) { 1341214501Srpaulo reply = wpas_dbus_new_invalid_opts_error( 1342214501Srpaulo message, "Byte array expected."); 1343214501Srpaulo break; 1344214501Srpaulo } 1345214501Srpaulo 1346214501Srpaulo if ((entry.array_len <= 0) || (entry.array_len > 65536) || 1347214501Srpaulo !strlen(entry.key)) { 1348214501Srpaulo reply = wpas_dbus_new_invalid_opts_error( 1349214501Srpaulo message, "Invalid array size."); 1350214501Srpaulo break; 1351214501Srpaulo } 1352214501Srpaulo 1353214501Srpaulo blob = os_zalloc(sizeof(*blob)); 1354214501Srpaulo if (blob == NULL) { 1355214501Srpaulo reply = dbus_message_new_error( 1356214501Srpaulo message, WPAS_ERROR_ADD_ERROR, 1357214501Srpaulo "Not enough memory to add blob."); 1358214501Srpaulo break; 1359214501Srpaulo } 1360214501Srpaulo blob->data = os_zalloc(entry.array_len); 1361214501Srpaulo if (blob->data == NULL) { 1362214501Srpaulo reply = dbus_message_new_error( 1363214501Srpaulo message, WPAS_ERROR_ADD_ERROR, 1364214501Srpaulo "Not enough memory to add blob data."); 1365214501Srpaulo os_free(blob); 1366214501Srpaulo break; 1367214501Srpaulo } 1368214501Srpaulo 1369214501Srpaulo blob->name = os_strdup(entry.key); 1370214501Srpaulo blob->len = entry.array_len; 1371214501Srpaulo os_memcpy(blob->data, (u8 *) entry.bytearray_value, 1372214501Srpaulo entry.array_len); 1373214501Srpaulo if (blob->name == NULL || blob->data == NULL) { 1374214501Srpaulo wpa_config_free_blob(blob); 1375214501Srpaulo reply = dbus_message_new_error( 1376214501Srpaulo message, WPAS_ERROR_ADD_ERROR, 1377214501Srpaulo "Error adding blob."); 1378214501Srpaulo break; 1379214501Srpaulo } 1380214501Srpaulo 1381214501Srpaulo /* Success */ 1382214501Srpaulo if (!wpa_config_remove_blob(wpa_s->conf, blob->name)) 1383214501Srpaulo wpas_notify_blob_removed(wpa_s, blob->name); 1384214501Srpaulo wpa_config_set_blob(wpa_s->conf, blob); 1385214501Srpaulo wpas_notify_blob_added(wpa_s, blob->name); 1386214501Srpaulo 1387214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 1388214501Srpaulo } 1389214501Srpaulo wpa_dbus_dict_entry_clear(&entry); 1390214501Srpaulo 1391214501Srpaulo return reply ? reply : wpas_dbus_new_success_reply(message); 1392214501Srpaulo} 1393214501Srpaulo 1394214501Srpaulo 1395214501Srpaulo/** 1396214501Srpaulo * wpas_dbus_iface_remove_blob - Remove named binary blobs 1397214501Srpaulo * @message: Pointer to incoming dbus message 1398214501Srpaulo * @wpa_s: %wpa_supplicant data structure 1399214501Srpaulo * Returns: A dbus message containing a UINT32 indicating success (1) or 1400214501Srpaulo * failure (0) 1401214501Srpaulo * 1402214501Srpaulo * Asks wpa_supplicant to remove one or more previously stored binary blobs. 1403214501Srpaulo */ 1404214501SrpauloDBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, 1405214501Srpaulo struct wpa_supplicant *wpa_s) 1406214501Srpaulo{ 1407214501Srpaulo DBusMessageIter iter, array; 1408214501Srpaulo char *err_msg = NULL; 1409214501Srpaulo 1410214501Srpaulo dbus_message_iter_init(message, &iter); 1411214501Srpaulo 1412214501Srpaulo if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) || 1413214501Srpaulo (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)) 1414214501Srpaulo return wpas_dbus_new_invalid_opts_error(message, NULL); 1415214501Srpaulo 1416214501Srpaulo dbus_message_iter_recurse(&iter, &array); 1417214501Srpaulo while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { 1418214501Srpaulo const char *name; 1419214501Srpaulo 1420214501Srpaulo dbus_message_iter_get_basic(&array, &name); 1421214501Srpaulo if (!os_strlen(name)) 1422214501Srpaulo err_msg = "Invalid blob name."; 1423214501Srpaulo 1424214501Srpaulo if (wpa_config_remove_blob(wpa_s->conf, name) != 0) 1425214501Srpaulo err_msg = "Error removing blob."; 1426214501Srpaulo else 1427214501Srpaulo wpas_notify_blob_removed(wpa_s, name); 1428214501Srpaulo dbus_message_iter_next(&array); 1429214501Srpaulo } 1430214501Srpaulo 1431214501Srpaulo if (err_msg) 1432214501Srpaulo return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR, 1433214501Srpaulo err_msg); 1434214501Srpaulo 1435214501Srpaulo return wpas_dbus_new_success_reply(message); 1436214501Srpaulo} 1437