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