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

Generated by: LCOV version 1.10