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