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