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