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 const char *group_ifname; 748 749 if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL)) 750 return reply; 751 752 dbus_message_iter_init(message, &iter); 753 754 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 755 goto err; 756 757 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 758 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 759 goto err; 760 761 if (os_strcmp(entry.key, "peer") == 0 && 762 entry.type == DBUS_TYPE_OBJECT_PATH) { 763 peer_object_path = os_strdup(entry.str_value); 764 wpa_dbus_dict_entry_clear(&entry); 765 } else if (os_strcmp(entry.key, "persistent_group_object") == 766 0 && 767 entry.type == DBUS_TYPE_OBJECT_PATH) { 768 pg_object_path = os_strdup(entry.str_value); 769 persistent = 1; 770 wpa_dbus_dict_entry_clear(&entry); 771 } else { 772 wpa_dbus_dict_entry_clear(&entry); 773 goto err; 774 } 775 } 776 777 if (parse_peer_object_path(peer_object_path, peer_addr) < 0 || 778 !p2p_peer_known(wpa_s->global->p2p, peer_addr)) 779 goto err; 780 781 /* Capture the interface name for the group first */ 782 group_ifname = wpa_s->ifname; 783 wpa_s = wpa_s->global->p2p_init_wpa_s; 784 785 if (persistent) { 786 char *net_id_str; 787 /* 788 * A group ID is defined meaning we want to re-invoke a 789 * persistent group 790 */ 791 792 iface = wpas_dbus_new_decompose_object_path( 793 pg_object_path, 794 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART, 795 &net_id_str); 796 if (iface == NULL || net_id_str == NULL || 797 !wpa_s->parent->dbus_new_path || 798 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) { 799 reply = wpas_dbus_error_invalid_args(message, 800 pg_object_path); 801 goto out; 802 } 803 804 group_id = strtoul(net_id_str, NULL, 10); 805 if (errno == EINVAL) { 806 reply = wpas_dbus_error_invalid_args( 807 message, pg_object_path); 808 goto out; 809 } 810 811 /* Get the SSID structure from the persistent group id */ 812 ssid = wpa_config_get_network(wpa_s->conf, group_id); 813 if (ssid == NULL || ssid->disabled != 2) 814 goto err; 815 816 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0, 817 0, 0, 0, false) < 0) { 818 reply = wpas_dbus_error_unknown_error( 819 message, 820 "Failed to reinvoke a persistent group"); 821 goto out; 822 } 823 } else { 824 /* 825 * No group ID means propose to a peer to join my active group 826 */ 827 if (wpas_p2p_invite_group(wpa_s, group_ifname, 828 peer_addr, NULL, false)) { 829 reply = wpas_dbus_error_unknown_error( 830 message, "Failed to join to an active group"); 831 goto out; 832 } 833 } 834 835 out: 836 os_free(iface); 837 os_free(pg_object_path); 838 os_free(peer_object_path); 839 return reply; 840 841 err: 842 reply = wpas_dbus_error_invalid_args(message, NULL); 843 goto out; 844 } 845 846 847 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message, 848 struct wpa_supplicant *wpa_s) 849 { 850 DBusMessageIter iter; 851 char *peer_object_path = NULL; 852 char *config_method = NULL; 853 u8 peer_addr[ETH_ALEN]; 854 855 dbus_message_iter_init(message, &iter); 856 dbus_message_iter_get_basic(&iter, &peer_object_path); 857 858 if (parse_peer_object_path(peer_object_path, peer_addr) < 0) 859 return wpas_dbus_error_invalid_args(message, NULL); 860 861 dbus_message_iter_next(&iter); 862 dbus_message_iter_get_basic(&iter, &config_method); 863 864 /* 865 * Validation checks on config_method are being duplicated here 866 * to be able to return invalid args reply since the error code 867 * from p2p module are not granular enough (yet). 868 */ 869 if (os_strcmp(config_method, "display") && 870 os_strcmp(config_method, "keypad") && 871 os_strcmp(config_method, "pbc") && 872 os_strcmp(config_method, "pushbutton")) 873 return wpas_dbus_error_invalid_args(message, NULL); 874 875 wpa_s = wpa_s->global->p2p_init_wpa_s; 876 if (!wpa_s) 877 return wpas_dbus_error_no_p2p_mgmt_iface(message); 878 879 if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method, 880 WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0) 881 return wpas_dbus_error_unknown_error(message, 882 "Failed to send provision discovery request"); 883 884 return NULL; 885 } 886 887 888 /* 889 * P2P Device property accessor methods. 890 */ 891 892 dbus_bool_t wpas_dbus_getter_p2p_device_config( 893 const struct wpa_dbus_property_desc *property_desc, 894 DBusMessageIter *iter, DBusError *error, void *user_data) 895 { 896 struct wpa_supplicant *wpa_s = user_data; 897 DBusMessageIter variant_iter, dict_iter; 898 DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val, 899 iter_secdev_dict_array; 900 const char *dev_name; 901 int num_vendor_extensions = 0; 902 int i; 903 const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT]; 904 905 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error)) 906 return FALSE; 907 908 wpa_s = wpa_s->global->p2p_init_wpa_s; 909 910 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 911 "a{sv}", &variant_iter) || 912 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) 913 goto err_no_mem; 914 915 /* DeviceName */ 916 dev_name = wpa_s->conf->device_name; 917 if (dev_name && 918 !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name)) 919 goto err_no_mem; 920 921 /* Primary device type */ 922 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType", 923 (char *) wpa_s->conf->device_type, 924 WPS_DEV_TYPE_LEN)) 925 goto err_no_mem; 926 927 /* Secondary device types */ 928 if (wpa_s->conf->num_sec_device_types) { 929 if (!wpa_dbus_dict_begin_array(&dict_iter, 930 "SecondaryDeviceTypes", 931 DBUS_TYPE_ARRAY_AS_STRING 932 DBUS_TYPE_BYTE_AS_STRING, 933 &iter_secdev_dict_entry, 934 &iter_secdev_dict_val, 935 &iter_secdev_dict_array)) 936 goto err_no_mem; 937 938 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++) 939 wpa_dbus_dict_bin_array_add_element( 940 &iter_secdev_dict_array, 941 wpa_s->conf->sec_device_type[i], 942 WPS_DEV_TYPE_LEN); 943 944 if (!wpa_dbus_dict_end_array(&dict_iter, 945 &iter_secdev_dict_entry, 946 &iter_secdev_dict_val, 947 &iter_secdev_dict_array)) 948 goto err_no_mem; 949 } 950 951 /* GO IP address */ 952 if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) && 953 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo", 954 (char *) wpa_s->conf->ip_addr_go, 955 4)) 956 goto err_no_mem; 957 958 /* IP address mask */ 959 if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) && 960 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask", 961 (char *) wpa_s->conf->ip_addr_mask, 962 4)) 963 goto err_no_mem; 964 965 /* IP address start */ 966 if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) && 967 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart", 968 (char *) 969 wpa_s->conf->ip_addr_start, 970 4)) 971 goto err_no_mem; 972 973 /* IP address end */ 974 if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) && 975 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd", 976 (char *) wpa_s->conf->ip_addr_end, 977 4)) 978 goto err_no_mem; 979 980 /* Vendor Extensions */ 981 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { 982 if (wpa_s->conf->wps_vendor_ext[i] == NULL) 983 continue; 984 vendor_ext[num_vendor_extensions++] = 985 wpa_s->conf->wps_vendor_ext[i]; 986 } 987 988 if ((num_vendor_extensions && 989 !wpa_dbus_dict_append_wpabuf_array(&dict_iter, 990 "VendorExtension", 991 vendor_ext, 992 num_vendor_extensions)) || 993 !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent", 994 wpa_s->conf->p2p_go_intent) || 995 !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect", 996 wpa_s->conf->persistent_reconnect) || 997 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass", 998 wpa_s->conf->p2p_listen_reg_class) || 999 !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel", 1000 wpa_s->conf->p2p_listen_channel) || 1001 !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass", 1002 wpa_s->conf->p2p_oper_reg_class) || 1003 !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel", 1004 wpa_s->conf->p2p_oper_channel) || 1005 (wpa_s->conf->p2p_ssid_postfix && 1006 !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix", 1007 wpa_s->conf->p2p_ssid_postfix)) || 1008 !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss", 1009 wpa_s->conf->p2p_intra_bss) || 1010 !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle", 1011 wpa_s->conf->p2p_group_idle) || 1012 !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack", 1013 wpa_s->conf->disassoc_low_ack) || 1014 !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface", 1015 wpa_s->conf->p2p_no_group_iface) || 1016 !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay", 1017 wpa_s->conf->p2p_search_delay) || 1018 !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || 1019 !dbus_message_iter_close_container(iter, &variant_iter)) 1020 goto err_no_mem; 1021 1022 return TRUE; 1023 1024 err_no_mem: 1025 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1026 return FALSE; 1027 } 1028 1029 1030 dbus_bool_t wpas_dbus_setter_p2p_device_config( 1031 const struct wpa_dbus_property_desc *property_desc, 1032 DBusMessageIter *iter, DBusError *error, void *user_data) 1033 { 1034 struct wpa_supplicant *wpa_s = user_data; 1035 DBusMessageIter variant_iter, iter_dict; 1036 struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING }; 1037 unsigned int i; 1038 1039 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error)) 1040 return FALSE; 1041 1042 wpa_s = wpa_s->global->p2p_init_wpa_s; 1043 1044 dbus_message_iter_recurse(iter, &variant_iter); 1045 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error)) 1046 return FALSE; 1047 1048 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 1049 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 1050 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 1051 "invalid message format"); 1052 return FALSE; 1053 } 1054 1055 if (os_strcmp(entry.key, "DeviceName") == 0) { 1056 char *devname; 1057 1058 if (entry.type != DBUS_TYPE_STRING || 1059 os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN) 1060 goto error; 1061 1062 devname = os_strdup(entry.str_value); 1063 if (devname == NULL) 1064 goto err_no_mem_clear; 1065 1066 os_free(wpa_s->conf->device_name); 1067 wpa_s->conf->device_name = devname; 1068 1069 wpa_s->conf->changed_parameters |= 1070 CFG_CHANGED_DEVICE_NAME; 1071 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) { 1072 if (entry.type != DBUS_TYPE_ARRAY || 1073 entry.array_type != DBUS_TYPE_BYTE || 1074 entry.array_len != WPS_DEV_TYPE_LEN) 1075 goto error; 1076 1077 os_memcpy(wpa_s->conf->device_type, 1078 entry.bytearray_value, 1079 WPS_DEV_TYPE_LEN); 1080 wpa_s->conf->changed_parameters |= 1081 CFG_CHANGED_DEVICE_TYPE; 1082 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) { 1083 if (entry.type != DBUS_TYPE_ARRAY || 1084 entry.array_type != WPAS_DBUS_TYPE_BINARRAY || 1085 entry.array_len > MAX_SEC_DEVICE_TYPES) 1086 goto error; 1087 1088 for (i = 0; i < entry.array_len; i++) 1089 if (wpabuf_len(entry.binarray_value[i]) != 1090 WPS_DEV_TYPE_LEN) 1091 goto err_no_mem_clear; 1092 for (i = 0; i < entry.array_len; i++) 1093 os_memcpy(wpa_s->conf->sec_device_type[i], 1094 wpabuf_head(entry.binarray_value[i]), 1095 WPS_DEV_TYPE_LEN); 1096 wpa_s->conf->num_sec_device_types = entry.array_len; 1097 wpa_s->conf->changed_parameters |= 1098 CFG_CHANGED_SEC_DEVICE_TYPE; 1099 } else if (os_strcmp(entry.key, "VendorExtension") == 0) { 1100 if (entry.type != DBUS_TYPE_ARRAY || 1101 entry.array_type != WPAS_DBUS_TYPE_BINARRAY || 1102 (entry.array_len > P2P_MAX_WPS_VENDOR_EXT)) 1103 goto error; 1104 1105 wpa_s->conf->changed_parameters |= 1106 CFG_CHANGED_VENDOR_EXTENSION; 1107 1108 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { 1109 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]); 1110 if (i < entry.array_len) { 1111 wpa_s->conf->wps_vendor_ext[i] = 1112 entry.binarray_value[i]; 1113 entry.binarray_value[i] = NULL; 1114 } else 1115 wpa_s->conf->wps_vendor_ext[i] = NULL; 1116 } 1117 } else if (os_strcmp(entry.key, "GOIntent") == 0 && 1118 entry.type == DBUS_TYPE_UINT32 && 1119 (entry.uint32_value <= 15)) 1120 wpa_s->conf->p2p_go_intent = entry.uint32_value; 1121 else if (os_strcmp(entry.key, "PersistentReconnect") == 0 && 1122 entry.type == DBUS_TYPE_BOOLEAN) 1123 wpa_s->conf->persistent_reconnect = entry.bool_value; 1124 else if (os_strcmp(entry.key, "ListenRegClass") == 0 && 1125 entry.type == DBUS_TYPE_UINT32) { 1126 wpa_s->conf->p2p_listen_reg_class = entry.uint32_value; 1127 wpa_s->conf->changed_parameters |= 1128 CFG_CHANGED_P2P_LISTEN_CHANNEL; 1129 } else if (os_strcmp(entry.key, "ListenChannel") == 0 && 1130 entry.type == DBUS_TYPE_UINT32) { 1131 wpa_s->conf->p2p_listen_channel = entry.uint32_value; 1132 wpa_s->conf->changed_parameters |= 1133 CFG_CHANGED_P2P_LISTEN_CHANNEL; 1134 } else if (os_strcmp(entry.key, "OperRegClass") == 0 && 1135 entry.type == DBUS_TYPE_UINT32) { 1136 wpa_s->conf->p2p_oper_reg_class = entry.uint32_value; 1137 wpa_s->conf->changed_parameters |= 1138 CFG_CHANGED_P2P_OPER_CHANNEL; 1139 } else if (os_strcmp(entry.key, "OperChannel") == 0 && 1140 entry.type == DBUS_TYPE_UINT32) { 1141 wpa_s->conf->p2p_oper_channel = entry.uint32_value; 1142 wpa_s->conf->changed_parameters |= 1143 CFG_CHANGED_P2P_OPER_CHANNEL; 1144 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) { 1145 char *postfix; 1146 1147 if (entry.type != DBUS_TYPE_STRING) 1148 goto error; 1149 1150 postfix = os_strdup(entry.str_value); 1151 if (!postfix) 1152 goto err_no_mem_clear; 1153 1154 os_free(wpa_s->conf->p2p_ssid_postfix); 1155 wpa_s->conf->p2p_ssid_postfix = postfix; 1156 1157 wpa_s->conf->changed_parameters |= 1158 CFG_CHANGED_P2P_SSID_POSTFIX; 1159 } else if (os_strcmp(entry.key, "IntraBss") == 0 && 1160 entry.type == DBUS_TYPE_BOOLEAN) { 1161 wpa_s->conf->p2p_intra_bss = entry.bool_value; 1162 wpa_s->conf->changed_parameters |= 1163 CFG_CHANGED_P2P_INTRA_BSS; 1164 } else if (os_strcmp(entry.key, "IpAddrGo") == 0) { 1165 if (!wpas_dbus_validate_dbus_ipaddr(entry)) 1166 goto error; 1167 os_memcpy(wpa_s->conf->ip_addr_go, 1168 entry.bytearray_value, 4); 1169 } else if (os_strcmp(entry.key, "IpAddrMask") == 0) { 1170 if (!wpas_dbus_validate_dbus_ipaddr(entry)) 1171 goto error; 1172 os_memcpy(wpa_s->conf->ip_addr_mask, 1173 entry.bytearray_value, 4); 1174 } else if (os_strcmp(entry.key, "IpAddrStart") == 0) { 1175 if (!wpas_dbus_validate_dbus_ipaddr(entry)) 1176 goto error; 1177 os_memcpy(wpa_s->conf->ip_addr_start, 1178 entry.bytearray_value, 4); 1179 } else if (os_strcmp(entry.key, "IpAddrEnd") == 0) { 1180 if (!wpas_dbus_validate_dbus_ipaddr(entry)) 1181 goto error; 1182 os_memcpy(wpa_s->conf->ip_addr_end, 1183 entry.bytearray_value, 4); 1184 } else if (os_strcmp(entry.key, "GroupIdle") == 0 && 1185 entry.type == DBUS_TYPE_UINT32) 1186 wpa_s->conf->p2p_group_idle = entry.uint32_value; 1187 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 && 1188 entry.type == DBUS_TYPE_UINT32) 1189 wpa_s->conf->disassoc_low_ack = entry.uint32_value; 1190 else if (os_strcmp(entry.key, "NoGroupIface") == 0 && 1191 entry.type == DBUS_TYPE_BOOLEAN) 1192 wpa_s->conf->p2p_no_group_iface = entry.bool_value; 1193 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 && 1194 entry.type == DBUS_TYPE_UINT32) 1195 wpa_s->conf->p2p_search_delay = entry.uint32_value; 1196 else 1197 goto error; 1198 1199 wpa_dbus_dict_entry_clear(&entry); 1200 } 1201 1202 if (wpa_s->conf->changed_parameters) { 1203 /* Some changed parameters requires to update config*/ 1204 wpa_supplicant_update_config(wpa_s); 1205 } 1206 1207 return TRUE; 1208 1209 error: 1210 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 1211 "invalid message format"); 1212 wpa_dbus_dict_entry_clear(&entry); 1213 return FALSE; 1214 1215 err_no_mem_clear: 1216 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1217 wpa_dbus_dict_entry_clear(&entry); 1218 return FALSE; 1219 } 1220 1221 1222 dbus_bool_t wpas_dbus_getter_p2p_peers( 1223 const struct wpa_dbus_property_desc *property_desc, 1224 DBusMessageIter *iter, DBusError *error, void *user_data) 1225 { 1226 struct wpa_supplicant *wpa_s = user_data; 1227 struct p2p_data *p2p = wpa_s->global->p2p; 1228 int next = 0, i = 0; 1229 int num = 0, out_of_mem = 0; 1230 const u8 *addr; 1231 const struct p2p_peer_info *peer_info = NULL; 1232 dbus_bool_t success = FALSE; 1233 1234 struct dl_list peer_objpath_list; 1235 struct peer_objpath_node { 1236 struct dl_list list; 1237 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 1238 } *node, *tmp; 1239 1240 char **peer_obj_paths = NULL; 1241 1242 if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) || 1243 !wpa_s->parent->parent->dbus_new_path) 1244 return FALSE; 1245 1246 dl_list_init(&peer_objpath_list); 1247 1248 /* Get the first peer info */ 1249 peer_info = p2p_get_peer_found(p2p, NULL, next); 1250 1251 /* Get next and accumulate them */ 1252 next = 1; 1253 while (peer_info != NULL) { 1254 node = os_zalloc(sizeof(struct peer_objpath_node)); 1255 if (!node) { 1256 out_of_mem = 1; 1257 goto error; 1258 } 1259 1260 addr = peer_info->p2p_device_addr; 1261 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX, 1262 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART 1263 "/" COMPACT_MACSTR, 1264 wpa_s->parent->parent->dbus_new_path, 1265 MAC2STR(addr)); 1266 dl_list_add_tail(&peer_objpath_list, &node->list); 1267 num++; 1268 1269 peer_info = p2p_get_peer_found(p2p, addr, next); 1270 } 1271 1272 /* 1273 * Now construct the peer object paths in a form suitable for 1274 * array_property_getter helper below. 1275 */ 1276 peer_obj_paths = os_calloc(num, sizeof(char *)); 1277 1278 if (!peer_obj_paths) { 1279 out_of_mem = 1; 1280 goto error; 1281 } 1282 1283 dl_list_for_each_safe(node, tmp, &peer_objpath_list, 1284 struct peer_objpath_node, list) 1285 peer_obj_paths[i++] = node->path; 1286 1287 success = wpas_dbus_simple_array_property_getter(iter, 1288 DBUS_TYPE_OBJECT_PATH, 1289 peer_obj_paths, num, 1290 error); 1291 1292 error: 1293 if (peer_obj_paths) 1294 os_free(peer_obj_paths); 1295 1296 dl_list_for_each_safe(node, tmp, &peer_objpath_list, 1297 struct peer_objpath_node, list) { 1298 dl_list_del(&node->list); 1299 os_free(node); 1300 } 1301 if (out_of_mem) 1302 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1303 1304 return success; 1305 } 1306 1307 1308 enum wpas_p2p_role { 1309 WPAS_P2P_ROLE_DEVICE, 1310 WPAS_P2P_ROLE_GO, 1311 WPAS_P2P_ROLE_CLIENT, 1312 }; 1313 1314 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s) 1315 { 1316 struct wpa_ssid *ssid = wpa_s->current_ssid; 1317 1318 if (!ssid) 1319 return WPAS_P2P_ROLE_DEVICE; 1320 if (wpa_s->wpa_state != WPA_COMPLETED) 1321 return WPAS_P2P_ROLE_DEVICE; 1322 1323 switch (ssid->mode) { 1324 case WPAS_MODE_P2P_GO: 1325 case WPAS_MODE_P2P_GROUP_FORMATION: 1326 return WPAS_P2P_ROLE_GO; 1327 case WPAS_MODE_INFRA: 1328 if (ssid->p2p_group) 1329 return WPAS_P2P_ROLE_CLIENT; 1330 return WPAS_P2P_ROLE_DEVICE; 1331 default: 1332 return WPAS_P2P_ROLE_DEVICE; 1333 } 1334 } 1335 1336 1337 dbus_bool_t wpas_dbus_getter_p2p_role( 1338 const struct wpa_dbus_property_desc *property_desc, 1339 DBusMessageIter *iter, DBusError *error, void *user_data) 1340 { 1341 struct wpa_supplicant *wpa_s = user_data; 1342 char *str; 1343 1344 switch (wpas_get_p2p_role(wpa_s)) { 1345 case WPAS_P2P_ROLE_GO: 1346 str = "GO"; 1347 break; 1348 case WPAS_P2P_ROLE_CLIENT: 1349 str = "client"; 1350 break; 1351 default: 1352 str = "device"; 1353 break; 1354 } 1355 1356 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str, 1357 error); 1358 } 1359 1360 1361 dbus_bool_t wpas_dbus_getter_p2p_group( 1362 const struct wpa_dbus_property_desc *property_desc, 1363 DBusMessageIter *iter, DBusError *error, void *user_data) 1364 { 1365 struct wpa_supplicant *wpa_s = user_data; 1366 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX]; 1367 char *dbus_groupobj_path = path_buf; 1368 1369 if (wpa_s->dbus_groupobj_path == NULL) 1370 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1371 "/"); 1372 else 1373 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1374 "%s", wpa_s->dbus_groupobj_path); 1375 1376 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 1377 &dbus_groupobj_path, error); 1378 } 1379 1380 1381 dbus_bool_t wpas_dbus_getter_p2p_peergo( 1382 const struct wpa_dbus_property_desc *property_desc, 1383 DBusMessageIter *iter, DBusError *error, void *user_data) 1384 { 1385 struct wpa_supplicant *wpa_s = user_data; 1386 char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1387 1388 if (!wpa_s->parent->parent->dbus_new_path) 1389 return FALSE; 1390 1391 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT) 1392 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 1393 else 1394 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1395 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1396 COMPACT_MACSTR, 1397 wpa_s->parent->parent->dbus_new_path, 1398 MAC2STR(wpa_s->go_dev_addr)); 1399 1400 path = go_peer_obj_path; 1401 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 1402 &path, error); 1403 } 1404 1405 1406 /* 1407 * Peer object properties accessor methods 1408 */ 1409 1410 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name( 1411 const struct wpa_dbus_property_desc *property_desc, 1412 DBusMessageIter *iter, DBusError *error, void *user_data) 1413 { 1414 struct peer_handler_args *peer_args = user_data; 1415 const struct p2p_peer_info *info; 1416 char *tmp; 1417 1418 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1419 return FALSE; 1420 1421 /* get the peer info */ 1422 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1423 peer_args->p2p_device_addr, 0); 1424 if (info == NULL) { 1425 dbus_set_error(error, DBUS_ERROR_FAILED, 1426 "failed to find peer"); 1427 return FALSE; 1428 } 1429 1430 tmp = os_strdup(info->device_name); 1431 if (!tmp) { 1432 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1433 return FALSE; 1434 } 1435 1436 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1437 error)) { 1438 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1439 os_free(tmp); 1440 return FALSE; 1441 } 1442 1443 os_free(tmp); 1444 return TRUE; 1445 } 1446 1447 1448 dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer( 1449 const struct wpa_dbus_property_desc *property_desc, 1450 DBusMessageIter *iter, DBusError *error, void *user_data) 1451 { 1452 struct peer_handler_args *peer_args = user_data; 1453 const struct p2p_peer_info *info; 1454 char *tmp; 1455 1456 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1457 return FALSE; 1458 1459 /* get the peer info */ 1460 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1461 peer_args->p2p_device_addr, 0); 1462 if (info == NULL) { 1463 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1464 return FALSE; 1465 } 1466 1467 tmp = os_strdup(info->manufacturer); 1468 if (!tmp) { 1469 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1470 return FALSE; 1471 } 1472 1473 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1474 error)) { 1475 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1476 os_free(tmp); 1477 return FALSE; 1478 } 1479 1480 os_free(tmp); 1481 return TRUE; 1482 } 1483 1484 1485 dbus_bool_t wpas_dbus_getter_p2p_peer_modelname( 1486 const struct wpa_dbus_property_desc *property_desc, 1487 DBusMessageIter *iter, DBusError *error, void *user_data) 1488 { 1489 struct peer_handler_args *peer_args = user_data; 1490 const struct p2p_peer_info *info; 1491 char *tmp; 1492 1493 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1494 return FALSE; 1495 1496 /* get the peer info */ 1497 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1498 peer_args->p2p_device_addr, 0); 1499 if (info == NULL) { 1500 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1501 return FALSE; 1502 } 1503 1504 tmp = os_strdup(info->model_name); 1505 if (!tmp) { 1506 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1507 return FALSE; 1508 } 1509 1510 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1511 error)) { 1512 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1513 os_free(tmp); 1514 return FALSE; 1515 } 1516 1517 os_free(tmp); 1518 return TRUE; 1519 } 1520 1521 1522 dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber( 1523 const struct wpa_dbus_property_desc *property_desc, 1524 DBusMessageIter *iter, DBusError *error, void *user_data) 1525 { 1526 struct peer_handler_args *peer_args = user_data; 1527 const struct p2p_peer_info *info; 1528 char *tmp; 1529 1530 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1531 return FALSE; 1532 1533 /* get the peer info */ 1534 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1535 peer_args->p2p_device_addr, 0); 1536 if (info == NULL) { 1537 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1538 return FALSE; 1539 } 1540 1541 tmp = os_strdup(info->model_number); 1542 if (!tmp) { 1543 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1544 return FALSE; 1545 } 1546 1547 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1548 error)) { 1549 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1550 os_free(tmp); 1551 return FALSE; 1552 } 1553 1554 os_free(tmp); 1555 return TRUE; 1556 } 1557 1558 1559 dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber( 1560 const struct wpa_dbus_property_desc *property_desc, 1561 DBusMessageIter *iter, DBusError *error, void *user_data) 1562 { 1563 struct peer_handler_args *peer_args = user_data; 1564 const struct p2p_peer_info *info; 1565 char *tmp; 1566 1567 if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) 1568 return FALSE; 1569 1570 /* get the peer info */ 1571 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1572 peer_args->p2p_device_addr, 0); 1573 if (info == NULL) { 1574 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1575 return FALSE; 1576 } 1577 1578 tmp = os_strdup(info->serial_number); 1579 if (!tmp) { 1580 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1581 return FALSE; 1582 } 1583 1584 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, 1585 error)) { 1586 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1587 os_free(tmp); 1588 return FALSE; 1589 } 1590 1591 os_free(tmp); 1592 return TRUE; 1593 } 1594 1595 1596 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type( 1597 const struct wpa_dbus_property_desc *property_desc, 1598 DBusMessageIter *iter, DBusError *error, void *user_data) 1599 { 1600 struct peer_handler_args *peer_args = user_data; 1601 const struct p2p_peer_info *info; 1602 1603 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1604 peer_args->p2p_device_addr, 0); 1605 if (info == NULL) { 1606 dbus_set_error(error, DBUS_ERROR_FAILED, 1607 "failed to find peer"); 1608 return FALSE; 1609 } 1610 1611 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 1612 (char *) 1613 info->pri_dev_type, 1614 WPS_DEV_TYPE_LEN, error)) { 1615 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1616 return FALSE; 1617 } 1618 1619 return TRUE; 1620 } 1621 1622 1623 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method( 1624 const struct wpa_dbus_property_desc *property_desc, 1625 DBusMessageIter *iter, DBusError *error, void *user_data) 1626 { 1627 struct peer_handler_args *peer_args = user_data; 1628 const struct p2p_peer_info *info; 1629 1630 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1631 peer_args->p2p_device_addr, 0); 1632 if (info == NULL) { 1633 dbus_set_error(error, DBUS_ERROR_FAILED, 1634 "failed to find peer"); 1635 return FALSE; 1636 } 1637 1638 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 1639 &info->config_methods, error)) { 1640 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1641 return FALSE; 1642 } 1643 1644 return TRUE; 1645 } 1646 1647 1648 dbus_bool_t wpas_dbus_getter_p2p_peer_level( 1649 const struct wpa_dbus_property_desc *property_desc, 1650 DBusMessageIter *iter, DBusError *error, void *user_data) 1651 { 1652 struct peer_handler_args *peer_args = user_data; 1653 const struct p2p_peer_info *info; 1654 1655 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1656 peer_args->p2p_device_addr, 0); 1657 if (info == NULL) { 1658 dbus_set_error(error, DBUS_ERROR_FAILED, 1659 "failed to find peer"); 1660 return FALSE; 1661 } 1662 1663 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 1664 &info->level, error)) { 1665 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1666 return FALSE; 1667 } 1668 1669 return TRUE; 1670 } 1671 1672 1673 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability( 1674 const struct wpa_dbus_property_desc *property_desc, 1675 DBusMessageIter *iter, DBusError *error, void *user_data) 1676 { 1677 struct peer_handler_args *peer_args = user_data; 1678 const struct p2p_peer_info *info; 1679 1680 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1681 peer_args->p2p_device_addr, 0); 1682 if (info == NULL) { 1683 dbus_set_error(error, DBUS_ERROR_FAILED, 1684 "failed to find peer"); 1685 return FALSE; 1686 } 1687 1688 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE, 1689 &info->dev_capab, error)) { 1690 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1691 return FALSE; 1692 } 1693 1694 return TRUE; 1695 } 1696 1697 1698 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability( 1699 const struct wpa_dbus_property_desc *property_desc, 1700 DBusMessageIter *iter, DBusError *error, void *user_data) 1701 { 1702 struct peer_handler_args *peer_args = user_data; 1703 const struct p2p_peer_info *info; 1704 1705 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1706 peer_args->p2p_device_addr, 0); 1707 if (info == NULL) { 1708 dbus_set_error(error, DBUS_ERROR_FAILED, 1709 "failed to find peer"); 1710 return FALSE; 1711 } 1712 1713 if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE, 1714 &info->group_capab, error)) { 1715 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1716 return FALSE; 1717 } 1718 1719 return TRUE; 1720 } 1721 1722 1723 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types( 1724 const struct wpa_dbus_property_desc *property_desc, 1725 DBusMessageIter *iter, DBusError *error, void *user_data) 1726 { 1727 struct peer_handler_args *peer_args = user_data; 1728 const struct p2p_peer_info *info; 1729 DBusMessageIter variant_iter, array_iter; 1730 1731 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1732 peer_args->p2p_device_addr, 0); 1733 if (info == NULL) { 1734 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1735 return FALSE; 1736 } 1737 1738 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 1739 DBUS_TYPE_ARRAY_AS_STRING 1740 DBUS_TYPE_ARRAY_AS_STRING 1741 DBUS_TYPE_BYTE_AS_STRING, 1742 &variant_iter) || 1743 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 1744 DBUS_TYPE_ARRAY_AS_STRING 1745 DBUS_TYPE_BYTE_AS_STRING, 1746 &array_iter)) { 1747 dbus_set_error(error, DBUS_ERROR_FAILED, 1748 "%s: failed to construct message 1", __func__); 1749 return FALSE; 1750 } 1751 1752 if (info->wps_sec_dev_type_list_len) { 1753 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list; 1754 int num_sec_device_types = 1755 info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; 1756 int i; 1757 DBusMessageIter inner_array_iter; 1758 1759 for (i = 0; i < num_sec_device_types; i++) { 1760 if (!dbus_message_iter_open_container( 1761 &array_iter, DBUS_TYPE_ARRAY, 1762 DBUS_TYPE_BYTE_AS_STRING, 1763 &inner_array_iter) || 1764 !dbus_message_iter_append_fixed_array( 1765 &inner_array_iter, DBUS_TYPE_BYTE, 1766 &sec_dev_type_list, WPS_DEV_TYPE_LEN) || 1767 !dbus_message_iter_close_container( 1768 &array_iter, &inner_array_iter)) { 1769 dbus_set_error(error, DBUS_ERROR_FAILED, 1770 "%s: failed to construct message 2 (%d)", 1771 __func__, i); 1772 return FALSE; 1773 } 1774 1775 sec_dev_type_list += WPS_DEV_TYPE_LEN; 1776 } 1777 } 1778 1779 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) || 1780 !dbus_message_iter_close_container(iter, &variant_iter)) { 1781 dbus_set_error(error, DBUS_ERROR_FAILED, 1782 "%s: failed to construct message 3", __func__); 1783 return FALSE; 1784 } 1785 1786 return TRUE; 1787 } 1788 1789 1790 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension( 1791 const struct wpa_dbus_property_desc *property_desc, 1792 DBusMessageIter *iter, DBusError *error, void *user_data) 1793 { 1794 struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT]; 1795 unsigned int i, num = 0; 1796 struct peer_handler_args *peer_args = user_data; 1797 const struct p2p_peer_info *info; 1798 1799 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1800 peer_args->p2p_device_addr, 0); 1801 if (info == NULL) { 1802 dbus_set_error(error, DBUS_ERROR_FAILED, 1803 "failed to find peer"); 1804 return FALSE; 1805 } 1806 1807 /* Add WPS vendor extensions attribute */ 1808 os_memset(vendor_extension, 0, sizeof(vendor_extension)); 1809 for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { 1810 if (info->wps_vendor_ext[i] == NULL) 1811 continue; 1812 vendor_extension[num] = info->wps_vendor_ext[i]; 1813 num++; 1814 } 1815 1816 if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE, 1817 vendor_extension, 1818 num, error)) 1819 return FALSE; 1820 1821 return TRUE; 1822 } 1823 1824 1825 dbus_bool_t wpas_dbus_getter_p2p_peer_ies( 1826 const struct wpa_dbus_property_desc *property_desc, 1827 DBusMessageIter *iter, DBusError *error, void *user_data) 1828 { 1829 struct peer_handler_args *peer_args = user_data; 1830 const struct p2p_peer_info *info; 1831 1832 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1833 peer_args->p2p_device_addr, 0); 1834 if (info == NULL) { 1835 dbus_set_error(error, DBUS_ERROR_FAILED, 1836 "failed to find peer"); 1837 return FALSE; 1838 } 1839 1840 if (info->wfd_subelems == NULL) 1841 return wpas_dbus_simple_array_property_getter(iter, 1842 DBUS_TYPE_BYTE, 1843 NULL, 0, error); 1844 1845 return wpas_dbus_simple_array_property_getter( 1846 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf, 1847 info->wfd_subelems->used, error); 1848 } 1849 1850 1851 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address( 1852 const struct wpa_dbus_property_desc *property_desc, 1853 DBusMessageIter *iter, DBusError *error, void *user_data) 1854 { 1855 struct peer_handler_args *peer_args = user_data; 1856 const struct p2p_peer_info *info; 1857 1858 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1859 peer_args->p2p_device_addr, 0); 1860 if (info == NULL) { 1861 dbus_set_error(error, DBUS_ERROR_FAILED, 1862 "failed to find peer"); 1863 return FALSE; 1864 } 1865 1866 return wpas_dbus_simple_array_property_getter( 1867 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr, 1868 ETH_ALEN, error); 1869 } 1870 1871 1872 struct peer_group_data { 1873 struct wpa_supplicant *wpa_s; 1874 const struct p2p_peer_info *info; 1875 char **paths; 1876 unsigned int nb_paths; 1877 int error; 1878 }; 1879 1880 1881 static int match_group_where_peer_is_client(struct p2p_group *group, 1882 void *user_data) 1883 { 1884 struct peer_group_data *data = user_data; 1885 const struct p2p_group_config *cfg; 1886 struct wpa_supplicant *wpa_s_go; 1887 char **paths; 1888 1889 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr)) 1890 return 1; 1891 1892 cfg = p2p_group_get_config(group); 1893 1894 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid, 1895 cfg->ssid_len); 1896 if (wpa_s_go == NULL) 1897 return 1; 1898 1899 paths = os_realloc_array(data->paths, data->nb_paths + 1, 1900 sizeof(char *)); 1901 if (paths == NULL) 1902 goto out_of_memory; 1903 1904 data->paths = paths; 1905 data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path; 1906 data->nb_paths++; 1907 1908 return 1; 1909 1910 out_of_memory: 1911 data->error = ENOMEM; 1912 return 0; 1913 } 1914 1915 1916 dbus_bool_t wpas_dbus_getter_p2p_peer_groups( 1917 const struct wpa_dbus_property_desc *property_desc, 1918 DBusMessageIter *iter, DBusError *error, void *user_data) 1919 { 1920 struct peer_handler_args *peer_args = user_data; 1921 const struct p2p_peer_info *info; 1922 struct peer_group_data data; 1923 struct wpa_supplicant *wpa_s, *wpa_s_go; 1924 dbus_bool_t success = FALSE; 1925 1926 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1927 peer_args->p2p_device_addr, 0); 1928 if (info == NULL) { 1929 dbus_set_error(error, DBUS_ERROR_FAILED, 1930 "failed to find peer"); 1931 return FALSE; 1932 } 1933 1934 os_memset(&data, 0, sizeof(data)); 1935 1936 wpa_s = peer_args->wpa_s; 1937 wpa_s = wpa_s->global->p2p_init_wpa_s; 1938 if (!wpa_s) 1939 return no_p2p_mgmt_interface(error); 1940 1941 wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr); 1942 if (wpa_s_go) { 1943 data.paths = os_calloc(1, sizeof(char *)); 1944 if (data.paths == NULL) 1945 goto out_of_memory; 1946 data.paths[0] = wpa_s_go->dbus_groupobj_path; 1947 data.nb_paths = 1; 1948 } 1949 1950 data.wpa_s = peer_args->wpa_s; 1951 data.info = info; 1952 1953 p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p, 1954 match_group_where_peer_is_client, &data); 1955 if (data.error) 1956 goto out_of_memory; 1957 1958 if (data.paths == NULL) { 1959 return wpas_dbus_simple_array_property_getter( 1960 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error); 1961 } 1962 1963 success = wpas_dbus_simple_array_property_getter(iter, 1964 DBUS_TYPE_OBJECT_PATH, 1965 data.paths, 1966 data.nb_paths, error); 1967 goto out; 1968 1969 out_of_memory: 1970 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1971 out: 1972 os_free(data.paths); 1973 return success; 1974 } 1975 1976 dbus_bool_t wpas_dbus_getter_p2p_peer_vsie( 1977 const struct wpa_dbus_property_desc *property_desc, 1978 DBusMessageIter *iter, DBusError *error, void *user_data) 1979 { 1980 struct peer_handler_args *peer_args = user_data; 1981 const struct p2p_peer_info *info; 1982 1983 info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, 1984 peer_args->p2p_device_addr, 0); 1985 if (!info) { 1986 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); 1987 return FALSE; 1988 } 1989 1990 if (!info->vendor_elems) 1991 return wpas_dbus_simple_array_property_getter(iter, 1992 DBUS_TYPE_BYTE, 1993 NULL, 0, error); 1994 1995 return wpas_dbus_simple_array_property_getter( 1996 iter, DBUS_TYPE_BYTE, (char *) info->vendor_elems->buf, 1997 info->vendor_elems->used, error); 1998 } 1999 2000 2001 /** 2002 * wpas_dbus_getter_persistent_groups - Get array of persistent group objects 2003 * @iter: Pointer to incoming dbus message iter 2004 * @error: Location to store error on failure 2005 * @user_data: Function specific data 2006 * Returns: TRUE on success, FALSE on failure 2007 * 2008 * Getter for "PersistentGroups" property. 2009 */ 2010 dbus_bool_t wpas_dbus_getter_persistent_groups( 2011 const struct wpa_dbus_property_desc *property_desc, 2012 DBusMessageIter *iter, DBusError *error, void *user_data) 2013 { 2014 struct wpa_supplicant *wpa_s = user_data; 2015 struct wpa_ssid *ssid; 2016 char **paths; 2017 unsigned int i = 0, num = 0; 2018 dbus_bool_t success = FALSE; 2019 2020 wpa_s = wpa_s->global->p2p_init_wpa_s; 2021 if (!wpa_s) 2022 return no_p2p_mgmt_interface(error); 2023 2024 if (!wpa_s->parent->dbus_new_path) 2025 return FALSE; 2026 2027 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 2028 if (network_is_persistent_group(ssid)) 2029 num++; 2030 2031 paths = os_calloc(num, sizeof(char *)); 2032 if (!paths) { 2033 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2034 return FALSE; 2035 } 2036 2037 /* Loop through configured networks and append object path of each */ 2038 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 2039 if (!network_is_persistent_group(ssid)) 2040 continue; 2041 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 2042 if (paths[i] == NULL) { 2043 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 2044 "no memory"); 2045 goto out; 2046 } 2047 /* Construct the object path for this network. */ 2048 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 2049 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d", 2050 wpa_s->parent->dbus_new_path, ssid->id); 2051 } 2052 2053 success = wpas_dbus_simple_array_property_getter(iter, 2054 DBUS_TYPE_OBJECT_PATH, 2055 paths, num, error); 2056 2057 out: 2058 while (i) 2059 os_free(paths[--i]); 2060 os_free(paths); 2061 return success; 2062 } 2063 2064 2065 /** 2066 * wpas_dbus_getter_persistent_group_properties - Get options for a persistent 2067 * group 2068 * @iter: Pointer to incoming dbus message iter 2069 * @error: Location to store error on failure 2070 * @user_data: Function specific data 2071 * Returns: TRUE on success, FALSE on failure 2072 * 2073 * Getter for "Properties" property of a persistent group. 2074 */ 2075 dbus_bool_t wpas_dbus_getter_persistent_group_properties( 2076 const struct wpa_dbus_property_desc *property_desc, 2077 DBusMessageIter *iter, DBusError *error, void *user_data) 2078 { 2079 struct network_handler_args *net = user_data; 2080 2081 /* Leveraging the fact that persistent group object is still 2082 * represented in same manner as network within. 2083 */ 2084 return wpas_dbus_getter_network_properties(property_desc, iter, error, net); 2085 } 2086 2087 2088 /** 2089 * wpas_dbus_setter_persistent_group_properties - Set options for a persistent 2090 * group 2091 * @iter: Pointer to incoming dbus message iter 2092 * @error: Location to store error on failure 2093 * @user_data: Function specific data 2094 * Returns: TRUE on success, FALSE on failure 2095 * 2096 * Setter for "Properties" property of a persistent group. 2097 */ 2098 dbus_bool_t wpas_dbus_setter_persistent_group_properties( 2099 const struct wpa_dbus_property_desc *property_desc, 2100 DBusMessageIter *iter, DBusError *error, void *user_data) 2101 { 2102 struct network_handler_args *net = user_data; 2103 struct wpa_ssid *ssid = net->ssid; 2104 DBusMessageIter variant_iter; 2105 2106 /* 2107 * Leveraging the fact that persistent group object is still 2108 * represented in same manner as network within. 2109 */ 2110 dbus_message_iter_recurse(iter, &variant_iter); 2111 return set_network_properties(net->wpa_s, ssid, &variant_iter, error); 2112 } 2113 2114 2115 /** 2116 * wpas_dbus_new_iface_add_persistent_group - Add a new configured 2117 * persistent_group 2118 * @message: Pointer to incoming dbus message 2119 * @wpa_s: wpa_supplicant structure for a network interface 2120 * Returns: A dbus message containing the object path of the new 2121 * persistent group 2122 * 2123 * Handler function for "AddPersistentGroup" method call of a P2P Device 2124 * interface. 2125 */ 2126 DBusMessage * wpas_dbus_handler_add_persistent_group( 2127 DBusMessage *message, struct wpa_supplicant *wpa_s) 2128 { 2129 DBusMessage *reply = NULL; 2130 DBusMessageIter iter; 2131 struct wpa_ssid *ssid = NULL; 2132 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 2133 DBusError error; 2134 2135 dbus_message_iter_init(message, &iter); 2136 2137 wpa_s = wpa_s->global->p2p_init_wpa_s; 2138 if (!wpa_s) { 2139 reply = wpas_dbus_error_no_p2p_mgmt_iface(message); 2140 goto err; 2141 } 2142 2143 if (wpa_s->parent->dbus_new_path) 2144 ssid = wpa_config_add_network(wpa_s->conf); 2145 if (ssid == NULL) { 2146 wpa_printf(MSG_ERROR, 2147 "dbus: %s: Cannot add new persistent group", 2148 __func__); 2149 reply = wpas_dbus_error_unknown_error( 2150 message, 2151 "wpa_supplicant could not add a persistent group on this interface."); 2152 goto err; 2153 } 2154 2155 /* Mark the ssid as being a persistent group before the notification */ 2156 ssid->disabled = 2; 2157 ssid->p2p_persistent_group = 1; 2158 wpas_notify_persistent_group_added(wpa_s, ssid); 2159 2160 wpa_config_set_network_defaults(ssid); 2161 2162 dbus_error_init(&error); 2163 if (!set_network_properties(wpa_s, ssid, &iter, &error)) { 2164 wpa_printf(MSG_DEBUG, 2165 "dbus: %s: Control interface could not set persistent group properties", 2166 __func__); 2167 reply = wpas_dbus_reply_new_from_error( 2168 message, &error, DBUS_ERROR_INVALID_ARGS, 2169 "Failed to set network properties"); 2170 dbus_error_free(&error); 2171 goto err; 2172 } 2173 2174 /* Construct the object path for this network. */ 2175 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 2176 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d", 2177 wpa_s->parent->dbus_new_path, ssid->id); 2178 2179 reply = dbus_message_new_method_return(message); 2180 if (reply == NULL) { 2181 reply = wpas_dbus_error_no_memory(message); 2182 goto err; 2183 } 2184 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, 2185 DBUS_TYPE_INVALID)) { 2186 dbus_message_unref(reply); 2187 reply = wpas_dbus_error_no_memory(message); 2188 goto err; 2189 } 2190 2191 return reply; 2192 2193 err: 2194 if (ssid) { 2195 wpas_notify_persistent_group_removed(wpa_s, ssid); 2196 wpa_config_remove_network(wpa_s->conf, ssid->id); 2197 } 2198 return reply; 2199 } 2200 2201 2202 /** 2203 * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent 2204 * group 2205 * @message: Pointer to incoming dbus message 2206 * @wpa_s: wpa_supplicant structure for a network interface 2207 * Returns: NULL on success or dbus error on failure 2208 * 2209 * Handler function for "RemovePersistentGroup" method call of a P2P Device 2210 * interface. 2211 */ 2212 DBusMessage * wpas_dbus_handler_remove_persistent_group( 2213 DBusMessage *message, struct wpa_supplicant *wpa_s) 2214 { 2215 DBusMessage *reply = NULL; 2216 const char *op; 2217 char *iface = NULL, *persistent_group_id; 2218 int id; 2219 struct wpa_ssid *ssid; 2220 2221 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 2222 DBUS_TYPE_INVALID); 2223 2224 wpa_s = wpa_s->global->p2p_init_wpa_s; 2225 if (!wpa_s) { 2226 reply = wpas_dbus_error_no_p2p_mgmt_iface(message); 2227 goto out; 2228 } 2229 2230 /* 2231 * Extract the network ID and ensure the network is actually a child of 2232 * this interface. 2233 */ 2234 iface = wpas_dbus_new_decompose_object_path( 2235 op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART, 2236 &persistent_group_id); 2237 if (iface == NULL || persistent_group_id == NULL || 2238 !wpa_s->parent->dbus_new_path || 2239 os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) { 2240 reply = wpas_dbus_error_invalid_args(message, op); 2241 goto out; 2242 } 2243 2244 id = strtoul(persistent_group_id, NULL, 10); 2245 if (errno == EINVAL) { 2246 reply = wpas_dbus_error_invalid_args(message, op); 2247 goto out; 2248 } 2249 2250 ssid = wpa_config_get_network(wpa_s->conf, id); 2251 if (ssid == NULL) { 2252 reply = wpas_dbus_error_persistent_group_unknown(message); 2253 goto out; 2254 } 2255 2256 wpas_notify_persistent_group_removed(wpa_s, ssid); 2257 2258 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 2259 wpa_printf(MSG_ERROR, 2260 "dbus: %s: error occurred when removing persistent group %d", 2261 __func__, id); 2262 reply = wpas_dbus_error_unknown_error( 2263 message, 2264 "error removing the specified persistent group on this interface."); 2265 goto out; 2266 } 2267 2268 out: 2269 os_free(iface); 2270 return reply; 2271 } 2272 2273 2274 static void remove_persistent_group(struct wpa_supplicant *wpa_s, 2275 struct wpa_ssid *ssid) 2276 { 2277 wpas_notify_persistent_group_removed(wpa_s, ssid); 2278 2279 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) { 2280 wpa_printf(MSG_ERROR, 2281 "dbus: %s: error occurred when removing persistent group %d", 2282 __func__, ssid->id); 2283 return; 2284 } 2285 } 2286 2287 2288 /** 2289 * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured 2290 * persistent groups 2291 * @message: Pointer to incoming dbus message 2292 * @wpa_s: wpa_supplicant structure for a network interface 2293 * Returns: NULL on success or dbus error on failure 2294 * 2295 * Handler function for "RemoveAllPersistentGroups" method call of a 2296 * P2P Device interface. 2297 */ 2298 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups( 2299 DBusMessage *message, struct wpa_supplicant *wpa_s) 2300 { 2301 struct wpa_ssid *ssid, *next; 2302 struct wpa_config *config; 2303 2304 wpa_s = wpa_s->global->p2p_init_wpa_s; 2305 if (!wpa_s) 2306 return wpas_dbus_error_no_p2p_mgmt_iface(message); 2307 2308 config = wpa_s->conf; 2309 ssid = config->ssid; 2310 while (ssid) { 2311 next = ssid->next; 2312 if (network_is_persistent_group(ssid)) 2313 remove_persistent_group(wpa_s, ssid); 2314 ssid = next; 2315 } 2316 return NULL; 2317 } 2318 2319 2320 /* 2321 * Group object properties accessor methods 2322 */ 2323 2324 dbus_bool_t wpas_dbus_getter_p2p_group_members( 2325 const struct wpa_dbus_property_desc *property_desc, 2326 DBusMessageIter *iter, DBusError *error, void *user_data) 2327 { 2328 struct wpa_supplicant *wpa_s = user_data; 2329 struct wpa_ssid *ssid; 2330 unsigned int num_members; 2331 char **paths; 2332 unsigned int i; 2333 void *next = NULL; 2334 const u8 *addr; 2335 dbus_bool_t success = FALSE; 2336 2337 if (!wpa_s->parent->parent->dbus_new_path) 2338 return FALSE; 2339 2340 /* Verify correct role for this property */ 2341 if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) { 2342 return wpas_dbus_simple_array_property_getter( 2343 iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error); 2344 } 2345 2346 ssid = wpa_s->conf->ssid; 2347 /* At present WPAS P2P_GO mode only applicable for p2p_go */ 2348 if (ssid->mode != WPAS_MODE_P2P_GO && 2349 ssid->mode != WPAS_MODE_AP && 2350 ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) 2351 return FALSE; 2352 2353 num_members = p2p_get_group_num_members(wpa_s->p2p_group); 2354 2355 paths = os_calloc(num_members, sizeof(char *)); 2356 if (!paths) 2357 goto out_of_memory; 2358 2359 i = 0; 2360 while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) { 2361 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 2362 if (!paths[i]) 2363 goto out_of_memory; 2364 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX, 2365 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART 2366 "/" COMPACT_MACSTR, 2367 wpa_s->parent->parent->dbus_new_path, 2368 MAC2STR(addr)); 2369 i++; 2370 } 2371 2372 success = wpas_dbus_simple_array_property_getter(iter, 2373 DBUS_TYPE_OBJECT_PATH, 2374 paths, num_members, 2375 error); 2376 2377 for (i = 0; i < num_members; i++) 2378 os_free(paths[i]); 2379 os_free(paths); 2380 return success; 2381 2382 out_of_memory: 2383 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2384 if (paths) { 2385 for (i = 0; i < num_members; i++) 2386 os_free(paths[i]); 2387 os_free(paths); 2388 } 2389 return FALSE; 2390 } 2391 2392 2393 dbus_bool_t wpas_dbus_getter_p2p_group_ssid( 2394 const struct wpa_dbus_property_desc *property_desc, 2395 DBusMessageIter *iter, DBusError *error, void *user_data) 2396 { 2397 struct wpa_supplicant *wpa_s = user_data; 2398 2399 if (wpa_s->current_ssid == NULL) 2400 return FALSE; 2401 return wpas_dbus_simple_array_property_getter( 2402 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid, 2403 wpa_s->current_ssid->ssid_len, error); 2404 } 2405 2406 2407 dbus_bool_t wpas_dbus_getter_p2p_group_bssid( 2408 const struct wpa_dbus_property_desc *property_desc, 2409 DBusMessageIter *iter, DBusError *error, void *user_data) 2410 { 2411 struct wpa_supplicant *wpa_s = user_data; 2412 u8 role = wpas_get_p2p_role(wpa_s); 2413 u8 *p_bssid; 2414 2415 if (role == WPAS_P2P_ROLE_CLIENT) { 2416 if (wpa_s->current_ssid == NULL) 2417 return FALSE; 2418 p_bssid = wpa_s->current_ssid->bssid; 2419 } else { 2420 if (wpa_s->ap_iface == NULL) 2421 return FALSE; 2422 p_bssid = wpa_s->ap_iface->bss[0]->own_addr; 2423 } 2424 2425 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 2426 p_bssid, ETH_ALEN, 2427 error); 2428 } 2429 2430 2431 dbus_bool_t wpas_dbus_getter_p2p_group_frequency( 2432 const struct wpa_dbus_property_desc *property_desc, 2433 DBusMessageIter *iter, DBusError *error, void *user_data) 2434 { 2435 struct wpa_supplicant *wpa_s = user_data; 2436 u16 op_freq; 2437 u8 role = wpas_get_p2p_role(wpa_s); 2438 2439 if (role == WPAS_P2P_ROLE_CLIENT) { 2440 if (wpa_s->go_params == NULL) 2441 return FALSE; 2442 op_freq = wpa_s->go_params->freq; 2443 } else { 2444 if (wpa_s->ap_iface == NULL) 2445 return FALSE; 2446 op_freq = wpa_s->ap_iface->freq; 2447 } 2448 2449 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 2450 &op_freq, error); 2451 } 2452 2453 2454 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase( 2455 const struct wpa_dbus_property_desc *property_desc, 2456 DBusMessageIter *iter, DBusError *error, void *user_data) 2457 { 2458 struct wpa_supplicant *wpa_s = user_data; 2459 struct wpa_ssid *ssid = wpa_s->current_ssid; 2460 2461 if (ssid == NULL) 2462 return FALSE; 2463 2464 return wpas_dbus_string_property_getter(iter, ssid->passphrase, error); 2465 } 2466 2467 2468 dbus_bool_t wpas_dbus_getter_p2p_group_psk( 2469 const struct wpa_dbus_property_desc *property_desc, 2470 DBusMessageIter *iter, DBusError *error, void *user_data) 2471 { 2472 struct wpa_supplicant *wpa_s = user_data; 2473 u8 *p_psk = NULL; 2474 u8 psk_len = 0; 2475 struct wpa_ssid *ssid = wpa_s->current_ssid; 2476 2477 if (ssid == NULL) 2478 return FALSE; 2479 2480 if (ssid->psk_set) { 2481 p_psk = ssid->psk; 2482 psk_len = sizeof(ssid->psk); 2483 } 2484 2485 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 2486 p_psk, psk_len, error); 2487 } 2488 2489 2490 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext( 2491 const struct wpa_dbus_property_desc *property_desc, 2492 DBusMessageIter *iter, DBusError *error, void *user_data) 2493 { 2494 struct wpa_supplicant *wpa_s = user_data; 2495 struct hostapd_data *hapd; 2496 struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; 2497 unsigned int i, num_vendor_ext = 0; 2498 2499 os_memset(vendor_ext, 0, sizeof(vendor_ext)); 2500 2501 /* Verify correct role for this property */ 2502 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) { 2503 if (wpa_s->ap_iface == NULL) 2504 return FALSE; 2505 hapd = wpa_s->ap_iface->bss[0]; 2506 2507 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */ 2508 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { 2509 if (hapd->conf->wps_vendor_ext[i] == NULL) 2510 continue; 2511 vendor_ext[num_vendor_ext++] = 2512 hapd->conf->wps_vendor_ext[i]; 2513 } 2514 } 2515 2516 /* Return vendor extensions or no data */ 2517 return wpas_dbus_simple_array_array_property_getter(iter, 2518 DBUS_TYPE_BYTE, 2519 vendor_ext, 2520 num_vendor_ext, 2521 error); 2522 } 2523 2524 2525 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext( 2526 const struct wpa_dbus_property_desc *property_desc, 2527 DBusMessageIter *iter, DBusError *error, void *user_data) 2528 { 2529 struct wpa_supplicant *wpa_s = user_data; 2530 DBusMessageIter variant_iter, iter_dict, array_iter, sub; 2531 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 2532 unsigned int i; 2533 struct hostapd_data *hapd = NULL; 2534 2535 if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO && 2536 wpa_s->ap_iface != NULL) 2537 hapd = wpa_s->ap_iface->bss[0]; 2538 else 2539 return FALSE; 2540 2541 dbus_message_iter_recurse(iter, &variant_iter); 2542 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY) 2543 return FALSE; 2544 2545 /* 2546 * This is supposed to be array of bytearrays (aay), but the earlier 2547 * implementation used a dict with "WPSVendorExtensions" as the key in 2548 * this setter function which does not match the format used by the 2549 * getter function. For backwards compatibility, allow both formats to 2550 * be used in the setter. 2551 */ 2552 if (dbus_message_iter_get_element_type(&variant_iter) == 2553 DBUS_TYPE_ARRAY) { 2554 /* This is the proper format matching the getter */ 2555 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS]; 2556 2557 dbus_message_iter_recurse(&variant_iter, &array_iter); 2558 2559 if (dbus_message_iter_get_arg_type(&array_iter) != 2560 DBUS_TYPE_ARRAY || 2561 dbus_message_iter_get_element_type(&array_iter) != 2562 DBUS_TYPE_BYTE) { 2563 wpa_printf(MSG_DEBUG, 2564 "dbus: Not an array of array of bytes"); 2565 return FALSE; 2566 } 2567 2568 i = 0; 2569 os_memset(vals, 0, sizeof(vals)); 2570 2571 while (dbus_message_iter_get_arg_type(&array_iter) == 2572 DBUS_TYPE_ARRAY) { 2573 char *val; 2574 int len; 2575 2576 if (i == MAX_WPS_VENDOR_EXTENSIONS) { 2577 wpa_printf(MSG_DEBUG, 2578 "dbus: Too many WPSVendorExtensions values"); 2579 i = MAX_WPS_VENDOR_EXTENSIONS + 1; 2580 break; 2581 } 2582 2583 dbus_message_iter_recurse(&array_iter, &sub); 2584 dbus_message_iter_get_fixed_array(&sub, &val, &len); 2585 wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]", 2586 val, len); 2587 vals[i] = wpabuf_alloc_copy(val, len); 2588 if (vals[i] == NULL) { 2589 i = MAX_WPS_VENDOR_EXTENSIONS + 1; 2590 break; 2591 } 2592 i++; 2593 dbus_message_iter_next(&array_iter); 2594 } 2595 2596 if (i > MAX_WPS_VENDOR_EXTENSIONS) { 2597 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) 2598 wpabuf_free(vals[i]); 2599 return FALSE; 2600 } 2601 2602 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { 2603 wpabuf_free(hapd->conf->wps_vendor_ext[i]); 2604 hapd->conf->wps_vendor_ext[i] = vals[i]; 2605 } 2606 2607 hostapd_update_wps(hapd); 2608 2609 return TRUE; 2610 } 2611 2612 if (dbus_message_iter_get_element_type(&variant_iter) != 2613 DBUS_TYPE_DICT_ENTRY) 2614 return FALSE; 2615 2616 wpa_printf(MSG_DEBUG, 2617 "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter"); 2618 if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error)) 2619 return FALSE; 2620 2621 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2622 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 2623 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 2624 "invalid message format"); 2625 return FALSE; 2626 } 2627 2628 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) { 2629 if (entry.type != DBUS_TYPE_ARRAY || 2630 entry.array_type != WPAS_DBUS_TYPE_BINARRAY || 2631 entry.array_len > MAX_WPS_VENDOR_EXTENSIONS) 2632 goto error; 2633 2634 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { 2635 wpabuf_free(hapd->conf->wps_vendor_ext[i]); 2636 if (i < entry.array_len) { 2637 hapd->conf->wps_vendor_ext[i] = 2638 entry.binarray_value[i]; 2639 entry.binarray_value[i] = NULL; 2640 } else 2641 hapd->conf->wps_vendor_ext[i] = NULL; 2642 } 2643 2644 hostapd_update_wps(hapd); 2645 } else 2646 goto error; 2647 2648 wpa_dbus_dict_entry_clear(&entry); 2649 } 2650 2651 return TRUE; 2652 2653 error: 2654 wpa_dbus_dict_entry_clear(&entry); 2655 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 2656 "invalid message format"); 2657 return FALSE; 2658 } 2659 2660 2661 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message, 2662 struct wpa_supplicant *wpa_s) 2663 { 2664 DBusMessageIter iter_dict; 2665 DBusMessage *reply = NULL; 2666 DBusMessageIter iter; 2667 struct wpa_dbus_dict_entry entry; 2668 int upnp = 0; 2669 int bonjour = 0; 2670 char *service = NULL; 2671 struct wpabuf *query = NULL; 2672 struct wpabuf *resp = NULL; 2673 u8 version = 0; 2674 2675 dbus_message_iter_init(message, &iter); 2676 2677 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2678 goto error; 2679 2680 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2681 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2682 goto error; 2683 2684 if (os_strcmp(entry.key, "service_type") == 0 && 2685 entry.type == DBUS_TYPE_STRING) { 2686 if (os_strcmp(entry.str_value, "upnp") == 0) 2687 upnp = 1; 2688 else if (os_strcmp(entry.str_value, "bonjour") == 0) 2689 bonjour = 1; 2690 else 2691 goto error_clear; 2692 } else if (os_strcmp(entry.key, "version") == 0 && 2693 entry.type == DBUS_TYPE_INT32) { 2694 version = entry.uint32_value; 2695 } else if (os_strcmp(entry.key, "service") == 0 && 2696 entry.type == DBUS_TYPE_STRING) { 2697 os_free(service); 2698 service = os_strdup(entry.str_value); 2699 } else if (os_strcmp(entry.key, "query") == 0) { 2700 if (entry.type != DBUS_TYPE_ARRAY || 2701 entry.array_type != DBUS_TYPE_BYTE) 2702 goto error_clear; 2703 query = wpabuf_alloc_copy( 2704 entry.bytearray_value, 2705 entry.array_len); 2706 } else if (os_strcmp(entry.key, "response") == 0) { 2707 if (entry.type != DBUS_TYPE_ARRAY || 2708 entry.array_type != DBUS_TYPE_BYTE) 2709 goto error_clear; 2710 resp = wpabuf_alloc_copy(entry.bytearray_value, 2711 entry.array_len); 2712 } 2713 wpa_dbus_dict_entry_clear(&entry); 2714 } 2715 2716 if (upnp == 1) { 2717 if (version <= 0 || service == NULL) 2718 goto error; 2719 2720 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0) 2721 goto error; 2722 2723 } else if (bonjour == 1) { 2724 if (query == NULL || resp == NULL) 2725 goto error; 2726 2727 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) 2728 goto error; 2729 query = NULL; 2730 resp = NULL; 2731 } else 2732 goto error; 2733 2734 os_free(service); 2735 return reply; 2736 error_clear: 2737 wpa_dbus_dict_entry_clear(&entry); 2738 error: 2739 os_free(service); 2740 wpabuf_free(query); 2741 wpabuf_free(resp); 2742 return wpas_dbus_error_invalid_args(message, NULL); 2743 } 2744 2745 2746 DBusMessage * wpas_dbus_handler_p2p_delete_service( 2747 DBusMessage *message, struct wpa_supplicant *wpa_s) 2748 { 2749 DBusMessageIter iter_dict; 2750 DBusMessage *reply = NULL; 2751 DBusMessageIter iter; 2752 struct wpa_dbus_dict_entry entry; 2753 int upnp = 0; 2754 int bonjour = 0; 2755 int ret = 0; 2756 char *service = NULL; 2757 struct wpabuf *query = NULL; 2758 u8 version = 0; 2759 2760 dbus_message_iter_init(message, &iter); 2761 2762 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2763 goto error; 2764 2765 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2766 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2767 goto error; 2768 2769 if (os_strcmp(entry.key, "service_type") == 0 && 2770 entry.type == DBUS_TYPE_STRING) { 2771 if (os_strcmp(entry.str_value, "upnp") == 0) 2772 upnp = 1; 2773 else if (os_strcmp(entry.str_value, "bonjour") == 0) 2774 bonjour = 1; 2775 else 2776 goto error_clear; 2777 } else if (os_strcmp(entry.key, "version") == 0 && 2778 entry.type == DBUS_TYPE_INT32) { 2779 version = entry.uint32_value; 2780 } else if (os_strcmp(entry.key, "service") == 0 && 2781 entry.type == DBUS_TYPE_STRING) { 2782 os_free(service); 2783 service = os_strdup(entry.str_value); 2784 } else if (os_strcmp(entry.key, "query") == 0) { 2785 if (entry.type != DBUS_TYPE_ARRAY || 2786 entry.array_type != DBUS_TYPE_BYTE) 2787 goto error_clear; 2788 wpabuf_free(query); 2789 query = wpabuf_alloc_copy(entry.bytearray_value, 2790 entry.array_len); 2791 } else { 2792 goto error_clear; 2793 } 2794 2795 wpa_dbus_dict_entry_clear(&entry); 2796 } 2797 if (upnp == 1) { 2798 if (version <= 0 || service == NULL) 2799 goto error; 2800 2801 ret = wpas_p2p_service_del_upnp(wpa_s, version, service); 2802 if (ret != 0) 2803 goto error; 2804 } else if (bonjour == 1) { 2805 if (query == NULL) 2806 goto error; 2807 2808 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 2809 if (ret != 0) 2810 goto error; 2811 } else 2812 goto error; 2813 2814 wpabuf_free(query); 2815 os_free(service); 2816 return reply; 2817 error_clear: 2818 wpa_dbus_dict_entry_clear(&entry); 2819 error: 2820 wpabuf_free(query); 2821 os_free(service); 2822 return wpas_dbus_error_invalid_args(message, NULL); 2823 } 2824 2825 2826 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message, 2827 struct wpa_supplicant *wpa_s) 2828 { 2829 wpas_p2p_service_flush(wpa_s); 2830 return NULL; 2831 } 2832 2833 2834 DBusMessage * wpas_dbus_handler_p2p_service_sd_req( 2835 DBusMessage *message, struct wpa_supplicant *wpa_s) 2836 { 2837 DBusMessageIter iter_dict; 2838 DBusMessage *reply = NULL; 2839 DBusMessageIter iter; 2840 struct wpa_dbus_dict_entry entry; 2841 int upnp = 0; 2842 char *service = NULL; 2843 char *peer_object_path = NULL; 2844 struct wpabuf *tlv = NULL; 2845 u8 version = 0; 2846 u64 ref = 0; 2847 u8 addr_buf[ETH_ALEN], *addr; 2848 2849 dbus_message_iter_init(message, &iter); 2850 2851 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2852 goto error; 2853 2854 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2855 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2856 goto error; 2857 if (os_strcmp(entry.key, "peer_object") == 0 && 2858 entry.type == DBUS_TYPE_OBJECT_PATH) { 2859 peer_object_path = os_strdup(entry.str_value); 2860 } else if (os_strcmp(entry.key, "service_type") == 0 && 2861 entry.type == DBUS_TYPE_STRING) { 2862 if (os_strcmp(entry.str_value, "upnp") == 0) 2863 upnp = 1; 2864 else 2865 goto error_clear; 2866 } else if (os_strcmp(entry.key, "version") == 0 && 2867 entry.type == DBUS_TYPE_INT32) { 2868 version = entry.uint32_value; 2869 } else if (os_strcmp(entry.key, "service") == 0 && 2870 entry.type == DBUS_TYPE_STRING) { 2871 service = os_strdup(entry.str_value); 2872 } else if (os_strcmp(entry.key, "tlv") == 0) { 2873 if (entry.type != DBUS_TYPE_ARRAY || 2874 entry.array_type != DBUS_TYPE_BYTE) 2875 goto error_clear; 2876 tlv = wpabuf_alloc_copy(entry.bytearray_value, 2877 entry.array_len); 2878 } else 2879 goto error_clear; 2880 2881 wpa_dbus_dict_entry_clear(&entry); 2882 } 2883 2884 if (!peer_object_path) { 2885 addr = NULL; 2886 } else { 2887 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 || 2888 !p2p_peer_known(wpa_s->global->p2p, addr_buf)) 2889 goto error; 2890 2891 addr = addr_buf; 2892 } 2893 2894 if (upnp == 1) { 2895 if (version <= 0 || service == NULL) 2896 goto error; 2897 2898 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service); 2899 } else { 2900 if (tlv == NULL) 2901 goto error; 2902 ref = wpas_p2p_sd_request(wpa_s, addr, tlv); 2903 wpabuf_free(tlv); 2904 } 2905 2906 if (ref != 0) { 2907 reply = dbus_message_new_method_return(message); 2908 dbus_message_append_args(reply, DBUS_TYPE_UINT64, 2909 &ref, DBUS_TYPE_INVALID); 2910 } else { 2911 reply = wpas_dbus_error_unknown_error( 2912 message, "Unable to send SD request"); 2913 } 2914 out: 2915 os_free(service); 2916 os_free(peer_object_path); 2917 return reply; 2918 error_clear: 2919 wpa_dbus_dict_entry_clear(&entry); 2920 error: 2921 if (tlv) 2922 wpabuf_free(tlv); 2923 reply = wpas_dbus_error_invalid_args(message, NULL); 2924 goto out; 2925 } 2926 2927 2928 DBusMessage * wpas_dbus_handler_p2p_service_sd_res( 2929 DBusMessage *message, struct wpa_supplicant *wpa_s) 2930 { 2931 DBusMessageIter iter_dict; 2932 DBusMessage *reply = NULL; 2933 DBusMessageIter iter; 2934 struct wpa_dbus_dict_entry entry; 2935 char *peer_object_path = NULL; 2936 struct wpabuf *tlv = NULL; 2937 int freq = 0; 2938 int dlg_tok = 0; 2939 u8 addr[ETH_ALEN]; 2940 2941 dbus_message_iter_init(message, &iter); 2942 2943 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2944 goto error; 2945 2946 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2947 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2948 goto error; 2949 2950 if (os_strcmp(entry.key, "peer_object") == 0 && 2951 entry.type == DBUS_TYPE_OBJECT_PATH) { 2952 peer_object_path = os_strdup(entry.str_value); 2953 } else if (os_strcmp(entry.key, "frequency") == 0 && 2954 entry.type == DBUS_TYPE_INT32) { 2955 freq = entry.uint32_value; 2956 } else if (os_strcmp(entry.key, "dialog_token") == 0 && 2957 (entry.type == DBUS_TYPE_UINT32 || 2958 entry.type == DBUS_TYPE_INT32)) { 2959 dlg_tok = entry.uint32_value; 2960 } else if (os_strcmp(entry.key, "tlvs") == 0) { 2961 if (entry.type != DBUS_TYPE_ARRAY || 2962 entry.array_type != DBUS_TYPE_BYTE) 2963 goto error_clear; 2964 tlv = wpabuf_alloc_copy(entry.bytearray_value, 2965 entry.array_len); 2966 } else 2967 goto error_clear; 2968 2969 wpa_dbus_dict_entry_clear(&entry); 2970 } 2971 if (parse_peer_object_path(peer_object_path, addr) < 0 || 2972 !p2p_peer_known(wpa_s->global->p2p, addr) || 2973 tlv == NULL) 2974 goto error; 2975 2976 wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv); 2977 wpabuf_free(tlv); 2978 out: 2979 os_free(peer_object_path); 2980 return reply; 2981 error_clear: 2982 wpa_dbus_dict_entry_clear(&entry); 2983 error: 2984 reply = wpas_dbus_error_invalid_args(message, NULL); 2985 goto out; 2986 } 2987 2988 2989 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req( 2990 DBusMessage *message, struct wpa_supplicant *wpa_s) 2991 { 2992 DBusMessageIter iter; 2993 u64 req = 0; 2994 2995 dbus_message_iter_init(message, &iter); 2996 dbus_message_iter_get_basic(&iter, &req); 2997 2998 if (req == 0) 2999 goto error; 3000 3001 if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0) 3002 goto error; 3003 3004 return NULL; 3005 error: 3006 return wpas_dbus_error_invalid_args(message, NULL); 3007 } 3008 3009 3010 DBusMessage * wpas_dbus_handler_p2p_service_update( 3011 DBusMessage *message, struct wpa_supplicant *wpa_s) 3012 { 3013 wpas_p2p_sd_service_update(wpa_s); 3014 return NULL; 3015 } 3016 3017 3018 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external( 3019 DBusMessage *message, struct wpa_supplicant *wpa_s) 3020 { 3021 DBusMessageIter iter; 3022 int ext = 0; 3023 3024 dbus_message_iter_init(message, &iter); 3025 dbus_message_iter_get_basic(&iter, &ext); 3026 3027 wpa_s->p2p_sd_over_ctrl_iface = ext; 3028 3029 return NULL; 3030 3031 } 3032 3033 3034 #ifdef CONFIG_WIFI_DISPLAY 3035 3036 dbus_bool_t wpas_dbus_getter_global_wfd_ies( 3037 const struct wpa_dbus_property_desc *property_desc, 3038 DBusMessageIter *iter, DBusError *error, void *user_data) 3039 { 3040 struct wpa_global *global = user_data; 3041 struct wpabuf *ie; 3042 dbus_bool_t ret; 3043 3044 ie = wifi_display_get_wfd_ie(global); 3045 if (ie == NULL) 3046 return wpas_dbus_simple_array_property_getter(iter, 3047 DBUS_TYPE_BYTE, 3048 NULL, 0, error); 3049 3050 ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3051 wpabuf_head(ie), 3052 wpabuf_len(ie), error); 3053 wpabuf_free(ie); 3054 3055 return ret; 3056 } 3057 3058 3059 dbus_bool_t wpas_dbus_setter_global_wfd_ies( 3060 const struct wpa_dbus_property_desc *property_desc, 3061 DBusMessageIter *iter, DBusError *error, void *user_data) 3062 { 3063 struct wpa_global *global = user_data; 3064 DBusMessageIter variant, array; 3065 struct wpabuf *ie = NULL; 3066 const u8 *data; 3067 int len; 3068 3069 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) 3070 goto err; 3071 3072 dbus_message_iter_recurse(iter, &variant); 3073 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY) 3074 goto err; 3075 3076 dbus_message_iter_recurse(&variant, &array); 3077 dbus_message_iter_get_fixed_array(&array, &data, &len); 3078 if (len == 0) { 3079 wifi_display_enable(global, 0); 3080 wifi_display_deinit(global); 3081 3082 return TRUE; 3083 } 3084 3085 ie = wpabuf_alloc(len); 3086 if (ie == NULL) 3087 goto err; 3088 3089 wpabuf_put_data(ie, data, len); 3090 if (wifi_display_subelem_set_from_ies(global, ie) != 0) 3091 goto err; 3092 3093 if (global->wifi_display == 0) 3094 wifi_display_enable(global, 1); 3095 3096 wpabuf_free(ie); 3097 3098 return TRUE; 3099 err: 3100 wpabuf_free(ie); 3101 3102 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 3103 "invalid message format"); 3104 return FALSE; 3105 } 3106 3107 #endif /* CONFIG_WIFI_DISPLAY */ 3108