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