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