00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "includes.h"
00018
00019 #include "common.h"
00020 #include "common/ieee802_11_defs.h"
00021 #include "eap_peer/eap_methods.h"
00022 #include "eapol_supp/eapol_supp_sm.h"
00023 #include "rsn_supp/wpa.h"
00024 #include "../config.h"
00025 #include "../wpa_supplicant_i.h"
00026 #include "../driver_i.h"
00027 #include "../notify.h"
00028 #include "../wpas_glue.h"
00029 #include "../bss.h"
00030 #include "../scan.h"
00031 #include "dbus_new_helpers.h"
00032 #include "dbus_new.h"
00033 #include "dbus_new_handlers.h"
00034 #include "dbus_dict_helpers.h"
00035
00036 extern int wpa_debug_level;
00037 extern int wpa_debug_show_keys;
00038 extern int wpa_debug_timestamp;
00039
00040 static const char *debug_strings[] = {
00041 "msgdump", "debug", "info", "warning", "error", NULL
00042 };
00043
00044
00055 static char * wpas_dbus_new_decompose_object_path(const char *path,
00056 char **network,
00057 char **bssid)
00058 {
00059 const unsigned int dev_path_prefix_len =
00060 strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/");
00061 char *obj_path_only;
00062 char *next_sep;
00063
00064
00065 if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/",
00066 dev_path_prefix_len))
00067 return NULL;
00068
00069
00070 if ((path + dev_path_prefix_len)[0] == '\0')
00071 return NULL;
00072
00073 obj_path_only = os_strdup(path);
00074 if (obj_path_only == NULL)
00075 return NULL;
00076
00077 next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/');
00078 if (next_sep != NULL) {
00079 const char *net_part = os_strstr(
00080 next_sep, WPAS_DBUS_NEW_NETWORKS_PART "/");
00081 const char *bssid_part = os_strstr(
00082 next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/");
00083
00084 if (network && net_part) {
00085
00086 const char *net_name = net_part +
00087 os_strlen(WPAS_DBUS_NEW_NETWORKS_PART "/");
00088 *network = NULL;
00089 if (os_strlen(net_name))
00090 *network = os_strdup(net_name);
00091 } else if (bssid && bssid_part) {
00092
00093 const char *bssid_name = bssid_part +
00094 os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/");
00095 if (strlen(bssid_name))
00096 *bssid = os_strdup(bssid_name);
00097 else
00098 *bssid = NULL;
00099 }
00100
00101
00102 *next_sep = '\0';
00103 }
00104
00105 return obj_path_only;
00106 }
00107
00108
00117 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
00118 const char *arg)
00119 {
00120 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
00121 arg);
00122 }
00123
00124
00132 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
00133 {
00134 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
00135 "wpa_supplicant knows nothing about "
00136 "this interface.");
00137 }
00138
00139
00147 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
00148 {
00149 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
00150 "There is no such a network in this "
00151 "interface.");
00152 }
00153
00154
00162 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
00163 const char *arg)
00164 {
00165 DBusMessage *reply;
00166
00167 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
00168 "Did not receive correct message "
00169 "arguments.");
00170 if (arg != NULL)
00171 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
00172 DBUS_TYPE_INVALID);
00173
00174 return reply;
00175 }
00176
00177
00178 static const char *dont_quote[] = {
00179 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
00180 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
00181 "bssid", NULL
00182 };
00183
00184 static dbus_bool_t should_quote_opt(const char *key)
00185 {
00186 int i = 0;
00187 while (dont_quote[i] != NULL) {
00188 if (os_strcmp(key, dont_quote[i]) == 0)
00189 return FALSE;
00190 i++;
00191 }
00192 return TRUE;
00193 }
00194
00201 static struct wpa_supplicant * get_iface_by_dbus_path(
00202 struct wpa_global *global, const char *path)
00203 {
00204 struct wpa_supplicant *wpa_s;
00205
00206 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
00207 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
00208 return wpa_s;
00209 }
00210 return NULL;
00211 }
00212
00213
00225 static DBusMessage * set_network_properties(DBusMessage *message,
00226 struct wpa_supplicant *wpa_s,
00227 struct wpa_ssid *ssid,
00228 DBusMessageIter *iter)
00229 {
00230
00231 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
00232 DBusMessage *reply = NULL;
00233 DBusMessageIter iter_dict;
00234
00235 if (!wpa_dbus_dict_open_read(iter, &iter_dict))
00236 return wpas_dbus_error_invalid_args(message, NULL);
00237
00238 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
00239 char *value = NULL;
00240 size_t size = 50;
00241 int ret;
00242 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
00243 reply = wpas_dbus_error_invalid_args(message, NULL);
00244 break;
00245 }
00246 if (entry.type == DBUS_TYPE_ARRAY &&
00247 entry.array_type == DBUS_TYPE_BYTE) {
00248 if (entry.array_len <= 0)
00249 goto error;
00250
00251 size = entry.array_len * 2 + 1;
00252 value = os_zalloc(size);
00253 if (value == NULL)
00254 goto error;
00255
00256 ret = wpa_snprintf_hex(value, size,
00257 (u8 *) entry.bytearray_value,
00258 entry.array_len);
00259 if (ret <= 0)
00260 goto error;
00261 } else if (entry.type == DBUS_TYPE_STRING) {
00262 if (should_quote_opt(entry.key)) {
00263 size = os_strlen(entry.str_value);
00264 if (size <= 0)
00265 goto error;
00266
00267 size += 3;
00268 value = os_zalloc(size);
00269 if (value == NULL)
00270 goto error;
00271
00272 ret = os_snprintf(value, size, "\"%s\"",
00273 entry.str_value);
00274 if (ret < 0 || (size_t) ret != (size - 1))
00275 goto error;
00276 } else {
00277 value = os_strdup(entry.str_value);
00278 if (value == NULL)
00279 goto error;
00280 }
00281 } else if (entry.type == DBUS_TYPE_UINT32) {
00282 value = os_zalloc(size);
00283 if (value == NULL)
00284 goto error;
00285
00286 ret = os_snprintf(value, size, "%u",
00287 entry.uint32_value);
00288 if (ret <= 0)
00289 goto error;
00290 } else if (entry.type == DBUS_TYPE_INT32) {
00291 value = os_zalloc(size);
00292 if (value == NULL)
00293 goto error;
00294
00295 ret = os_snprintf(value, size, "%d",
00296 entry.int32_value);
00297 if (ret <= 0)
00298 goto error;
00299 } else
00300 goto error;
00301
00302 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
00303 goto error;
00304
00305 if ((os_strcmp(entry.key, "psk") == 0 &&
00306 value[0] == '"' && ssid->ssid_len) ||
00307 (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
00308 wpa_config_update_psk(ssid);
00309 else if (os_strcmp(entry.key, "priority") == 0)
00310 wpa_config_update_prio_list(wpa_s->conf);
00311
00312 os_free(value);
00313 wpa_dbus_dict_entry_clear(&entry);
00314 continue;
00315
00316 error:
00317 os_free(value);
00318 reply = wpas_dbus_error_invalid_args(message, entry.key);
00319 wpa_dbus_dict_entry_clear(&entry);
00320 break;
00321 }
00322
00323 return reply;
00324 }
00325
00326
00337 DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message,
00338 const int type, const void *val)
00339 {
00340 DBusMessage *reply = NULL;
00341 DBusMessageIter iter, variant_iter;
00342
00343 if (!dbus_type_is_basic(type)) {
00344 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
00345 " given type is not basic");
00346 return wpas_dbus_error_unknown_error(message, NULL);
00347 }
00348
00349 if (message == NULL)
00350 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
00351 else
00352 reply = dbus_message_new_method_return(message);
00353
00354 if (reply != NULL) {
00355 dbus_message_iter_init_append(reply, &iter);
00356 if (!dbus_message_iter_open_container(
00357 &iter, DBUS_TYPE_VARIANT,
00358 wpa_dbus_type_as_string(type), &variant_iter) ||
00359 !dbus_message_iter_append_basic(&variant_iter, type,
00360 val) ||
00361 !dbus_message_iter_close_container(&iter, &variant_iter)) {
00362 wpa_printf(MSG_ERROR, "dbus: "
00363 "wpas_dbus_simple_property_getter: out of "
00364 "memory to put property value into "
00365 "message");
00366 dbus_message_unref(reply);
00367 reply = dbus_message_new_error(message,
00368 DBUS_ERROR_NO_MEMORY,
00369 NULL);
00370 }
00371 } else {
00372 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
00373 " out of memory to return property value");
00374 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00375 NULL);
00376 }
00377
00378 return reply;
00379 }
00380
00381
00391 DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message,
00392 const int type, void *val)
00393 {
00394 DBusMessageIter iter, variant_iter;
00395
00396 if (!dbus_type_is_basic(type)) {
00397 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
00398 " given type is not basic");
00399 return wpas_dbus_error_unknown_error(message, NULL);
00400 }
00401
00402 if (!dbus_message_iter_init(message, &iter)) {
00403 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
00404 " out of memory to return scanning state");
00405 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00406 NULL);
00407 }
00408
00409
00410 dbus_message_iter_next(&iter);
00411 dbus_message_iter_next(&iter);
00412 dbus_message_iter_recurse(&iter, &variant_iter);
00413
00414 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
00415 wpa_printf(MSG_DEBUG, "dbus: wpas_dbus_simple_property_setter:"
00416 " wrong property type");
00417 return wpas_dbus_error_invalid_args(message,
00418 "wrong property type");
00419 }
00420 dbus_message_iter_get_basic(&variant_iter, val);
00421
00422 return NULL;
00423 }
00424
00425
00438 DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message,
00439 const int type,
00440 const void *array,
00441 size_t array_len)
00442 {
00443 DBusMessage *reply = NULL;
00444 DBusMessageIter iter, variant_iter, array_iter;
00445 char type_str[] = "a?";
00446 const char *sub_type_str;
00447 size_t element_size, i;
00448
00449 if (!dbus_type_is_basic(type)) {
00450 wpa_printf(MSG_ERROR, "dbus: "
00451 "wpas_dbus_simple_array_property_getter: given "
00452 "type is not basic");
00453 return wpas_dbus_error_unknown_error(message, NULL);
00454 }
00455
00456 sub_type_str = wpa_dbus_type_as_string(type);
00457 type_str[1] = sub_type_str[0];
00458
00459 if (message == NULL)
00460 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
00461 else
00462 reply = dbus_message_new_method_return(message);
00463 if (reply == NULL) {
00464 wpa_printf(MSG_ERROR, "dbus: "
00465 "wpas_dbus_simple_array_property_getter: out of "
00466 "memory to create return message");
00467 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00468 NULL);
00469 }
00470
00471 dbus_message_iter_init_append(reply, &iter);
00472
00473 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
00474 type_str, &variant_iter) ||
00475 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
00476 sub_type_str, &array_iter)) {
00477 wpa_printf(MSG_ERROR, "dbus: "
00478 "wpas_dbus_simple_array_property_getter: out of "
00479 "memory to open container");
00480 dbus_message_unref(reply);
00481 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00482 NULL);
00483 }
00484
00485 switch(type) {
00486 case DBUS_TYPE_BYTE:
00487 case DBUS_TYPE_BOOLEAN:
00488 element_size = 1;
00489 break;
00490 case DBUS_TYPE_INT16:
00491 case DBUS_TYPE_UINT16:
00492 element_size = sizeof(uint16_t);
00493 break;
00494 case DBUS_TYPE_INT32:
00495 case DBUS_TYPE_UINT32:
00496 element_size = sizeof(uint32_t);
00497 break;
00498 case DBUS_TYPE_INT64:
00499 case DBUS_TYPE_UINT64:
00500 element_size = sizeof(uint64_t);
00501 break;
00502 case DBUS_TYPE_DOUBLE:
00503 element_size = sizeof(double);
00504 break;
00505 case DBUS_TYPE_STRING:
00506 case DBUS_TYPE_OBJECT_PATH:
00507 element_size = sizeof(char *);
00508 break;
00509 default:
00510 wpa_printf(MSG_ERROR, "dbus: "
00511 "wpas_dbus_simple_array_property_getter: "
00512 "fatal: unknown element type");
00513 element_size = 1;
00514 break;
00515 }
00516
00517 for (i = 0; i < array_len; i++) {
00518 dbus_message_iter_append_basic(&array_iter, type,
00519 array + i * element_size);
00520 }
00521
00522 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
00523 !dbus_message_iter_close_container(&iter, &variant_iter)) {
00524 wpa_printf(MSG_ERROR, "dbus: "
00525 "wpas_dbus_simple_array_property_getter: out of "
00526 "memory to close container");
00527 dbus_message_unref(reply);
00528 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00529 NULL);
00530 }
00531
00532 return reply;
00533 }
00534
00535
00547 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
00548 struct wpa_global *global)
00549 {
00550 DBusMessageIter iter_dict;
00551 DBusMessage *reply = NULL;
00552 DBusMessageIter iter;
00553 struct wpa_dbus_dict_entry entry;
00554 char *driver = NULL;
00555 char *ifname = NULL;
00556 char *bridge_ifname = NULL;
00557
00558 dbus_message_iter_init(message, &iter);
00559
00560 if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
00561 goto error;
00562 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
00563 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
00564 goto error;
00565 if (!strcmp(entry.key, "Driver") &&
00566 (entry.type == DBUS_TYPE_STRING)) {
00567 driver = os_strdup(entry.str_value);
00568 wpa_dbus_dict_entry_clear(&entry);
00569 if (driver == NULL)
00570 goto error;
00571 } else if (!strcmp(entry.key, "Ifname") &&
00572 (entry.type == DBUS_TYPE_STRING)) {
00573 ifname = os_strdup(entry.str_value);
00574 wpa_dbus_dict_entry_clear(&entry);
00575 if (ifname == NULL)
00576 goto error;
00577 } else if (!strcmp(entry.key, "BridgeIfname") &&
00578 (entry.type == DBUS_TYPE_STRING)) {
00579 bridge_ifname = os_strdup(entry.str_value);
00580 wpa_dbus_dict_entry_clear(&entry);
00581 if (bridge_ifname == NULL)
00582 goto error;
00583 } else {
00584 wpa_dbus_dict_entry_clear(&entry);
00585 goto error;
00586 }
00587 }
00588
00589 if (ifname == NULL)
00590 goto error;
00591
00592
00593
00594
00595
00596 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
00597 reply = dbus_message_new_error(message,
00598 WPAS_DBUS_ERROR_IFACE_EXISTS,
00599 "wpa_supplicant already "
00600 "controls this interface.");
00601 } else {
00602 struct wpa_supplicant *wpa_s;
00603 struct wpa_interface iface;
00604 os_memset(&iface, 0, sizeof(iface));
00605 iface.driver = driver;
00606 iface.ifname = ifname;
00607 iface.bridge_ifname = bridge_ifname;
00608
00609 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
00610 const char *path = wpa_s->dbus_new_path;
00611 reply = dbus_message_new_method_return(message);
00612 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
00613 &path, DBUS_TYPE_INVALID);
00614 } else {
00615 reply = wpas_dbus_error_unknown_error(
00616 message, "wpa_supplicant couldn't grab this "
00617 "interface.");
00618 }
00619 }
00620
00621 out:
00622 os_free(driver);
00623 os_free(ifname);
00624 os_free(bridge_ifname);
00625 return reply;
00626
00627 error:
00628 reply = wpas_dbus_error_invalid_args(message, NULL);
00629 goto out;
00630 }
00631
00632
00644 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
00645 struct wpa_global *global)
00646 {
00647 struct wpa_supplicant *wpa_s;
00648 char *path;
00649 DBusMessage *reply = NULL;
00650
00651 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
00652 DBUS_TYPE_INVALID);
00653
00654 wpa_s = get_iface_by_dbus_path(global, path);
00655 if (wpa_s == NULL)
00656 reply = wpas_dbus_error_iface_unknown(message);
00657 else if (wpa_supplicant_remove_iface(global, wpa_s)) {
00658 reply = wpas_dbus_error_unknown_error(
00659 message, "wpa_supplicant couldn't remove this "
00660 "interface.");
00661 }
00662
00663 return reply;
00664 }
00665
00666
00676 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
00677 struct wpa_global *global)
00678 {
00679 DBusMessage *reply = NULL;
00680 const char *ifname;
00681 const char *path;
00682 struct wpa_supplicant *wpa_s;
00683
00684 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
00685 DBUS_TYPE_INVALID);
00686
00687 wpa_s = wpa_supplicant_get_iface(global, ifname);
00688 if (wpa_s == NULL)
00689 return wpas_dbus_error_iface_unknown(message);
00690
00691 path = wpa_s->dbus_new_path;
00692 reply = dbus_message_new_method_return(message);
00693 if (reply == NULL)
00694 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00695 NULL);
00696 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
00697 DBUS_TYPE_INVALID)) {
00698 dbus_message_unref(reply);
00699 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00700 NULL);
00701 }
00702
00703 return reply;
00704 }
00705
00706
00715 DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message,
00716 struct wpa_global *global)
00717 {
00718 const char *str;
00719 int idx = wpa_debug_level;
00720 if (idx < 0)
00721 idx = 0;
00722 if (idx > 4)
00723 idx = 4;
00724 str = debug_strings[idx];
00725 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
00726 &str);
00727 }
00728
00729
00738 DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message,
00739 struct wpa_global *global)
00740 {
00741 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
00742 &wpa_debug_timestamp);
00743
00744 }
00745
00746
00755 DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message,
00756 struct wpa_global *global)
00757 {
00758 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
00759 &wpa_debug_show_keys);
00760
00761 }
00762
00771 DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message,
00772 struct wpa_global *global)
00773 {
00774 DBusMessage *reply;
00775 const char *str = NULL;
00776 int i, val = -1;
00777
00778 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
00779 &str);
00780 if (reply)
00781 return reply;
00782
00783 for (i = 0; debug_strings[i]; i++)
00784 if (os_strcmp(debug_strings[i], str) == 0) {
00785 val = i;
00786 break;
00787 }
00788
00789 if (val < 0 ||
00790 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
00791 wpa_debug_show_keys)) {
00792 dbus_message_unref(reply);
00793 return wpas_dbus_error_invalid_args(
00794 message, "Wrong debug level value");
00795 }
00796
00797 return NULL;
00798 }
00799
00800
00809 DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message,
00810 struct wpa_global *global)
00811 {
00812 DBusMessage *reply;
00813 dbus_bool_t val;
00814
00815 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
00816 &val);
00817 if (reply)
00818 return reply;
00819
00820 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
00821 wpa_debug_show_keys);
00822
00823 return NULL;
00824 }
00825
00826
00835 DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message,
00836 struct wpa_global *global)
00837 {
00838 DBusMessage *reply;
00839 dbus_bool_t val;
00840
00841 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
00842 &val);
00843 if (reply)
00844 return reply;
00845
00846 wpa_supplicant_set_debug_params(global, wpa_debug_level,
00847 wpa_debug_timestamp,
00848 val ? 1 : 0);
00849
00850 return NULL;
00851 }
00852
00853
00865 DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
00866 struct wpa_global *global)
00867 {
00868 DBusMessage *reply = NULL;
00869 struct wpa_supplicant *wpa_s;
00870 const char **paths;
00871 unsigned int i = 0, num = 0;
00872
00873 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
00874 num++;
00875
00876 paths = os_zalloc(num * sizeof(char*));
00877 if (!paths) {
00878 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00879 NULL);
00880 }
00881
00882 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
00883 paths[i] = wpa_s->dbus_new_path;
00884
00885 reply = wpas_dbus_simple_array_property_getter(message,
00886 DBUS_TYPE_OBJECT_PATH,
00887 paths, num);
00888
00889 os_free(paths);
00890 return reply;
00891 }
00892
00893
00904 DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing)
00905 {
00906 DBusMessage *reply = NULL;
00907 char **eap_methods;
00908 size_t num_items = 0;
00909
00910 eap_methods = eap_get_names_as_string_array(&num_items);
00911 if (!eap_methods) {
00912 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
00913 NULL);
00914 }
00915
00916 reply = wpas_dbus_simple_array_property_getter(message,
00917 DBUS_TYPE_STRING,
00918 eap_methods, num_items);
00919
00920 while (num_items)
00921 os_free(eap_methods[--num_items]);
00922 os_free(eap_methods);
00923 return reply;
00924 }
00925
00926
00927 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
00928 char **type, DBusMessage **reply)
00929 {
00930 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
00931 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
00932 "Type must be a string");
00933 *reply = wpas_dbus_error_invalid_args(
00934 message, "Wrong Type value type. String required");
00935 return -1;
00936 }
00937 dbus_message_iter_get_basic(var, type);
00938 return 0;
00939 }
00940
00941
00942 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
00943 struct wpa_driver_scan_params *params,
00944 DBusMessage **reply)
00945 {
00946 struct wpa_driver_scan_ssid *ssids = params->ssids;
00947 size_t ssids_num = 0;
00948 u8 *ssid;
00949 DBusMessageIter array_iter, sub_array_iter;
00950 char *val;
00951 int len;
00952
00953 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
00954 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
00955 "must be an array of arrays of bytes");
00956 *reply = wpas_dbus_error_invalid_args(
00957 message, "Wrong SSIDs value type. Array of arrays of "
00958 "bytes required");
00959 return -1;
00960 }
00961
00962 dbus_message_iter_recurse(var, &array_iter);
00963
00964 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
00965 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
00966 {
00967 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
00968 "must be an array of arrays of bytes");
00969 *reply = wpas_dbus_error_invalid_args(
00970 message, "Wrong SSIDs value type. Array of arrays of "
00971 "bytes required");
00972 return -1;
00973 }
00974
00975 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
00976 {
00977 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
00978 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
00979 "Too many ssids specified on scan dbus "
00980 "call");
00981 *reply = wpas_dbus_error_invalid_args(
00982 message, "Too many ssids specified. Specify "
00983 "at most four");
00984 return -1;
00985 }
00986
00987 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
00988
00989 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
00990 if (len == 0) {
00991 dbus_message_iter_next(&array_iter);
00992 continue;
00993 }
00994
00995 ssid = os_malloc(len);
00996 if (ssid == NULL) {
00997 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
00998 "out of memory. Cannot allocate memory for "
00999 "SSID");
01000 *reply = dbus_message_new_error(
01001 message, DBUS_ERROR_NO_MEMORY, NULL);
01002 return -1;
01003 }
01004 os_memcpy(ssid, val, len);
01005 ssids[ssids_num].ssid = ssid;
01006 ssids[ssids_num].ssid_len = len;
01007
01008 dbus_message_iter_next(&array_iter);
01009 ssids_num++;
01010 }
01011
01012 params->num_ssids = ssids_num;
01013 return 0;
01014 }
01015
01016
01017 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
01018 struct wpa_driver_scan_params *params,
01019 DBusMessage **reply)
01020 {
01021 u8 *ies = NULL, *nies;
01022 int ies_len = 0;
01023 DBusMessageIter array_iter, sub_array_iter;
01024 char *val;
01025 int len;
01026
01027 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
01028 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
01029 "be an array of arrays of bytes");
01030 *reply = wpas_dbus_error_invalid_args(
01031 message, "Wrong IEs value type. Array of arrays of "
01032 "bytes required");
01033 return -1;
01034 }
01035
01036 dbus_message_iter_recurse(var, &array_iter);
01037
01038 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
01039 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
01040 {
01041 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
01042 "be an array of arrays of bytes");
01043 *reply = wpas_dbus_error_invalid_args(
01044 message, "Wrong IEs value type. Array required");
01045 return -1;
01046 }
01047
01048 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
01049 {
01050 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
01051
01052 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
01053 if (len == 0) {
01054 dbus_message_iter_next(&array_iter);
01055 continue;
01056 }
01057
01058 nies = os_realloc(ies, ies_len + len);
01059 if (nies == NULL) {
01060 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01061 "out of memory. Cannot allocate memory for "
01062 "IE");
01063 os_free(ies);
01064 *reply = dbus_message_new_error(
01065 message, DBUS_ERROR_NO_MEMORY, NULL);
01066 return -1;
01067 }
01068 ies = nies;
01069 os_memcpy(ies + ies_len, val, len);
01070 ies_len += len;
01071
01072 dbus_message_iter_next(&array_iter);
01073 }
01074
01075 params->extra_ies = ies;
01076 params->extra_ies_len = ies_len;
01077 return 0;
01078 }
01079
01080
01081 static int wpas_dbus_get_scan_channels(DBusMessage *message,
01082 DBusMessageIter *var,
01083 struct wpa_driver_scan_params *params,
01084 DBusMessage **reply)
01085 {
01086 DBusMessageIter array_iter, sub_array_iter;
01087 int *freqs = NULL, *nfreqs;
01088 int freqs_num = 0;
01089
01090 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
01091 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01092 "Channels must be an array of structs");
01093 *reply = wpas_dbus_error_invalid_args(
01094 message, "Wrong Channels value type. Array of structs "
01095 "required");
01096 return -1;
01097 }
01098
01099 dbus_message_iter_recurse(var, &array_iter);
01100
01101 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
01102 wpa_printf(MSG_DEBUG,
01103 "wpas_dbus_handler_scan[dbus]: Channels must be an "
01104 "array of structs");
01105 *reply = wpas_dbus_error_invalid_args(
01106 message, "Wrong Channels value type. Array of structs "
01107 "required");
01108 return -1;
01109 }
01110
01111 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
01112 {
01113 int freq, width;
01114
01115 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
01116
01117 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
01118 DBUS_TYPE_UINT32) {
01119 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01120 "Channel must by specified by struct of "
01121 "two UINT32s %c",
01122 dbus_message_iter_get_arg_type(
01123 &sub_array_iter));
01124 *reply = wpas_dbus_error_invalid_args(
01125 message, "Wrong Channel struct. Two UINT32s "
01126 "required");
01127 os_free(freqs);
01128 return -1;
01129 }
01130 dbus_message_iter_get_basic(&sub_array_iter, &freq);
01131
01132 if (!dbus_message_iter_next(&sub_array_iter) ||
01133 dbus_message_iter_get_arg_type(&sub_array_iter) !=
01134 DBUS_TYPE_UINT32) {
01135 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01136 "Channel must by specified by struct of "
01137 "two UINT32s");
01138 *reply = wpas_dbus_error_invalid_args(
01139 message,
01140 "Wrong Channel struct. Two UINT32s required");
01141 os_free(freqs);
01142 return -1;
01143 }
01144
01145 dbus_message_iter_get_basic(&sub_array_iter, &width);
01146
01147 #define FREQS_ALLOC_CHUNK 32
01148 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
01149 nfreqs = os_realloc(freqs, sizeof(int) *
01150 (freqs_num + FREQS_ALLOC_CHUNK));
01151 if (nfreqs == NULL)
01152 os_free(freqs);
01153 freqs = nfreqs;
01154 }
01155 if (freqs == NULL) {
01156 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01157 "out of memory. can't allocate memory for "
01158 "freqs");
01159 *reply = dbus_message_new_error(
01160 message, DBUS_ERROR_NO_MEMORY, NULL);
01161 return -1;
01162 }
01163
01164 freqs[freqs_num] = freq;
01165
01166 freqs_num++;
01167 dbus_message_iter_next(&array_iter);
01168 }
01169
01170 nfreqs = os_realloc(freqs,
01171 sizeof(int) * (freqs_num + 1));
01172 if (nfreqs == NULL)
01173 os_free(freqs);
01174 freqs = nfreqs;
01175 if (freqs == NULL) {
01176 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01177 "out of memory. Can't allocate memory for freqs");
01178 *reply = dbus_message_new_error(
01179 message, DBUS_ERROR_NO_MEMORY, NULL);
01180 return -1;
01181 }
01182 freqs[freqs_num] = 0;
01183
01184 params->freqs = freqs;
01185 return 0;
01186 }
01187
01188
01199 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
01200 struct wpa_supplicant *wpa_s)
01201 {
01202 DBusMessage *reply = NULL;
01203 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
01204 char *key = NULL, *type = NULL;
01205 struct wpa_driver_scan_params params;
01206 size_t i;
01207
01208 os_memset(¶ms, 0, sizeof(params));
01209
01210 dbus_message_iter_init(message, &iter);
01211
01212 dbus_message_iter_recurse(&iter, &dict_iter);
01213
01214 while (dbus_message_iter_get_arg_type(&dict_iter) ==
01215 DBUS_TYPE_DICT_ENTRY) {
01216 dbus_message_iter_recurse(&dict_iter, &entry_iter);
01217 dbus_message_iter_get_basic(&entry_iter, &key);
01218 dbus_message_iter_next(&entry_iter);
01219 dbus_message_iter_recurse(&entry_iter, &variant_iter);
01220
01221 if (os_strcmp(key, "Type") == 0) {
01222 if (wpas_dbus_get_scan_type(message, &variant_iter,
01223 &type, &reply) < 0)
01224 goto out;
01225 } else if (os_strcmp(key, "SSIDs") == 0) {
01226 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
01227 ¶ms, &reply) < 0)
01228 goto out;
01229 } else if (os_strcmp(key, "IEs") == 0) {
01230 if (wpas_dbus_get_scan_ies(message, &variant_iter,
01231 ¶ms, &reply) < 0)
01232 goto out;
01233 } else if (os_strcmp(key, "Channels") == 0) {
01234 if (wpas_dbus_get_scan_channels(message, &variant_iter,
01235 ¶ms, &reply) < 0)
01236 goto out;
01237 } else {
01238 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01239 "Unknown argument %s", key);
01240 reply = wpas_dbus_error_invalid_args(message, key);
01241 goto out;
01242 }
01243
01244 dbus_message_iter_next(&dict_iter);
01245 }
01246
01247 if (!type) {
01248 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01249 "Scan type not specified");
01250 reply = wpas_dbus_error_invalid_args(message, key);
01251 goto out;
01252 }
01253
01254 if (!os_strcmp(type, "passive")) {
01255 if (params.num_ssids || params.extra_ies_len) {
01256 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01257 "SSIDs or IEs specified for passive scan.");
01258 reply = wpas_dbus_error_invalid_args(
01259 message, "You can specify only Channels in "
01260 "passive scan");
01261 goto out;
01262 } else if (params.freqs && params.freqs[0]) {
01263
01264 params.num_ssids++;
01265 wpa_supplicant_trigger_scan(wpa_s, ¶ms);
01266 } else {
01267 wpa_s->scan_req = 2;
01268 wpa_supplicant_req_scan(wpa_s, 0, 0);
01269 }
01270 } else if (!os_strcmp(type, "active")) {
01271 wpa_supplicant_trigger_scan(wpa_s, ¶ms);
01272 } else {
01273 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
01274 "Unknown scan type: %s", type);
01275 reply = wpas_dbus_error_invalid_args(message,
01276 "Wrong scan type");
01277 goto out;
01278 }
01279
01280 out:
01281 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
01282 os_free((u8 *) params.ssids[i].ssid);
01283 os_free((u8 *) params.extra_ies);
01284 os_free(params.freqs);
01285 return reply;
01286 }
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
01299 struct wpa_supplicant *wpa_s)
01300 {
01301 if (wpa_s->current_ssid != NULL) {
01302 wpa_s->disconnected = 1;
01303 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
01304
01305 return NULL;
01306 }
01307
01308 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
01309 "This interface is not connected");
01310 }
01311
01312
01321 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
01322 struct wpa_supplicant *wpa_s)
01323 {
01324 DBusMessage *reply = NULL;
01325 DBusMessageIter iter;
01326 struct wpa_ssid *ssid = NULL;
01327 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
01328
01329 dbus_message_iter_init(message, &iter);
01330
01331 ssid = wpa_config_add_network(wpa_s->conf);
01332 if (ssid == NULL) {
01333 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
01334 "can't add new interface.");
01335 reply = wpas_dbus_error_unknown_error(
01336 message,
01337 "wpa_supplicant could not add "
01338 "a network on this interface.");
01339 goto err;
01340 }
01341 wpas_notify_network_added(wpa_s, ssid);
01342 ssid->disabled = 1;
01343 wpa_config_set_network_defaults(ssid);
01344
01345 reply = set_network_properties(message, wpa_s, ssid, &iter);
01346 if (reply) {
01347 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
01348 "control interface couldn't set network "
01349 "properties");
01350 goto err;
01351 }
01352
01353
01354 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
01355 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
01356 wpa_s->dbus_new_path, ssid->id);
01357
01358 reply = dbus_message_new_method_return(message);
01359 if (reply == NULL) {
01360 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01361 NULL);
01362 goto err;
01363 }
01364 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
01365 DBUS_TYPE_INVALID)) {
01366 dbus_message_unref(reply);
01367 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01368 NULL);
01369 goto err;
01370 }
01371
01372 return reply;
01373
01374 err:
01375 if (ssid) {
01376 wpas_notify_network_removed(wpa_s, ssid);
01377 wpa_config_remove_network(wpa_s->conf, ssid->id);
01378 }
01379 return reply;
01380 }
01381
01382
01391 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
01392 struct wpa_supplicant *wpa_s)
01393 {
01394 DBusMessage *reply = NULL;
01395 const char *op;
01396 char *iface = NULL, *net_id = NULL;
01397 int id;
01398 struct wpa_ssid *ssid;
01399
01400 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
01401 DBUS_TYPE_INVALID);
01402
01403
01404
01405 iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
01406 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
01407 reply = wpas_dbus_error_invalid_args(message, op);
01408 goto out;
01409 }
01410
01411 id = strtoul(net_id, NULL, 10);
01412 if (errno == EINVAL) {
01413 reply = wpas_dbus_error_invalid_args(message, op);
01414 goto out;
01415 }
01416
01417 ssid = wpa_config_get_network(wpa_s->conf, id);
01418 if (ssid == NULL) {
01419 reply = wpas_dbus_error_network_unknown(message);
01420 goto out;
01421 }
01422
01423 wpas_notify_network_removed(wpa_s, ssid);
01424
01425 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
01426 wpa_printf(MSG_ERROR,
01427 "wpas_dbus_handler_remove_network[dbus]: "
01428 "error occurred when removing network %d", id);
01429 reply = wpas_dbus_error_unknown_error(
01430 message, "error removing the specified network on "
01431 "this interface.");
01432 goto out;
01433 }
01434
01435 if (ssid == wpa_s->current_ssid)
01436 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
01437
01438 out:
01439 os_free(iface);
01440 os_free(net_id);
01441 return reply;
01442 }
01443
01444
01453 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
01454 struct wpa_supplicant *wpa_s)
01455 {
01456 DBusMessage *reply = NULL;
01457 const char *op;
01458 char *iface = NULL, *net_id = NULL;
01459 int id;
01460 struct wpa_ssid *ssid;
01461
01462 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
01463 DBUS_TYPE_INVALID);
01464
01465
01466
01467 iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
01468 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
01469 reply = wpas_dbus_error_invalid_args(message, op);
01470 goto out;
01471 }
01472
01473 id = strtoul(net_id, NULL, 10);
01474 if (errno == EINVAL) {
01475 reply = wpas_dbus_error_invalid_args(message, op);
01476 goto out;
01477 }
01478
01479 ssid = wpa_config_get_network(wpa_s->conf, id);
01480 if (ssid == NULL) {
01481 reply = wpas_dbus_error_network_unknown(message);
01482 goto out;
01483 }
01484
01485
01486 wpa_supplicant_select_network(wpa_s, ssid);
01487
01488 out:
01489 os_free(iface);
01490 os_free(net_id);
01491 return reply;
01492 }
01493
01494
01503 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
01504 struct wpa_supplicant *wpa_s)
01505 {
01506 DBusMessage *reply = NULL;
01507 DBusMessageIter iter, array_iter;
01508
01509 char *blob_name;
01510 u8 *blob_data;
01511 int blob_len;
01512 struct wpa_config_blob *blob = NULL;
01513
01514 dbus_message_iter_init(message, &iter);
01515 dbus_message_iter_get_basic(&iter, &blob_name);
01516
01517 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
01518 return dbus_message_new_error(message,
01519 WPAS_DBUS_ERROR_BLOB_EXISTS,
01520 NULL);
01521 }
01522
01523 dbus_message_iter_next(&iter);
01524 dbus_message_iter_recurse(&iter, &array_iter);
01525
01526 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
01527
01528 blob = os_zalloc(sizeof(*blob));
01529 if (!blob) {
01530 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01531 NULL);
01532 goto err;
01533 }
01534
01535 blob->data = os_malloc(blob_len);
01536 if (!blob->data) {
01537 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01538 NULL);
01539 goto err;
01540 }
01541 os_memcpy(blob->data, blob_data, blob_len);
01542
01543 blob->len = blob_len;
01544 blob->name = os_strdup(blob_name);
01545 if (!blob->name) {
01546 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01547 NULL);
01548 goto err;
01549 }
01550
01551 wpa_config_set_blob(wpa_s->conf, blob);
01552 wpas_notify_blob_added(wpa_s, blob->name);
01553
01554 return reply;
01555
01556 err:
01557 if (blob) {
01558 os_free(blob->name);
01559 os_free(blob->data);
01560 os_free(blob);
01561 }
01562 return reply;
01563 }
01564
01565
01574 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
01575 struct wpa_supplicant *wpa_s)
01576 {
01577 DBusMessage *reply = NULL;
01578 DBusMessageIter iter, array_iter;
01579
01580 char *blob_name;
01581 const struct wpa_config_blob *blob;
01582
01583 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
01584 DBUS_TYPE_INVALID);
01585
01586 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
01587 if (!blob) {
01588 return dbus_message_new_error(message,
01589 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
01590 "Blob id not set");
01591 }
01592
01593 reply = dbus_message_new_method_return(message);
01594 if (!reply) {
01595 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01596 NULL);
01597 goto out;
01598 }
01599
01600 dbus_message_iter_init_append(reply, &iter);
01601
01602 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
01603 DBUS_TYPE_BYTE_AS_STRING,
01604 &array_iter)) {
01605 dbus_message_unref(reply);
01606 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01607 NULL);
01608 goto out;
01609 }
01610
01611 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
01612 &(blob->data), blob->len)) {
01613 dbus_message_unref(reply);
01614 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01615 NULL);
01616 goto out;
01617 }
01618
01619 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
01620 dbus_message_unref(reply);
01621 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01622 NULL);
01623 goto out;
01624 }
01625
01626 out:
01627 return reply;
01628 }
01629
01630
01639 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
01640 struct wpa_supplicant *wpa_s)
01641 {
01642 DBusMessage *reply = NULL;
01643 char *blob_name;
01644
01645 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
01646 DBUS_TYPE_INVALID);
01647
01648 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
01649 return dbus_message_new_error(message,
01650 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
01651 "Blob id not set");
01652 }
01653 wpas_notify_blob_removed(wpa_s, blob_name);
01654
01655 return reply;
01656
01657 }
01658
01659
01668 DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
01669 struct wpa_supplicant *wpa_s)
01670 {
01671 DBusMessage *reply = NULL;
01672 struct wpa_driver_capa capa;
01673 int res;
01674 DBusMessageIter iter, iter_dict;
01675 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array,
01676 variant_iter;
01677 const char *scans[] = { "active", "passive", "ssid" };
01678 const char *modes[] = { "infrastructure", "ad-hoc", "ap" };
01679 int n = sizeof(modes) / sizeof(char *);
01680
01681 if (message == NULL)
01682 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
01683 else
01684 reply = dbus_message_new_method_return(message);
01685 if (!reply)
01686 goto nomem;
01687
01688 dbus_message_iter_init_append(reply, &iter);
01689 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
01690 "a{sv}", &variant_iter))
01691 goto nomem;
01692
01693 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
01694 goto nomem;
01695
01696 res = wpa_drv_get_capa(wpa_s, &capa);
01697
01698
01699 if (res < 0) {
01700 const char *args[] = {"ccmp", "tkip", "none"};
01701 if (!wpa_dbus_dict_append_string_array(
01702 &iter_dict, "Pairwise", args,
01703 sizeof(args) / sizeof(char*)))
01704 goto nomem;
01705 } else {
01706 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
01707 &iter_dict_entry,
01708 &iter_dict_val,
01709 &iter_array))
01710 goto nomem;
01711
01712 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
01713 if (!wpa_dbus_dict_string_array_add_element(
01714 &iter_array, "ccmp"))
01715 goto nomem;
01716 }
01717
01718 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
01719 if (!wpa_dbus_dict_string_array_add_element(
01720 &iter_array, "tkip"))
01721 goto nomem;
01722 }
01723
01724 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
01725 if (!wpa_dbus_dict_string_array_add_element(
01726 &iter_array, "none"))
01727 goto nomem;
01728 }
01729
01730 if (!wpa_dbus_dict_end_string_array(&iter_dict,
01731 &iter_dict_entry,
01732 &iter_dict_val,
01733 &iter_array))
01734 goto nomem;
01735 }
01736
01737
01738 if (res < 0) {
01739 const char *args[] = {
01740 "ccmp", "tkip", "wep104", "wep40"
01741 };
01742 if (!wpa_dbus_dict_append_string_array(
01743 &iter_dict, "Group", args,
01744 sizeof(args) / sizeof(char*)))
01745 goto nomem;
01746 } else {
01747 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
01748 &iter_dict_entry,
01749 &iter_dict_val,
01750 &iter_array))
01751 goto nomem;
01752
01753 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
01754 if (!wpa_dbus_dict_string_array_add_element(
01755 &iter_array, "ccmp"))
01756 goto nomem;
01757 }
01758
01759 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
01760 if (!wpa_dbus_dict_string_array_add_element(
01761 &iter_array, "tkip"))
01762 goto nomem;
01763 }
01764
01765 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
01766 if (!wpa_dbus_dict_string_array_add_element(
01767 &iter_array, "wep104"))
01768 goto nomem;
01769 }
01770
01771 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
01772 if (!wpa_dbus_dict_string_array_add_element(
01773 &iter_array, "wep40"))
01774 goto nomem;
01775 }
01776
01777 if (!wpa_dbus_dict_end_string_array(&iter_dict,
01778 &iter_dict_entry,
01779 &iter_dict_val,
01780 &iter_array))
01781 goto nomem;
01782 }
01783
01784
01785 if (res < 0) {
01786 const char *args[] = {
01787 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
01788 #ifdef CONFIG_WPS
01789 "wps",
01790 #endif
01791 "none"
01792 };
01793 if (!wpa_dbus_dict_append_string_array(
01794 &iter_dict, "KeyMgmt", args,
01795 sizeof(args) / sizeof(char*)))
01796 goto nomem;
01797 } else {
01798 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
01799 &iter_dict_entry,
01800 &iter_dict_val,
01801 &iter_array))
01802 goto nomem;
01803
01804 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
01805 "none"))
01806 goto nomem;
01807
01808 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
01809 "ieee8021x"))
01810 goto nomem;
01811
01812 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
01813 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
01814 if (!wpa_dbus_dict_string_array_add_element(
01815 &iter_array, "wpa-eap"))
01816 goto nomem;
01817
01818 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
01819 if (!wpa_dbus_dict_string_array_add_element(
01820 &iter_array, "wpa-ft-eap"))
01821 goto nomem;
01822
01823
01824 #ifdef CONFIG_IEEE80211W
01825 if (!wpa_dbus_dict_string_array_add_element(
01826 &iter_array, "wpa-eap-sha256"))
01827 goto nomem;
01828 #endif
01829 }
01830
01831 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
01832 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
01833 if (!wpa_dbus_dict_string_array_add_element(
01834 &iter_array, "wpa-psk"))
01835 goto nomem;
01836
01837 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
01838 if (!wpa_dbus_dict_string_array_add_element(
01839 &iter_array, "wpa-ft-psk"))
01840 goto nomem;
01841
01842
01843 #ifdef CONFIG_IEEE80211W
01844 if (!wpa_dbus_dict_string_array_add_element(
01845 &iter_array, "wpa-psk-sha256"))
01846 goto nomem;
01847 #endif
01848 }
01849
01850 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
01851 if (!wpa_dbus_dict_string_array_add_element(
01852 &iter_array, "wpa-none"))
01853 goto nomem;
01854 }
01855
01856
01857 #ifdef CONFIG_WPS
01858 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
01859 "wps"))
01860 goto nomem;
01861 #endif
01862
01863 if (!wpa_dbus_dict_end_string_array(&iter_dict,
01864 &iter_dict_entry,
01865 &iter_dict_val,
01866 &iter_array))
01867 goto nomem;
01868 }
01869
01870
01871 if (res < 0) {
01872 const char *args[] = { "rsn", "wpa" };
01873 if (!wpa_dbus_dict_append_string_array(
01874 &iter_dict, "Protocol", args,
01875 sizeof(args) / sizeof(char*)))
01876 goto nomem;
01877 } else {
01878 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
01879 &iter_dict_entry,
01880 &iter_dict_val,
01881 &iter_array))
01882 goto nomem;
01883
01884 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
01885 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
01886 if (!wpa_dbus_dict_string_array_add_element(
01887 &iter_array, "rsn"))
01888 goto nomem;
01889 }
01890
01891 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
01892 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
01893 if (!wpa_dbus_dict_string_array_add_element(
01894 &iter_array, "wpa"))
01895 goto nomem;
01896 }
01897
01898 if (!wpa_dbus_dict_end_string_array(&iter_dict,
01899 &iter_dict_entry,
01900 &iter_dict_val,
01901 &iter_array))
01902 goto nomem;
01903 }
01904
01905
01906 if (res < 0) {
01907 const char *args[] = { "open", "shared", "leap" };
01908 if (!wpa_dbus_dict_append_string_array(
01909 &iter_dict, "AuthAlg", args,
01910 sizeof(args) / sizeof(char*)))
01911 goto nomem;
01912 } else {
01913 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
01914 &iter_dict_entry,
01915 &iter_dict_val,
01916 &iter_array))
01917 goto nomem;
01918
01919 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
01920 if (!wpa_dbus_dict_string_array_add_element(
01921 &iter_array, "open"))
01922 goto nomem;
01923 }
01924
01925 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
01926 if (!wpa_dbus_dict_string_array_add_element(
01927 &iter_array, "shared"))
01928 goto nomem;
01929 }
01930
01931 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
01932 if (!wpa_dbus_dict_string_array_add_element(
01933 &iter_array, "leap"))
01934 goto nomem;
01935 }
01936
01937 if (!wpa_dbus_dict_end_string_array(&iter_dict,
01938 &iter_dict_entry,
01939 &iter_dict_val,
01940 &iter_array))
01941 goto nomem;
01942 }
01943
01944
01945 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
01946 sizeof(scans) / sizeof(char *)))
01947 goto nomem;
01948
01949
01950 if (res < 0 || !(capa.flags & WPA_DRIVER_FLAGS_AP))
01951 n--;
01952 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Modes", modes, n))
01953 goto nomem;
01954
01955 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
01956 goto nomem;
01957 if (!dbus_message_iter_close_container(&iter, &variant_iter))
01958 goto nomem;
01959
01960 return reply;
01961
01962 nomem:
01963 if (reply)
01964 dbus_message_unref(reply);
01965
01966 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
01967 }
01968
01969
01979 DBusMessage * wpas_dbus_getter_state(DBusMessage *message,
01980 struct wpa_supplicant *wpa_s)
01981 {
01982 DBusMessage *reply = NULL;
01983 const char *str_state;
01984 char *state_ls, *tmp;
01985
01986 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
01987
01988
01989
01990 state_ls = tmp = os_strdup(str_state);
01991 if (!tmp) {
01992 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
01993 NULL);
01994 }
01995 while (*tmp) {
01996 *tmp = tolower(*tmp);
01997 tmp++;
01998 }
01999
02000 reply = wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
02001 &state_ls);
02002
02003 os_free(state_ls);
02004
02005 return reply;
02006 }
02007
02008
02017 DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message,
02018 struct wpa_supplicant *wpa_s)
02019 {
02020 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
02021 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
02022 &scanning);
02023 }
02024
02025
02034 DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message,
02035 struct wpa_supplicant *wpa_s)
02036 {
02037 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
02038 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
02039 &ap_scan);
02040 }
02041
02042
02051 DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message,
02052 struct wpa_supplicant *wpa_s)
02053 {
02054 DBusMessage *reply = NULL;
02055 dbus_uint32_t ap_scan;
02056
02057 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
02058 &ap_scan);
02059 if (reply)
02060 return reply;
02061
02062 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
02063 return wpas_dbus_error_invalid_args(
02064 message, "ap_scan must equal 0, 1 or 2");
02065 }
02066 return NULL;
02067 }
02068
02069
02079 DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message,
02080 struct wpa_supplicant *wpa_s)
02081 {
02082 const char *ifname = wpa_s->ifname;
02083 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
02084 &ifname);
02085 }
02086
02087
02097 DBusMessage * wpas_dbus_getter_driver(DBusMessage *message,
02098 struct wpa_supplicant *wpa_s)
02099 {
02100 const char *driver;
02101
02102 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
02103 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
02104 "wpa_s has no driver set");
02105 return wpas_dbus_error_unknown_error(message, NULL);
02106 }
02107
02108 driver = wpa_s->driver->name;
02109 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
02110 &driver);
02111 }
02112
02113
02123 DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message,
02124 struct wpa_supplicant *wpa_s)
02125 {
02126 DBusMessage *reply;
02127 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
02128
02129 if (wpa_s->current_bss)
02130 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
02131 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
02132 wpa_s->dbus_new_path, wpa_s->current_bss->id);
02133 else
02134 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
02135
02136 reply = wpas_dbus_simple_property_getter(message,
02137 DBUS_TYPE_OBJECT_PATH,
02138 &bss_obj_path);
02139
02140 return reply;
02141 }
02142
02143
02153 DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
02154 struct wpa_supplicant *wpa_s)
02155 {
02156 DBusMessage *reply;
02157 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
02158
02159 if (wpa_s->current_ssid)
02160 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
02161 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
02162 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
02163 else
02164 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
02165
02166 reply = wpas_dbus_simple_property_getter(message,
02167 DBUS_TYPE_OBJECT_PATH,
02168 &net_obj_path);
02169
02170 return reply;
02171 }
02172
02173
02183 DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message,
02184 struct wpa_supplicant *wpa_s)
02185 {
02186 const char *bridge_ifname = NULL;
02187
02188 bridge_ifname = wpa_s->bridge_ifname;
02189 if (bridge_ifname == NULL) {
02190 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: "
02191 "wpa_s has no bridge interface name set");
02192 return wpas_dbus_error_unknown_error(message, NULL);
02193 }
02194
02195 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
02196 &bridge_ifname);
02197 }
02198
02199
02209 DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
02210 struct wpa_supplicant *wpa_s)
02211 {
02212 DBusMessage *reply = NULL;
02213 struct wpa_bss *bss;
02214 char **paths;
02215 unsigned int i = 0;
02216
02217 paths = os_zalloc(wpa_s->num_bss * sizeof(char *));
02218 if (!paths) {
02219 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02220 NULL);
02221 }
02222
02223
02224 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
02225 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
02226 if (paths[i] == NULL) {
02227 reply = dbus_message_new_error(message,
02228 DBUS_ERROR_NO_MEMORY,
02229 NULL);
02230 goto out;
02231 }
02232
02233 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
02234 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
02235 wpa_s->dbus_new_path, bss->id);
02236 }
02237
02238 reply = wpas_dbus_simple_array_property_getter(message,
02239 DBUS_TYPE_OBJECT_PATH,
02240 paths, wpa_s->num_bss);
02241
02242 out:
02243 while (i)
02244 os_free(paths[--i]);
02245 os_free(paths);
02246 return reply;
02247 }
02248
02249
02259 DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
02260 struct wpa_supplicant *wpa_s)
02261 {
02262 DBusMessage *reply = NULL;
02263 struct wpa_ssid *ssid;
02264 char **paths;
02265 unsigned int i = 0, num = 0;
02266
02267 if (wpa_s->conf == NULL) {
02268 wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: "
02269 "An error occurred getting networks list.");
02270 return wpas_dbus_error_unknown_error(message, NULL);
02271 }
02272
02273 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
02274 num++;
02275
02276 paths = os_zalloc(num * sizeof(char *));
02277 if (!paths) {
02278 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02279 NULL);
02280 }
02281
02282
02283 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
02284 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
02285 if (paths[i] == NULL) {
02286 reply = dbus_message_new_error(message,
02287 DBUS_ERROR_NO_MEMORY,
02288 NULL);
02289 goto out;
02290 }
02291
02292
02293 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
02294 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
02295 wpa_s->dbus_new_path, ssid->id);
02296 }
02297
02298 reply = wpas_dbus_simple_array_property_getter(message,
02299 DBUS_TYPE_OBJECT_PATH,
02300 paths, num);
02301
02302 out:
02303 while (i)
02304 os_free(paths[--i]);
02305 os_free(paths);
02306 return reply;
02307 }
02308
02309
02318 DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message,
02319 struct wpa_supplicant *wpa_s)
02320 {
02321 DBusMessage *reply = NULL;
02322 DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter;
02323 struct wpa_config_blob *blob;
02324
02325 if (message == NULL)
02326 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
02327 else
02328 reply = dbus_message_new_method_return(message);
02329 if (!reply)
02330 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02331 NULL);
02332
02333 dbus_message_iter_init_append(reply, &iter);
02334
02335 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
02336 "a{say}", &variant_iter) ||
02337 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
02338 "{say}", &dict_iter)) {
02339 dbus_message_unref(reply);
02340 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02341 NULL);
02342 }
02343
02344 blob = wpa_s->conf->blobs;
02345 while (blob) {
02346 if (!dbus_message_iter_open_container(&dict_iter,
02347 DBUS_TYPE_DICT_ENTRY,
02348 NULL, &entry_iter) ||
02349 !dbus_message_iter_append_basic(&entry_iter,
02350 DBUS_TYPE_STRING,
02351 &(blob->name)) ||
02352 !dbus_message_iter_open_container(&entry_iter,
02353 DBUS_TYPE_ARRAY,
02354 DBUS_TYPE_BYTE_AS_STRING,
02355 &array_iter) ||
02356 !dbus_message_iter_append_fixed_array(&array_iter,
02357 DBUS_TYPE_BYTE,
02358 &(blob->data),
02359 blob->len) ||
02360 !dbus_message_iter_close_container(&entry_iter,
02361 &array_iter) ||
02362 !dbus_message_iter_close_container(&dict_iter,
02363 &entry_iter)) {
02364 dbus_message_unref(reply);
02365 return dbus_message_new_error(message,
02366 DBUS_ERROR_NO_MEMORY,
02367 NULL);
02368 }
02369
02370 blob = blob->next;
02371 }
02372
02373 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
02374 !dbus_message_iter_close_container(&iter, &variant_iter)) {
02375 dbus_message_unref(reply);
02376 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02377 NULL);
02378 }
02379
02380 return reply;
02381 }
02382
02383
02392 DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message,
02393 struct bss_handler_args *bss)
02394 {
02395 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02396
02397 if (!res) {
02398 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_bssid[dbus]: no "
02399 "bss with id %d found", bss->id);
02400 return NULL;
02401 }
02402
02403 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
02404 res->bssid, ETH_ALEN);
02405 }
02406
02407
02416 DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message,
02417 struct bss_handler_args *bss)
02418 {
02419 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02420
02421 if (!res) {
02422 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ssid[dbus]: no "
02423 "bss with id %d found", bss->id);
02424 return NULL;
02425 }
02426
02427 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
02428 res->ssid,
02429 res->ssid_len);
02430 }
02431
02432
02441 DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message,
02442 struct bss_handler_args *bss)
02443 {
02444 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02445 dbus_bool_t privacy;
02446
02447 if (!res) {
02448 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_privacy[dbus]: no "
02449 "bss with id %d found", bss->id);
02450 return NULL;
02451 }
02452
02453 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
02454 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
02455 &privacy);
02456 }
02457
02458
02467 DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message,
02468 struct bss_handler_args *bss)
02469 {
02470 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02471 const char *mode;
02472
02473 if (!res) {
02474 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_mode[dbus]: no "
02475 "bss with id %d found", bss->id);
02476 return NULL;
02477 }
02478
02479 if (res->caps & IEEE80211_CAP_IBSS)
02480 mode = "ad-hoc";
02481 else
02482 mode = "infrastructure";
02483
02484 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
02485 &mode);
02486 }
02487
02488
02497 DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message,
02498 struct bss_handler_args *bss)
02499 {
02500 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02501
02502 if (!res) {
02503 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_signal[dbus]: no "
02504 "bss with id %d found", bss->id);
02505 return NULL;
02506 }
02507
02508 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_INT16,
02509 &res->level);
02510 }
02511
02512
02521 DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message,
02522 struct bss_handler_args *bss)
02523 {
02524 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02525
02526 if (!res) {
02527 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_frequency[dbus]: "
02528 "no bss with id %d found", bss->id);
02529 return NULL;
02530 }
02531
02532 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT16,
02533 &res->freq);
02534 }
02535
02536
02537 static int cmp_u8s_desc(const void *a, const void *b)
02538 {
02539 return (*(u8 *) b - *(u8 *) a);
02540 }
02541
02542
02551 DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message,
02552 struct bss_handler_args *bss)
02553 {
02554 DBusMessage *reply;
02555 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02556 u8 *ie_rates = NULL;
02557 u32 *real_rates;
02558 int rates_num, i;
02559
02560 if (!res) {
02561 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rates[dbus]: "
02562 "no bss with id %d found", bss->id);
02563 return NULL;
02564 }
02565
02566 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
02567 if (rates_num < 0)
02568 return NULL;
02569
02570 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
02571
02572 real_rates = os_malloc(sizeof(u32) * rates_num);
02573 if (!real_rates) {
02574 os_free(ie_rates);
02575 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02576 NULL);
02577 }
02578
02579 for (i = 0; i < rates_num; i++)
02580 real_rates[i] = ie_rates[i] * 500000;
02581
02582 reply = wpas_dbus_simple_array_property_getter(message,
02583 DBUS_TYPE_UINT32,
02584 real_rates, rates_num);
02585
02586 os_free(ie_rates);
02587 os_free(real_rates);
02588 return reply;
02589 }
02590
02591
02592 static DBusMessage * wpas_dbus_get_bss_security_prop(
02593 DBusMessage *message, struct wpa_ie_data *ie_data)
02594 {
02595 DBusMessage *reply;
02596 DBusMessageIter iter, iter_dict, variant_iter;
02597 const char *group;
02598 const char *pairwise[2];
02599 const char *key_mgmt[7];
02600 int n;
02601
02602 if (message == NULL)
02603 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
02604 else
02605 reply = dbus_message_new_method_return(message);
02606 if (!reply)
02607 goto nomem;
02608
02609 dbus_message_iter_init_append(reply, &iter);
02610 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
02611 "a{sv}", &variant_iter))
02612 goto nomem;
02613
02614 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
02615 goto nomem;
02616
02617
02618 n = 0;
02619 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
02620 key_mgmt[n++] = "wpa-psk";
02621 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
02622 key_mgmt[n++] = "wpa-ft-psk";
02623 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
02624 key_mgmt[n++] = "wpa-psk-sha256";
02625 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
02626 key_mgmt[n++] = "wpa-eap";
02627 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
02628 key_mgmt[n++] = "wpa-ft-eap";
02629 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
02630 key_mgmt[n++] = "wpa-eap-sha256";
02631 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
02632 key_mgmt[n++] = "wpa-none";
02633
02634 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
02635 key_mgmt, n))
02636 goto nomem;
02637
02638
02639 switch (ie_data->group_cipher) {
02640 case WPA_CIPHER_WEP40:
02641 group = "wep40";
02642 break;
02643 case WPA_CIPHER_TKIP:
02644 group = "tkip";
02645 break;
02646 case WPA_CIPHER_CCMP:
02647 group = "ccmp";
02648 break;
02649 case WPA_CIPHER_WEP104:
02650 group = "wep104";
02651 break;
02652 default:
02653 group = "";
02654 break;
02655 }
02656
02657 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
02658 goto nomem;
02659
02660
02661 n = 0;
02662 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
02663 pairwise[n++] = "tkip";
02664 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
02665 pairwise[n++] = "ccmp";
02666
02667 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
02668 pairwise, n))
02669 goto nomem;
02670
02671
02672 if (ie_data->proto == WPA_PROTO_RSN) {
02673 switch (ie_data->mgmt_group_cipher) {
02674 #ifdef CONFIG_IEEE80211W
02675 case WPA_CIPHER_AES_128_CMAC:
02676 group = "aes128cmac";
02677 break;
02678 #endif
02679 default:
02680 group = "";
02681 break;
02682 }
02683
02684 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
02685 group))
02686 goto nomem;
02687 }
02688
02689 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
02690 goto nomem;
02691 if (!dbus_message_iter_close_container(&iter, &variant_iter))
02692 goto nomem;
02693
02694 return reply;
02695
02696 nomem:
02697 if (reply)
02698 dbus_message_unref(reply);
02699
02700 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
02701 }
02702
02703
02712 DBusMessage * wpas_dbus_getter_bss_wpa(DBusMessage *message,
02713 struct bss_handler_args *bss)
02714 {
02715 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02716 struct wpa_ie_data wpa_data;
02717 const u8 *ie;
02718
02719 if (!res) {
02720 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_wpa[dbus]: no "
02721 "bss with id %d found", bss->id);
02722 return NULL;
02723 }
02724
02725 os_memset(&wpa_data, 0, sizeof(wpa_data));
02726 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
02727 if (ie)
02728 wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data);
02729
02730 return wpas_dbus_get_bss_security_prop(message, &wpa_data);
02731 }
02732
02733
02742 DBusMessage * wpas_dbus_getter_bss_rsn(DBusMessage *message,
02743 struct bss_handler_args *bss)
02744 {
02745 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02746 struct wpa_ie_data wpa_data;
02747 const u8 *ie;
02748
02749 if (!res) {
02750 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rsn[dbus]: no "
02751 "bss with id %d found", bss->id);
02752 return NULL;
02753 }
02754
02755 os_memset(&wpa_data, 0, sizeof(wpa_data));
02756 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
02757 if (ie)
02758 wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data);
02759
02760 return wpas_dbus_get_bss_security_prop(message, &wpa_data);
02761 }
02762
02763
02772 DBusMessage * wpas_dbus_getter_bss_ies(DBusMessage *message,
02773 struct bss_handler_args *bss)
02774 {
02775 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
02776
02777 if (!res) {
02778 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ies[dbus]: no "
02779 "bss with id %d found", bss->id);
02780 return NULL;
02781 }
02782
02783 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
02784 res + 1, res->ie_len);
02785 }
02786
02787
02798 DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message,
02799 struct network_handler_args *net)
02800 {
02801 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
02802 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
02803 &enabled);
02804 }
02805
02806
02816 DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message,
02817 struct network_handler_args *net)
02818 {
02819 DBusMessage *reply = NULL;
02820
02821 struct wpa_supplicant *wpa_s;
02822 struct wpa_ssid *ssid;
02823
02824 dbus_bool_t enable;
02825
02826 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
02827 &enable);
02828
02829 if (reply)
02830 return reply;
02831
02832 wpa_s = net->wpa_s;
02833 ssid = net->ssid;
02834
02835 if (enable)
02836 wpa_supplicant_enable_network(wpa_s, ssid);
02837 else
02838 wpa_supplicant_disable_network(wpa_s, ssid);
02839
02840 return NULL;
02841 }
02842
02843
02853 DBusMessage * wpas_dbus_getter_network_properties(
02854 DBusMessage *message, struct network_handler_args *net)
02855 {
02856 DBusMessage *reply = NULL;
02857 DBusMessageIter iter, variant_iter, dict_iter;
02858 char **iterator;
02859 char **props = wpa_config_get_all(net->ssid, 0);
02860 if (!props)
02861 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02862 NULL);
02863
02864 if (message == NULL)
02865 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
02866 else
02867 reply = dbus_message_new_method_return(message);
02868 if (!reply) {
02869 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02870 NULL);
02871 goto out;
02872 }
02873
02874 dbus_message_iter_init_append(reply, &iter);
02875
02876 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
02877 "a{sv}", &variant_iter) ||
02878 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
02879 dbus_message_unref(reply);
02880 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02881 NULL);
02882 goto out;
02883 }
02884
02885 iterator = props;
02886 while (*iterator) {
02887 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
02888 *(iterator + 1))) {
02889 dbus_message_unref(reply);
02890 reply = dbus_message_new_error(message,
02891 DBUS_ERROR_NO_MEMORY,
02892 NULL);
02893 goto out;
02894 }
02895 iterator += 2;
02896 }
02897
02898
02899 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
02900 !dbus_message_iter_close_container(&iter, &variant_iter)) {
02901 dbus_message_unref(reply);
02902 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
02903 NULL);
02904 goto out;
02905 }
02906
02907 out:
02908 iterator = props;
02909 while (*iterator) {
02910 os_free(*iterator);
02911 iterator++;
02912 }
02913 os_free(props);
02914 return reply;
02915 }
02916
02917
02927 DBusMessage * wpas_dbus_setter_network_properties(
02928 DBusMessage *message, struct network_handler_args *net)
02929 {
02930 struct wpa_ssid *ssid = net->ssid;
02931
02932 DBusMessage *reply = NULL;
02933 DBusMessageIter iter, variant_iter;
02934
02935 dbus_message_iter_init(message, &iter);
02936
02937 dbus_message_iter_next(&iter);
02938 dbus_message_iter_next(&iter);
02939
02940 dbus_message_iter_recurse(&iter, &variant_iter);
02941
02942 reply = set_network_properties(message, net->wpa_s, ssid,
02943 &variant_iter);
02944 if (reply)
02945 wpa_printf(MSG_DEBUG, "dbus control interface couldn't set "
02946 "network properties");
02947
02948 return reply;
02949 }