$search
00001 /* 00002 * WPA Supplicant / dbus-based control interface 00003 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 00004 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com> 00005 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License version 2 as 00009 * published by the Free Software Foundation. 00010 * 00011 * Alternatively, this software may be distributed under the terms of BSD 00012 * license. 00013 * 00014 * See README and COPYING for more details. 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 /* Be a bit paranoid about path */ 00065 if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/", 00066 dev_path_prefix_len)) 00067 return NULL; 00068 00069 /* Ensure there's something at the end of the path */ 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 /* Deal with a request for a configured network */ 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 /* Deal with a request for a scanned BSSID */ 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 /* Cut off interface object path before "/" */ 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 /* omit first and second argument and get value from third */ 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?"; /* ? will be replaced with subtype letter; */ 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; /* Required Ifname argument missing */ 00591 00592 /* 00593 * Try to get the wpa_supplicant record for this iface, return 00594 * an error if we already control it. 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 /* Otherwise, have wpa_supplicant attach to it. */ 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 /* wildcard ssid */ 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 * wpas_dbus_handler_disconnect - Terminate the current connection 01291 * @message: Pointer to incoming dbus message 01292 * @wpa_s: wpa_supplicant structure for a network interface 01293 * Returns: NotConnected DBus error message if already not connected 01294 * or NULL otherwise. 01295 * 01296 * Handler function for "Disconnect" method call of network interface. 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 /* Construct the object path for this network. */ 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 /* Extract the network ID and ensure the network */ 01404 /* is actually a child of this interface */ 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 /* Extract the network ID and ensure the network */ 01466 /* is actually a child of this interface */ 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 /* Finally, associate with the network */ 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 /***** pairwise cipher */ 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 /***** group cipher */ 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 /***** key management */ 01785 if (res < 0) { 01786 const char *args[] = { 01787 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none", 01788 #ifdef CONFIG_WPS 01789 "wps", 01790 #endif /* CONFIG_WPS */ 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 /* TODO: Ensure that driver actually supports sha256 encryption. */ 01824 #ifdef CONFIG_IEEE80211W 01825 if (!wpa_dbus_dict_string_array_add_element( 01826 &iter_array, "wpa-eap-sha256")) 01827 goto nomem; 01828 #endif /* CONFIG_IEEE80211W */ 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 /* TODO: Ensure that driver actually supports sha256 encryption. */ 01843 #ifdef CONFIG_IEEE80211W 01844 if (!wpa_dbus_dict_string_array_add_element( 01845 &iter_array, "wpa-psk-sha256")) 01846 goto nomem; 01847 #endif /* CONFIG_IEEE80211W */ 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 /* CONFIG_WPS */ 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 /***** WPA protocol */ 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 /***** auth alg */ 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 /***** Scan */ 01945 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans, 01946 sizeof(scans) / sizeof(char *))) 01947 goto nomem; 01948 01949 /***** Modes */ 01950 if (res < 0 || !(capa.flags & WPA_DRIVER_FLAGS_AP)) 01951 n--; /* exclude ap mode if it is not supported by the driver */ 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 /* make state string lowercase to fit new DBus API convention 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 /* Loop through scan results and append each result's object path */ 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 /* Construct the object path for this BSS. */ 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 /* Loop through configured networks and append object path of each */ 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 /* Construct the object path for this network. */ 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]; /* max 2 pairwise ciphers is supported */ 02599 const char *key_mgmt[7]; /* max 7 key managements may be supported */ 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 /* KeyMgmt */ 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 /* Group */ 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 /* Pairwise */ 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 /* Management group (RSN only) */ 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 /* CONFIG_IEEE80211W */ 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 }