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