Only add IP configurations with callbacks to the list
[platform/upstream/connman.git] / src / ipconfig.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  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 <net/if.h>
27 #include <net/if_arp.h>
28
29 #ifndef IFF_LOWER_UP
30 #define IFF_LOWER_UP    0x10000
31 #endif
32
33 #include <gdbus.h>
34
35 #include "connman.h"
36
37 struct connman_ipconfig {
38         gint refcount;
39         int index;
40
41         const struct connman_ipconfig_ops *ops;
42         void *ops_data;
43
44         enum connman_ipconfig_method method;
45         struct connman_ipaddress *address;
46 };
47
48 struct connman_ipdevice {
49         int index;
50         char *ifname;
51         unsigned short type;
52         unsigned int flags;
53
54         GSList *address_list;
55         char *gateway;
56
57         struct connman_ipconfig *config;
58         struct connman_ipconfig_driver *driver;
59 };
60
61 static GHashTable *ipdevice_hash = NULL;
62 static GList *ipconfig_list = NULL;
63
64 struct connman_ipaddress *connman_ipaddress_alloc(void)
65 {
66         struct connman_ipaddress *ipaddress;
67
68         ipaddress = g_try_new0(struct connman_ipaddress, 1);
69         if (ipaddress == NULL)
70                 return NULL;
71
72         return ipaddress;
73 }
74
75 void connman_ipaddress_free(struct connman_ipaddress *ipaddress)
76 {
77         g_free(ipaddress->broadcast);
78         g_free(ipaddress->peer);
79         g_free(ipaddress->local);
80         g_free(ipaddress);
81 }
82
83 void connman_ipaddress_copy(struct connman_ipaddress *ipaddress,
84                                         struct connman_ipaddress *source)
85 {
86         ipaddress->prefixlen = source->prefixlen;
87
88         g_free(ipaddress->local);
89         ipaddress->local = g_strdup(source->local);
90
91         g_free(ipaddress->peer);
92         ipaddress->peer = g_strdup(source->peer);
93
94         g_free(ipaddress->broadcast);
95         ipaddress->broadcast = g_strdup(source->broadcast);
96 }
97
98 static void free_address_list(struct connman_ipdevice *ipdevice)
99 {
100         GSList *list;
101
102         for (list = ipdevice->address_list; list; list = list->next) {
103                 struct connman_ipaddress *ipaddress = list->data;
104
105                 connman_ipaddress_free(ipaddress);
106                 list->data = NULL;
107         }
108
109         g_slist_free(ipdevice->address_list);
110         ipdevice->address_list = NULL;
111 }
112
113 static struct connman_ipaddress *find_ipaddress(struct connman_ipdevice *ipdevice,
114                                 unsigned char prefixlen, const char *local)
115 {
116         GSList *list;
117
118         for (list = ipdevice->address_list; list; list = list->next) {
119                 struct connman_ipaddress *ipaddress = list->data;
120
121                 if (g_strcmp0(ipaddress->local, local) == 0 &&
122                                         ipaddress->prefixlen == prefixlen)
123                         return ipaddress;
124         }
125
126         return NULL;
127 }
128
129 static const char *type2str(unsigned short type)
130 {
131         switch (type) {
132         case ARPHRD_ETHER:
133                 return "ETHER";
134         case ARPHRD_LOOPBACK:
135                 return "LOOPBACK";
136         case ARPHRD_PPP:
137                 return "PPP";
138         case ARPHRD_NONE:
139                 return "NONE";
140         case ARPHRD_VOID:
141                 return "VOID";
142         }
143
144         return "";
145 }
146
147 static const char *scope2str(unsigned char scope)
148 {
149         switch (scope) {
150         case 0:
151                 return "UNIVERSE";
152         case 253:
153                 return "LINK";
154         }
155
156         return "";
157 }
158
159 static void free_ipdevice(gpointer data)
160 {
161         struct connman_ipdevice *ipdevice = data;
162
163         connman_info("%s {remove} index %d", ipdevice->ifname,
164                                                         ipdevice->index);
165
166         if (ipdevice->config != NULL)
167                 connman_ipconfig_unref(ipdevice->config);
168
169         free_address_list(ipdevice);
170         g_free(ipdevice->gateway);
171
172         g_free(ipdevice->ifname);
173         g_free(ipdevice);
174 }
175
176 static GSList *driver_list = NULL;
177
178 static gint compare_priority(gconstpointer a, gconstpointer b)
179 {
180         const struct connman_ipconfig_driver *driver1 = a;
181         const struct connman_ipconfig_driver *driver2 = b;
182
183         return driver2->priority - driver1->priority;
184 }
185
186 /**
187  * connman_ipconfig_driver_register:
188  * @driver: IP configuration driver
189  *
190  * Register a new IP configuration driver
191  *
192  * Returns: %0 on success
193  */
194 int connman_ipconfig_driver_register(struct connman_ipconfig_driver *driver)
195 {
196         DBG("driver %p name %s", driver, driver->name);
197
198         driver_list = g_slist_insert_sorted(driver_list, driver,
199                                                         compare_priority);
200
201         return 0;
202 }
203
204 /**
205  * connman_ipconfig_driver_unregister:
206  * @driver: IP configuration driver
207  *
208  * Remove a previously registered IP configuration driver.
209  */
210 void connman_ipconfig_driver_unregister(struct connman_ipconfig_driver *driver)
211 {
212         DBG("driver %p name %s", driver, driver->name);
213
214         driver_list = g_slist_remove(driver_list, driver);
215 }
216
217 static void __connman_ipconfig_lower_up(struct connman_ipdevice *ipdevice)
218 {
219         GSList *list;
220
221         DBG("ipconfig %p", ipdevice->config);
222
223         if (ipdevice->config == NULL)
224                 return;
225
226         switch (ipdevice->config->method) {
227         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
228         case CONNMAN_IPCONFIG_METHOD_IGNORE:
229         case CONNMAN_IPCONFIG_METHOD_STATIC:
230                 return;
231         case CONNMAN_IPCONFIG_METHOD_DHCP:
232                 break;
233         }
234
235         if (ipdevice->driver != NULL)
236                 return;
237
238         for (list = driver_list; list; list = list->next) {
239                 struct connman_ipconfig_driver *driver = list->data;
240
241                 if (driver->request(ipdevice->config) == 0) {
242                         ipdevice->driver = driver;
243                         break;
244                 }
245         }
246 }
247
248 static void __connman_ipconfig_lower_down(struct connman_ipdevice *ipdevice)
249 {
250         DBG("ipconfig %p", ipdevice->config);
251
252         if (ipdevice->config == NULL)
253                 return;
254
255         if (ipdevice->driver == NULL)
256                 return;
257
258         ipdevice->driver->release(ipdevice->config);
259
260         connman_inet_clear_address(ipdevice->index);
261 }
262
263 void __connman_ipconfig_newlink(int index, unsigned short type,
264                                                         unsigned int flags)
265 {
266         struct connman_ipdevice *ipdevice;
267         GList *list;
268         GString *str;
269         gboolean up = FALSE, down = FALSE;
270         gboolean lower_up = FALSE, lower_down = FALSE;
271
272         DBG("index %d", index);
273
274         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
275         if (ipdevice != NULL)
276                 goto update;
277
278         ipdevice = g_try_new0(struct connman_ipdevice, 1);
279         if (ipdevice == NULL)
280                 return;
281
282         ipdevice->index = index;
283         ipdevice->ifname = connman_inet_ifname(index);
284         ipdevice->type = type;
285
286         ipdevice->config = connman_ipconfig_create(index);
287         if (ipdevice->config == NULL) {
288                 g_free(ipdevice->ifname);
289                 g_free(ipdevice);
290                 return;
291         }
292
293         if (type == ARPHRD_ETHER)
294                 connman_ipconfig_set_method(ipdevice->config,
295                                         CONNMAN_IPCONFIG_METHOD_IGNORE);
296
297         g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
298
299         connman_info("%s {create} index %d type %d <%s>", ipdevice->ifname,
300                                                 index, type, type2str(type));
301
302 update:
303         if (flags == ipdevice->flags)
304                 return;
305
306         if ((ipdevice->flags & IFF_UP) != (flags & IFF_UP)) {
307                 if (flags & IFF_UP)
308                         up = TRUE;
309                 else
310                         down = TRUE;
311         }
312
313         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) !=
314                                 (flags & (IFF_RUNNING | IFF_LOWER_UP))) {
315                 if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
316                                         (IFF_RUNNING | IFF_LOWER_UP))
317                         lower_up = TRUE;
318                 else if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
319                         lower_down = TRUE;
320         }
321
322         connman_inet_clear_address(index);
323
324         ipdevice->flags = flags;
325
326         str = g_string_new(NULL);
327         if (str == NULL)
328                 return;
329
330         if (flags & IFF_UP)
331                 g_string_append(str, "UP");
332         else
333                 g_string_append(str, "DOWN");
334
335         if (flags & IFF_RUNNING)
336                 g_string_append(str, ",RUNNING");
337
338         if (flags & IFF_LOWER_UP)
339                 g_string_append(str, ",LOWER_UP");
340
341         connman_info("%s {update} flags %u <%s>", ipdevice->ifname,
342                                                         flags, str->str);
343
344         g_string_free(str, TRUE);
345
346         for (list = g_list_first(ipconfig_list); list;
347                                                 list = g_list_next(list)) {
348                 struct connman_ipconfig *ipconfig = list->data;
349
350                 if (index != ipconfig->index)
351                         continue;
352
353                 if (up == TRUE && ipconfig->ops->up)
354                         ipconfig->ops->up(ipconfig);
355                 if (lower_up == TRUE && ipconfig->ops->lower_up)
356                         ipconfig->ops->lower_up(ipconfig);
357
358                 if (lower_down == TRUE && ipconfig->ops->lower_down)
359                         ipconfig->ops->lower_down(ipconfig);
360                 if (down == TRUE && ipconfig->ops->down)
361                         ipconfig->ops->down(ipconfig);
362         }
363
364         if (lower_up)
365                 __connman_ipconfig_lower_up(ipdevice);
366         if (lower_down)
367                 __connman_ipconfig_lower_down(ipdevice);
368 }
369
370 void __connman_ipconfig_dellink(int index)
371 {
372         struct connman_ipdevice *ipdevice;
373         GList *list;
374
375         DBG("index %d", index);
376
377         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
378         if (ipdevice == NULL)
379                 return;
380
381         for (list = g_list_first(ipconfig_list); list;
382                                                 list = g_list_next(list)) {
383                 struct connman_ipconfig *ipconfig = list->data;
384
385                 if (index != ipconfig->index)
386                         continue;
387
388                 ipconfig->index = -1;
389
390                 if (ipconfig->ops->lower_down)
391                         ipconfig->ops->lower_down(ipconfig);
392                 if (ipconfig->ops->down)
393                         ipconfig->ops->down(ipconfig);
394         }
395
396         __connman_ipconfig_lower_down(ipdevice);
397
398         g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
399 }
400
401 void __connman_ipconfig_newaddr(int index, const char *label,
402                                 unsigned char prefixlen, const char *address)
403 {
404         struct connman_ipdevice *ipdevice;
405         struct connman_ipaddress *ipaddress;
406         GList *list;
407
408         DBG("index %d", index);
409
410         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
411         if (ipdevice == NULL)
412                 return;
413
414         ipaddress = connman_ipaddress_alloc();
415         if (ipaddress == NULL)
416                 return;
417
418         ipaddress->prefixlen = prefixlen;
419         ipaddress->local = g_strdup(address);
420
421         ipdevice->address_list = g_slist_append(ipdevice->address_list,
422                                                                 ipaddress);
423
424         connman_info("%s {add} address %s/%u label %s", ipdevice->ifname,
425                                                 address, prefixlen, label);
426
427         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
428                 return;
429
430         if (g_slist_length(ipdevice->address_list) > 1)
431                 return;
432
433         for (list = g_list_first(ipconfig_list); list;
434                                                 list = g_list_next(list)) {
435                 struct connman_ipconfig *ipconfig = list->data;
436
437                 if (index != ipconfig->index)
438                         continue;
439
440                 if (ipconfig->ops->ip_bound)
441                         ipconfig->ops->ip_bound(ipconfig);
442         }
443 }
444
445 void __connman_ipconfig_deladdr(int index, const char *label,
446                                 unsigned char prefixlen, const char *address)
447 {
448         struct connman_ipdevice *ipdevice;
449         struct connman_ipaddress *ipaddress;
450         GList *list;
451
452         DBG("index %d", index);
453
454         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
455         if (ipdevice == NULL)
456                 return;
457
458         ipaddress = find_ipaddress(ipdevice, prefixlen, address);
459         if (ipaddress == NULL)
460                 return;
461
462         ipdevice->address_list = g_slist_remove(ipdevice->address_list,
463                                                                 ipaddress);
464
465         connman_ipaddress_free(ipaddress);
466
467         connman_info("%s {del} address %s/%u label %s", ipdevice->ifname,
468                                                 address, prefixlen, label);
469
470         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
471                 return;
472
473         if (g_slist_length(ipdevice->address_list) > 0)
474                 return;
475
476         for (list = g_list_first(ipconfig_list); list;
477                                                 list = g_list_next(list)) {
478                 struct connman_ipconfig *ipconfig = list->data;
479
480                 if (index != ipconfig->index)
481                         continue;
482
483                 if (ipconfig->ops->ip_release)
484                         ipconfig->ops->ip_release(ipconfig);
485         }
486 }
487
488 void __connman_ipconfig_newroute(int index, unsigned char scope,
489                                         const char *dst, const char *gateway)
490 {
491         struct connman_ipdevice *ipdevice;
492
493         DBG("index %d", index);
494
495         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
496         if (ipdevice == NULL)
497                 return;
498
499         if (scope == 0 && g_strcmp0(dst, "0.0.0.0") == 0) {
500                 g_free(ipdevice->gateway);
501                 ipdevice->gateway = g_strdup(gateway);
502         }
503
504         connman_info("%s {add} route %s gw %s scope %u <%s>",
505                                         ipdevice->ifname, dst, gateway,
506                                                 scope, scope2str(scope));
507 }
508
509 void __connman_ipconfig_delroute(int index, unsigned char scope,
510                                         const char *dst, const char *gateway)
511 {
512         struct connman_ipdevice *ipdevice;
513
514         DBG("index %d", index);
515
516         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
517         if (ipdevice == NULL)
518                 return;
519
520         if (scope == 0 && g_strcmp0(dst, "0.0.0.0") == 0) {
521                 g_free(ipdevice->gateway);
522                 ipdevice->gateway = NULL;
523         }
524
525         connman_info("%s {del} route %s gw %s scope %u <%s>",
526                                         ipdevice->ifname, dst, gateway,
527                                                 scope, scope2str(scope));
528 }
529
530 void __connman_ipconfig_foreach(void (*function) (int index, void *user_data),
531                                                         void *user_data)
532 {
533         GList *list, *keys;
534
535         keys = g_hash_table_get_keys(ipdevice_hash);
536         if (keys == NULL)
537                 return;
538
539         for (list = g_list_first(keys); list; list = g_list_next(list)) {
540                 int index = GPOINTER_TO_INT(list->data);
541
542                 function(index, user_data);
543         }
544
545         g_list_free(keys);
546 }
547
548 unsigned short __connman_ipconfig_get_type(int index)
549 {
550         struct connman_ipdevice *ipdevice;
551
552         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
553         if (ipdevice == NULL)
554                 return ARPHRD_VOID;
555
556         return ipdevice->type;
557 }
558
559 unsigned int __connman_ipconfig_get_flags(int index)
560 {
561         struct connman_ipdevice *ipdevice;
562
563         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
564         if (ipdevice == NULL)
565                 return 0;
566
567         return ipdevice->flags;
568 }
569
570 const char *__connman_ipconfig_get_gateway(int index)
571 {
572         struct connman_ipdevice *ipdevice;
573
574         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
575         if (ipdevice == NULL)
576                 return NULL;
577
578         return ipdevice->gateway;
579 }
580
581 /**
582  * connman_ipconfig_create:
583  *
584  * Allocate a new ipconfig structure.
585  *
586  * Returns: a newly-allocated #connman_ipconfig structure
587  */
588 struct connman_ipconfig *connman_ipconfig_create(int index)
589 {
590         struct connman_ipconfig *ipconfig;
591
592         DBG("index %d", index);
593
594         ipconfig = g_try_new0(struct connman_ipconfig, 1);
595         if (ipconfig == NULL)
596                 return NULL;
597
598         ipconfig->refcount = 1;
599
600         ipconfig->index = index;
601
602         ipconfig->address = connman_ipaddress_alloc();
603         if (ipconfig->address == NULL) {
604                 g_free(ipconfig);
605                 return NULL;
606         }
607
608         DBG("ipconfig %p", ipconfig);
609
610         return ipconfig;
611 }
612
613 /**
614  * connman_ipconfig_ref:
615  * @ipconfig: ipconfig structure
616  *
617  * Increase reference counter of ipconfig
618  */
619 struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig)
620 {
621         g_atomic_int_inc(&ipconfig->refcount);
622
623         return ipconfig;
624 }
625
626 /**
627  * connman_ipconfig_unref:
628  * @ipconfig: ipconfig structure
629  *
630  * Decrease reference counter of ipconfig
631  */
632 void connman_ipconfig_unref(struct connman_ipconfig *ipconfig)
633 {
634         if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) {
635                 connman_ipconfig_set_ops(ipconfig, NULL);
636
637                 connman_ipaddress_free(ipconfig->address);
638                 g_free(ipconfig);
639         }
640 }
641
642 /**
643  * connman_ipconfig_get_data:
644  * @ipconfig: ipconfig structure
645  *
646  * Get private data pointer
647  */
648 void *connman_ipconfig_get_data(struct connman_ipconfig *ipconfig)
649 {
650         return ipconfig->ops_data;
651 }
652
653 /**
654  * connman_ipconfig_set_data:
655  * @ipconfig: ipconfig structure
656  * @data: data pointer
657  *
658  * Set private data pointer
659  */
660 void connman_ipconfig_set_data(struct connman_ipconfig *ipconfig, void *data)
661 {
662         ipconfig->ops_data = data;
663 }
664
665 /**
666  * connman_ipconfig_get_index:
667  * @ipconfig: ipconfig structure
668  *
669  * Get interface index
670  */
671 int connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
672 {
673         return ipconfig->index;
674 }
675
676 /**
677  * connman_ipconfig_get_ifname:
678  * @ipconfig: ipconfig structure
679  *
680  * Get interface name
681  */
682 const char *connman_ipconfig_get_ifname(struct connman_ipconfig *ipconfig)
683 {
684         struct connman_ipdevice *ipdevice;
685
686         if (ipconfig->index < 0)
687                 return NULL;
688
689         ipdevice = g_hash_table_lookup(ipdevice_hash,
690                                         GINT_TO_POINTER(ipconfig->index));
691         if (ipdevice == NULL)
692                 return NULL;
693
694         return ipdevice->ifname;
695 }
696
697 /**
698  * connman_ipconfig_set_ops:
699  * @ipconfig: ipconfig structure
700  * @ops: operation callbacks
701  *
702  * Set the operation callbacks
703  */
704 void connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
705                                 const struct connman_ipconfig_ops *ops)
706 {
707         if (ipconfig->ops != NULL)
708                 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
709
710         ipconfig->ops = ops;
711
712         if (ops != NULL)
713                 ipconfig_list = g_list_append(ipconfig_list, ipconfig);
714 }
715
716 /**
717  * connman_ipconfig_set_method:
718  * @ipconfig: ipconfig structure
719  * @method: configuration method
720  *
721  * Set the configuration method
722  */
723 int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
724                                         enum connman_ipconfig_method method)
725 {
726         ipconfig->method = method;
727
728         return 0;
729 }
730
731 /**
732  * connman_ipconfig_bind:
733  * @ipconfig: ipconfig structure
734  * @ipaddress: ipaddress structure
735  *
736  * Bind IP address details to configuration
737  */
738 void connman_ipconfig_bind(struct connman_ipconfig *ipconfig,
739                                         struct connman_ipaddress *ipaddress)
740 {
741         connman_ipaddress_copy(ipconfig->address, ipaddress);
742
743         connman_inet_set_address(ipconfig->index, ipconfig->address);
744 }
745
746 const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
747 {
748         switch (method) {
749         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
750                 break;
751         case CONNMAN_IPCONFIG_METHOD_IGNORE:
752                 return "ignore";
753         case CONNMAN_IPCONFIG_METHOD_STATIC:
754                 return "static";
755         case CONNMAN_IPCONFIG_METHOD_DHCP:
756                 return "dhcp";
757         }
758
759         return NULL;
760 }
761
762 enum connman_ipconfig_method __connman_ipconfig_string2method(const char *method)
763 {
764         if (g_strcmp0(method, "ignore") == 0)
765                 return CONNMAN_IPCONFIG_METHOD_IGNORE;
766         else if (g_strcmp0(method, "static") == 0)
767                 return CONNMAN_IPCONFIG_METHOD_STATIC;
768         else if (g_strcmp0(method, "dhcp") == 0)
769                 return CONNMAN_IPCONFIG_METHOD_DHCP;
770         else
771                 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
772 }
773
774 static void append_variant(DBusMessageIter *iter, const char *prefix,
775                                         const char *key, int type, void *val)
776 {
777         char *str;
778
779         if (prefix == NULL) {
780                 connman_dbus_dict_append_variant(iter, key, type, val);
781                 return;
782         }
783
784         str = g_strdup_printf("%s%s", prefix, key);
785         if (str != NULL)
786                 connman_dbus_dict_append_variant(iter, str, type, val);
787
788         g_free(str);
789 }
790
791 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
792                                 DBusMessageIter *iter, const char *prefix)
793 {
794         const char *str;
795
796         str = __connman_ipconfig_method2string(ipconfig->method);
797         if (str == NULL)
798                 return;
799
800         append_variant(iter, prefix, "Method", DBUS_TYPE_STRING, &str);
801 }
802
803 int __connman_ipconfig_set_ipv4(struct connman_ipconfig *ipconfig,
804                                 const char *key, DBusMessageIter *value)
805 {
806         int type = dbus_message_iter_get_arg_type(value);
807
808         DBG("ipconfig %p key %s type %d", ipconfig, key, type);
809
810         if (g_strcmp0(key, "Method") == 0) {
811                 const char *method;
812
813                 if (type != DBUS_TYPE_STRING)
814                         return -EINVAL;
815
816                 dbus_message_iter_get_basic(value, &method);
817
818                 ipconfig->method = __connman_ipconfig_string2method(method);
819         } else
820                 return -EINVAL;
821
822         return 0;
823 }
824
825 int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
826                 GKeyFile *keyfile, const char *identifier, const char *prefix)
827 {
828         DBG("ipconfig %p identifier %s", ipconfig, identifier);
829
830         return 0;
831 }
832
833 int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
834                 GKeyFile *keyfile, const char *identifier, const char *prefix)
835 {
836         DBG("ipconfig %p identifier %s", ipconfig, identifier);
837
838         return 0;
839 }
840
841 int __connman_ipconfig_init(void)
842 {
843         DBG("");
844
845         ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
846                                                         NULL, free_ipdevice);
847
848         return 0;
849 }
850
851 void __connman_ipconfig_cleanup(void)
852 {
853         DBG("");
854
855         g_hash_table_destroy(ipdevice_hash);
856         ipdevice_hash = NULL;
857 }