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