dbus_old.c
Go to the documentation of this file.
00001 /*
00002  * WPA Supplicant / dbus-based control interface
00003  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
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         /* Be a bit paranoid about path */
00049         if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/",
00050                              dev_path_prefix_len))
00051                 return NULL;
00052 
00053         /* Ensure there's something at the end of the path */
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                         /* Deal with a request for a configured network */
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                         /* Deal with a request for a scanned BSSID */
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                 /* Cut off interface object path before "/" */
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         /* Dispatch the method call against the scanned bssid */
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         /* Caller must specify a message interface */
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         /* Make sure the message's object path actually refers to the
00234          * wpa_supplicant structure it's supposed to (which is wpa_s)
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                 /* A method for one of this interface's configured networks */
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                 /* A method for one of this interface's scanned BSSIDs */
00252                 reply = wpas_dispatch_bssid_method(message, wpa_s, bssid);
00253         } else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) {
00254                 /* A method for an interface only. */
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 /* CONFIG_WPS */
00290         }
00291 
00292         /* If the message was handled, send back the reply */
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         /* Validate the method interface */
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                 /* dispatch methods against our global dbus interface here */
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         /* If the message was handled, send back the reply */
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         /* Do nothing if the control interface is not turned on */
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         /* Do nothing if the control interface is not turned on */
00414         if (wpa_s->global == NULL)
00415                 return;
00416         iface = wpa_s->global->dbus;
00417         if (iface == NULL)
00418                 return;
00419 
00420         /* Only send signal if state really changed */
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         /* Do nothing if the control interface is not turned on */
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         /* Do nothing if the control interface is not turned on */
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 /* CONFIG_WPS */
00541 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
00542                                          const struct wps_credential *cred)
00543 {
00544 }
00545 #endif /* CONFIG_WPS */
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         /* Register the message handler for the global dbus interface */
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         /* Register our service with the message bus */
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         /* Do nothing if the control interface is not turned on */
00620         if (ctrl_iface == NULL)
00621                 return 0;
00622 
00623         con = ctrl_iface->con;
00624         next = ctrl_iface->next_objid++;
00625 
00626         /* Create and set the interface's object path */
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         /* Register the message handler for the interface functions */
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         /* Do nothing if the control interface is not turned on */
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 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:34