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