Deal with another libgdbus API change
[connman] / src / iface.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
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  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <net/if.h>
36 #include <net/route.h>
37
38 #include <linux/netlink.h>
39 #include <linux/rtnetlink.h>
40
41 #include <glib.h>
42 #include <gdbus.h>
43
44 #include <hal/libhal.h>
45
46 #include "connman.h"
47
48 static DBusConnection *connection = NULL;
49
50 static gchar *ifname_filter = NULL;
51
52 static GSList *drivers = NULL;
53
54 int connman_iface_register(struct connman_iface_driver *driver)
55 {
56         DBG("driver %p", driver);
57
58         drivers = g_slist_append(drivers, driver);
59
60         return 0;
61 }
62
63 void connman_iface_unregister(struct connman_iface_driver *driver)
64 {
65         DBG("driver %p", driver);
66
67         drivers = g_slist_remove(drivers, driver);
68 }
69
70 static GSList *interfaces = NULL;
71
72 struct connman_iface *__connman_iface_find(int index)
73 {
74         GSList *list;
75
76         for (list = interfaces; list; list = list->next) {
77                 struct connman_iface *iface = list->data;
78
79                 if (iface->index == index)
80                         return iface;
81         }
82
83         return NULL;
84 }
85
86 void __connman_iface_list(DBusMessageIter *iter)
87 {
88         GSList *list;
89
90         DBG("");
91
92         for (list = interfaces; list; list = list->next) {
93                 struct connman_iface *iface = list->data;
94
95                 dbus_message_iter_append_basic(iter,
96                                 DBUS_TYPE_OBJECT_PATH, &iface->path);
97         }
98 }
99
100 gboolean __connman_iface_is_connected(void)
101 {
102         GSList *list;
103         gboolean connected = FALSE;
104
105         DBG("");
106
107         for (list = interfaces; list; list = list->next) {
108                 struct connman_iface *iface = list->data;
109
110                 if (iface->state == CONNMAN_IFACE_STATE_READY) {
111                         connected = TRUE;
112                         break;
113                 }
114         }
115
116         return connected;
117 }
118
119 static void append_entry(DBusMessageIter *dict,
120                                 const char *key, int type, void *val)
121 {
122         DBusMessageIter entry, value;
123         const char *signature;
124
125         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
126                                                                 NULL, &entry);
127
128         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
129
130         switch (type) {
131         case DBUS_TYPE_STRING:
132                 signature = DBUS_TYPE_STRING_AS_STRING;
133                 break;
134         case DBUS_TYPE_UINT16:
135                 signature = DBUS_TYPE_UINT16_AS_STRING;
136                 break;
137         default:
138                 signature = DBUS_TYPE_VARIANT_AS_STRING;
139                 break;
140         }
141
142         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
143                                                         signature, &value);
144         dbus_message_iter_append_basic(&value, type, val);
145         dbus_message_iter_close_container(&entry, &value);
146
147         dbus_message_iter_close_container(dict, &entry);
148 }
149
150 static gboolean scan_timeout(gpointer user_data)
151 {
152         struct connman_iface *iface = user_data;
153
154         switch (iface->state) {
155         case CONNMAN_IFACE_STATE_SCANNING:
156                 if (iface->driver->scan)
157                         iface->driver->scan(iface);
158                 return TRUE;
159         default:
160                 break;
161         }
162
163         return FALSE;
164 }
165
166 static void state_changed(struct connman_iface *iface)
167 {
168         const char *str = __connman_iface_state2string(iface->state);
169         enum connman_iface_state state = iface->state;
170
171         DBG("iface %p state %s", iface, str);
172
173         g_dbus_emit_signal(connection, iface->path,
174                                 CONNMAN_IFACE_INTERFACE, "StateChanged",
175                                 DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
176
177         switch (iface->state) {
178         case CONNMAN_IFACE_STATE_OFF:
179                 __connman_iface_stop(iface);
180                 break;
181
182         case CONNMAN_IFACE_STATE_ENABLED:
183                 __connman_iface_start(iface);
184                 if (iface->flags & CONNMAN_IFACE_FLAG_SCANNING)
185                         state = CONNMAN_IFACE_STATE_SCANNING;
186                 break;
187
188         case CONNMAN_IFACE_STATE_SCANNING:
189                 if (iface->driver->scan)
190                         iface->driver->scan(iface);
191                 g_timeout_add(8000, scan_timeout, iface);
192                 break;
193
194         case CONNMAN_IFACE_STATE_CARRIER:
195                 if (iface->policy == CONNMAN_IFACE_POLICY_AUTO)
196                         state = CONNMAN_IFACE_STATE_CONFIGURE;
197                 break;
198
199         case CONNMAN_IFACE_STATE_CONFIGURE:
200                 __connman_dhcp_request(iface);
201                 break;
202
203         case CONNMAN_IFACE_STATE_SHUTDOWN:
204                 __connman_iface_stop(iface);
205                 if (iface->policy != CONNMAN_IFACE_POLICY_AUTO)
206                         state = CONNMAN_IFACE_STATE_OFF;
207                 break;
208
209         case CONNMAN_IFACE_STATE_READY:
210                 break;
211
212         default:
213                 break;
214         }
215
216         if (iface->state != state) {
217                 iface->state = state;
218                 state_changed(iface);
219         }
220 }
221
222 static void switch_policy(struct connman_iface *iface)
223 {
224         DBG("iface %p policy %d", iface, iface->policy);
225
226         switch (iface->policy) {
227         case CONNMAN_IFACE_POLICY_OFF:
228                 __connman_iface_stop(iface);
229                 break;
230
231         case CONNMAN_IFACE_POLICY_IGNORE:
232                 break;
233
234         case CONNMAN_IFACE_POLICY_AUTO:
235         case CONNMAN_IFACE_POLICY_ASK:
236                 __connman_iface_start(iface);
237                 break;
238
239         default:
240                 break;
241         }
242 }
243
244 void connman_iface_indicate_ifup(struct connman_iface *iface)
245 {
246         DBG("iface %p state %d", iface, iface->state);
247
248         switch (iface->state) {
249         case CONNMAN_IFACE_STATE_OFF:
250                 iface->state = CONNMAN_IFACE_STATE_ENABLED;
251                 state_changed(iface);
252                 break;
253         default:
254                 break;
255         }
256 }
257
258 void connman_iface_indicate_ifdown(struct connman_iface *iface)
259 {
260         DBG("iface %p state %d", iface, iface->state);
261
262         if (iface->policy == CONNMAN_IFACE_POLICY_AUTO)
263                 iface->state = CONNMAN_IFACE_STATE_ENABLED;
264         else
265                 iface->state = CONNMAN_IFACE_STATE_SHUTDOWN;
266
267         state_changed(iface);
268 }
269
270 void connman_iface_indicate_connected(struct connman_iface *iface)
271 {
272         DBG("iface %p state %d", iface, iface->state);
273
274         switch (iface->state) {
275         case CONNMAN_IFACE_STATE_CONNECT:
276                 iface->state = CONNMAN_IFACE_STATE_CONNECTED;
277                 state_changed(iface);
278                 break;
279         default:
280                 break;
281         }
282 }
283
284 void connman_iface_indicate_carrier_on(struct connman_iface *iface)
285 {
286         DBG("iface %p state %d", iface, iface->state);
287
288         switch (iface->state) {
289         case CONNMAN_IFACE_STATE_ENABLED:
290         case CONNMAN_IFACE_STATE_CONNECT:
291         case CONNMAN_IFACE_STATE_CONNECTED:
292                 iface->state = CONNMAN_IFACE_STATE_CARRIER;
293                 state_changed(iface);
294                 break;
295         default:
296                 break;
297         }
298 }
299
300 void connman_iface_indicate_carrier_off(struct connman_iface *iface)
301 {
302         DBG("iface %p state %d", iface, iface->state);
303
304         switch (iface->state) {
305         case CONNMAN_IFACE_STATE_CARRIER:
306         case CONNMAN_IFACE_STATE_CONFIGURE:
307         case CONNMAN_IFACE_STATE_READY:
308                 __connman_iface_disconnect(iface);
309                 if (iface->flags & CONNMAN_IFACE_FLAG_SCANNING)
310                         iface->state = CONNMAN_IFACE_STATE_SCANNING;
311                 else
312                         iface->state = CONNMAN_IFACE_STATE_ENABLED;
313                 state_changed(iface);
314                 break;
315         default:
316                 break;
317         }
318 }
319
320 void connman_iface_indicate_configured(struct connman_iface *iface)
321 {
322         DBG("iface %p state %d", iface, iface->state);
323
324         switch (iface->state) {
325         case CONNMAN_IFACE_STATE_CONFIGURE:
326                 iface->state = CONNMAN_IFACE_STATE_READY;
327                 state_changed(iface);
328                 __connman_iface_store_current_network(iface);
329                 break;
330         default:
331                 break;
332         }
333 }
334
335 static void append_station(DBusMessage *reply, const char *name,
336                                                 int signal, int security)
337 {
338         DBusMessageIter array, dict;
339         const char *wpa = "WPA";
340
341         dbus_message_iter_init_append(reply, &array);
342
343         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
344                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
345                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
346                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
347
348         append_entry(&dict, "ESSID", DBUS_TYPE_STRING, &name);
349         append_entry(&dict, "Signal", DBUS_TYPE_UINT16, &signal);
350
351         if (security > 0)
352                 append_entry(&dict, "Security", DBUS_TYPE_STRING, &wpa);
353
354         dbus_message_iter_close_container(&array, &dict);
355 }
356
357 void connman_iface_indicate_station(struct connman_iface *iface,
358                                 const char *name, int strength, int security)
359 {
360         DBusMessage *signal;
361         char *ssid, *passphrase;
362         int len;
363
364         DBG("iface %p security %d name %s", iface, security, name);
365
366         if (name == NULL || strlen(name) == 0)
367                 return;
368
369         signal = dbus_message_new_signal(iface->path,
370                                 CONNMAN_IFACE_INTERFACE, "NetworkFound");
371         if (signal == NULL)
372                 return;
373
374         append_station(signal, name, strength, security);
375
376         dbus_connection_send(connection, signal, NULL);
377         dbus_message_unref(signal);
378
379         switch (iface->state) {
380         case CONNMAN_IFACE_STATE_CONNECT:
381         case CONNMAN_IFACE_STATE_CONNECTED:
382         case CONNMAN_IFACE_STATE_CARRIER:
383         case CONNMAN_IFACE_STATE_CONFIGURE:
384         case CONNMAN_IFACE_STATE_READY:
385                 return;
386         default:
387                 break;
388         }
389
390         len = strlen(name);
391         ssid = strdup(name);
392         if (ssid == NULL)
393                 return;
394
395         /* The D-Link access points return a 0x05 at the end of the SSID */
396         if (ssid[len - 1] == '\05')
397                 ssid[len - 1] = '\0';
398
399         passphrase = __connman_iface_find_passphrase(iface, ssid);
400         if (passphrase != NULL) {
401                 DBG("network %s passphrase %s", ssid, passphrase);
402
403                 g_free(iface->network.identifier);
404                 iface->network.identifier = g_strdup(ssid);
405                 g_free(iface->network.passphrase);
406                 iface->network.passphrase = passphrase;
407
408                 __connman_iface_connect(iface, &iface->network);
409
410                 iface->state = CONNMAN_IFACE_STATE_CONNECT;
411                 state_changed(iface);
412         }
413
414         free(ssid);
415 }
416
417 int connman_iface_get_ipv4(struct connman_iface *iface,
418                                                 struct connman_ipv4 *ipv4)
419 {
420 #if 0
421         struct {
422                 struct nlmsghdr hdr;
423                 struct rtgenmsg msg;
424         } req;
425
426         if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
427                 return -1;
428
429         DBG("iface %p ipv4 %p", iface, ipv4);
430
431         memset(&req, 0, sizeof(req));
432         req.hdr.nlmsg_len = sizeof(req.hdr) + sizeof(req.msg);
433         req.hdr.nlmsg_type = RTM_GETADDR;
434         req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
435         req.hdr.nlmsg_pid = 0;
436         req.hdr.nlmsg_seq = 4711;
437         req.msg.rtgen_family = AF_INET;
438
439         __connman_rtnl_send(&req, sizeof(req));
440 #endif
441
442         return 0;
443 }
444
445 int connman_iface_set_ipv4(struct connman_iface *iface,
446                                                 struct connman_ipv4 *ipv4)
447 {
448         struct ifreq ifr;
449         struct rtentry rt;
450         struct sockaddr_in *addr;
451         int sk, err;
452
453         if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
454                 return -1;
455
456         DBG("iface %p ipv4 %p", iface, ipv4);
457
458         sk = socket(PF_INET, SOCK_DGRAM, 0);
459         if (sk < 0)
460                 return -1;
461
462         memset(&ifr, 0, sizeof(ifr));
463         ifr.ifr_ifindex = iface->index;
464
465         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
466                 close(sk);
467                 return -1;
468         }
469
470         DBG("ifname %s", ifr.ifr_name);
471
472         addr = (struct sockaddr_in *) &ifr.ifr_addr;
473         addr->sin_family = AF_INET;
474         addr->sin_addr = ipv4->address;
475
476         err = ioctl(sk, SIOCSIFADDR, &ifr);
477
478         if (err < 0)
479                 DBG("address setting failed (%s)", strerror(errno));
480
481         addr = (struct sockaddr_in *) &ifr.ifr_netmask;
482         addr->sin_family = AF_INET;
483         addr->sin_addr = ipv4->netmask;
484
485         err = ioctl(sk, SIOCSIFNETMASK, &ifr);
486
487         if (err < 0)
488                 DBG("netmask setting failed (%s)", strerror(errno));
489
490         addr = (struct sockaddr_in *) &ifr.ifr_broadaddr;
491         addr->sin_family = AF_INET;
492         addr->sin_addr = ipv4->broadcast;
493
494         err = ioctl(sk, SIOCSIFBRDADDR, &ifr);
495
496         if (err < 0)
497                 DBG("broadcast setting failed (%s)", strerror(errno));
498
499         memset(&rt, 0, sizeof(rt));
500         rt.rt_flags = RTF_UP | RTF_GATEWAY;
501
502         addr = (struct sockaddr_in *) &rt.rt_dst;
503         addr->sin_family = AF_INET;
504         addr->sin_addr.s_addr = INADDR_ANY;
505
506         addr = (struct sockaddr_in *) &rt.rt_gateway;
507         addr->sin_family = AF_INET;
508         addr->sin_addr = ipv4->gateway;
509
510         addr = (struct sockaddr_in *) &rt.rt_genmask;
511         addr->sin_family = AF_INET;
512         addr->sin_addr.s_addr = INADDR_ANY;
513
514         err = ioctl(sk, SIOCADDRT, &rt);
515
516         close(sk);
517
518         if (err < 0) {
519                 DBG("default route failed (%s)", strerror(errno));
520                 return -1;
521         }
522
523         __connman_resolver_append(iface, inet_ntoa(ipv4->nameserver));
524
525         return 0;
526 }
527
528 int connman_iface_clear_ipv4(struct connman_iface *iface)
529 {
530         struct ifreq ifr;
531         struct sockaddr_in *addr;
532         int sk, err;
533
534         if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
535                 return -1;
536
537         DBG("iface %p", iface);
538
539         sk = socket(PF_INET, SOCK_DGRAM, 0);
540         if (sk < 0)
541                 return -1;
542
543         memset(&ifr, 0, sizeof(ifr));
544         ifr.ifr_ifindex = iface->index;
545
546         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
547                 close(sk);
548                 return -1;
549         }
550
551         DBG("ifname %s", ifr.ifr_name);
552
553         addr = (struct sockaddr_in *) &ifr.ifr_addr;
554         addr->sin_family = AF_INET;
555         addr->sin_addr.s_addr = INADDR_ANY;
556
557         //err = ioctl(sk, SIOCDIFADDR, &ifr);
558         err = ioctl(sk, SIOCSIFADDR, &ifr);
559
560         close(sk);
561
562         if (err < 0 && errno != EADDRNOTAVAIL) {
563                 DBG("address removal failed (%s)", strerror(errno));
564                 return -1;
565         }
566
567         __connman_resolver_remove(iface);
568
569         return 0;
570 }
571
572 static DBusMessage *scan_iface(DBusConnection *conn,
573                                         DBusMessage *msg, void *data)
574 {
575         struct connman_iface *iface = data;
576         struct connman_iface_driver *driver = iface->driver;
577         DBusMessage *reply;
578
579         DBG("conn %p", conn);
580
581         reply = dbus_message_new_method_return(msg);
582         if (reply == NULL)
583                 return NULL;
584
585         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
586
587         switch (iface->state) {
588         case CONNMAN_IFACE_STATE_CONNECT:
589         case CONNMAN_IFACE_STATE_CONFIGURE:
590                         return reply;
591         default:
592                 break;
593         }
594
595         if (driver->scan)
596                 driver->scan(iface);
597
598         return reply;
599 }
600
601 static DBusMessage *get_properties(DBusConnection *conn,
602                                         DBusMessage *msg, void *data)
603 {
604         struct connman_iface *iface = data;
605         DBusMessage *reply;
606         DBusMessageIter array, dict;
607         const char *str;
608
609         DBG("conn %p", conn);
610
611         reply = dbus_message_new_method_return(msg);
612         if (reply == NULL)
613                 return NULL;
614
615         dbus_message_iter_init_append(reply, &array);
616
617         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
618                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
619                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
620                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
621
622         str = __connman_iface_type2string(iface->type);
623         append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
624
625         str = __connman_iface_state2string(iface->state);
626         append_entry(&dict, "State", DBUS_TYPE_STRING, &str);
627
628         if (iface->type == CONNMAN_IFACE_TYPE_80211) {
629                 dbus_uint16_t signal = 75;
630                 append_entry(&dict, "Signal", DBUS_TYPE_UINT16, &signal);
631         }
632
633         str = __connman_iface_policy2string(iface->policy);
634         append_entry(&dict, "Policy", DBUS_TYPE_STRING, &str);
635
636         if (iface->device.driver != NULL)
637                 append_entry(&dict, "Driver",
638                                 DBUS_TYPE_STRING, &iface->device.driver);
639
640         if (iface->device.vendor != NULL)
641                 append_entry(&dict, "Vendor",
642                                 DBUS_TYPE_STRING, &iface->device.vendor);
643
644         if (iface->device.product != NULL)
645                 append_entry(&dict, "Product",
646                                 DBUS_TYPE_STRING, &iface->device.product);
647
648         dbus_message_iter_close_container(&array, &dict);
649
650         return reply;
651 }
652
653 static DBusMessage *get_state(DBusConnection *conn,
654                                         DBusMessage *msg, void *data)
655 {
656         struct connman_iface *iface = data;
657         DBusMessage *reply;
658         const char *state;
659
660         DBG("conn %p", conn);
661
662         reply = dbus_message_new_method_return(msg);
663         if (reply == NULL)
664                 return NULL;
665
666         state = __connman_iface_state2string(iface->state);
667
668         dbus_message_append_args(reply, DBUS_TYPE_STRING, &state,
669                                                         DBUS_TYPE_INVALID);
670
671         return reply;
672 }
673
674 static DBusMessage *get_signal(DBusConnection *conn,
675                                         DBusMessage *msg, void *data)
676 {
677         struct connman_iface *iface = data;
678         DBusMessage *reply;
679         dbus_uint16_t signal;
680
681         DBG("conn %p", conn);
682
683         reply = dbus_message_new_method_return(msg);
684         if (reply == NULL)
685                 return NULL;
686
687         if (iface->type == CONNMAN_IFACE_TYPE_80211)
688                 signal = 75;
689         else
690                 signal = 0;
691
692         dbus_message_append_args(reply, DBUS_TYPE_UINT16, &signal,
693                                                         DBUS_TYPE_INVALID);
694
695         return reply;
696 }
697
698 static DBusMessage *get_policy(DBusConnection *conn,
699                                         DBusMessage *msg, void *data)
700 {
701         struct connman_iface *iface = data;
702         DBusMessage *reply;
703         const char *policy;
704
705         DBG("conn %p", conn);
706
707         reply = dbus_message_new_method_return(msg);
708         if (reply == NULL)
709                 return NULL;
710
711         policy = __connman_iface_policy2string(iface->policy);
712
713         dbus_message_append_args(reply, DBUS_TYPE_STRING, &policy,
714                                                         DBUS_TYPE_INVALID);
715
716         return reply;
717 }
718
719 static DBusMessage *set_policy(DBusConnection *conn,
720                                         DBusMessage *msg, void *data)
721 {
722         struct connman_iface *iface = data;
723         DBusMessage *reply;
724         enum connman_iface_policy new_policy;
725         const char *policy;
726
727         DBG("conn %p", conn);
728
729         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &policy,
730                                                         DBUS_TYPE_INVALID);
731
732         new_policy = __connman_iface_string2policy(policy);
733
734         reply = dbus_message_new_method_return(msg);
735         if (reply == NULL)
736                 return NULL;
737
738         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
739
740         if (iface->policy != new_policy) {
741                 iface->policy = new_policy;
742                 __connman_iface_store(iface);
743
744                 switch_policy(iface);
745                 policy = __connman_iface_policy2string(new_policy);
746
747                 g_dbus_emit_signal(conn, iface->path, CONNMAN_IFACE_INTERFACE,
748                                 "PolicyChanged", DBUS_TYPE_STRING, &policy,
749                                                         DBUS_TYPE_INVALID);
750         }
751
752         return reply;
753 }
754
755 static void append_network(DBusMessage *reply,
756                                 struct connman_iface *iface, gboolean secrets)
757 {
758         DBusMessageIter array, dict;
759
760         dbus_message_iter_init_append(reply, &array);
761
762         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
763                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
764                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
765                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
766
767         switch (iface->type) {
768         case CONNMAN_IFACE_TYPE_80211:
769                 if (iface->network.identifier != NULL)
770                         append_entry(&dict, "ESSID",
771                                 DBUS_TYPE_STRING, &iface->network.identifier);
772                 if (secrets == TRUE && iface->network.passphrase != NULL)
773                         append_entry(&dict, "PSK",
774                                 DBUS_TYPE_STRING, &iface->network.passphrase);
775                 break;
776         default:
777                 break;
778         }
779
780         dbus_message_iter_close_container(&array, &dict);
781 }
782
783 static DBusMessage *get_network(DBusConnection *conn,
784                                         DBusMessage *msg, void *data)
785 {
786         struct connman_iface *iface = data;
787         DBusMessage *reply;
788
789         DBG("conn %p", conn);
790
791         reply = dbus_message_new_method_return(msg);
792         if (reply == NULL)
793                 return NULL;
794
795         append_network(reply, iface, TRUE);
796
797         return reply;
798 }
799
800 static DBusMessage *set_network(DBusConnection *conn,
801                                         DBusMessage *msg, void *data)
802 {
803         struct connman_iface *iface = data;
804         DBusMessage *reply, *signal;
805         DBusMessageIter array, dict;
806         gboolean changed = FALSE;
807
808         DBG("conn %p", conn);
809
810         dbus_message_iter_init(msg, &array);
811
812         dbus_message_iter_recurse(&array, &dict);
813
814         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
815                 DBusMessageIter entry, value;
816                 const char *key, *val;
817
818                 dbus_message_iter_recurse(&dict, &entry);
819                 dbus_message_iter_get_basic(&entry, &key);
820
821                 dbus_message_iter_next(&entry);
822
823                 dbus_message_iter_recurse(&entry, &value);
824
825                 //type = dbus_message_iter_get_arg_type(&value);
826                 dbus_message_iter_get_basic(&value, &val);
827
828                 if (g_strcasecmp(key, "ESSID") == 0) {
829                         g_free(iface->network.identifier);
830                         iface->network.identifier = g_strdup(val);
831                         changed = TRUE;
832                 }
833
834                 if (g_strcasecmp(key, "PSK") == 0) {
835                         g_free(iface->network.passphrase);
836                         iface->network.passphrase = g_strdup(val);
837                         changed = TRUE;
838                 }
839
840                 dbus_message_iter_next(&dict);
841         }
842
843         reply = dbus_message_new_method_return(msg);
844         if (reply == NULL)
845                 return NULL;
846
847         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
848
849         if (changed == TRUE) {
850                 __connman_iface_store(iface);
851
852                 signal = dbus_message_new_signal(iface->path,
853                                 CONNMAN_IFACE_INTERFACE, "NetworkChanged");
854                 if (signal != NULL) {
855                         append_network(signal, iface, FALSE);
856                         dbus_connection_send(conn, signal, NULL);
857                         dbus_message_unref(signal);
858                 }
859
860                 __connman_iface_connect(iface, &iface->network);
861         }
862
863         return reply;
864 }
865
866 static DBusMessage *list_networks(DBusConnection *conn,
867                                         DBusMessage *msg, void *data)
868 {
869         struct connman_iface *iface = data;
870         DBusMessage *reply;
871         DBusMessageIter array, iter;
872
873         DBG("conn %p", conn);
874
875         reply = dbus_message_new_method_return(msg);
876         if (reply == NULL)
877                 return NULL;
878
879         dbus_message_iter_init_append(reply, &array);
880
881         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
882                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
883
884         __connman_iface_network_list(iface, &iter);
885
886         dbus_message_iter_close_container(&array, &iter);
887
888         return reply;
889 }
890
891 static DBusMessage *create_network(DBusConnection *conn,
892                                         DBusMessage *msg, void *data)
893 {
894         struct connman_iface *iface = data;
895         DBusMessage *reply;
896         DBusMessageIter array, dict;
897         const char *path, *identifier = NULL, *passphrase = NULL;
898
899         DBG("conn %p", conn);
900
901         dbus_message_iter_init(msg, &array);
902
903         dbus_message_iter_recurse(&array, &dict);
904
905         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
906                 DBusMessageIter entry, value;
907                 const char *key, *val;
908
909                 dbus_message_iter_recurse(&dict, &entry);
910                 dbus_message_iter_get_basic(&entry, &key);
911
912                 dbus_message_iter_next(&entry);
913
914                 dbus_message_iter_recurse(&entry, &value);
915
916                 //type = dbus_message_iter_get_arg_type(&value);
917                 dbus_message_iter_get_basic(&value, &val);
918
919                 if (g_strcasecmp(key, "Identifier") == 0)
920                         identifier = val;
921
922                 if (g_strcasecmp(key, "Passphrase") == 0)
923                         passphrase = val;
924
925                 dbus_message_iter_next(&dict);
926         }
927
928         DBG("identifier %s passphrase %s", identifier, passphrase);
929
930         path = __connman_iface_add_network(iface, identifier, passphrase);
931
932         reply = dbus_message_new_method_return(msg);
933         if (reply == NULL)
934                 return NULL;
935
936         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
937                                                         DBUS_TYPE_INVALID);
938
939         return reply;
940 }
941
942 static DBusMessage *remove_network(DBusConnection *conn,
943                                         DBusMessage *msg, void *data)
944 {
945         struct connman_iface *iface = data;
946         DBusMessage *reply;
947         const char *path;
948
949         DBG("conn %p", conn);
950
951         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
952                                                         DBUS_TYPE_INVALID);
953
954         __connman_iface_remove_network(iface, path);
955
956         reply = dbus_message_new_method_return(msg);
957         if (reply == NULL)
958                 return NULL;
959
960         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
961
962         return reply;
963 }
964
965 static DBusMessage *select_network(DBusConnection *conn,
966                                         DBusMessage *msg, void *data)
967 {
968         struct connman_iface *iface = data;
969         struct connman_network *network;
970         DBusMessage *reply;
971         const char *path;
972
973         DBG("conn %p", conn);
974
975         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
976                                                         DBUS_TYPE_INVALID);
977
978         network = __connman_iface_find_network(iface, path);
979         if (network == NULL)
980                 goto done;
981
982         g_free(iface->network.identifier);
983         iface->network.identifier = g_strdup(network->identifier);
984         g_free(iface->network.passphrase);
985         iface->network.passphrase = g_strdup(network->passphrase);
986
987         __connman_iface_connect(iface, &iface->network);
988
989 done:
990         reply = dbus_message_new_method_return(msg);
991         if (reply == NULL)
992                 return NULL;
993
994         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
995
996         return reply;
997 }
998
999 static void append_ipv4(DBusMessage *reply, struct connman_iface *iface)
1000 {
1001         DBusMessageIter array, dict;
1002         const char *str;
1003
1004         dbus_message_iter_init_append(reply, &array);
1005
1006         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
1007                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1008                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
1009                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
1010
1011         str = __connman_ipv4_method2string(CONNMAN_IPV4_METHOD_DHCP);
1012         append_entry(&dict, "Method", DBUS_TYPE_STRING, &str);
1013
1014         if (iface->ipv4.address.s_addr != INADDR_ANY) {
1015                 str = inet_ntoa(iface->ipv4.address);
1016                 append_entry(&dict, "Address", DBUS_TYPE_STRING, &str);
1017         }
1018
1019         if (iface->ipv4.netmask.s_addr != INADDR_ANY) {
1020                 str = inet_ntoa(iface->ipv4.netmask);
1021                 append_entry(&dict, "Netmask", DBUS_TYPE_STRING, &str);
1022         }
1023
1024         if (iface->ipv4.gateway.s_addr != INADDR_ANY) {
1025                 str = inet_ntoa(iface->ipv4.gateway);
1026                 append_entry(&dict, "Gateway", DBUS_TYPE_STRING, &str);
1027         }
1028
1029         dbus_message_iter_close_container(&array, &dict);
1030 }
1031
1032 static DBusMessage *get_ipv4(DBusConnection *conn,
1033                                         DBusMessage *msg, void *data)
1034 {
1035         struct connman_iface *iface = data;
1036         DBusMessage *reply;
1037
1038         DBG("conn %p", conn);
1039
1040         switch (iface->policy) {
1041         case CONNMAN_IFACE_POLICY_OFF:
1042         case CONNMAN_IFACE_POLICY_IGNORE:
1043                 return dbus_message_new_error(msg, CONNMAN_ERROR_INTERFACE
1044                                                 ".NotAvailable", "");
1045         default:
1046                 break;
1047         }
1048
1049         reply = dbus_message_new_method_return(msg);
1050         if (reply == NULL)
1051                 return NULL;
1052
1053         append_ipv4(reply, iface);
1054
1055         return reply;
1056 }
1057
1058 static DBusMessage *set_ipv4(DBusConnection *conn,
1059                                         DBusMessage *msg, void *data)
1060 {
1061         struct connman_iface *iface = data;
1062         DBusMessage *reply, *signal;
1063         DBusMessageIter array, dict;
1064         gboolean changed = FALSE;
1065
1066         DBG("conn %p", conn);
1067
1068         return dbus_message_new_error(msg, CONNMAN_ERROR_INTERFACE
1069                                                 ".NotImplemented", "");
1070
1071         dbus_message_iter_init(msg, &array);
1072
1073         dbus_message_iter_recurse(&array, &dict);
1074
1075         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1076                 DBusMessageIter entry, value;
1077                 const char *key, *val;
1078                 enum connman_ipv4_method method;
1079                 in_addr_t addr;
1080
1081                 dbus_message_iter_recurse(&dict, &entry);
1082                 dbus_message_iter_get_basic(&entry, &key);
1083
1084                 dbus_message_iter_next(&entry);
1085
1086                 dbus_message_iter_recurse(&entry, &value);
1087
1088                 //type = dbus_message_iter_get_arg_type(&value);
1089                 dbus_message_iter_get_basic(&value, &val);
1090
1091                 if (g_strcasecmp(key, "Method") == 0) {
1092                         method = __connman_ipv4_string2method(val);
1093                         if (iface->ipv4.method != method) {
1094                                 iface->ipv4.method = method;
1095                                 changed = TRUE;
1096                         }
1097                 }
1098
1099                 if (g_strcasecmp(key, "Address") == 0) {
1100                         addr = inet_addr(val);
1101                         if (iface->ipv4.address.s_addr != addr) {
1102                                 iface->ipv4.address.s_addr = addr;
1103                                 changed = TRUE;
1104                         }
1105                 }
1106
1107                 if (g_strcasecmp(key, "Netmask") == 0) {
1108                         addr = inet_addr(val);
1109                         if (iface->ipv4.netmask.s_addr != addr) {
1110                                 iface->ipv4.netmask.s_addr = addr;
1111                                 changed = TRUE;
1112                         }
1113                 }
1114
1115                 if (g_strcasecmp(key, "Gateway") == 0) {
1116                         addr = inet_addr(val);
1117                         if (iface->ipv4.gateway.s_addr != addr) {
1118                                 iface->ipv4.gateway.s_addr = addr;
1119                                 changed = TRUE;
1120                         }
1121                 }
1122
1123                 dbus_message_iter_next(&dict);
1124         }
1125
1126         reply = dbus_message_new_method_return(msg);
1127         if (reply == NULL)
1128                 return NULL;
1129
1130         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
1131
1132         if (changed == TRUE) {
1133                 __connman_iface_store(iface);
1134
1135                 signal = dbus_message_new_signal(iface->path,
1136                                 CONNMAN_IFACE_INTERFACE, "IPv4Changed");
1137                 if (signal != NULL) {
1138                         append_ipv4(signal, iface);
1139                         dbus_connection_send(conn, signal, NULL);
1140                         dbus_message_unref(signal);
1141                 }
1142         }
1143
1144         return reply;
1145 }
1146
1147 static GDBusMethodTable iface_methods[] = {
1148         { "Scan",          "",      "",      scan_iface     },
1149         { "GetProperties", "",      "a{sv}", get_properties },
1150         { "GetState",      "",      "s",     get_state      },
1151         { "GetSignal",     "",      "q",     get_signal     },
1152         { "GetPolicy",     "",      "s",     get_policy     },
1153         { "SetPolicy",     "s",     "",      set_policy     },
1154         { "GetNetwork",    "",      "a{sv}", get_network    },
1155         { "SetNetwork",    "a{sv}", "",      set_network    },
1156         { "ListNetworks",  "",      "ao",    list_networks  },
1157         { "CreateNetwork", "a{av}", "o",     create_network },
1158         { "RemoveNetwork", "o",     "",      remove_network },
1159         { "SelectNetwork", "o",     "",      select_network },
1160         { "GetIPv4",       "",      "a{sv}", get_ipv4       },
1161         { "SetIPv4",       "a{sv}", "",      set_ipv4       },
1162         { },
1163 };
1164
1165 static GDBusSignalTable iface_signals[] = {
1166         { "StateChanged",   "s"     },
1167         { "SignalChanged",  "q"     },
1168         { "PolicyChanged",  "s"     },
1169         { "NetworkFound",   "a{sv}" },
1170         { "NetworkChanged", "a{sv}" },
1171         { "IPv4Changed",    "a{sv}" },
1172         { },
1173 };
1174
1175 static void device_free(void *data)
1176 {
1177         struct connman_iface *iface = data;
1178
1179         DBG("iface %p", iface);
1180
1181         connman_iface_clear_ipv4(iface);
1182
1183         if (iface->driver && iface->driver->remove)
1184                 iface->driver->remove(iface);
1185
1186         g_free(iface->path);
1187         g_free(iface->udi);
1188         g_free(iface->sysfs);
1189         g_free(iface->identifier);
1190         g_free(iface->network.identifier);
1191         g_free(iface->network.passphrase);
1192         g_free(iface->device.driver);
1193         g_free(iface->device.vendor);
1194         g_free(iface->device.product);
1195         g_free(iface);
1196 }
1197
1198 static void detect_device_info(LibHalContext *ctx, struct connman_iface *iface)
1199 {
1200         char *parent, *subsys, *value;
1201
1202         parent = libhal_device_get_property_string(ctx, iface->udi,
1203                                                 "info.parent", NULL);
1204
1205         subsys = libhal_device_get_property_string(ctx, iface->udi,
1206                                                 "linux.subsystem", NULL);
1207
1208         value = libhal_device_get_property_string(ctx, iface->udi,
1209                                                 "info.linux.driver", NULL);
1210         if (value == NULL) {
1211                 value = libhal_device_get_property_string(ctx, parent,
1212                                                 "info.linux.driver", NULL);
1213                 if (value != NULL)
1214                         iface->device.driver = g_strdup(value);
1215         }
1216
1217         if (strcmp(subsys, "net") == 0) {
1218                 value = libhal_device_get_property_string(ctx, parent,
1219                                                         "info.vendor", NULL);
1220                 if (value != NULL)
1221                         iface->device.vendor = g_strdup(value);
1222
1223                 value = libhal_device_get_property_string(ctx, parent,
1224                                                         "info.product", NULL);
1225                 if (value != NULL)
1226                         iface->device.product = g_strdup(value);
1227         }
1228 }
1229
1230 static int probe_device(LibHalContext *ctx,
1231                         struct connman_iface_driver *driver, const char *udi)
1232 {
1233         DBusConnection *conn;
1234         struct connman_iface *iface;
1235         char *temp, *sysfs, *ifname;
1236         int err;
1237
1238         DBG("ctx %p driver %p udi %s", ctx, driver, udi);
1239
1240         if (!driver->probe)
1241                 return -1;
1242
1243         iface = g_try_new0(struct connman_iface, 1);
1244         if (iface == NULL)
1245                 return -1;
1246
1247         temp = g_path_get_basename(udi);
1248         iface->path = g_strdup_printf("%s/%s", CONNMAN_IFACE_BASEPATH, temp);
1249         g_free(temp);
1250
1251         iface->udi = g_strdup(udi);
1252
1253         DBG("iface %p path %s", iface, iface->path);
1254
1255         sysfs = libhal_device_get_property_string(ctx, udi,
1256                                                 "linux.sysfs_path", NULL);
1257         if (sysfs != NULL)
1258                 iface->sysfs = g_strdup(sysfs);
1259
1260         detect_device_info(ctx, iface);
1261
1262         iface->index = -1;
1263
1264         if (g_str_has_prefix(driver->capability, "net") == TRUE) {
1265                 iface->index = libhal_device_get_property_int(ctx, udi,
1266                                                 "net.linux.ifindex", NULL);
1267
1268                 ifname = libhal_device_get_property_string(ctx, udi,
1269                                                 "net.interface", NULL);
1270                 if (ifname != NULL && ifname_filter != NULL &&
1271                                 g_str_equal(ifname, ifname_filter) == FALSE) {
1272                         device_free(iface);
1273                         return -1;
1274                 }
1275         }
1276
1277         iface->type = CONNMAN_IFACE_TYPE_UNKNOWN;
1278         iface->flags = 0;
1279         iface->state = CONNMAN_IFACE_STATE_UNKNOWN;
1280         iface->policy = CONNMAN_IFACE_POLICY_UNKNOWN;
1281
1282         err = driver->probe(iface);
1283         if (err < 0) {
1284                 device_free(iface);
1285                 return -1;
1286         }
1287
1288         __connman_iface_create_identifier(iface);
1289
1290         __connman_iface_init_via_inet(iface);
1291
1292         iface->driver = driver;
1293
1294         iface->policy = CONNMAN_IFACE_POLICY_AUTO;
1295
1296         __connman_iface_load(iface);
1297
1298         DBG("iface %p network %s secret %s", iface,
1299                                         iface->network.identifier,
1300                                         iface->network.passphrase);
1301
1302         conn = libhal_ctx_get_dbus_connection(ctx);
1303
1304         interfaces = g_slist_append(interfaces, iface);
1305
1306         if (iface->flags & CONNMAN_IFACE_FLAG_IPV4) {
1307                 connman_iface_get_ipv4(iface, &iface->ipv4);
1308
1309                 DBG("address %s", inet_ntoa(iface->ipv4.address));
1310         }
1311
1312         g_dbus_register_interface(conn, iface->path,
1313                                         CONNMAN_IFACE_INTERFACE,
1314                                         iface_methods, iface_signals, NULL,
1315                                                         iface, device_free);
1316
1317         DBG("iface %p identifier %s", iface, iface->identifier);
1318
1319         g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
1320                                         CONNMAN_MANAGER_INTERFACE,
1321                                         "InterfaceAdded",
1322                                         DBUS_TYPE_OBJECT_PATH, &iface->path,
1323                                         DBUS_TYPE_INVALID);
1324
1325         __connman_iface_load_networks(iface);
1326
1327         switch_policy(iface);
1328
1329         state_changed(iface);
1330
1331         return 0;
1332 }
1333
1334 static void device_added(LibHalContext *ctx, const char *udi)
1335 {
1336         GSList *list;
1337
1338         DBG("ctx %p udi %s", ctx, udi);
1339
1340         for (list = drivers; list; list = list->next) {
1341                 struct connman_iface_driver *driver = list->data;
1342
1343                 if (driver->capability == NULL)
1344                         continue;
1345
1346                 if (libhal_device_query_capability(ctx, udi,
1347                                         driver->capability, NULL) == TRUE) {
1348                         if (probe_device(ctx, driver, udi) == 0)
1349                                 break;
1350                 }
1351         }
1352 }
1353
1354 static void device_removed(LibHalContext *ctx, const char *udi)
1355 {
1356         DBusConnection *conn;
1357         GSList *list;
1358
1359         DBG("ctx %p udi %s", ctx, udi);
1360
1361         conn = libhal_ctx_get_dbus_connection(ctx);
1362
1363         for (list = interfaces; list; list = list->next) {
1364                 struct connman_iface *iface = list->data;
1365
1366                 if (strcmp(udi, iface->udi) == 0) {
1367                         g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
1368                                         CONNMAN_MANAGER_INTERFACE,
1369                                         "InterfaceRemoved",
1370                                         DBUS_TYPE_OBJECT_PATH, &iface->path,
1371                                         DBUS_TYPE_INVALID);
1372                         interfaces = g_slist_remove(interfaces, iface);
1373                         g_dbus_unregister_interface(conn, iface->path,
1374                                                 CONNMAN_IFACE_INTERFACE);
1375                         break;
1376                 }
1377         }
1378 }
1379
1380 static void probe_driver(LibHalContext *ctx,
1381                                 struct connman_iface_driver *driver)
1382 {
1383         char **list;
1384         int num;
1385
1386         DBG("ctx %p driver %p", ctx, driver);
1387
1388         list = libhal_find_device_by_capability(ctx,
1389                                         driver->capability, &num, NULL);
1390         if (list) {
1391                 char **tmp = list;
1392
1393                 while (*tmp) {
1394                         probe_device(ctx, driver, *tmp);
1395                         tmp++;
1396                 }
1397
1398                 libhal_free_string_array(list);
1399         }
1400 }
1401
1402 static void find_devices(LibHalContext *ctx)
1403 {
1404         GSList *list;
1405
1406         DBG("ctx %p", ctx);
1407
1408         for (list = drivers; list; list = list->next) {
1409                 struct connman_iface_driver *driver = list->data;
1410
1411                 DBG("driver %p", driver);
1412
1413                 if (driver->capability == NULL)
1414                         continue;
1415
1416                 probe_driver(ctx, driver);
1417         }
1418 }
1419
1420 static LibHalContext *hal_ctx = NULL;
1421
1422 static void hal_init(void *data)
1423 {
1424         DBusConnection *conn = data;
1425
1426         DBG("conn %p", conn);
1427
1428         if (hal_ctx != NULL)
1429                 return;
1430
1431         hal_ctx = libhal_ctx_new();
1432         if (hal_ctx == NULL)
1433                 return;
1434
1435         if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) {
1436                 libhal_ctx_free(hal_ctx);
1437                 return;
1438         }
1439
1440         if (libhal_ctx_init(hal_ctx, NULL) == FALSE) {
1441                 libhal_ctx_free(hal_ctx);
1442                 return ;
1443         }
1444
1445         libhal_ctx_set_device_added(hal_ctx, device_added);
1446         libhal_ctx_set_device_removed(hal_ctx, device_removed);
1447
1448         //libhal_ctx_set_device_new_capability(hal_ctx, new_capability);
1449         //libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability);
1450
1451         find_devices(hal_ctx);
1452 }
1453
1454 static void hal_cleanup(void *data)
1455 {
1456         DBusConnection *conn = data;
1457         GSList *list;
1458
1459         DBG("conn %p", conn);
1460
1461         if (hal_ctx == NULL)
1462                 return;
1463
1464         for (list = interfaces; list; list = list->next) {
1465                 struct connman_iface *iface = list->data;
1466
1467                 DBG("path %s", iface->path);
1468
1469                 g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
1470                                         CONNMAN_MANAGER_INTERFACE,
1471                                         "InterfaceRemoved",
1472                                         DBUS_TYPE_OBJECT_PATH, &iface->path,
1473                                         DBUS_TYPE_INVALID);
1474
1475                 g_dbus_unregister_interface(conn, iface->path,
1476                                                 CONNMAN_IFACE_INTERFACE);
1477         }
1478
1479         g_slist_free(interfaces);
1480
1481         interfaces = NULL;
1482
1483         libhal_ctx_shutdown(hal_ctx, NULL);
1484
1485         libhal_ctx_free(hal_ctx);
1486
1487         hal_ctx = NULL;
1488 }
1489
1490 static guint hal_watch = 0;
1491
1492 int __connman_iface_init(DBusConnection *conn, const char *interface)
1493 {
1494         DBG("conn %p", conn);
1495
1496         connection = dbus_connection_ref(conn);
1497         if (connection == NULL)
1498                 return -1;
1499
1500         if (interface != NULL)
1501                 ifname_filter = g_strdup(interface);
1502
1503         hal_init(connection);
1504
1505         hal_watch = g_dbus_add_service_watch(connection, "org.freedesktop.Hal",
1506                                 hal_init, hal_cleanup, connection, NULL);
1507
1508         return 0;
1509 }
1510
1511 void __connman_iface_cleanup(void)
1512 {
1513         DBG("conn %p", connection);
1514
1515         g_dbus_remove_watch(connection, hal_watch);
1516
1517         hal_cleanup(connection);
1518
1519         g_free(ifname_filter);
1520
1521         dbus_connection_unref(connection);
1522 }