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

Generated by: LCOV version 1.10