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