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