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