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