00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016 #include <dbus/dbus.h>
00017
00018 #include "common.h"
00019 #include "eloop.h"
00020 #include "wps/wps.h"
00021 #include "../config.h"
00022 #include "../wpa_supplicant_i.h"
00023 #include "../bss.h"
00024 #include "dbus_old.h"
00025 #include "dbus_old_handlers.h"
00026 #include "dbus_common.h"
00027 #include "dbus_common_i.h"
00028
00029
00040 char * wpas_dbus_decompose_object_path(const char *path, char **network,
00041 char **bssid)
00042 {
00043 const unsigned int dev_path_prefix_len =
00044 strlen(WPAS_DBUS_PATH_INTERFACES "/");
00045 char *obj_path_only;
00046 char *next_sep;
00047
00048
00049 if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/",
00050 dev_path_prefix_len))
00051 return NULL;
00052
00053
00054 if ((path + dev_path_prefix_len)[0] == '\0')
00055 return NULL;
00056
00057 obj_path_only = os_strdup(path);
00058 if (obj_path_only == NULL)
00059 return NULL;
00060
00061 next_sep = strchr(obj_path_only + dev_path_prefix_len, '/');
00062 if (next_sep != NULL) {
00063 const char *net_part = strstr(next_sep,
00064 WPAS_DBUS_NETWORKS_PART "/");
00065 const char *bssid_part = strstr(next_sep,
00066 WPAS_DBUS_BSSIDS_PART "/");
00067
00068 if (network && net_part) {
00069
00070 const char *net_name = net_part +
00071 strlen(WPAS_DBUS_NETWORKS_PART "/");
00072 *network = NULL;
00073 if (strlen(net_name))
00074 *network = os_strdup(net_name);
00075 } else if (bssid && bssid_part) {
00076
00077 const char *bssid_name = bssid_part +
00078 strlen(WPAS_DBUS_BSSIDS_PART "/");
00079 if (strlen(bssid_name))
00080 *bssid = os_strdup(bssid_name);
00081 else
00082 *bssid = NULL;
00083 }
00084
00085
00086 *next_sep = '\0';
00087 }
00088
00089 return obj_path_only;
00090 }
00091
00092
00100 DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message)
00101 {
00102 return dbus_message_new_error(message, WPAS_ERROR_INVALID_IFACE,
00103 "wpa_supplicant knows nothing about "
00104 "this interface.");
00105 }
00106
00107
00115 DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message)
00116 {
00117 return dbus_message_new_error(message, WPAS_ERROR_INVALID_NETWORK,
00118 "The requested network does not exist.");
00119 }
00120
00121
00129 static DBusMessage * wpas_dbus_new_invalid_bssid_error(DBusMessage *message)
00130 {
00131 return dbus_message_new_error(message, WPAS_ERROR_INVALID_BSSID,
00132 "The BSSID requested was invalid.");
00133 }
00134
00135
00145 static DBusMessage * wpas_dispatch_network_method(DBusMessage *message,
00146 struct wpa_supplicant *wpa_s,
00147 int network_id)
00148 {
00149 DBusMessage *reply = NULL;
00150 const char *method = dbus_message_get_member(message);
00151 struct wpa_ssid *ssid;
00152
00153 ssid = wpa_config_get_network(wpa_s->conf, network_id);
00154 if (ssid == NULL)
00155 return wpas_dbus_new_invalid_network_error(message);
00156
00157 if (!strcmp(method, "set"))
00158 reply = wpas_dbus_iface_set_network(message, wpa_s, ssid);
00159 else if (!strcmp(method, "enable"))
00160 reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid);
00161 else if (!strcmp(method, "disable"))
00162 reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid);
00163
00164 return reply;
00165 }
00166
00167
00177 static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message,
00178 struct wpa_supplicant *wpa_s,
00179 const char *bssid_txt)
00180 {
00181 u8 bssid[ETH_ALEN];
00182 struct wpa_bss *bss;
00183
00184 if (hexstr2bin(bssid_txt, bssid, ETH_ALEN) < 0)
00185 return wpas_dbus_new_invalid_bssid_error(message);
00186
00187 bss = wpa_bss_get_bssid(wpa_s, bssid);
00188 if (bss == NULL)
00189 return wpas_dbus_new_invalid_bssid_error(message);
00190
00191
00192 if (os_strcmp(dbus_message_get_member(message), "properties") == 0)
00193 return wpas_dbus_bssid_properties(message, wpa_s, bss);
00194
00195 return NULL;
00196 }
00197
00198
00209 static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection,
00210 DBusMessage *message,
00211 void *user_data)
00212 {
00213 struct wpa_supplicant *wpa_s = user_data;
00214 const char *method = dbus_message_get_member(message);
00215 const char *path = dbus_message_get_path(message);
00216 const char *msg_interface = dbus_message_get_interface(message);
00217 char *iface_obj_path = NULL;
00218 char *network = NULL;
00219 char *bssid = NULL;
00220 DBusMessage *reply = NULL;
00221
00222
00223 if (!msg_interface)
00224 goto out;
00225
00226 iface_obj_path = wpas_dbus_decompose_object_path(path, &network,
00227 &bssid);
00228 if (iface_obj_path == NULL) {
00229 reply = wpas_dbus_new_invalid_iface_error(message);
00230 goto out;
00231 }
00232
00233
00234
00235
00236 if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global,
00237 iface_obj_path) != wpa_s) {
00238 reply = wpas_dbus_new_invalid_iface_error(message);
00239 goto out;
00240 }
00241
00242 if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) {
00243
00244 int nid = strtoul(network, NULL, 10);
00245 if (errno != EINVAL)
00246 reply = wpas_dispatch_network_method(message, wpa_s,
00247 nid);
00248 else
00249 reply = wpas_dbus_new_invalid_network_error(message);
00250 } else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) {
00251
00252 reply = wpas_dispatch_bssid_method(message, wpa_s, bssid);
00253 } else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) {
00254
00255 if (!strcmp(method, "scan"))
00256 reply = wpas_dbus_iface_scan(message, wpa_s);
00257 else if (!strcmp(method, "scanResults"))
00258 reply = wpas_dbus_iface_scan_results(message, wpa_s);
00259 else if (!strcmp(method, "addNetwork"))
00260 reply = wpas_dbus_iface_add_network(message, wpa_s);
00261 else if (!strcmp(method, "removeNetwork"))
00262 reply = wpas_dbus_iface_remove_network(message, wpa_s);
00263 else if (!strcmp(method, "selectNetwork"))
00264 reply = wpas_dbus_iface_select_network(message, wpa_s);
00265 else if (!strcmp(method, "capabilities"))
00266 reply = wpas_dbus_iface_capabilities(message, wpa_s);
00267 else if (!strcmp(method, "disconnect"))
00268 reply = wpas_dbus_iface_disconnect(message, wpa_s);
00269 else if (!strcmp(method, "setAPScan"))
00270 reply = wpas_dbus_iface_set_ap_scan(message, wpa_s);
00271 else if (!strcmp(method, "setSmartcardModules"))
00272 reply = wpas_dbus_iface_set_smartcard_modules(message,
00273 wpa_s);
00274 else if (!strcmp(method, "state"))
00275 reply = wpas_dbus_iface_get_state(message, wpa_s);
00276 else if (!strcmp(method, "scanning"))
00277 reply = wpas_dbus_iface_get_scanning(message, wpa_s);
00278 else if (!strcmp(method, "setBlobs"))
00279 reply = wpas_dbus_iface_set_blobs(message, wpa_s);
00280 else if (!strcmp(method, "removeBlobs"))
00281 reply = wpas_dbus_iface_remove_blobs(message, wpa_s);
00282 #ifdef CONFIG_WPS
00283 else if (!os_strcmp(method, "wpsPbc"))
00284 reply = wpas_dbus_iface_wps_pbc(message, wpa_s);
00285 else if (!os_strcmp(method, "wpsPin"))
00286 reply = wpas_dbus_iface_wps_pin(message, wpa_s);
00287 else if (!os_strcmp(method, "wpsReg"))
00288 reply = wpas_dbus_iface_wps_reg(message, wpa_s);
00289 #endif
00290 }
00291
00292
00293 if (reply) {
00294 if (!dbus_message_get_no_reply(message))
00295 dbus_connection_send(connection, reply, NULL);
00296 dbus_message_unref(reply);
00297 }
00298
00299 out:
00300 os_free(iface_obj_path);
00301 os_free(network);
00302 os_free(bssid);
00303 return reply ? DBUS_HANDLER_RESULT_HANDLED :
00304 DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00305 }
00306
00307
00319 static DBusHandlerResult wpas_message_handler(DBusConnection *connection,
00320 DBusMessage *message, void *user_data)
00321 {
00322 struct wpas_dbus_priv *ctrl_iface = user_data;
00323 const char *method;
00324 const char *path;
00325 const char *msg_interface;
00326 DBusMessage *reply = NULL;
00327
00328 method = dbus_message_get_member(message);
00329 path = dbus_message_get_path(message);
00330 msg_interface = dbus_message_get_interface(message);
00331 if (!method || !path || !ctrl_iface || !msg_interface)
00332 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00333
00334
00335 if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0)
00336 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00337
00338 if (!strcmp(path, WPAS_DBUS_PATH)) {
00339
00340 if (!strcmp(method, "addInterface")) {
00341 reply = wpas_dbus_global_add_interface(
00342 message, ctrl_iface->global);
00343 } else if (!strcmp(method, "removeInterface")) {
00344 reply = wpas_dbus_global_remove_interface(
00345 message, ctrl_iface->global);
00346 } else if (!strcmp(method, "getInterface")) {
00347 reply = wpas_dbus_global_get_interface(
00348 message, ctrl_iface->global);
00349 } else if (!strcmp(method, "setDebugParams")) {
00350 reply = wpas_dbus_global_set_debugparams(
00351 message, ctrl_iface->global);
00352 }
00353 }
00354
00355
00356 if (reply) {
00357 if (!dbus_message_get_no_reply(message))
00358 dbus_connection_send(connection, reply, NULL);
00359 dbus_message_unref(reply);
00360 }
00361
00362 return reply ? DBUS_HANDLER_RESULT_HANDLED :
00363 DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00364 }
00365
00366
00374 void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
00375 {
00376 struct wpas_dbus_priv *iface = wpa_s->global->dbus;
00377 DBusMessage *_signal;
00378
00379
00380 if (iface == NULL)
00381 return;
00382
00383 _signal = dbus_message_new_signal(wpa_s->dbus_path,
00384 WPAS_DBUS_IFACE_INTERFACE,
00385 "ScanResultsAvailable");
00386 if (_signal == NULL) {
00387 wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan "
00388 "results signal");
00389 return;
00390 }
00391 dbus_connection_send(iface->con, _signal, NULL);
00392 dbus_message_unref(_signal);
00393 }
00394
00395
00405 void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
00406 enum wpa_states new_state,
00407 enum wpa_states old_state)
00408 {
00409 struct wpas_dbus_priv *iface;
00410 DBusMessage *_signal = NULL;
00411 const char *new_state_str, *old_state_str;
00412
00413
00414 if (wpa_s->global == NULL)
00415 return;
00416 iface = wpa_s->global->dbus;
00417 if (iface == NULL)
00418 return;
00419
00420
00421 if (new_state == old_state)
00422 return;
00423
00424 _signal = dbus_message_new_signal(wpa_s->dbus_path,
00425 WPAS_DBUS_IFACE_INTERFACE,
00426 "StateChange");
00427 if (_signal == NULL) {
00428 wpa_printf(MSG_ERROR,
00429 "dbus: wpa_supplicant_dbus_notify_state_change: "
00430 "could not create dbus signal; likely out of "
00431 "memory");
00432 return;
00433 }
00434
00435 new_state_str = wpa_supplicant_state_txt(new_state);
00436 old_state_str = wpa_supplicant_state_txt(old_state);
00437 if (new_state_str == NULL || old_state_str == NULL) {
00438 wpa_printf(MSG_ERROR,
00439 "dbus: wpa_supplicant_dbus_notify_state_change: "
00440 "Could not convert state strings");
00441 goto out;
00442 }
00443
00444 if (!dbus_message_append_args(_signal,
00445 DBUS_TYPE_STRING, &new_state_str,
00446 DBUS_TYPE_STRING, &old_state_str,
00447 DBUS_TYPE_INVALID)) {
00448 wpa_printf(MSG_ERROR,
00449 "dbus: wpa_supplicant_dbus_notify_state_change: "
00450 "Not enough memory to construct state change "
00451 "signal");
00452 goto out;
00453 }
00454
00455 dbus_connection_send(iface->con, _signal, NULL);
00456
00457 out:
00458 dbus_message_unref(_signal);
00459 }
00460
00461
00469 void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
00470 {
00471 struct wpas_dbus_priv *iface = wpa_s->global->dbus;
00472 DBusMessage *_signal;
00473 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
00474
00475
00476 if (iface == NULL)
00477 return;
00478
00479 _signal = dbus_message_new_signal(wpa_s->dbus_path,
00480 WPAS_DBUS_IFACE_INTERFACE,
00481 "Scanning");
00482 if (_signal == NULL) {
00483 wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan "
00484 "results signal");
00485 return;
00486 }
00487
00488 if (dbus_message_append_args(_signal,
00489 DBUS_TYPE_BOOLEAN, &scanning,
00490 DBUS_TYPE_INVALID)) {
00491 dbus_connection_send(iface->con, _signal, NULL);
00492 } else {
00493 wpa_printf(MSG_ERROR, "dbus: Not enough memory to construct "
00494 "signal");
00495 }
00496 dbus_message_unref(_signal);
00497 }
00498
00499
00500 #ifdef CONFIG_WPS
00501 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
00502 const struct wps_credential *cred)
00503 {
00504 struct wpas_dbus_priv *iface;
00505 DBusMessage *_signal = NULL;
00506
00507
00508 if (wpa_s->global == NULL)
00509 return;
00510 iface = wpa_s->global->dbus;
00511 if (iface == NULL)
00512 return;
00513
00514 _signal = dbus_message_new_signal(wpa_s->dbus_path,
00515 WPAS_DBUS_IFACE_INTERFACE,
00516 "WpsCred");
00517 if (_signal == NULL) {
00518 wpa_printf(MSG_ERROR,
00519 "dbus: wpa_supplicant_dbus_notify_wps_cred: "
00520 "Could not create dbus signal; likely out of "
00521 "memory");
00522 return;
00523 }
00524
00525 if (!dbus_message_append_args(_signal,
00526 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
00527 &cred->cred_attr, cred->cred_attr_len,
00528 DBUS_TYPE_INVALID)) {
00529 wpa_printf(MSG_ERROR,
00530 "dbus: wpa_supplicant_dbus_notify_wps_cred: "
00531 "Not enough memory to construct signal");
00532 goto out;
00533 }
00534
00535 dbus_connection_send(iface->con, _signal, NULL);
00536
00537 out:
00538 dbus_message_unref(_signal);
00539 }
00540 #else
00541 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
00542 const struct wps_credential *cred)
00543 {
00544 }
00545 #endif
00546
00547
00556 int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface)
00557 {
00558 DBusError error;
00559 int ret = -1;
00560 DBusObjectPathVTable wpas_vtable = {
00561 NULL, &wpas_message_handler, NULL, NULL, NULL, NULL
00562 };
00563
00564
00565 if (!dbus_connection_register_object_path(iface->con,
00566 WPAS_DBUS_PATH, &wpas_vtable,
00567 iface)) {
00568 wpa_printf(MSG_ERROR, "dbus: Could not set up message "
00569 "handler");
00570 return -1;
00571 }
00572
00573
00574 dbus_error_init(&error);
00575 switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE,
00576 0, &error)) {
00577 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
00578 ret = 0;
00579 break;
00580 case DBUS_REQUEST_NAME_REPLY_EXISTS:
00581 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
00582 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
00583 wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
00584 "already registered");
00585 break;
00586 default:
00587 wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
00588 "%s %s", error.name, error.message);
00589 break;
00590 }
00591 dbus_error_free(&error);
00592
00593 if (ret != 0)
00594 return -1;
00595
00596 wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE
00597 "'.");
00598
00599 return 0;
00600 }
00601
00602
00610 int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
00611 {
00612 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
00613 DBusConnection * con;
00614 u32 next;
00615 DBusObjectPathVTable vtable = {
00616 NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL
00617 };
00618
00619
00620 if (ctrl_iface == NULL)
00621 return 0;
00622
00623 con = ctrl_iface->con;
00624 next = ctrl_iface->next_objid++;
00625
00626
00627 wpa_s->dbus_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
00628 if (wpa_s->dbus_path == NULL)
00629 return -1;
00630 os_snprintf(wpa_s->dbus_path, WPAS_DBUS_OBJECT_PATH_MAX,
00631 WPAS_DBUS_PATH_INTERFACES "/%u",
00632 next);
00633
00634
00635 if (!dbus_connection_register_fallback(con, wpa_s->dbus_path, &vtable,
00636 wpa_s)) {
00637 wpa_printf(MSG_ERROR, "dbus: Could not set up message "
00638 "handler for interface %s", wpa_s->ifname);
00639 return -1;
00640 }
00641
00642 return 0;
00643 }
00644
00645
00653 int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
00654 {
00655 struct wpas_dbus_priv *ctrl_iface;
00656 DBusConnection *con;
00657
00658
00659 if (wpa_s == NULL || wpa_s->global == NULL)
00660 return 0;
00661 ctrl_iface = wpa_s->global->dbus;
00662 if (ctrl_iface == NULL)
00663 return 0;
00664
00665 con = ctrl_iface->con;
00666 if (!dbus_connection_unregister_object_path(con, wpa_s->dbus_path))
00667 return -1;
00668
00669 os_free(wpa_s->dbus_path);
00670 wpa_s->dbus_path = NULL;
00671
00672 return 0;
00673 }
00674
00675
00682 struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
00683 struct wpa_global *global, const char *path)
00684 {
00685 struct wpa_supplicant *wpa_s;
00686
00687 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
00688 if (strcmp(wpa_s->dbus_path, path) == 0)
00689 return wpa_s;
00690 }
00691 return NULL;
00692 }