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