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