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