LCOV - code coverage report
Current view: top level - wpa_supplicant/dbus - dbus_new_handlers.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 1379 1560 88.4 %
Date: 2015-02-03 Functions: 103 103 100.0 %

          Line data    Source code
       1             : /*
       2             :  * WPA Supplicant / dbus-based control interface
       3             :  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
       4             :  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
       5             :  * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
       6             :  *
       7             :  * This software may be distributed under the terms of the BSD license.
       8             :  * See README for more details.
       9             :  */
      10             : 
      11             : #include "includes.h"
      12             : 
      13             : #include "common.h"
      14             : #include "common/ieee802_11_defs.h"
      15             : #include "eap_peer/eap_methods.h"
      16             : #include "eapol_supp/eapol_supp_sm.h"
      17             : #include "rsn_supp/wpa.h"
      18             : #include "../config.h"
      19             : #include "../wpa_supplicant_i.h"
      20             : #include "../driver_i.h"
      21             : #include "../notify.h"
      22             : #include "../bss.h"
      23             : #include "../scan.h"
      24             : #include "../autoscan.h"
      25             : #include "dbus_new_helpers.h"
      26             : #include "dbus_new.h"
      27             : #include "dbus_new_handlers.h"
      28             : #include "dbus_dict_helpers.h"
      29             : #include "dbus_common_i.h"
      30             : #include "drivers/driver.h"
      31             : 
      32             : static const char * const debug_strings[] = {
      33             :         "excessive", "msgdump", "debug", "info", "warning", "error", NULL
      34             : };
      35             : 
      36             : 
      37             : /**
      38             :  * wpas_dbus_error_unknown_error - Return a new UnknownError error message
      39             :  * @message: Pointer to incoming dbus message this error refers to
      40             :  * @arg: Optional string appended to error message
      41             :  * Returns: a dbus error message
      42             :  *
      43             :  * Convenience function to create and return an UnknownError
      44             :  */
      45          33 : DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
      46             :                                             const char *arg)
      47             : {
      48          33 :         return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
      49             :                                       arg);
      50             : }
      51             : 
      52             : 
      53             : /**
      54             :  * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
      55             :  * @message: Pointer to incoming dbus message this error refers to
      56             :  * Returns: A dbus error message
      57             :  *
      58             :  * Convenience function to create and return an invalid interface error
      59             :  */
      60           2 : static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
      61             : {
      62           2 :         return dbus_message_new_error(
      63             :                 message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
      64             :                 "wpa_supplicant knows nothing about this interface.");
      65             : }
      66             : 
      67             : 
      68             : /**
      69             :  * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
      70             :  * @message: Pointer to incoming dbus message this error refers to
      71             :  * Returns: a dbus error message
      72             :  *
      73             :  * Convenience function to create and return an invalid network error
      74             :  */
      75           2 : static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
      76             : {
      77           2 :         return dbus_message_new_error(
      78             :                 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
      79             :                 "There is no such a network in this interface.");
      80             : }
      81             : 
      82             : 
      83             : /**
      84             :  * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
      85             :  * @message: Pointer to incoming dbus message this error refers to
      86             :  * Returns: a dbus error message
      87             :  *
      88             :  * Convenience function to create and return an invalid options error
      89             :  */
      90         118 : DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
      91             :                                           const char *arg)
      92             : {
      93             :         DBusMessage *reply;
      94             : 
      95         118 :         reply = dbus_message_new_error(
      96             :                 message, WPAS_DBUS_ERROR_INVALID_ARGS,
      97             :                 "Did not receive correct message arguments.");
      98         118 :         if (arg != NULL)
      99          40 :                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
     100             :                                          DBUS_TYPE_INVALID);
     101             : 
     102         118 :         return reply;
     103             : }
     104             : 
     105             : 
     106             : /**
     107             :  * wpas_dbus_error_scan_error - Return a new ScanError error message
     108             :  * @message: Pointer to incoming dbus message this error refers to
     109             :  * @error: Optional string to be used as the error message
     110             :  * Returns: a dbus error message
     111             :  *
     112             :  * Convenience function to create and return a scan error
     113             :  */
     114           2 : static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
     115             :                                                 const char *error)
     116             : {
     117           2 :         return dbus_message_new_error(message,
     118             :                                       WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
     119             :                                       error);
     120             : }
     121             : 
     122             : 
     123          12 : DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
     124             : {
     125          12 :         wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
     126          12 :         return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
     127             : }
     128             : 
     129             : 
     130             : static const char * const dont_quote[] = {
     131             :         "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
     132             :         "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
     133             :         "bssid", "scan_freq", "freq_list", NULL
     134             : };
     135             : 
     136         165 : static dbus_bool_t should_quote_opt(const char *key)
     137             : {
     138         165 :         int i = 0;
     139             : 
     140        1680 :         while (dont_quote[i] != NULL) {
     141        1405 :                 if (os_strcmp(key, dont_quote[i]) == 0)
     142          55 :                         return FALSE;
     143        1350 :                 i++;
     144             :         }
     145         110 :         return TRUE;
     146             : }
     147             : 
     148             : /**
     149             :  * get_iface_by_dbus_path - Get a new network interface
     150             :  * @global: Pointer to global data from wpa_supplicant_init()
     151             :  * @path: Pointer to a dbus object path representing an interface
     152             :  * Returns: Pointer to the interface or %NULL if not found
     153             :  */
     154          20 : static struct wpa_supplicant * get_iface_by_dbus_path(
     155             :         struct wpa_global *global, const char *path)
     156             : {
     157             :         struct wpa_supplicant *wpa_s;
     158             : 
     159          21 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
     160          20 :                 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
     161          19 :                         return wpa_s;
     162             :         }
     163           1 :         return NULL;
     164             : }
     165             : 
     166             : 
     167             : /**
     168             :  * set_network_properties - Set properties of a configured network
     169             :  * @wpa_s: wpa_supplicant structure for a network interface
     170             :  * @ssid: wpa_ssid structure for a configured network
     171             :  * @iter: DBus message iterator containing dictionary of network
     172             :  * properties to set.
     173             :  * @error: On failure, an error describing the failure
     174             :  * Returns: TRUE if the request succeeds, FALSE if it failed
     175             :  *
     176             :  * Sets network configuration with parameters given id DBus dictionary
     177             :  */
     178          66 : dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
     179             :                                    struct wpa_ssid *ssid,
     180             :                                    DBusMessageIter *iter,
     181             :                                    DBusError *error)
     182             : {
     183          66 :         struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
     184             :         DBusMessageIter iter_dict;
     185          66 :         char *value = NULL;
     186             : 
     187          66 :         if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
     188           0 :                 return FALSE;
     189             : 
     190         341 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     191         219 :                 size_t size = 50;
     192             :                 int ret;
     193             : 
     194         219 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
     195           1 :                         goto error;
     196             : 
     197         218 :                 value = NULL;
     198         221 :                 if (entry.type == DBUS_TYPE_ARRAY &&
     199           3 :                     entry.array_type == DBUS_TYPE_BYTE) {
     200           3 :                         if (entry.array_len <= 0)
     201           1 :                                 goto error;
     202             : 
     203           2 :                         size = entry.array_len * 2 + 1;
     204           2 :                         value = os_zalloc(size);
     205           2 :                         if (value == NULL)
     206           1 :                                 goto error;
     207             : 
     208           2 :                         ret = wpa_snprintf_hex(value, size,
     209           1 :                                                (u8 *) entry.bytearray_value,
     210           1 :                                                entry.array_len);
     211           2 :                         if (ret <= 0)
     212           0 :                                 goto error;
     213         215 :                 } else if (entry.type == DBUS_TYPE_STRING) {
     214         165 :                         if (should_quote_opt(entry.key)) {
     215         110 :                                 size = os_strlen(entry.str_value);
     216         110 :                                 if (size <= 0)
     217           1 :                                         goto error;
     218             : 
     219         109 :                                 size += 3;
     220         109 :                                 value = os_zalloc(size);
     221         109 :                                 if (value == NULL)
     222           1 :                                         goto error;
     223             : 
     224         108 :                                 ret = os_snprintf(value, size, "\"%s\"",
     225             :                                                   entry.str_value);
     226         108 :                                 if (os_snprintf_error(size, ret))
     227           0 :                                         goto error;
     228             :                         } else {
     229          55 :                                 value = os_strdup(entry.str_value);
     230          55 :                                 if (value == NULL)
     231           1 :                                         goto error;
     232             :                         }
     233          50 :                 } else if (entry.type == DBUS_TYPE_UINT32) {
     234           2 :                         value = os_zalloc(size);
     235           2 :                         if (value == NULL)
     236           1 :                                 goto error;
     237             : 
     238           1 :                         ret = os_snprintf(value, size, "%u",
     239             :                                           entry.uint32_value);
     240           1 :                         if (os_snprintf_error(size, ret))
     241           0 :                                 goto error;
     242          48 :                 } else if (entry.type == DBUS_TYPE_INT32) {
     243          47 :                         value = os_zalloc(size);
     244          47 :                         if (value == NULL)
     245           1 :                                 goto error;
     246             : 
     247          46 :                         ret = os_snprintf(value, size, "%d",
     248             :                                           entry.int32_value);
     249          46 :                         if (os_snprintf_error(size, ret))
     250           0 :                                 goto error;
     251             :                 } else
     252           1 :                         goto error;
     253             : 
     254         210 :                 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
     255           1 :                         goto error;
     256             : 
     257         418 :                 if (os_strcmp(entry.key, "bssid") != 0 &&
     258         209 :                     os_strcmp(entry.key, "priority") != 0)
     259         208 :                         wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
     260             : 
     261         417 :                 if (wpa_s->current_ssid == ssid ||
     262         208 :                     wpa_s->current_ssid == NULL) {
     263             :                         /*
     264             :                          * Invalidate the EAP session cache if anything in the
     265             :                          * current or previously used configuration changes.
     266             :                          */
     267         205 :                         eapol_sm_invalidate_cached_session(wpa_s->eapol);
     268             :                 }
     269             : 
     270         254 :                 if ((os_strcmp(entry.key, "psk") == 0 &&
     271         299 :                      value[0] == '"' && ssid->ssid_len) ||
     272         263 :                     (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
     273          46 :                         wpa_config_update_psk(ssid);
     274         163 :                 else if (os_strcmp(entry.key, "priority") == 0)
     275           1 :                         wpa_config_update_prio_list(wpa_s->conf);
     276             : 
     277         209 :                 os_free(value);
     278         209 :                 value = NULL;
     279         209 :                 wpa_dbus_dict_entry_clear(&entry);
     280             :         }
     281             : 
     282          56 :         return TRUE;
     283             : 
     284             : error:
     285          10 :         os_free(value);
     286          10 :         wpa_dbus_dict_entry_clear(&entry);
     287          10 :         dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
     288             :                              "invalid message format");
     289          10 :         return FALSE;
     290             : }
     291             : 
     292             : 
     293             : /**
     294             :  * wpas_dbus_simple_property_getter - Get basic type property
     295             :  * @iter: Message iter to use when appending arguments
     296             :  * @type: DBus type of property (must be basic type)
     297             :  * @val: pointer to place holding property value
     298             :  * @error: On failure an error describing the failure
     299             :  * Returns: TRUE if the request was successful, FALSE if it failed
     300             :  *
     301             :  * Generic getter for basic type properties. Type is required to be basic.
     302             :  */
     303       56742 : dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
     304             :                                              const int type,
     305             :                                              const void *val,
     306             :                                              DBusError *error)
     307             : {
     308             :         DBusMessageIter variant_iter;
     309             : 
     310       56742 :         if (!dbus_type_is_basic(type)) {
     311           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     312             :                                "%s: given type is not basic", __func__);
     313           0 :                 return FALSE;
     314             :         }
     315             : 
     316       56742 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
     317             :                                               wpa_dbus_type_as_string(type),
     318       56742 :                                               &variant_iter) ||
     319      113484 :             !dbus_message_iter_append_basic(&variant_iter, type, val) ||
     320       56742 :             !dbus_message_iter_close_container(iter, &variant_iter)) {
     321           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     322             :                                "%s: error constructing reply", __func__);
     323           0 :                 return FALSE;
     324             :         }
     325             : 
     326       56742 :         return TRUE;
     327             : }
     328             : 
     329             : 
     330             : /**
     331             :  * wpas_dbus_simple_property_setter - Set basic type property
     332             :  * @message: Pointer to incoming dbus message
     333             :  * @type: DBus type of property (must be basic type)
     334             :  * @val: pointer to place where value being set will be stored
     335             :  * Returns: TRUE if the request was successful, FALSE if it failed
     336             :  *
     337             :  * Generic setter for basic type properties. Type is required to be basic.
     338             :  */
     339          43 : dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
     340             :                                              DBusError *error,
     341             :                                              const int type, void *val)
     342             : {
     343             :         DBusMessageIter variant_iter;
     344             : 
     345          43 :         if (!dbus_type_is_basic(type)) {
     346           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     347             :                                "%s: given type is not basic", __func__);
     348           0 :                 return FALSE;
     349             :         }
     350             : 
     351             :         /* Look at the new value */
     352          43 :         dbus_message_iter_recurse(iter, &variant_iter);
     353          43 :         if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
     354          10 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
     355             :                                      "wrong property type");
     356          10 :                 return FALSE;
     357             :         }
     358          33 :         dbus_message_iter_get_basic(&variant_iter, val);
     359             : 
     360          33 :         return TRUE;
     361             : }
     362             : 
     363             : 
     364             : /**
     365             :  * wpas_dbus_simple_array_property_getter - Get array type property
     366             :  * @iter: Pointer to incoming dbus message iterator
     367             :  * @type: DBus type of property array elements (must be basic type)
     368             :  * @array: pointer to array of elements to put into response message
     369             :  * @array_len: length of above array
     370             :  * @error: a pointer to an error to fill on failure
     371             :  * Returns: TRUE if the request succeeded, FALSE if it failed
     372             :  *
     373             :  * Generic getter for array type properties. Array elements type is
     374             :  * required to be basic.
     375             :  */
     376        8314 : dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
     377             :                                                    const int type,
     378             :                                                    const void *array,
     379             :                                                    size_t array_len,
     380             :                                                    DBusError *error)
     381             : {
     382             :         DBusMessageIter variant_iter, array_iter;
     383        8314 :         char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
     384             :         const char *sub_type_str;
     385             :         size_t element_size, i;
     386             : 
     387        8314 :         if (!dbus_type_is_basic(type)) {
     388           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     389             :                                "%s: given type is not basic", __func__);
     390           0 :                 return FALSE;
     391             :         }
     392             : 
     393        8314 :         sub_type_str = wpa_dbus_type_as_string(type);
     394        8314 :         type_str[1] = sub_type_str[0];
     395             : 
     396        8314 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
     397        8314 :                                               type_str, &variant_iter) ||
     398        8314 :             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
     399             :                                               sub_type_str, &array_iter)) {
     400           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     401             :                                "%s: failed to construct message", __func__);
     402           0 :                 return FALSE;
     403             :         }
     404             : 
     405        8314 :         switch (type) {
     406             :         case DBUS_TYPE_BYTE:
     407             :         case DBUS_TYPE_BOOLEAN:
     408        3143 :                 element_size = 1;
     409        3143 :                 break;
     410             :         case DBUS_TYPE_INT16:
     411             :         case DBUS_TYPE_UINT16:
     412           0 :                 element_size = sizeof(uint16_t);
     413           0 :                 break;
     414             :         case DBUS_TYPE_INT32:
     415             :         case DBUS_TYPE_UINT32:
     416        1007 :                 element_size = sizeof(uint32_t);
     417        1007 :                 break;
     418             :         case DBUS_TYPE_INT64:
     419             :         case DBUS_TYPE_UINT64:
     420           0 :                 element_size = sizeof(uint64_t);
     421           0 :                 break;
     422             :         case DBUS_TYPE_DOUBLE:
     423           0 :                 element_size = sizeof(double);
     424           0 :                 break;
     425             :         case DBUS_TYPE_STRING:
     426             :         case DBUS_TYPE_OBJECT_PATH:
     427        4164 :                 element_size = sizeof(char *);
     428        4164 :                 break;
     429             :         default:
     430           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     431             :                                "%s: unknown element type %d", __func__, type);
     432           0 :                 return FALSE;
     433             :         }
     434             : 
     435      223055 :         for (i = 0; i < array_len; i++) {
     436      214741 :                 if (!dbus_message_iter_append_basic(&array_iter, type,
     437      214741 :                                                     array + i * element_size)) {
     438           0 :                         dbus_set_error(error, DBUS_ERROR_FAILED,
     439             :                                        "%s: failed to construct message 2.5",
     440             :                                        __func__);
     441           0 :                         return FALSE;
     442             :                 }
     443             :         }
     444             : 
     445       16628 :         if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
     446        8314 :             !dbus_message_iter_close_container(iter, &variant_iter)) {
     447           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     448             :                                "%s: failed to construct message 3", __func__);
     449           0 :                 return FALSE;
     450             :         }
     451             : 
     452        8314 :         return TRUE;
     453             : }
     454             : 
     455             : 
     456             : /**
     457             :  * wpas_dbus_simple_array_array_property_getter - Get array array type property
     458             :  * @iter: Pointer to incoming dbus message iterator
     459             :  * @type: DBus type of property array elements (must be basic type)
     460             :  * @array: pointer to array of elements to put into response message
     461             :  * @array_len: length of above array
     462             :  * @error: a pointer to an error to fill on failure
     463             :  * Returns: TRUE if the request succeeded, FALSE if it failed
     464             :  *
     465             :  * Generic getter for array type properties. Array elements type is
     466             :  * required to be basic.
     467             :  */
     468          16 : dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
     469             :                                                          const int type,
     470             :                                                          struct wpabuf **array,
     471             :                                                          size_t array_len,
     472             :                                                          DBusError *error)
     473             : {
     474             :         DBusMessageIter variant_iter, array_iter;
     475          16 :         char type_str[] = "aa?";
     476          16 :         char inner_type_str[] = "a?";
     477             :         const char *sub_type_str;
     478             :         size_t i;
     479             : 
     480          16 :         if (!dbus_type_is_basic(type)) {
     481           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     482             :                                "%s: given type is not basic", __func__);
     483           0 :                 return FALSE;
     484             :         }
     485             : 
     486          16 :         sub_type_str = wpa_dbus_type_as_string(type);
     487          16 :         type_str[2] = sub_type_str[0];
     488          16 :         inner_type_str[1] = sub_type_str[0];
     489             : 
     490          16 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
     491          16 :                                               type_str, &variant_iter) ||
     492          16 :             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
     493             :                                               inner_type_str, &array_iter)) {
     494           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     495             :                                "%s: failed to construct message", __func__);
     496           0 :                 return FALSE;
     497             :         }
     498             : 
     499          20 :         for (i = 0; i < array_len && array[i]; i++) {
     500           8 :                 wpa_dbus_dict_bin_array_add_element(&array_iter,
     501           4 :                                                     wpabuf_head(array[i]),
     502           4 :                                                     wpabuf_len(array[i]));
     503             : 
     504             :         }
     505             : 
     506          32 :         if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
     507          16 :             !dbus_message_iter_close_container(iter, &variant_iter)) {
     508           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
     509             :                                "%s: failed to close message", __func__);
     510           0 :                 return FALSE;
     511             :         }
     512             : 
     513          16 :         return TRUE;
     514             : }
     515             : 
     516             : 
     517             : /**
     518             :  * wpas_dbus_handler_create_interface - Request registration of a network iface
     519             :  * @message: Pointer to incoming dbus message
     520             :  * @global: %wpa_supplicant global data structure
     521             :  * Returns: The object path of the new interface object,
     522             :  *          or a dbus error message with more information
     523             :  *
     524             :  * Handler function for "CreateInterface" method call. Handles requests
     525             :  * by dbus clients to register a network interface that wpa_supplicant
     526             :  * will manage.
     527             :  */
     528          47 : DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
     529             :                                                  struct wpa_global *global)
     530             : {
     531             :         DBusMessageIter iter_dict;
     532          47 :         DBusMessage *reply = NULL;
     533             :         DBusMessageIter iter;
     534             :         struct wpa_dbus_dict_entry entry;
     535          47 :         char *driver = NULL;
     536          47 :         char *ifname = NULL;
     537          47 :         char *confname = NULL;
     538          47 :         char *bridge_ifname = NULL;
     539             : 
     540          47 :         dbus_message_iter_init(message, &iter);
     541             : 
     542          47 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
     543           0 :                 goto error;
     544         178 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     545          90 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
     546           1 :                         goto error;
     547         131 :                 if (os_strcmp(entry.key, "Driver") == 0 &&
     548          42 :                     entry.type == DBUS_TYPE_STRING) {
     549          42 :                         os_free(driver);
     550          42 :                         driver = os_strdup(entry.str_value);
     551          42 :                         wpa_dbus_dict_entry_clear(&entry);
     552          83 :                         if (driver == NULL)
     553           1 :                                 goto oom;
     554          89 :                 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
     555          42 :                            entry.type == DBUS_TYPE_STRING) {
     556          42 :                         os_free(ifname);
     557          42 :                         ifname = os_strdup(entry.str_value);
     558          42 :                         wpa_dbus_dict_entry_clear(&entry);
     559          83 :                         if (ifname == NULL)
     560           1 :                                 goto oom;
     561           7 :                 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
     562           2 :                            entry.type == DBUS_TYPE_STRING) {
     563           2 :                         os_free(confname);
     564           2 :                         confname = os_strdup(entry.str_value);
     565           2 :                         wpa_dbus_dict_entry_clear(&entry);
     566           3 :                         if (confname == NULL)
     567           1 :                                 goto oom;
     568           5 :                 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
     569           2 :                            entry.type == DBUS_TYPE_STRING) {
     570           2 :                         os_free(bridge_ifname);
     571           2 :                         bridge_ifname = os_strdup(entry.str_value);
     572           2 :                         wpa_dbus_dict_entry_clear(&entry);
     573           3 :                         if (bridge_ifname == NULL)
     574           1 :                                 goto oom;
     575             :                 } else {
     576           1 :                         wpa_dbus_dict_entry_clear(&entry);
     577           1 :                         goto error;
     578             :                 }
     579             :         }
     580             : 
     581          41 :         if (ifname == NULL)
     582           1 :                 goto error; /* Required Ifname argument missing */
     583             : 
     584             :         /*
     585             :          * Try to get the wpa_supplicant record for this iface, return
     586             :          * an error if we already control it.
     587             :          */
     588          40 :         if (wpa_supplicant_get_iface(global, ifname) != NULL) {
     589           1 :                 reply = dbus_message_new_error(
     590             :                         message, WPAS_DBUS_ERROR_IFACE_EXISTS,
     591             :                         "wpa_supplicant already controls this interface.");
     592             :         } else {
     593             :                 struct wpa_supplicant *wpa_s;
     594             :                 struct wpa_interface iface;
     595             : 
     596          39 :                 os_memset(&iface, 0, sizeof(iface));
     597          39 :                 iface.driver = driver;
     598          39 :                 iface.ifname = ifname;
     599          39 :                 iface.confname = confname;
     600          39 :                 iface.bridge_ifname = bridge_ifname;
     601             :                 /* Otherwise, have wpa_supplicant attach to it. */
     602          39 :                 wpa_s = wpa_supplicant_add_iface(global, &iface);
     603          39 :                 if (wpa_s) {
     604          19 :                         const char *path = wpa_s->dbus_new_path;
     605             : 
     606          19 :                         reply = dbus_message_new_method_return(message);
     607          19 :                         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
     608             :                                                  &path, DBUS_TYPE_INVALID);
     609             :                 } else {
     610          20 :                         reply = wpas_dbus_error_unknown_error(
     611             :                                 message,
     612             :                                 "wpa_supplicant couldn't grab this interface.");
     613             :                 }
     614             :         }
     615             : 
     616             : out:
     617          47 :         os_free(driver);
     618          47 :         os_free(ifname);
     619          47 :         os_free(confname);
     620          47 :         os_free(bridge_ifname);
     621          94 :         return reply;
     622             : 
     623             : error:
     624           3 :         reply = wpas_dbus_error_invalid_args(message, NULL);
     625           3 :         goto out;
     626             : oom:
     627           4 :         reply = wpas_dbus_error_no_memory(message);
     628           4 :         goto out;
     629             : }
     630             : 
     631             : 
     632             : /**
     633             :  * wpas_dbus_handler_remove_interface - Request deregistration of an interface
     634             :  * @message: Pointer to incoming dbus message
     635             :  * @global: wpa_supplicant global data structure
     636             :  * Returns: a dbus message containing a UINT32 indicating success (1) or
     637             :  *          failure (0), or returns a dbus error message with more information
     638             :  *
     639             :  * Handler function for "removeInterface" method call.  Handles requests
     640             :  * by dbus clients to deregister a network interface that wpa_supplicant
     641             :  * currently manages.
     642             :  */
     643          20 : DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
     644             :                                                  struct wpa_global *global)
     645             : {
     646             :         struct wpa_supplicant *wpa_s;
     647             :         char *path;
     648          20 :         DBusMessage *reply = NULL;
     649             : 
     650          20 :         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
     651             :                               DBUS_TYPE_INVALID);
     652             : 
     653          20 :         wpa_s = get_iface_by_dbus_path(global, path);
     654          20 :         if (wpa_s == NULL)
     655           1 :                 reply = wpas_dbus_error_iface_unknown(message);
     656          19 :         else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
     657           0 :                 reply = wpas_dbus_error_unknown_error(
     658             :                         message,
     659             :                         "wpa_supplicant couldn't remove this interface.");
     660             :         }
     661             : 
     662          20 :         return reply;
     663             : }
     664             : 
     665             : 
     666             : /**
     667             :  * wpas_dbus_handler_get_interface - Get the object path for an interface name
     668             :  * @message: Pointer to incoming dbus message
     669             :  * @global: %wpa_supplicant global data structure
     670             :  * Returns: The object path of the interface object,
     671             :  *          or a dbus error message with more information
     672             :  *
     673             :  * Handler function for "getInterface" method call.
     674             :  */
     675          59 : DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
     676             :                                               struct wpa_global *global)
     677             : {
     678          59 :         DBusMessage *reply = NULL;
     679             :         const char *ifname;
     680             :         const char *path;
     681             :         struct wpa_supplicant *wpa_s;
     682             : 
     683          59 :         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
     684             :                               DBUS_TYPE_INVALID);
     685             : 
     686          59 :         wpa_s = wpa_supplicant_get_iface(global, ifname);
     687          59 :         if (wpa_s == NULL)
     688           1 :                 return wpas_dbus_error_iface_unknown(message);
     689             : 
     690          58 :         path = wpa_s->dbus_new_path;
     691          58 :         reply = dbus_message_new_method_return(message);
     692          58 :         if (reply == NULL)
     693           0 :                 return wpas_dbus_error_no_memory(message);
     694          58 :         if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
     695             :                                       DBUS_TYPE_INVALID)) {
     696           0 :                 dbus_message_unref(reply);
     697           0 :                 return wpas_dbus_error_no_memory(message);
     698             :         }
     699             : 
     700          58 :         return reply;
     701             : }
     702             : 
     703             : 
     704             : /**
     705             :  * wpas_dbus_getter_debug_level - Get debug level
     706             :  * @iter: Pointer to incoming dbus message iter
     707             :  * @error: Location to store error on failure
     708             :  * @user_data: Function specific data
     709             :  * Returns: TRUE on success, FALSE on failure
     710             :  *
     711             :  * Getter for "DebugLevel" property.
     712             :  */
     713           8 : dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
     714             :                                          DBusError *error,
     715             :                                          void *user_data)
     716             : {
     717             :         const char *str;
     718           8 :         int idx = wpa_debug_level;
     719             : 
     720           8 :         if (idx < 0)
     721           0 :                 idx = 0;
     722           8 :         if (idx > 5)
     723           0 :                 idx = 5;
     724           8 :         str = debug_strings[idx];
     725           8 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
     726             :                                                 &str, error);
     727             : }
     728             : 
     729             : 
     730             : /**
     731             :  * wpas_dbus_getter_debug_timestamp - Get debug timestamp
     732             :  * @iter: Pointer to incoming dbus message iter
     733             :  * @error: Location to store error on failure
     734             :  * @user_data: Function specific data
     735             :  * Returns: TRUE on success, FALSE on failure
     736             :  *
     737             :  * Getter for "DebugTimestamp" property.
     738             :  */
     739           8 : dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
     740             :                                              DBusError *error,
     741             :                                              void *user_data)
     742             : {
     743           8 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
     744             :                                                 &wpa_debug_timestamp, error);
     745             : 
     746             : }
     747             : 
     748             : 
     749             : /**
     750             :  * wpas_dbus_getter_debug_show_keys - Get debug show keys
     751             :  * @iter: Pointer to incoming dbus message iter
     752             :  * @error: Location to store error on failure
     753             :  * @user_data: Function specific data
     754             :  * Returns: TRUE on success, FALSE on failure
     755             :  *
     756             :  * Getter for "DebugShowKeys" property.
     757             :  */
     758           8 : dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
     759             :                                              DBusError *error,
     760             :                                              void *user_data)
     761             : {
     762           8 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
     763             :                                                 &wpa_debug_show_keys, error);
     764             : 
     765             : }
     766             : 
     767             : /**
     768             :  * wpas_dbus_setter_debug_level - Set debug level
     769             :  * @iter: Pointer to incoming dbus message iter
     770             :  * @error: Location to store error on failure
     771             :  * @user_data: Function specific data
     772             :  * Returns: TRUE on success, FALSE on failure
     773             :  *
     774             :  * Setter for "DebugLevel" property.
     775             :  */
     776           4 : dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
     777             :                                          DBusError *error, void *user_data)
     778             : {
     779           4 :         struct wpa_global *global = user_data;
     780           4 :         const char *str = NULL;
     781           4 :         int i, val = -1;
     782             : 
     783           4 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
     784             :                                               &str))
     785           1 :                 return FALSE;
     786             : 
     787          12 :         for (i = 0; debug_strings[i]; i++)
     788          11 :                 if (os_strcmp(debug_strings[i], str) == 0) {
     789           2 :                         val = i;
     790           2 :                         break;
     791             :                 }
     792             : 
     793           5 :         if (val < 0 ||
     794           2 :             wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
     795             :                                             wpa_debug_show_keys)) {
     796           1 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
     797             :                                      "wrong debug level value");
     798           1 :                 return FALSE;
     799             :         }
     800             : 
     801           2 :         return TRUE;
     802             : }
     803             : 
     804             : 
     805             : /**
     806             :  * wpas_dbus_setter_debug_timestamp - Set debug timestamp
     807             :  * @iter: Pointer to incoming dbus message iter
     808             :  * @error: Location to store error on failure
     809             :  * @user_data: Function specific data
     810             :  * Returns: TRUE on success, FALSE on failure
     811             :  *
     812             :  * Setter for "DebugTimestamp" property.
     813             :  */
     814           3 : dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
     815             :                                              DBusError *error,
     816             :                                              void *user_data)
     817             : {
     818           3 :         struct wpa_global *global = user_data;
     819             :         dbus_bool_t val;
     820             : 
     821           3 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
     822             :                                               &val))
     823           1 :                 return FALSE;
     824             : 
     825           2 :         wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
     826             :                                         wpa_debug_show_keys);
     827           2 :         return TRUE;
     828             : }
     829             : 
     830             : 
     831             : /**
     832             :  * wpas_dbus_setter_debug_show_keys - Set debug show keys
     833             :  * @iter: Pointer to incoming dbus message iter
     834             :  * @error: Location to store error on failure
     835             :  * @user_data: Function specific data
     836             :  * Returns: TRUE on success, FALSE on failure
     837             :  *
     838             :  * Setter for "DebugShowKeys" property.
     839             :  */
     840           3 : dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
     841             :                                              DBusError *error,
     842             :                                              void *user_data)
     843             : {
     844           3 :         struct wpa_global *global = user_data;
     845             :         dbus_bool_t val;
     846             : 
     847           3 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
     848             :                                               &val))
     849           1 :                 return FALSE;
     850             : 
     851           2 :         wpa_supplicant_set_debug_params(global, wpa_debug_level,
     852             :                                         wpa_debug_timestamp,
     853             :                                         val ? 1 : 0);
     854           2 :         return TRUE;
     855             : }
     856             : 
     857             : 
     858             : /**
     859             :  * wpas_dbus_getter_interfaces - Request registered interfaces list
     860             :  * @iter: Pointer to incoming dbus message iter
     861             :  * @error: Location to store error on failure
     862             :  * @user_data: Function specific data
     863             :  * Returns: TRUE on success, FALSE on failure
     864             :  *
     865             :  * Getter for "Interfaces" property. Handles requests
     866             :  * by dbus clients to return list of registered interfaces objects
     867             :  * paths
     868             :  */
     869           3 : dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
     870             :                                         DBusError *error,
     871             :                                         void *user_data)
     872             : {
     873           3 :         struct wpa_global *global = user_data;
     874             :         struct wpa_supplicant *wpa_s;
     875             :         const char **paths;
     876           3 :         unsigned int i = 0, num = 0;
     877             :         dbus_bool_t success;
     878             : 
     879           6 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
     880           3 :                 num++;
     881             : 
     882           3 :         paths = os_calloc(num, sizeof(char *));
     883           3 :         if (!paths) {
     884           1 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
     885           1 :                 return FALSE;
     886             :         }
     887             : 
     888           4 :         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
     889           2 :                 paths[i++] = wpa_s->dbus_new_path;
     890             : 
     891           2 :         success = wpas_dbus_simple_array_property_getter(iter,
     892             :                                                          DBUS_TYPE_OBJECT_PATH,
     893             :                                                          paths, num, error);
     894             : 
     895           2 :         os_free(paths);
     896           2 :         return success;
     897             : }
     898             : 
     899             : 
     900             : /**
     901             :  * wpas_dbus_getter_eap_methods - Request supported EAP methods list
     902             :  * @iter: Pointer to incoming dbus message iter
     903             :  * @error: Location to store error on failure
     904             :  * @user_data: Function specific data
     905             :  * Returns: TRUE on success, FALSE on failure
     906             :  *
     907             :  * Getter for "EapMethods" property. Handles requests
     908             :  * by dbus clients to return list of strings with supported EAP methods
     909             :  */
     910           8 : dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
     911             :                                          DBusError *error, void *user_data)
     912             : {
     913             :         char **eap_methods;
     914           8 :         size_t num_items = 0;
     915             :         dbus_bool_t success;
     916             : 
     917           8 :         eap_methods = eap_get_names_as_string_array(&num_items);
     918           8 :         if (!eap_methods) {
     919           5 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
     920           5 :                 return FALSE;
     921             :         }
     922             : 
     923           3 :         success = wpas_dbus_simple_array_property_getter(iter,
     924             :                                                          DBUS_TYPE_STRING,
     925             :                                                          eap_methods,
     926             :                                                          num_items, error);
     927             : 
     928          78 :         while (num_items)
     929          72 :                 os_free(eap_methods[--num_items]);
     930           3 :         os_free(eap_methods);
     931           3 :         return success;
     932             : }
     933             : 
     934             : 
     935             : /**
     936             :  * wpas_dbus_getter_global_capabilities - Request supported global capabilities
     937             :  * @iter: Pointer to incoming dbus message iter
     938             :  * @error: Location to store error on failure
     939             :  * @user_data: Function specific data
     940             :  * Returns: TRUE on success, FALSE on failure
     941             :  *
     942             :  * Getter for "Capabilities" property. Handles requests by dbus clients to
     943             :  * return a list of strings with supported capabilities like AP, RSN IBSS,
     944             :  * and P2P that are determined at compile time.
     945             :  */
     946           2 : dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
     947             :                                                  DBusError *error,
     948             :                                                  void *user_data)
     949             : {
     950           2 :         const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
     951           2 :         size_t num_items = 0;
     952             : 
     953             : #ifdef CONFIG_AP
     954           2 :         capabilities[num_items++] = "ap";
     955             : #endif /* CONFIG_AP */
     956             : #ifdef CONFIG_IBSS_RSN
     957           2 :         capabilities[num_items++] = "ibss-rsn";
     958             : #endif /* CONFIG_IBSS_RSN */
     959             : #ifdef CONFIG_P2P
     960           2 :         capabilities[num_items++] = "p2p";
     961             : #endif /* CONFIG_P2P */
     962             : #ifdef CONFIG_INTERWORKING
     963           2 :         capabilities[num_items++] = "interworking";
     964             : #endif /* CONFIG_INTERWORKING */
     965             : 
     966           2 :         return wpas_dbus_simple_array_property_getter(iter,
     967             :                                                       DBUS_TYPE_STRING,
     968             :                                                       capabilities,
     969             :                                                       num_items, error);
     970             : }
     971             : 
     972             : 
     973          15 : static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
     974             :                                    char **type, DBusMessage **reply)
     975             : {
     976          15 :         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
     977           1 :                 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
     978             :                            __func__);
     979           1 :                 *reply = wpas_dbus_error_invalid_args(
     980             :                         message, "Wrong Type value type. String required");
     981           1 :                 return -1;
     982             :         }
     983          14 :         dbus_message_iter_get_basic(var, type);
     984          14 :         return 0;
     985             : }
     986             : 
     987             : 
     988           7 : static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
     989             :                                     struct wpa_driver_scan_params *params,
     990             :                                     DBusMessage **reply)
     991             : {
     992           7 :         struct wpa_driver_scan_ssid *ssids = params->ssids;
     993           7 :         size_t ssids_num = 0;
     994             :         u8 *ssid;
     995             :         DBusMessageIter array_iter, sub_array_iter;
     996             :         char *val;
     997             :         int len;
     998             : 
     999           7 :         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
    1000           1 :                 wpa_printf(MSG_DEBUG,
    1001             :                            "%s[dbus]: ssids must be an array of arrays of bytes",
    1002             :                            __func__);
    1003           1 :                 *reply = wpas_dbus_error_invalid_args(
    1004             :                         message,
    1005             :                         "Wrong SSIDs value type. Array of arrays of bytes required");
    1006           1 :                 return -1;
    1007             :         }
    1008             : 
    1009           6 :         dbus_message_iter_recurse(var, &array_iter);
    1010             : 
    1011          11 :         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
    1012           5 :             dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
    1013           1 :                 wpa_printf(MSG_DEBUG,
    1014             :                            "%s[dbus]: ssids must be an array of arrays of bytes",
    1015             :                            __func__);
    1016           1 :                 *reply = wpas_dbus_error_invalid_args(
    1017             :                         message,
    1018             :                         "Wrong SSIDs value type. Array of arrays of bytes required");
    1019           1 :                 return -1;
    1020             :         }
    1021             : 
    1022          29 :         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
    1023          22 :                 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
    1024           1 :                         wpa_printf(MSG_DEBUG,
    1025             :                                    "%s[dbus]: Too many ssids specified on scan dbus call",
    1026             :                                    __func__);
    1027           1 :                         *reply = wpas_dbus_error_invalid_args(
    1028             :                                 message,
    1029             :                                 "Too many ssids specified. Specify at most four");
    1030           1 :                         return -1;
    1031             :                 }
    1032             : 
    1033          21 :                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
    1034             : 
    1035          21 :                 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
    1036             : 
    1037          21 :                 if (len > MAX_SSID_LEN) {
    1038           1 :                         wpa_printf(MSG_DEBUG,
    1039             :                                    "%s[dbus]: SSID too long (len=%d max_len=%d)",
    1040             :                                    __func__, len, MAX_SSID_LEN);
    1041           1 :                         *reply = wpas_dbus_error_invalid_args(
    1042             :                                 message, "Invalid SSID: too long");
    1043           1 :                         return -1;
    1044             :                 }
    1045             : 
    1046          20 :                 if (len != 0) {
    1047          19 :                         ssid = os_malloc(len);
    1048          19 :                         if (ssid == NULL) {
    1049           1 :                                 *reply = wpas_dbus_error_no_memory(message);
    1050           1 :                                 return -1;
    1051             :                         }
    1052          18 :                         os_memcpy(ssid, val, len);
    1053             :                 } else {
    1054             :                         /* Allow zero-length SSIDs */
    1055           1 :                         ssid = NULL;
    1056             :                 }
    1057             : 
    1058          19 :                 ssids[ssids_num].ssid = ssid;
    1059          19 :                 ssids[ssids_num].ssid_len = len;
    1060             : 
    1061          19 :                 dbus_message_iter_next(&array_iter);
    1062          19 :                 ssids_num++;
    1063             :         }
    1064             : 
    1065           2 :         params->num_ssids = ssids_num;
    1066           2 :         return 0;
    1067             : }
    1068             : 
    1069             : 
    1070           5 : static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
    1071             :                                   struct wpa_driver_scan_params *params,
    1072             :                                   DBusMessage **reply)
    1073             : {
    1074           5 :         u8 *ies = NULL, *nies;
    1075           5 :         int ies_len = 0;
    1076             :         DBusMessageIter array_iter, sub_array_iter;
    1077             :         char *val;
    1078             :         int len;
    1079             : 
    1080           5 :         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
    1081           1 :                 wpa_printf(MSG_DEBUG,
    1082             :                            "%s[dbus]: ies must be an array of arrays of bytes",
    1083             :                            __func__);
    1084           1 :                 *reply = wpas_dbus_error_invalid_args(
    1085             :                         message,
    1086             :                         "Wrong IEs value type. Array of arrays of bytes required");
    1087           1 :                 return -1;
    1088             :         }
    1089             : 
    1090           4 :         dbus_message_iter_recurse(var, &array_iter);
    1091             : 
    1092           7 :         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
    1093           3 :             dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
    1094           1 :                 wpa_printf(MSG_DEBUG,
    1095             :                            "%s[dbus]: ies must be an array of arrays of bytes",
    1096             :                            __func__);
    1097           1 :                 *reply = wpas_dbus_error_invalid_args(
    1098             :                         message, "Wrong IEs value type. Array required");
    1099           1 :                 return -1;
    1100             :         }
    1101             : 
    1102           9 :         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
    1103           4 :                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
    1104             : 
    1105           4 :                 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
    1106           4 :                 if (len == 0) {
    1107           1 :                         dbus_message_iter_next(&array_iter);
    1108           1 :                         continue;
    1109             :                 }
    1110             : 
    1111           3 :                 nies = os_realloc(ies, ies_len + len);
    1112           3 :                 if (nies == NULL) {
    1113           1 :                         os_free(ies);
    1114           1 :                         *reply = wpas_dbus_error_no_memory(message);
    1115           1 :                         return -1;
    1116             :                 }
    1117           2 :                 ies = nies;
    1118           2 :                 os_memcpy(ies + ies_len, val, len);
    1119           2 :                 ies_len += len;
    1120             : 
    1121           2 :                 dbus_message_iter_next(&array_iter);
    1122             :         }
    1123             : 
    1124           2 :         params->extra_ies = ies;
    1125           2 :         params->extra_ies_len = ies_len;
    1126           2 :         return 0;
    1127             : }
    1128             : 
    1129             : 
    1130          10 : static int wpas_dbus_get_scan_channels(DBusMessage *message,
    1131             :                                        DBusMessageIter *var,
    1132             :                                        struct wpa_driver_scan_params *params,
    1133             :                                        DBusMessage **reply)
    1134             : {
    1135             :         DBusMessageIter array_iter, sub_array_iter;
    1136          10 :         int *freqs = NULL, *nfreqs;
    1137          10 :         int freqs_num = 0;
    1138             : 
    1139          10 :         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
    1140           1 :                 wpa_printf(MSG_DEBUG,
    1141             :                            "%s[dbus]: Channels must be an array of structs",
    1142             :                            __func__);
    1143           1 :                 *reply = wpas_dbus_error_invalid_args(
    1144             :                         message,
    1145             :                         "Wrong Channels value type. Array of structs required");
    1146           1 :                 return -1;
    1147             :         }
    1148             : 
    1149           9 :         dbus_message_iter_recurse(var, &array_iter);
    1150             : 
    1151           9 :         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
    1152           1 :                 wpa_printf(MSG_DEBUG,
    1153             :                            "%s[dbus]: Channels must be an array of structs",
    1154             :                            __func__);
    1155           1 :                 *reply = wpas_dbus_error_invalid_args(
    1156             :                         message,
    1157             :                         "Wrong Channels value type. Array of structs required");
    1158           1 :                 return -1;
    1159             :         }
    1160             : 
    1161          21 :         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
    1162             :         {
    1163             :                 int freq, width;
    1164             : 
    1165           8 :                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
    1166             : 
    1167           8 :                 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
    1168             :                     DBUS_TYPE_UINT32) {
    1169           1 :                         wpa_printf(MSG_DEBUG,
    1170             :                                    "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
    1171             :                                    __func__,
    1172             :                                    dbus_message_iter_get_arg_type(
    1173             :                                            &sub_array_iter));
    1174           1 :                         *reply = wpas_dbus_error_invalid_args(
    1175             :                                 message,
    1176             :                                 "Wrong Channel struct. Two UINT32s required");
    1177           1 :                         os_free(freqs);
    1178           4 :                         return -1;
    1179             :                 }
    1180           7 :                 dbus_message_iter_get_basic(&sub_array_iter, &freq);
    1181             : 
    1182          14 :                 if (!dbus_message_iter_next(&sub_array_iter) ||
    1183           7 :                     dbus_message_iter_get_arg_type(&sub_array_iter) !=
    1184             :                     DBUS_TYPE_UINT32) {
    1185           1 :                         wpa_printf(MSG_DEBUG,
    1186             :                                    "%s[dbus]: Channel must by specified by struct of two UINT32s",
    1187             :                                    __func__);
    1188           1 :                         *reply = wpas_dbus_error_invalid_args(
    1189             :                                 message,
    1190             :                                 "Wrong Channel struct. Two UINT32s required");
    1191           1 :                         os_free(freqs);
    1192           1 :                         return -1;
    1193             :                 }
    1194             : 
    1195           6 :                 dbus_message_iter_get_basic(&sub_array_iter, &width);
    1196             : 
    1197             : #define FREQS_ALLOC_CHUNK 32
    1198           6 :                 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
    1199           6 :                         nfreqs = os_realloc_array(
    1200           6 :                                 freqs, freqs_num + FREQS_ALLOC_CHUNK,
    1201             :                                 sizeof(int));
    1202           6 :                         if (nfreqs == NULL)
    1203           1 :                                 os_free(freqs);
    1204           6 :                         freqs = nfreqs;
    1205             :                 }
    1206           6 :                 if (freqs == NULL) {
    1207           1 :                         *reply = wpas_dbus_error_no_memory(message);
    1208           1 :                         return -1;
    1209             :                 }
    1210             : 
    1211           5 :                 freqs[freqs_num] = freq;
    1212             : 
    1213           5 :                 freqs_num++;
    1214           5 :                 dbus_message_iter_next(&array_iter);
    1215             :         }
    1216             : 
    1217           5 :         nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
    1218           5 :         if (nfreqs == NULL)
    1219           0 :                 os_free(freqs);
    1220           5 :         freqs = nfreqs;
    1221           5 :         if (freqs == NULL) {
    1222           0 :                 *reply = wpas_dbus_error_no_memory(message);
    1223           0 :                 return -1;
    1224             :         }
    1225           5 :         freqs[freqs_num] = 0;
    1226             : 
    1227           5 :         params->freqs = freqs;
    1228           5 :         return 0;
    1229             : }
    1230             : 
    1231             : 
    1232           5 : static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
    1233             :                                          DBusMessageIter *var,
    1234             :                                          dbus_bool_t *allow,
    1235             :                                          DBusMessage **reply)
    1236             : {
    1237           5 :         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
    1238           1 :                 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
    1239             :                            __func__);
    1240           1 :                 *reply = wpas_dbus_error_invalid_args(
    1241             :                         message, "Wrong Type value type. Boolean required");
    1242           1 :                 return -1;
    1243             :         }
    1244           4 :         dbus_message_iter_get_basic(var, allow);
    1245           4 :         return 0;
    1246             : }
    1247             : 
    1248             : 
    1249             : /**
    1250             :  * wpas_dbus_handler_scan - Request a wireless scan on an interface
    1251             :  * @message: Pointer to incoming dbus message
    1252             :  * @wpa_s: wpa_supplicant structure for a network interface
    1253             :  * Returns: NULL indicating success or DBus error message on failure
    1254             :  *
    1255             :  * Handler function for "Scan" method call of a network device. Requests
    1256             :  * that wpa_supplicant perform a wireless scan as soon as possible
    1257             :  * on a particular wireless interface.
    1258             :  */
    1259          25 : DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
    1260             :                                      struct wpa_supplicant *wpa_s)
    1261             : {
    1262          25 :         DBusMessage *reply = NULL;
    1263             :         DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
    1264          25 :         char *key = NULL, *type = NULL;
    1265             :         struct wpa_driver_scan_params params;
    1266             :         size_t i;
    1267          25 :         dbus_bool_t allow_roam = 1;
    1268             : 
    1269          25 :         os_memset(&params, 0, sizeof(params));
    1270             : 
    1271          25 :         dbus_message_iter_init(message, &iter);
    1272             : 
    1273          25 :         dbus_message_iter_recurse(&iter, &dict_iter);
    1274             : 
    1275          77 :         while (dbus_message_iter_get_arg_type(&dict_iter) ==
    1276             :                DBUS_TYPE_DICT_ENTRY) {
    1277          43 :                 dbus_message_iter_recurse(&dict_iter, &entry_iter);
    1278          43 :                 dbus_message_iter_get_basic(&entry_iter, &key);
    1279          43 :                 dbus_message_iter_next(&entry_iter);
    1280          43 :                 dbus_message_iter_recurse(&entry_iter, &variant_iter);
    1281             : 
    1282          43 :                 if (os_strcmp(key, "Type") == 0) {
    1283          15 :                         if (wpas_dbus_get_scan_type(message, &variant_iter,
    1284             :                                                     &type, &reply) < 0)
    1285           1 :                                 goto out;
    1286          28 :                 } else if (os_strcmp(key, "SSIDs") == 0) {
    1287           7 :                         if (wpas_dbus_get_scan_ssids(message, &variant_iter,
    1288             :                                                      &params, &reply) < 0)
    1289           5 :                                 goto out;
    1290          21 :                 } else if (os_strcmp(key, "IEs") == 0) {
    1291           5 :                         if (wpas_dbus_get_scan_ies(message, &variant_iter,
    1292             :                                                    &params, &reply) < 0)
    1293           3 :                                 goto out;
    1294          16 :                 } else if (os_strcmp(key, "Channels") == 0) {
    1295          10 :                         if (wpas_dbus_get_scan_channels(message, &variant_iter,
    1296             :                                                         &params, &reply) < 0)
    1297           5 :                                 goto out;
    1298           6 :                 } else if (os_strcmp(key, "AllowRoam") == 0) {
    1299           5 :                         if (wpas_dbus_get_scan_allow_roam(message,
    1300             :                                                           &variant_iter,
    1301             :                                                           &allow_roam,
    1302             :                                                           &reply) < 0)
    1303           1 :                                 goto out;
    1304             :                 } else {
    1305           1 :                         wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
    1306             :                                    __func__, key);
    1307           1 :                         reply = wpas_dbus_error_invalid_args(message, key);
    1308           1 :                         goto out;
    1309             :                 }
    1310             : 
    1311          27 :                 dbus_message_iter_next(&dict_iter);
    1312             :         }
    1313             : 
    1314           9 :         if (!type) {
    1315           1 :                 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
    1316             :                            __func__);
    1317           1 :                 reply = wpas_dbus_error_invalid_args(message, key);
    1318           1 :                 goto out;
    1319             :         }
    1320             : 
    1321           8 :         if (os_strcmp(type, "passive") == 0) {
    1322           5 :                 if (params.num_ssids || params.extra_ies_len) {
    1323           2 :                         wpa_printf(MSG_DEBUG,
    1324             :                                    "%s[dbus]: SSIDs or IEs specified for passive scan.",
    1325             :                                    __func__);
    1326           2 :                         reply = wpas_dbus_error_invalid_args(
    1327             :                                 message,
    1328             :                                 "You can specify only Channels in passive scan");
    1329           2 :                         goto out;
    1330           3 :                 } else if (params.freqs && params.freqs[0]) {
    1331           4 :                         if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
    1332           1 :                                 reply = wpas_dbus_error_scan_error(
    1333             :                                         message, "Scan request rejected");
    1334             :                         }
    1335             :                 } else {
    1336           1 :                         wpa_s->scan_req = MANUAL_SCAN_REQ;
    1337           1 :                         wpa_supplicant_req_scan(wpa_s, 0, 0);
    1338             :                 }
    1339           3 :         } else if (os_strcmp(type, "active") == 0) {
    1340           2 :                 if (!params.num_ssids) {
    1341             :                         /* Add wildcard ssid */
    1342           1 :                         params.num_ssids++;
    1343             :                 }
    1344             : #ifdef CONFIG_AUTOSCAN
    1345           2 :                 autoscan_deinit(wpa_s);
    1346             : #endif /* CONFIG_AUTOSCAN */
    1347           2 :                 if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
    1348           1 :                         reply = wpas_dbus_error_scan_error(
    1349             :                                 message, "Scan request rejected");
    1350             :                 }
    1351             :         } else {
    1352           1 :                 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
    1353             :                            __func__, type);
    1354           1 :                 reply = wpas_dbus_error_invalid_args(message,
    1355             :                                                      "Wrong scan type");
    1356           1 :                 goto out;
    1357             :         }
    1358             : 
    1359           5 :         if (!allow_roam)
    1360           3 :                 wpa_s->scan_res_handler = scan_only_handler;
    1361             : 
    1362             : out:
    1363         425 :         for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
    1364         400 :                 os_free((u8 *) params.ssids[i].ssid);
    1365          25 :         os_free((u8 *) params.extra_ies);
    1366          25 :         os_free(params.freqs);
    1367          25 :         return reply;
    1368             : }
    1369             : 
    1370             : 
    1371             : /**
    1372             :  * wpas_dbus_handler_signal_poll - Request immediate signal properties
    1373             :  * @message: Pointer to incoming dbus message
    1374             :  * @wpa_s: wpa_supplicant structure for a network interface
    1375             :  * Returns: NULL indicating success or DBus error message on failure
    1376             :  *
    1377             :  * Handler function for "SignalPoll" method call of a network device. Requests
    1378             :  * that wpa_supplicant read signal properties like RSSI, noise, and link
    1379             :  * speed and return them.
    1380             :  */
    1381          36 : DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
    1382             :                                             struct wpa_supplicant *wpa_s)
    1383             : {
    1384             :         struct wpa_signal_info si;
    1385          36 :         DBusMessage *reply = NULL;
    1386             :         DBusMessageIter iter, iter_dict, variant_iter;
    1387             :         int ret;
    1388             : 
    1389          36 :         ret = wpa_drv_signal_poll(wpa_s, &si);
    1390          36 :         if (ret) {
    1391           0 :                 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
    1392             :                                               "Failed to read signal");
    1393             :         }
    1394             : 
    1395          36 :         reply = dbus_message_new_method_return(message);
    1396          36 :         if (reply == NULL)
    1397           0 :                 goto nomem;
    1398             : 
    1399          36 :         dbus_message_iter_init_append(reply, &iter);
    1400             : 
    1401          36 :         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
    1402          36 :                                               "a{sv}", &variant_iter) ||
    1403          72 :             !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
    1404          36 :             !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
    1405          36 :                                         si.current_signal) ||
    1406          36 :             !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
    1407          72 :                                         si.current_txrate / 1000) ||
    1408          36 :             !wpa_dbus_dict_append_int32(&iter_dict, "noise",
    1409          36 :                                         si.current_noise) ||
    1410          36 :             !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
    1411          36 :                                          si.frequency) ||
    1412          72 :             (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
    1413          36 :              !wpa_dbus_dict_append_string(
    1414             :                      &iter_dict, "width",
    1415          36 :                      channel_width_to_string(si.chanwidth))) ||
    1416          72 :             (si.center_frq1 > 0 && si.center_frq2 > 0 &&
    1417           0 :              (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
    1418           0 :                                           si.center_frq1) ||
    1419           0 :               !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
    1420          36 :                                           si.center_frq2))) ||
    1421          72 :             (si.avg_signal &&
    1422          36 :              !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
    1423          36 :                                          si.avg_signal)) ||
    1424          72 :             !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
    1425          36 :             !dbus_message_iter_close_container(&iter, &variant_iter))
    1426             :                 goto nomem;
    1427             : 
    1428          36 :         return reply;
    1429             : 
    1430             : nomem:
    1431           0 :         if (reply)
    1432           0 :                 dbus_message_unref(reply);
    1433           0 :         return wpas_dbus_error_no_memory(message);
    1434             : }
    1435             : 
    1436             : 
    1437             : /*
    1438             :  * wpas_dbus_handler_disconnect - Terminate the current connection
    1439             :  * @message: Pointer to incoming dbus message
    1440             :  * @wpa_s: wpa_supplicant structure for a network interface
    1441             :  * Returns: NotConnected DBus error message if already not connected
    1442             :  * or NULL otherwise.
    1443             :  *
    1444             :  * Handler function for "Disconnect" method call of network interface.
    1445             :  */
    1446          74 : DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
    1447             :                                            struct wpa_supplicant *wpa_s)
    1448             : {
    1449          74 :         if (wpa_s->current_ssid != NULL) {
    1450          73 :                 wpa_s->disconnected = 1;
    1451          73 :                 wpa_supplicant_deauthenticate(wpa_s,
    1452             :                                               WLAN_REASON_DEAUTH_LEAVING);
    1453             : 
    1454          73 :                 return NULL;
    1455             :         }
    1456             : 
    1457           1 :         return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
    1458             :                                       "This interface is not connected");
    1459             : }
    1460             : 
    1461             : 
    1462             : /**
    1463             :  * wpas_dbus_new_iface_add_network - Add a new configured network
    1464             :  * @message: Pointer to incoming dbus message
    1465             :  * @wpa_s: wpa_supplicant structure for a network interface
    1466             :  * Returns: A dbus message containing the object path of the new network
    1467             :  *
    1468             :  * Handler function for "AddNetwork" method call of a network interface.
    1469             :  */
    1470          62 : DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
    1471             :                                             struct wpa_supplicant *wpa_s)
    1472             : {
    1473          62 :         DBusMessage *reply = NULL;
    1474             :         DBusMessageIter iter;
    1475          62 :         struct wpa_ssid *ssid = NULL;
    1476          62 :         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
    1477             :         DBusError error;
    1478             : 
    1479          62 :         dbus_message_iter_init(message, &iter);
    1480             : 
    1481          62 :         ssid = wpa_config_add_network(wpa_s->conf);
    1482          62 :         if (ssid == NULL) {
    1483           1 :                 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
    1484             :                            __func__);
    1485           1 :                 reply = wpas_dbus_error_unknown_error(
    1486             :                         message,
    1487             :                         "wpa_supplicant could not add a network on this interface.");
    1488           1 :                 goto err;
    1489             :         }
    1490          61 :         wpas_notify_network_added(wpa_s, ssid);
    1491          61 :         ssid->disabled = 1;
    1492          61 :         wpa_config_set_network_defaults(ssid);
    1493             : 
    1494          61 :         dbus_error_init(&error);
    1495          61 :         if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
    1496          10 :                 wpa_printf(MSG_DEBUG,
    1497             :                            "%s[dbus]: control interface couldn't set network properties",
    1498             :                            __func__);
    1499          10 :                 reply = wpas_dbus_reply_new_from_error(message, &error,
    1500             :                                                        DBUS_ERROR_INVALID_ARGS,
    1501             :                                                        "Failed to add network");
    1502          10 :                 dbus_error_free(&error);
    1503          10 :                 goto err;
    1504             :         }
    1505             : 
    1506             :         /* Construct the object path for this network. */
    1507          51 :         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
    1508             :                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
    1509             :                     wpa_s->dbus_new_path, ssid->id);
    1510             : 
    1511          51 :         reply = dbus_message_new_method_return(message);
    1512          51 :         if (reply == NULL) {
    1513           0 :                 reply = wpas_dbus_error_no_memory(message);
    1514           0 :                 goto err;
    1515             :         }
    1516          51 :         if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
    1517             :                                       DBUS_TYPE_INVALID)) {
    1518           0 :                 dbus_message_unref(reply);
    1519           0 :                 reply = wpas_dbus_error_no_memory(message);
    1520           0 :                 goto err;
    1521             :         }
    1522             : 
    1523          51 :         return reply;
    1524             : 
    1525             : err:
    1526          11 :         if (ssid) {
    1527          10 :                 wpas_notify_network_removed(wpa_s, ssid);
    1528          10 :                 wpa_config_remove_network(wpa_s->conf, ssid->id);
    1529             :         }
    1530          11 :         return reply;
    1531             : }
    1532             : 
    1533             : 
    1534             : /**
    1535             :  * wpas_dbus_handler_reassociate - Reassociate
    1536             :  * @message: Pointer to incoming dbus message
    1537             :  * @wpa_s: wpa_supplicant structure for a network interface
    1538             :  * Returns: InterfaceDisabled DBus error message if disabled
    1539             :  * or NULL otherwise.
    1540             :  *
    1541             :  * Handler function for "Reassociate" method call of network interface.
    1542             :  */
    1543          36 : DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
    1544             :                                             struct wpa_supplicant *wpa_s)
    1545             : {
    1546          36 :         if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
    1547          36 :                 wpas_request_connection(wpa_s);
    1548          36 :                 return NULL;
    1549             :         }
    1550             : 
    1551           0 :         return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
    1552             :                                       "This interface is disabled");
    1553             : }
    1554             : 
    1555             : 
    1556             : /**
    1557             :  * wpas_dbus_handler_reattach - Reattach to current AP
    1558             :  * @message: Pointer to incoming dbus message
    1559             :  * @wpa_s: wpa_supplicant structure for a network interface
    1560             :  * Returns: NotConnected DBus error message if not connected
    1561             :  * or NULL otherwise.
    1562             :  *
    1563             :  * Handler function for "Reattach" method call of network interface.
    1564             :  */
    1565          37 : DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
    1566             :                                          struct wpa_supplicant *wpa_s)
    1567             : {
    1568          37 :         if (wpa_s->current_ssid != NULL) {
    1569          36 :                 wpa_s->reattach = 1;
    1570          36 :                 wpas_request_connection(wpa_s);
    1571          36 :                 return NULL;
    1572             :         }
    1573             : 
    1574           1 :         return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
    1575             :                                       "This interface is not connected");
    1576             : }
    1577             : 
    1578             : 
    1579             : /**
    1580             :  * wpas_dbus_handler_remove_network - Remove a configured network
    1581             :  * @message: Pointer to incoming dbus message
    1582             :  * @wpa_s: wpa_supplicant structure for a network interface
    1583             :  * Returns: NULL on success or dbus error on failure
    1584             :  *
    1585             :  * Handler function for "RemoveNetwork" method call of a network interface.
    1586             :  */
    1587          42 : DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
    1588             :                                                struct wpa_supplicant *wpa_s)
    1589             : {
    1590          42 :         DBusMessage *reply = NULL;
    1591             :         const char *op;
    1592             :         char *iface, *net_id;
    1593             :         int id;
    1594             :         struct wpa_ssid *ssid;
    1595             :         int was_disabled;
    1596             : 
    1597          42 :         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
    1598             :                               DBUS_TYPE_INVALID);
    1599             : 
    1600             :         /* Extract the network ID and ensure the network */
    1601             :         /* is actually a child of this interface */
    1602          42 :         iface = wpas_dbus_new_decompose_object_path(op,
    1603             :                                                     WPAS_DBUS_NEW_NETWORKS_PART,
    1604             :                                                     &net_id);
    1605          83 :         if (iface == NULL || net_id == NULL ||
    1606          41 :             os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
    1607           1 :                 reply = wpas_dbus_error_invalid_args(message, op);
    1608           1 :                 goto out;
    1609             :         }
    1610             : 
    1611          41 :         errno = 0;
    1612          41 :         id = strtoul(net_id, NULL, 10);
    1613          41 :         if (errno != 0) {
    1614           0 :                 reply = wpas_dbus_error_invalid_args(message, op);
    1615           0 :                 goto out;
    1616             :         }
    1617             : 
    1618          41 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    1619          41 :         if (ssid == NULL) {
    1620           1 :                 reply = wpas_dbus_error_network_unknown(message);
    1621           1 :                 goto out;
    1622             :         }
    1623             : 
    1624          40 :         was_disabled = ssid->disabled;
    1625             : 
    1626          40 :         wpas_notify_network_removed(wpa_s, ssid);
    1627             : 
    1628          40 :         if (ssid == wpa_s->current_ssid)
    1629          36 :                 wpa_supplicant_deauthenticate(wpa_s,
    1630             :                                               WLAN_REASON_DEAUTH_LEAVING);
    1631           4 :         else if (!was_disabled && wpa_s->sched_scanning) {
    1632           0 :                 wpa_printf(MSG_DEBUG,
    1633             :                            "Stop ongoing sched_scan to remove network from filters");
    1634           0 :                 wpa_supplicant_cancel_sched_scan(wpa_s);
    1635           0 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
    1636             :         }
    1637             : 
    1638          40 :         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
    1639           0 :                 wpa_printf(MSG_ERROR,
    1640             :                            "%s[dbus]: error occurred when removing network %d",
    1641             :                            __func__, id);
    1642           0 :                 reply = wpas_dbus_error_unknown_error(
    1643             :                         message,
    1644             :                         "error removing the specified network on is interface.");
    1645           0 :                 goto out;
    1646             :         }
    1647             : 
    1648             : out:
    1649          42 :         os_free(iface);
    1650          42 :         return reply;
    1651             : }
    1652             : 
    1653             : 
    1654           3 : static void remove_network(void *arg, struct wpa_ssid *ssid)
    1655             : {
    1656           3 :         struct wpa_supplicant *wpa_s = arg;
    1657             : 
    1658           3 :         wpas_notify_network_removed(wpa_s, ssid);
    1659             : 
    1660           3 :         if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
    1661           0 :                 wpa_printf(MSG_ERROR,
    1662             :                            "%s[dbus]: error occurred when removing network %d",
    1663             :                            __func__, ssid->id);
    1664           3 :                 return;
    1665             :         }
    1666             : 
    1667           3 :         if (ssid == wpa_s->current_ssid)
    1668           0 :                 wpa_supplicant_deauthenticate(wpa_s,
    1669             :                                               WLAN_REASON_DEAUTH_LEAVING);
    1670             : }
    1671             : 
    1672             : 
    1673             : /**
    1674             :  * wpas_dbus_handler_remove_all_networks - Remove all configured networks
    1675             :  * @message: Pointer to incoming dbus message
    1676             :  * @wpa_s: wpa_supplicant structure for a network interface
    1677             :  * Returns: NULL on success or dbus error on failure
    1678             :  *
    1679             :  * Handler function for "RemoveAllNetworks" method call of a network interface.
    1680             :  */
    1681           3 : DBusMessage * wpas_dbus_handler_remove_all_networks(
    1682             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    1683             : {
    1684           3 :         if (wpa_s->sched_scanning)
    1685           0 :                 wpa_supplicant_cancel_sched_scan(wpa_s);
    1686             : 
    1687             :         /* NB: could check for failure and return an error */
    1688           3 :         wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
    1689           3 :         return NULL;
    1690             : }
    1691             : 
    1692             : 
    1693             : /**
    1694             :  * wpas_dbus_handler_select_network - Attempt association with a network
    1695             :  * @message: Pointer to incoming dbus message
    1696             :  * @wpa_s: wpa_supplicant structure for a network interface
    1697             :  * Returns: NULL on success or dbus error on failure
    1698             :  *
    1699             :  * Handler function for "SelectNetwork" method call of network interface.
    1700             :  */
    1701          83 : DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
    1702             :                                                struct wpa_supplicant *wpa_s)
    1703             : {
    1704          83 :         DBusMessage *reply = NULL;
    1705             :         const char *op;
    1706             :         char *iface, *net_id;
    1707             :         int id;
    1708             :         struct wpa_ssid *ssid;
    1709             : 
    1710          83 :         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
    1711             :                               DBUS_TYPE_INVALID);
    1712             : 
    1713             :         /* Extract the network ID and ensure the network */
    1714             :         /* is actually a child of this interface */
    1715          83 :         iface = wpas_dbus_new_decompose_object_path(op,
    1716             :                                                     WPAS_DBUS_NEW_NETWORKS_PART,
    1717             :                                                     &net_id);
    1718         166 :         if (iface == NULL || net_id == NULL ||
    1719          83 :             os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
    1720           0 :                 reply = wpas_dbus_error_invalid_args(message, op);
    1721           0 :                 goto out;
    1722             :         }
    1723             : 
    1724          83 :         errno = 0;
    1725          83 :         id = strtoul(net_id, NULL, 10);
    1726          83 :         if (errno != 0) {
    1727           0 :                 reply = wpas_dbus_error_invalid_args(message, op);
    1728           0 :                 goto out;
    1729             :         }
    1730             : 
    1731          83 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    1732          83 :         if (ssid == NULL) {
    1733           1 :                 reply = wpas_dbus_error_network_unknown(message);
    1734           1 :                 goto out;
    1735             :         }
    1736             : 
    1737             :         /* Finally, associate with the network */
    1738          82 :         wpa_supplicant_select_network(wpa_s, ssid);
    1739             : 
    1740             : out:
    1741          83 :         os_free(iface);
    1742          83 :         return reply;
    1743             : }
    1744             : 
    1745             : 
    1746             : /**
    1747             :  * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
    1748             :  * @message: Pointer to incoming dbus message
    1749             :  * @wpa_s: wpa_supplicant structure for a network interface
    1750             :  * Returns: NULL on success or dbus error on failure
    1751             :  *
    1752             :  * Handler function for "NetworkReply" method call of network interface.
    1753             :  */
    1754           1 : DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
    1755             :                                               struct wpa_supplicant *wpa_s)
    1756             : {
    1757             : #ifdef IEEE8021X_EAPOL
    1758           1 :         DBusMessage *reply = NULL;
    1759             :         const char *op, *field, *value;
    1760             :         char *iface, *net_id;
    1761             :         int id;
    1762             :         struct wpa_ssid *ssid;
    1763             : 
    1764           1 :         if (!dbus_message_get_args(message, NULL,
    1765             :                                    DBUS_TYPE_OBJECT_PATH, &op,
    1766             :                                    DBUS_TYPE_STRING, &field,
    1767             :                                    DBUS_TYPE_STRING, &value,
    1768             :                                    DBUS_TYPE_INVALID))
    1769           0 :                 return wpas_dbus_error_invalid_args(message, NULL);
    1770             : 
    1771             :         /* Extract the network ID and ensure the network */
    1772             :         /* is actually a child of this interface */
    1773           1 :         iface = wpas_dbus_new_decompose_object_path(op,
    1774             :                                                     WPAS_DBUS_NEW_NETWORKS_PART,
    1775             :                                                     &net_id);
    1776           2 :         if (iface == NULL || net_id == NULL ||
    1777           1 :             os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
    1778           0 :                 reply = wpas_dbus_error_invalid_args(message, op);
    1779           0 :                 goto out;
    1780             :         }
    1781             : 
    1782           1 :         errno = 0;
    1783           1 :         id = strtoul(net_id, NULL, 10);
    1784           1 :         if (errno != 0) {
    1785           0 :                 reply = wpas_dbus_error_invalid_args(message, net_id);
    1786           0 :                 goto out;
    1787             :         }
    1788             : 
    1789           1 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    1790           1 :         if (ssid == NULL) {
    1791           0 :                 reply = wpas_dbus_error_network_unknown(message);
    1792           0 :                 goto out;
    1793             :         }
    1794             : 
    1795           1 :         if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
    1796             :                                                       field, value) < 0)
    1797           0 :                 reply = wpas_dbus_error_invalid_args(message, field);
    1798             :         else {
    1799             :                 /* Tell EAP to retry immediately */
    1800           1 :                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
    1801             :         }
    1802             : 
    1803             : out:
    1804           1 :         os_free(iface);
    1805           1 :         return reply;
    1806             : #else /* IEEE8021X_EAPOL */
    1807             :         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
    1808             :         return wpas_dbus_error_unknown_error(message, "802.1X not included");
    1809             : #endif /* IEEE8021X_EAPOL */
    1810             : }
    1811             : 
    1812             : 
    1813             : #ifndef CONFIG_NO_CONFIG_BLOBS
    1814             : 
    1815             : /**
    1816             :  * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
    1817             :  * @message: Pointer to incoming dbus message
    1818             :  * @wpa_s: %wpa_supplicant data structure
    1819             :  * Returns: A dbus message containing an error on failure or NULL on success
    1820             :  *
    1821             :  * Asks wpa_supplicant to internally store a binary blobs.
    1822             :  */
    1823           6 : DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
    1824             :                                          struct wpa_supplicant *wpa_s)
    1825             : {
    1826           6 :         DBusMessage *reply = NULL;
    1827             :         DBusMessageIter iter, array_iter;
    1828             : 
    1829             :         char *blob_name;
    1830             :         u8 *blob_data;
    1831             :         int blob_len;
    1832           6 :         struct wpa_config_blob *blob = NULL;
    1833             : 
    1834           6 :         dbus_message_iter_init(message, &iter);
    1835           6 :         dbus_message_iter_get_basic(&iter, &blob_name);
    1836             : 
    1837           6 :         if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
    1838           1 :                 return dbus_message_new_error(message,
    1839             :                                               WPAS_DBUS_ERROR_BLOB_EXISTS,
    1840             :                                               NULL);
    1841             :         }
    1842             : 
    1843           5 :         dbus_message_iter_next(&iter);
    1844           5 :         dbus_message_iter_recurse(&iter, &array_iter);
    1845             : 
    1846           5 :         dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
    1847             : 
    1848           5 :         blob = os_zalloc(sizeof(*blob));
    1849           5 :         if (!blob) {
    1850           1 :                 reply = wpas_dbus_error_no_memory(message);
    1851           1 :                 goto err;
    1852             :         }
    1853             : 
    1854           4 :         blob->data = os_malloc(blob_len);
    1855           4 :         blob->name = os_strdup(blob_name);
    1856           4 :         if (!blob->data || !blob->name) {
    1857           2 :                 reply = wpas_dbus_error_no_memory(message);
    1858           2 :                 goto err;
    1859             :         }
    1860           2 :         os_memcpy(blob->data, blob_data, blob_len);
    1861           2 :         blob->len = blob_len;
    1862             : 
    1863           2 :         wpa_config_set_blob(wpa_s->conf, blob);
    1864           2 :         wpas_notify_blob_added(wpa_s, blob->name);
    1865             : 
    1866           2 :         return reply;
    1867             : 
    1868             : err:
    1869           3 :         if (blob) {
    1870           2 :                 os_free(blob->name);
    1871           2 :                 os_free(blob->data);
    1872           2 :                 os_free(blob);
    1873             :         }
    1874           3 :         return reply;
    1875             : }
    1876             : 
    1877             : 
    1878             : /**
    1879             :  * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
    1880             :  * @message: Pointer to incoming dbus message
    1881             :  * @wpa_s: %wpa_supplicant data structure
    1882             :  * Returns: A dbus message containing array of bytes (blob)
    1883             :  *
    1884             :  * Gets one wpa_supplicant's binary blobs.
    1885             :  */
    1886           2 : DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
    1887             :                                          struct wpa_supplicant *wpa_s)
    1888             : {
    1889           2 :         DBusMessage *reply = NULL;
    1890             :         DBusMessageIter iter, array_iter;
    1891             : 
    1892             :         char *blob_name;
    1893             :         const struct wpa_config_blob *blob;
    1894             : 
    1895           2 :         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
    1896             :                               DBUS_TYPE_INVALID);
    1897             : 
    1898           2 :         blob = wpa_config_get_blob(wpa_s->conf, blob_name);
    1899           2 :         if (!blob) {
    1900           1 :                 return dbus_message_new_error(message,
    1901             :                                               WPAS_DBUS_ERROR_BLOB_UNKNOWN,
    1902             :                                               "Blob id not set");
    1903             :         }
    1904             : 
    1905           1 :         reply = dbus_message_new_method_return(message);
    1906           1 :         if (!reply)
    1907           0 :                 return wpas_dbus_error_no_memory(message);
    1908             : 
    1909           1 :         dbus_message_iter_init_append(reply, &iter);
    1910             : 
    1911           1 :         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
    1912             :                                               DBUS_TYPE_BYTE_AS_STRING,
    1913           1 :                                               &array_iter) ||
    1914           2 :             !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
    1915           3 :                                                   &(blob->data), blob->len) ||
    1916           1 :             !dbus_message_iter_close_container(&iter, &array_iter)) {
    1917           0 :                 dbus_message_unref(reply);
    1918           0 :                 reply = wpas_dbus_error_no_memory(message);
    1919             :         }
    1920             : 
    1921           1 :         return reply;
    1922             : }
    1923             : 
    1924             : 
    1925             : /**
    1926             :  * wpas_remove_handler_remove_blob - Remove named binary blob
    1927             :  * @message: Pointer to incoming dbus message
    1928             :  * @wpa_s: %wpa_supplicant data structure
    1929             :  * Returns: NULL on success or dbus error
    1930             :  *
    1931             :  * Asks wpa_supplicant to internally remove a binary blobs.
    1932             :  */
    1933           3 : DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
    1934             :                                             struct wpa_supplicant *wpa_s)
    1935             : {
    1936           3 :         DBusMessage *reply = NULL;
    1937             :         char *blob_name;
    1938             : 
    1939           3 :         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
    1940             :                               DBUS_TYPE_INVALID);
    1941             : 
    1942           3 :         if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
    1943           1 :                 return dbus_message_new_error(message,
    1944             :                                               WPAS_DBUS_ERROR_BLOB_UNKNOWN,
    1945             :                                               "Blob id not set");
    1946             :         }
    1947           2 :         wpas_notify_blob_removed(wpa_s, blob_name);
    1948             : 
    1949           2 :         return reply;
    1950             : 
    1951             : }
    1952             : 
    1953             : #endif /* CONFIG_NO_CONFIG_BLOBS */
    1954             : 
    1955             : 
    1956             : /*
    1957             :  * wpas_dbus_handler_flush_bss - Flush the BSS cache
    1958             :  * @message: Pointer to incoming dbus message
    1959             :  * @wpa_s: wpa_supplicant structure for a network interface
    1960             :  * Returns: NULL
    1961             :  *
    1962             :  * Handler function for "FlushBSS" method call of network interface.
    1963             :  */
    1964           2 : DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
    1965             :                                           struct wpa_supplicant *wpa_s)
    1966             : {
    1967             :         dbus_uint32_t age;
    1968             : 
    1969           2 :         dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
    1970             :                               DBUS_TYPE_INVALID);
    1971             : 
    1972           2 :         if (age == 0)
    1973           1 :                 wpa_bss_flush(wpa_s);
    1974             :         else
    1975           1 :                 wpa_bss_flush_by_age(wpa_s, age);
    1976             : 
    1977           2 :         return NULL;
    1978             : }
    1979             : 
    1980             : 
    1981             : #ifdef CONFIG_AUTOSCAN
    1982             : /**
    1983             :  * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
    1984             :  * @message: Pointer to incoming dbus message
    1985             :  * @wpa_s: wpa_supplicant structure for a network interface
    1986             :  * Returns: NULL
    1987             :  *
    1988             :  * Handler function for "AutoScan" method call of network interface.
    1989             :  */
    1990           4 : DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
    1991             :                                          struct wpa_supplicant *wpa_s)
    1992             : {
    1993           4 :         DBusMessage *reply = NULL;
    1994           4 :         enum wpa_states state = wpa_s->wpa_state;
    1995             :         char *arg;
    1996             : 
    1997           4 :         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
    1998             :                               DBUS_TYPE_INVALID);
    1999             : 
    2000           7 :         if (arg != NULL && os_strlen(arg) > 0) {
    2001             :                 char *tmp;
    2002             : 
    2003           3 :                 tmp = os_strdup(arg);
    2004           3 :                 if (tmp == NULL) {
    2005           1 :                         reply = wpas_dbus_error_no_memory(message);
    2006             :                 } else {
    2007           2 :                         os_free(wpa_s->conf->autoscan);
    2008           2 :                         wpa_s->conf->autoscan = tmp;
    2009           2 :                         if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
    2010           0 :                                 autoscan_init(wpa_s, 1);
    2011           2 :                         else if (state == WPA_SCANNING)
    2012           2 :                                 wpa_supplicant_reinit_autoscan(wpa_s);
    2013             :                 }
    2014           1 :         } else if (arg != NULL && os_strlen(arg) == 0) {
    2015           1 :                 os_free(wpa_s->conf->autoscan);
    2016           1 :                 wpa_s->conf->autoscan = NULL;
    2017           1 :                 autoscan_deinit(wpa_s);
    2018             :         } else
    2019           0 :                 reply = dbus_message_new_error(message,
    2020             :                                                DBUS_ERROR_INVALID_ARGS,
    2021             :                                                NULL);
    2022             : 
    2023           4 :         return reply;
    2024             : }
    2025             : #endif /* CONFIG_AUTOSCAN */
    2026             : 
    2027             : 
    2028             : /*
    2029             :  * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
    2030             :  * @message: Pointer to incoming dbus message
    2031             :  * @wpa_s: wpa_supplicant structure for a network interface
    2032             :  * Returns: NULL
    2033             :  *
    2034             :  * Handler function for "EAPLogoff" method call of network interface.
    2035             :  */
    2036           1 : DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
    2037             :                                            struct wpa_supplicant *wpa_s)
    2038             : {
    2039           1 :         eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
    2040           1 :         return NULL;
    2041             : }
    2042             : 
    2043             : 
    2044             : /*
    2045             :  * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
    2046             :  * @message: Pointer to incoming dbus message
    2047             :  * @wpa_s: wpa_supplicant structure for a network interface
    2048             :  * Returns: NULL
    2049             :  *
    2050             :  * Handler function for "EAPLogin" method call of network interface.
    2051             :  */
    2052           1 : DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
    2053             :                                           struct wpa_supplicant *wpa_s)
    2054             : {
    2055           1 :         eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
    2056           1 :         return NULL;
    2057             : }
    2058             : 
    2059             : 
    2060             : #ifdef CONFIG_TDLS
    2061             : 
    2062          12 : static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
    2063             :                                   u8 *peer_address, DBusMessage **error)
    2064             : {
    2065             :         const char *peer_string;
    2066             : 
    2067          12 :         *error = NULL;
    2068             : 
    2069          12 :         if (!dbus_message_get_args(message, NULL,
    2070             :                                    DBUS_TYPE_STRING, &peer_string,
    2071             :                                    DBUS_TYPE_INVALID)) {
    2072           0 :                 *error = wpas_dbus_error_invalid_args(message, NULL);
    2073           0 :                 return -1;
    2074             :         }
    2075             : 
    2076          12 :         if (hwaddr_aton(peer_string, peer_address)) {
    2077           4 :                 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
    2078             :                            func_name, peer_string);
    2079           4 :                 *error = wpas_dbus_error_invalid_args(
    2080             :                         message, "Invalid hardware address format");
    2081           4 :                 return -1;
    2082             :         }
    2083             : 
    2084           8 :         return 0;
    2085             : }
    2086             : 
    2087             : 
    2088             : /*
    2089             :  * wpas_dbus_handler_tdls_discover - Discover TDLS peer
    2090             :  * @message: Pointer to incoming dbus message
    2091             :  * @wpa_s: wpa_supplicant structure for a network interface
    2092             :  * Returns: NULL indicating success or DBus error message on failure
    2093             :  *
    2094             :  * Handler function for "TDLSDiscover" method call of network interface.
    2095             :  */
    2096           2 : DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
    2097             :                                               struct wpa_supplicant *wpa_s)
    2098             : {
    2099             :         u8 peer[ETH_ALEN];
    2100             :         DBusMessage *error_reply;
    2101             :         int ret;
    2102             : 
    2103           2 :         if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
    2104           1 :                 return error_reply;
    2105             : 
    2106           1 :         wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
    2107             : 
    2108           1 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
    2109           1 :                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
    2110             :         else
    2111           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
    2112             : 
    2113           1 :         if (ret) {
    2114           0 :                 return wpas_dbus_error_unknown_error(
    2115             :                         message, "error performing TDLS discovery");
    2116             :         }
    2117             : 
    2118           1 :         return NULL;
    2119             : }
    2120             : 
    2121             : 
    2122             : /*
    2123             :  * wpas_dbus_handler_tdls_setup - Setup TDLS session
    2124             :  * @message: Pointer to incoming dbus message
    2125             :  * @wpa_s: wpa_supplicant structure for a network interface
    2126             :  * Returns: NULL indicating success or DBus error message on failure
    2127             :  *
    2128             :  * Handler function for "TDLSSetup" method call of network interface.
    2129             :  */
    2130           3 : DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
    2131             :                                            struct wpa_supplicant *wpa_s)
    2132             : {
    2133             :         u8 peer[ETH_ALEN];
    2134             :         DBusMessage *error_reply;
    2135             :         int ret;
    2136             : 
    2137           3 :         if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
    2138           1 :                 return error_reply;
    2139             : 
    2140           2 :         wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
    2141             : 
    2142           2 :         wpa_tdls_remove(wpa_s->wpa, peer);
    2143           2 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
    2144           2 :                 ret = wpa_tdls_start(wpa_s->wpa, peer);
    2145             :         else
    2146           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
    2147             : 
    2148           2 :         if (ret) {
    2149           1 :                 return wpas_dbus_error_unknown_error(
    2150             :                         message, "error performing TDLS setup");
    2151             :         }
    2152             : 
    2153           1 :         return NULL;
    2154             : }
    2155             : 
    2156             : 
    2157             : /*
    2158             :  * wpas_dbus_handler_tdls_status - Return TDLS session status
    2159             :  * @message: Pointer to incoming dbus message
    2160             :  * @wpa_s: wpa_supplicant structure for a network interface
    2161             :  * Returns: A string representing the state of the link to this TDLS peer
    2162             :  *
    2163             :  * Handler function for "TDLSStatus" method call of network interface.
    2164             :  */
    2165           4 : DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
    2166             :                                             struct wpa_supplicant *wpa_s)
    2167             : {
    2168             :         u8 peer[ETH_ALEN];
    2169             :         DBusMessage *reply;
    2170             :         const char *tdls_status;
    2171             : 
    2172           4 :         if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
    2173           1 :                 return reply;
    2174             : 
    2175           3 :         wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
    2176             : 
    2177           3 :         tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
    2178             : 
    2179           3 :         reply = dbus_message_new_method_return(message);
    2180           3 :         dbus_message_append_args(reply, DBUS_TYPE_STRING,
    2181             :                                  &tdls_status, DBUS_TYPE_INVALID);
    2182           3 :         return reply;
    2183             : }
    2184             : 
    2185             : 
    2186             : /*
    2187             :  * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
    2188             :  * @message: Pointer to incoming dbus message
    2189             :  * @wpa_s: wpa_supplicant structure for a network interface
    2190             :  * Returns: NULL indicating success or DBus error message on failure
    2191             :  *
    2192             :  * Handler function for "TDLSTeardown" method call of network interface.
    2193             :  */
    2194           3 : DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
    2195             :                                               struct wpa_supplicant *wpa_s)
    2196             : {
    2197             :         u8 peer[ETH_ALEN];
    2198             :         DBusMessage *error_reply;
    2199             :         int ret;
    2200             : 
    2201           3 :         if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
    2202           1 :                 return error_reply;
    2203             : 
    2204           2 :         wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
    2205             : 
    2206           2 :         if (wpa_tdls_is_external_setup(wpa_s->wpa))
    2207           2 :                 ret = wpa_tdls_teardown_link(
    2208             :                         wpa_s->wpa, peer,
    2209             :                         WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
    2210             :         else
    2211           0 :                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
    2212             : 
    2213           2 :         if (ret) {
    2214           1 :                 return wpas_dbus_error_unknown_error(
    2215             :                         message, "error performing TDLS teardown");
    2216             :         }
    2217             : 
    2218           1 :         return NULL;
    2219             : }
    2220             : 
    2221             : #endif /* CONFIG_TDLS */
    2222             : 
    2223             : 
    2224             : /**
    2225             :  * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
    2226             :  * @message: Pointer to incoming dbus message
    2227             :  * @wpa_s: %wpa_supplicant data structure
    2228             :  * Returns: A dbus message containing an error on failure or NULL on success
    2229             :  *
    2230             :  * Sets the PKCS #11 engine and module path.
    2231             :  */
    2232           4 : DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
    2233             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2234             : {
    2235             :         DBusMessageIter iter;
    2236           4 :         char *value = NULL;
    2237           4 :         char *pkcs11_engine_path = NULL;
    2238           4 :         char *pkcs11_module_path = NULL;
    2239             : 
    2240           4 :         dbus_message_iter_init(message, &iter);
    2241           4 :         dbus_message_iter_get_basic(&iter, &value);
    2242           4 :         if (value == NULL) {
    2243           0 :                 return dbus_message_new_error(
    2244             :                         message, DBUS_ERROR_INVALID_ARGS,
    2245             :                         "Invalid pkcs11_engine_path argument");
    2246             :         }
    2247             :         /* Empty path defaults to NULL */
    2248           4 :         if (os_strlen(value))
    2249           2 :                 pkcs11_engine_path = value;
    2250             : 
    2251           4 :         dbus_message_iter_next(&iter);
    2252           4 :         dbus_message_iter_get_basic(&iter, &value);
    2253           4 :         if (value == NULL) {
    2254           0 :                 os_free(pkcs11_engine_path);
    2255           0 :                 return dbus_message_new_error(
    2256             :                         message, DBUS_ERROR_INVALID_ARGS,
    2257             :                         "Invalid pkcs11_module_path argument");
    2258             :         }
    2259             :         /* Empty path defaults to NULL */
    2260           4 :         if (os_strlen(value))
    2261           2 :                 pkcs11_module_path = value;
    2262             : 
    2263           4 :         if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
    2264             :                                                    pkcs11_module_path))
    2265           0 :                 return dbus_message_new_error(
    2266             :                         message, DBUS_ERROR_FAILED,
    2267             :                         "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
    2268             : 
    2269           4 :         wpa_dbus_mark_property_changed(
    2270           4 :                 wpa_s->global->dbus, wpa_s->dbus_new_path,
    2271             :                 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
    2272           4 :         wpa_dbus_mark_property_changed(
    2273           4 :                 wpa_s->global->dbus, wpa_s->dbus_new_path,
    2274             :                 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
    2275             : 
    2276           4 :         return NULL;
    2277             : }
    2278             : 
    2279             : 
    2280             : /**
    2281             :  * wpas_dbus_getter_capabilities - Return interface capabilities
    2282             :  * @iter: Pointer to incoming dbus message iter
    2283             :  * @error: Location to store error on failure
    2284             :  * @user_data: Function specific data
    2285             :  * Returns: TRUE on success, FALSE on failure
    2286             :  *
    2287             :  * Getter for "Capabilities" property of an interface.
    2288             :  */
    2289          57 : dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
    2290             :                                           DBusError *error, void *user_data)
    2291             : {
    2292          57 :         struct wpa_supplicant *wpa_s = user_data;
    2293             :         struct wpa_driver_capa capa;
    2294             :         int res;
    2295             :         DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
    2296             :                 variant_iter;
    2297          57 :         const char *scans[] = { "active", "passive", "ssid" };
    2298             : 
    2299          57 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    2300          57 :                                               "a{sv}", &variant_iter) ||
    2301          57 :             !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
    2302             :                 goto nomem;
    2303             : 
    2304          57 :         res = wpa_drv_get_capa(wpa_s, &capa);
    2305             : 
    2306             :         /***** pairwise cipher */
    2307          57 :         if (res < 0) {
    2308          20 :                 const char *args[] = {"ccmp", "tkip", "none"};
    2309             : 
    2310          20 :                 if (!wpa_dbus_dict_append_string_array(
    2311             :                             &iter_dict, "Pairwise", args,
    2312             :                             ARRAY_SIZE(args)))
    2313           0 :                         goto nomem;
    2314             :         } else {
    2315          37 :                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
    2316             :                                                       &iter_dict_entry,
    2317             :                                                       &iter_dict_val,
    2318          37 :                                                       &iter_array) ||
    2319          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
    2320          37 :                      !wpa_dbus_dict_string_array_add_element(
    2321          37 :                              &iter_array, "ccmp-256")) ||
    2322          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
    2323          37 :                      !wpa_dbus_dict_string_array_add_element(
    2324          37 :                              &iter_array, "gcmp-256")) ||
    2325          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
    2326          37 :                      !wpa_dbus_dict_string_array_add_element(
    2327          37 :                              &iter_array, "ccmp")) ||
    2328          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
    2329          37 :                      !wpa_dbus_dict_string_array_add_element(
    2330          37 :                              &iter_array, "gcmp")) ||
    2331          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
    2332          37 :                      !wpa_dbus_dict_string_array_add_element(
    2333          37 :                              &iter_array, "tkip")) ||
    2334          37 :                     ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
    2335           0 :                      !wpa_dbus_dict_string_array_add_element(
    2336          37 :                              &iter_array, "none")) ||
    2337          37 :                     !wpa_dbus_dict_end_string_array(&iter_dict,
    2338             :                                                     &iter_dict_entry,
    2339             :                                                     &iter_dict_val,
    2340             :                                                     &iter_array))
    2341             :                         goto nomem;
    2342             :         }
    2343             : 
    2344             :         /***** group cipher */
    2345          57 :         if (res < 0) {
    2346          20 :                 const char *args[] = {
    2347             :                         "ccmp", "tkip", "wep104", "wep40"
    2348             :                 };
    2349             : 
    2350          20 :                 if (!wpa_dbus_dict_append_string_array(
    2351             :                             &iter_dict, "Group", args,
    2352             :                             ARRAY_SIZE(args)))
    2353           0 :                         goto nomem;
    2354             :         } else {
    2355          37 :                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
    2356             :                                                       &iter_dict_entry,
    2357             :                                                       &iter_dict_val,
    2358          37 :                                                       &iter_array) ||
    2359          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
    2360          37 :                      !wpa_dbus_dict_string_array_add_element(
    2361          37 :                              &iter_array, "ccmp-256")) ||
    2362          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
    2363          37 :                      !wpa_dbus_dict_string_array_add_element(
    2364          37 :                              &iter_array, "gcmp-256")) ||
    2365          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
    2366          37 :                      !wpa_dbus_dict_string_array_add_element(
    2367          37 :                              &iter_array, "ccmp")) ||
    2368          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
    2369          37 :                      !wpa_dbus_dict_string_array_add_element(
    2370          37 :                              &iter_array, "gcmp")) ||
    2371          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
    2372          37 :                      !wpa_dbus_dict_string_array_add_element(
    2373          37 :                              &iter_array, "tkip")) ||
    2374          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
    2375          37 :                      !wpa_dbus_dict_string_array_add_element(
    2376          37 :                              &iter_array, "wep104")) ||
    2377          74 :                     ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
    2378          37 :                      !wpa_dbus_dict_string_array_add_element(
    2379          37 :                              &iter_array, "wep40")) ||
    2380          37 :                     !wpa_dbus_dict_end_string_array(&iter_dict,
    2381             :                                                     &iter_dict_entry,
    2382             :                                                     &iter_dict_val,
    2383             :                                                     &iter_array))
    2384             :                         goto nomem;
    2385             :         }
    2386             : 
    2387             :         /***** key management */
    2388          57 :         if (res < 0) {
    2389          20 :                 const char *args[] = {
    2390             :                         "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
    2391             : #ifdef CONFIG_WPS
    2392             :                         "wps",
    2393             : #endif /* CONFIG_WPS */
    2394             :                         "none"
    2395             :                 };
    2396          20 :                 if (!wpa_dbus_dict_append_string_array(
    2397             :                             &iter_dict, "KeyMgmt", args,
    2398             :                             ARRAY_SIZE(args)))
    2399           0 :                         goto nomem;
    2400             :         } else {
    2401          37 :                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
    2402             :                                                       &iter_dict_entry,
    2403             :                                                       &iter_dict_val,
    2404          37 :                                                       &iter_array) ||
    2405          37 :                     !wpa_dbus_dict_string_array_add_element(&iter_array,
    2406          37 :                                                             "none") ||
    2407          37 :                     !wpa_dbus_dict_string_array_add_element(&iter_array,
    2408             :                                                             "ieee8021x"))
    2409             :                         goto nomem;
    2410             : 
    2411          37 :                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
    2412             :                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
    2413          37 :                         if (!wpa_dbus_dict_string_array_add_element(
    2414          37 :                                     &iter_array, "wpa-eap") ||
    2415          54 :                             ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
    2416          17 :                              !wpa_dbus_dict_string_array_add_element(
    2417             :                                      &iter_array, "wpa-ft-eap")))
    2418             :                                 goto nomem;
    2419             : 
    2420             : /* TODO: Ensure that driver actually supports sha256 encryption. */
    2421             : #ifdef CONFIG_IEEE80211W
    2422          37 :                         if (!wpa_dbus_dict_string_array_add_element(
    2423             :                                     &iter_array, "wpa-eap-sha256"))
    2424           0 :                                 goto nomem;
    2425             : #endif /* CONFIG_IEEE80211W */
    2426             :                 }
    2427             : 
    2428          37 :                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
    2429             :                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
    2430          37 :                         if (!wpa_dbus_dict_string_array_add_element(
    2431          37 :                                     &iter_array, "wpa-psk") ||
    2432          37 :                             ((capa.key_mgmt &
    2433          17 :                               WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
    2434          17 :                              !wpa_dbus_dict_string_array_add_element(
    2435             :                                      &iter_array, "wpa-ft-psk")))
    2436             :                                 goto nomem;
    2437             : 
    2438             : /* TODO: Ensure that driver actually supports sha256 encryption. */
    2439             : #ifdef CONFIG_IEEE80211W
    2440          37 :                         if (!wpa_dbus_dict_string_array_add_element(
    2441             :                                     &iter_array, "wpa-psk-sha256"))
    2442           0 :                                 goto nomem;
    2443             : #endif /* CONFIG_IEEE80211W */
    2444             :                 }
    2445             : 
    2446          37 :                 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
    2447           0 :                     !wpa_dbus_dict_string_array_add_element(&iter_array,
    2448             :                                                             "wpa-none"))
    2449           0 :                         goto nomem;
    2450             : 
    2451             : 
    2452             : #ifdef CONFIG_WPS
    2453          37 :                 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
    2454             :                                                             "wps"))
    2455           0 :                         goto nomem;
    2456             : #endif /* CONFIG_WPS */
    2457             : 
    2458          37 :                 if (!wpa_dbus_dict_end_string_array(&iter_dict,
    2459             :                                                     &iter_dict_entry,
    2460             :                                                     &iter_dict_val,
    2461             :                                                     &iter_array))
    2462           0 :                         goto nomem;
    2463             :         }
    2464             : 
    2465             :         /***** WPA protocol */
    2466          57 :         if (res < 0) {
    2467          20 :                 const char *args[] = { "rsn", "wpa" };
    2468             : 
    2469          20 :                 if (!wpa_dbus_dict_append_string_array(
    2470             :                             &iter_dict, "Protocol", args,
    2471             :                             ARRAY_SIZE(args)))
    2472           0 :                         goto nomem;
    2473             :         } else {
    2474          37 :                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
    2475             :                                                       &iter_dict_entry,
    2476             :                                                       &iter_dict_val,
    2477          37 :                                                       &iter_array) ||
    2478          37 :                     ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
    2479          37 :                                        WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
    2480          37 :                      !wpa_dbus_dict_string_array_add_element(
    2481          37 :                              &iter_array, "rsn")) ||
    2482          37 :                     ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
    2483          37 :                                        WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
    2484          37 :                      !wpa_dbus_dict_string_array_add_element(
    2485          37 :                              &iter_array, "wpa")) ||
    2486          37 :                     !wpa_dbus_dict_end_string_array(&iter_dict,
    2487             :                                                     &iter_dict_entry,
    2488             :                                                     &iter_dict_val,
    2489             :                                                     &iter_array))
    2490             :                         goto nomem;
    2491             :         }
    2492             : 
    2493             :         /***** auth alg */
    2494          57 :         if (res < 0) {
    2495          20 :                 const char *args[] = { "open", "shared", "leap" };
    2496             : 
    2497          20 :                 if (!wpa_dbus_dict_append_string_array(
    2498             :                             &iter_dict, "AuthAlg", args,
    2499             :                             ARRAY_SIZE(args)))
    2500           0 :                         goto nomem;
    2501             :         } else {
    2502          37 :                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
    2503             :                                                       &iter_dict_entry,
    2504             :                                                       &iter_dict_val,
    2505             :                                                       &iter_array))
    2506           0 :                         goto nomem;
    2507             : 
    2508          74 :                 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
    2509          37 :                      !wpa_dbus_dict_string_array_add_element(
    2510          37 :                              &iter_array, "open")) ||
    2511          74 :                     ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
    2512          37 :                      !wpa_dbus_dict_string_array_add_element(
    2513          37 :                              &iter_array, "shared")) ||
    2514          74 :                     ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
    2515          37 :                      !wpa_dbus_dict_string_array_add_element(
    2516          37 :                              &iter_array, "leap")) ||
    2517          37 :                     !wpa_dbus_dict_end_string_array(&iter_dict,
    2518             :                                                     &iter_dict_entry,
    2519             :                                                     &iter_dict_val,
    2520             :                                                     &iter_array))
    2521             :                         goto nomem;
    2522             :         }
    2523             : 
    2524             :         /***** Scan */
    2525          57 :         if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
    2526             :                                                ARRAY_SIZE(scans)))
    2527           0 :                 goto nomem;
    2528             : 
    2529             :         /***** Modes */
    2530          57 :         if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
    2531             :                                               &iter_dict_entry,
    2532             :                                               &iter_dict_val,
    2533          57 :                                               &iter_array) ||
    2534          57 :             !wpa_dbus_dict_string_array_add_element(
    2535          57 :                     &iter_array, "infrastructure") ||
    2536          57 :             !wpa_dbus_dict_string_array_add_element(
    2537          57 :                     &iter_array, "ad-hoc") ||
    2538          74 :             (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
    2539          37 :              !wpa_dbus_dict_string_array_add_element(
    2540          57 :                      &iter_array, "ap")) ||
    2541          74 :             (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
    2542          37 :              !wpa_dbus_dict_string_array_add_element(
    2543          57 :                      &iter_array, "p2p")) ||
    2544          57 :             !wpa_dbus_dict_end_string_array(&iter_dict,
    2545             :                                             &iter_dict_entry,
    2546             :                                             &iter_dict_val,
    2547             :                                             &iter_array))
    2548             :                 goto nomem;
    2549             :         /***** Modes end */
    2550             : 
    2551          57 :         if (res >= 0) {
    2552          37 :                 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
    2553             : 
    2554          37 :                 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
    2555             :                                                 max_scan_ssid))
    2556           0 :                         goto nomem;
    2557             :         }
    2558             : 
    2559         114 :         if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
    2560          57 :             !dbus_message_iter_close_container(iter, &variant_iter))
    2561             :                 goto nomem;
    2562             : 
    2563          57 :         return TRUE;
    2564             : 
    2565             : nomem:
    2566           0 :         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    2567           0 :         return FALSE;
    2568             : }
    2569             : 
    2570             : 
    2571             : /**
    2572             :  * wpas_dbus_getter_state - Get interface state
    2573             :  * @iter: Pointer to incoming dbus message iter
    2574             :  * @error: Location to store error on failure
    2575             :  * @user_data: Function specific data
    2576             :  * Returns: TRUE on success, FALSE on failure
    2577             :  *
    2578             :  * Getter for "State" property.
    2579             :  */
    2580       21616 : dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
    2581             :                                    void *user_data)
    2582             : {
    2583       21616 :         struct wpa_supplicant *wpa_s = user_data;
    2584             :         const char *str_state;
    2585             :         char *state_ls, *tmp;
    2586       21616 :         dbus_bool_t success = FALSE;
    2587             : 
    2588       21616 :         str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
    2589             : 
    2590             :         /* make state string lowercase to fit new DBus API convention
    2591             :          */
    2592       21616 :         state_ls = tmp = os_strdup(str_state);
    2593       21616 :         if (!tmp) {
    2594           6 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    2595           6 :                 return FALSE;
    2596             :         }
    2597      282033 :         while (*tmp) {
    2598      238813 :                 *tmp = tolower(*tmp);
    2599      238813 :                 tmp++;
    2600             :         }
    2601             : 
    2602       21610 :         success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    2603             :                                                    &state_ls, error);
    2604             : 
    2605       21610 :         os_free(state_ls);
    2606             : 
    2607       21610 :         return success;
    2608             : }
    2609             : 
    2610             : 
    2611             : /**
    2612             :  * wpas_dbus_new_iface_get_scanning - Get interface scanning state
    2613             :  * @iter: Pointer to incoming dbus message iter
    2614             :  * @error: Location to store error on failure
    2615             :  * @user_data: Function specific data
    2616             :  * Returns: TRUE on success, FALSE on failure
    2617             :  *
    2618             :  * Getter for "scanning" property.
    2619             :  */
    2620        5314 : dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
    2621             :                                       void *user_data)
    2622             : {
    2623        5314 :         struct wpa_supplicant *wpa_s = user_data;
    2624        5314 :         dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
    2625             : 
    2626        5314 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
    2627             :                                                 &scanning, error);
    2628             : }
    2629             : 
    2630             : 
    2631             : /**
    2632             :  * wpas_dbus_getter_ap_scan - Control roaming mode
    2633             :  * @iter: Pointer to incoming dbus message iter
    2634             :  * @error: Location to store error on failure
    2635             :  * @user_data: Function specific data
    2636             :  * Returns: TRUE on success, FALSE on failure
    2637             :  *
    2638             :  * Getter function for "ApScan" property.
    2639             :  */
    2640          76 : dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
    2641             :                                      void *user_data)
    2642             : {
    2643          76 :         struct wpa_supplicant *wpa_s = user_data;
    2644          76 :         dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
    2645             : 
    2646          76 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
    2647             :                                                 &ap_scan, error);
    2648             : }
    2649             : 
    2650             : 
    2651             : /**
    2652             :  * wpas_dbus_setter_ap_scan - Control roaming mode
    2653             :  * @iter: Pointer to incoming dbus message iter
    2654             :  * @error: Location to store error on failure
    2655             :  * @user_data: Function specific data
    2656             :  * Returns: TRUE on success, FALSE on failure
    2657             :  *
    2658             :  * Setter function for "ApScan" property.
    2659             :  */
    2660           6 : dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
    2661             :                                      void *user_data)
    2662             : {
    2663           6 :         struct wpa_supplicant *wpa_s = user_data;
    2664             :         dbus_uint32_t ap_scan;
    2665             : 
    2666           6 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
    2667             :                                               &ap_scan))
    2668           1 :                 return FALSE;
    2669             : 
    2670           5 :         if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
    2671           1 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
    2672             :                                      "ap_scan must be 0, 1, or 2");
    2673           1 :                 return FALSE;
    2674             :         }
    2675           4 :         return TRUE;
    2676             : }
    2677             : 
    2678             : 
    2679             : /**
    2680             :  * wpas_dbus_getter_fast_reauth - Control fast
    2681             :  * reauthentication (TLS session resumption)
    2682             :  * @iter: Pointer to incoming dbus message iter
    2683             :  * @error: Location to store error on failure
    2684             :  * @user_data: Function specific data
    2685             :  * Returns: TRUE on success, FALSE on failure
    2686             :  *
    2687             :  * Getter function for "FastReauth" property.
    2688             :  */
    2689          57 : dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
    2690             :                                          DBusError *error,
    2691             :                                          void *user_data)
    2692             : {
    2693          57 :         struct wpa_supplicant *wpa_s = user_data;
    2694          57 :         dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
    2695             : 
    2696          57 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
    2697             :                                                 &fast_reauth, error);
    2698             : }
    2699             : 
    2700             : 
    2701             : /**
    2702             :  * wpas_dbus_setter_fast_reauth - Control fast
    2703             :  * reauthentication (TLS session resumption)
    2704             :  * @iter: Pointer to incoming dbus message iter
    2705             :  * @error: Location to store error on failure
    2706             :  * @user_data: Function specific data
    2707             :  * Returns: TRUE on success, FALSE on failure
    2708             :  *
    2709             :  * Setter function for "FastReauth" property.
    2710             :  */
    2711           4 : dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
    2712             :                                      DBusError *error,
    2713             :                                      void *user_data)
    2714             : {
    2715           4 :         struct wpa_supplicant *wpa_s = user_data;
    2716             :         dbus_bool_t fast_reauth;
    2717             : 
    2718           4 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
    2719             :                                               &fast_reauth))
    2720           1 :                 return FALSE;
    2721             : 
    2722           3 :         wpa_s->conf->fast_reauth = fast_reauth;
    2723           3 :         return TRUE;
    2724             : }
    2725             : 
    2726             : 
    2727             : /**
    2728             :  * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
    2729             :  * @iter: Pointer to incoming dbus message iter
    2730             :  * @error: Location to store error on failure
    2731             :  * @user_data: Function specific data
    2732             :  * Returns: TRUE on success, FALSE on failure
    2733             :  *
    2734             :  * Getter for "DisconnectReason" property.  The reason is negative if it is
    2735             :  * locally generated.
    2736             :  */
    2737        3256 : dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
    2738             :                                                DBusError *error,
    2739             :                                                void *user_data)
    2740             : {
    2741        3256 :         struct wpa_supplicant *wpa_s = user_data;
    2742        3256 :         dbus_int32_t reason = wpa_s->disconnect_reason;
    2743             : 
    2744        3256 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
    2745             :                                                 &reason, error);
    2746             : }
    2747             : 
    2748             : 
    2749             : /**
    2750             :  * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
    2751             :  * @iter: Pointer to incoming dbus message iter
    2752             :  * @error: Location to store error on failure
    2753             :  * @user_data: Function specific data
    2754             :  * Returns: TRUE on success, FALSE on failure
    2755             :  *
    2756             :  * Getter function for "BSSExpireAge" property.
    2757             :  */
    2758          57 : dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
    2759             :                                             DBusError *error,
    2760             :                                             void *user_data)
    2761             : {
    2762          57 :         struct wpa_supplicant *wpa_s = user_data;
    2763          57 :         dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
    2764             : 
    2765          57 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
    2766             :                                                 &expire_age, error);
    2767             : }
    2768             : 
    2769             : 
    2770             : /**
    2771             :  * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
    2772             :  * @iter: Pointer to incoming dbus message iter
    2773             :  * @error: Location to store error on failure
    2774             :  * @user_data: Function specific data
    2775             :  * Returns: TRUE on success, FALSE on failure
    2776             :  *
    2777             :  * Setter function for "BSSExpireAge" property.
    2778             :  */
    2779           4 : dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
    2780             :                                             DBusError *error,
    2781             :                                             void *user_data)
    2782             : {
    2783           4 :         struct wpa_supplicant *wpa_s = user_data;
    2784             :         dbus_uint32_t expire_age;
    2785             : 
    2786           4 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
    2787             :                                               &expire_age))
    2788           1 :                 return FALSE;
    2789             : 
    2790           3 :         if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
    2791           1 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
    2792             :                                      "BSSExpireAge must be >= 10");
    2793           1 :                 return FALSE;
    2794             :         }
    2795           2 :         return TRUE;
    2796             : }
    2797             : 
    2798             : 
    2799             : /**
    2800             :  * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
    2801             :  * @iter: Pointer to incoming dbus message iter
    2802             :  * @error: Location to store error on failure
    2803             :  * @user_data: Function specific data
    2804             :  * Returns: TRUE on success, FALSE on failure
    2805             :  *
    2806             :  * Getter function for "BSSExpireCount" property.
    2807             :  */
    2808          57 : dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
    2809             :                                               DBusError *error,
    2810             :                                               void *user_data)
    2811             : {
    2812          57 :         struct wpa_supplicant *wpa_s = user_data;
    2813          57 :         dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
    2814             : 
    2815          57 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
    2816             :                                                 &expire_count, error);
    2817             : }
    2818             : 
    2819             : 
    2820             : /**
    2821             :  * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
    2822             :  * @iter: Pointer to incoming dbus message iter
    2823             :  * @error: Location to store error on failure
    2824             :  * @user_data: Function specific data
    2825             :  * Returns: TRUE on success, FALSE on failure
    2826             :  *
    2827             :  * Setter function for "BSSExpireCount" property.
    2828             :  */
    2829           4 : dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
    2830             :                                               DBusError *error,
    2831             :                                               void *user_data)
    2832             : {
    2833           4 :         struct wpa_supplicant *wpa_s = user_data;
    2834             :         dbus_uint32_t expire_count;
    2835             : 
    2836           4 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
    2837             :                                               &expire_count))
    2838           1 :                 return FALSE;
    2839             : 
    2840           3 :         if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
    2841           1 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
    2842             :                                      "BSSExpireCount must be > 0");
    2843           1 :                 return FALSE;
    2844             :         }
    2845           2 :         return TRUE;
    2846             : }
    2847             : 
    2848             : 
    2849             : /**
    2850             :  * wpas_dbus_getter_country - Control country code
    2851             :  * @iter: Pointer to incoming dbus message iter
    2852             :  * @error: Location to store error on failure
    2853             :  * @user_data: Function specific data
    2854             :  * Returns: TRUE on success, FALSE on failure
    2855             :  *
    2856             :  * Getter function for "Country" property.
    2857             :  */
    2858          57 : dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
    2859             :                                      void *user_data)
    2860             : {
    2861          57 :         struct wpa_supplicant *wpa_s = user_data;
    2862             :         char country[3];
    2863          57 :         char *str = country;
    2864             : 
    2865          57 :         country[0] = wpa_s->conf->country[0];
    2866          57 :         country[1] = wpa_s->conf->country[1];
    2867          57 :         country[2] = '\0';
    2868             : 
    2869          57 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    2870             :                                                 &str, error);
    2871             : }
    2872             : 
    2873             : 
    2874             : /**
    2875             :  * wpas_dbus_setter_country - Control country code
    2876             :  * @iter: Pointer to incoming dbus message iter
    2877             :  * @error: Location to store error on failure
    2878             :  * @user_data: Function specific data
    2879             :  * Returns: TRUE on success, FALSE on failure
    2880             :  *
    2881             :  * Setter function for "Country" property.
    2882             :  */
    2883           4 : dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
    2884             :                                      void *user_data)
    2885             : {
    2886           4 :         struct wpa_supplicant *wpa_s = user_data;
    2887             :         const char *country;
    2888             : 
    2889           4 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
    2890             :                                               &country))
    2891           1 :                 return FALSE;
    2892             : 
    2893           3 :         if (!country[0] || !country[1]) {
    2894           1 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
    2895             :                                      "invalid country code");
    2896           1 :                 return FALSE;
    2897             :         }
    2898             : 
    2899           2 :         if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
    2900           0 :                 wpa_printf(MSG_DEBUG, "Failed to set country");
    2901           0 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
    2902             :                                      "failed to set country code");
    2903           0 :                 return FALSE;
    2904             :         }
    2905             : 
    2906           2 :         wpa_s->conf->country[0] = country[0];
    2907           2 :         wpa_s->conf->country[1] = country[1];
    2908           2 :         return TRUE;
    2909             : }
    2910             : 
    2911             : 
    2912             : /**
    2913             :  * wpas_dbus_getter_scan_interval - Get scan interval
    2914             :  * @iter: Pointer to incoming dbus message iter
    2915             :  * @error: Location to store error on failure
    2916             :  * @user_data: Function specific data
    2917             :  * Returns: TRUE on success, FALSE on failure
    2918             :  *
    2919             :  * Getter function for "ScanInterval" property.
    2920             :  */
    2921          55 : dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
    2922             :                                            DBusError *error,
    2923             :                                            void *user_data)
    2924             : {
    2925          55 :         struct wpa_supplicant *wpa_s = user_data;
    2926          55 :         dbus_int32_t scan_interval = wpa_s->scan_interval;
    2927             : 
    2928          55 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
    2929             :                                                 &scan_interval, error);
    2930             : }
    2931             : 
    2932             : 
    2933             : /**
    2934             :  * wpas_dbus_setter_scan_interval - Control scan interval
    2935             :  * @iter: Pointer to incoming dbus message iter
    2936             :  * @error: Location to store error on failure
    2937             :  * @user_data: Function specific data
    2938             :  * Returns: TRUE on success, FALSE on failure
    2939             :  *
    2940             :  * Setter function for "ScanInterval" property.
    2941             :  */
    2942           4 : dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
    2943             :                                            DBusError *error,
    2944             :                                            void *user_data)
    2945             : {
    2946           4 :         struct wpa_supplicant *wpa_s = user_data;
    2947             :         dbus_int32_t scan_interval;
    2948             : 
    2949           4 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
    2950             :                                               &scan_interval))
    2951           1 :                 return FALSE;
    2952             : 
    2953           3 :         if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
    2954           1 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
    2955             :                                      "scan_interval must be >= 0");
    2956           1 :                 return FALSE;
    2957             :         }
    2958           2 :         return TRUE;
    2959             : }
    2960             : 
    2961             : 
    2962             : /**
    2963             :  * wpas_dbus_getter_ifname - Get interface name
    2964             :  * @iter: Pointer to incoming dbus message iter
    2965             :  * @error: Location to store error on failure
    2966             :  * @user_data: Function specific data
    2967             :  * Returns: TRUE on success, FALSE on failure
    2968             :  *
    2969             :  * Getter for "Ifname" property.
    2970             :  */
    2971          56 : dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
    2972             :                                     void *user_data)
    2973             : {
    2974          56 :         struct wpa_supplicant *wpa_s = user_data;
    2975          56 :         const char *ifname = wpa_s->ifname;
    2976             : 
    2977          56 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    2978             :                                                 &ifname, error);
    2979             : }
    2980             : 
    2981             : 
    2982             : /**
    2983             :  * wpas_dbus_getter_driver - Get interface name
    2984             :  * @iter: Pointer to incoming dbus message iter
    2985             :  * @error: Location to store error on failure
    2986             :  * @user_data: Function specific data
    2987             :  * Returns: TRUE on success, FALSE on failure
    2988             :  *
    2989             :  * Getter for "Driver" property.
    2990             :  */
    2991          56 : dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
    2992             :                                     void *user_data)
    2993             : {
    2994          56 :         struct wpa_supplicant *wpa_s = user_data;
    2995             :         const char *driver;
    2996             : 
    2997          56 :         if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
    2998           0 :                 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
    2999             :                            __func__);
    3000           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
    3001             :                                __func__);
    3002           0 :                 return FALSE;
    3003             :         }
    3004             : 
    3005          56 :         driver = wpa_s->driver->name;
    3006          56 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    3007             :                                                 &driver, error);
    3008             : }
    3009             : 
    3010             : 
    3011             : /**
    3012             :  * wpas_dbus_getter_current_bss - Get current bss object path
    3013             :  * @iter: Pointer to incoming dbus message iter
    3014             :  * @error: Location to store error on failure
    3015             :  * @user_data: Function specific data
    3016             :  * Returns: TRUE on success, FALSE on failure
    3017             :  *
    3018             :  * Getter for "CurrentBSS" property.
    3019             :  */
    3020        7372 : dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
    3021             :                                          DBusError *error,
    3022             :                                          void *user_data)
    3023             : {
    3024        7372 :         struct wpa_supplicant *wpa_s = user_data;
    3025        7372 :         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
    3026             : 
    3027        7372 :         if (wpa_s->current_bss)
    3028        4158 :                 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
    3029             :                             "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
    3030        4158 :                             wpa_s->dbus_new_path, wpa_s->current_bss->id);
    3031             :         else
    3032        3214 :                 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
    3033             : 
    3034        7372 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
    3035             :                                                 &bss_obj_path, error);
    3036             : }
    3037             : 
    3038             : 
    3039             : /**
    3040             :  * wpas_dbus_getter_current_network - Get current network object path
    3041             :  * @iter: Pointer to incoming dbus message iter
    3042             :  * @error: Location to store error on failure
    3043             :  * @user_data: Function specific data
    3044             :  * Returns: TRUE on success, FALSE on failure
    3045             :  *
    3046             :  * Getter for "CurrentNetwork" property.
    3047             :  */
    3048        1002 : dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
    3049             :                                              DBusError *error,
    3050             :                                              void *user_data)
    3051             : {
    3052        1002 :         struct wpa_supplicant *wpa_s = user_data;
    3053        1002 :         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
    3054             : 
    3055        1002 :         if (wpa_s->current_ssid)
    3056         886 :                 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
    3057             :                             "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
    3058         886 :                             wpa_s->dbus_new_path, wpa_s->current_ssid->id);
    3059             :         else
    3060         116 :                 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
    3061             : 
    3062        1002 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
    3063             :                                                 &net_obj_path, error);
    3064             : }
    3065             : 
    3066             : 
    3067             : /**
    3068             :  * wpas_dbus_getter_current_auth_mode - Get current authentication type
    3069             :  * @iter: Pointer to incoming dbus message iter
    3070             :  * @error: Location to store error on failure
    3071             :  * @user_data: Function specific data
    3072             :  * Returns: TRUE on success, FALSE on failure
    3073             :  *
    3074             :  * Getter for "CurrentAuthMode" property.
    3075             :  */
    3076        6354 : dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
    3077             :                                                DBusError *error,
    3078             :                                                void *user_data)
    3079             : {
    3080        6354 :         struct wpa_supplicant *wpa_s = user_data;
    3081             :         const char *eap_mode;
    3082             :         const char *auth_mode;
    3083             :         char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
    3084             : 
    3085        6354 :         if (wpa_s->wpa_state != WPA_COMPLETED) {
    3086        3162 :                 auth_mode = "INACTIVE";
    3087        5282 :         } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
    3088        2090 :             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
    3089        1118 :                 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
    3090        1118 :                 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
    3091             :                             "EAP-%s", eap_mode);
    3092        1118 :                 auth_mode = eap_mode_buf;
    3093             : 
    3094             :         } else {
    3095        2074 :                 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
    3096        2074 :                                              wpa_s->current_ssid->proto);
    3097             :         }
    3098             : 
    3099        6354 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    3100             :                                                 &auth_mode, error);
    3101             : }
    3102             : 
    3103             : 
    3104             : /**
    3105             :  * wpas_dbus_getter_bridge_ifname - Get interface name
    3106             :  * @iter: Pointer to incoming dbus message iter
    3107             :  * @error: Location to store error on failure
    3108             :  * @user_data: Function specific data
    3109             :  * Returns: TRUE on success, FALSE on failure
    3110             :  *
    3111             :  * Getter for "BridgeIfname" property.
    3112             :  */
    3113          56 : dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
    3114             :                                            DBusError *error,
    3115             :                                            void *user_data)
    3116             : {
    3117          56 :         struct wpa_supplicant *wpa_s = user_data;
    3118          56 :         const char *bridge_ifname = wpa_s->bridge_ifname;
    3119             : 
    3120          56 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    3121             :                                                 &bridge_ifname, error);
    3122             : }
    3123             : 
    3124             : 
    3125             : /**
    3126             :  * wpas_dbus_getter_bsss - Get array of BSSs objects
    3127             :  * @iter: Pointer to incoming dbus message iter
    3128             :  * @error: Location to store error on failure
    3129             :  * @user_data: Function specific data
    3130             :  * Returns: TRUE on success, FALSE on failure
    3131             :  *
    3132             :  * Getter for "BSSs" property.
    3133             :  */
    3134        3431 : dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
    3135             :                                   void *user_data)
    3136             : {
    3137        3431 :         struct wpa_supplicant *wpa_s = user_data;
    3138             :         struct wpa_bss *bss;
    3139             :         char **paths;
    3140        3431 :         unsigned int i = 0;
    3141        3431 :         dbus_bool_t success = FALSE;
    3142             : 
    3143        3431 :         paths = os_calloc(wpa_s->num_bss, sizeof(char *));
    3144        3431 :         if (!paths) {
    3145           2 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3146           2 :                 return FALSE;
    3147             :         }
    3148             : 
    3149             :         /* Loop through scan results and append each result's object path */
    3150        5572 :         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
    3151        2144 :                 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
    3152        2144 :                 if (paths[i] == NULL) {
    3153           1 :                         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
    3154             :                                              "no memory");
    3155           1 :                         goto out;
    3156             :                 }
    3157             :                 /* Construct the object path for this BSS. */
    3158        2143 :                 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
    3159             :                             "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
    3160             :                             wpa_s->dbus_new_path, bss->id);
    3161             :         }
    3162             : 
    3163        3428 :         success = wpas_dbus_simple_array_property_getter(iter,
    3164             :                                                          DBUS_TYPE_OBJECT_PATH,
    3165             :                                                          paths, wpa_s->num_bss,
    3166             :                                                          error);
    3167             : 
    3168             : out:
    3169        9001 :         while (i)
    3170        2143 :                 os_free(paths[--i]);
    3171        3429 :         os_free(paths);
    3172        3429 :         return success;
    3173             : }
    3174             : 
    3175             : 
    3176             : /**
    3177             :  * wpas_dbus_getter_networks - Get array of networks objects
    3178             :  * @iter: Pointer to incoming dbus message iter
    3179             :  * @error: Location to store error on failure
    3180             :  * @user_data: Function specific data
    3181             :  * Returns: TRUE on success, FALSE on failure
    3182             :  *
    3183             :  * Getter for "Networks" property.
    3184             :  */
    3185          62 : dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
    3186             :                                       void *user_data)
    3187             : {
    3188          62 :         struct wpa_supplicant *wpa_s = user_data;
    3189             :         struct wpa_ssid *ssid;
    3190             :         char **paths;
    3191          62 :         unsigned int i = 0, num = 0;
    3192          62 :         dbus_bool_t success = FALSE;
    3193             : 
    3194          67 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
    3195           5 :                 if (!network_is_persistent_group(ssid))
    3196           5 :                         num++;
    3197             : 
    3198          62 :         paths = os_calloc(num, sizeof(char *));
    3199          62 :         if (!paths) {
    3200           2 :                 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3201           2 :                 return FALSE;
    3202             :         }
    3203             : 
    3204             :         /* Loop through configured networks and append object path of each */
    3205          63 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    3206           4 :                 if (network_is_persistent_group(ssid))
    3207           0 :                         continue;
    3208           4 :                 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
    3209           4 :                 if (paths[i] == NULL) {
    3210           1 :                         dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
    3211             :                                        "no memory");
    3212           1 :                         goto out;
    3213             :                 }
    3214             : 
    3215             :                 /* Construct the object path for this network. */
    3216           3 :                 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
    3217             :                             "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
    3218             :                             wpa_s->dbus_new_path, ssid->id);
    3219             :         }
    3220             : 
    3221          59 :         success = wpas_dbus_simple_array_property_getter(iter,
    3222             :                                                          DBUS_TYPE_OBJECT_PATH,
    3223             :                                                          paths, num, error);
    3224             : 
    3225             : out:
    3226         123 :         while (i)
    3227           3 :                 os_free(paths[--i]);
    3228          60 :         os_free(paths);
    3229          60 :         return success;
    3230             : }
    3231             : 
    3232             : 
    3233             : /**
    3234             :  * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
    3235             :  * @iter: Pointer to incoming dbus message iter
    3236             :  * @error: Location to store error on failure
    3237             :  * @user_data: Function specific data
    3238             :  * Returns: A dbus message containing the PKCS #11 engine path
    3239             :  *
    3240             :  * Getter for "PKCS11EnginePath" property.
    3241             :  */
    3242          64 : dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
    3243             :                                                 DBusError *error,
    3244             :                                                 void *user_data)
    3245             : {
    3246          64 :         struct wpa_supplicant *wpa_s = user_data;
    3247             :         const char *pkcs11_engine_path;
    3248             : 
    3249          64 :         if (wpa_s->conf->pkcs11_engine_path == NULL)
    3250          60 :                 pkcs11_engine_path = "";
    3251             :         else
    3252           4 :                 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
    3253          64 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    3254             :                                                 &pkcs11_engine_path, error);
    3255             : }
    3256             : 
    3257             : 
    3258             : /**
    3259             :  * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
    3260             :  * @iter: Pointer to incoming dbus message iter
    3261             :  * @error: Location to store error on failure
    3262             :  * @user_data: Function specific data
    3263             :  * Returns: A dbus message containing the PKCS #11 module path
    3264             :  *
    3265             :  * Getter for "PKCS11ModulePath" property.
    3266             :  */
    3267          64 : dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
    3268             :                                                 DBusError *error,
    3269             :                                                 void *user_data)
    3270             : {
    3271          64 :         struct wpa_supplicant *wpa_s = user_data;
    3272             :         const char *pkcs11_module_path;
    3273             : 
    3274          64 :         if (wpa_s->conf->pkcs11_module_path == NULL)
    3275          59 :                 pkcs11_module_path = "";
    3276             :         else
    3277           5 :                 pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
    3278          64 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    3279             :                                                 &pkcs11_module_path, error);
    3280             : }
    3281             : 
    3282             : 
    3283             : /**
    3284             :  * wpas_dbus_getter_blobs - Get all blobs defined for this interface
    3285             :  * @iter: Pointer to incoming dbus message iter
    3286             :  * @error: Location to store error on failure
    3287             :  * @user_data: Function specific data
    3288             :  * Returns: TRUE on success, FALSE on failure
    3289             :  *
    3290             :  * Getter for "Blobs" property.
    3291             :  */
    3292          57 : dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
    3293             :                                    void *user_data)
    3294             : {
    3295          57 :         struct wpa_supplicant *wpa_s = user_data;
    3296             :         DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
    3297             :         struct wpa_config_blob *blob;
    3298             : 
    3299          57 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    3300          57 :                                               "a{say}", &variant_iter) ||
    3301          57 :             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
    3302             :                                               "{say}", &dict_iter)) {
    3303           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3304           0 :                 return FALSE;
    3305             :         }
    3306             : 
    3307          57 :         blob = wpa_s->conf->blobs;
    3308         115 :         while (blob) {
    3309           1 :                 if (!dbus_message_iter_open_container(&dict_iter,
    3310             :                                                       DBUS_TYPE_DICT_ENTRY,
    3311           1 :                                                       NULL, &entry_iter) ||
    3312           1 :                     !dbus_message_iter_append_basic(&entry_iter,
    3313             :                                                     DBUS_TYPE_STRING,
    3314           2 :                                                     &(blob->name)) ||
    3315           1 :                     !dbus_message_iter_open_container(&entry_iter,
    3316             :                                                       DBUS_TYPE_ARRAY,
    3317             :                                                       DBUS_TYPE_BYTE_AS_STRING,
    3318           1 :                                                       &array_iter) ||
    3319           2 :                     !dbus_message_iter_append_fixed_array(&array_iter,
    3320             :                                                           DBUS_TYPE_BYTE,
    3321           1 :                                                           &(blob->data),
    3322           2 :                                                           blob->len) ||
    3323           1 :                     !dbus_message_iter_close_container(&entry_iter,
    3324           1 :                                                        &array_iter) ||
    3325           1 :                     !dbus_message_iter_close_container(&dict_iter,
    3326             :                                                        &entry_iter)) {
    3327           0 :                         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
    3328             :                                              "no memory");
    3329           0 :                         return FALSE;
    3330             :                 }
    3331             : 
    3332           1 :                 blob = blob->next;
    3333             :         }
    3334             : 
    3335         114 :         if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
    3336          57 :             !dbus_message_iter_close_container(iter, &variant_iter)) {
    3337           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3338           0 :                 return FALSE;
    3339             :         }
    3340             : 
    3341          57 :         return TRUE;
    3342             : }
    3343             : 
    3344             : 
    3345       13623 : static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
    3346             :                                        DBusError *error, const char *func_name)
    3347             : {
    3348       13623 :         struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
    3349             : 
    3350       13623 :         if (!res) {
    3351           0 :                 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
    3352             :                            func_name, args->id);
    3353           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    3354             :                                "%s: BSS %d not found",
    3355             :                                func_name, args->id);
    3356             :         }
    3357             : 
    3358       13623 :         return res;
    3359             : }
    3360             : 
    3361             : 
    3362             : /**
    3363             :  * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
    3364             :  * @iter: Pointer to incoming dbus message iter
    3365             :  * @error: Location to store error on failure
    3366             :  * @user_data: Function specific data
    3367             :  * Returns: TRUE on success, FALSE on failure
    3368             :  *
    3369             :  * Getter for "BSSID" property.
    3370             :  */
    3371        1007 : dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
    3372             :                                        void *user_data)
    3373             : {
    3374        1007 :         struct bss_handler_args *args = user_data;
    3375             :         struct wpa_bss *res;
    3376             : 
    3377        1007 :         res = get_bss_helper(args, error, __func__);
    3378        1007 :         if (!res)
    3379           0 :                 return FALSE;
    3380             : 
    3381        1007 :         return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
    3382        1007 :                                                       res->bssid, ETH_ALEN,
    3383             :                                                       error);
    3384             : }
    3385             : 
    3386             : 
    3387             : /**
    3388             :  * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
    3389             :  * @iter: Pointer to incoming dbus message iter
    3390             :  * @error: Location to store error on failure
    3391             :  * @user_data: Function specific data
    3392             :  * Returns: TRUE on success, FALSE on failure
    3393             :  *
    3394             :  * Getter for "SSID" property.
    3395             :  */
    3396        1007 : dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
    3397             :                                       void *user_data)
    3398             : {
    3399        1007 :         struct bss_handler_args *args = user_data;
    3400             :         struct wpa_bss *res;
    3401             : 
    3402        1007 :         res = get_bss_helper(args, error, __func__);
    3403        1007 :         if (!res)
    3404           0 :                 return FALSE;
    3405             : 
    3406        2014 :         return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
    3407        1007 :                                                       res->ssid, res->ssid_len,
    3408             :                                                       error);
    3409             : }
    3410             : 
    3411             : 
    3412             : /**
    3413             :  * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
    3414             :  * @iter: Pointer to incoming dbus message iter
    3415             :  * @error: Location to store error on failure
    3416             :  * @user_data: Function specific data
    3417             :  * Returns: TRUE on success, FALSE on failure
    3418             :  *
    3419             :  * Getter for "Privacy" property.
    3420             :  */
    3421        1025 : dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
    3422             :                                          DBusError *error, void *user_data)
    3423             : {
    3424        1025 :         struct bss_handler_args *args = user_data;
    3425             :         struct wpa_bss *res;
    3426             :         dbus_bool_t privacy;
    3427             : 
    3428        1025 :         res = get_bss_helper(args, error, __func__);
    3429        1025 :         if (!res)
    3430           0 :                 return FALSE;
    3431             : 
    3432        1025 :         privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
    3433        1025 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
    3434             :                                                 &privacy, error);
    3435             : }
    3436             : 
    3437             : 
    3438             : /**
    3439             :  * wpas_dbus_getter_bss_mode - Return the mode of a BSS
    3440             :  * @iter: Pointer to incoming dbus message iter
    3441             :  * @error: Location to store error on failure
    3442             :  * @user_data: Function specific data
    3443             :  * Returns: TRUE on success, FALSE on failure
    3444             :  *
    3445             :  * Getter for "Mode" property.
    3446             :  */
    3447        1007 : dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
    3448             :                                       void *user_data)
    3449             : {
    3450        1007 :         struct bss_handler_args *args = user_data;
    3451             :         struct wpa_bss *res;
    3452             :         const char *mode;
    3453             : 
    3454        1007 :         res = get_bss_helper(args, error, __func__);
    3455        1007 :         if (!res)
    3456           0 :                 return FALSE;
    3457        1007 :         if (bss_is_dmg(res)) {
    3458           0 :                 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
    3459             :                 case IEEE80211_CAP_DMG_PBSS:
    3460             :                 case IEEE80211_CAP_DMG_IBSS:
    3461           0 :                         mode = "ad-hoc";
    3462           0 :                         break;
    3463             :                 case IEEE80211_CAP_DMG_AP:
    3464           0 :                         mode = "infrastructure";
    3465           0 :                         break;
    3466             :                 }
    3467             :         } else {
    3468        1007 :                 if (res->caps & IEEE80211_CAP_IBSS)
    3469           6 :                         mode = "ad-hoc";
    3470             :                 else
    3471        1001 :                         mode = "infrastructure";
    3472             :         }
    3473             : 
    3474        1007 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    3475             :                                                 &mode, error);
    3476             : }
    3477             : 
    3478             : 
    3479             : /**
    3480             :  * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
    3481             :  * @iter: Pointer to incoming dbus message iter
    3482             :  * @error: Location to store error on failure
    3483             :  * @user_data: Function specific data
    3484             :  * Returns: TRUE on success, FALSE on failure
    3485             :  *
    3486             :  * Getter for "Level" property.
    3487             :  */
    3488        1007 : dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
    3489             :                                         DBusError *error, void *user_data)
    3490             : {
    3491        1007 :         struct bss_handler_args *args = user_data;
    3492             :         struct wpa_bss *res;
    3493             :         s16 level;
    3494             : 
    3495        1007 :         res = get_bss_helper(args, error, __func__);
    3496        1007 :         if (!res)
    3497           0 :                 return FALSE;
    3498             : 
    3499        1007 :         level = (s16) res->level;
    3500        1007 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
    3501             :                                                 &level, error);
    3502             : }
    3503             : 
    3504             : 
    3505             : /**
    3506             :  * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
    3507             :  * @iter: Pointer to incoming dbus message iter
    3508             :  * @error: Location to store error on failure
    3509             :  * @user_data: Function specific data
    3510             :  * Returns: TRUE on success, FALSE on failure
    3511             :  *
    3512             :  * Getter for "Frequency" property.
    3513             :  */
    3514        1013 : dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
    3515             :                                            DBusError *error, void *user_data)
    3516             : {
    3517        1013 :         struct bss_handler_args *args = user_data;
    3518             :         struct wpa_bss *res;
    3519             :         u16 freq;
    3520             : 
    3521        1013 :         res = get_bss_helper(args, error, __func__);
    3522        1013 :         if (!res)
    3523           0 :                 return FALSE;
    3524             : 
    3525        1013 :         freq = (u16) res->freq;
    3526        1013 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
    3527             :                                                 &freq, error);
    3528             : }
    3529             : 
    3530             : 
    3531       21974 : static int cmp_u8s_desc(const void *a, const void *b)
    3532             : {
    3533       21974 :         return (*(u8 *) b - *(u8 *) a);
    3534             : }
    3535             : 
    3536             : 
    3537             : /**
    3538             :  * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
    3539             :  * @iter: Pointer to incoming dbus message iter
    3540             :  * @error: Location to store error on failure
    3541             :  * @user_data: Function specific data
    3542             :  * Returns: TRUE on success, FALSE on failure
    3543             :  *
    3544             :  * Getter for "Rates" property.
    3545             :  */
    3546        1008 : dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
    3547             :                                        DBusError *error, void *user_data)
    3548             : {
    3549        1008 :         struct bss_handler_args *args = user_data;
    3550             :         struct wpa_bss *res;
    3551        1008 :         u8 *ie_rates = NULL;
    3552             :         u32 *real_rates;
    3553             :         int rates_num, i;
    3554        1008 :         dbus_bool_t success = FALSE;
    3555             : 
    3556        1008 :         res = get_bss_helper(args, error, __func__);
    3557        1008 :         if (!res)
    3558           0 :                 return FALSE;
    3559             : 
    3560        1008 :         rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
    3561        1008 :         if (rates_num < 0)
    3562           0 :                 return FALSE;
    3563             : 
    3564        1008 :         qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
    3565             : 
    3566        1008 :         real_rates = os_malloc(sizeof(u32) * rates_num);
    3567        1008 :         if (!real_rates) {
    3568           1 :                 os_free(ie_rates);
    3569           1 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3570           1 :                 return FALSE;
    3571             :         }
    3572             : 
    3573       12647 :         for (i = 0; i < rates_num; i++)
    3574       11640 :                 real_rates[i] = ie_rates[i] * 500000;
    3575             : 
    3576        1007 :         success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
    3577             :                                                          real_rates, rates_num,
    3578             :                                                          error);
    3579             : 
    3580        1007 :         os_free(ie_rates);
    3581        1007 :         os_free(real_rates);
    3582        1007 :         return success;
    3583             : }
    3584             : 
    3585             : 
    3586        2056 : static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
    3587             :                                                    struct wpa_ie_data *ie_data,
    3588             :                                                    DBusError *error)
    3589             : {
    3590             :         DBusMessageIter iter_dict, variant_iter;
    3591             :         const char *group;
    3592             :         const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
    3593             :         const char *key_mgmt[9]; /* max 9 key managements may be supported */
    3594             :         int n;
    3595             : 
    3596        2056 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    3597             :                                               "a{sv}", &variant_iter))
    3598           0 :                 goto nomem;
    3599             : 
    3600        2056 :         if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
    3601           0 :                 goto nomem;
    3602             : 
    3603             :         /* KeyMgmt */
    3604        2056 :         n = 0;
    3605        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
    3606         302 :                 key_mgmt[n++] = "wpa-psk";
    3607        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
    3608          34 :                 key_mgmt[n++] = "wpa-ft-psk";
    3609        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
    3610          21 :                 key_mgmt[n++] = "wpa-psk-sha256";
    3611        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
    3612         347 :                 key_mgmt[n++] = "wpa-eap";
    3613        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
    3614           8 :                 key_mgmt[n++] = "wpa-ft-eap";
    3615        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
    3616           6 :                 key_mgmt[n++] = "wpa-eap-sha256";
    3617             : #ifdef CONFIG_SUITEB
    3618        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
    3619           1 :                 key_mgmt[n++] = "wpa-eap-suite-b";
    3620             : #endif /* CONFIG_SUITEB */
    3621             : #ifdef CONFIG_SUITEB192
    3622        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
    3623           1 :                 key_mgmt[n++] = "wpa-eap-suite-b-192";
    3624             : #endif /* CONFIG_SUITEB192 */
    3625        2056 :         if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
    3626           0 :                 key_mgmt[n++] = "wpa-none";
    3627             : 
    3628        2056 :         if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
    3629             :                                                key_mgmt, n))
    3630           0 :                 goto nomem;
    3631             : 
    3632             :         /* Group */
    3633        2056 :         switch (ie_data->group_cipher) {
    3634             :         case WPA_CIPHER_WEP40:
    3635           0 :                 group = "wep40";
    3636           0 :                 break;
    3637             :         case WPA_CIPHER_TKIP:
    3638          73 :                 group = "tkip";
    3639          73 :                 break;
    3640             :         case WPA_CIPHER_CCMP:
    3641         635 :                 group = "ccmp";
    3642         635 :                 break;
    3643             :         case WPA_CIPHER_GCMP:
    3644           2 :                 group = "gcmp";
    3645           2 :                 break;
    3646             :         case WPA_CIPHER_WEP104:
    3647           0 :                 group = "wep104";
    3648           0 :                 break;
    3649             :         case WPA_CIPHER_CCMP_256:
    3650           1 :                 group = "ccmp-256";
    3651           1 :                 break;
    3652             :         case WPA_CIPHER_GCMP_256:
    3653           2 :                 group = "gcmp-256";
    3654           2 :                 break;
    3655             :         default:
    3656        1343 :                 group = "";
    3657        1343 :                 break;
    3658             :         }
    3659             : 
    3660        2056 :         if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
    3661           0 :                 goto nomem;
    3662             : 
    3663             :         /* Pairwise */
    3664        2056 :         n = 0;
    3665        2056 :         if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
    3666          64 :                 pairwise[n++] = "tkip";
    3667        2056 :         if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
    3668         684 :                 pairwise[n++] = "ccmp";
    3669        2056 :         if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
    3670           2 :                 pairwise[n++] = "gcmp";
    3671        2056 :         if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
    3672           1 :                 pairwise[n++] = "ccmp-256";
    3673        2056 :         if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
    3674           2 :                 pairwise[n++] = "gcmp-256";
    3675             : 
    3676        2056 :         if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
    3677             :                                                pairwise, n))
    3678           0 :                 goto nomem;
    3679             : 
    3680             :         /* Management group (RSN only) */
    3681        2056 :         if (ie_data->proto == WPA_PROTO_RSN) {
    3682         669 :                 switch (ie_data->mgmt_group_cipher) {
    3683             : #ifdef CONFIG_IEEE80211W
    3684             :                 case WPA_CIPHER_AES_128_CMAC:
    3685         663 :                         group = "aes128cmac";
    3686         663 :                         break;
    3687             : #endif /* CONFIG_IEEE80211W */
    3688             :                 default:
    3689           6 :                         group = "";
    3690           6 :                         break;
    3691             :                 }
    3692             : 
    3693         669 :                 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
    3694             :                                                  group))
    3695           0 :                         goto nomem;
    3696             :         }
    3697             : 
    3698        4112 :         if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
    3699        2056 :             !dbus_message_iter_close_container(iter, &variant_iter))
    3700             :                 goto nomem;
    3701             : 
    3702        2056 :         return TRUE;
    3703             : 
    3704             : nomem:
    3705           0 :         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3706           0 :         return FALSE;
    3707             : }
    3708             : 
    3709             : 
    3710             : /**
    3711             :  * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
    3712             :  * @iter: Pointer to incoming dbus message iter
    3713             :  * @error: Location to store error on failure
    3714             :  * @user_data: Function specific data
    3715             :  * Returns: TRUE on success, FALSE on failure
    3716             :  *
    3717             :  * Getter for "WPA" property.
    3718             :  */
    3719        1025 : dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
    3720             :                                      void *user_data)
    3721             : {
    3722        1025 :         struct bss_handler_args *args = user_data;
    3723             :         struct wpa_bss *res;
    3724             :         struct wpa_ie_data wpa_data;
    3725             :         const u8 *ie;
    3726             : 
    3727        1025 :         res = get_bss_helper(args, error, __func__);
    3728        1025 :         if (!res)
    3729           0 :                 return FALSE;
    3730             : 
    3731        1025 :         os_memset(&wpa_data, 0, sizeof(wpa_data));
    3732        1025 :         ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
    3733        1025 :         if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
    3734           0 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
    3735             :                                      "failed to parse WPA IE");
    3736           0 :                 return FALSE;
    3737             :         }
    3738             : 
    3739        1025 :         return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
    3740             : }
    3741             : 
    3742             : 
    3743             : /**
    3744             :  * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
    3745             :  * @iter: Pointer to incoming dbus message iter
    3746             :  * @error: Location to store error on failure
    3747             :  * @user_data: Function specific data
    3748             :  * Returns: TRUE on success, FALSE on failure
    3749             :  *
    3750             :  * Getter for "RSN" property.
    3751             :  */
    3752        1031 : dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
    3753             :                                      void *user_data)
    3754             : {
    3755        1031 :         struct bss_handler_args *args = user_data;
    3756             :         struct wpa_bss *res;
    3757             :         struct wpa_ie_data wpa_data;
    3758             :         const u8 *ie;
    3759             : 
    3760        1031 :         res = get_bss_helper(args, error, __func__);
    3761        1031 :         if (!res)
    3762           0 :                 return FALSE;
    3763             : 
    3764        1031 :         os_memset(&wpa_data, 0, sizeof(wpa_data));
    3765        1031 :         ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
    3766        1031 :         if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
    3767           0 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
    3768             :                                      "failed to parse RSN IE");
    3769           0 :                 return FALSE;
    3770             :         }
    3771             : 
    3772        1031 :         return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
    3773             : }
    3774             : 
    3775             : 
    3776             : /**
    3777             :  * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
    3778             :  * @iter: Pointer to incoming dbus message iter
    3779             :  * @error: Location to store error on failure
    3780             :  * @user_data: Function specific data
    3781             :  * Returns: TRUE on success, FALSE on failure
    3782             :  *
    3783             :  * Getter for "WPS" property.
    3784             :  */
    3785        1063 : dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
    3786             :                                      void *user_data)
    3787             : {
    3788        1063 :         struct bss_handler_args *args = user_data;
    3789             :         struct wpa_bss *res;
    3790             : #ifdef CONFIG_WPS
    3791             :         struct wpabuf *wps_ie;
    3792             : #endif /* CONFIG_WPS */
    3793             :         DBusMessageIter iter_dict, variant_iter;
    3794        1063 :         const char *type = "";
    3795             : 
    3796        1063 :         res = get_bss_helper(args, error, __func__);
    3797        1063 :         if (!res)
    3798           0 :                 return FALSE;
    3799             : 
    3800        1063 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    3801        1063 :                                               "a{sv}", &variant_iter) ||
    3802        1063 :             !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
    3803             :                 goto nomem;
    3804             : 
    3805             : #ifdef CONFIG_WPS
    3806        1063 :         wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
    3807        1063 :         if (wps_ie) {
    3808         229 :                 if (wps_is_selected_pbc_registrar(wps_ie))
    3809          49 :                         type = "pbc";
    3810         180 :                 else if (wps_is_selected_pin_registrar(wps_ie))
    3811          95 :                         type = "pin";
    3812             : 
    3813         229 :                 wpabuf_free(wps_ie);
    3814             :         }
    3815             : #endif /* CONFIG_WPS */
    3816             : 
    3817        2126 :         if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type) ||
    3818        2126 :             !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
    3819        1063 :             !dbus_message_iter_close_container(iter, &variant_iter))
    3820             :                 goto nomem;
    3821             : 
    3822        1063 :         return TRUE;
    3823             : 
    3824             : nomem:
    3825           0 :         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3826           0 :         return FALSE;
    3827             : }
    3828             : 
    3829             : 
    3830             : /**
    3831             :  * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
    3832             :  * @iter: Pointer to incoming dbus message iter
    3833             :  * @error: Location to store error on failure
    3834             :  * @user_data: Function specific data
    3835             :  * Returns: TRUE on success, FALSE on failure
    3836             :  *
    3837             :  * Getter for "IEs" property.
    3838             :  */
    3839        1083 : dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
    3840             :                                      void *user_data)
    3841             : {
    3842        1083 :         struct bss_handler_args *args = user_data;
    3843             :         struct wpa_bss *res;
    3844             : 
    3845        1083 :         res = get_bss_helper(args, error, __func__);
    3846        1083 :         if (!res)
    3847           0 :                 return FALSE;
    3848             : 
    3849        1083 :         return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
    3850             :                                                       res + 1, res->ie_len,
    3851             :                                                       error);
    3852             : }
    3853             : 
    3854             : 
    3855             : /**
    3856             :  * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
    3857             :  * @iter: Pointer to incoming dbus message iter
    3858             :  * @error: Location to store error on failure
    3859             :  * @user_data: Function specific data
    3860             :  * Returns: TRUE on success, FALSE on failure
    3861             :  *
    3862             :  * Getter for BSS age
    3863             :  */
    3864        2347 : dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
    3865             :                                      void *user_data)
    3866             : {
    3867        2347 :         struct bss_handler_args *args = user_data;
    3868             :         struct wpa_bss *res;
    3869        2347 :         struct os_reltime now, diff = { 0, 0 };
    3870             :         u32 age;
    3871             : 
    3872        2347 :         res = get_bss_helper(args, error, __func__);
    3873        2347 :         if (!res)
    3874           0 :                 return FALSE;
    3875             : 
    3876        2347 :         os_get_reltime(&now);
    3877        2347 :         os_reltime_sub(&now, &res->last_update, &diff);
    3878        2347 :         age = diff.sec > 0 ? diff.sec : 0;
    3879        2347 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
    3880             :                                                 error);
    3881             : }
    3882             : 
    3883             : 
    3884             : /**
    3885             :  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
    3886             :  * @iter: Pointer to incoming dbus message iter
    3887             :  * @error: Location to store error on failure
    3888             :  * @user_data: Function specific data
    3889             :  * Returns: TRUE on success, FALSE on failure
    3890             :  *
    3891             :  * Getter for "enabled" property of a configured network.
    3892             :  */
    3893        4659 : dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
    3894             :                                      void *user_data)
    3895             : {
    3896        4659 :         struct network_handler_args *net = user_data;
    3897        4659 :         dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
    3898             : 
    3899        4659 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
    3900             :                                                 &enabled, error);
    3901             : }
    3902             : 
    3903             : 
    3904             : /**
    3905             :  * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
    3906             :  * @iter: Pointer to incoming dbus message iter
    3907             :  * @error: Location to store error on failure
    3908             :  * @user_data: Function specific data
    3909             :  * Returns: TRUE on success, FALSE on failure
    3910             :  *
    3911             :  * Setter for "Enabled" property of a configured network.
    3912             :  */
    3913           3 : dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
    3914             :                                      void *user_data)
    3915             : {
    3916           3 :         struct network_handler_args *net = user_data;
    3917             :         struct wpa_supplicant *wpa_s;
    3918             :         struct wpa_ssid *ssid;
    3919             :         dbus_bool_t enable;
    3920             : 
    3921           3 :         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
    3922             :                                               &enable))
    3923           1 :                 return FALSE;
    3924             : 
    3925           2 :         wpa_s = net->wpa_s;
    3926           2 :         ssid = net->ssid;
    3927             : 
    3928           2 :         if (enable)
    3929           1 :                 wpa_supplicant_enable_network(wpa_s, ssid);
    3930             :         else
    3931           1 :                 wpa_supplicant_disable_network(wpa_s, ssid);
    3932             : 
    3933           2 :         return TRUE;
    3934             : }
    3935             : 
    3936             : 
    3937             : /**
    3938             :  * wpas_dbus_getter_network_properties - Get options for a configured network
    3939             :  * @iter: Pointer to incoming dbus message iter
    3940             :  * @error: Location to store error on failure
    3941             :  * @user_data: Function specific data
    3942             :  * Returns: TRUE on success, FALSE on failure
    3943             :  *
    3944             :  * Getter for "Properties" property of a configured network.
    3945             :  */
    3946        2380 : dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
    3947             :                                                 DBusError *error,
    3948             :                                                 void *user_data)
    3949             : {
    3950        2380 :         struct network_handler_args *net = user_data;
    3951             :         DBusMessageIter variant_iter, dict_iter;
    3952             :         char **iterator;
    3953        2380 :         char **props = wpa_config_get_all(net->ssid, 1);
    3954        2380 :         dbus_bool_t success = FALSE;
    3955             : 
    3956        2380 :         if (!props) {
    3957           1 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3958           1 :                 return FALSE;
    3959             :         }
    3960             : 
    3961        2379 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
    3962        2379 :                                               &variant_iter) ||
    3963        2379 :             !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
    3964           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3965           0 :                 goto out;
    3966             :         }
    3967             : 
    3968        2379 :         iterator = props;
    3969      142768 :         while (*iterator) {
    3970      138010 :                 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
    3971      138010 :                                                  *(iterator + 1))) {
    3972           0 :                         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
    3973             :                                              "no memory");
    3974           0 :                         goto out;
    3975             :                 }
    3976      138010 :                 iterator += 2;
    3977             :         }
    3978             : 
    3979             : 
    3980        4758 :         if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
    3981        2379 :             !dbus_message_iter_close_container(iter, &variant_iter)) {
    3982           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    3983           0 :                 goto out;
    3984             :         }
    3985             : 
    3986        2379 :         success = TRUE;
    3987             : 
    3988             : out:
    3989        2379 :         iterator = props;
    3990      280778 :         while (*iterator) {
    3991      276020 :                 os_free(*iterator);
    3992      276020 :                 iterator++;
    3993             :         }
    3994        2379 :         os_free(props);
    3995        2379 :         return success;
    3996             : }
    3997             : 
    3998             : 
    3999             : /**
    4000             :  * wpas_dbus_setter_network_properties - Set options for a configured network
    4001             :  * @iter: Pointer to incoming dbus message iter
    4002             :  * @error: Location to store error on failure
    4003             :  * @user_data: Function specific data
    4004             :  * Returns: TRUE on success, FALSE on failure
    4005             :  *
    4006             :  * Setter for "Properties" property of a configured network.
    4007             :  */
    4008           3 : dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
    4009             :                                                 DBusError *error,
    4010             :                                                 void *user_data)
    4011             : {
    4012           3 :         struct network_handler_args *net = user_data;
    4013           3 :         struct wpa_ssid *ssid = net->ssid;
    4014             :         DBusMessageIter variant_iter;
    4015             : 
    4016           3 :         dbus_message_iter_recurse(iter, &variant_iter);
    4017           3 :         return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
    4018             : }
    4019             : 
    4020             : 
    4021             : #ifdef CONFIG_AP
    4022             : 
    4023           4 : DBusMessage * wpas_dbus_handler_subscribe_preq(
    4024             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    4025             : {
    4026           4 :         struct wpas_dbus_priv *priv = wpa_s->global->dbus;
    4027             :         char *name;
    4028             : 
    4029           4 :         if (wpa_s->preq_notify_peer != NULL) {
    4030           0 :                 if (os_strcmp(dbus_message_get_sender(message),
    4031             :                               wpa_s->preq_notify_peer) == 0)
    4032           0 :                         return NULL;
    4033             : 
    4034           0 :                 return dbus_message_new_error(message,
    4035             :                         WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
    4036             :                         "Another application is already subscribed");
    4037             :         }
    4038             : 
    4039           4 :         name = os_strdup(dbus_message_get_sender(message));
    4040           4 :         if (!name)
    4041           1 :                 return wpas_dbus_error_no_memory(message);
    4042             : 
    4043           3 :         wpa_s->preq_notify_peer = name;
    4044             : 
    4045             :         /* Subscribe to clean up if application closes socket */
    4046           3 :         wpas_dbus_subscribe_noc(priv);
    4047             : 
    4048             :         /*
    4049             :          * Double-check it's still alive to make sure that we didn't
    4050             :          * miss the NameOwnerChanged signal, e.g. while strdup'ing.
    4051             :          */
    4052           3 :         if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
    4053             :                 /*
    4054             :                  * Application no longer exists, clean up.
    4055             :                  * The return value is irrelevant now.
    4056             :                  *
    4057             :                  * Need to check if the NameOwnerChanged handling
    4058             :                  * already cleaned up because we have processed
    4059             :                  * DBus messages while checking if the name still
    4060             :                  * has an owner.
    4061             :                  */
    4062           0 :                 if (!wpa_s->preq_notify_peer)
    4063           0 :                         return NULL;
    4064           0 :                 os_free(wpa_s->preq_notify_peer);
    4065           0 :                 wpa_s->preq_notify_peer = NULL;
    4066           0 :                 wpas_dbus_unsubscribe_noc(priv);
    4067             :         }
    4068             : 
    4069           3 :         return NULL;
    4070             : }
    4071             : 
    4072             : 
    4073           3 : DBusMessage * wpas_dbus_handler_unsubscribe_preq(
    4074             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    4075             : {
    4076           3 :         struct wpas_dbus_priv *priv = wpa_s->global->dbus;
    4077             : 
    4078           3 :         if (!wpa_s->preq_notify_peer)
    4079           1 :                 return dbus_message_new_error(message,
    4080             :                         WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
    4081             :                         "Not subscribed");
    4082             : 
    4083           2 :         if (os_strcmp(wpa_s->preq_notify_peer,
    4084             :                       dbus_message_get_sender(message)))
    4085           0 :                 return dbus_message_new_error(message,
    4086             :                         WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
    4087             :                         "Can't unsubscribe others");
    4088             : 
    4089           2 :         os_free(wpa_s->preq_notify_peer);
    4090           2 :         wpa_s->preq_notify_peer = NULL;
    4091           2 :         wpas_dbus_unsubscribe_noc(priv);
    4092           2 :         return NULL;
    4093             : }
    4094             : 
    4095             : 
    4096         415 : void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
    4097             :                            const u8 *addr, const u8 *dst, const u8 *bssid,
    4098             :                            const u8 *ie, size_t ie_len, u32 ssi_signal)
    4099             : {
    4100             :         DBusMessage *msg;
    4101             :         DBusMessageIter iter, dict_iter;
    4102         415 :         struct wpas_dbus_priv *priv = wpa_s->global->dbus;
    4103             : 
    4104             :         /* Do nothing if the control interface is not turned on */
    4105         415 :         if (priv == NULL)
    4106         495 :                 return;
    4107             : 
    4108         316 :         if (wpa_s->preq_notify_peer == NULL)
    4109         297 :                 return;
    4110             : 
    4111          19 :         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    4112             :                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
    4113             :                                       "ProbeRequest");
    4114          19 :         if (msg == NULL)
    4115           0 :                 return;
    4116             : 
    4117          19 :         dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
    4118             : 
    4119          19 :         dbus_message_iter_init_append(msg, &iter);
    4120             : 
    4121          19 :         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    4122          19 :             (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
    4123             :                                                       (const char *) addr,
    4124          19 :                                                       ETH_ALEN)) ||
    4125          19 :             (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
    4126             :                                                      (const char *) dst,
    4127          19 :                                                      ETH_ALEN)) ||
    4128          19 :             (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
    4129             :                                                        (const char *) bssid,
    4130          19 :                                                        ETH_ALEN)) ||
    4131          19 :             (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
    4132             :                                                               (const char *) ie,
    4133          19 :                                                               ie_len)) ||
    4134          19 :             (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
    4135          19 :                                                        ssi_signal)) ||
    4136          19 :             !wpa_dbus_dict_close_write(&iter, &dict_iter))
    4137             :                 goto fail;
    4138             : 
    4139          19 :         dbus_connection_send(priv->con, msg, NULL);
    4140          19 :         goto out;
    4141             : fail:
    4142           0 :         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    4143             : out:
    4144          19 :         dbus_message_unref(msg);
    4145             : }
    4146             : 
    4147             : #endif /* CONFIG_AP */

Generated by: LCOV version 1.10