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