055809c2cd9537e9347e6f4ac505fafa9ec58768
[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         wpa_printf(MSG_MSGDUMP, "dbus[old/iface]: %s.%s (%s) [%s]",
220                    msg_interface, method, path,
221                    dbus_message_get_signature(message));
222
223         iface_obj_path = wpas_dbus_decompose_object_path(path, &network,
224                                                          &bssid);
225         if (iface_obj_path == NULL) {
226                 reply = wpas_dbus_new_invalid_iface_error(message);
227                 goto out;
228         }
229
230         /* Make sure the message's object path actually refers to the
231          * wpa_supplicant structure it's supposed to (which is wpa_s)
232          */
233         if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global,
234                                                   iface_obj_path) != wpa_s) {
235                 reply = wpas_dbus_new_invalid_iface_error(message);
236                 goto out;
237         }
238
239         if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) {
240                 /* A method for one of this interface's configured networks */
241                 int nid = strtoul(network, NULL, 10);
242                 if (errno != EINVAL)
243                         reply = wpas_dispatch_network_method(message, wpa_s,
244                                                              nid);
245                 else
246                         reply = wpas_dbus_new_invalid_network_error(message);
247         } else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) {
248                 /* A method for one of this interface's scanned BSSIDs */
249                 reply = wpas_dispatch_bssid_method(message, wpa_s, bssid);
250         } else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) {
251                 /* A method for an interface only. */
252                 if (!strcmp(method, "scan"))
253                         reply = wpas_dbus_iface_scan(message, wpa_s);
254                 else if (!strcmp(method, "scanResults"))
255                         reply = wpas_dbus_iface_scan_results(message, wpa_s);
256                 else if (!strcmp(method, "addNetwork"))
257                         reply = wpas_dbus_iface_add_network(message, wpa_s);
258                 else if (!strcmp(method, "removeNetwork"))
259                         reply = wpas_dbus_iface_remove_network(message, wpa_s);
260                 else if (!strcmp(method, "selectNetwork"))
261                         reply = wpas_dbus_iface_select_network(message, wpa_s);
262                 else if (!strcmp(method, "capabilities"))
263                         reply = wpas_dbus_iface_capabilities(message, wpa_s);
264                 else if (!strcmp(method, "disconnect"))
265                         reply = wpas_dbus_iface_disconnect(message, wpa_s);
266                 else if (!strcmp(method, "setAPScan"))
267                         reply = wpas_dbus_iface_set_ap_scan(message, wpa_s);
268                 else if (!strcmp(method, "setSmartcardModules"))
269                         reply = wpas_dbus_iface_set_smartcard_modules(message,
270                                                                       wpa_s);
271                 else if (!strcmp(method, "state"))
272                         reply = wpas_dbus_iface_get_state(message, wpa_s);
273                 else if (!strcmp(method, "scanning"))
274                         reply = wpas_dbus_iface_get_scanning(message, wpa_s);
275 #ifndef CONFIG_NO_CONFIG_BLOBS
276                 else if (!strcmp(method, "setBlobs"))
277                         reply = wpas_dbus_iface_set_blobs(message, wpa_s);
278                 else if (!strcmp(method, "removeBlobs"))
279                         reply = wpas_dbus_iface_remove_blobs(message, wpa_s);
280 #endif /* CONFIG_NO_CONFIG_BLOBS */
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         wpa_printf(MSG_MSGDUMP, "dbus[old]: %s.%s (%s) [%s]",
336                    msg_interface, method, path,
337                    dbus_message_get_signature(message));
338
339         /* Validate the method interface */
340         if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0)
341                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
342
343         if (!strcmp(path, WPAS_DBUS_PATH)) {
344                 /* dispatch methods against our global dbus interface here */
345                 if (!strcmp(method, "addInterface")) {
346                         reply = wpas_dbus_global_add_interface(
347                                 message, ctrl_iface->global);
348                 } else if (!strcmp(method, "removeInterface")) {
349                         reply = wpas_dbus_global_remove_interface(
350                                 message, ctrl_iface->global);
351                 } else if (!strcmp(method, "getInterface")) {
352                         reply = wpas_dbus_global_get_interface(
353                                 message, ctrl_iface->global);
354                 } else if (!strcmp(method, "setDebugParams")) {
355                         reply = wpas_dbus_global_set_debugparams(
356                                 message, ctrl_iface->global);
357                 }
358         }
359
360         /* If the message was handled, send back the reply */
361         if (reply) {
362                 if (!dbus_message_get_no_reply(message))
363                         dbus_connection_send(connection, reply, NULL);
364                 dbus_message_unref(reply);
365         }
366
367         return reply ? DBUS_HANDLER_RESULT_HANDLED :
368                 DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
369 }
370
371
372 /**
373  * wpa_supplicant_dbus_notify_scan_results - Send a scan results signal
374  * @wpa_s: %wpa_supplicant network interface data
375  * Returns: 0 on success, -1 on failure
376  *
377  * Notify listeners that this interface has updated scan results.
378  */
379 void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
380 {
381         struct wpas_dbus_priv *iface = wpa_s->global->dbus;
382         DBusMessage *_signal;
383
384         /* Do nothing if the control interface is not turned on */
385         if (iface == NULL)
386                 return;
387
388         _signal = dbus_message_new_signal(wpa_s->dbus_path,
389                                           WPAS_DBUS_IFACE_INTERFACE,
390                                           "ScanResultsAvailable");
391         if (_signal == NULL) {
392                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan "
393                            "results signal");
394                 return;
395         }
396         dbus_connection_send(iface->con, _signal, NULL);
397         dbus_message_unref(_signal);
398 }
399
400
401 /**
402  * wpa_supplicant_dbus_notify_state_change - Send a state change signal
403  * @wpa_s: %wpa_supplicant network interface data
404  * @new_state: new state wpa_supplicant is entering
405  * @old_state: old state wpa_supplicant is leaving
406  * Returns: 0 on success, -1 on failure
407  *
408  * Notify listeners that wpa_supplicant has changed state
409  */
410 void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
411                                              enum wpa_states new_state,
412                                              enum wpa_states old_state)
413 {
414         struct wpas_dbus_priv *iface;
415         DBusMessage *_signal = NULL;
416         const char *new_state_str, *old_state_str;
417
418         if (wpa_s->dbus_path == NULL)
419                 return; /* Skip signal since D-Bus setup is not yet ready */
420
421         /* Do nothing if the control interface is not turned on */
422         if (wpa_s->global == NULL)
423                 return;
424         iface = wpa_s->global->dbus;
425         if (iface == NULL)
426                 return;
427
428         /* Only send signal if state really changed */
429         if (new_state == old_state)
430                 return;
431
432         _signal = dbus_message_new_signal(wpa_s->dbus_path,
433                                           WPAS_DBUS_IFACE_INTERFACE,
434                                           "StateChange");
435         if (_signal == NULL) {
436                 wpa_printf(MSG_ERROR,
437                            "dbus: wpa_supplicant_dbus_notify_state_change: "
438                            "could not create dbus signal; likely out of "
439                            "memory");
440                 return;
441         }
442
443         new_state_str = wpa_supplicant_state_txt(new_state);
444         old_state_str = wpa_supplicant_state_txt(old_state);
445
446         if (!dbus_message_append_args(_signal,
447                                       DBUS_TYPE_STRING, &new_state_str,
448                                       DBUS_TYPE_STRING, &old_state_str,
449                                       DBUS_TYPE_INVALID)) {
450                 wpa_printf(MSG_ERROR,
451                            "dbus: wpa_supplicant_dbus_notify_state_change: "
452                            "Not enough memory to construct state change "
453                            "signal");
454                 goto out;
455         }
456
457         dbus_connection_send(iface->con, _signal, NULL);
458
459 out:
460         dbus_message_unref(_signal);
461 }
462
463
464 /**
465  * wpa_supplicant_dbus_notify_scanning - send scanning status
466  * @wpa_s: %wpa_supplicant network interface data
467  * Returns: 0 on success, -1 on failure
468  *
469  * Notify listeners of interface scanning state changes
470  */
471 void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
472 {
473         struct wpas_dbus_priv *iface = wpa_s->global->dbus;
474         DBusMessage *_signal;
475         dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
476
477         /* Do nothing if the control interface is not turned on */
478         if (iface == NULL)
479                 return;
480
481         _signal = dbus_message_new_signal(wpa_s->dbus_path,
482                                           WPAS_DBUS_IFACE_INTERFACE,
483                                           "Scanning");
484         if (_signal == NULL) {
485                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan "
486                            "results signal");
487                 return;
488         }
489
490         if (dbus_message_append_args(_signal,
491                                      DBUS_TYPE_BOOLEAN, &scanning,
492                                      DBUS_TYPE_INVALID)) {
493                 dbus_connection_send(iface->con, _signal, NULL);
494         } else {
495                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to construct "
496                            "signal");
497         }
498         dbus_message_unref(_signal);
499 }
500
501
502 #ifdef CONFIG_WPS
503 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
504                                          const struct wps_credential *cred)
505 {
506         struct wpas_dbus_priv *iface;
507         DBusMessage *_signal = NULL;
508
509         /* Do nothing if the control interface is not turned on */
510         if (wpa_s->global == NULL)
511                 return;
512         iface = wpa_s->global->dbus;
513         if (iface == NULL)
514                 return;
515
516         _signal = dbus_message_new_signal(wpa_s->dbus_path,
517                                           WPAS_DBUS_IFACE_INTERFACE,
518                                           "WpsCred");
519         if (_signal == NULL) {
520                 wpa_printf(MSG_ERROR,
521                            "dbus: wpa_supplicant_dbus_notify_wps_cred: "
522                            "Could not create dbus signal; likely out of "
523                            "memory");
524                 return;
525         }
526
527         if (!dbus_message_append_args(_signal,
528                                       DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
529                                       &cred->cred_attr, cred->cred_attr_len,
530                                       DBUS_TYPE_INVALID)) {
531                 wpa_printf(MSG_ERROR,
532                            "dbus: wpa_supplicant_dbus_notify_wps_cred: "
533                            "Not enough memory to construct signal");
534                 goto out;
535         }
536
537         dbus_connection_send(iface->con, _signal, NULL);
538
539 out:
540         dbus_message_unref(_signal);
541 }
542 #else /* CONFIG_WPS */
543 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
544                                          const struct wps_credential *cred)
545 {
546 }
547 #endif /* CONFIG_WPS */
548
549 void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
550                                               int depth, const char *subject,
551                                               const char *cert_hash,
552                                               const struct wpabuf *cert)
553 {
554         struct wpas_dbus_priv *iface;
555         DBusMessage *_signal = NULL;
556         const char *hash;
557         const char *cert_hex;
558         int cert_hex_len;
559
560         /* Do nothing if the control interface is not turned on */
561         if (wpa_s->global == NULL)
562                 return;
563         iface = wpa_s->global->dbus;
564         if (iface == NULL)
565                 return;
566
567         _signal = dbus_message_new_signal(wpa_s->dbus_path,
568                                           WPAS_DBUS_IFACE_INTERFACE,
569                                           "Certification");
570         if (_signal == NULL) {
571                 wpa_printf(MSG_ERROR,
572                            "dbus: wpa_supplicant_dbus_notify_certification: "
573                            "Could not create dbus signal; likely out of "
574                            "memory");
575                 return;
576         }
577
578         hash = cert_hash ? cert_hash : "";
579         cert_hex = cert ? wpabuf_head(cert) : "";
580         cert_hex_len = cert ? wpabuf_len(cert) : 0;
581
582         if (!dbus_message_append_args(_signal,
583                                       DBUS_TYPE_INT32,&depth,
584                                       DBUS_TYPE_STRING, &subject,
585                                       DBUS_TYPE_STRING, &hash,
586                                       DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
587                                       &cert_hex, cert_hex_len,
588                                       DBUS_TYPE_INVALID)) {
589                 wpa_printf(MSG_ERROR,
590                            "dbus: wpa_supplicant_dbus_notify_certification: "
591                            "Not enough memory to construct signal");
592                 goto out;
593         }
594
595         dbus_connection_send(iface->con, _signal, NULL);
596
597 out:
598         dbus_message_unref(_signal);
599
600 }
601
602
603 /**
604  * wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface
605  * @global: Pointer to global data from wpa_supplicant_init()
606  * Returns: 0 on success, -1 on failure
607  *
608  * Initialize the dbus control interface and start receiving commands from
609  * external programs over the bus.
610  */
611 int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface)
612 {
613         DBusError error;
614         int ret = -1;
615         DBusObjectPathVTable wpas_vtable = {
616                 NULL, &wpas_message_handler, NULL, NULL, NULL, NULL
617         };
618
619         /* Register the message handler for the global dbus interface */
620         if (!dbus_connection_register_object_path(iface->con,
621                                                   WPAS_DBUS_PATH, &wpas_vtable,
622                                                   iface)) {
623                 wpa_printf(MSG_ERROR, "dbus: Could not set up message "
624                            "handler");
625                 return -1;
626         }
627
628         /* Register our service with the message bus */
629         dbus_error_init(&error);
630         switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE,
631                                       0, &error)) {
632         case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
633                 ret = 0;
634                 break;
635         case DBUS_REQUEST_NAME_REPLY_EXISTS:
636         case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
637         case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
638                 wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
639                            "already registered");
640                 break;
641         default:
642                 wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
643                            "%s %s", error.name, error.message);
644                 break;
645         }
646         dbus_error_free(&error);
647
648         if (ret != 0)
649                 return -1;
650
651         wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE
652                    "'.");
653
654         return 0;
655 }
656
657
658 /**
659  * wpas_dbus_register_new_iface - Register a new interface with dbus
660  * @wpa_s: %wpa_supplicant interface description structure to register
661  * Returns: 0 on success, -1 on error
662  *
663  * Registers a new interface with dbus and assigns it a dbus object path.
664  */
665 int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
666 {
667         struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
668         DBusConnection * con;
669         u32 next;
670         DBusObjectPathVTable vtable = {
671                 NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL
672         };
673
674         /* Do nothing if the control interface is not turned on */
675         if (ctrl_iface == NULL)
676                 return 0;
677
678         con = ctrl_iface->con;
679         next = ctrl_iface->next_objid++;
680
681         /* Create and set the interface's object path */
682         wpa_s->dbus_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
683         if (wpa_s->dbus_path == NULL)
684                 return -1;
685         os_snprintf(wpa_s->dbus_path, WPAS_DBUS_OBJECT_PATH_MAX,
686                     WPAS_DBUS_PATH_INTERFACES "/%u",
687                     next);
688
689         /* Register the message handler for the interface functions */
690         if (!dbus_connection_register_fallback(con, wpa_s->dbus_path, &vtable,
691                                                wpa_s)) {
692                 wpa_printf(MSG_ERROR, "dbus: Could not set up message "
693                            "handler for interface %s", wpa_s->ifname);
694                 return -1;
695         }
696
697         return 0;
698 }
699
700
701 /**
702  * wpas_dbus_unregister_iface - Unregister an interface from dbus
703  * @wpa_s: wpa_supplicant interface structure
704  * Returns: 0 on success, -1 on failure
705  *
706  * Unregisters the interface with dbus
707  */
708 int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
709 {
710         struct wpas_dbus_priv *ctrl_iface;
711         DBusConnection *con;
712
713         /* Do nothing if the control interface is not turned on */
714         if (wpa_s == NULL || wpa_s->global == NULL)
715                 return 0;
716         ctrl_iface = wpa_s->global->dbus;
717         if (ctrl_iface == NULL)
718                 return 0;
719
720         con = ctrl_iface->con;
721         if (!dbus_connection_unregister_object_path(con, wpa_s->dbus_path))
722                 return -1;
723
724         os_free(wpa_s->dbus_path);
725         wpa_s->dbus_path = NULL;
726
727         return 0;
728 }
729
730
731 /**
732  * wpa_supplicant_get_iface_by_dbus_path - Get a new network interface
733  * @global: Pointer to global data from wpa_supplicant_init()
734  * @path: Pointer to a dbus object path representing an interface
735  * Returns: Pointer to the interface or %NULL if not found
736  */
737 struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
738         struct wpa_global *global, const char *path)
739 {
740         struct wpa_supplicant *wpa_s;
741
742         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
743                 if (strcmp(wpa_s->dbus_path, path) == 0)
744                         return wpa_s;
745         }
746         return NULL;
747 }