1/* 2 * WPA Supplicant / dbus-based control interface (P2P) 3 * Copyright (c) 2011-2012, Intel Corporation 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "includes.h" 10 11#include "utils/includes.h" 12#include "common.h" 13#include "../config.h" 14#include "../wpa_supplicant_i.h" 15#include "../wps_supplicant.h" 16#include "../notify.h" 17#include "dbus_new_helpers.h" 18#include "dbus_new.h" 19#include "dbus_new_handlers.h" 20#include "dbus_new_handlers_p2p.h" 21#include "dbus_dict_helpers.h" 22#include "p2p/p2p.h" 23#include "common/ieee802_11_defs.h" 24#include "ap/hostapd.h" 25#include "ap/ap_config.h" 26#include "ap/wps_hostapd.h" 27 28#include "../p2p_supplicant.h" 29#include "../wifi_display.h" 30 31/** 32 * Parses out the mac address from the peer object path. 33 * @peer_path - object path of the form 34 * /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons) 35 * @addr - out param must be of ETH_ALEN size 36 * Returns 0 if valid (including MAC), -1 otherwise 37 */ 38static int parse_peer_object_path(const char *peer_path, u8 addr[ETH_ALEN]) 39{ 40 const char *p; 41 42 if (!peer_path) 43 return -1; 44 p = os_strrchr(peer_path, '/'); 45 if (!p) 46 return -1; 47 p++; 48 return hwaddr_compact_aton(p, addr); 49} 50 51 52/** 53 * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown 54 * error message 55 * @message: Pointer to incoming dbus message this error refers to 56 * Returns: a dbus error message 57 * 58 * Convenience function to create and return an invalid persistent group error. 59 */ 60static DBusMessage * 61wpas_dbus_error_persistent_group_unknown(DBusMessage *message) 62{ 63 return dbus_message_new_error( 64 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN, 65 "There is no such persistent group in this P2P device."); 66} 67 68 69DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message, 70 struct wpa_supplicant *wpa_s) 71{ 72 struct wpa_dbus_dict_entry entry; 73 DBusMessage *reply = NULL; 74 DBusMessageIter iter; 75 DBusMessageIter iter_dict; 76 unsigned int timeout = 0; 77 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 78 int num_req_dev_types = 0; 79 unsigned int i; 80 u8 *req_dev_types = NULL; 81 82 dbus_message_iter_init(message, &iter); 83 entry.key = NULL; 84 85 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 86 goto error; 87 88 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 89 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 90 goto error; 91 92 if (os_strcmp(entry.key, "Timeout") == 0 && 93 entry.type == DBUS_TYPE_INT32) { 94 timeout = entry.uint32_value; 95 } else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) { 96 if (entry.type != DBUS_TYPE_ARRAY || 97 entry.array_type != WPAS_DBUS_TYPE_BINARRAY) 98 goto error_clear; 99 100 os_free(req_dev_types); 101 req_dev_types = 102 os_malloc(WPS_DEV_TYPE_LEN * entry.array_len); 103 if (!req_dev_types) 104 goto error_clear; 105 106 for (i = 0; i < entry.array_len; i++) { 107 if (wpabuf_len(entry.binarray_value[i]) != 108 WPS_DEV_TYPE_LEN) 109 goto error_clear; 110 os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN, 111 wpabuf_head(entry.binarray_value[i]), 112 WPS_DEV_TYPE_LEN); 113 } 114 num_req_dev_types = entry.array_len; 115 } else if (os_strcmp(entry.key, "DiscoveryType") == 0 && 116 entry.type == DBUS_TYPE_STRING) { 117 if (os_strcmp(entry.str_value, "start_with_full") == 0) 118 type = P2P_FIND_START_WITH_FULL; 119 else if (os_strcmp(entry.str_value, "social") == 0) 120 type = P2P_FIND_ONLY_SOCIAL; 121 else if (os_strcmp(entry.str_value, "progressive") == 0) 122 type = P2P_FIND_PROGRESSIVE; 123 else 124 goto error_clear; 125 } else 126 goto error_clear; 127 wpa_dbus_dict_entry_clear(&entry); 128 } 129 130 wpa_s = wpa_s->global->p2p_init_wpa_s; 131 132 wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types, 133 NULL, 0, 0, NULL, 0); 134 os_free(req_dev_types); 135 return reply; 136 137error_clear: 138 wpa_dbus_dict_entry_clear(&entry); 139error: 140 os_free(req_dev_types); 141 reply = wpas_dbus_error_invalid_args(message, entry.key); 142 return reply; 143} 144 145 146DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message, 147 struct wpa_supplicant *wpa_s) 148{ 149 wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s); 150 return NULL; 151} 152 153 154DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message, 155 struct wpa_supplicant *wpa_s) 156{ 157 DBusMessageIter iter; 158 char *peer_object_path = NULL; 159 u8 peer_addr[ETH_ALEN]; 160 161 dbus_message_iter_init(message, &iter); 162 dbus_message_iter_get_basic(&iter, &peer_object_path); 163 164 if (parse_peer_object_path(peer_object_path, peer_addr) < 0) 165 return wpas_dbus_error_invalid_args(message, NULL); 166 167 wpa_s = wpa_s->global->p2p_init_wpa_s; 168 169 if (wpas_p2p_reject(wpa_s, peer_addr) < 0) 170 return wpas_dbus_error_unknown_error(message, 171 "Failed to call wpas_p2p_reject method."); 172 173 return NULL; 174} 175 176 177DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message, 178 struct wpa_supplicant *wpa_s) 179{ 180 dbus_int32_t timeout = 0; 181 182 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout, 183 DBUS_TYPE_INVALID)) 184 return wpas_dbus_error_no_memory(message); 185 186 wpa_s = wpa_s->global->p2p_init_wpa_s; 187 188 if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) { 189 return dbus_message_new_error(message, 190 WPAS_DBUS_ERROR_UNKNOWN_ERROR, 191 "Could not start P2P listen"); 192 } 193 194 return NULL; 195} 196 197 198DBusMessage * wpas_dbus_handler_p2p_extendedlisten( 199 DBusMessage *message, struct wpa_supplicant *wpa_s) 200{ 201 unsigned int period = 0, interval = 0; 202 struct wpa_dbus_dict_entry entry; 203 DBusMessageIter iter; 204 DBusMessageIter iter_dict; 205 206 dbus_message_iter_init(message, &iter); 207 entry.key = NULL; 208 209 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 210 goto error; 211 212 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 213 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 214 goto error; 215 216 if (os_strcmp(entry.key, "period") == 0 && 217 entry.type == DBUS_TYPE_INT32) 218 period = entry.uint32_value; 219 else if (os_strcmp(entry.key, "interval") == 0 && 220 entry.type == DBUS_TYPE_INT32) 221 interval = entry.uint32_value; 222 else 223 goto error_clear; 224 wpa_dbus_dict_entry_clear(&entry); 225 } 226 227 wpa_s = wpa_s->global->p2p_init_wpa_s; 228 229 if (wpas_p2p_ext_listen(wpa_s, period, interval)) 230 return wpas_dbus_error_unknown_error( 231 message, "failed to initiate a p2p_ext_listen."); 232 233 return NULL; 234 235error_clear: 236 wpa_dbus_dict_entry_clear(&entry); 237error: 238 return wpas_dbus_error_invalid_args(message, entry.key); 239} 240 241 242DBusMessage * wpas_dbus_handler_p2p_presence_request( 243 DBusMessage *message, struct wpa_supplicant *wpa_s) 244{ 245 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 246 struct wpa_dbus_dict_entry entry; 247 DBusMessageIter iter; 248 DBusMessageIter iter_dict; 249 250 dbus_message_iter_init(message, &iter); 251 entry.key = NULL; 252 253 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 254 goto error; 255 256 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 257 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 258 goto error; 259 260 if (os_strcmp(entry.key, "duration1") == 0 && 261 entry.type == DBUS_TYPE_INT32) 262 dur1 = entry.uint32_value; 263 else if (os_strcmp(entry.key, "interval1") == 0 && 264 entry.type == DBUS_TYPE_INT32) 265 int1 = entry.uint32_value; 266 else if (os_strcmp(entry.key, "duration2") == 0 && 267 entry.type == DBUS_TYPE_INT32) 268 dur2 = entry.uint32_value; 269 else if (os_strcmp(entry.key, "interval2") == 0 && 270 entry.type == DBUS_TYPE_INT32) 271 int2 = entry.uint32_value; 272 else 273 goto error_clear; 274 275 wpa_dbus_dict_entry_clear(&entry); 276 } 277 278 if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0) 279 return wpas_dbus_error_unknown_error(message, 280 "Failed to invoke presence request."); 281 282 return NULL; 283 284error_clear: 285 wpa_dbus_dict_entry_clear(&entry); 286error: 287 return wpas_dbus_error_invalid_args(message, entry.key); 288} 289 290 291DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message, 292 struct wpa_supplicant *wpa_s) 293{ 294 DBusMessageIter iter_dict; 295 DBusMessage *reply = NULL; 296 DBusMessageIter iter; 297 struct wpa_dbus_dict_entry entry; 298 char *pg_object_path = NULL; 299 int persistent_group = 0; 300 int freq = 0; 301 char *iface = NULL; 302 unsigned int group_id = 0; 303 struct wpa_ssid *ssid; 304 305 dbus_message_iter_init(message, &iter); 306 307 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 308 goto inv_args; 309 310 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 311 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 312 goto inv_args; 313 314 if (os_strcmp(entry.key, "persistent") == 0 && 315 entry.type == DBUS_TYPE_BOOLEAN) { 316 persistent_group = entry.bool_value; 317 } else if (os_strcmp(entry.key, "frequency") == 0 && 318 entry.type == DBUS_TYPE_INT32) { 319 freq = entry.int32_value; 320 if (freq <= 0) 321 goto inv_args_clear; 322 } else if (os_strcmp(entry.key, "persistent_group_object") == 323 0 && 324 entry.type == DBUS_TYPE_OBJECT_PATH) 325 pg_object_path = os_strdup(entry.str_value); 326 else 327 goto inv_args_clear; 328 329 wpa_dbus_dict_entry_clear(&entry); 330 } 331 332 wpa_s = wpa_s->global->p2p_init_wpa_s; 333 334 if (pg_object_path != NULL) { 335 char *net_id_str; 336 337 /* 338 * A persistent group Object Path is defined meaning we want 339 * to re-invoke a persistent group. 340 */ 341 342 iface = wpas_dbus_new_decompose_object_path( 343 pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART, 344 &net_id_str); 345 if (iface == NULL || net_id_str == NULL || 346 !wpa_s->parent->dbus_new_path || 347 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) { 348 reply = 349 wpas_dbus_error_invalid_args(message, 350 pg_object_path); 351 goto out; 352 } 353 354 group_id = strtoul(net_id_str, NULL, 10); 355 if (errno == EINVAL) { 356 reply = wpas_dbus_error_invalid_args( 357 message, pg_object_path); 358 goto out; 359 } 360 361 /* Get the SSID structure from the persistent group id */ 362 ssid = wpa_config_get_network(wpa_s->conf, group_id); 363 if (ssid == NULL || ssid->disabled != 2) 364 goto inv_args; 365 366 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0, 367 0, 0, NULL, 0, 0)) { 368 reply = wpas_dbus_error_unknown_error( 369 message, 370 "Failed to reinvoke a persistent group"); 371 goto out; 372 } 373 } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0, 374 0)) 375 goto inv_args; 376 377out: 378 os_free(pg_object_path); 379 os_free(iface); 380 return reply; 381inv_args_clear: 382 wpa_dbus_dict_entry_clear(&entry); 383inv_args: 384 reply = wpas_dbus_error_invalid_args(message, NULL); 385 goto out; 386} 387 388 389DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message, 390 struct wpa_supplicant *wpa_s) 391{ 392 if (wpas_p2p_disconnect(wpa_s)) 393 return wpas_dbus_error_unknown_error(message, 394 "failed to disconnect"); 395 396 return NULL; 397} 398 399 400static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s, 401 DBusMessage *message, 402 DBusMessage **out_reply, 403 DBusError *error) 404{ 405 /* Return an error message or an error if P2P isn't available */ 406 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) { 407 if (out_reply) { 408 *out_reply = dbus_message_new_error( 409 message, DBUS_ERROR_FAILED, 410 "P2P is not available for this interface"); 411 } 412 dbus_set_error_const(error, DBUS_ERROR_FAILED, 413 "P2P is not available for this interface"); 414 return FALSE; 415 } 416 return TRUE; 417} 418 419 420DBusMessage * wpas_dbus_handler_p2p_remove_client(DBusMessage *message, 421 struct wpa_supplicant *wpa_s) 422{ 423 DBusMessageIter iter_dict; 424 DBusMessage *reply = NULL; 425 DBusMessageIter iter; 426 struct wpa_dbus_dict_entry entry; 427 char *peer_object_path = NULL; 428 char *interface_addr = NULL; 429 u8 peer_addr[ETH_ALEN]; 430 431 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL)) 432 return reply; 433 434 dbus_message_iter_init(message, &iter); 435 436 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 437 goto err; 438 439 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 440 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 441 goto err; 442 443 if (os_strcmp(entry.key, "peer") == 0 && 444 entry.type == DBUS_TYPE_OBJECT_PATH) { 445 os_free(peer_object_path); 446 peer_object_path = os_strdup(entry.str_value); 447 wpa_dbus_dict_entry_clear(&entry); 448 } else if (os_strcmp(entry.key, "iface") == 0 && 449 entry.type == DBUS_TYPE_STRING) { 450 os_free(interface_addr); 451 interface_addr = os_strdup(entry.str_value); 452 wpa_dbus_dict_entry_clear(&entry); 453 } else { 454 wpa_dbus_dict_entry_clear(&entry); 455 goto err; 456 } 457 } 458 459 if ((!peer_object_path && !interface_addr) || 460 (peer_object_path && 461 (parse_peer_object_path(peer_object_path, peer_addr) < 0 || 462 !p2p_peer_known(wpa_s->global->p2p, peer_addr))) || 463 (interface_addr && hwaddr_aton(interface_addr, peer_addr) < 0)) 464 goto err; 465 466 wpas_p2p_remove_client(wpa_s, peer_addr, interface_addr != NULL); 467 reply = NULL; 468out: 469 os_free(peer_object_path); 470 os_free(interface_addr); 471 return reply; 472err: 473 reply = wpas_dbus_error_invalid_args(message, "Invalid address format"); 474 goto out; 475} 476 477 478DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message, 479 struct wpa_supplicant *wpa_s) 480{ 481 DBusMessage *reply = NULL; 482 483 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL)) 484 return reply; 485 486 wpa_s = wpa_s->global->p2p_init_wpa_s; 487 488 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 489 wpa_s->force_long_sd = 0; 490 p2p_flush(wpa_s->global->p2p); 491 492 return NULL; 493} 494 495 496DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message, 497 struct wpa_supplicant *wpa_s) 498{ 499 DBusMessageIter iter_dict; 500 DBusMessage *reply = NULL; 501 DBusMessageIter iter; 502 struct wpa_dbus_dict_entry entry; 503 char *peer_object_path = NULL; 504 int persistent_group = 0; 505 int join = 0; 506 int authorize_only = 0; 507 int go_intent = -1; 508 int freq = 0; 509 u8 addr[ETH_ALEN]; 510 char *pin = NULL; 511 enum p2p_wps_method wps_method = WPS_NOT_READY; 512 int new_pin; 513 char *err_msg = NULL; 514 char *iface = NULL; 515 516 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL)) 517 return reply; 518 519 dbus_message_iter_init(message, &iter); 520 521 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 522 goto inv_args; 523 524 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 525 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 526 goto inv_args; 527 528 if (os_strcmp(entry.key, "peer") == 0 && 529 entry.type == DBUS_TYPE_OBJECT_PATH) { 530 peer_object_path = os_strdup(entry.str_value); 531 } else if (os_strcmp(entry.key, "persistent") == 0 && 532 entry.type == DBUS_TYPE_BOOLEAN) { 533 persistent_group = entry.bool_value; 534 } else if (os_strcmp(entry.key, "join") == 0 && 535 entry.type == DBUS_TYPE_BOOLEAN) { 536 join = entry.bool_value; 537 } else if (os_strcmp(entry.key, "authorize_only") == 0 && 538 entry.type == DBUS_TYPE_BOOLEAN) { 539 authorize_only = entry.bool_value; 540 } else if (os_strcmp(entry.key, "frequency") == 0 && 541 entry.type == DBUS_TYPE_INT32) { 542 freq = entry.int32_value; 543 if (freq <= 0) 544 goto inv_args_clear; 545 } else if (os_strcmp(entry.key, "go_intent") == 0 && 546 entry.type == DBUS_TYPE_INT32) { 547 go_intent = entry.int32_value; 548 if ((go_intent < 0) || (go_intent > 15)) 549 goto inv_args_clear; 550 } else if (os_strcmp(entry.key, "wps_method") == 0 && 551 entry.type == DBUS_TYPE_STRING) { 552 if (os_strcmp(entry.str_value, "pbc") == 0) 553 wps_method = WPS_PBC; 554 else if (os_strcmp(entry.str_value, "pin") == 0) 555 wps_method = WPS_PIN_DISPLAY; 556 else if (os_strcmp(entry.str_value, "display") == 0) 557 wps_method = WPS_PIN_DISPLAY; 558 else if (os_strcmp(entry.str_value, "keypad") == 0) 559 wps_method = WPS_PIN_KEYPAD; 560 else 561 goto inv_args_clear; 562 } else if (os_strcmp(entry.key, "pin") == 0 && 563 entry.type == DBUS_TYPE_STRING) { 564 pin = os_strdup(entry.str_value); 565 } else 566 goto inv_args_clear; 567 568 wpa_dbus_dict_entry_clear(&entry); 569 } 570 571 if (wps_method == WPS_NOT_READY || 572 parse_peer_object_path(peer_object_path, addr) < 0 || 573 !p2p_peer_known(wpa_s->global->p2p, addr)) 574 goto inv_args; 575 576 /* 577 * Validate the wps_method specified and the pin value. 578 */ 579 if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD) 580 goto inv_args; 581 582 wpa_s = wpa_s->global->p2p_init_wpa_s; 583 584 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 585 persistent_group, 0, join, authorize_only, 586 go_intent, freq, 0, -1, 0, 0, 0, 0, NULL, 0); 587 588 if (new_pin >= 0) { 589 char npin[9]; 590 char *generated_pin; 591 592 os_snprintf(npin, sizeof(npin), "%08d", new_pin); 593 generated_pin = npin; 594 reply = dbus_message_new_method_return(message); 595 dbus_message_append_args(reply, DBUS_TYPE_STRING, 596 &generated_pin, DBUS_TYPE_INVALID); 597 } else { 598 switch (new_pin) { 599 case -2: 600 err_msg = 601 "connect failed due to channel unavailability."; 602 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE; 603 break; 604 605 case -3: 606 err_msg = "connect failed due to unsupported channel."; 607 iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED; 608 break; 609 610 default: 611 err_msg = "connect failed due to unspecified error."; 612 iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR; 613 break; 614 } 615 616 /* 617 * TODO: 618 * Do we need specialized errors corresponding to above 619 * error conditions as against just returning a different 620 * error message? 621 */ 622 reply = dbus_message_new_error(message, iface, err_msg); 623 } 624 625out: 626 os_free(peer_object_path); 627 os_free(pin); 628 return reply; 629inv_args_clear: 630 wpa_dbus_dict_entry_clear(&entry); 631inv_args: 632 reply = wpas_dbus_error_invalid_args(message, NULL); 633 goto out; 634} 635 636 637/** 638 * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation 639 * @message: Pointer to incoming dbus message 640 * @wpa_s: %wpa_supplicant data structure 641 * Returns: NULL on success or DBus error on failure 642 * 643 * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus 644 * error on P2P cancel failure 645 */ 646DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message, 647 struct wpa_supplicant *wpa_s) 648{ 649 if (wpas_p2p_cancel(wpa_s)) 650 return wpas_dbus_error_unknown_error(message, 651 "P2P cancel failed"); 652 653 return NULL; 654} 655 656 657DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message, 658 struct wpa_supplicant *wpa_s) 659{ 660 DBusMessageIter iter_dict; 661 DBusMessage *reply = NULL; 662 DBusMessageIter iter; 663 struct wpa_dbus_dict_entry entry; 664 char *peer_object_path = NULL; 665 char *pg_object_path = NULL; 666 char *iface = NULL; 667 u8 peer_addr[ETH_ALEN]; 668 unsigned int group_id = 0; 669 int persistent = 0; 670 struct wpa_ssid *ssid; 671 672 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL)) 673 return reply; 674 675 dbus_message_iter_init(message, &iter); 676 677 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 678 goto err; 679 680 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 681 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 682 goto err; 683 684 if (os_strcmp(entry.key, "peer") == 0 && 685 entry.type == DBUS_TYPE_OBJECT_PATH) { 686 peer_object_path = os_strdup(entry.str_value); 687 wpa_dbus_dict_entry_clear(&entry); 688 } else if (os_strcmp(entry.key, "persistent_group_object") == 689 0 && 690 entry.type == DBUS_TYPE_OBJECT_PATH) { 691 pg_object_path = os_strdup(entry.str_value); 692 persistent = 1; 693 wpa_dbus_dict_entry_clear(&entry); 694 } else { 695 wpa_dbus_dict_entry_clear(&entry); 696 goto err; 697 } 698 } 699 700 if (parse_peer_object_path(peer_object_path, peer_addr) < 0 || 701 !p2p_peer_known(wpa_s->global->p2p, peer_addr)) 702 goto err; 703 704 wpa_s = wpa_s->global->p2p_init_wpa_s; 705 706 if (persistent) { 707 char *net_id_str; 708 /* 709 * A group ID is defined meaning we want to re-invoke a 710 * persistent group 711 */ 712 713 iface = wpas_dbus_new_decompose_object_path( 714 pg_object_path, 715 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART, 716 &net_id_str); 717 if (iface == NULL || net_id_str == NULL || 718 !wpa_s->parent->dbus_new_path || 719 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) { 720 reply = wpas_dbus_error_invalid_args(message, 721 pg_object_path); 722 goto out; 723 } 724 725 group_id = strtoul(net_id_str, NULL, 10); 726 if (errno == EINVAL) { 727 reply = wpas_dbus_error_invalid_args( 728 message, pg_object_path); 729 goto out; 730 } 731 732 /* Get the SSID structure from the persistent group id */ 733 ssid = wpa_config_get_network(wpa_s->conf, group_id); 734 if (ssid == NULL || ssid->disabled != 2) 735 goto err; 736 737 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0, 738 0) < 0) { 739 reply = wpas_dbus_error_unknown_error( 740 message, 741 "Failed to reinvoke a persistent group"); 742 goto out; 743 } 744 } else { 745 /* 746 * No group ID means propose to a peer to join my active group 747 */ 748 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname, 749 peer_addr, NULL)) { 750 reply = wpas_dbus_error_unknown_error( 751 message, "Failed to join to an active group"); 752 goto out; 753 } 754 } 755 756out: 757 os_free(iface); 758 os_free(pg_object_path); 759 os_free(peer_object_path); 760 return reply; 761 762err: 763 reply = wpas_dbus_error_invalid_args(message, NULL); 764 goto out; 765} 766 767 768DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message, 769 struct wpa_supplicant *wpa_s) 770{ 771 DBusMessageIter iter; 772 char *peer_object_path = NULL; 773 char *config_method = NULL; 774 u8 peer_addr[ETH_ALEN]; 775 776 dbus_message_iter_init(message, &iter); 777 dbus_message_iter_get_basic(&iter, &peer_object_path); 778 779 if (parse_peer_object_path(peer_object_path, peer_addr) < 0) 780 return wpas_dbus_error_invalid_args(message, NULL); 781 782 dbus_message_iter_next(&iter); 783 dbus_message_iter_get_basic(&iter, &config_method); 784 785 /* 786 * Validation checks on config_method are being duplicated here 787 * to be able to return invalid args reply since the error code 788 * from p2p module are not granular enough (yet). 789 */ 790 if (os_strcmp(config_method, "display") && 791 os_strcmp(config_method, "keypad") && 792 os_strcmp(config_method, "pbc") && 793 os_strcmp(config_method, "pushbutton")) 794 return wpas_dbus_error_invalid_args(message, NULL); 795 796 wpa_s = wpa_s->global->p2p_init_wpa_s; 797 798 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method, 799 WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0) 800 return wpas_dbus_error_unknown_error(message, 801 "Failed to send provision discovery request"); 802 803 return NULL; 804} 805 806 807/* 808 * P2P Device property accessor methods. 809 */ 810 811dbus_bool_t wpas_dbus_getter_p2p_device_config( 812 const struct wpa_dbus_property_desc *property_desc, 813 DBusMessageIter *iter, DBusError *error, void *user_data) 814{ 815 struct wpa_supplicant *wpa_s = user_data; 816 DBusMessageIter variant_iter, dict_iter; 817 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val, 818 iter_secdev_dict_array; 819 const char *dev_name; 820 int num_vendor_extensions = 0; 821 int i; 822 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT]; 823 824 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error)) 825 return FALSE; 826 827 wpa_s = wpa_s->global->p2p_init_wpa_s; 828 829 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 830 "a{sv}", &variant_iter) || 831 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) 832 goto err_no_mem; 833 834 /* DeviceName */ 835 dev_name = wpa_s->conf->device_name; 836 if (dev_name && 837 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name)) 838 goto err_no_mem; 839 840 /* Primary device type */ 841 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType", 842 (char *) wpa_s->conf->device_type, 843 WPS_DEV_TYPE_LEN)) 844 goto err_no_mem; 845 846 /* Secondary device types */ 847 if (wpa_s->conf->num_sec_device_types) { 848 if (!wpa_dbus_dict_begin_array(&dict_iter, 849 "SecondaryDeviceTypes", 850 DBUS_TYPE_ARRAY_AS_STRING 851 DBUS_TYPE_BYTE_AS_STRING, 852 &iter_secdev_dict_entry, 853 &iter_secdev_dict_val, 854 &iter_secdev_dict_array)) 855 goto err_no_mem; 856 857 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++) 858 wpa_dbus_dict_bin_array_add_element( 859 &iter_secdev_dict_array, 860 wpa_s->conf->sec_device_type[i], 861 WPS_DEV_TYPE_LEN); 862 863 if (!wpa_dbus_dict_end_array(&dict_iter, 864 &iter_secdev_dict_entry, 865 &iter_secdev_dict_val, 866 &iter_secdev_dict_array)) 867 goto err_no_mem; 868 } 869 870 /* Vendor Extensions */ 871 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { 872 if (wpa_s->conf->wps_vendor_ext[i] == NULL) 873 continue; 874 vendor_ext[num_vendor_extensions++] = 875 wpa_s->conf->wps_vendor_ext[i]; 876 } 877 878 if ((num_vendor_extensions && 879 !wpa_dbus_dict_append_wpabuf_array(&dict_iter, 880 "VendorExtension", 881 vendor_ext, 882 num_vendor_extensions)) || 883 !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent", 884 wpa_s->conf->p2p_go_intent) || 885 !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect", 886 wpa_s->conf->persistent_reconnect) || 887 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass", 888 wpa_s->conf->p2p_listen_reg_class) || 889 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel", 890 wpa_s->conf->p2p_listen_channel) || 891 !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass", 892 wpa_s->conf->p2p_oper_reg_class) || 893 !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel", 894 wpa_s->conf->p2p_oper_channel) || 895 (wpa_s->conf->p2p_ssid_postfix && 896 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix", 897 wpa_s->conf->p2p_ssid_postfix)) || 898 !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss", 899 wpa_s->conf->p2p_intra_bss) || 900 !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle", 901 wpa_s->conf->p2p_group_idle) || 902 !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack", 903 wpa_s->conf->disassoc_low_ack) || 904 !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface", 905 wpa_s->conf->p2p_no_group_iface) || 906 !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay", 907 wpa_s->conf->p2p_search_delay) || 908 !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || 909 !dbus_message_iter_close_container(iter, &variant_iter)) 910 goto err_no_mem; 911 912 return TRUE; 913 914err_no_mem: 915 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 916 return FALSE; 917} 918 919 920dbus_bool_t wpas_dbus_setter_p2p_device_config( 921 const struct wpa_dbus_property_desc *property_desc, 922 DBusMessageIter *iter, DBusError *error, void *user_data) 923{ 924 struct wpa_supplicant *wpa_s = user_data; 925 DBusMessageIter variant_iter, iter_dict; 926 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING }; 927 unsigned int i; 928 929 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error)) 930 return FALSE; 931 932 wpa_s = wpa_s->global->p2p_init_wpa_s; 933 934 dbus_message_iter_recurse(iter, &variant_iter); 935 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error)) 936 return FALSE; 937 938 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 939 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 940 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 941 "invalid message format"); 942 return FALSE; 943 } 944 945 if (os_strcmp(entry.key, "DeviceName") == 0) { 946 char *devname; 947 948 if (entry.type != DBUS_TYPE_STRING || 949 os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN) 950 goto error; 951 952 devname = os_strdup(entry.str_value); 953 if (devname == NULL) 954 goto err_no_mem_clear; 955 956 os_free(wpa_s->conf->device_name); 957 wpa_s->conf->device_name = devname; 958 959 wpa_s->conf->changed_parameters |= 960 CFG_CHANGED_DEVICE_NAME; 961 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) { 962 if (entry.type != DBUS_TYPE_ARRAY || 963 entry.array_type != DBUS_TYPE_BYTE || 964 entry.array_len != WPS_DEV_TYPE_LEN) 965 goto error; 966 967 os_memcpy(wpa_s->conf->device_type, 968 entry.bytearray_value, 969 WPS_DEV_TYPE_LEN); 970 wpa_s->conf->changed_parameters |= 971 CFG_CHANGED_DEVICE_TYPE; 972 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) { 973 if (entry.type != DBUS_TYPE_ARRAY || 974 entry.array_type != WPAS_DBUS_TYPE_BINARRAY || 975 entry.array_len > MAX_SEC_DEVICE_TYPES) 976 goto error; 977 978 for (i = 0; i < entry.array_len; i++) 979 if (wpabuf_len(entry.binarray_value[i]) != 980 WPS_DEV_TYPE_LEN) 981 goto err_no_mem_clear; 982 for (i = 0; i < entry.array_len; i++) 983 os_memcpy(wpa_s->conf->sec_device_type[i], 984 wpabuf_head(entry.binarray_value[i]), 985 WPS_DEV_TYPE_LEN); 986 wpa_s->conf->num_sec_device_types = entry.array_len; 987 wpa_s->conf->changed_parameters |= 988 CFG_CHANGED_SEC_DEVICE_TYPE; 989 } else if (os_strcmp(entry.key, "VendorExtension") == 0) { 990 if (entry.type != DBUS_TYPE_ARRAY || 991 entry.array_type != WPAS_DBUS_TYPE_BINARRAY || 992 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT)) 993 goto error; 994 995 wpa_s->conf->changed_parameters |= 996 CFG_CHANGED_VENDOR_EXTENSION; 997 998 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { 999 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]); 1000 if (i < entry.array_len) { 1001 wpa_s->conf->wps_vendor_ext[i] = 1002 entry.binarray_value[i]; 1003 entry.binarray_value[i] = NULL; 1004 } else 1005 wpa_s->conf->wps_vendor_ext[i] = NULL; 1006 } 1007 } else if (os_strcmp(entry.key, "GOIntent") == 0 && 1008 entry.type == DBUS_TYPE_UINT32 && 1009 (entry.uint32_value <= 15)) 1010 wpa_s->conf->p2p_go_intent = entry.uint32_value; 1011 else if (os_strcmp(entry.key, "PersistentReconnect") == 0 && 1012 entry.type == DBUS_TYPE_BOOLEAN) 1013 wpa_s->conf->persistent_reconnect = entry.bool_value; 1014 else if (os_strcmp(entry.key, "ListenRegClass") == 0 && 1015 entry.type == DBUS_TYPE_UINT32) { 1016 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value; 1017 wpa_s->conf->changed_parameters |= 1018 CFG_CHANGED_P2P_LISTEN_CHANNEL; 1019 } else if (os_strcmp(entry.key, "ListenChannel") == 0 && 1020 entry.type == DBUS_TYPE_UINT32) { 1021 wpa_s->conf->p2p_listen_channel = entry.uint32_value; 1022 wpa_s->conf->changed_parameters |= 1023 CFG_CHANGED_P2P_LISTEN_CHANNEL; 1024 } else if (os_strcmp(entry.key, "OperRegClass") == 0 && 1025 entry.type == DBUS_TYPE_UINT32) { 1026 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value; 1027 wpa_s->conf->changed_parameters |= 1028 CFG_CHANGED_P2P_OPER_CHANNEL; 1029 } else if (os_strcmp(entry.key, "OperChannel") == 0 && 1030 entry.type == DBUS_TYPE_UINT32) { 1031 wpa_s->conf->p2p_oper_channel = entry.uint32_value; 1032 wpa_s->conf->changed_parameters |= 1033 CFG_CHANGED_P2P_OPER_CHANNEL; 1034 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) { 1035 char *postfix; 1036 1037 if (entry.type != DBUS_TYPE_STRING) 1038 goto error; 1039 1040 postfix = os_strdup(entry.str_value); 1041 if (!postfix) 1042 goto err_no_mem_clear; 1043 1044 os_free(wpa_s->conf->p2p_ssid_postfix); 1045 wpa_s->conf->p2p_ssid_postfix = postfix; 1046 1047 wpa_s->conf->changed_parameters |= 1048 CFG_CHANGED_P2P_SSID_POSTFIX; 1049 } else if (os_strcmp(entry.key, "IntraBss") == 0 && 1050 entry.type == DBUS_TYPE_BOOLEAN) { 1051 wpa_s->conf->p2p_intra_bss = entry.bool_value; 1052 wpa_s->conf->changed_parameters |= 1053 CFG_CHANGED_P2P_INTRA_BSS; 1054 } else if (os_strcmp(entry.key, "GroupIdle") == 0 && 1055 entry.type == DBUS_TYPE_UINT32) 1056 wpa_s->conf->p2p_group_idle = entry.uint32_value; 1057 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 && 1058 entry.type == DBUS_TYPE_UINT32) 1059 wpa_s->conf->disassoc_low_ack = entry.uint32_value; 1060 else if (os_strcmp(entry.key, "NoGroupIface") == 0 && 1061 entry.type == DBUS_TYPE_BOOLEAN) 1062 wpa_s->conf->p2p_no_group_iface = entry.bool_value; 1063 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 && 1064 entry.type == DBUS_TYPE_UINT32) 1065 wpa_s->conf->p2p_search_delay = entry.uint32_value; 1066 else 1067 goto error; 1068 1069 wpa_dbus_dict_entry_clear(&entry); 1070 } 1071 1072 if (wpa_s->conf->changed_parameters) { 1073 /* Some changed parameters requires to update config*/ 1074 wpa_supplicant_update_config(wpa_s); 1075 } 1076 1077 return TRUE; 1078 1079 error: 1080 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 1081 "invalid message format"); 1082 wpa_dbus_dict_entry_clear(&entry); 1083 return FALSE; 1084 1085 err_no_mem_clear: 1086 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1087 wpa_dbus_dict_entry_clear(&entry); 1088 return FALSE; 1089} 1090 1091 1092dbus_bool_t wpas_dbus_getter_p2p_peers( 1093 const struct wpa_dbus_property_desc *property_desc, 1094 DBusMessageIter *iter, DBusError *error, void *user_data) 1095{ 1096 struct wpa_supplicant *wpa_s = user_data; 1097 struct p2p_data *p2p = wpa_s->global->p2p; 1098 int next = 0, i = 0; 1099 int num = 0, out_of_mem = 0; 1100 const u8 *addr; 1101 const struct p2p_peer_info *peer_info = NULL; 1102 dbus_bool_t success = FALSE; 1103 1104 struct dl_list peer_objpath_list; 1105 struct peer_objpath_node { 1106 struct dl_list list; 1107 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 1108 } *node, *tmp; 1109 1110 char **peer_obj_paths = NULL; 1111 1112 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) || 1113 !wpa_s->parent->parent->dbus_new_path) 1114 return FALSE; 1115 1116 dl_list_init(&peer_objpath_list); 1117 1118 /* Get the first peer info */ 1119 peer_info = p2p_get_peer_found(p2p, NULL, next); 1120 1121 /* Get next and accumulate them */ 1122 next = 1; 1123 while (peer_info != NULL) { 1124 node = os_zalloc(sizeof(struct peer_objpath_node)); 1125 if (!node) { 1126 out_of_mem = 1; 1127 goto error; 1128 } 1129 1130 addr = peer_info->p2p_device_addr; 1131 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX, 1132 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART 1133 "/" COMPACT_MACSTR, 1134 wpa_s->parent->parent->dbus_new_path, 1135 MAC2STR(addr)); 1136 dl_list_add_tail(&peer_objpath_list, &node->list); 1137 num++; 1138 1139 peer_info = p2p_get_peer_found(p2p, addr, next); 1140 } 1141 1142 /* 1143 * Now construct the peer object paths in a form suitable for 1144 * array_property_getter helper below. 1145 */ 1146 peer_obj_paths = os_calloc(num, sizeof(char *)); 1147 1148 if (!peer_obj_paths) { 1149 out_of_mem = 1; 1150 goto error; 1151 } 1152 1153 dl_list_for_each_safe(node, tmp, &peer_objpath_list, 1154 struct peer_objpath_node, list) 1155 peer_obj_paths[i++] = node->path; 1156 1157 success = wpas_dbus_simple_array_property_getter(iter, 1158 DBUS_TYPE_OBJECT_PATH, 1159 peer_obj_paths, num, 1160 error); 1161 1162error: 1163 if (peer_obj_paths) 1164 os_free(peer_obj_paths); 1165 1166 dl_list_for_each_safe(node, tmp, &peer_objpath_list, 1167 struct peer_objpath_node, list) { 1168 dl_list_del(&node->list); 1169 os_free(node); 1170 } 1171 if (out_of_mem) 1172 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1173 1174 return success; 1175} 1176 1177 1178enum wpas_p2p_role { 1179 WPAS_P2P_ROLE_DEVICE, 1180 WPAS_P2P_ROLE_GO, 1181 WPAS_P2P_ROLE_CLIENT, 1182}; 1183 1184static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s) 1185{ 1186 struct wpa_ssid *ssid = wpa_s->current_ssid; 1187 1188 if (!ssid) 1189 return WPAS_P2P_ROLE_DEVICE; 1190 if (wpa_s->wpa_state != WPA_COMPLETED) 1191 return WPAS_P2P_ROLE_DEVICE; 1192 1193 switch (ssid->mode) { 1194 case WPAS_MODE_P2P_GO: 1195 case WPAS_MODE_P2P_GROUP_FORMATION: 1196 return WPAS_P2P_ROLE_GO; 1197 case WPAS_MODE_INFRA: 1198 if (ssid->p2p_group) 1199 return WPAS_P2P_ROLE_CLIENT; 1200 return WPAS_P2P_ROLE_DEVICE; 1201 default: 1202 return WPAS_P2P_ROLE_DEVICE; 1203 } 1204} 1205 1206 1207dbus_bool_t wpas_dbus_getter_p2p_role( 1208 const struct wpa_dbus_property_desc *property_desc, 1209 DBusMessageIter *iter, DBusError *error, void *user_data) 1210{ 1211 struct wpa_supplicant *wpa_s = user_data; 1212 char *str; 1213 1214 switch (wpas_get_p2p_role(wpa_s)) { 1215 case WPAS_P2P_ROLE_GO: 1216 str = "GO"; 1217 break; 1218 case WPAS_P2P_ROLE_CLIENT: 1219 str = "client"; 1220 break; 1221 default: 1222 str = "device"; 1223 break; 1224 } 1225 1226 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str, 1227 error); 1228} 1229 1230 1231dbus_bool_t wpas_dbus_getter_p2p_group( 1232 const struct wpa_dbus_property_desc *property_desc, 1233 DBusMessageIter *iter, DBusError *error, void *user_data) 1234{ 1235 struct wpa_supplicant *wpa_s = user_data; 1236 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX]; 1237 char *dbus_groupobj_path = path_buf; 1238 1239 if (wpa_s->dbus_groupobj_path == NULL) 1240 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1241 "/"); 1242 else 1243 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1244 "%s", wpa_s->dbus_groupobj_path); 1245 1246 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 1247 &dbus_groupobj_path, error); 1248} 1249 1250 1251dbus_bool_t wpas_dbus_getter_p2p_peergo( 1252 const struct wpa_dbus_property_desc *property_desc, 1253 DBusMessageIter *iter, DBusError *error, void *user_data) 1254{ 1255 struct wpa_supplicant *wpa_s = user_data; 1256 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1257 1258 if (!wpa_s->parent->parent->dbus_new_path) 1259 return FALSE; 1260 1261 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT) 1262 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 1263 else 1264 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1265 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1266 COMPACT_MACSTR, 1267 wpa_s->parent->parent->dbus_new_path, 1268 MAC2STR(wpa_s->go_dev_addr)); 1269 1270 path = go_peer_obj_path; 1271 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 1272 &path, error); 1273} 1274 1275 1276/* 1277 * Peer object properties accessor methods 1278 */ 1279 1280dbus_bool_t wpas_dbus_getter_p2p_peer_device_name( 1281 const struct wpa_dbus_property_desc *property_desc, 1282 DBusMessageIter *iter, DBusError *error, void *user_data) 1283{ 1284 struct peer_handler_args *peer_args = user_data; 1285 const struct p2p_peer_info *info; 1286 char *tmp; 1287 1288 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1289 return FALSE; 1290 1291 /* get the peer info */ 1292 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1293 peer_args->p2p_device_addr, 0); 1294 if (info == NULL) { 1295 dbus_set_error(error, DBUS_ERROR_FAILED, 1296 "failed to find peer"); 1297 return FALSE; 1298 } 1299 1300 tmp = os_strdup(info->device_name); 1301 if (!tmp) { 1302 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1303 return FALSE; 1304 } 1305 1306 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1307 error)) { 1308 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1309 os_free(tmp); 1310 return FALSE; 1311 } 1312 1313 os_free(tmp); 1314 return TRUE; 1315} 1316 1317 1318dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer( 1319 const struct wpa_dbus_property_desc *property_desc, 1320 DBusMessageIter *iter, DBusError *error, void *user_data) 1321{ 1322 struct peer_handler_args *peer_args = user_data; 1323 const struct p2p_peer_info *info; 1324 char *tmp; 1325 1326 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1327 return FALSE; 1328 1329 /* get the peer info */ 1330 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1331 peer_args->p2p_device_addr, 0); 1332 if (info == NULL) { 1333 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1334 return FALSE; 1335 } 1336 1337 tmp = os_strdup(info->manufacturer); 1338 if (!tmp) { 1339 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1340 return FALSE; 1341 } 1342 1343 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1344 error)) { 1345 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1346 os_free(tmp); 1347 return FALSE; 1348 } 1349 1350 os_free(tmp); 1351 return TRUE; 1352} 1353 1354 1355dbus_bool_t wpas_dbus_getter_p2p_peer_modelname( 1356 const struct wpa_dbus_property_desc *property_desc, 1357 DBusMessageIter *iter, DBusError *error, void *user_data) 1358{ 1359 struct peer_handler_args *peer_args = user_data; 1360 const struct p2p_peer_info *info; 1361 char *tmp; 1362 1363 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1364 return FALSE; 1365 1366 /* get the peer info */ 1367 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1368 peer_args->p2p_device_addr, 0); 1369 if (info == NULL) { 1370 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1371 return FALSE; 1372 } 1373 1374 tmp = os_strdup(info->model_name); 1375 if (!tmp) { 1376 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1377 return FALSE; 1378 } 1379 1380 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1381 error)) { 1382 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1383 os_free(tmp); 1384 return FALSE; 1385 } 1386 1387 os_free(tmp); 1388 return TRUE; 1389} 1390 1391 1392dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber( 1393 const struct wpa_dbus_property_desc *property_desc, 1394 DBusMessageIter *iter, DBusError *error, void *user_data) 1395{ 1396 struct peer_handler_args *peer_args = user_data; 1397 const struct p2p_peer_info *info; 1398 char *tmp; 1399 1400 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1401 return FALSE; 1402 1403 /* get the peer info */ 1404 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1405 peer_args->p2p_device_addr, 0); 1406 if (info == NULL) { 1407 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1408 return FALSE; 1409 } 1410 1411 tmp = os_strdup(info->model_number); 1412 if (!tmp) { 1413 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1414 return FALSE; 1415 } 1416 1417 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1418 error)) { 1419 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1420 os_free(tmp); 1421 return FALSE; 1422 } 1423 1424 os_free(tmp); 1425 return TRUE; 1426} 1427 1428 1429dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber( 1430 const struct wpa_dbus_property_desc *property_desc, 1431 DBusMessageIter *iter, DBusError *error, void *user_data) 1432{ 1433 struct peer_handler_args *peer_args = user_data; 1434 const struct p2p_peer_info *info; 1435 char *tmp; 1436 1437 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1438 return FALSE; 1439 1440 /* get the peer info */ 1441 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1442 peer_args->p2p_device_addr, 0); 1443 if (info == NULL) { 1444 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1445 return FALSE; 1446 } 1447 1448 tmp = os_strdup(info->serial_number); 1449 if (!tmp) { 1450 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1451 return FALSE; 1452 } 1453 1454 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1455 error)) { 1456 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1457 os_free(tmp); 1458 return FALSE; 1459 } 1460 1461 os_free(tmp); 1462 return TRUE; 1463} 1464 1465 1466dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type( 1467 const struct wpa_dbus_property_desc *property_desc, 1468 DBusMessageIter *iter, DBusError *error, void *user_data) 1469{ 1470 struct peer_handler_args *peer_args = user_data; 1471 const struct p2p_peer_info *info; 1472 1473 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1474 peer_args->p2p_device_addr, 0); 1475 if (info == NULL) { 1476 dbus_set_error(error, DBUS_ERROR_FAILED, 1477 "failed to find peer"); 1478 return FALSE; 1479 } 1480 1481 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 1482 (char *) 1483 info->pri_dev_type, 1484 WPS_DEV_TYPE_LEN, error)) { 1485 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1486 return FALSE; 1487 } 1488 1489 return TRUE; 1490} 1491 1492 1493dbus_bool_t wpas_dbus_getter_p2p_peer_config_method( 1494 const struct wpa_dbus_property_desc *property_desc, 1495 DBusMessageIter *iter, DBusError *error, void *user_data) 1496{ 1497 struct peer_handler_args *peer_args = user_data; 1498 const struct p2p_peer_info *info; 1499 1500 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1501 peer_args->p2p_device_addr, 0); 1502 if (info == NULL) { 1503 dbus_set_error(error, DBUS_ERROR_FAILED, 1504 "failed to find peer"); 1505 return FALSE; 1506 } 1507 1508 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 1509 &info->config_methods, error)) { 1510 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1511 return FALSE; 1512 } 1513 1514 return TRUE; 1515} 1516 1517 1518dbus_bool_t wpas_dbus_getter_p2p_peer_level( 1519 const struct wpa_dbus_property_desc *property_desc, 1520 DBusMessageIter *iter, DBusError *error, void *user_data) 1521{ 1522 struct peer_handler_args *peer_args = user_data; 1523 const struct p2p_peer_info *info; 1524 1525 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1526 peer_args->p2p_device_addr, 0); 1527 if (info == NULL) { 1528 dbus_set_error(error, DBUS_ERROR_FAILED, 1529 "failed to find peer"); 1530 return FALSE; 1531 } 1532 1533 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 1534 &info->level, error)) { 1535 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1536 return FALSE; 1537 } 1538 1539 return TRUE; 1540} 1541 1542 1543dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability( 1544 const struct wpa_dbus_property_desc *property_desc, 1545 DBusMessageIter *iter, DBusError *error, void *user_data) 1546{ 1547 struct peer_handler_args *peer_args = user_data; 1548 const struct p2p_peer_info *info; 1549 1550 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1551 peer_args->p2p_device_addr, 0); 1552 if (info == NULL) { 1553 dbus_set_error(error, DBUS_ERROR_FAILED, 1554 "failed to find peer"); 1555 return FALSE; 1556 } 1557 1558 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE, 1559 &info->dev_capab, error)) { 1560 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1561 return FALSE; 1562 } 1563 1564 return TRUE; 1565} 1566 1567 1568dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability( 1569 const struct wpa_dbus_property_desc *property_desc, 1570 DBusMessageIter *iter, DBusError *error, void *user_data) 1571{ 1572 struct peer_handler_args *peer_args = user_data; 1573 const struct p2p_peer_info *info; 1574 1575 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1576 peer_args->p2p_device_addr, 0); 1577 if (info == NULL) { 1578 dbus_set_error(error, DBUS_ERROR_FAILED, 1579 "failed to find peer"); 1580 return FALSE; 1581 } 1582 1583 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE, 1584 &info->group_capab, error)) { 1585 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1586 return FALSE; 1587 } 1588 1589 return TRUE; 1590} 1591 1592 1593dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types( 1594 const struct wpa_dbus_property_desc *property_desc, 1595 DBusMessageIter *iter, DBusError *error, void *user_data) 1596{ 1597 struct peer_handler_args *peer_args = user_data; 1598 const struct p2p_peer_info *info; 1599 DBusMessageIter variant_iter, array_iter; 1600 1601 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1602 peer_args->p2p_device_addr, 0); 1603 if (info == NULL) { 1604 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1605 return FALSE; 1606 } 1607 1608 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 1609 DBUS_TYPE_ARRAY_AS_STRING 1610 DBUS_TYPE_ARRAY_AS_STRING 1611 DBUS_TYPE_BYTE_AS_STRING, 1612 &variant_iter) || 1613 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 1614 DBUS_TYPE_ARRAY_AS_STRING 1615 DBUS_TYPE_BYTE_AS_STRING, 1616 &array_iter)) { 1617 dbus_set_error(error, DBUS_ERROR_FAILED, 1618 "%s: failed to construct message 1", __func__); 1619 return FALSE; 1620 } 1621 1622 if (info->wps_sec_dev_type_list_len) { 1623 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list; 1624 int num_sec_device_types = 1625 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; 1626 int i; 1627 DBusMessageIter inner_array_iter; 1628 1629 for (i = 0; i < num_sec_device_types; i++) { 1630 if (!dbus_message_iter_open_container( 1631 &array_iter, DBUS_TYPE_ARRAY, 1632 DBUS_TYPE_BYTE_AS_STRING, 1633 &inner_array_iter) || 1634 !dbus_message_iter_append_fixed_array( 1635 &inner_array_iter, DBUS_TYPE_BYTE, 1636 &sec_dev_type_list, WPS_DEV_TYPE_LEN) || 1637 !dbus_message_iter_close_container( 1638 &array_iter, &inner_array_iter)) { 1639 dbus_set_error(error, DBUS_ERROR_FAILED, 1640 "%s: failed to construct message 2 (%d)", 1641 __func__, i); 1642 return FALSE; 1643 } 1644 1645 sec_dev_type_list += WPS_DEV_TYPE_LEN; 1646 } 1647 } 1648 1649 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) || 1650 !dbus_message_iter_close_container(iter, &variant_iter)) { 1651 dbus_set_error(error, DBUS_ERROR_FAILED, 1652 "%s: failed to construct message 3", __func__); 1653 return FALSE; 1654 } 1655 1656 return TRUE; 1657} 1658 1659 1660dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension( 1661 const struct wpa_dbus_property_desc *property_desc, 1662 DBusMessageIter *iter, DBusError *error, void *user_data) 1663{ 1664 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT]; 1665 unsigned int i, num = 0; 1666 struct peer_handler_args *peer_args = user_data; 1667 const struct p2p_peer_info *info; 1668 1669 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1670 peer_args->p2p_device_addr, 0); 1671 if (info == NULL) { 1672 dbus_set_error(error, DBUS_ERROR_FAILED, 1673 "failed to find peer"); 1674 return FALSE; 1675 } 1676 1677 /* Add WPS vendor extensions attribute */ 1678 os_memset(vendor_extension, 0, sizeof(vendor_extension)); 1679 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { 1680 if (info->wps_vendor_ext[i] == NULL) 1681 continue; 1682 vendor_extension[num] = info->wps_vendor_ext[i]; 1683 num++; 1684 } 1685 1686 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE, 1687 vendor_extension, 1688 num, error)) 1689 return FALSE; 1690 1691 return TRUE; 1692} 1693 1694 1695dbus_bool_t wpas_dbus_getter_p2p_peer_ies( 1696 const struct wpa_dbus_property_desc *property_desc, 1697 DBusMessageIter *iter, DBusError *error, void *user_data) 1698{ 1699 struct peer_handler_args *peer_args = user_data; 1700 const struct p2p_peer_info *info; 1701 1702 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1703 peer_args->p2p_device_addr, 0); 1704 if (info == NULL) { 1705 dbus_set_error(error, DBUS_ERROR_FAILED, 1706 "failed to find peer"); 1707 return FALSE; 1708 } 1709 1710 if (info->wfd_subelems == NULL) 1711 return wpas_dbus_simple_array_property_getter(iter, 1712 DBUS_TYPE_BYTE, 1713 NULL, 0, error); 1714 1715 return wpas_dbus_simple_array_property_getter( 1716 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf, 1717 info->wfd_subelems->used, error); 1718} 1719 1720 1721dbus_bool_t wpas_dbus_getter_p2p_peer_device_address( 1722 const struct wpa_dbus_property_desc *property_desc, 1723 DBusMessageIter *iter, DBusError *error, void *user_data) 1724{ 1725 struct peer_handler_args *peer_args = user_data; 1726 const struct p2p_peer_info *info; 1727 1728 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1729 peer_args->p2p_device_addr, 0); 1730 if (info == NULL) { 1731 dbus_set_error(error, DBUS_ERROR_FAILED, 1732 "failed to find peer"); 1733 return FALSE; 1734 } 1735 1736 return wpas_dbus_simple_array_property_getter( 1737 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr, 1738 ETH_ALEN, error); 1739} 1740 1741 1742struct peer_group_data { 1743 struct wpa_supplicant *wpa_s; 1744 const struct p2p_peer_info *info; 1745 char **paths; 1746 unsigned int nb_paths; 1747 int error; 1748}; 1749 1750 1751static int match_group_where_peer_is_client(struct p2p_group *group, 1752 void *user_data) 1753{ 1754 struct peer_group_data *data = user_data; 1755 const struct p2p_group_config *cfg; 1756 struct wpa_supplicant *wpa_s_go; 1757 char **paths; 1758 1759 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr)) 1760 return 1; 1761 1762 cfg = p2p_group_get_config(group); 1763 1764 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid, 1765 cfg->ssid_len); 1766 if (wpa_s_go == NULL) 1767 return 1; 1768 1769 paths = os_realloc_array(data->paths, data->nb_paths + 1, 1770 sizeof(char *)); 1771 if (paths == NULL) 1772 goto out_of_memory; 1773 1774 data->paths = paths; 1775 data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path; 1776 data->nb_paths++; 1777 1778 return 1; 1779 1780out_of_memory: 1781 data->error = ENOMEM; 1782 return 0; 1783} 1784 1785 1786dbus_bool_t wpas_dbus_getter_p2p_peer_groups( 1787 const struct wpa_dbus_property_desc *property_desc, 1788 DBusMessageIter *iter, DBusError *error, void *user_data) 1789{ 1790 struct peer_handler_args *peer_args = user_data; 1791 const struct p2p_peer_info *info; 1792 struct peer_group_data data; 1793 struct wpa_supplicant *wpa_s, *wpa_s_go; 1794 dbus_bool_t success = FALSE; 1795 1796 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1797 peer_args->p2p_device_addr, 0); 1798 if (info == NULL) { 1799 dbus_set_error(error, DBUS_ERROR_FAILED, 1800 "failed to find peer"); 1801 return FALSE; 1802 } 1803 1804 os_memset(&data, 0, sizeof(data)); 1805 1806 wpa_s = peer_args->wpa_s; 1807 wpa_s = wpa_s->global->p2p_init_wpa_s; 1808 1809 wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr); 1810 if (wpa_s_go) { 1811 data.paths = os_calloc(1, sizeof(char *)); 1812 if (data.paths == NULL) 1813 goto out_of_memory; 1814 data.paths[0] = wpa_s_go->dbus_groupobj_path; 1815 data.nb_paths = 1; 1816 } 1817 1818 data.wpa_s = peer_args->wpa_s; 1819 data.info = info; 1820 1821 p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p, 1822 match_group_where_peer_is_client, &data); 1823 if (data.error) 1824 goto out_of_memory; 1825 1826 if (data.paths == NULL) { 1827 return wpas_dbus_simple_array_property_getter( 1828 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error); 1829 } 1830 1831 success = wpas_dbus_simple_array_property_getter(iter, 1832 DBUS_TYPE_OBJECT_PATH, 1833 data.paths, 1834 data.nb_paths, error); 1835 goto out; 1836 1837out_of_memory: 1838 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1839out: 1840 os_free(data.paths); 1841 return success; 1842} 1843 1844 1845/** 1846 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects 1847 * @iter: Pointer to incoming dbus message iter 1848 * @error: Location to store error on failure 1849 * @user_data: Function specific data 1850 * Returns: TRUE on success, FALSE on failure 1851 * 1852 * Getter for "PersistentGroups" property. 1853 */ 1854dbus_bool_t wpas_dbus_getter_persistent_groups( 1855 const struct wpa_dbus_property_desc *property_desc, 1856 DBusMessageIter *iter, DBusError *error, void *user_data) 1857{ 1858 struct wpa_supplicant *wpa_s = user_data; 1859 struct wpa_ssid *ssid; 1860 char **paths; 1861 unsigned int i = 0, num = 0; 1862 dbus_bool_t success = FALSE; 1863 1864 wpa_s = wpa_s->global->p2p_init_wpa_s; 1865 if (!wpa_s->parent->dbus_new_path) 1866 return FALSE; 1867 1868 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 1869 if (network_is_persistent_group(ssid)) 1870 num++; 1871 1872 paths = os_calloc(num, sizeof(char *)); 1873 if (!paths) { 1874 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1875 return FALSE; 1876 } 1877 1878 /* Loop through configured networks and append object path of each */ 1879 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 1880 if (!network_is_persistent_group(ssid)) 1881 continue; 1882 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 1883 if (paths[i] == NULL) { 1884 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 1885 "no memory"); 1886 goto out; 1887 } 1888 /* Construct the object path for this network. */ 1889 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 1890 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d", 1891 wpa_s->parent->dbus_new_path, ssid->id); 1892 } 1893 1894 success = wpas_dbus_simple_array_property_getter(iter, 1895 DBUS_TYPE_OBJECT_PATH, 1896 paths, num, error); 1897 1898out: 1899 while (i) 1900 os_free(paths[--i]); 1901 os_free(paths); 1902 return success; 1903} 1904 1905 1906/** 1907 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent 1908 * group 1909 * @iter: Pointer to incoming dbus message iter 1910 * @error: Location to store error on failure 1911 * @user_data: Function specific data 1912 * Returns: TRUE on success, FALSE on failure 1913 * 1914 * Getter for "Properties" property of a persistent group. 1915 */ 1916dbus_bool_t wpas_dbus_getter_persistent_group_properties( 1917 const struct wpa_dbus_property_desc *property_desc, 1918 DBusMessageIter *iter, DBusError *error, void *user_data) 1919{ 1920 struct network_handler_args *net = user_data; 1921 1922 /* Leveraging the fact that persistent group object is still 1923 * represented in same manner as network within. 1924 */ 1925 return wpas_dbus_getter_network_properties(property_desc, iter, error, net); 1926} 1927 1928 1929/** 1930 * wpas_dbus_setter_persistent_group_properties - Set options for a persistent 1931 * group 1932 * @iter: Pointer to incoming dbus message iter 1933 * @error: Location to store error on failure 1934 * @user_data: Function specific data 1935 * Returns: TRUE on success, FALSE on failure 1936 * 1937 * Setter for "Properties" property of a persistent group. 1938 */ 1939dbus_bool_t wpas_dbus_setter_persistent_group_properties( 1940 const struct wpa_dbus_property_desc *property_desc, 1941 DBusMessageIter *iter, DBusError *error, void *user_data) 1942{ 1943 struct network_handler_args *net = user_data; 1944 struct wpa_ssid *ssid = net->ssid; 1945 DBusMessageIter variant_iter; 1946 1947 /* 1948 * Leveraging the fact that persistent group object is still 1949 * represented in same manner as network within. 1950 */ 1951 dbus_message_iter_recurse(iter, &variant_iter); 1952 return set_network_properties(net->wpa_s, ssid, &variant_iter, error); 1953} 1954 1955 1956/** 1957 * wpas_dbus_new_iface_add_persistent_group - Add a new configured 1958 * persistent_group 1959 * @message: Pointer to incoming dbus message 1960 * @wpa_s: wpa_supplicant structure for a network interface 1961 * Returns: A dbus message containing the object path of the new 1962 * persistent group 1963 * 1964 * Handler function for "AddPersistentGroup" method call of a P2P Device 1965 * interface. 1966 */ 1967DBusMessage * wpas_dbus_handler_add_persistent_group( 1968 DBusMessage *message, struct wpa_supplicant *wpa_s) 1969{ 1970 DBusMessage *reply = NULL; 1971 DBusMessageIter iter; 1972 struct wpa_ssid *ssid = NULL; 1973 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 1974 DBusError error; 1975 1976 dbus_message_iter_init(message, &iter); 1977 1978 wpa_s = wpa_s->global->p2p_init_wpa_s; 1979 if (wpa_s->parent->dbus_new_path) 1980 ssid = wpa_config_add_network(wpa_s->conf); 1981 if (ssid == NULL) { 1982 wpa_printf(MSG_ERROR, 1983 "dbus: %s: Cannot add new persistent group", 1984 __func__); 1985 reply = wpas_dbus_error_unknown_error( 1986 message, 1987 "wpa_supplicant could not add a persistent group on this interface."); 1988 goto err; 1989 } 1990 1991 /* Mark the ssid as being a persistent group before the notification */ 1992 ssid->disabled = 2; 1993 ssid->p2p_persistent_group = 1; 1994 wpas_notify_persistent_group_added(wpa_s, ssid); 1995 1996 wpa_config_set_network_defaults(ssid); 1997 1998 dbus_error_init(&error); 1999 if (!set_network_properties(wpa_s, ssid, &iter, &error)) { 2000 wpa_printf(MSG_DEBUG, 2001 "dbus: %s: Control interface could not set persistent group properties", 2002 __func__); 2003 reply = wpas_dbus_reply_new_from_error( 2004 message, &error, DBUS_ERROR_INVALID_ARGS, 2005 "Failed to set network properties"); 2006 dbus_error_free(&error); 2007 goto err; 2008 } 2009 2010 /* Construct the object path for this network. */ 2011 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 2012 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d", 2013 wpa_s->parent->dbus_new_path, ssid->id); 2014 2015 reply = dbus_message_new_method_return(message); 2016 if (reply == NULL) { 2017 reply = wpas_dbus_error_no_memory(message); 2018 goto err; 2019 } 2020 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, 2021 DBUS_TYPE_INVALID)) { 2022 dbus_message_unref(reply); 2023 reply = wpas_dbus_error_no_memory(message); 2024 goto err; 2025 } 2026 2027 return reply; 2028 2029err: 2030 if (ssid) { 2031 wpas_notify_persistent_group_removed(wpa_s, ssid); 2032 wpa_config_remove_network(wpa_s->conf, ssid->id); 2033 } 2034 return reply; 2035} 2036 2037 2038/** 2039 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent 2040 * group 2041 * @message: Pointer to incoming dbus message 2042 * @wpa_s: wpa_supplicant structure for a network interface 2043 * Returns: NULL on success or dbus error on failure 2044 * 2045 * Handler function for "RemovePersistentGroup" method call of a P2P Device 2046 * interface. 2047 */ 2048DBusMessage * wpas_dbus_handler_remove_persistent_group( 2049 DBusMessage *message, struct wpa_supplicant *wpa_s) 2050{ 2051 DBusMessage *reply = NULL; 2052 const char *op; 2053 char *iface = NULL, *persistent_group_id; 2054 int id; 2055 struct wpa_ssid *ssid; 2056 2057 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 2058 DBUS_TYPE_INVALID); 2059 2060 wpa_s = wpa_s->global->p2p_init_wpa_s; 2061 2062 /* 2063 * Extract the network ID and ensure the network is actually a child of 2064 * this interface. 2065 */ 2066 iface = wpas_dbus_new_decompose_object_path( 2067 op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART, 2068 &persistent_group_id); 2069 if (iface == NULL || persistent_group_id == NULL || 2070 !wpa_s->parent->dbus_new_path || 2071 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) { 2072 reply = wpas_dbus_error_invalid_args(message, op); 2073 goto out; 2074 } 2075 2076 id = strtoul(persistent_group_id, NULL, 10); 2077 if (errno == EINVAL) { 2078 reply = wpas_dbus_error_invalid_args(message, op); 2079 goto out; 2080 } 2081 2082 ssid = wpa_config_get_network(wpa_s->conf, id); 2083 if (ssid == NULL) { 2084 reply = wpas_dbus_error_persistent_group_unknown(message); 2085 goto out; 2086 } 2087 2088 wpas_notify_persistent_group_removed(wpa_s, ssid); 2089 2090 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 2091 wpa_printf(MSG_ERROR, 2092 "dbus: %s: error occurred when removing persistent group %d", 2093 __func__, id); 2094 reply = wpas_dbus_error_unknown_error( 2095 message, 2096 "error removing the specified persistent group on this interface."); 2097 goto out; 2098 } 2099 2100out: 2101 os_free(iface); 2102 return reply; 2103} 2104 2105 2106static void remove_persistent_group(struct wpa_supplicant *wpa_s, 2107 struct wpa_ssid *ssid) 2108{ 2109 wpas_notify_persistent_group_removed(wpa_s, ssid); 2110 2111 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) { 2112 wpa_printf(MSG_ERROR, 2113 "dbus: %s: error occurred when removing persistent group %d", 2114 __func__, ssid->id); 2115 return; 2116 } 2117} 2118 2119 2120/** 2121 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured 2122 * persistent groups 2123 * @message: Pointer to incoming dbus message 2124 * @wpa_s: wpa_supplicant structure for a network interface 2125 * Returns: NULL on success or dbus error on failure 2126 * 2127 * Handler function for "RemoveAllPersistentGroups" method call of a 2128 * P2P Device interface. 2129 */ 2130DBusMessage * wpas_dbus_handler_remove_all_persistent_groups( 2131 DBusMessage *message, struct wpa_supplicant *wpa_s) 2132{ 2133 struct wpa_ssid *ssid, *next; 2134 struct wpa_config *config; 2135 2136 wpa_s = wpa_s->global->p2p_init_wpa_s; 2137 2138 config = wpa_s->conf; 2139 ssid = config->ssid; 2140 while (ssid) { 2141 next = ssid->next; 2142 if (network_is_persistent_group(ssid)) 2143 remove_persistent_group(wpa_s, ssid); 2144 ssid = next; 2145 } 2146 return NULL; 2147} 2148 2149 2150/* 2151 * Group object properties accessor methods 2152 */ 2153 2154dbus_bool_t wpas_dbus_getter_p2p_group_members( 2155 const struct wpa_dbus_property_desc *property_desc, 2156 DBusMessageIter *iter, DBusError *error, void *user_data) 2157{ 2158 struct wpa_supplicant *wpa_s = user_data; 2159 struct wpa_ssid *ssid; 2160 unsigned int num_members; 2161 char **paths; 2162 unsigned int i; 2163 void *next = NULL; 2164 const u8 *addr; 2165 dbus_bool_t success = FALSE; 2166 2167 if (!wpa_s->parent->parent->dbus_new_path) 2168 return FALSE; 2169 2170 /* Verify correct role for this property */ 2171 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) { 2172 return wpas_dbus_simple_array_property_getter( 2173 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error); 2174 } 2175 2176 ssid = wpa_s->conf->ssid; 2177 /* At present WPAS P2P_GO mode only applicable for p2p_go */ 2178 if (ssid->mode != WPAS_MODE_P2P_GO && 2179 ssid->mode != WPAS_MODE_AP && 2180 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) 2181 return FALSE; 2182 2183 num_members = p2p_get_group_num_members(wpa_s->p2p_group); 2184 2185 paths = os_calloc(num_members, sizeof(char *)); 2186 if (!paths) 2187 goto out_of_memory; 2188 2189 i = 0; 2190 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) { 2191 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 2192 if (!paths[i]) 2193 goto out_of_memory; 2194 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX, 2195 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART 2196 "/" COMPACT_MACSTR, 2197 wpa_s->parent->parent->dbus_new_path, 2198 MAC2STR(addr)); 2199 i++; 2200 } 2201 2202 success = wpas_dbus_simple_array_property_getter(iter, 2203 DBUS_TYPE_OBJECT_PATH, 2204 paths, num_members, 2205 error); 2206 2207 for (i = 0; i < num_members; i++) 2208 os_free(paths[i]); 2209 os_free(paths); 2210 return success; 2211 2212out_of_memory: 2213 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2214 if (paths) { 2215 for (i = 0; i < num_members; i++) 2216 os_free(paths[i]); 2217 os_free(paths); 2218 } 2219 return FALSE; 2220} 2221 2222 2223dbus_bool_t wpas_dbus_getter_p2p_group_ssid( 2224 const struct wpa_dbus_property_desc *property_desc, 2225 DBusMessageIter *iter, DBusError *error, void *user_data) 2226{ 2227 struct wpa_supplicant *wpa_s = user_data; 2228 2229 if (wpa_s->current_ssid == NULL) 2230 return FALSE; 2231 return wpas_dbus_simple_array_property_getter( 2232 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid, 2233 wpa_s->current_ssid->ssid_len, error); 2234} 2235 2236 2237dbus_bool_t wpas_dbus_getter_p2p_group_bssid( 2238 const struct wpa_dbus_property_desc *property_desc, 2239 DBusMessageIter *iter, DBusError *error, void *user_data) 2240{ 2241 struct wpa_supplicant *wpa_s = user_data; 2242 u8 role = wpas_get_p2p_role(wpa_s); 2243 u8 *p_bssid; 2244 2245 if (role == WPAS_P2P_ROLE_CLIENT) { 2246 if (wpa_s->current_ssid == NULL) 2247 return FALSE; 2248 p_bssid = wpa_s->current_ssid->bssid; 2249 } else { 2250 if (wpa_s->ap_iface == NULL) 2251 return FALSE; 2252 p_bssid = wpa_s->ap_iface->bss[0]->own_addr; 2253 } 2254 2255 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 2256 p_bssid, ETH_ALEN, 2257 error); 2258} 2259 2260 2261dbus_bool_t wpas_dbus_getter_p2p_group_frequency( 2262 const struct wpa_dbus_property_desc *property_desc, 2263 DBusMessageIter *iter, DBusError *error, void *user_data) 2264{ 2265 struct wpa_supplicant *wpa_s = user_data; 2266 u16 op_freq; 2267 u8 role = wpas_get_p2p_role(wpa_s); 2268 2269 if (role == WPAS_P2P_ROLE_CLIENT) { 2270 if (wpa_s->go_params == NULL) 2271 return FALSE; 2272 op_freq = wpa_s->go_params->freq; 2273 } else { 2274 if (wpa_s->ap_iface == NULL) 2275 return FALSE; 2276 op_freq = wpa_s->ap_iface->freq; 2277 } 2278 2279 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 2280 &op_freq, error); 2281} 2282 2283 2284dbus_bool_t wpas_dbus_getter_p2p_group_passphrase( 2285 const struct wpa_dbus_property_desc *property_desc, 2286 DBusMessageIter *iter, DBusError *error, void *user_data) 2287{ 2288 struct wpa_supplicant *wpa_s = user_data; 2289 char *p_pass; 2290 struct wpa_ssid *ssid = wpa_s->current_ssid; 2291 2292 if (ssid == NULL) 2293 return FALSE; 2294 2295 p_pass = ssid->passphrase; 2296 if (!p_pass) 2297 p_pass = ""; 2298 2299 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2300 &p_pass, error); 2301 2302} 2303 2304 2305dbus_bool_t wpas_dbus_getter_p2p_group_psk( 2306 const struct wpa_dbus_property_desc *property_desc, 2307 DBusMessageIter *iter, DBusError *error, void *user_data) 2308{ 2309 struct wpa_supplicant *wpa_s = user_data; 2310 u8 *p_psk = NULL; 2311 u8 psk_len = 0; 2312 struct wpa_ssid *ssid = wpa_s->current_ssid; 2313 2314 if (ssid == NULL) 2315 return FALSE; 2316 2317 if (ssid->psk_set) { 2318 p_psk = ssid->psk; 2319 psk_len = sizeof(ssid->psk); 2320 } 2321 2322 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 2323 p_psk, psk_len, error); 2324} 2325 2326 2327dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext( 2328 const struct wpa_dbus_property_desc *property_desc, 2329 DBusMessageIter *iter, DBusError *error, void *user_data) 2330{ 2331 struct wpa_supplicant *wpa_s = user_data; 2332 struct hostapd_data *hapd; 2333 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; 2334 unsigned int i, num_vendor_ext = 0; 2335 2336 os_memset(vendor_ext, 0, sizeof(vendor_ext)); 2337 2338 /* Verify correct role for this property */ 2339 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) { 2340 if (wpa_s->ap_iface == NULL) 2341 return FALSE; 2342 hapd = wpa_s->ap_iface->bss[0]; 2343 2344 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */ 2345 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { 2346 if (hapd->conf->wps_vendor_ext[i] == NULL) 2347 continue; 2348 vendor_ext[num_vendor_ext++] = 2349 hapd->conf->wps_vendor_ext[i]; 2350 } 2351 } 2352 2353 /* Return vendor extensions or no data */ 2354 return wpas_dbus_simple_array_array_property_getter(iter, 2355 DBUS_TYPE_BYTE, 2356 vendor_ext, 2357 num_vendor_ext, 2358 error); 2359} 2360 2361 2362dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext( 2363 const struct wpa_dbus_property_desc *property_desc, 2364 DBusMessageIter *iter, DBusError *error, void *user_data) 2365{ 2366 struct wpa_supplicant *wpa_s = user_data; 2367 DBusMessageIter variant_iter, iter_dict, array_iter, sub; 2368 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 2369 unsigned int i; 2370 struct hostapd_data *hapd = NULL; 2371 2372 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO && 2373 wpa_s->ap_iface != NULL) 2374 hapd = wpa_s->ap_iface->bss[0]; 2375 else 2376 return FALSE; 2377 2378 dbus_message_iter_recurse(iter, &variant_iter); 2379 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY) 2380 return FALSE; 2381 2382 /* 2383 * This is supposed to be array of bytearrays (aay), but the earlier 2384 * implementation used a dict with "WPSVendorExtensions" as the key in 2385 * this setter function which does not match the format used by the 2386 * getter function. For backwards compatibility, allow both formats to 2387 * be used in the setter. 2388 */ 2389 if (dbus_message_iter_get_element_type(&variant_iter) == 2390 DBUS_TYPE_ARRAY) { 2391 /* This is the proper format matching the getter */ 2392 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS]; 2393 2394 dbus_message_iter_recurse(&variant_iter, &array_iter); 2395 2396 if (dbus_message_iter_get_arg_type(&array_iter) != 2397 DBUS_TYPE_ARRAY || 2398 dbus_message_iter_get_element_type(&array_iter) != 2399 DBUS_TYPE_BYTE) { 2400 wpa_printf(MSG_DEBUG, 2401 "dbus: Not an array of array of bytes"); 2402 return FALSE; 2403 } 2404 2405 i = 0; 2406 os_memset(vals, 0, sizeof(vals)); 2407 2408 while (dbus_message_iter_get_arg_type(&array_iter) == 2409 DBUS_TYPE_ARRAY) { 2410 char *val; 2411 int len; 2412 2413 if (i == MAX_WPS_VENDOR_EXTENSIONS) { 2414 wpa_printf(MSG_DEBUG, 2415 "dbus: Too many WPSVendorExtensions values"); 2416 i = MAX_WPS_VENDOR_EXTENSIONS + 1; 2417 break; 2418 } 2419 2420 dbus_message_iter_recurse(&array_iter, &sub); 2421 dbus_message_iter_get_fixed_array(&sub, &val, &len); 2422 wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]", 2423 val, len); 2424 vals[i] = wpabuf_alloc_copy(val, len); 2425 if (vals[i] == NULL) { 2426 i = MAX_WPS_VENDOR_EXTENSIONS + 1; 2427 break; 2428 } 2429 i++; 2430 dbus_message_iter_next(&array_iter); 2431 } 2432 2433 if (i > MAX_WPS_VENDOR_EXTENSIONS) { 2434 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) 2435 wpabuf_free(vals[i]); 2436 return FALSE; 2437 } 2438 2439 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { 2440 wpabuf_free(hapd->conf->wps_vendor_ext[i]); 2441 hapd->conf->wps_vendor_ext[i] = vals[i]; 2442 } 2443 2444 hostapd_update_wps(hapd); 2445 2446 return TRUE; 2447 } 2448 2449 if (dbus_message_iter_get_element_type(&variant_iter) != 2450 DBUS_TYPE_DICT_ENTRY) 2451 return FALSE; 2452 2453 wpa_printf(MSG_DEBUG, 2454 "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter"); 2455 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error)) 2456 return FALSE; 2457 2458 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2459 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 2460 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 2461 "invalid message format"); 2462 return FALSE; 2463 } 2464 2465 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) { 2466 if (entry.type != DBUS_TYPE_ARRAY || 2467 entry.array_type != WPAS_DBUS_TYPE_BINARRAY || 2468 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS) 2469 goto error; 2470 2471 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { 2472 wpabuf_free(hapd->conf->wps_vendor_ext[i]); 2473 if (i < entry.array_len) { 2474 hapd->conf->wps_vendor_ext[i] = 2475 entry.binarray_value[i]; 2476 entry.binarray_value[i] = NULL; 2477 } else 2478 hapd->conf->wps_vendor_ext[i] = NULL; 2479 } 2480 2481 hostapd_update_wps(hapd); 2482 } else 2483 goto error; 2484 2485 wpa_dbus_dict_entry_clear(&entry); 2486 } 2487 2488 return TRUE; 2489 2490error: 2491 wpa_dbus_dict_entry_clear(&entry); 2492 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 2493 "invalid message format"); 2494 return FALSE; 2495} 2496 2497 2498DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message, 2499 struct wpa_supplicant *wpa_s) 2500{ 2501 DBusMessageIter iter_dict; 2502 DBusMessage *reply = NULL; 2503 DBusMessageIter iter; 2504 struct wpa_dbus_dict_entry entry; 2505 int upnp = 0; 2506 int bonjour = 0; 2507 char *service = NULL; 2508 struct wpabuf *query = NULL; 2509 struct wpabuf *resp = NULL; 2510 u8 version = 0; 2511 2512 dbus_message_iter_init(message, &iter); 2513 2514 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2515 goto error; 2516 2517 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2518 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2519 goto error; 2520 2521 if (os_strcmp(entry.key, "service_type") == 0 && 2522 entry.type == DBUS_TYPE_STRING) { 2523 if (os_strcmp(entry.str_value, "upnp") == 0) 2524 upnp = 1; 2525 else if (os_strcmp(entry.str_value, "bonjour") == 0) 2526 bonjour = 1; 2527 else 2528 goto error_clear; 2529 } else if (os_strcmp(entry.key, "version") == 0 && 2530 entry.type == DBUS_TYPE_INT32) { 2531 version = entry.uint32_value; 2532 } else if (os_strcmp(entry.key, "service") == 0 && 2533 entry.type == DBUS_TYPE_STRING) { 2534 os_free(service); 2535 service = os_strdup(entry.str_value); 2536 } else if (os_strcmp(entry.key, "query") == 0) { 2537 if (entry.type != DBUS_TYPE_ARRAY || 2538 entry.array_type != DBUS_TYPE_BYTE) 2539 goto error_clear; 2540 query = wpabuf_alloc_copy( 2541 entry.bytearray_value, 2542 entry.array_len); 2543 } else if (os_strcmp(entry.key, "response") == 0) { 2544 if (entry.type != DBUS_TYPE_ARRAY || 2545 entry.array_type != DBUS_TYPE_BYTE) 2546 goto error_clear; 2547 resp = wpabuf_alloc_copy(entry.bytearray_value, 2548 entry.array_len); 2549 } 2550 wpa_dbus_dict_entry_clear(&entry); 2551 } 2552 2553 if (upnp == 1) { 2554 if (version <= 0 || service == NULL) 2555 goto error; 2556 2557 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0) 2558 goto error; 2559 2560 } else if (bonjour == 1) { 2561 if (query == NULL || resp == NULL) 2562 goto error; 2563 2564 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) 2565 goto error; 2566 query = NULL; 2567 resp = NULL; 2568 } else 2569 goto error; 2570 2571 os_free(service); 2572 return reply; 2573error_clear: 2574 wpa_dbus_dict_entry_clear(&entry); 2575error: 2576 os_free(service); 2577 wpabuf_free(query); 2578 wpabuf_free(resp); 2579 return wpas_dbus_error_invalid_args(message, NULL); 2580} 2581 2582 2583DBusMessage * wpas_dbus_handler_p2p_delete_service( 2584 DBusMessage *message, struct wpa_supplicant *wpa_s) 2585{ 2586 DBusMessageIter iter_dict; 2587 DBusMessage *reply = NULL; 2588 DBusMessageIter iter; 2589 struct wpa_dbus_dict_entry entry; 2590 int upnp = 0; 2591 int bonjour = 0; 2592 int ret = 0; 2593 char *service = NULL; 2594 struct wpabuf *query = NULL; 2595 u8 version = 0; 2596 2597 dbus_message_iter_init(message, &iter); 2598 2599 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2600 goto error; 2601 2602 if (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2603 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2604 goto error; 2605 2606 if (os_strcmp(entry.key, "service_type") == 0 && 2607 entry.type == DBUS_TYPE_STRING) { 2608 if (os_strcmp(entry.str_value, "upnp") == 0) 2609 upnp = 1; 2610 else if (os_strcmp(entry.str_value, "bonjour") == 0) 2611 bonjour = 1; 2612 else 2613 goto error_clear; 2614 wpa_dbus_dict_entry_clear(&entry); 2615 } 2616 } 2617 if (upnp == 1) { 2618 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2619 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2620 goto error; 2621 if (os_strcmp(entry.key, "version") == 0 && 2622 entry.type == DBUS_TYPE_INT32) 2623 version = entry.uint32_value; 2624 else if (os_strcmp(entry.key, "service") == 0 && 2625 entry.type == DBUS_TYPE_STRING) { 2626 os_free(service); 2627 service = os_strdup(entry.str_value); 2628 } else 2629 goto error_clear; 2630 2631 wpa_dbus_dict_entry_clear(&entry); 2632 } 2633 2634 if (version <= 0 || service == NULL) 2635 goto error; 2636 2637 ret = wpas_p2p_service_del_upnp(wpa_s, version, service); 2638 if (ret != 0) 2639 goto error; 2640 } else if (bonjour == 1) { 2641 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2642 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2643 goto error; 2644 2645 if (os_strcmp(entry.key, "query") == 0) { 2646 if (entry.type != DBUS_TYPE_ARRAY || 2647 entry.array_type != DBUS_TYPE_BYTE) 2648 goto error_clear; 2649 wpabuf_free(query); 2650 query = wpabuf_alloc_copy( 2651 entry.bytearray_value, 2652 entry.array_len); 2653 } else 2654 goto error_clear; 2655 2656 wpa_dbus_dict_entry_clear(&entry); 2657 } 2658 2659 if (query == NULL) 2660 goto error; 2661 2662 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 2663 if (ret != 0) 2664 goto error; 2665 } else 2666 goto error; 2667 2668 wpabuf_free(query); 2669 os_free(service); 2670 return reply; 2671error_clear: 2672 wpa_dbus_dict_entry_clear(&entry); 2673error: 2674 wpabuf_free(query); 2675 os_free(service); 2676 return wpas_dbus_error_invalid_args(message, NULL); 2677} 2678 2679 2680DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message, 2681 struct wpa_supplicant *wpa_s) 2682{ 2683 wpas_p2p_service_flush(wpa_s); 2684 return NULL; 2685} 2686 2687 2688DBusMessage * wpas_dbus_handler_p2p_service_sd_req( 2689 DBusMessage *message, struct wpa_supplicant *wpa_s) 2690{ 2691 DBusMessageIter iter_dict; 2692 DBusMessage *reply = NULL; 2693 DBusMessageIter iter; 2694 struct wpa_dbus_dict_entry entry; 2695 int upnp = 0; 2696 char *service = NULL; 2697 char *peer_object_path = NULL; 2698 struct wpabuf *tlv = NULL; 2699 u8 version = 0; 2700 u64 ref = 0; 2701 u8 addr_buf[ETH_ALEN], *addr; 2702 2703 dbus_message_iter_init(message, &iter); 2704 2705 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2706 goto error; 2707 2708 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2709 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2710 goto error; 2711 if (os_strcmp(entry.key, "peer_object") == 0 && 2712 entry.type == DBUS_TYPE_OBJECT_PATH) { 2713 peer_object_path = os_strdup(entry.str_value); 2714 } else if (os_strcmp(entry.key, "service_type") == 0 && 2715 entry.type == DBUS_TYPE_STRING) { 2716 if (os_strcmp(entry.str_value, "upnp") == 0) 2717 upnp = 1; 2718 else 2719 goto error_clear; 2720 } else if (os_strcmp(entry.key, "version") == 0 && 2721 entry.type == DBUS_TYPE_INT32) { 2722 version = entry.uint32_value; 2723 } else if (os_strcmp(entry.key, "service") == 0 && 2724 entry.type == DBUS_TYPE_STRING) { 2725 service = os_strdup(entry.str_value); 2726 } else if (os_strcmp(entry.key, "tlv") == 0) { 2727 if (entry.type != DBUS_TYPE_ARRAY || 2728 entry.array_type != DBUS_TYPE_BYTE) 2729 goto error_clear; 2730 tlv = wpabuf_alloc_copy(entry.bytearray_value, 2731 entry.array_len); 2732 } else 2733 goto error_clear; 2734 2735 wpa_dbus_dict_entry_clear(&entry); 2736 } 2737 2738 if (!peer_object_path) { 2739 addr = NULL; 2740 } else { 2741 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 || 2742 !p2p_peer_known(wpa_s->global->p2p, addr_buf)) 2743 goto error; 2744 2745 addr = addr_buf; 2746 } 2747 2748 if (upnp == 1) { 2749 if (version <= 0 || service == NULL) 2750 goto error; 2751 2752 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service); 2753 } else { 2754 if (tlv == NULL) 2755 goto error; 2756 ref = wpas_p2p_sd_request(wpa_s, addr, tlv); 2757 wpabuf_free(tlv); 2758 } 2759 2760 if (ref != 0) { 2761 reply = dbus_message_new_method_return(message); 2762 dbus_message_append_args(reply, DBUS_TYPE_UINT64, 2763 &ref, DBUS_TYPE_INVALID); 2764 } else { 2765 reply = wpas_dbus_error_unknown_error( 2766 message, "Unable to send SD request"); 2767 } 2768out: 2769 os_free(service); 2770 os_free(peer_object_path); 2771 return reply; 2772error_clear: 2773 wpa_dbus_dict_entry_clear(&entry); 2774error: 2775 if (tlv) 2776 wpabuf_free(tlv); 2777 reply = wpas_dbus_error_invalid_args(message, NULL); 2778 goto out; 2779} 2780 2781 2782DBusMessage * wpas_dbus_handler_p2p_service_sd_res( 2783 DBusMessage *message, struct wpa_supplicant *wpa_s) 2784{ 2785 DBusMessageIter iter_dict; 2786 DBusMessage *reply = NULL; 2787 DBusMessageIter iter; 2788 struct wpa_dbus_dict_entry entry; 2789 char *peer_object_path = NULL; 2790 struct wpabuf *tlv = NULL; 2791 int freq = 0; 2792 int dlg_tok = 0; 2793 u8 addr[ETH_ALEN]; 2794 2795 dbus_message_iter_init(message, &iter); 2796 2797 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2798 goto error; 2799 2800 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2801 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2802 goto error; 2803 2804 if (os_strcmp(entry.key, "peer_object") == 0 && 2805 entry.type == DBUS_TYPE_OBJECT_PATH) { 2806 peer_object_path = os_strdup(entry.str_value); 2807 } else if (os_strcmp(entry.key, "frequency") == 0 && 2808 entry.type == DBUS_TYPE_INT32) { 2809 freq = entry.uint32_value; 2810 } else if (os_strcmp(entry.key, "dialog_token") == 0 && 2811 (entry.type == DBUS_TYPE_UINT32 || 2812 entry.type == DBUS_TYPE_INT32)) { 2813 dlg_tok = entry.uint32_value; 2814 } else if (os_strcmp(entry.key, "tlvs") == 0) { 2815 if (entry.type != DBUS_TYPE_ARRAY || 2816 entry.array_type != DBUS_TYPE_BYTE) 2817 goto error_clear; 2818 tlv = wpabuf_alloc_copy(entry.bytearray_value, 2819 entry.array_len); 2820 } else 2821 goto error_clear; 2822 2823 wpa_dbus_dict_entry_clear(&entry); 2824 } 2825 if (parse_peer_object_path(peer_object_path, addr) < 0 || 2826 !p2p_peer_known(wpa_s->global->p2p, addr) || 2827 tlv == NULL) 2828 goto error; 2829 2830 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv); 2831 wpabuf_free(tlv); 2832out: 2833 os_free(peer_object_path); 2834 return reply; 2835error_clear: 2836 wpa_dbus_dict_entry_clear(&entry); 2837error: 2838 reply = wpas_dbus_error_invalid_args(message, NULL); 2839 goto out; 2840} 2841 2842 2843DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req( 2844 DBusMessage *message, struct wpa_supplicant *wpa_s) 2845{ 2846 DBusMessageIter iter; 2847 u64 req = 0; 2848 2849 dbus_message_iter_init(message, &iter); 2850 dbus_message_iter_get_basic(&iter, &req); 2851 2852 if (req == 0) 2853 goto error; 2854 2855 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0) 2856 goto error; 2857 2858 return NULL; 2859error: 2860 return wpas_dbus_error_invalid_args(message, NULL); 2861} 2862 2863 2864DBusMessage * wpas_dbus_handler_p2p_service_update( 2865 DBusMessage *message, struct wpa_supplicant *wpa_s) 2866{ 2867 wpas_p2p_sd_service_update(wpa_s); 2868 return NULL; 2869} 2870 2871 2872DBusMessage * wpas_dbus_handler_p2p_serv_disc_external( 2873 DBusMessage *message, struct wpa_supplicant *wpa_s) 2874{ 2875 DBusMessageIter iter; 2876 int ext = 0; 2877 2878 dbus_message_iter_init(message, &iter); 2879 dbus_message_iter_get_basic(&iter, &ext); 2880 2881 wpa_s->p2p_sd_over_ctrl_iface = ext; 2882 2883 return NULL; 2884 2885} 2886 2887 2888#ifdef CONFIG_WIFI_DISPLAY 2889 2890dbus_bool_t wpas_dbus_getter_global_wfd_ies( 2891 const struct wpa_dbus_property_desc *property_desc, 2892 DBusMessageIter *iter, DBusError *error, void *user_data) 2893{ 2894 struct wpa_global *global = user_data; 2895 struct wpabuf *ie; 2896 dbus_bool_t ret; 2897 2898 ie = wifi_display_get_wfd_ie(global); 2899 if (ie == NULL) 2900 return wpas_dbus_simple_array_property_getter(iter, 2901 DBUS_TYPE_BYTE, 2902 NULL, 0, error); 2903 2904 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 2905 wpabuf_head(ie), 2906 wpabuf_len(ie), error); 2907 wpabuf_free(ie); 2908 2909 return ret; 2910} 2911 2912 2913dbus_bool_t wpas_dbus_setter_global_wfd_ies( 2914 const struct wpa_dbus_property_desc *property_desc, 2915 DBusMessageIter *iter, DBusError *error, void *user_data) 2916{ 2917 struct wpa_global *global = user_data; 2918 DBusMessageIter variant, array; 2919 struct wpabuf *ie = NULL; 2920 const u8 *data; 2921 int len; 2922 2923 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) 2924 goto err; 2925 2926 dbus_message_iter_recurse(iter, &variant); 2927 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY) 2928 goto err; 2929 2930 dbus_message_iter_recurse(&variant, &array); 2931 dbus_message_iter_get_fixed_array(&array, &data, &len); 2932 if (len == 0) { 2933 wifi_display_enable(global, 0); 2934 wifi_display_deinit(global); 2935 2936 return TRUE; 2937 } 2938 2939 ie = wpabuf_alloc(len); 2940 if (ie == NULL) 2941 goto err; 2942 2943 wpabuf_put_data(ie, data, len); 2944 if (wifi_display_subelem_set_from_ies(global, ie) != 0) 2945 goto err; 2946 2947 if (global->wifi_display == 0) 2948 wifi_display_enable(global, 1); 2949 2950 wpabuf_free(ie); 2951 2952 return TRUE; 2953err: 2954 wpabuf_free(ie); 2955 2956 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 2957 "invalid message format"); 2958 return FALSE; 2959} 2960 2961#endif /* CONFIG_WIFI_DISPLAY */ 2962