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