wpa_supplicant: new DBus API implementation
[libeap.git] / wpa_supplicant / ctrl_iface_dbus_new.c
1 /*
2  * WPA Supplicant / dbus-based control interface
3  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4  * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Alternatively, this software may be distributed under the terms of BSD
11  * license.
12  *
13  * See README and COPYING for more details.
14  */
15
16 #include "includes.h"
17
18 #include "common.h"
19 #include "config.h"
20 #include "wpa_supplicant_i.h"
21 #include "drivers/driver.h"
22 #include "wps/wps.h"
23 #include "ctrl_iface_dbus_new_helpers.h"
24 #include "dbus_dict_helpers.h"
25 #include "ctrl_iface_dbus_new.h"
26 #include "ctrl_iface_dbus_new_handlers.h"
27
28 /**
29  * wpas_dbus_set_path - Assign a dbus path to an interface
30  * @wpa_s: wpa_supplicant interface structure
31  * @path: dbus path to set on the interface
32  * Returns: 0 on succes, -1 on error
33  */
34 static int wpas_dbus_set_path(struct wpa_supplicant *wpa_s,
35                               const char *path)
36 {
37         u32 len = os_strlen(path);
38         if (len >= WPAS_DBUS_OBJECT_PATH_MAX)
39                 return -1;
40         if (wpa_s->dbus_new_path)
41                 return -1;
42         wpa_s->dbus_new_path = os_strdup(path);
43         return 0;
44 }
45
46
47 /**
48  * wpas_dbus_signal_interface - Send a interface related event signal
49  * @wpa_s: %wpa_supplicant network interface data
50  * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
51  *
52  * Notify listeners about event related with interface
53  */
54 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
55                                        const char *sig_name)
56 {
57         struct ctrl_iface_dbus_new_priv *iface;
58         DBusMessage *_signal;
59         const char *path;
60
61         iface = wpa_s->global->dbus_new_ctrl_iface;
62
63         /* Do nothing if the control interface is not turned on */
64         if (iface == NULL)
65                 return;
66
67         path = wpas_dbus_get_path(wpa_s);
68         if (path == NULL) {
69                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
70                            "Interface doesn't have a dbus path. "
71                            "Can't send signal.");
72                 return;
73         }
74         _signal = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
75                                           WPAS_DBUS_NEW_INTERFACE, sig_name);
76         if (_signal == NULL) {
77                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
78                            "enough memory to send scan results signal.");
79                 return;
80         }
81
82         if (dbus_message_append_args(_signal, DBUS_TYPE_OBJECT_PATH, &path,
83                                      DBUS_TYPE_INVALID)) {
84                 dbus_connection_send(iface->con, _signal, NULL);
85         } else {
86                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
87                            "not enough memory to construct signal.");
88         }
89         dbus_message_unref(_signal);
90 }
91
92
93 /**
94  * wpas_dbus_signal_interface_created - Send a interface created signal
95  * @wpa_s: %wpa_supplicant network interface data
96  *
97  * Notify listeners about creating new interface
98  */
99 static void wpas_dbus_signal_interface_created(struct wpa_supplicant *wpa_s)
100 {
101         wpas_dbus_signal_interface(wpa_s, "InterfaceCreated");
102 }
103
104
105 /**
106  * wpas_dbus_signal_interface_removed - Send a interface removed signal
107  * @wpa_s: %wpa_supplicant network interface data
108  *
109  * Notify listeners about removing interface
110  */
111 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
112 {
113         wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved");
114
115 }
116
117
118 /**
119  * wpas_dbus_signal_scan_done - send scan done signal
120  * @wpa_s: %wpa_supplicant network interface data
121  * @success: indicates if scanning succeed or failed
122  *
123  * Notify listeners about finishing a scan
124  */
125 static void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
126                                        int success)
127 {
128         struct ctrl_iface_dbus_new_priv *iface;
129         DBusMessage *_signal;
130         const char *path;
131         dbus_bool_t succ;
132
133         iface = wpa_s->global->dbus_new_ctrl_iface;
134
135         /* Do nothing if the control interface is not turned on */
136         if (iface == NULL)
137                 return;
138
139         path = wpas_dbus_get_path(wpa_s);
140         if (path == NULL) {
141                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
142                            "Interface doesn't have a dbus path. "
143                            "Can't send signal.");
144                 return;
145         }
146         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
147                                           "ScanDone");
148         if (_signal == NULL) {
149                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
150                            "enough memory to send signal.");
151                 return;
152         }
153
154         succ = success ? TRUE : FALSE;
155         if (dbus_message_append_args(_signal, DBUS_TYPE_BOOLEAN, &succ,
156                                      DBUS_TYPE_INVALID)) {
157                 dbus_connection_send(iface->con, _signal, NULL);
158         } else {
159                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
160                            "not enough memory to construct signal.");
161         }
162         dbus_message_unref(_signal);
163 }
164
165
166 /**
167  * wpas_dbus_signal_blob - Send a BSS related event signal
168  * @wpa_s: %wpa_supplicant network interface data
169  * @bss_obj_path: BSS object path
170  * @sig_name: signal name - BSSAdded or BSSRemoved
171  *
172  * Notify listeners about event related with BSS
173  */
174 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
175                                  const char *bss_obj_path,
176                                  const char *sig_name)
177 {
178         struct ctrl_iface_dbus_new_priv *iface;
179         DBusMessage *_signal;
180         const char *path;
181
182         iface = wpa_s->global->dbus_new_ctrl_iface;
183
184         /* Do nothing if the control interface is not turned on */
185         if (iface == NULL)
186                 return;
187
188         path = wpas_dbus_get_path(wpa_s);
189         if (path == NULL) {
190                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
191                            "Interface doesn't have a dbus path. "
192                            "Can't send signal.");
193                 return;
194         }
195         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
196                                           sig_name);
197         if (_signal == NULL) {
198                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
199                            "enough memory to send signal.");
200                 return;
201         }
202
203         if (dbus_message_append_args(_signal, DBUS_TYPE_OBJECT_PATH,
204                                      &bss_obj_path, DBUS_TYPE_INVALID)) {
205                 dbus_connection_send(iface->con, _signal, NULL);
206         } else {
207                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
208                            "not enough memory to construct signal.");
209         }
210         dbus_message_unref(_signal);
211 }
212
213
214 /**
215  * wpas_dbus_signal_bss_added - Send a BSS added signal
216  * @wpa_s: %wpa_supplicant network interface data
217  * @bss_obj_path: new BSS object path
218  *
219  * Notify listeners about adding new BSS
220  */
221 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
222                                        const char *bss_obj_path)
223 {
224         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded");
225 }
226
227
228 /**
229  * wpas_dbus_signal_bss_removed - Send a BSS removed signal
230  * @wpa_s: %wpa_supplicant network interface data
231  * @bss_obj_path: BSS object path
232  *
233  * Notify listeners about removing BSS
234  */
235 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
236                                          const char *bss_obj_path)
237 {
238         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved");
239 }
240
241
242 /**
243  * wpas_dbus_signal_blob - Send a blob related event signal
244  * @wpa_s: %wpa_supplicant network interface data
245  * @name: blob name
246  * @sig_name: signal name - BlobAdded or BlobRemoved
247  *
248  * Notify listeners about event related with blob
249  */
250 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
251                                   const char *name, const char *sig_name)
252 {
253         struct ctrl_iface_dbus_new_priv *iface;
254         DBusMessage *_signal;
255         const char *path;
256
257         iface = wpa_s->global->dbus_new_ctrl_iface;
258
259         /* Do nothing if the control interface is not turned on */
260         if (iface == NULL)
261                 return;
262
263         path = wpas_dbus_get_path(wpa_s);
264         if (path == NULL) {
265                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
266                            "Interface doesn't have a dbus path. "
267                            "Can't send signal.");
268                 return;
269         }
270         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
271                                           sig_name);
272         if (_signal == NULL) {
273                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
274                            "enough memory to send signal.");
275                 return;
276         }
277
278         if (dbus_message_append_args(_signal, DBUS_TYPE_STRING, &name,
279                                      DBUS_TYPE_INVALID)) {
280                 dbus_connection_send(iface->con, _signal, NULL);
281         } else {
282                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
283                            "not enough memory to construct signal.");
284         }
285         dbus_message_unref(_signal);
286 }
287
288
289 /**
290  * wpas_dbus_signal_blob_added - Send a blob added signal
291  * @wpa_s: %wpa_supplicant network interface data
292  * @name: blob name
293  *
294  * Notify listeners about adding a new blob
295  */
296 static void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
297                                         const char *name)
298 {
299         wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
300 }
301
302
303 /**
304  * wpas_dbus_signal_blob_removed - Send a blob removed signal
305  * @wpa_s: %wpa_supplicant network interface data
306  * @name: blob name
307  *
308  * Notify listeners about removing blob
309  */
310 static void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
311                                           const char *name)
312 {
313         wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
314 }
315
316
317 /**
318  * wpas_dbus_signal_network - Send a network related event signal
319  * @wpa_s: %wpa_supplicant network interface data
320  * @id: new network id
321  * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
322  *
323  * Notify listeners about event related with configured network
324  */
325 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
326                                      int id, const char *sig_name)
327 {
328         struct ctrl_iface_dbus_new_priv *iface;
329         DBusMessage *_signal;
330         const char *path;
331         char *net_obj_path;
332
333         iface = wpa_s->global->dbus_new_ctrl_iface;
334
335         /* Do nothing if the control interface is not turned on */
336         if (iface == NULL)
337                 return;
338
339         path = wpas_dbus_get_path(wpa_s);
340         if (path == NULL) {
341                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
342                            "Interface doesn't have a dbus path. "
343                            "Can't send signal.");
344                 return;
345         }
346
347         net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
348         if (net_obj_path == NULL)
349                 return;
350         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
351                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path, id);
352
353         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
354                                           sig_name);
355         if (_signal == NULL) {
356                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
357                            "enough memory to send signal.");
358                 os_free(net_obj_path);
359                 return;
360         }
361
362         if (dbus_message_append_args(_signal, DBUS_TYPE_OBJECT_PATH,
363                                      &net_obj_path, DBUS_TYPE_INVALID)) {
364                 dbus_connection_send(iface->con, _signal, NULL);
365         } else {
366                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
367                            "not enough memory to construct signal.");
368         }
369
370         os_free(net_obj_path);
371         dbus_message_unref(_signal);
372 }
373
374
375 /**
376  * wpas_dbus_signal_network_added - Send a network added signal
377  * @wpa_s: %wpa_supplicant network interface data
378  * @id: new network id
379  *
380  * Notify listeners about adding new network
381  */
382 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
383                                            int id)
384 {
385         wpas_dbus_signal_network(wpa_s, id, "NetworkAdded");
386 }
387
388
389 /**
390  * wpas_dbus_signal_network_added - Send a network removed signal
391  * @wpa_s: %wpa_supplicant network interface data
392  * @id: network id
393  *
394  * Notify listeners about removing a network
395  */
396 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
397                                              int id)
398 {
399         wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved");
400 }
401
402
403 /**
404  * wpas_dbus_signal_network_selected - Send a network selected signal
405  * @wpa_s: %wpa_supplicant network interface data
406  * @id: network id
407  *
408  * Notify listeners about selecting a network
409  */
410 static void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s,
411                                               int id)
412 {
413         wpas_dbus_signal_network(wpa_s, id, "NetworkSelected");
414 }
415
416
417 /**
418  * wpas_dbus_signal_state_changed - Send a state changed signal
419  * @wpa_s: %wpa_supplicant network interface data
420  * @new_state: new state wpa_supplicant is entering
421  * @old_state: old state wpa_supplicant is leaving
422  *
423  * Notify listeners that wpa_supplicant has changed state
424  */
425 static void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s,
426                                            wpa_states new_state,
427                                            wpa_states old_state)
428 {
429         struct ctrl_iface_dbus_new_priv *iface;
430         DBusMessage *_signal = NULL;
431         const char *path;
432         char *new_state_str, *old_state_str;
433         char *tmp;
434
435         /* Do nothing if the control interface is not turned on */
436         if (wpa_s->global == NULL)
437                 return;
438         iface = wpa_s->global->dbus_new_ctrl_iface;
439         if (iface == NULL)
440                 return;
441
442         /* Only send signal if state really changed */
443         if (new_state == old_state)
444                 return;
445
446         path = wpas_dbus_get_path(wpa_s);
447         if (path == NULL) {
448                 perror("wpas_dbus_signal_state_changed[dbus]: "
449                        "interface didn't have a dbus path");
450                 wpa_printf(MSG_ERROR,
451                            "wpas_dbus_signal_state_changed[dbus]: "
452                            "interface didn't have a dbus path; can't send "
453                            "signal.");
454                 return;
455         }
456         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
457                                           "StateChanged");
458         if (_signal == NULL) {
459                 perror("wpas_dbus_signal_state_changed[dbus]: "
460                        "couldn't create dbus signal; likely out of memory");
461                 wpa_printf(MSG_ERROR,
462                            "wpas_dbus_signal_state_changed[dbus]: "
463                            "couldn't create dbus signal; likely out of "
464                            "memory.");
465                 return;
466         }
467
468         new_state_str = os_strdup(wpa_supplicant_state_txt(new_state));
469         old_state_str = os_strdup(wpa_supplicant_state_txt(old_state));
470         if (new_state_str == NULL || old_state_str == NULL) {
471                 perror("wpas_dbus_signal_state_changed[dbus]: "
472                        "couldn't convert state strings");
473                 wpa_printf(MSG_ERROR,
474                            "wpas_dbus_signal_state_changed[dbus]: "
475                            "couldn't convert state strings.");
476                 goto out;
477         }
478
479         /* make state string lowercase to fit new DBus API convention */
480         tmp = new_state_str;
481         while (*tmp) {
482                 *tmp = tolower(*tmp);
483                 tmp++;
484         }
485         tmp = old_state_str;
486         while (*tmp) {
487                 *tmp = tolower(*tmp);
488                 tmp++;
489         }
490
491         if (!dbus_message_append_args(_signal,
492                                       DBUS_TYPE_STRING, &new_state_str,
493                                       DBUS_TYPE_STRING, &old_state_str,
494                                       DBUS_TYPE_INVALID)) {
495                 perror("wpas_dbus_signal_state_changed[dbus]: "
496                        "not enough memory to construct state change signal.");
497                 wpa_printf(MSG_ERROR,
498                            "wpas_dbus_signal_state_changed[dbus]: "
499                            "not enough memory to construct state change "
500                            "signal.");
501                 goto out;
502         }
503
504         dbus_connection_send(iface->con, _signal, NULL);
505
506 out:
507         dbus_message_unref(_signal);
508         os_free(new_state_str);
509         os_free(old_state_str);
510 }
511
512
513 /**
514  * wpas_dbus_signal_state_changed - Signals that Enabled property changed
515  * @wpa_s: %wpa_supplicant network interface data
516  * @ssid: configured network which Enabled property has changed
517  *
518  * Sends PropertyChanged signals containing new value of Enabled property
519  * for specified network
520  */
521 static void wpas_dbus_signal_network_enabled_changed(
522         struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
523 {
524
525         struct network_handler_args args = {wpa_s, ssid};
526
527         char path[WPAS_DBUS_OBJECT_PATH_MAX];
528         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
529                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
530                     wpas_dbus_get_path(wpa_s), ssid->id);
531
532         wpa_dbus_signal_property_changed(wpa_s->global->dbus_new_ctrl_iface,
533                                          (WPADBusPropertyAccessor)
534                                          wpas_dbus_getter_enabled, &args,
535                                          path, WPAS_DBUS_NEW_IFACE_NETWORK,
536                                          "Enabled");
537 }
538
539
540 #ifdef CONFIG_WPS
541
542 /**
543  * wpas_dbus_signal_wps_event_success - Signals Success WPS event
544  * @wpa_s: %wpa_supplicant network interface data
545  *
546  * Sends Event dbus signal with name "success" and empty dict as arguments
547  */
548 static void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
549 {
550
551         DBusMessage * _signal = NULL;
552         DBusMessageIter iter, dict_iter;
553         struct ctrl_iface_dbus_new_priv *iface;
554         char *key = "success";
555         const char * path;
556
557         iface = wpa_s->global->dbus_new_ctrl_iface;
558
559         /* Do nothing if the control interface is not turned on */
560         if (iface == NULL)
561                 return;
562
563         path = wpas_dbus_get_path(wpa_s);
564         if (!path) {
565                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
566                            "[dbus]: interface has no dbus path set");
567                 return;
568         }
569
570         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
571                                           "Event");
572         if (!_signal) {
573                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
574                            "[dbus]: out of memory when creating a signal");
575                 return;
576         }
577
578         dbus_message_iter_init_append(_signal, &iter);
579
580         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
581             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
582             !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
583                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
584                            "[dbus]: out of memory");
585                 goto out;
586         }
587
588         dbus_connection_send(iface->con, _signal, NULL);
589 out:
590         dbus_message_unref(_signal);
591 }
592
593
594 /**
595  * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
596  * @wpa_s: %wpa_supplicant network interface data
597  *
598  * Sends Event dbus signal with name "fail" and dictionary containing
599  * "msg field with fail message number (int32) as arguments
600  */
601 static void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
602                                             struct wps_event_fail *fail)
603 {
604
605         DBusMessage * _signal = NULL;
606         DBusMessageIter iter, dict_iter;
607         struct ctrl_iface_dbus_new_priv *iface;
608         char* key = "fail";
609         const char * path;
610
611         iface = wpa_s->global->dbus_new_ctrl_iface;
612
613         /* Do nothing if the control interface is not turned on */
614         if (iface == NULL)
615                 return;
616
617         path = wpas_dbus_get_path(wpa_s);
618         if (!path) {
619                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
620                            "interface has no dbus path set");
621                 return;
622         }
623
624         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
625                                           "Event");
626         if (!_signal) {
627                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
628                            "out of memory when creating a signal");
629                 return;
630         }
631
632         dbus_message_iter_init_append(_signal, &iter);
633
634         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
635             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
636             !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
637             !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
638                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
639                            "out of memory");
640                 goto out;
641         }
642
643         dbus_connection_send(iface->con, _signal, NULL);
644 out:
645         dbus_message_unref(_signal);
646 }
647
648
649 /**
650  * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
651  * @wpa_s: %wpa_supplicant network interface data
652  *
653  * Sends Event dbus signal with name "m2d" and dictionary containing
654  * fields of wps_event_m2d structure.
655  */
656 static void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
657                                            struct wps_event_m2d *m2d)
658 {
659
660         DBusMessage * _signal = NULL;
661         DBusMessageIter iter, dict_iter;
662         struct ctrl_iface_dbus_new_priv *iface;
663         char* key = "m2d";
664         const char * path;
665
666         iface = wpa_s->global->dbus_new_ctrl_iface;
667
668         /* Do nothing if the control interface is not turned on */
669         if (iface == NULL)
670                 return;
671
672         path = wpas_dbus_get_path(wpa_s);
673         if (!path) {
674                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
675                            "interface has no dbus path set");
676                 return;
677         }
678
679         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
680                                           "Event");
681         if (!_signal) {
682                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
683                            "out of memory when creating a signal");
684                 return;
685         }
686
687         dbus_message_iter_init_append(_signal, &iter);
688
689         if (!(dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) &&
690               wpa_dbus_dict_open_write(&iter, &dict_iter) &&
691               wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
692                                           m2d->config_methods) &&
693               wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
694                                               (const char *) m2d->manufacturer,
695                                               m2d->manufacturer_len) &&
696               wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
697                                               (const char *) m2d->model_name,
698                                               m2d->model_name_len) &&
699               wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
700                                               (const char *) m2d->model_number,
701                                               m2d->model_number_len) &&
702               wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
703                                               (const char *)
704                                               m2d->serial_number,
705                                               m2d->serial_number_len) &&
706               wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
707                                               (const char *) m2d->dev_name,
708                                               m2d->dev_name_len) &&
709               wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
710                                               (const char *)
711                                               m2d->primary_dev_type, 8) &&
712               wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
713                                           m2d->config_error) &&
714               wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
715                                           m2d->dev_password_id) &&
716               wpa_dbus_dict_close_write(&iter, &dict_iter))) {
717                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
718                            "out of memory");
719                 goto out;
720         }
721
722         dbus_connection_send(iface->con, _signal, NULL);
723 out:
724         dbus_message_unref(_signal);
725 }
726
727
728 /**
729  * wpas_dbus_signal_wps_cred - Signals new credentials
730  * @wpa_s: %wpa_supplicant network interface data
731  *
732  * Sends signal with credentials in directory argument
733  */
734 static void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
735                                       const struct wps_credential *cred)
736 {
737         DBusMessage *_signal = NULL;
738         DBusMessageIter iter, dict_iter;
739         struct ctrl_iface_dbus_new_priv *iface;
740         const char *path;
741         char *auth_type[6]; /* we have six possible authorization types */
742         int at_num = 0;
743         char *encr_type[4]; /* we have four possible encryption types */
744         int et_num = 0;
745
746         iface = wpa_s->global->dbus_new_ctrl_iface;
747
748         /* Do nothing if the control interface is not turned on */
749         if (iface == NULL)
750                 return;
751
752         path = wpas_dbus_get_path(wpa_s);
753         if (!path) {
754                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
755                            "interface has no dbus path set");
756                 return;
757         }
758
759         _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
760                                           "Credentials");
761         if (!_signal) {
762                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
763                            "out of memory when creating a signal");
764                 return;
765         }
766
767         dbus_message_iter_init_append(_signal, &iter);
768
769         if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
770                 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
771                        "when opening a dictionary");
772                 goto nomem;
773         }
774
775         if (cred->auth_type & WPS_AUTH_OPEN)
776                 auth_type[at_num++] = "open";
777         if (cred->auth_type & WPS_AUTH_WPAPSK)
778                 auth_type[at_num++] = "wpa-psk";
779         if (cred->auth_type & WPS_AUTH_SHARED)
780                 auth_type[at_num++] = "shared";
781         if (cred->auth_type & WPS_AUTH_WPA)
782                 auth_type[at_num++] = "wpa-eap";
783         if (cred->auth_type & WPS_AUTH_WPA2)
784                 auth_type[at_num++] = "wpa2-eap";
785         if (cred->auth_type & WPS_AUTH_WPA2PSK)
786                 auth_type[at_num++] =
787                 "wpa2-psk";
788
789         if (cred->encr_type & WPS_ENCR_NONE)
790                 encr_type[et_num++] = "none";
791         if (cred->encr_type & WPS_ENCR_WEP)
792                 encr_type[et_num++] = "wep";
793         if (cred->encr_type & WPS_ENCR_TKIP)
794                 encr_type[et_num++] = "tkip";
795         if (cred->encr_type & WPS_ENCR_AES)
796                 encr_type[et_num++] = "aes";
797
798         if (wpa_s->current_ssid) {
799                 if (!wpa_dbus_dict_append_byte_array(
800                             &dict_iter, "BSSID",
801                             (const char *) wpa_s->current_ssid->bssid,
802                             ETH_ALEN)) {
803                         perror("wpas_dbus_signal_wps_cred[dbus]: out of "
804                                "memory when appending bssid to dictionary");
805                         goto nomem;
806                 }
807         }
808
809         if (!(wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
810                                               (const char *) cred->ssid,
811                                               cred->ssid_len) &&
812               wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
813                                                 (const char **) auth_type,
814                                                 at_num) &&
815               wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
816                                                 (const char **) encr_type,
817                                                 et_num) &&
818               wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
819                                               (const char *) cred->key,
820                                               cred->key_len) &&
821               wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
822                                           cred->key_idx))) {
823                 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
824                        "when appending to dictionary");
825                 goto nomem;
826         }
827
828         if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
829                 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
830                        "when closing a dictionary");
831                 goto nomem;
832         }
833
834         dbus_connection_send(iface->con, _signal, NULL);
835
836 nomem:
837         dbus_message_unref(_signal);
838 }
839
840 #endif /* CONFIG_WPS */
841
842
843 /**
844  * wpas_dbus_signal_prop_changed - Signals change of property
845  * @wpa_s: %wpa_supplicant network interface data
846  * @property: indicates which property has changed
847  *
848  * Sends ProertyChanged signals with path, interface and arguments
849  * depending on which property has changed.
850  */
851 static void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
852                                           enum wpas_dbus_prop property)
853 {
854         WPADBusPropertyAccessor getter;
855         char *iface;
856         char *prop;
857         void *arg;
858
859         switch (property) {
860         case WPAS_DBUS_PROP_AP_SCAN:
861                 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
862                 arg = wpa_s;
863                 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
864                 prop = "ApScan";
865                 break;
866         case WPAS_DBUS_PROP_SCANNING:
867                 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
868                 arg = wpa_s;
869                 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
870                 prop = "Scanning";
871                 break;
872         case WPAS_DBUS_PROP_CURRENT_BSS:
873                 getter = (WPADBusPropertyAccessor)
874                         wpas_dbus_getter_current_bss;
875                 arg = wpa_s;
876                 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
877                 prop = "CurrentBSS";
878                 break;
879         case WPAS_DBUS_PROP_CURRENT_NETWORK:
880                 getter = (WPADBusPropertyAccessor)
881                         wpas_dbus_getter_current_network;
882                 arg = wpa_s;
883                 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
884                 prop = "CurrentNetwork";
885                 break;
886         default:
887                 wpa_printf(MSG_ERROR, "wpas_dbus_signal_prop_changed[dbus]: "
888                            "Unknown Property enum value %d", property);
889                 return;
890         }
891
892         wpa_dbus_signal_property_changed(wpa_s->global->dbus_new_ctrl_iface,
893                                          getter, arg,
894                                          wpas_dbus_get_path(wpa_s), iface,
895                                          prop);
896 }
897
898
899 /**
900  * wpas_dbus_signal_debug_params_changed - Signals change of debug params
901  * @global: wpa_global structure
902  *
903  * Sends ProertyChanged signals informing that debug params has changed.
904  */
905 static void wpas_dbus_signal_debug_params_changed(struct wpa_global *global)
906 {
907
908         wpa_dbus_signal_property_changed(global->dbus_new_ctrl_iface,
909                                          (WPADBusPropertyAccessor)
910                                          wpas_dbus_getter_debug_params,
911                                          global, WPAS_DBUS_NEW_PATH,
912                                          WPAS_DBUS_NEW_INTERFACE,
913                                          "DebugParams");
914 }
915
916
917 /**
918  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
919  * @global: Pointer to global data from wpa_supplicant_init()
920  * Returns: Pointer to dbus_new_ctrl_iface date or %NULL on failure
921  *
922  * Initialize the dbus control interface for wpa_supplicantand and start
923  * receiving commands from external programs over the bus.
924  */
925 static struct ctrl_iface_dbus_new_priv * wpas_dbus_ctrl_iface_init(
926         struct wpa_global *global)
927 {
928         struct ctrl_iface_dbus_new_priv *ctrl_iface;
929         struct wpa_dbus_object_desc *obj_desc;
930         /* register methods */
931         struct wpa_dbus_argument margs1[] = {
932                 { "args", "a{sv}", ARG_IN },
933                 { "path", "o", ARG_OUT },
934                 END_ARGS
935         };
936         struct wpa_dbus_argument margs2[] = {
937                 { "path", "o", ARG_IN },
938                 END_ARGS
939         };
940         struct wpa_dbus_argument margs3[] = {
941                 { "ifname", "s", ARG_IN },
942                 { "path", "o", ARG_OUT },
943                 END_ARGS
944         };
945         struct wpa_dbus_argument sargs1[] = {
946                 { "path", "o", ARG_OUT },
947                 END_ARGS
948         };
949         struct wpa_dbus_argument sargs2[] = {
950                 { "path", "o", ARG_OUT },
951                 END_ARGS
952         };
953         struct wpa_dbus_argument sargs3[] = {
954                 { "properties", "a{sv}", ARG_OUT },
955                 END_ARGS
956         };
957
958         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
959         if (!obj_desc) {
960                 wpa_printf(MSG_ERROR, "Not enough memory "
961                            "to create object description");
962                 return NULL;
963         }
964
965         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
966                                      "CreateInterface",
967                                      (WPADBusMethodHandler)
968                                      &wpas_dbus_handler_create_interface,
969                                      global, NULL, margs1)) {
970                 wpa_printf(MSG_ERROR,
971                            "Failed to register dbus method %s"
972                            "in interface %s", "CreateInterface",
973                            WPAS_DBUS_NEW_INTERFACE);
974         }
975
976         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
977                         "RemoveInterface",
978                                      (WPADBusMethodHandler)
979                                      &wpas_dbus_handler_remove_interface,
980                                      global, NULL, margs2)) {
981                 wpa_printf(MSG_ERROR,
982                            "Failed to register dbus method %s"
983                            "in interface %s", "RemoveInterface",
984                            WPAS_DBUS_NEW_INTERFACE);
985         }
986
987         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
988                                      "GetInterface",
989                                      (WPADBusMethodHandler)
990                                      &wpas_dbus_handler_get_interface,
991                                      global, NULL, margs3)) {
992                 wpa_printf(MSG_ERROR,
993                            "Failed to register dbus method %s"
994                            "in interface %s", "global",
995                            WPAS_DBUS_NEW_INTERFACE);
996         }
997
998         /* register properties */
999         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
1000                                        "DebugParams", "(ibb)",
1001                                        (WPADBusPropertyAccessor)
1002                                        &wpas_dbus_getter_debug_params,
1003                                        (WPADBusPropertyAccessor)
1004                                        &wpas_dbus_setter_debug_params,
1005                                        global, NULL, RW)) {
1006                 wpa_printf(MSG_ERROR,
1007                            "Failed to register dbus property %s"
1008                            "in interface %s", "DebugParams",
1009                            WPAS_DBUS_NEW_INTERFACE);
1010         }
1011
1012         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
1013                                        "Interfaces", "ao",
1014                                        (WPADBusPropertyAccessor)
1015                                        &wpas_dbus_getter_interfaces, NULL,
1016                                        global, NULL, R)) {
1017                 wpa_printf(MSG_ERROR,
1018                            "Failed to register dbus property %s"
1019                            "in interface %s", "Interfaces",
1020                            WPAS_DBUS_NEW_INTERFACE);
1021         }
1022
1023         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
1024                                        "EapMethods", "as",
1025                                        wpas_dbus_getter_eap_methods, NULL,
1026                                        NULL, NULL, R)) {
1027                 wpa_printf(MSG_ERROR,
1028                            "Failed to register dbus property %s"
1029                            "in interface %s", "EapMethods",
1030                            WPAS_DBUS_NEW_INTERFACE);
1031         }
1032
1033
1034         /* register signals */
1035         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
1036                                      "InterfaceAdded", sargs1)) {
1037                 wpa_printf(MSG_ERROR,
1038                            "Failed to register dbus signal %s"
1039                            "in interface %s", "InterfaceAdded",
1040                            WPAS_DBUS_NEW_INTERFACE);
1041         }
1042
1043         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
1044                                      "InterfaceRemoved", sargs2)) {
1045                 wpa_printf(MSG_ERROR,
1046                            "Failed to register dbus signal %s"
1047                            "in interface %s", "InterfaceRemoved",
1048                            WPAS_DBUS_NEW_INTERFACE);
1049         }
1050
1051         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_INTERFACE,
1052                                      "PropertiesChanged", sargs3)) {
1053                 wpa_printf(MSG_ERROR,
1054                            "Failed to register dbus signal %s"
1055                            "in interface %s", "PropertiesChanged",
1056                            WPAS_DBUS_NEW_INTERFACE);
1057         }
1058
1059         ctrl_iface = wpa_dbus_ctrl_iface_init(global, WPAS_DBUS_NEW_PATH,
1060                                               WPAS_DBUS_NEW_SERVICE,
1061                                               obj_desc);
1062
1063         if (!ctrl_iface)
1064                 free_dbus_object_desc(obj_desc);
1065
1066         return ctrl_iface;
1067 }
1068
1069
1070 /**
1071  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1072  * wpa_supplicant
1073  * @iface: Pointer to dbus private data from
1074  * wpas_dbus_ctrl_iface_init()
1075  *
1076  * Deinitialize the dbus control interface that was initialized with
1077  * wpas_dbus_ctrl_iface_init().
1078  */
1079 static void wpas_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface)
1080 {
1081         if (iface) {
1082                 dbus_connection_unregister_object_path(iface->con,
1083                                                        WPAS_DBUS_NEW_PATH);
1084                 wpa_dbus_ctrl_iface_deinit(iface);
1085         }
1086 }
1087
1088
1089 /**
1090  * wpas_dbus_register_network - Register a configured network with dbus
1091  * @wpa_s: wpa_supplicant interface structure
1092  * @ssid: network configuration data
1093  * Returns: 0 on success, -1 on failure
1094  *
1095  * Registers network representing object with dbus
1096  */
1097 static int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1098                                       struct wpa_ssid *ssid)
1099 {
1100         struct ctrl_iface_dbus_new_priv *ctrl_iface;
1101         struct wpa_dbus_object_desc *obj_desc;
1102
1103         struct network_handler_args *arg1 = NULL;
1104         struct network_handler_args *arg2 = NULL;
1105         struct network_handler_args *arg3 = NULL;
1106
1107         const char *path = wpas_dbus_get_path(wpa_s);
1108         char *net_obj_path;
1109
1110         struct wpa_dbus_argument sargs[] = {
1111                 { "properties", "a{sv}", ARG_OUT },
1112                 END_ARGS
1113         };
1114
1115         /* Do nothing if the control interface is not turned on */
1116         if (wpa_s == NULL || wpa_s->global == NULL)
1117                 return 0;
1118         ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
1119         if (ctrl_iface == NULL)
1120                 return 0;
1121
1122         net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1123         if (net_obj_path == NULL)
1124                 return -1;
1125         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1126                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path, ssid->id);
1127
1128         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1129         if (!obj_desc) {
1130                 wpa_printf(MSG_ERROR, "Not enough memory "
1131                            "to create object description");
1132                 goto err;
1133         }
1134
1135         /* allocate memory for handlers arguments */
1136         arg1 =  os_zalloc(sizeof(struct network_handler_args));
1137         if (!arg1) {
1138                 wpa_printf(MSG_ERROR, "Not enough memory "
1139                            "to create arguments for method");
1140                 goto err;
1141         }
1142         arg2 =  os_zalloc(sizeof(struct network_handler_args));
1143         if (!arg2) {
1144                 wpa_printf(MSG_ERROR, "Not enough memory "
1145                            "to create arguments for method");
1146                 goto err;
1147         }
1148
1149         arg1->wpa_s = wpa_s;
1150         arg1->ssid = ssid;
1151         arg2->wpa_s = wpa_s;
1152         arg2->ssid = ssid;
1153
1154         /* Enabled property */
1155         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1156                                        "Enabled", "b",
1157                                        (WPADBusPropertyAccessor)
1158                                        wpas_dbus_getter_enabled,
1159                                        (WPADBusPropertyAccessor)
1160                                        wpas_dbus_setter_enabled,
1161                                        arg1, free, RW)) {
1162                 wpa_printf(MSG_ERROR,
1163                            "Failed to register dbus property %s"
1164                            "in interface %s", "Enabled",
1165                            WPAS_DBUS_NEW_IFACE_NETWORK);
1166         }
1167
1168         /* Properties property */
1169         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1170                                        "Properties", "a{sv}",
1171                                        (WPADBusPropertyAccessor)
1172                                        wpas_dbus_getter_network_properties,
1173                                        (WPADBusPropertyAccessor)
1174                                        wpas_dbus_setter_network_properties,
1175                                        arg2, free, RW)) {
1176                 wpa_printf(MSG_ERROR,
1177                            "Failed to register dbus property %s"
1178                            "in interface %s", "Properties",
1179                            WPAS_DBUS_NEW_IFACE_NETWORK);
1180         }
1181
1182         /* PropertiesChanged signal */
1183         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1184                                      "PropertiesChanged", sargs)) {
1185                 wpa_printf(MSG_ERROR,
1186                            "Failed to register dbus signal %s"
1187                            "in interface %s", "PropertiesChanged",
1188                            WPAS_DBUS_NEW_IFACE_NETWORK);
1189         }
1190
1191
1192         if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1193                                                wpa_s->ifname, obj_desc))
1194                 goto err;
1195
1196         wpas_dbus_signal_network_added(wpa_s, ssid->id);
1197
1198         os_free(net_obj_path);
1199         return 0;
1200
1201 err:
1202         os_free(net_obj_path);
1203         os_free(obj_desc);
1204         os_free(arg1);
1205         os_free(arg2);
1206         os_free(arg3);
1207         return -1;
1208 }
1209
1210
1211 /**
1212  * wpas_dbus_unregister_network - Unregister a configured network from dbus
1213  * @wpa_s: wpa_supplicant interface structure
1214  * @nid: network id
1215  * Returns: 0 on success, -1 on failure
1216  *
1217  * Unregisters network representing object from dbus
1218  */
1219 static int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1220 {
1221         struct ctrl_iface_dbus_new_priv *ctrl_iface;
1222         const char *path = wpas_dbus_get_path(wpa_s);
1223         char *net_obj_path;
1224         int ret;
1225
1226         /* Do nothing if the control interface is not turned on */
1227         if (wpa_s == NULL || wpa_s->global == NULL)
1228                 return 0;
1229         ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
1230         if (ctrl_iface == NULL)
1231                 return 0;
1232
1233         net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1234         if (net_obj_path == NULL)
1235                 return -1;
1236         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1237                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path, nid);
1238
1239         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1240
1241         if (!ret)
1242                 wpas_dbus_signal_network_removed(wpa_s, nid);
1243
1244         os_free(net_obj_path);
1245         return ret;
1246 }
1247
1248
1249 /**
1250  * wpas_dbus_register_bss - Register a scanned BSS with dbus
1251  * @wpa_s: wpa_supplicant interface structure
1252  * @bssid: scanned network bssid
1253  * Returns: 0 on success, -1 on failure
1254  *
1255  * Registers BSS representing object with dbus
1256  */
1257 static int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1258                                     u8 bssid[ETH_ALEN])
1259 {
1260         struct ctrl_iface_dbus_new_priv *ctrl_iface;
1261         const char *path = wpas_dbus_get_path(wpa_s);
1262         char *bss_obj_path;
1263
1264         /* Do nothing if the control interface is not turned on */
1265         if (wpa_s == NULL || wpa_s->global == NULL)
1266                 return 0;
1267         ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
1268         if (ctrl_iface == NULL)
1269                 return 0;
1270
1271         bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1272         if (bss_obj_path == NULL)
1273                 return -1;
1274
1275         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1276                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/" WPAS_DBUS_BSSID_FORMAT,
1277                     path, MAC2STR(bssid));
1278
1279         if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1280                 wpa_printf(MSG_ERROR,
1281                            "Cannot unregister BSSID dbus object %s.",
1282                            bss_obj_path);
1283                 os_free(bss_obj_path);
1284                 return -1;
1285         }
1286
1287         wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1288
1289         os_free(bss_obj_path);
1290         return 0;
1291 }
1292
1293
1294 static int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1295                                   u8 bssid[ETH_ALEN])
1296 {
1297         struct ctrl_iface_dbus_new_priv *ctrl_iface;
1298         struct wpa_dbus_object_desc *obj_desc;
1299         const char *path = wpas_dbus_get_path(wpa_s);
1300         char *bss_obj_path;
1301
1302         struct bss_handler_args *arg = NULL;
1303
1304         /* Do nothing if the control interface is not turned on */
1305         if (wpa_s == NULL || wpa_s->global == NULL)
1306                 return 0;
1307         ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
1308         if (ctrl_iface == NULL)
1309                 return 0;
1310
1311         bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1312         if (bss_obj_path == NULL)
1313                 return -1;
1314
1315         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1316                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/" WPAS_DBUS_BSSID_FORMAT,
1317                     path, MAC2STR(bssid));
1318
1319         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1320         if (!obj_desc) {
1321                 wpa_printf(MSG_ERROR, "Not enough memory "
1322                            "to create object description");
1323                 goto err;
1324         }
1325
1326         arg = os_zalloc(sizeof(struct bss_handler_args));
1327         if (!arg) {
1328                 wpa_printf(MSG_ERROR, "Not enough memory "
1329                            "to create arguments for handler");
1330                 goto err;
1331         }
1332         arg->wpa_s = wpa_s;
1333         os_memcpy(arg->bssid, bssid, ETH_ALEN);
1334
1335         /* Properties property */
1336         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_BSSID,
1337                                        "Properties", "a{sv}",
1338                                        (WPADBusPropertyAccessor)
1339                                        wpas_dbus_getter_bss_properties, NULL,
1340                                        arg, free, R)) {
1341                 wpa_printf(MSG_ERROR,
1342                            "Failed to register dbus property %s"
1343                            "in interface %s", "Properties",
1344                            WPAS_DBUS_NEW_IFACE_BSSID);
1345         }
1346
1347         if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1348                                                wpa_s->ifname, obj_desc)) {
1349                 wpa_printf(MSG_ERROR,
1350                            "Cannot register BSSID dbus object %s.",
1351                            bss_obj_path);
1352                 goto err;
1353         }
1354
1355         wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1356
1357         os_free(bss_obj_path);
1358         return 0;
1359
1360 err:
1361         os_free(bss_obj_path);
1362         os_free(obj_desc);
1363         os_free(arg);
1364         return -1;
1365 }
1366
1367
1368 /**
1369  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1370  * @wpa_s: wpa_supplicant interface structure
1371  * @bssid: scanned network bssid
1372  * Returns: 0 on success, -1 on failure
1373  *
1374  * Unregisters BSS representing object from dbus
1375  */
1376 static int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1377 {
1378
1379         struct wpa_dbus_object_desc *obj_desc = NULL;
1380         char *path;
1381         struct ctrl_iface_dbus_new_priv *ctrl_iface =
1382                 wpa_s->global->dbus_new_ctrl_iface;
1383         int next;
1384
1385         struct wpa_dbus_argument args1[] = {
1386                 { "args", "a{sv}", ARG_IN },
1387                 END_ARGS
1388         };
1389         struct wpa_dbus_argument args3[] = {
1390                 { "args", "a{sv}", ARG_IN },
1391                 { "path", "o", ARG_OUT },
1392                 END_ARGS
1393         };
1394         struct wpa_dbus_argument args4[] = {
1395                 { "path", "o", ARG_IN },
1396                 END_ARGS
1397         };
1398         struct wpa_dbus_argument args5[] = {
1399                 { "path", "o", ARG_IN },
1400                 END_ARGS
1401         };
1402         struct wpa_dbus_argument args6[] = {
1403                 { "name", "s", ARG_IN },
1404                 { "data", "ay", ARG_IN },
1405                 END_ARGS
1406         };
1407         struct wpa_dbus_argument args7[] = {
1408                 { "name", "s", ARG_IN },
1409                 { "data", "ay", ARG_OUT },
1410                 END_ARGS
1411         };
1412         struct wpa_dbus_argument args8[] = {
1413                 { "name", "s", ARG_IN },
1414                 END_ARGS
1415         };
1416         struct wpa_dbus_argument sargs1[] = {
1417                 { "success", "b", ARG_OUT },
1418                 END_ARGS
1419         };
1420         struct wpa_dbus_argument sargs2[] = {
1421                 { "newState", "s", ARG_OUT },
1422                 { "oldState", "s", ARG_OUT },
1423                 END_ARGS
1424         };
1425         struct wpa_dbus_argument sargs3[] = {
1426                 { "path", "o", ARG_OUT },
1427                 END_ARGS
1428         };
1429         struct wpa_dbus_argument sargs4[] = {
1430                 { "path", "o", ARG_OUT },
1431                 END_ARGS
1432         };
1433         struct wpa_dbus_argument sargs5[] = {
1434                 { "name", "s", ARG_OUT },
1435                 END_ARGS
1436         };
1437         struct wpa_dbus_argument sargs6[] = {
1438                 { "name", "s", ARG_OUT },
1439                 END_ARGS
1440         };
1441         struct wpa_dbus_argument sargs7[] = {
1442                 { "path", "o", ARG_OUT },
1443                 END_ARGS
1444         };
1445         struct wpa_dbus_argument sargs8[] = {
1446                 { "path", "o", ARG_OUT },
1447                 END_ARGS
1448         };
1449         struct wpa_dbus_argument sargs9[] = {
1450                 { "path", "o", ARG_OUT },
1451                 END_ARGS
1452         };
1453         struct wpa_dbus_argument sargs10[] = {
1454                 { "properties", "a{sv}", ARG_OUT },
1455                 END_ARGS
1456         };
1457
1458 #ifdef CONFIG_WPS
1459         struct wpa_dbus_argument args9[] = {
1460                 { "args", "a{sv}", ARG_IN },
1461                 { "output", "a{sv}", ARG_OUT },
1462                 END_ARGS
1463         };
1464         struct wpa_dbus_argument sargs11[] = {
1465                 { "name", "s", ARG_OUT },
1466                 { "args", "a{sv}", ARG_OUT },
1467                 END_ARGS
1468         };
1469         struct wpa_dbus_argument sargs12[] = {
1470                 { "credentials", "a{sv}", ARG_OUT },
1471                 END_ARGS
1472         };
1473         struct wpa_dbus_argument sargs13[] = {
1474                 { "properties", "a{sv}", ARG_OUT },
1475                 END_ARGS
1476         };
1477 #endif /* CONFIG_WPS */
1478         /* Do nothing if the control interface is not turned on */
1479         if (ctrl_iface == NULL)
1480                 return 0;
1481
1482         /* Create and set the interface's object path */
1483         path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1484         if (path == NULL)
1485                 return -1;
1486         next = wpa_dbus_next_objid(ctrl_iface);
1487         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1488                     WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1489                     next);
1490         if (wpas_dbus_set_path(wpa_s, path)) {
1491                 wpa_printf(MSG_DEBUG,
1492                            "Failed to set dbus path for interface %s",
1493                            wpa_s->ifname);
1494                 goto err;
1495         }
1496
1497         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1498         if (!obj_desc) {
1499                 wpa_printf(MSG_ERROR, "Not enough memory "
1500                            "to create object description");
1501                 goto err;
1502         }
1503
1504         /* Scan method */
1505         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1506                                      "Scan",
1507                                      (WPADBusMethodHandler)
1508                                      &wpas_dbus_handler_scan,
1509                                      wpa_s, NULL, args1)) {
1510                 wpa_printf(MSG_DEBUG,
1511                            "Failed to register dbus method %s"
1512                            "in interface %s", "Scan",
1513                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1514         }
1515
1516         /* Disconnect method */
1517         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1518                                      "Disconnect",
1519                                      (WPADBusMethodHandler)
1520                                      &wpas_dbus_handler_disconnect,
1521                                      wpa_s, NULL, NULL)) {
1522                 wpa_printf(MSG_DEBUG,
1523                            "Failed to register dbus method %s"
1524                            "in interface %s", "Disconnect",
1525                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1526         }
1527
1528         /* AddNetwork method */
1529         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1530                                      "AddNetwork",
1531                                      (WPADBusMethodHandler)
1532                                      &wpas_dbus_handler_add_network,
1533                                      wpa_s, NULL, args3)) {
1534                 wpa_printf(MSG_DEBUG,
1535                            "Failed to register dbus method %s"
1536                            "in interface %s", "AddNetwork",
1537                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1538         }
1539
1540         /* RemoveNetwork method */
1541         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1542                                      "RemoveNetwork",
1543                                      (WPADBusMethodHandler)
1544                                      &wpas_dbus_handler_remove_network,
1545                                      wpa_s, NULL, args4)) {
1546                 wpa_printf(MSG_DEBUG,
1547                            "Failed to register dbus method %s"
1548                            "in interface %s", "RemoveNetwork",
1549                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1550         }
1551
1552         /* SelectNetwork method */
1553         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1554                                      "SelectNetwork",
1555                                      (WPADBusMethodHandler)
1556                                      &wpas_dbus_handler_select_network,
1557                                      wpa_s, NULL, args5)) {
1558                 wpa_printf(MSG_DEBUG,
1559                            "Failed to register dbus method %s"
1560                            "in interface %s", "SelectNetwork",
1561                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1562         }
1563
1564         /* AddBlob method */
1565         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1566                                      "AddBlob",
1567                                      (WPADBusMethodHandler)
1568                                      &wpas_dbus_handler_add_blob,
1569                                      wpa_s, NULL, args6)) {
1570                 wpa_printf(MSG_DEBUG,
1571                            "Failed to register dbus method %s"
1572                            "in interface %s", "AddBlob",
1573                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1574         }
1575
1576         /* GetBlob method */
1577         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1578                                      "GetBlob",
1579                                      (WPADBusMethodHandler)
1580                                      &wpas_dbus_handler_get_blob,
1581                                      wpa_s, NULL, args7)) {
1582                 wpa_printf(MSG_DEBUG,
1583                            "Failed to register dbus method %s"
1584                            "in interface %s", "GetBlob",
1585                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1586         }
1587
1588         /* RemoveBlob method */
1589         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1590                                      "RemoveBlob",
1591                                      (WPADBusMethodHandler)
1592                                      &wpas_dbus_handler_remove_blob,
1593                                      wpa_s, NULL, args8)) {
1594                 wpa_printf(MSG_DEBUG,
1595                            "Failed to register dbus method %s"
1596                            "in interface %s", "RemoveBlob",
1597                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1598         }
1599
1600         /* Capabilities property */
1601         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1602                                        "Capabilities", "a{sv}",
1603                                        (WPADBusPropertyAccessor)
1604                                        wpas_dbus_getter_capabilities, NULL,
1605                                        wpa_s, NULL, R)) {
1606                 wpa_printf(MSG_ERROR,
1607                            "Failed to register dbus property %s"
1608                            "in interface %s", "Capabilities",
1609                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1610         }
1611
1612         /* State property */
1613         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1614                                        "State", "s",
1615                                        (WPADBusPropertyAccessor)
1616                                        wpas_dbus_getter_state, NULL,
1617                                        wpa_s, NULL, R)) {
1618                 wpa_printf(MSG_ERROR,
1619                            "Failed to register dbus property %s"
1620                            "in interface %s", "State",
1621                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1622         }
1623
1624         /* Scanning property */
1625         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1626                                        "Scanning", "b",
1627                                        (WPADBusPropertyAccessor)
1628                                        wpas_dbus_getter_scanning, NULL,
1629                                        wpa_s, NULL, R)) {
1630                 wpa_printf(MSG_ERROR,
1631                            "Failed to register dbus property %s"
1632                            "in interface %s", "Scanning",
1633                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1634         }
1635
1636         /* ApScan property */
1637         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1638                                        "ApScan", "u",
1639                                        (WPADBusPropertyAccessor)
1640                                        wpas_dbus_getter_ap_scan,
1641                                        (WPADBusPropertyAccessor)
1642                                        wpas_dbus_setter_ap_scan,
1643                                        wpa_s, NULL, RW)) {
1644                 wpa_printf(MSG_ERROR,
1645                            "Failed to register dbus property %s"
1646                            "in interface %s", "ApScan",
1647                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1648         }
1649
1650         /* Ifname property */
1651         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1652                                        "Ifname", "s",
1653                                        (WPADBusPropertyAccessor)
1654                                        wpas_dbus_getter_ifname, NULL,
1655                                        wpa_s, NULL, R)) {
1656                 wpa_printf(MSG_ERROR,
1657                            "Failed to register dbus property %s"
1658                            "in interface %s", "Ifname",
1659                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1660         }
1661
1662         /* Driver property */
1663         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1664                                        "Driver", "s",
1665                                        (WPADBusPropertyAccessor)
1666                                        wpas_dbus_getter_driver, NULL,
1667                                        wpa_s, NULL, R)) {
1668                 wpa_printf(MSG_ERROR,
1669                            "Failed to register dbus property %s"
1670                            "in interface %s", "Driver",
1671                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1672         }
1673
1674         /* BridgeIfname property */
1675         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1676                                        "BridgeIfname", "s",
1677                                        (WPADBusPropertyAccessor)
1678                                        wpas_dbus_getter_bridge_ifname, NULL,
1679                                        wpa_s, NULL, R)) {
1680                 wpa_printf(MSG_ERROR,
1681                            "Failed to register dbus property %s"
1682                            "in interface %s", "BridgeIfname",
1683                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1684         }
1685
1686         /* CurrentBSS property */
1687         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1688                                        "CurrentBSS", "o",
1689                                        (WPADBusPropertyAccessor)
1690                                        wpas_dbus_getter_current_bss, NULL,
1691                                        wpa_s, NULL, R)) {
1692                 wpa_printf(MSG_ERROR,
1693                            "Failed to register dbus property %s"
1694                            "in interface %s", "CurrentBSS",
1695                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1696         }
1697
1698         /* CurrentNetwork property */
1699         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1700                                        "CurrentNetwork", "o",
1701                                        (WPADBusPropertyAccessor)
1702                                        wpas_dbus_getter_current_network, NULL,
1703                                        wpa_s, NULL, R)) {
1704                 wpa_printf(MSG_ERROR,
1705                            "Failed to register dbus property %s"
1706                            "in interface %s", "CurrentNetwork",
1707                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1708         }
1709
1710         /* Blobs property */
1711         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1712                                        "Blobs", "a{say}",
1713                                        (WPADBusPropertyAccessor)
1714                                        wpas_dbus_getter_blobs, NULL,
1715                                        wpa_s, NULL, R)) {
1716                 wpa_printf(MSG_ERROR,
1717                            "Failed to register dbus property %s"
1718                            "in interface %s", "Blobs",
1719                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1720         }
1721
1722         /* BSSs property */
1723         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1724                                        "BSSs", "ao",
1725                                        (WPADBusPropertyAccessor)
1726                                        wpas_dbus_getter_bsss, NULL,
1727                                        wpa_s, NULL, R)) {
1728                 wpa_printf(MSG_ERROR,
1729                            "Failed to register dbus property %s"
1730                            "in interface %s", "BSSs",
1731                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1732         }
1733
1734         /* Networks property */
1735         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1736                                        "Networks", "ao",
1737                                        (WPADBusPropertyAccessor)
1738                                        wpas_dbus_getter_networks, NULL,
1739                                        wpa_s, NULL, R)) {
1740                 wpa_printf(MSG_ERROR,
1741                            "Failed to register dbus property %s"
1742                            "in interface %s", "Networks",
1743                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1744         }
1745
1746         /* ScanDone signal */
1747         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1748                                      "ScanDone", sargs1)) {
1749                 wpa_printf(MSG_ERROR,
1750                            "Failed to register dbus signal %s"
1751                            "in interface %s", "ScanDone",
1752                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1753         }
1754
1755         /* StateChanged signal */
1756         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1757                                      "StateChanged", sargs2)) {
1758                 wpa_printf(MSG_ERROR,
1759                            "Failed to register dbus signal %s"
1760                            "in interface %s", "StateChanged",
1761                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1762         }
1763
1764         /* BSSAdded signal */
1765         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1766                                      "BSSAdded", sargs3)) {
1767                 wpa_printf(MSG_ERROR,
1768                            "Failed to register dbus signal %s"
1769                            "in interface %s", "BSSAdded",
1770                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1771         }
1772
1773         /* BSSRemoved signal */
1774         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1775                                      "BSSRemoved", sargs4)) {
1776                 wpa_printf(MSG_ERROR,
1777                            "Failed to register dbus signal %s"
1778                            "in interface %s", "BSSRemoved",
1779                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1780         }
1781
1782         /* BlobAdded signal */
1783         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1784                                      "BlobAdded", sargs5)) {
1785                 wpa_printf(MSG_ERROR,
1786                            "Failed to register dbus signal %s"
1787                            "in interface %s", "BlobAdded",
1788                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1789         }
1790
1791         /* BlobRemoved signal */
1792         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1793                                      "BlobRemoved", sargs6)) {
1794                 wpa_printf(MSG_ERROR,
1795                            "Failed to register dbus signal %s"
1796                            "in interface %s", "BlobRemoved",
1797                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1798         }
1799
1800         /* NetworkAdded signal */
1801         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1802                                      "NetworkAdded", sargs7)) {
1803                 wpa_printf(MSG_ERROR,
1804                            "Failed to register dbus signal %s"
1805                            "in interface %s", "NetworkAdded",
1806                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1807         }
1808
1809         /* NetworkRemoved signal */
1810         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1811                                      "NetworkRemoved", sargs8)) {
1812                 wpa_printf(MSG_ERROR,
1813                            "Failed to register dbus signal %s"
1814                            "in interface %s", "NetworkRemoved",
1815                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1816         }
1817
1818         /* NetworkSelected signal */
1819         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1820                                      "NetworkSelected", sargs9)) {
1821                 wpa_printf(MSG_ERROR,
1822                            "Failed to register dbus signal %s"
1823                            "in interface %s", "NetworkSelected",
1824                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1825         }
1826
1827         /* PropertiesChanged signal */
1828         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_INTERFACE,
1829                                      "PropertiesChanged", sargs10)) {
1830                 wpa_printf(MSG_ERROR,
1831                            "Failed to register dbus signal %s"
1832                            "in interface %s", "PropertiesChanged",
1833                            WPAS_DBUS_NEW_IFACE_INTERFACE);
1834         }
1835
1836 #ifdef CONFIG_WPS
1837         /* Start method */
1838         if (wpa_dbus_method_register(obj_desc, WPAS_DBUS_NEW_IFACE_WPS,
1839                                      "Start",
1840                                      (WPADBusMethodHandler)
1841                                      &wpas_dbus_handler_wps_start,
1842                                      wpa_s, NULL, args9)) {
1843                 wpa_printf(MSG_DEBUG,
1844                            "Failed to register dbus method %s"
1845                            "in interface %s", "Start",
1846                            WPAS_DBUS_NEW_IFACE_WPS);
1847         }
1848
1849         /* ProcessCredentials property */
1850         if (wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_WPS,
1851                                        "ProcessCredentials", "b",
1852                                        (WPADBusPropertyAccessor)
1853                                        wpas_dbus_getter_process_credentials,
1854                                        (WPADBusPropertyAccessor)
1855                                        wpas_dbus_setter_process_credentials,
1856                                        wpa_s, NULL, RW)) {
1857                 wpa_printf(MSG_ERROR,
1858                            "Failed to register dbus property %s"
1859                            "in interface %s", "ProcessCredentials",
1860                            WPAS_DBUS_NEW_IFACE_WPS);
1861         }
1862
1863         /* Event signal */
1864         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_WPS,
1865                                      "Event", sargs11)) {
1866                 wpa_printf(MSG_ERROR,
1867                            "Failed to register dbus signal %s"
1868                            "in interface %s", "Event",
1869                            WPAS_DBUS_NEW_IFACE_WPS);
1870         }
1871
1872         /* Credentials signal */
1873         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_WPS,
1874                                      "Credentials", sargs12)) {
1875                 wpa_printf(MSG_ERROR,
1876                            "Failed to register dbus signal %s"
1877                            "in interface %s", "Credentials",
1878                            WPAS_DBUS_NEW_IFACE_WPS);
1879         }
1880
1881         /* PropertiesChanged signal */
1882         if (wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_WPS,
1883                                      "PropertiesChanged", sargs13)) {
1884                 wpa_printf(MSG_ERROR,
1885                            "Failed to register dbus signal %s"
1886                            "in interface %s", "PropertiesChanged",
1887                            WPAS_DBUS_NEW_IFACE_WPS);
1888         }
1889 #endif /* CONFIG_WPS */
1890
1891         if (wpa_dbus_register_object_per_iface(ctrl_iface, path, wpa_s->ifname,
1892                                                obj_desc))
1893                 goto err;
1894
1895         wpas_dbus_signal_interface_created(wpa_s);
1896
1897         os_free(path);
1898         return 0;
1899
1900 err:
1901         os_free(obj_desc);
1902         os_free(path);
1903         return -1;
1904 }
1905
1906
1907 static int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1908 {
1909         struct ctrl_iface_dbus_new_priv *ctrl_iface;
1910         struct wpa_ssid *ssid = wpa_s->conf->ssid;
1911         size_t i;
1912         const char *path;
1913
1914         /* Do nothing if the control interface is not turned on */
1915         if (wpa_s == NULL || wpa_s->global == NULL)
1916                 return 0;
1917         ctrl_iface = wpa_s->global->dbus_new_ctrl_iface;
1918         if (ctrl_iface == NULL)
1919                 return 0;
1920
1921         path = wpas_dbus_get_path(wpa_s);
1922
1923         /* unregister all BSSs and networks from dbus */
1924         for (i = 0; i < wpa_s->scan_res->num; i++) {
1925                 wpas_dbus_unregister_bss(wpa_s,
1926                                          wpa_s->scan_res->res[i]->bssid);
1927         }
1928
1929         while (ssid) {
1930                 wpas_dbus_unregister_network(wpa_s, ssid->id);
1931                 ssid = ssid->next;
1932         }
1933
1934         if (wpa_dbus_unregister_object_per_iface(ctrl_iface, path))
1935                 return -1;
1936
1937         wpas_dbus_signal_interface_removed(wpa_s);
1938
1939         os_free(wpa_s->dbus_new_path);
1940         wpa_s->dbus_new_path = NULL;
1941
1942         return 0;
1943 }
1944
1945
1946 static struct wpas_dbus_callbacks callbacks =
1947 {
1948         .dbus_ctrl_init = wpas_dbus_ctrl_iface_init,
1949         .dbus_ctrl_deinit = wpas_dbus_ctrl_iface_deinit,
1950
1951         .signal_interface_created = wpas_dbus_signal_interface_created,
1952         .signal_interface_removed = wpas_dbus_signal_interface_removed,
1953
1954         .register_interface = wpas_dbus_register_interface,
1955         .unregister_interface = wpas_dbus_unregister_interface,
1956
1957         .signal_scan_done = wpas_dbus_signal_scan_done,
1958
1959         .signal_blob_added = wpas_dbus_signal_blob_added,
1960         .signal_blob_removed = wpas_dbus_signal_blob_removed,
1961
1962         .signal_network_selected = wpas_dbus_signal_network_selected,
1963
1964         .signal_state_changed = wpas_dbus_signal_state_changed,
1965         .register_network = wpas_dbus_register_network,
1966         .unregister_network = wpas_dbus_unregister_network,
1967
1968         .signal_network_enabled_changed =
1969         wpas_dbus_signal_network_enabled_changed,
1970
1971         .register_bss = wpas_dbus_register_bss,
1972         .unregister_bss = wpas_dbus_unregister_bss,
1973
1974         .signal_prop_changed = wpas_dbus_signal_prop_changed,
1975         .signal_debug_params_changed = wpas_dbus_signal_debug_params_changed,
1976
1977 #ifdef CONFIG_WPS
1978         .signal_wps_event_success = wpas_dbus_signal_wps_event_success,
1979         .signal_wps_event_fail = wpas_dbus_signal_wps_event_fail,
1980         .signal_wps_event_m2d = wpas_dbus_signal_wps_event_m2d,
1981         .signal_wps_credentials = wpas_dbus_signal_wps_cred,
1982 #endif /* CONFIG_WPS */
1983 };
1984
1985
1986 struct wpas_dbus_callbacks * wpas_dbus_get_callbacks(void)
1987 {
1988         return &callbacks;
1989 }
1990
1991
1992 /**
1993  * wpas_dbus_get_path - Get an interface's dbus path
1994  * @wpa_s: %wpa_supplicant interface structure
1995  * Returns: Interface's dbus object path, or %NULL on error
1996  */
1997 const char * wpas_dbus_get_path(struct wpa_supplicant *wpa_s)
1998 {
1999         return wpa_s->dbus_new_path;
2000 }