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