1 /* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 #include <dbus/dbus.h> 17 18 #include "common.h" 19 #include "eloop.h" 20 #include "wps/wps.h" 21 #include "../config.h" 22 #include "../wpa_supplicant_i.h" 23 #include "../bss.h" 24 #include "dbus_old.h" 25 #include "dbus_old_handlers.h" 26 #include "dbus_common_i.h" 27 28 29 /** 30 * wpas_dbus_decompose_object_path - Decompose an interface object path into parts 31 * @path: The dbus object path 32 * @network: (out) the configured network this object path refers to, if any 33 * @bssid: (out) the scanned bssid this object path refers to, if any 34 * Returns: The object path of the network interface this path refers to 35 * 36 * For a given object path, decomposes the object path into object id, network, 37 * and BSSID parts, if those parts exist. 38 */ 39 char * wpas_dbus_decompose_object_path(const char *path, char **network, 40 char **bssid) 41 { 42 const unsigned int dev_path_prefix_len = 43 strlen(WPAS_DBUS_PATH_INTERFACES "/"); 44 char *obj_path_only; 45 char *next_sep; 46 47 /* Be a bit paranoid about path */ 48 if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/", 49 dev_path_prefix_len)) 50 return NULL; 51 52 /* Ensure there's something at the end of the path */ 53 if ((path + dev_path_prefix_len)[0] == '\0') 54 return NULL; 55 56 obj_path_only = os_strdup(path); 57 if (obj_path_only == NULL) 58 return NULL; 59 60 next_sep = strchr(obj_path_only + dev_path_prefix_len, '/'); 61 if (next_sep != NULL) { 62 const char *net_part = strstr(next_sep, 63 WPAS_DBUS_NETWORKS_PART "/"); 64 const char *bssid_part = strstr(next_sep, 65 WPAS_DBUS_BSSIDS_PART "/"); 66 67 if (network && net_part) { 68 /* Deal with a request for a configured network */ 69 const char *net_name = net_part + 70 strlen(WPAS_DBUS_NETWORKS_PART "/"); 71 *network = NULL; 72 if (strlen(net_name)) 73 *network = os_strdup(net_name); 74 } else if (bssid && bssid_part) { 75 /* Deal with a request for a scanned BSSID */ 76 const char *bssid_name = bssid_part + 77 strlen(WPAS_DBUS_BSSIDS_PART "/"); 78 if (strlen(bssid_name)) 79 *bssid = os_strdup(bssid_name); 80 else 81 *bssid = NULL; 82 } 83 84 /* Cut off interface object path before "/" */ 85 *next_sep = '\0'; 86 } 87 88 return obj_path_only; 89 } 90 91 92 /** 93 * wpas_dbus_new_invalid_iface_error - Return a new invalid interface error message 94 * @message: Pointer to incoming dbus message this error refers to 95 * Returns: A dbus error message 96 * 97 * Convenience function to create and return an invalid interface error 98 */ 99 DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message) 100 { 101 return dbus_message_new_error(message, WPAS_ERROR_INVALID_IFACE, 102 "wpa_supplicant knows nothing about " 103 "this interface."); 104 } 105 106 107 /** 108 * wpas_dbus_new_invalid_network_error - Return a new invalid network error message 109 * @message: Pointer to incoming dbus message this error refers to 110 * Returns: a dbus error message 111 * 112 * Convenience function to create and return an invalid network error 113 */ 114 DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message) 115 { 116 return dbus_message_new_error(message, WPAS_ERROR_INVALID_NETWORK, 117 "The requested network does not exist."); 118 } 119 120 121 /** 122 * wpas_dbus_new_invalid_bssid_error - Return a new invalid bssid error message 123 * @message: Pointer to incoming dbus message this error refers to 124 * Returns: a dbus error message 125 * 126 * Convenience function to create and return an invalid bssid error 127 */ 128 static DBusMessage * wpas_dbus_new_invalid_bssid_error(DBusMessage *message) 129 { 130 return dbus_message_new_error(message, WPAS_ERROR_INVALID_BSSID, 131 "The BSSID requested was invalid."); 132 } 133 134 135 /** 136 * wpas_dispatch_network_method - dispatch messages for configured networks 137 * @message: the incoming dbus message 138 * @wpa_s: a network interface's data 139 * @network_id: id of the configured network we're interested in 140 * Returns: a reply dbus message, or a dbus error message 141 * 142 * This function dispatches all incoming dbus messages for configured networks. 143 */ 144 static DBusMessage * wpas_dispatch_network_method(DBusMessage *message, 145 struct wpa_supplicant *wpa_s, 146 int network_id) 147 { 148 DBusMessage *reply = NULL; 149 const char *method = dbus_message_get_member(message); 150 struct wpa_ssid *ssid; 151 152 ssid = wpa_config_get_network(wpa_s->conf, network_id); 153 if (ssid == NULL) 154 return wpas_dbus_new_invalid_network_error(message); 155 156 if (!strcmp(method, "set")) 157 reply = wpas_dbus_iface_set_network(message, wpa_s, ssid); 158 else if (!strcmp(method, "enable")) 159 reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid); 160 else if (!strcmp(method, "disable")) 161 reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid); 162 163 return reply; 164 } 165 166 167 /** 168 * wpas_dispatch_bssid_method - dispatch messages for scanned networks 169 * @message: the incoming dbus message 170 * @wpa_s: a network interface's data 171 * @bssid: bssid of the scanned network we're interested in 172 * Returns: a reply dbus message, or a dbus error message 173 * 174 * This function dispatches all incoming dbus messages for scanned networks. 175 */ 176 static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message, 177 struct wpa_supplicant *wpa_s, 178 const char *bssid_txt) 179 { 180 u8 bssid[ETH_ALEN]; 181 struct wpa_bss *bss; 182 183 if (hexstr2bin(bssid_txt, bssid, ETH_ALEN) < 0) 184 return wpas_dbus_new_invalid_bssid_error(message); 185 186 bss = wpa_bss_get_bssid(wpa_s, bssid); 187 if (bss == NULL) 188 return wpas_dbus_new_invalid_bssid_error(message); 189 190 /* Dispatch the method call against the scanned bssid */ 191 if (os_strcmp(dbus_message_get_member(message), "properties") == 0) 192 return wpas_dbus_bssid_properties(message, wpa_s, bss); 193 194 return NULL; 195 } 196 197 198 /** 199 * wpas_iface_message_handler - Dispatch messages for interfaces or networks 200 * @connection: Connection to the system message bus 201 * @message: An incoming dbus message 202 * @user_data: A pointer to a dbus control interface data structure 203 * Returns: Whether or not the message was handled 204 * 205 * This function dispatches all incoming dbus messages for network interfaces, 206 * or objects owned by them, such as scanned BSSIDs and configured networks. 207 */ 208 static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection, 209 DBusMessage *message, 210 void *user_data) 211 { 212 struct wpa_supplicant *wpa_s = user_data; 213 const char *method = dbus_message_get_member(message); 214 const char *path = dbus_message_get_path(message); 215 const char *msg_interface = dbus_message_get_interface(message); 216 char *iface_obj_path = NULL; 217 char *network = NULL; 218 char *bssid = NULL; 219 DBusMessage *reply = NULL; 220 221 /* Caller must specify a message interface */ 222 if (!msg_interface) 223 goto out; 224 225 iface_obj_path = wpas_dbus_decompose_object_path(path, &network, 226 &bssid); 227 if (iface_obj_path == NULL) { 228 reply = wpas_dbus_new_invalid_iface_error(message); 229 goto out; 230 } 231 232 /* Make sure the message's object path actually refers to the 233 * wpa_supplicant structure it's supposed to (which is wpa_s) 234 */ 235 if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global, 236 iface_obj_path) != wpa_s) { 237 reply = wpas_dbus_new_invalid_iface_error(message); 238 goto out; 239 } 240 241 if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) { 242 /* A method for one of this interface's configured networks */ 243 int nid = strtoul(network, NULL, 10); 244 if (errno != EINVAL) 245 reply = wpas_dispatch_network_method(message, wpa_s, 246 nid); 247 else 248 reply = wpas_dbus_new_invalid_network_error(message); 249 } else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) { 250 /* A method for one of this interface's scanned BSSIDs */ 251 reply = wpas_dispatch_bssid_method(message, wpa_s, bssid); 252 } else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) { 253 /* A method for an interface only. */ 254 if (!strcmp(method, "scan")) 255 reply = wpas_dbus_iface_scan(message, wpa_s); 256 else if (!strcmp(method, "scanResults")) 257 reply = wpas_dbus_iface_scan_results(message, wpa_s); 258 else if (!strcmp(method, "addNetwork")) 259 reply = wpas_dbus_iface_add_network(message, wpa_s); 260 else if (!strcmp(method, "removeNetwork")) 261 reply = wpas_dbus_iface_remove_network(message, wpa_s); 262 else if (!strcmp(method, "selectNetwork")) 263 reply = wpas_dbus_iface_select_network(message, wpa_s); 264 else if (!strcmp(method, "capabilities")) 265 reply = wpas_dbus_iface_capabilities(message, wpa_s); 266 else if (!strcmp(method, "disconnect")) 267 reply = wpas_dbus_iface_disconnect(message, wpa_s); 268 else if (!strcmp(method, "setAPScan")) 269 reply = wpas_dbus_iface_set_ap_scan(message, wpa_s); 270 else if (!strcmp(method, "setSmartcardModules")) 271 reply = wpas_dbus_iface_set_smartcard_modules(message, 272 wpa_s); 273 else if (!strcmp(method, "state")) 274 reply = wpas_dbus_iface_get_state(message, wpa_s); 275 else if (!strcmp(method, "scanning")) 276 reply = wpas_dbus_iface_get_scanning(message, wpa_s); 277 else if (!strcmp(method, "setBlobs")) 278 reply = wpas_dbus_iface_set_blobs(message, wpa_s); 279 else if (!strcmp(method, "removeBlobs")) 280 reply = wpas_dbus_iface_remove_blobs(message, wpa_s); 281 #ifdef CONFIG_WPS 282 else if (!os_strcmp(method, "wpsPbc")) 283 reply = wpas_dbus_iface_wps_pbc(message, wpa_s); 284 else if (!os_strcmp(method, "wpsPin")) 285 reply = wpas_dbus_iface_wps_pin(message, wpa_s); 286 else if (!os_strcmp(method, "wpsReg")) 287 reply = wpas_dbus_iface_wps_reg(message, wpa_s); 288 #endif /* CONFIG_WPS */ 289 else if (!os_strcmp(method, "flush")) 290 reply = wpas_dbus_iface_flush(message, wpa_s); 291 } 292 293 /* If the message was handled, send back the reply */ 294 if (reply) { 295 if (!dbus_message_get_no_reply(message)) 296 dbus_connection_send(connection, reply, NULL); 297 dbus_message_unref(reply); 298 } 299 300 out: 301 os_free(iface_obj_path); 302 os_free(network); 303 os_free(bssid); 304 return reply ? DBUS_HANDLER_RESULT_HANDLED : 305 DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 306 } 307 308 309 /** 310 * wpas_message_handler - dispatch incoming dbus messages 311 * @connection: connection to the system message bus 312 * @message: an incoming dbus message 313 * @user_data: a pointer to a dbus control interface data structure 314 * Returns: whether or not the message was handled 315 * 316 * This function dispatches all incoming dbus messages to the correct 317 * handlers, depending on what the message's target object path is, 318 * and what the method call is. 319 */ 320 static DBusHandlerResult wpas_message_handler(DBusConnection *connection, 321 DBusMessage *message, void *user_data) 322 { 323 struct wpas_dbus_priv *ctrl_iface = user_data; 324 const char *method; 325 const char *path; 326 const char *msg_interface; 327 DBusMessage *reply = NULL; 328 329 method = dbus_message_get_member(message); 330 path = dbus_message_get_path(message); 331 msg_interface = dbus_message_get_interface(message); 332 if (!method || !path || !ctrl_iface || !msg_interface) 333 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 334 335 /* Validate the method interface */ 336 if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0) 337 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 338 339 if (!strcmp(path, WPAS_DBUS_PATH)) { 340 /* dispatch methods against our global dbus interface here */ 341 if (!strcmp(method, "addInterface")) { 342 reply = wpas_dbus_global_add_interface( 343 message, ctrl_iface->global); 344 } else if (!strcmp(method, "removeInterface")) { 345 reply = wpas_dbus_global_remove_interface( 346 message, ctrl_iface->global); 347 } else if (!strcmp(method, "getInterface")) { 348 reply = wpas_dbus_global_get_interface( 349 message, ctrl_iface->global); 350 } else if (!strcmp(method, "setDebugParams")) { 351 reply = wpas_dbus_global_set_debugparams( 352 message, ctrl_iface->global); 353 } 354 } 355 356 /* If the message was handled, send back the reply */ 357 if (reply) { 358 if (!dbus_message_get_no_reply(message)) 359 dbus_connection_send(connection, reply, NULL); 360 dbus_message_unref(reply); 361 } 362 363 return reply ? DBUS_HANDLER_RESULT_HANDLED : 364 DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 365 } 366 367 368 /** 369 * wpa_supplicant_dbus_notify_scan_results - Send a scan results signal 370 * @wpa_s: %wpa_supplicant network interface data 371 * Returns: 0 on success, -1 on failure 372 * 373 * Notify listeners that this interface has updated scan results. 374 */ 375 void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s) 376 { 377 struct wpas_dbus_priv *iface = wpa_s->global->dbus; 378 DBusMessage *_signal; 379 380 /* Do nothing if the control interface is not turned on */ 381 if (iface == NULL) 382 return; 383 384 _signal = dbus_message_new_signal(wpa_s->dbus_path, 385 WPAS_DBUS_IFACE_INTERFACE, 386 "ScanResultsAvailable"); 387 if (_signal == NULL) { 388 wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan " 389 "results signal"); 390 return; 391 } 392 dbus_connection_send(iface->con, _signal, NULL); 393 dbus_message_unref(_signal); 394 } 395 396 397 /** 398 * wpa_supplicant_dbus_notify_state_change - Send a state change signal 399 * @wpa_s: %wpa_supplicant network interface data 400 * @new_state: new state wpa_supplicant is entering 401 * @old_state: old state wpa_supplicant is leaving 402 * Returns: 0 on success, -1 on failure 403 * 404 * Notify listeners that wpa_supplicant has changed state 405 */ 406 void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, 407 enum wpa_states new_state, 408 enum wpa_states old_state) 409 { 410 struct wpas_dbus_priv *iface; 411 DBusMessage *_signal = NULL; 412 const char *new_state_str, *old_state_str; 413 414 if (wpa_s->dbus_path == NULL) 415 return; /* Skip signal since D-Bus setup is not yet ready */ 416 417 /* Do nothing if the control interface is not turned on */ 418 if (wpa_s->global == NULL) 419 return; 420 iface = wpa_s->global->dbus; 421 if (iface == NULL) 422 return; 423 424 /* Only send signal if state really changed */ 425 if (new_state == old_state) 426 return; 427 428 _signal = dbus_message_new_signal(wpa_s->dbus_path, 429 WPAS_DBUS_IFACE_INTERFACE, 430 "StateChange"); 431 if (_signal == NULL) { 432 wpa_printf(MSG_ERROR, 433 "dbus: wpa_supplicant_dbus_notify_state_change: " 434 "could not create dbus signal; likely out of " 435 "memory"); 436 return; 437 } 438 439 new_state_str = wpa_supplicant_state_txt(new_state); 440 old_state_str = wpa_supplicant_state_txt(old_state); 441 if (new_state_str == NULL || old_state_str == NULL) { 442 wpa_printf(MSG_ERROR, 443 "dbus: wpa_supplicant_dbus_notify_state_change: " 444 "Could not convert state strings"); 445 goto out; 446 } 447 448 if (!dbus_message_append_args(_signal, 449 DBUS_TYPE_STRING, &new_state_str, 450 DBUS_TYPE_STRING, &old_state_str, 451 DBUS_TYPE_INVALID)) { 452 wpa_printf(MSG_ERROR, 453 "dbus: wpa_supplicant_dbus_notify_state_change: " 454 "Not enough memory to construct state change " 455 "signal"); 456 goto out; 457 } 458 459 dbus_connection_send(iface->con, _signal, NULL); 460 461 out: 462 dbus_message_unref(_signal); 463 } 464 465 466 /** 467 * wpa_supplicant_dbus_notify_scanning - send scanning status 468 * @wpa_s: %wpa_supplicant network interface data 469 * Returns: 0 on success, -1 on failure 470 * 471 * Notify listeners of interface scanning state changes 472 */ 473 void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s) 474 { 475 struct wpas_dbus_priv *iface = wpa_s->global->dbus; 476 DBusMessage *_signal; 477 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 478 479 /* Do nothing if the control interface is not turned on */ 480 if (iface == NULL) 481 return; 482 483 _signal = dbus_message_new_signal(wpa_s->dbus_path, 484 WPAS_DBUS_IFACE_INTERFACE, 485 "Scanning"); 486 if (_signal == NULL) { 487 wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan " 488 "results signal"); 489 return; 490 } 491 492 if (dbus_message_append_args(_signal, 493 DBUS_TYPE_BOOLEAN, &scanning, 494 DBUS_TYPE_INVALID)) { 495 dbus_connection_send(iface->con, _signal, NULL); 496 } else { 497 wpa_printf(MSG_ERROR, "dbus: Not enough memory to construct " 498 "signal"); 499 } 500 dbus_message_unref(_signal); 501 } 502 503 504 #ifdef CONFIG_WPS 505 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s, 506 const struct wps_credential *cred) 507 { 508 struct wpas_dbus_priv *iface; 509 DBusMessage *_signal = NULL; 510 511 /* Do nothing if the control interface is not turned on */ 512 if (wpa_s->global == NULL) 513 return; 514 iface = wpa_s->global->dbus; 515 if (iface == NULL) 516 return; 517 518 _signal = dbus_message_new_signal(wpa_s->dbus_path, 519 WPAS_DBUS_IFACE_INTERFACE, 520 "WpsCred"); 521 if (_signal == NULL) { 522 wpa_printf(MSG_ERROR, 523 "dbus: wpa_supplicant_dbus_notify_wps_cred: " 524 "Could not create dbus signal; likely out of " 525 "memory"); 526 return; 527 } 528 529 if (!dbus_message_append_args(_signal, 530 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 531 &cred->cred_attr, cred->cred_attr_len, 532 DBUS_TYPE_INVALID)) { 533 wpa_printf(MSG_ERROR, 534 "dbus: wpa_supplicant_dbus_notify_wps_cred: " 535 "Not enough memory to construct signal"); 536 goto out; 537 } 538 539 dbus_connection_send(iface->con, _signal, NULL); 540 541 out: 542 dbus_message_unref(_signal); 543 } 544 #else /* CONFIG_WPS */ 545 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s, 546 const struct wps_credential *cred) 547 { 548 } 549 #endif /* CONFIG_WPS */ 550 551 void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s, 552 int depth, const char *subject, 553 const char *cert_hash, 554 const struct wpabuf *cert) 555 { 556 struct wpas_dbus_priv *iface; 557 DBusMessage *_signal = NULL; 558 const char *hash; 559 const char *cert_hex; 560 int cert_hex_len; 561 562 /* Do nothing if the control interface is not turned on */ 563 if (wpa_s->global == NULL) 564 return; 565 iface = wpa_s->global->dbus; 566 if (iface == NULL) 567 return; 568 569 _signal = dbus_message_new_signal(wpa_s->dbus_path, 570 WPAS_DBUS_IFACE_INTERFACE, 571 "Certification"); 572 if (_signal == NULL) { 573 wpa_printf(MSG_ERROR, 574 "dbus: wpa_supplicant_dbus_notify_certification: " 575 "Could not create dbus signal; likely out of " 576 "memory"); 577 return; 578 } 579 580 hash = cert_hash ? cert_hash : ""; 581 cert_hex = cert ? wpabuf_head(cert) : ""; 582 cert_hex_len = cert ? wpabuf_len(cert) : 0; 583 584 if (!dbus_message_append_args(_signal, 585 DBUS_TYPE_INT32,&depth, 586 DBUS_TYPE_STRING, &subject, 587 DBUS_TYPE_STRING, &hash, 588 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 589 &cert_hex, cert_hex_len, 590 DBUS_TYPE_INVALID)) { 591 wpa_printf(MSG_ERROR, 592 "dbus: wpa_supplicant_dbus_notify_certification: " 593 "Not enough memory to construct signal"); 594 goto out; 595 } 596 597 dbus_connection_send(iface->con, _signal, NULL); 598 599 out: 600 dbus_message_unref(_signal); 601 602 } 603 604 605 /** 606 * wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface 607 * @global: Pointer to global data from wpa_supplicant_init() 608 * Returns: 0 on success, -1 on failure 609 * 610 * Initialize the dbus control interface and start receiving commands from 611 * external programs over the bus. 612 */ 613 int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface) 614 { 615 DBusError error; 616 int ret = -1; 617 DBusObjectPathVTable wpas_vtable = { 618 NULL, &wpas_message_handler, NULL, NULL, NULL, NULL 619 }; 620 621 /* Register the message handler for the global dbus interface */ 622 if (!dbus_connection_register_object_path(iface->con, 623 WPAS_DBUS_PATH, &wpas_vtable, 624 iface)) { 625 wpa_printf(MSG_ERROR, "dbus: Could not set up message " 626 "handler"); 627 return -1; 628 } 629 630 /* Register our service with the message bus */ 631 dbus_error_init(&error); 632 switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE, 633 0, &error)) { 634 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: 635 ret = 0; 636 break; 637 case DBUS_REQUEST_NAME_REPLY_EXISTS: 638 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: 639 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: 640 wpa_printf(MSG_ERROR, "dbus: Could not request service name: " 641 "already registered"); 642 break; 643 default: 644 wpa_printf(MSG_ERROR, "dbus: Could not request service name: " 645 "%s %s", error.name, error.message); 646 break; 647 } 648 dbus_error_free(&error); 649 650 if (ret != 0) 651 return -1; 652 653 wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE 654 "'."); 655 656 return 0; 657 } 658 659 660 /** 661 * wpas_dbus_register_new_iface - Register a new interface with dbus 662 * @wpa_s: %wpa_supplicant interface description structure to register 663 * Returns: 0 on success, -1 on error 664 * 665 * Registers a new interface with dbus and assigns it a dbus object path. 666 */ 667 int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s) 668 { 669 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus; 670 DBusConnection * con; 671 u32 next; 672 DBusObjectPathVTable vtable = { 673 NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL 674 }; 675 676 /* Do nothing if the control interface is not turned on */ 677 if (ctrl_iface == NULL) 678 return 0; 679 680 con = ctrl_iface->con; 681 next = ctrl_iface->next_objid++; 682 683 /* Create and set the interface's object path */ 684 wpa_s->dbus_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 685 if (wpa_s->dbus_path == NULL) 686 return -1; 687 os_snprintf(wpa_s->dbus_path, WPAS_DBUS_OBJECT_PATH_MAX, 688 WPAS_DBUS_PATH_INTERFACES "/%u", 689 next); 690 691 /* Register the message handler for the interface functions */ 692 if (!dbus_connection_register_fallback(con, wpa_s->dbus_path, &vtable, 693 wpa_s)) { 694 wpa_printf(MSG_ERROR, "dbus: Could not set up message " 695 "handler for interface %s", wpa_s->ifname); 696 return -1; 697 } 698 699 return 0; 700 } 701 702 703 /** 704 * wpas_dbus_unregister_iface - Unregister an interface from dbus 705 * @wpa_s: wpa_supplicant interface structure 706 * Returns: 0 on success, -1 on failure 707 * 708 * Unregisters the interface with dbus 709 */ 710 int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s) 711 { 712 struct wpas_dbus_priv *ctrl_iface; 713 DBusConnection *con; 714 715 /* Do nothing if the control interface is not turned on */ 716 if (wpa_s == NULL || wpa_s->global == NULL) 717 return 0; 718 ctrl_iface = wpa_s->global->dbus; 719 if (ctrl_iface == NULL) 720 return 0; 721 722 con = ctrl_iface->con; 723 if (!dbus_connection_unregister_object_path(con, wpa_s->dbus_path)) 724 return -1; 725 726 os_free(wpa_s->dbus_path); 727 wpa_s->dbus_path = NULL; 728 729 return 0; 730 } 731 732 733 /** 734 * wpa_supplicant_get_iface_by_dbus_path - Get a new network interface 735 * @global: Pointer to global data from wpa_supplicant_init() 736 * @path: Pointer to a dbus object path representing an interface 737 * Returns: Pointer to the interface or %NULL if not found 738 */ 739 struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path( 740 struct wpa_global *global, const char *path) 741 { 742 struct wpa_supplicant *wpa_s; 743 744 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 745 if (strcmp(wpa_s->dbus_path, path) == 0) 746 return wpa_s; 747 } 748 return NULL; 749 } 750