Add support to get PMF information
[platform/upstream/connman.git] / src / ipconfig.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2013  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 <errno.h>
27 #include <stdio.h>
28 #include <net/if.h>
29 #include <net/if_arp.h>
30 #include <linux/if_link.h>
31 #include <string.h>
32 #include <stdlib.h>
33
34 #ifndef IFF_LOWER_UP
35 #define IFF_LOWER_UP    0x10000
36 #endif
37
38 #include <gdbus.h>
39 #include <connman/ipaddress.h>
40
41 #include "connman.h"
42
43 struct connman_ipconfig {
44         int refcount;
45         int index;
46         enum connman_ipconfig_type type;
47
48         const struct connman_ipconfig_ops *ops;
49         void *ops_data;
50
51         enum connman_ipconfig_method method;
52         struct connman_ipaddress *address;
53         struct connman_ipaddress *system;
54
55 #if defined TIZEN_EXT
56         int dhcp_lease_duration;
57 #endif
58
59         int ipv6_privacy_config;
60         char *last_dhcp_address;
61         char **last_dhcpv6_prefixes;
62 };
63
64 struct connman_ipdevice {
65         int index;
66         unsigned short type;
67         unsigned int flags;
68         char *address;
69         uint16_t mtu;
70         uint32_t rx_packets;
71         uint32_t tx_packets;
72         uint32_t rx_bytes;
73         uint32_t tx_bytes;
74         uint32_t rx_errors;
75         uint32_t tx_errors;
76         uint32_t rx_dropped;
77         uint32_t tx_dropped;
78
79         GSList *address_list;
80         char *ipv4_gateway;
81         char *ipv6_gateway;
82
83         char *pac;
84
85         struct connman_ipconfig *config_ipv4;
86         struct connman_ipconfig *config_ipv6;
87
88         bool ipv6_enabled;
89         int ipv6_privacy;
90 };
91
92 struct ipconfig_store {
93         GKeyFile *file;
94         const char *group;
95         const char *prefix;
96 };
97
98 static GHashTable *ipdevice_hash = NULL;
99 static GList *ipconfig_list = NULL;
100 static bool is_ipv6_supported = false;
101
102 static void store_set_str(struct ipconfig_store *store,
103                         const char *key, const char *val)
104
105 {
106         char *pk;
107
108         if (!val || strlen(val) == 0)
109                 return;
110
111         pk = g_strdup_printf("%s%s", store->prefix, key);
112         g_key_file_set_string(store->file, store->group, pk, val);
113         g_free(pk);
114 }
115
116 static char *store_get_str(struct ipconfig_store *store, const char *key)
117 {
118         char *pk, *val;
119
120         pk = g_strdup_printf("%s%s", store->prefix, key);
121         val = g_key_file_get_string(store->file, store->group, pk, NULL);
122         g_free(pk);
123
124         return val;
125 }
126
127 static void store_set_strs(struct ipconfig_store *store,
128                         const char *key, char **val)
129 {
130         guint len;
131         char *pk;
132
133         if (!val)
134                 return;
135
136         len = g_strv_length(val);
137         if (len == 0)
138                 return;
139
140         pk = g_strdup_printf("%s%s", store->prefix, key);
141         g_key_file_set_string_list(store->file, store->group,
142                                 pk, (const gchar **)val, len);
143         g_free(pk);
144 }
145
146 static char **store_get_strs(struct ipconfig_store *store, const char *key)
147 {
148         gsize len;
149         char *pk, **val;
150
151         pk = g_strdup_printf("%s%s", store->prefix, key);
152         val = g_key_file_get_string_list(store->file, store->group,
153                                         pk, &len, NULL);
154         g_free(pk);
155
156         if (val && len == 0) {
157                 g_free(val);
158                 return NULL;
159         }
160
161         return val;
162 }
163
164 static void store_set_int(struct ipconfig_store *store,
165                         const char *key, int val)
166 {
167         char *pk;
168
169         if (val == 0)
170                 return;
171
172         pk = g_strdup_printf("%s%s", store->prefix, key);
173         g_key_file_set_integer(store->file, store->group, pk, val);
174         g_free(pk);
175 }
176
177 static int store_get_int(struct ipconfig_store *store, const char *key)
178 {
179         int val;
180         char *pk;
181
182         pk = g_strdup_printf("%s%s", store->prefix, key);
183         val = g_key_file_get_integer(store->file, store->group, pk, 0);
184         g_free(pk);
185
186         return val;
187 }
188
189 static void free_address_list(struct connman_ipdevice *ipdevice)
190 {
191         GSList *list;
192
193         for (list = ipdevice->address_list; list; list = list->next) {
194                 struct connman_ipaddress *ipaddress = list->data;
195
196                 connman_ipaddress_free(ipaddress);
197                 list->data = NULL;
198         }
199
200         g_slist_free(ipdevice->address_list);
201         ipdevice->address_list = NULL;
202 }
203
204 static struct connman_ipaddress *find_ipaddress(struct connman_ipdevice *ipdevice,
205                                 unsigned char prefixlen, const char *local)
206 {
207         GSList *list;
208
209         for (list = ipdevice->address_list; list; list = list->next) {
210                 struct connman_ipaddress *ipaddress = list->data;
211
212                 if (g_strcmp0(ipaddress->local, local) == 0 &&
213                                         ipaddress->prefixlen == prefixlen)
214                         return ipaddress;
215         }
216
217         return NULL;
218 }
219
220 const char *__connman_ipconfig_type2string(enum connman_ipconfig_type type)
221 {
222         switch (type) {
223         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
224         case CONNMAN_IPCONFIG_TYPE_ALL:
225                 return "unknown";
226         case CONNMAN_IPCONFIG_TYPE_IPV4:
227                 return "IPv4";
228         case CONNMAN_IPCONFIG_TYPE_IPV6:
229                 return "IPv6";
230         }
231
232         return NULL;
233 }
234
235 static const char *type2str(unsigned short type)
236 {
237         switch (type) {
238         case ARPHRD_ETHER:
239                 return "ETHER";
240         case ARPHRD_LOOPBACK:
241                 return "LOOPBACK";
242         case ARPHRD_PPP:
243                 return "PPP";
244         case ARPHRD_NONE:
245                 return "NONE";
246         case ARPHRD_VOID:
247                 return "VOID";
248         }
249
250         return "";
251 }
252
253 static const char *scope2str(unsigned char scope)
254 {
255         switch (scope) {
256         case 0:
257                 return "UNIVERSE";
258         case 253:
259                 return "LINK";
260         }
261
262         return "";
263 }
264
265 static bool get_ipv6_state(gchar *ifname)
266 {
267         int disabled;
268         gchar *path;
269         FILE *f;
270         bool enabled = false;
271
272         if (!ifname)
273                 path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
274         else
275                 path = g_strdup_printf(
276                         "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
277
278         if (!path)
279                 return enabled;
280
281         f = fopen(path, "r");
282
283         g_free(path);
284
285         if (f) {
286                 if (fscanf(f, "%d", &disabled) > 0)
287                         enabled = !disabled;
288                 fclose(f);
289         }
290
291         return enabled;
292 }
293
294 static void set_ipv6_state(gchar *ifname, bool enable)
295 {
296         gchar *path;
297         FILE *f;
298
299         if (!ifname)
300                 path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
301         else
302                 path = g_strdup_printf(
303                         "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
304
305         if (!path)
306                 return;
307
308         f = fopen(path, "r+");
309
310         g_free(path);
311
312         if (!f)
313                 return;
314
315         if (!enable)
316                 fprintf(f, "1");
317         else
318                 fprintf(f, "0");
319
320         fclose(f);
321 }
322
323 static int get_ipv6_privacy(gchar *ifname)
324 {
325         gchar *path;
326         FILE *f;
327         int value;
328
329         if (!ifname)
330                 return 0;
331
332         path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
333                                                                 ifname);
334
335         if (!path)
336                 return 0;
337
338         f = fopen(path, "r");
339
340         g_free(path);
341
342         if (!f)
343                 return 0;
344
345         if (fscanf(f, "%d", &value) <= 0)
346                 value = 0;
347
348         fclose(f);
349
350         return value;
351 }
352
353 /* Enable the IPv6 privacy extension for stateless address autoconfiguration.
354  * The privacy extension is described in RFC 3041 and RFC 4941
355  */
356 static void set_ipv6_privacy(gchar *ifname, int value)
357 {
358         gchar *path;
359         FILE *f;
360
361         if (!ifname)
362                 return;
363
364         path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
365                                                                 ifname);
366
367         if (!path)
368                 return;
369
370         if (value < 0)
371                 value = 0;
372
373         f = fopen(path, "r+");
374
375         g_free(path);
376
377         if (!f)
378                 return;
379
380         fprintf(f, "%d", value);
381         fclose(f);
382 }
383
384 static int get_rp_filter(void)
385 {
386         FILE *f;
387         int value = -EINVAL, tmp;
388
389         f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r");
390
391         if (f) {
392                 if (fscanf(f, "%d", &tmp) == 1)
393                         value = tmp;
394                 fclose(f);
395         }
396
397         return value;
398 }
399
400 static void set_rp_filter(int value)
401 {
402         FILE *f;
403
404         f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r+");
405
406         if (!f)
407                 return;
408
409         fprintf(f, "%d", value);
410
411         fclose(f);
412 }
413
414 int __connman_ipconfig_set_rp_filter()
415 {
416         int value;
417
418         value = get_rp_filter();
419
420         if (value < 0)
421                 return value;
422
423         set_rp_filter(2);
424
425         connman_info("rp_filter set to 2 (loose mode routing), "
426                         "old value was %d", value);
427
428         return value;
429 }
430
431 void __connman_ipconfig_unset_rp_filter(int old_value)
432 {
433         set_rp_filter(old_value);
434
435         connman_info("rp_filter restored to %d", old_value);
436 }
437
438 bool __connman_ipconfig_ipv6_privacy_enabled(struct connman_ipconfig *ipconfig)
439 {
440         if (!ipconfig)
441                 return false;
442
443         return ipconfig->ipv6_privacy_config == 0 ? FALSE : TRUE;
444 }
445
446 bool __connman_ipconfig_ipv6_is_enabled(struct connman_ipconfig *ipconfig)
447 {
448         struct connman_ipdevice *ipdevice;
449         char *ifname;
450         bool ret;
451
452         if (!ipconfig)
453                 return false;
454
455         ipdevice = g_hash_table_lookup(ipdevice_hash,
456                                         GINT_TO_POINTER(ipconfig->index));
457         if (!ipdevice)
458                 return false;
459
460         ifname = connman_inet_ifname(ipconfig->index);
461         ret = get_ipv6_state(ifname);
462         g_free(ifname);
463
464         return ret;
465 }
466
467 static void free_ipdevice(gpointer data)
468 {
469         struct connman_ipdevice *ipdevice = data;
470         char *ifname = connman_inet_ifname(ipdevice->index);
471
472         connman_info("%s {remove} index %d", ifname, ipdevice->index);
473
474         if (ipdevice->config_ipv4) {
475                 __connman_ipconfig_unref(ipdevice->config_ipv4);
476                 ipdevice->config_ipv4 = NULL;
477         }
478
479         if (ipdevice->config_ipv6) {
480                 __connman_ipconfig_unref(ipdevice->config_ipv6);
481                 ipdevice->config_ipv6 = NULL;
482         }
483
484         free_address_list(ipdevice);
485         g_free(ipdevice->ipv4_gateway);
486         g_free(ipdevice->ipv6_gateway);
487         g_free(ipdevice->pac);
488
489         g_free(ipdevice->address);
490
491         if (ifname) {
492                 set_ipv6_state(ifname, ipdevice->ipv6_enabled);
493                 set_ipv6_privacy(ifname, ipdevice->ipv6_privacy);
494         }
495
496         g_free(ifname);
497         g_free(ipdevice);
498 }
499
500 static void update_stats(struct connman_ipdevice *ipdevice,
501                         const char *ifname, struct rtnl_link_stats *stats)
502 {
503         struct connman_service *service;
504
505         if (stats->rx_packets == 0 && stats->tx_packets == 0)
506                 return;
507
508         connman_info("%s {RX} %u packets %u bytes", ifname,
509                                         stats->rx_packets, stats->rx_bytes);
510         connman_info("%s {TX} %u packets %u bytes", ifname,
511                                         stats->tx_packets, stats->tx_bytes);
512
513         if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
514                 return;
515
516         service = __connman_service_lookup_from_index(ipdevice->index);
517
518         DBG("service %p", service);
519
520         if (!service)
521                 return;
522
523         ipdevice->rx_packets = stats->rx_packets;
524         ipdevice->tx_packets = stats->tx_packets;
525         ipdevice->rx_bytes = stats->rx_bytes;
526         ipdevice->tx_bytes = stats->tx_bytes;
527         ipdevice->rx_errors = stats->rx_errors;
528         ipdevice->tx_errors = stats->tx_errors;
529         ipdevice->rx_dropped = stats->rx_dropped;
530         ipdevice->tx_dropped = stats->tx_dropped;
531
532         __connman_service_notify(service,
533                                 ipdevice->rx_packets, ipdevice->tx_packets,
534                                 ipdevice->rx_bytes, ipdevice->tx_bytes,
535                                 ipdevice->rx_errors, ipdevice->tx_errors,
536                                 ipdevice->rx_dropped, ipdevice->tx_dropped);
537 }
538
539 void __connman_ipconfig_newlink(int index, unsigned short type,
540                                 unsigned int flags, const char *address,
541                                                         unsigned short mtu,
542                                                 struct rtnl_link_stats *stats)
543 {
544         struct connman_ipdevice *ipdevice;
545         GList *list, *ipconfig_copy;
546         GString *str;
547         bool up = false, down = false;
548         bool lower_up = false, lower_down = false;
549         char *ifname;
550
551         DBG("index %d", index);
552
553         if (type == ARPHRD_LOOPBACK)
554                 return;
555
556         ifname = connman_inet_ifname(index);
557
558         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
559         if (ipdevice)
560                 goto update;
561
562         ipdevice = g_try_new0(struct connman_ipdevice, 1);
563         if (!ipdevice)
564                 goto out;
565
566         ipdevice->index = index;
567         ipdevice->type = type;
568
569         ipdevice->ipv6_enabled = get_ipv6_state(ifname);
570         ipdevice->ipv6_privacy = get_ipv6_privacy(ifname);
571
572         ipdevice->address = g_strdup(address);
573
574         g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
575
576         connman_info("%s {create} index %d type %d <%s>", ifname,
577                                                 index, type, type2str(type));
578
579 update:
580 #if defined TIZEN_EXT
581         if (g_strcmp0(ipdevice->address, address) != 0) {
582                 /* If an original address is built-in physical device,
583                  * it's hardly get an address at a initial creation
584                  */
585                 g_free(ipdevice->address);
586                 ipdevice->address = g_strdup(address);
587         }
588 #endif
589
590         ipdevice->mtu = mtu;
591
592         update_stats(ipdevice, ifname, stats);
593
594         if (flags == ipdevice->flags)
595                 goto out;
596
597         if ((ipdevice->flags & IFF_UP) != (flags & IFF_UP)) {
598                 if (flags & IFF_UP)
599                         up = true;
600                 else
601                         down = true;
602         }
603
604         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) !=
605                                 (flags & (IFF_RUNNING | IFF_LOWER_UP))) {
606                 if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
607                                         (IFF_RUNNING | IFF_LOWER_UP))
608                         lower_up = true;
609                 else if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
610                         lower_down = true;
611         }
612
613         ipdevice->flags = flags;
614
615         str = g_string_new(NULL);
616         if (!str)
617                 goto out;
618
619         if (flags & IFF_UP)
620                 g_string_append(str, "UP");
621         else
622                 g_string_append(str, "DOWN");
623
624         if (flags & IFF_RUNNING)
625                 g_string_append(str, ",RUNNING");
626
627         if (flags & IFF_LOWER_UP)
628                 g_string_append(str, ",LOWER_UP");
629
630         connman_info("%s {update} flags %u <%s>", ifname, flags, str->str);
631
632         g_string_free(str, TRUE);
633
634         ipconfig_copy = g_list_copy(ipconfig_list);
635
636         for (list = g_list_first(ipconfig_copy); list;
637                                                 list = g_list_next(list)) {
638                 struct connman_ipconfig *ipconfig = list->data;
639
640                 if (index != ipconfig->index)
641                         continue;
642
643                 if (!ipconfig->ops)
644                         continue;
645
646                 if (up && ipconfig->ops->up)
647                         ipconfig->ops->up(ipconfig, ifname);
648                 if (lower_up && ipconfig->ops->lower_up)
649                         ipconfig->ops->lower_up(ipconfig, ifname);
650
651                 if (lower_down && ipconfig->ops->lower_down)
652                         ipconfig->ops->lower_down(ipconfig, ifname);
653                 if (down && ipconfig->ops->down)
654                         ipconfig->ops->down(ipconfig, ifname);
655         }
656
657         g_list_free(ipconfig_copy);
658
659 out:
660         g_free(ifname);
661 }
662
663 void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats)
664 {
665         struct connman_ipdevice *ipdevice;
666         GList *list;
667         char *ifname;
668
669         DBG("index %d", index);
670
671         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
672         if (!ipdevice)
673                 return;
674
675         ifname = connman_inet_ifname(index);
676
677         update_stats(ipdevice, ifname, stats);
678
679         for (list = g_list_first(ipconfig_list); list;
680                                                 list = g_list_next(list)) {
681                 struct connman_ipconfig *ipconfig = list->data;
682
683                 if (index != ipconfig->index)
684                         continue;
685
686                 ipconfig->index = -1;
687
688                 if (!ipconfig->ops)
689                         continue;
690
691                 if (ipconfig->ops->lower_down)
692                         ipconfig->ops->lower_down(ipconfig, ifname);
693                 if (ipconfig->ops->down)
694                         ipconfig->ops->down(ipconfig, ifname);
695         }
696
697         g_free(ifname);
698
699         g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
700 }
701
702 static inline gint check_duplicate_address(gconstpointer a, gconstpointer b)
703 {
704         const struct connman_ipaddress *addr1 = a;
705         const struct connman_ipaddress *addr2 = b;
706
707         if (addr1->prefixlen != addr2->prefixlen)
708                 return addr2->prefixlen - addr1->prefixlen;
709
710         return g_strcmp0(addr1->local, addr2->local);
711 }
712
713 int __connman_ipconfig_newaddr(int index, int family, const char *label,
714                                 unsigned char prefixlen, const char *address)
715 {
716         struct connman_ipdevice *ipdevice;
717         struct connman_ipaddress *ipaddress;
718         enum connman_ipconfig_type type;
719         GList *list;
720         char *ifname;
721
722         DBG("index %d", index);
723
724         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
725         if (!ipdevice)
726                 return -ENXIO;
727
728         ipaddress = connman_ipaddress_alloc(family);
729         if (!ipaddress)
730                 return -ENOMEM;
731
732         ipaddress->prefixlen = prefixlen;
733         ipaddress->local = g_strdup(address);
734
735         if (g_slist_find_custom(ipdevice->address_list, ipaddress,
736                                         check_duplicate_address)) {
737                 connman_ipaddress_free(ipaddress);
738                 return -EALREADY;
739         }
740
741         if (family == AF_INET)
742                 type = CONNMAN_IPCONFIG_TYPE_IPV4;
743         else if (family == AF_INET6)
744                 type = CONNMAN_IPCONFIG_TYPE_IPV6;
745         else
746                 return -EINVAL;
747
748         ipdevice->address_list = g_slist_prepend(ipdevice->address_list,
749                                                                 ipaddress);
750
751         ifname = connman_inet_ifname(index);
752         connman_info("%s {add} address %s/%u label %s family %d",
753                 ifname, address, prefixlen, label, family);
754
755         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
756                 __connman_ippool_newaddr(index, address, prefixlen);
757
758         if (ipdevice->config_ipv4 && family == AF_INET)
759                 connman_ipaddress_copy_address(ipdevice->config_ipv4->system,
760                                         ipaddress);
761
762         else if (ipdevice->config_ipv6 && family == AF_INET6)
763                 connman_ipaddress_copy_address(ipdevice->config_ipv6->system,
764                                         ipaddress);
765         else
766                 goto out;
767
768         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
769                 goto out;
770
771         for (list = g_list_first(ipconfig_list); list;
772                                                 list = g_list_next(list)) {
773                 struct connman_ipconfig *ipconfig = list->data;
774
775                 if (index != ipconfig->index)
776                         continue;
777
778                 if (type != ipconfig->type)
779                         continue;
780
781                 if (!ipconfig->ops)
782                         continue;
783
784                 if (ipconfig->ops->ip_bound)
785                         ipconfig->ops->ip_bound(ipconfig, ifname);
786         }
787
788 out:
789         g_free(ifname);
790         return 0;
791 }
792
793 void __connman_ipconfig_deladdr(int index, int family, const char *label,
794                                 unsigned char prefixlen, const char *address)
795 {
796         struct connman_ipdevice *ipdevice;
797         struct connman_ipaddress *ipaddress;
798         enum connman_ipconfig_type type;
799         GList *list;
800         char *ifname;
801
802         DBG("index %d", index);
803
804         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
805         if (!ipdevice)
806                 return;
807
808         ipaddress = find_ipaddress(ipdevice, prefixlen, address);
809         if (!ipaddress)
810                 return;
811
812         if (family == AF_INET)
813                 type = CONNMAN_IPCONFIG_TYPE_IPV4;
814         else if (family == AF_INET6)
815                 type = CONNMAN_IPCONFIG_TYPE_IPV6;
816         else
817                 return;
818
819         ipdevice->address_list = g_slist_remove(ipdevice->address_list,
820                                                                 ipaddress);
821
822         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
823                 __connman_ippool_deladdr(index, address, prefixlen);
824
825         connman_ipaddress_clear(ipaddress);
826         g_free(ipaddress);
827
828         ifname = connman_inet_ifname(index);
829         connman_info("%s {del} address %s/%u label %s", ifname,
830                                                 address, prefixlen, label);
831
832         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
833                 goto out;
834
835         if (g_slist_length(ipdevice->address_list) > 0)
836                 goto out;
837
838         for (list = g_list_first(ipconfig_list); list;
839                                                 list = g_list_next(list)) {
840                 struct connman_ipconfig *ipconfig = list->data;
841
842                 if (index != ipconfig->index)
843                         continue;
844
845                 if (type != ipconfig->type)
846                         continue;
847
848                 if (!ipconfig->ops)
849                         continue;
850
851                 if (ipconfig->ops->ip_release)
852                         ipconfig->ops->ip_release(ipconfig, ifname);
853         }
854
855 out:
856         g_free(ifname);
857 }
858
859 void __connman_ipconfig_newroute(int index, int family, unsigned char scope,
860                                         const char *dst, const char *gateway)
861 {
862         struct connman_ipdevice *ipdevice;
863         char *ifname;
864
865         DBG("index %d", index);
866
867         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
868         if (!ipdevice)
869                 return;
870
871         ifname = connman_inet_ifname(index);
872
873         if (scope == 0 && (g_strcmp0(dst, "0.0.0.0") == 0 ||
874                                                 g_strcmp0(dst, "::") == 0)) {
875                 GList *config_list;
876                 enum connman_ipconfig_type type;
877
878                 if (family == AF_INET6) {
879                         type = CONNMAN_IPCONFIG_TYPE_IPV6;
880                         g_free(ipdevice->ipv6_gateway);
881                         ipdevice->ipv6_gateway = g_strdup(gateway);
882
883                         if (ipdevice->config_ipv6 &&
884                                 ipdevice->config_ipv6->system) {
885                                 g_free(ipdevice->config_ipv6->system->gateway);
886                                 ipdevice->config_ipv6->system->gateway =
887                                         g_strdup(gateway);
888                         }
889                 } else if (family == AF_INET) {
890                         type = CONNMAN_IPCONFIG_TYPE_IPV4;
891                         g_free(ipdevice->ipv4_gateway);
892                         ipdevice->ipv4_gateway = g_strdup(gateway);
893
894                         if (ipdevice->config_ipv4 &&
895                                 ipdevice->config_ipv4->system) {
896                                 g_free(ipdevice->config_ipv4->system->gateway);
897                                 ipdevice->config_ipv4->system->gateway =
898                                         g_strdup(gateway);
899                         }
900                 } else
901                         goto out;
902
903                 for (config_list = g_list_first(ipconfig_list); config_list;
904                                         config_list = g_list_next(config_list)) {
905                         struct connman_ipconfig *ipconfig = config_list->data;
906
907                         if (index != ipconfig->index)
908                                 continue;
909
910                         if (type != ipconfig->type)
911                                 continue;
912
913                         if (!ipconfig->ops)
914                                 continue;
915
916                         if (ipconfig->ops->route_set)
917                                 ipconfig->ops->route_set(ipconfig, ifname);
918                 }
919         }
920
921         connman_info("%s {add} route %s gw %s scope %u <%s>",
922                 ifname, dst, gateway, scope, scope2str(scope));
923
924 out:
925         g_free(ifname);
926 }
927
928 void __connman_ipconfig_delroute(int index, int family, unsigned char scope,
929                                         const char *dst, const char *gateway)
930 {
931         struct connman_ipdevice *ipdevice;
932         char *ifname;
933
934         DBG("index %d", index);
935
936         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
937         if (!ipdevice)
938                 return;
939
940         ifname = connman_inet_ifname(index);
941
942         if (scope == 0 && (g_strcmp0(dst, "0.0.0.0") == 0 ||
943                                                 g_strcmp0(dst, "::") == 0)) {
944                 GList *config_list;
945                 enum connman_ipconfig_type type;
946
947                 if (family == AF_INET6) {
948                         type = CONNMAN_IPCONFIG_TYPE_IPV6;
949                         g_free(ipdevice->ipv6_gateway);
950                         ipdevice->ipv6_gateway = NULL;
951
952                         if (ipdevice->config_ipv6 &&
953                                 ipdevice->config_ipv6->system) {
954                                 g_free(ipdevice->config_ipv6->system->gateway);
955                                 ipdevice->config_ipv6->system->gateway = NULL;
956                         }
957                 } else if (family == AF_INET) {
958                         type = CONNMAN_IPCONFIG_TYPE_IPV4;
959                         g_free(ipdevice->ipv4_gateway);
960                         ipdevice->ipv4_gateway = NULL;
961
962                         if (ipdevice->config_ipv4 &&
963                                 ipdevice->config_ipv4->system) {
964                                 g_free(ipdevice->config_ipv4->system->gateway);
965                                 ipdevice->config_ipv4->system->gateway = NULL;
966                         }
967                 } else
968                         goto out;
969
970                 for (config_list = g_list_first(ipconfig_list); config_list;
971                                         config_list = g_list_next(config_list)) {
972                         struct connman_ipconfig *ipconfig = config_list->data;
973
974                         if (index != ipconfig->index)
975                                 continue;
976
977                         if (type != ipconfig->type)
978                                 continue;
979
980                         if (!ipconfig->ops)
981                                 continue;
982
983                         if (ipconfig->ops->route_unset)
984                                 ipconfig->ops->route_unset(ipconfig, ifname);
985                 }
986         }
987
988         connman_info("%s {del} route %s gw %s scope %u <%s>",
989                 ifname, dst, gateway, scope, scope2str(scope));
990
991 out:
992         g_free(ifname);
993 }
994
995 void __connman_ipconfig_foreach(void (*function) (int index, void *user_data),
996                                                         void *user_data)
997 {
998         GList *list, *keys;
999
1000         keys = g_hash_table_get_keys(ipdevice_hash);
1001         if (!keys)
1002                 return;
1003
1004         for (list = g_list_first(keys); list; list = g_list_next(list)) {
1005                 int index = GPOINTER_TO_INT(list->data);
1006
1007                 function(index, user_data);
1008         }
1009
1010         g_list_free(keys);
1011 }
1012
1013 enum connman_ipconfig_type __connman_ipconfig_get_config_type(
1014                                         struct connman_ipconfig *ipconfig)
1015 {
1016         return ipconfig ? ipconfig->type : CONNMAN_IPCONFIG_TYPE_UNKNOWN;
1017 }
1018
1019 unsigned short __connman_ipconfig_get_type_from_index(int index)
1020 {
1021         struct connman_ipdevice *ipdevice;
1022
1023         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1024         if (!ipdevice)
1025                 return ARPHRD_VOID;
1026
1027         return ipdevice->type;
1028 }
1029
1030 unsigned int __connman_ipconfig_get_flags_from_index(int index)
1031 {
1032         struct connman_ipdevice *ipdevice;
1033
1034         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1035         if (!ipdevice)
1036                 return 0;
1037
1038         return ipdevice->flags;
1039 }
1040
1041 const char *__connman_ipconfig_get_gateway_from_index(int index,
1042         enum connman_ipconfig_type type)
1043 {
1044         struct connman_ipdevice *ipdevice;
1045
1046         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1047         if (!ipdevice)
1048                 return NULL;
1049
1050         if (type != CONNMAN_IPCONFIG_TYPE_IPV6) {
1051                 if (ipdevice->ipv4_gateway)
1052                         return ipdevice->ipv4_gateway;
1053
1054                 if (ipdevice->config_ipv4 &&
1055                                 ipdevice->config_ipv4->address)
1056                         return ipdevice->config_ipv4->address->gateway;
1057         }
1058
1059         if (type != CONNMAN_IPCONFIG_TYPE_IPV4) {
1060                 if (ipdevice->ipv6_gateway)
1061                         return ipdevice->ipv6_gateway;
1062
1063                 if (ipdevice->config_ipv6 &&
1064                                 ipdevice->config_ipv6->address)
1065                         return ipdevice->config_ipv6->address->gateway;
1066         }
1067
1068         return NULL;
1069 }
1070
1071 void __connman_ipconfig_set_index(struct connman_ipconfig *ipconfig, int index)
1072 {
1073         ipconfig->index = index;
1074 }
1075
1076 const char *__connman_ipconfig_get_local(struct connman_ipconfig *ipconfig)
1077 {
1078         if (!ipconfig->address)
1079                 return NULL;
1080
1081         return ipconfig->address->local;
1082 }
1083
1084 void __connman_ipconfig_set_local(struct connman_ipconfig *ipconfig,
1085                                         const char *address)
1086 {
1087         if (!ipconfig->address)
1088                 return;
1089
1090         g_free(ipconfig->address->local);
1091         ipconfig->address->local = g_strdup(address);
1092 }
1093
1094 const char *__connman_ipconfig_get_peer(struct connman_ipconfig *ipconfig)
1095 {
1096         if (!ipconfig->address)
1097                 return NULL;
1098
1099         return ipconfig->address->peer;
1100 }
1101
1102 void __connman_ipconfig_set_peer(struct connman_ipconfig *ipconfig,
1103                                         const char *address)
1104 {
1105         if (!ipconfig->address)
1106                 return;
1107
1108         g_free(ipconfig->address->peer);
1109         ipconfig->address->peer = g_strdup(address);
1110 }
1111
1112 const char *__connman_ipconfig_get_broadcast(struct connman_ipconfig *ipconfig)
1113 {
1114         if (!ipconfig->address)
1115                 return NULL;
1116
1117         return ipconfig->address->broadcast;
1118 }
1119
1120 void __connman_ipconfig_set_broadcast(struct connman_ipconfig *ipconfig,
1121                                         const char *broadcast)
1122 {
1123         if (!ipconfig->address)
1124                 return;
1125
1126         g_free(ipconfig->address->broadcast);
1127         ipconfig->address->broadcast = g_strdup(broadcast);
1128 }
1129
1130 const char *__connman_ipconfig_get_gateway(struct connman_ipconfig *ipconfig)
1131 {
1132         if (!ipconfig->address)
1133                 return NULL;
1134
1135         return ipconfig->address->gateway;
1136 }
1137
1138 void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig,
1139                                         const char *gateway)
1140 {
1141         DBG("");
1142
1143         if (!ipconfig->address)
1144                 return;
1145         g_free(ipconfig->address->gateway);
1146         ipconfig->address->gateway = g_strdup(gateway);
1147 }
1148
1149 #if defined TIZEN_EXT
1150 void __connman_ipconfig_set_dhcp_lease_duration(struct connman_ipconfig *ipconfig,
1151                 int dhcp_lease_duration)
1152 {
1153         ipconfig->dhcp_lease_duration = dhcp_lease_duration;
1154 }
1155 #endif
1156
1157 #if defined TIZEN_EXT
1158 int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig, struct connman_service *service)
1159 #else
1160 int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig)
1161 #endif
1162 {
1163 #if !defined TIZEN_EXT
1164         struct connman_service *service;
1165 #endif
1166
1167         DBG("");
1168
1169         if (!ipconfig->address)
1170                 return -EINVAL;
1171
1172 #if !defined TIZEN_EXT
1173         service = __connman_service_lookup_from_index(ipconfig->index);
1174 #endif
1175         if (!service)
1176                 return -EINVAL;
1177
1178         DBG("type %d gw %s peer %s", ipconfig->type,
1179                 ipconfig->address->gateway, ipconfig->address->peer);
1180
1181         if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6 ||
1182                                 ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1183                 return __connman_connection_gateway_add(service,
1184                                                 ipconfig->address->gateway,
1185                                                 ipconfig->type,
1186                                                 ipconfig->address->peer);
1187
1188         return 0;
1189 }
1190
1191 void __connman_ipconfig_gateway_remove(struct connman_ipconfig *ipconfig)
1192 {
1193         struct connman_service *service;
1194
1195         DBG("");
1196
1197         service = __connman_service_lookup_from_index(ipconfig->index);
1198         if (service)
1199                 __connman_connection_gateway_remove(service, ipconfig->type);
1200 }
1201
1202 unsigned char __connman_ipconfig_get_prefixlen(struct connman_ipconfig *ipconfig)
1203 {
1204         if (!ipconfig->address)
1205                 return 0;
1206
1207         return ipconfig->address->prefixlen;
1208 }
1209
1210 void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig,
1211                                         unsigned char prefixlen)
1212 {
1213         if (!ipconfig->address)
1214                 return;
1215
1216         ipconfig->address->prefixlen = prefixlen;
1217 }
1218
1219 static struct connman_ipconfig *create_ipv6config(int index)
1220 {
1221         struct connman_ipconfig *ipv6config;
1222         struct connman_ipdevice *ipdevice;
1223
1224         ipv6config = g_try_new0(struct connman_ipconfig, 1);
1225         if (!ipv6config)
1226                 return NULL;
1227
1228         ipv6config->refcount = 1;
1229
1230         ipv6config->index = index;
1231         ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6;
1232
1233         if (!is_ipv6_supported)
1234                 ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF;
1235         else
1236                 ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO;
1237
1238         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1239         if (ipdevice)
1240 #if !defined TIZEN_EXT
1241                 ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy;
1242 #else
1243                 ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy = 2;
1244 #endif
1245
1246         ipv6config->address = connman_ipaddress_alloc(AF_INET6);
1247         if (!ipv6config->address) {
1248                 g_free(ipv6config);
1249                 return NULL;
1250         }
1251
1252         ipv6config->system = connman_ipaddress_alloc(AF_INET6);
1253
1254         DBG("ipconfig %p index %d method %s", ipv6config, index,
1255                 __connman_ipconfig_method2string(ipv6config->method));
1256
1257         return ipv6config;
1258 }
1259
1260 /**
1261  * connman_ipconfig_create:
1262  *
1263  * Allocate a new ipconfig structure.
1264  *
1265  * Returns: a newly-allocated #connman_ipconfig structure
1266  */
1267 struct connman_ipconfig *__connman_ipconfig_create(int index,
1268                                         enum connman_ipconfig_type type)
1269 {
1270         struct connman_ipconfig *ipconfig;
1271
1272         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1273                 return create_ipv6config(index);
1274
1275         ipconfig = g_try_new0(struct connman_ipconfig, 1);
1276         if (!ipconfig)
1277                 return NULL;
1278
1279         ipconfig->refcount = 1;
1280
1281         ipconfig->index = index;
1282         ipconfig->type = CONNMAN_IPCONFIG_TYPE_IPV4;
1283
1284         ipconfig->address = connman_ipaddress_alloc(AF_INET);
1285         if (!ipconfig->address) {
1286                 g_free(ipconfig);
1287                 return NULL;
1288         }
1289
1290         ipconfig->system = connman_ipaddress_alloc(AF_INET);
1291 #if defined TIZEN_EXT
1292         if (!simplified_log)
1293 #endif
1294         DBG("ipconfig %p index %d", ipconfig, index);
1295
1296         return ipconfig;
1297 }
1298
1299
1300 /**
1301  * connman_ipconfig_ref:
1302  * @ipconfig: ipconfig structure
1303  *
1304  * Increase reference counter of ipconfig
1305  */
1306 struct connman_ipconfig *
1307 __connman_ipconfig_ref_debug(struct connman_ipconfig *ipconfig,
1308                                 const char *file, int line, const char *caller)
1309 {
1310         DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount + 1,
1311                 file, line, caller);
1312
1313         __sync_fetch_and_add(&ipconfig->refcount, 1);
1314
1315         return ipconfig;
1316 }
1317
1318 /**
1319  * connman_ipconfig_unref:
1320  * @ipconfig: ipconfig structure
1321  *
1322  * Decrease reference counter of ipconfig
1323  */
1324 void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig,
1325                                 const char *file, int line, const char *caller)
1326 {
1327         if (!ipconfig)
1328                 return;
1329 #if defined TIZEN_EXT
1330         if (!simplified_log)
1331 #endif
1332         DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount - 1,
1333                 file, line, caller);
1334
1335         if (__sync_fetch_and_sub(&ipconfig->refcount, 1) != 1)
1336                 return;
1337
1338         if (__connman_ipconfig_disable(ipconfig) < 0)
1339                 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1340
1341         __connman_ipconfig_set_ops(ipconfig, NULL);
1342
1343         connman_ipaddress_free(ipconfig->system);
1344         connman_ipaddress_free(ipconfig->address);
1345         g_free(ipconfig->last_dhcp_address);
1346         g_strfreev(ipconfig->last_dhcpv6_prefixes);
1347         g_free(ipconfig);
1348 }
1349
1350 /**
1351  * connman_ipconfig_get_data:
1352  * @ipconfig: ipconfig structure
1353  *
1354  * Get private data pointer
1355  */
1356 void *__connman_ipconfig_get_data(struct connman_ipconfig *ipconfig)
1357 {
1358         if (!ipconfig)
1359                 return NULL;
1360
1361         return ipconfig->ops_data;
1362 }
1363
1364 /**
1365  * connman_ipconfig_set_data:
1366  * @ipconfig: ipconfig structure
1367  * @data: data pointer
1368  *
1369  * Set private data pointer
1370  */
1371 void __connman_ipconfig_set_data(struct connman_ipconfig *ipconfig, void *data)
1372 {
1373         ipconfig->ops_data = data;
1374 }
1375
1376 /**
1377  * connman_ipconfig_get_index:
1378  * @ipconfig: ipconfig structure
1379  *
1380  * Get interface index
1381  */
1382 int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
1383 {
1384         if (!ipconfig)
1385                 return -1;
1386
1387         return ipconfig->index;
1388 }
1389
1390 /**
1391  * connman_ipconfig_set_ops:
1392  * @ipconfig: ipconfig structure
1393  * @ops: operation callbacks
1394  *
1395  * Set the operation callbacks
1396  */
1397 void __connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
1398                                 const struct connman_ipconfig_ops *ops)
1399 {
1400         ipconfig->ops = ops;
1401 }
1402
1403 /**
1404  * connman_ipconfig_set_method:
1405  * @ipconfig: ipconfig structure
1406  * @method: configuration method
1407  *
1408  * Set the configuration method
1409  */
1410 int __connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
1411                                         enum connman_ipconfig_method method)
1412 {
1413         ipconfig->method = method;
1414
1415         return 0;
1416 }
1417
1418 enum connman_ipconfig_method __connman_ipconfig_get_method(
1419                                 struct connman_ipconfig *ipconfig)
1420 {
1421         if (!ipconfig)
1422                 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1423
1424         return ipconfig->method;
1425 }
1426
1427 int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig)
1428 {
1429         switch (ipconfig->method) {
1430         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1431         case CONNMAN_IPCONFIG_METHOD_OFF:
1432                 break;
1433         case CONNMAN_IPCONFIG_METHOD_AUTO:
1434         case CONNMAN_IPCONFIG_METHOD_FIXED:
1435         case CONNMAN_IPCONFIG_METHOD_DHCP:
1436         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1437                 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1438                         return connman_inet_set_address(ipconfig->index,
1439                                                         ipconfig->address);
1440                 else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
1441                         return connman_inet_set_ipv6_address(
1442                                         ipconfig->index, ipconfig->address);
1443         }
1444
1445         return 0;
1446 }
1447
1448 int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig)
1449 {
1450         int err;
1451
1452         if (!ipconfig)
1453                 return 0;
1454
1455         switch (ipconfig->method) {
1456         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1457         case CONNMAN_IPCONFIG_METHOD_OFF:
1458                 break;
1459         case CONNMAN_IPCONFIG_METHOD_AUTO:
1460         case CONNMAN_IPCONFIG_METHOD_DHCP:
1461                 err = __connman_ipconfig_address_unset(ipconfig);
1462                 connman_ipaddress_clear(ipconfig->address);
1463
1464                 return err;
1465         case CONNMAN_IPCONFIG_METHOD_FIXED:
1466         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1467                 return __connman_ipconfig_address_unset(ipconfig);
1468         }
1469
1470         return 0;
1471 }
1472
1473 int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig)
1474 {
1475         int err;
1476
1477         if (!ipconfig)
1478                 return 0;
1479
1480 #if defined TIZEN_EXT
1481         DBG("ipconfig method %d type %d", ipconfig->method, ipconfig->type);
1482 #else
1483         DBG("method %d", ipconfig->method);
1484 #endif
1485
1486         switch (ipconfig->method) {
1487         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1488         case CONNMAN_IPCONFIG_METHOD_OFF:
1489                 break;
1490         case CONNMAN_IPCONFIG_METHOD_AUTO:
1491         case CONNMAN_IPCONFIG_METHOD_FIXED:
1492         case CONNMAN_IPCONFIG_METHOD_DHCP:
1493         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1494                 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1495                         err = connman_inet_clear_address(ipconfig->index,
1496                                                         ipconfig->address);
1497                 else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
1498                         err = connman_inet_clear_ipv6_address(
1499                                                 ipconfig->index,
1500                                                 ipconfig->address->local,
1501                                                 ipconfig->address->prefixlen);
1502                 else
1503                         err = -EINVAL;
1504
1505                 return err;
1506         }
1507
1508         return 0;
1509 }
1510
1511 int __connman_ipconfig_set_proxy_autoconfig(struct connman_ipconfig *ipconfig,
1512                                                         const char *url)
1513 {
1514         struct connman_ipdevice *ipdevice;
1515
1516         if (!ipconfig || ipconfig->index < 0)
1517                 return -ENODEV;
1518
1519         ipdevice = g_hash_table_lookup(ipdevice_hash,
1520                                         GINT_TO_POINTER(ipconfig->index));
1521         if (!ipdevice)
1522                 return -ENXIO;
1523
1524         g_free(ipdevice->pac);
1525         ipdevice->pac = g_strdup(url);
1526
1527         return 0;
1528 }
1529
1530 const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipconfig)
1531 {
1532         struct connman_ipdevice *ipdevice;
1533
1534         if (!ipconfig || ipconfig->index < 0)
1535                 return NULL;
1536
1537         ipdevice = g_hash_table_lookup(ipdevice_hash,
1538                                         GINT_TO_POINTER(ipconfig->index));
1539         if (!ipdevice)
1540                 return NULL;
1541
1542         return ipdevice->pac;
1543 }
1544
1545 void __connman_ipconfig_set_dhcp_address(struct connman_ipconfig *ipconfig,
1546                                         const char *address)
1547 {
1548         if (!ipconfig)
1549                 return;
1550
1551         g_free(ipconfig->last_dhcp_address);
1552         ipconfig->last_dhcp_address = g_strdup(address);
1553 }
1554
1555 char *__connman_ipconfig_get_dhcp_address(struct connman_ipconfig *ipconfig)
1556 {
1557         if (!ipconfig)
1558                 return NULL;
1559
1560         return ipconfig->last_dhcp_address;
1561 }
1562
1563 void __connman_ipconfig_set_dhcpv6_prefixes(struct connman_ipconfig *ipconfig,
1564                                         char **prefixes)
1565 {
1566         if (!ipconfig)
1567                 return;
1568
1569         g_strfreev(ipconfig->last_dhcpv6_prefixes);
1570         ipconfig->last_dhcpv6_prefixes = prefixes;
1571 }
1572
1573 char **__connman_ipconfig_get_dhcpv6_prefixes(struct connman_ipconfig *ipconfig)
1574 {
1575         if (!ipconfig)
1576                 return NULL;
1577
1578         return ipconfig->last_dhcpv6_prefixes;
1579 }
1580
1581 static void disable_ipv6(struct connman_ipconfig *ipconfig)
1582 {
1583         struct connman_ipdevice *ipdevice;
1584         char *ifname;
1585
1586         DBG("");
1587
1588         ipdevice = g_hash_table_lookup(ipdevice_hash,
1589                                         GINT_TO_POINTER(ipconfig->index));
1590         if (!ipdevice)
1591                 return;
1592
1593         ifname = connman_inet_ifname(ipconfig->index);
1594
1595         set_ipv6_state(ifname, false);
1596
1597         g_free(ifname);
1598 }
1599
1600 static void enable_ipv6(struct connman_ipconfig *ipconfig)
1601 {
1602         struct connman_ipdevice *ipdevice;
1603         char *ifname;
1604
1605         DBG("");
1606
1607         ipdevice = g_hash_table_lookup(ipdevice_hash,
1608                                         GINT_TO_POINTER(ipconfig->index));
1609         if (!ipdevice)
1610                 return;
1611
1612         ifname = connman_inet_ifname(ipconfig->index);
1613
1614         if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO)
1615                 set_ipv6_privacy(ifname, ipconfig->ipv6_privacy_config);
1616
1617         set_ipv6_state(ifname, true);
1618
1619         g_free(ifname);
1620 }
1621
1622 void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig)
1623 {
1624         if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1625                 return;
1626
1627         enable_ipv6(ipconfig);
1628 }
1629
1630 void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig)
1631 {
1632         if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1633                 return;
1634
1635         disable_ipv6(ipconfig);
1636 }
1637
1638 bool __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig)
1639 {
1640         if (!ipconfig)
1641                 return false;
1642
1643         switch (ipconfig->method) {
1644         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1645         case CONNMAN_IPCONFIG_METHOD_OFF:
1646                 return false;
1647         case CONNMAN_IPCONFIG_METHOD_AUTO:
1648         case CONNMAN_IPCONFIG_METHOD_FIXED:
1649         case CONNMAN_IPCONFIG_METHOD_DHCP:
1650         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1651                 break;
1652         }
1653
1654         return true;
1655 }
1656
1657 int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
1658 {
1659         struct connman_ipdevice *ipdevice;
1660         bool up = false, down = false;
1661         bool lower_up = false, lower_down = false;
1662         enum connman_ipconfig_type type;
1663         char *ifname;
1664
1665         DBG("ipconfig %p", ipconfig);
1666
1667         if (!ipconfig || ipconfig->index < 0)
1668                 return -ENODEV;
1669
1670         ipdevice = g_hash_table_lookup(ipdevice_hash,
1671                                         GINT_TO_POINTER(ipconfig->index));
1672         if (!ipdevice)
1673                 return -ENXIO;
1674
1675         if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4) {
1676                 if (ipdevice->config_ipv4 == ipconfig)
1677                         return -EALREADY;
1678                 type = CONNMAN_IPCONFIG_TYPE_IPV4;
1679         } else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
1680                 if (ipdevice->config_ipv6 == ipconfig)
1681                         return -EALREADY;
1682                 type = CONNMAN_IPCONFIG_TYPE_IPV6;
1683         } else
1684                 return -EINVAL;
1685
1686         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
1687                                         ipdevice->config_ipv4) {
1688                 ipconfig_list = g_list_remove(ipconfig_list,
1689                                                         ipdevice->config_ipv4);
1690
1691                 connman_ipaddress_clear(ipdevice->config_ipv4->system);
1692
1693                 __connman_ipconfig_unref(ipdevice->config_ipv4);
1694         }
1695
1696         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
1697                                         ipdevice->config_ipv6) {
1698                 ipconfig_list = g_list_remove(ipconfig_list,
1699                                                         ipdevice->config_ipv6);
1700
1701                 connman_ipaddress_clear(ipdevice->config_ipv6->system);
1702
1703                 __connman_ipconfig_unref(ipdevice->config_ipv6);
1704         }
1705
1706         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1707                 ipdevice->config_ipv4 = __connman_ipconfig_ref(ipconfig);
1708         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
1709                 ipdevice->config_ipv6 = __connman_ipconfig_ref(ipconfig);
1710
1711                 enable_ipv6(ipdevice->config_ipv6);
1712         }
1713         ipconfig_list = g_list_append(ipconfig_list, ipconfig);
1714
1715         if (ipdevice->flags & IFF_UP)
1716                 up = true;
1717         else
1718                 down = true;
1719
1720         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
1721                         (IFF_RUNNING | IFF_LOWER_UP))
1722                 lower_up = true;
1723         else if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
1724                 lower_down = true;
1725
1726         ifname = connman_inet_ifname(ipconfig->index);
1727
1728         if (up && ipconfig->ops->up)
1729                 ipconfig->ops->up(ipconfig, ifname);
1730         if (lower_up && ipconfig->ops->lower_up)
1731                 ipconfig->ops->lower_up(ipconfig, ifname);
1732
1733         if (lower_down && ipconfig->ops->lower_down)
1734                 ipconfig->ops->lower_down(ipconfig, ifname);
1735         if (down && ipconfig->ops->down)
1736                 ipconfig->ops->down(ipconfig, ifname);
1737
1738         g_free(ifname);
1739
1740         return 0;
1741 }
1742
1743 int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
1744 {
1745         struct connman_ipdevice *ipdevice;
1746 #if defined TIZEN_EXT
1747         if (!simplified_log)
1748 #endif
1749         DBG("ipconfig %p", ipconfig);
1750
1751         if (!ipconfig || ipconfig->index < 0)
1752                 return -ENODEV;
1753
1754         ipdevice = g_hash_table_lookup(ipdevice_hash,
1755                                         GINT_TO_POINTER(ipconfig->index));
1756         if (!ipdevice)
1757                 return -ENXIO;
1758
1759         if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
1760                 return -EINVAL;
1761
1762         if (ipdevice->config_ipv4 == ipconfig) {
1763                 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1764
1765                 connman_ipaddress_clear(ipdevice->config_ipv4->system);
1766                 __connman_ipconfig_unref(ipdevice->config_ipv4);
1767                 ipdevice->config_ipv4 = NULL;
1768                 return 0;
1769         }
1770
1771         if (ipdevice->config_ipv6 == ipconfig) {
1772                 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1773
1774 #if defined TIZEN_EXT
1775                 if (ipdevice->config_ipv6->method ==
1776                                 CONNMAN_IPCONFIG_METHOD_AUTO) {
1777                         disable_ipv6(ipdevice->config_ipv6);
1778                         enable_ipv6(ipdevice->config_ipv6);
1779                 }
1780 #endif
1781                 connman_ipaddress_clear(ipdevice->config_ipv6->system);
1782                 __connman_ipconfig_unref(ipdevice->config_ipv6);
1783                 ipdevice->config_ipv6 = NULL;
1784                 return 0;
1785         }
1786
1787         return -EINVAL;
1788 }
1789
1790 const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
1791 {
1792         switch (method) {
1793         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1794                 break;
1795         case CONNMAN_IPCONFIG_METHOD_OFF:
1796                 return "off";
1797         case CONNMAN_IPCONFIG_METHOD_FIXED:
1798                 return "fixed";
1799         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1800                 return "manual";
1801         case CONNMAN_IPCONFIG_METHOD_DHCP:
1802                 return "dhcp";
1803         case CONNMAN_IPCONFIG_METHOD_AUTO:
1804                 return "auto";
1805         }
1806
1807         return NULL;
1808 }
1809
1810 enum connman_ipconfig_method __connman_ipconfig_string2method(const char *method)
1811 {
1812         if (g_strcmp0(method, "off") == 0)
1813                 return CONNMAN_IPCONFIG_METHOD_OFF;
1814         else if (g_strcmp0(method, "fixed") == 0)
1815                 return CONNMAN_IPCONFIG_METHOD_FIXED;
1816         else if (g_strcmp0(method, "manual") == 0)
1817                 return CONNMAN_IPCONFIG_METHOD_MANUAL;
1818         else if (g_strcmp0(method, "dhcp") == 0)
1819                 return CONNMAN_IPCONFIG_METHOD_DHCP;
1820         else if (g_strcmp0(method, "auto") == 0)
1821                 return CONNMAN_IPCONFIG_METHOD_AUTO;
1822         else
1823                 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1824 }
1825
1826 static const char *privacy2string(int privacy)
1827 {
1828         if (privacy <= 0)
1829                 return "disabled";
1830         else if (privacy == 1)
1831                 return "enabled";
1832         else
1833                 return "prefered";
1834 }
1835
1836 static int string2privacy(const char *privacy)
1837 {
1838         if (g_strcmp0(privacy, "disabled") == 0)
1839                 return 0;
1840         else if (g_strcmp0(privacy, "enabled") == 0)
1841                 return 1;
1842         else if (g_strcmp0(privacy, "preferred") == 0)
1843                 return 2;
1844         else if (g_strcmp0(privacy, "prefered") == 0)
1845                 return 2;
1846         else
1847                 return 0;
1848 }
1849
1850 int __connman_ipconfig_ipv6_reset_privacy(struct connman_ipconfig *ipconfig)
1851 {
1852         struct connman_ipdevice *ipdevice;
1853         int err;
1854
1855         if (!ipconfig)
1856                 return -EINVAL;
1857
1858         ipdevice = g_hash_table_lookup(ipdevice_hash,
1859                                                 GINT_TO_POINTER(ipconfig->index));
1860         if (!ipdevice)
1861                 return -ENODEV;
1862
1863         err = __connman_ipconfig_ipv6_set_privacy(ipconfig, privacy2string(
1864                                                         ipdevice->ipv6_privacy));
1865
1866         return err;
1867 }
1868
1869 int __connman_ipconfig_ipv6_set_privacy(struct connman_ipconfig *ipconfig,
1870                                         const char *value)
1871 {
1872         int privacy;
1873
1874         if (!ipconfig)
1875                 return -EINVAL;
1876
1877         privacy = string2privacy(value);
1878
1879         ipconfig->ipv6_privacy_config = privacy;
1880
1881         enable_ipv6(ipconfig);
1882
1883         return 0;
1884 }
1885
1886 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
1887                                                         DBusMessageIter *iter)
1888 {
1889         struct connman_ipaddress *append_addr = NULL;
1890         const char *str;
1891
1892         if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
1893                 return;
1894
1895         str = __connman_ipconfig_method2string(ipconfig->method);
1896         if (!str)
1897                 return;
1898
1899         connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1900
1901         switch (ipconfig->method) {
1902         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1903         case CONNMAN_IPCONFIG_METHOD_OFF:
1904                 return;
1905
1906         case CONNMAN_IPCONFIG_METHOD_FIXED:
1907                 append_addr = ipconfig->address;
1908                 break;
1909
1910         case CONNMAN_IPCONFIG_METHOD_AUTO:
1911         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1912         case CONNMAN_IPCONFIG_METHOD_DHCP:
1913                 append_addr = ipconfig->system;
1914 #if defined TIZEN_EXT
1915                 /* TIZEN enables get_properties before __connman_ipconfig_newaddr */
1916                 if (append_addr && append_addr->local == NULL)
1917                         append_addr = ipconfig->address;
1918 #endif
1919                 break;
1920         }
1921
1922         if (!append_addr)
1923                 return;
1924
1925         if (append_addr->local) {
1926                 in_addr_t addr;
1927                 struct in_addr netmask;
1928                 char *mask;
1929
1930                 connman_dbus_dict_append_basic(iter, "Address",
1931                                 DBUS_TYPE_STRING, &append_addr->local);
1932
1933                 addr = 0xffffffff << (32 - append_addr->prefixlen);
1934                 netmask.s_addr = htonl(addr);
1935                 mask = inet_ntoa(netmask);
1936                 connman_dbus_dict_append_basic(iter, "Netmask",
1937                                                 DBUS_TYPE_STRING, &mask);
1938         }
1939
1940         if (append_addr->gateway)
1941                 connman_dbus_dict_append_basic(iter, "Gateway",
1942                                 DBUS_TYPE_STRING, &append_addr->gateway);
1943
1944 #if defined TIZEN_EXT
1945         if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_DHCP) {
1946                 char *server_ip;
1947                 server_ip = __connman_dhcp_get_server_address(ipconfig);
1948                 if (server_ip) {
1949                         connman_dbus_dict_append_basic(iter, "DHCPServerIP",
1950                                         DBUS_TYPE_STRING, &server_ip);
1951                         g_free(server_ip);
1952                 }
1953                 connman_dbus_dict_append_basic(iter, "DHCPLeaseDuration",
1954                                 DBUS_TYPE_INT32, &ipconfig->dhcp_lease_duration);
1955         }
1956 #endif
1957 }
1958
1959 void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
1960                                         DBusMessageIter *iter,
1961                                         struct connman_ipconfig *ipconfig_ipv4)
1962 {
1963         struct connman_ipaddress *append_addr = NULL;
1964         const char *str, *privacy;
1965
1966         if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1967                 return;
1968
1969         str = __connman_ipconfig_method2string(ipconfig->method);
1970         if (!str)
1971                 return;
1972
1973         if (ipconfig_ipv4 &&
1974                         ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1975                 if (__connman_6to4_check(ipconfig_ipv4) == 1)
1976                         str = "6to4";
1977         }
1978
1979         connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1980
1981         switch (ipconfig->method) {
1982         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1983         case CONNMAN_IPCONFIG_METHOD_OFF:
1984                 return;
1985
1986         case CONNMAN_IPCONFIG_METHOD_FIXED:
1987                 append_addr = ipconfig->address;
1988                 break;
1989
1990         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1991         case CONNMAN_IPCONFIG_METHOD_DHCP:
1992         case CONNMAN_IPCONFIG_METHOD_AUTO:
1993                 append_addr = ipconfig->system;
1994 #if defined TIZEN_EXT
1995                 /* TIZEN enables get_properties before __connman_ipconfig_newaddr */
1996                 if (append_addr && append_addr->local == NULL)
1997                         append_addr = ipconfig->address;
1998 #endif
1999                 break;
2000         }
2001
2002         if (!append_addr)
2003                 return;
2004
2005         if (append_addr->local) {
2006                 connman_dbus_dict_append_basic(iter, "Address",
2007                                 DBUS_TYPE_STRING, &append_addr->local);
2008                 connman_dbus_dict_append_basic(iter, "PrefixLength",
2009                                                 DBUS_TYPE_BYTE,
2010                                                 &append_addr->prefixlen);
2011         }
2012
2013         if (append_addr->gateway)
2014                 connman_dbus_dict_append_basic(iter, "Gateway",
2015                                 DBUS_TYPE_STRING, &append_addr->gateway);
2016
2017         privacy = privacy2string(ipconfig->ipv6_privacy_config);
2018         connman_dbus_dict_append_basic(iter, "Privacy",
2019                                 DBUS_TYPE_STRING, &privacy);
2020 }
2021
2022 void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig,
2023                                                         DBusMessageIter *iter)
2024 {
2025         const char *str, *privacy;
2026
2027         str = __connman_ipconfig_method2string(ipconfig->method);
2028         if (!str)
2029                 return;
2030
2031         connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
2032
2033         switch (ipconfig->method) {
2034         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2035         case CONNMAN_IPCONFIG_METHOD_OFF:
2036         case CONNMAN_IPCONFIG_METHOD_DHCP:
2037                 return;
2038         case CONNMAN_IPCONFIG_METHOD_FIXED:
2039         case CONNMAN_IPCONFIG_METHOD_MANUAL:
2040         case CONNMAN_IPCONFIG_METHOD_AUTO:
2041                 break;
2042         }
2043
2044         if (!ipconfig->address)
2045                 return;
2046
2047         if (ipconfig->address->local) {
2048                 connman_dbus_dict_append_basic(iter, "Address",
2049                                 DBUS_TYPE_STRING, &ipconfig->address->local);
2050                 connman_dbus_dict_append_basic(iter, "PrefixLength",
2051                                                 DBUS_TYPE_BYTE,
2052                                                 &ipconfig->address->prefixlen);
2053         }
2054
2055         if (ipconfig->address->gateway)
2056                 connman_dbus_dict_append_basic(iter, "Gateway",
2057                                 DBUS_TYPE_STRING, &ipconfig->address->gateway);
2058
2059         privacy = privacy2string(ipconfig->ipv6_privacy_config);
2060         connman_dbus_dict_append_basic(iter, "Privacy",
2061                                 DBUS_TYPE_STRING, &privacy);
2062 }
2063
2064 void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig,
2065                                                         DBusMessageIter *iter)
2066 {
2067         const char *str;
2068
2069         str = __connman_ipconfig_method2string(ipconfig->method);
2070         if (!str)
2071                 return;
2072
2073         connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
2074
2075         switch (ipconfig->method) {
2076         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2077         case CONNMAN_IPCONFIG_METHOD_OFF:
2078         case CONNMAN_IPCONFIG_METHOD_DHCP:
2079         case CONNMAN_IPCONFIG_METHOD_AUTO:
2080                 return;
2081         case CONNMAN_IPCONFIG_METHOD_FIXED:
2082         case CONNMAN_IPCONFIG_METHOD_MANUAL:
2083                 break;
2084         }
2085
2086         if (!ipconfig->address)
2087                 return;
2088
2089         if (ipconfig->address->local) {
2090                 in_addr_t addr;
2091                 struct in_addr netmask;
2092                 char *mask;
2093
2094                 connman_dbus_dict_append_basic(iter, "Address",
2095                                 DBUS_TYPE_STRING, &ipconfig->address->local);
2096
2097                 addr = 0xffffffff << (32 - ipconfig->address->prefixlen);
2098                 netmask.s_addr = htonl(addr);
2099                 mask = inet_ntoa(netmask);
2100                 connman_dbus_dict_append_basic(iter, "Netmask",
2101                                                 DBUS_TYPE_STRING, &mask);
2102         }
2103
2104         if (ipconfig->address->gateway)
2105                 connman_dbus_dict_append_basic(iter, "Gateway",
2106                                 DBUS_TYPE_STRING, &ipconfig->address->gateway);
2107 }
2108
2109 int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
2110                                                         DBusMessageIter *array)
2111 {
2112         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
2113         const char *address = NULL, *netmask = NULL, *gateway = NULL,
2114                 *privacy_string = NULL;
2115         int prefix_length = 0, privacy = 0;
2116         DBusMessageIter dict;
2117         int type = -1;
2118
2119         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
2120                 return -EINVAL;
2121
2122         dbus_message_iter_recurse(array, &dict);
2123
2124         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2125                 DBusMessageIter entry, value;
2126                 const char *key;
2127                 int type;
2128
2129                 dbus_message_iter_recurse(&dict, &entry);
2130
2131                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2132                         return -EINVAL;
2133
2134                 dbus_message_iter_get_basic(&entry, &key);
2135                 dbus_message_iter_next(&entry);
2136
2137                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2138                         return -EINVAL;
2139
2140                 dbus_message_iter_recurse(&entry, &value);
2141
2142                 type = dbus_message_iter_get_arg_type(&value);
2143
2144                 if (g_str_equal(key, "Method")) {
2145                         const char *str;
2146
2147                         if (type != DBUS_TYPE_STRING)
2148                                 return -EINVAL;
2149
2150                         dbus_message_iter_get_basic(&value, &str);
2151                         method = __connman_ipconfig_string2method(str);
2152                 } else if (g_str_equal(key, "Address")) {
2153                         if (type != DBUS_TYPE_STRING)
2154                                 return -EINVAL;
2155
2156                         dbus_message_iter_get_basic(&value, &address);
2157                 } else if (g_str_equal(key, "PrefixLength")) {
2158                         if (type != DBUS_TYPE_BYTE)
2159                                 return -EINVAL;
2160
2161                         dbus_message_iter_get_basic(&value, &prefix_length);
2162
2163                         if (prefix_length < 0 || prefix_length > 128)
2164                                 return -EINVAL;
2165                 } else if (g_str_equal(key, "Netmask")) {
2166                         if (type != DBUS_TYPE_STRING)
2167                                 return -EINVAL;
2168
2169                         dbus_message_iter_get_basic(&value, &netmask);
2170                 } else if (g_str_equal(key, "Gateway")) {
2171                         if (type != DBUS_TYPE_STRING)
2172                                 return -EINVAL;
2173
2174                         dbus_message_iter_get_basic(&value, &gateway);
2175                 } else if (g_str_equal(key, "Privacy")) {
2176                         if (type != DBUS_TYPE_STRING)
2177                                 return -EINVAL;
2178
2179                         dbus_message_iter_get_basic(&value, &privacy_string);
2180                         privacy = string2privacy(privacy_string);
2181                 }
2182
2183                 dbus_message_iter_next(&dict);
2184         }
2185
2186         DBG("method %d address %s netmask %s gateway %s prefix_length %d "
2187                 "privacy %s",
2188                 method, address, netmask, gateway, prefix_length,
2189                 privacy_string);
2190
2191         switch (method) {
2192         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2193         case CONNMAN_IPCONFIG_METHOD_FIXED:
2194                 return -EINVAL;
2195
2196         case CONNMAN_IPCONFIG_METHOD_OFF:
2197                 ipconfig->method = method;
2198 #if defined TIZEN_EXT
2199                 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
2200                         disable_ipv6(ipconfig);
2201 #endif
2202
2203                 break;
2204
2205         case CONNMAN_IPCONFIG_METHOD_AUTO:
2206                 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
2207                         return -EOPNOTSUPP;
2208
2209                 ipconfig->method = method;
2210                 if (privacy_string)
2211                         ipconfig->ipv6_privacy_config = privacy;
2212 #if defined TIZEN_EXT
2213                 enable_ipv6(ipconfig);
2214 #endif
2215
2216                 break;
2217
2218         case CONNMAN_IPCONFIG_METHOD_MANUAL:
2219                 switch (ipconfig->type) {
2220                 case CONNMAN_IPCONFIG_TYPE_IPV4:
2221                         type = AF_INET;
2222                         break;
2223                 case CONNMAN_IPCONFIG_TYPE_IPV6:
2224                         type = AF_INET6;
2225                         break;
2226                 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2227                 case CONNMAN_IPCONFIG_TYPE_ALL:
2228                         type = -1;
2229                         break;
2230                 }
2231
2232                 if ((address && connman_inet_check_ipaddress(address)
2233                                                 != type) ||
2234                                 (netmask &&
2235                                 connman_inet_check_ipaddress(netmask)
2236                                                 != type) ||
2237                                 (gateway &&
2238                                 connman_inet_check_ipaddress(gateway)
2239                                                 != type))
2240                         return -EINVAL;
2241
2242                 ipconfig->method = method;
2243
2244                 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
2245                         connman_ipaddress_set_ipv4(ipconfig->address,
2246                                                 address, netmask, gateway);
2247                 else
2248                         return connman_ipaddress_set_ipv6(
2249                                         ipconfig->address, address,
2250                                                 prefix_length, gateway);
2251
2252                 break;
2253
2254         case CONNMAN_IPCONFIG_METHOD_DHCP:
2255                 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
2256                         return -EOPNOTSUPP;
2257
2258                 ipconfig->method = method;
2259                 break;
2260         }
2261
2262         return 0;
2263 }
2264
2265 void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
2266                                                         DBusMessageIter *iter)
2267 {
2268         struct connman_ipdevice *ipdevice;
2269         const char *method = "auto";
2270
2271         connman_dbus_dict_append_basic(iter, "Method",
2272                                                 DBUS_TYPE_STRING, &method);
2273
2274         ipdevice = g_hash_table_lookup(ipdevice_hash,
2275                                         GINT_TO_POINTER(ipconfig->index));
2276         if (!ipdevice)
2277                 return;
2278
2279         if (ipconfig->index >= 0) {
2280                 char *ifname = connman_inet_ifname(ipconfig->index);
2281                 if (ifname) {
2282                         connman_dbus_dict_append_basic(iter, "Interface",
2283                                                 DBUS_TYPE_STRING, &ifname);
2284                         g_free(ifname);
2285                 }
2286         }
2287
2288         if (ipdevice->address)
2289                 connman_dbus_dict_append_basic(iter, "Address",
2290                                         DBUS_TYPE_STRING, &ipdevice->address);
2291
2292         if (ipdevice->mtu > 0)
2293                 connman_dbus_dict_append_basic(iter, "MTU",
2294                                         DBUS_TYPE_UINT16, &ipdevice->mtu);
2295 }
2296
2297 void __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
2298                 GKeyFile *keyfile, const char *identifier, const char *prefix)
2299 {
2300         char *method;
2301         char *str;
2302         struct ipconfig_store is = { .file = keyfile,
2303                                      .group = identifier,
2304                                      .prefix = prefix };
2305
2306         DBG("ipconfig %p identifier %s", ipconfig, identifier);
2307
2308         method = store_get_str(&is, "method");
2309         if (!method) {
2310                 switch (ipconfig->type) {
2311                 case CONNMAN_IPCONFIG_TYPE_IPV4:
2312                         ipconfig->method = CONNMAN_IPCONFIG_METHOD_DHCP;
2313                         break;
2314
2315                 case CONNMAN_IPCONFIG_TYPE_IPV6:
2316                         ipconfig->method = CONNMAN_IPCONFIG_METHOD_AUTO;
2317                         break;
2318
2319                 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2320                 case CONNMAN_IPCONFIG_TYPE_ALL:
2321                         ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
2322                         break;
2323                 }
2324         } else {
2325                 ipconfig->method = __connman_ipconfig_string2method(method);
2326                 g_free(method);
2327         }
2328
2329         if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_UNKNOWN)
2330                 ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
2331
2332         if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
2333                 if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO ||
2334                                 ipconfig->method == CONNMAN_IPCONFIG_METHOD_MANUAL) {
2335                         char *privacy;
2336
2337                         privacy = store_get_str(&is, "privacy");
2338                         ipconfig->ipv6_privacy_config = string2privacy(privacy);
2339                         g_free(privacy);
2340                 }
2341
2342                 g_strfreev(ipconfig->last_dhcpv6_prefixes);
2343                 ipconfig->last_dhcpv6_prefixes =
2344                         store_get_strs(&is, "DHCP.LastPrefixes");
2345         }
2346
2347
2348         switch (ipconfig->method) {
2349         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2350         case CONNMAN_IPCONFIG_METHOD_OFF:
2351                 break;
2352
2353         case CONNMAN_IPCONFIG_METHOD_FIXED:
2354         case CONNMAN_IPCONFIG_METHOD_MANUAL:
2355                 ipconfig->address->prefixlen =
2356                         store_get_int(&is, "netmask_prefixlen");
2357
2358                 g_free(ipconfig->address->local);
2359                 ipconfig->address->local =
2360                         store_get_str(&is, "local_address");
2361
2362                 g_free(ipconfig->address->peer);
2363                 ipconfig->address->peer =
2364                         store_get_str(&is, "peer_address");
2365
2366                 g_free(ipconfig->address->broadcast);
2367                 ipconfig->address->broadcast =
2368                         store_get_str(&is, "broadcast_address");
2369
2370                 g_free(ipconfig->address->gateway);
2371                 ipconfig->address->gateway =
2372                         store_get_str(&is, "gateway");
2373                 break;
2374
2375         case CONNMAN_IPCONFIG_METHOD_AUTO:
2376                 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
2377                         break;
2378
2379                 /*
2380                  * If the last used method for IPv4 was AUTO then we
2381                  * try first DHCP. We will try also to use the last
2382                  * used DHCP address, if exits.
2383                  */
2384                 __connman_ipconfig_set_method(ipconfig,
2385                                         CONNMAN_IPCONFIG_METHOD_DHCP);
2386                 /* fall through */
2387
2388         case CONNMAN_IPCONFIG_METHOD_DHCP:
2389                 str = store_get_str(&is, "DHCP.LastAddress");
2390                 if (str) {
2391                         g_free(ipconfig->last_dhcp_address);
2392                         ipconfig->last_dhcp_address = str;
2393                 }
2394
2395                 break;
2396         }
2397 }
2398
2399 void __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
2400                 GKeyFile *keyfile, const char *identifier, const char *prefix)
2401 {
2402         const char *method;
2403         struct ipconfig_store is = { .file = keyfile,
2404                                      .group = identifier,
2405                                      .prefix = prefix };
2406
2407         method = __connman_ipconfig_method2string(ipconfig->method);
2408         DBG("ipconfig %p identifier %s method %s", ipconfig, identifier,
2409                                                                 method);
2410         store_set_str(&is, "method", method);
2411
2412         if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
2413                 store_set_str(&is, "privacy",
2414                                 privacy2string(ipconfig->ipv6_privacy_config));
2415
2416                 store_set_str(&is, "DHCP.LastAddress",
2417                                 ipconfig->last_dhcp_address);
2418
2419                 store_set_strs(&is, "DHCP.LastPrefixes",
2420                                 ipconfig->last_dhcpv6_prefixes);
2421         }
2422
2423         switch (ipconfig->method) {
2424         case CONNMAN_IPCONFIG_METHOD_FIXED:
2425         case CONNMAN_IPCONFIG_METHOD_MANUAL:
2426                 break;
2427
2428         case CONNMAN_IPCONFIG_METHOD_DHCP:
2429                 store_set_str(&is, "DHCP.LastAddress",
2430                                 ipconfig->last_dhcp_address);
2431                 /* fall through */
2432
2433         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2434         case CONNMAN_IPCONFIG_METHOD_OFF:
2435         case CONNMAN_IPCONFIG_METHOD_AUTO:
2436                 return;
2437         }
2438
2439         store_set_int(&is, "netmask_prefixlen", ipconfig->address->prefixlen);
2440         store_set_str(&is, "local_address", ipconfig->address->local);
2441         store_set_str(&is, "peer_address", ipconfig->address->peer);
2442         store_set_str(&is, "broadcast_address", ipconfig->address->broadcast);
2443         store_set_str(&is, "gateway", ipconfig->address->gateway);
2444 }
2445
2446 int __connman_ipconfig_init(void)
2447 {
2448         DBG("");
2449
2450         ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2451                                                         NULL, free_ipdevice);
2452
2453         is_ipv6_supported = connman_inet_is_ipv6_supported();
2454
2455         return 0;
2456 }
2457
2458 void __connman_ipconfig_cleanup(void)
2459 {
2460         DBG("");
2461
2462         g_hash_table_destroy(ipdevice_hash);
2463         ipdevice_hash = NULL;
2464 }