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