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