Fix update of Ethernet address and MTU values
[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 (ipdevice->config != NULL) {
335                 g_free(ipdevice->config->eth);
336                 ipdevice->config->eth = g_strdup(address);
337                 ipdevice->config->mtu = mtu;
338         }
339
340         if (flags == ipdevice->flags)
341                 return;
342
343         if ((ipdevice->flags & IFF_UP) != (flags & IFF_UP)) {
344                 if (flags & IFF_UP)
345                         up = TRUE;
346                 else
347                         down = TRUE;
348         }
349
350         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) !=
351                                 (flags & (IFF_RUNNING | IFF_LOWER_UP))) {
352                 if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
353                                         (IFF_RUNNING | IFF_LOWER_UP))
354                         lower_up = TRUE;
355                 else if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
356                         lower_down = TRUE;
357         }
358
359         ipdevice->flags = flags;
360
361         str = g_string_new(NULL);
362         if (str == NULL)
363                 return;
364
365         if (flags & IFF_UP)
366                 g_string_append(str, "UP");
367         else
368                 g_string_append(str, "DOWN");
369
370         if (flags & IFF_RUNNING)
371                 g_string_append(str, ",RUNNING");
372
373         if (flags & IFF_LOWER_UP)
374                 g_string_append(str, ",LOWER_UP");
375
376         connman_info("%s {update} flags %u <%s>", ipdevice->ifname,
377                                                         flags, str->str);
378
379         g_string_free(str, TRUE);
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                 if (up == TRUE && ipconfig->ops->up)
389                         ipconfig->ops->up(ipconfig);
390                 if (lower_up == TRUE && ipconfig->ops->lower_up)
391                         ipconfig->ops->lower_up(ipconfig);
392
393                 if (lower_down == TRUE && ipconfig->ops->lower_down)
394                         ipconfig->ops->lower_down(ipconfig);
395                 if (down == TRUE && ipconfig->ops->down)
396                         ipconfig->ops->down(ipconfig);
397         }
398
399         if (lower_up)
400                 __connman_ipconfig_lower_up(ipdevice);
401         if (lower_down)
402                 __connman_ipconfig_lower_down(ipdevice);
403 }
404
405 void __connman_ipconfig_dellink(int index)
406 {
407         struct connman_ipdevice *ipdevice;
408         GList *list;
409
410         DBG("index %d", index);
411
412         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
413         if (ipdevice == NULL)
414                 return;
415
416         for (list = g_list_first(ipconfig_list); list;
417                                                 list = g_list_next(list)) {
418                 struct connman_ipconfig *ipconfig = list->data;
419
420                 if (index != ipconfig->index)
421                         continue;
422
423                 ipconfig->index = -1;
424
425                 if (ipconfig->ops->lower_down)
426                         ipconfig->ops->lower_down(ipconfig);
427                 if (ipconfig->ops->down)
428                         ipconfig->ops->down(ipconfig);
429         }
430
431         __connman_ipconfig_lower_down(ipdevice);
432
433         g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
434 }
435
436 void __connman_ipconfig_newaddr(int index, const char *label,
437                                 unsigned char prefixlen, const char *address)
438 {
439         struct connman_ipdevice *ipdevice;
440         struct connman_ipaddress *ipaddress;
441         GList *list;
442
443         DBG("index %d", index);
444
445         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
446         if (ipdevice == NULL)
447                 return;
448
449         ipaddress = connman_ipaddress_alloc();
450         if (ipaddress == NULL)
451                 return;
452
453         ipaddress->prefixlen = prefixlen;
454         ipaddress->local = g_strdup(address);
455
456         ipdevice->address_list = g_slist_append(ipdevice->address_list,
457                                                                 ipaddress);
458
459         connman_info("%s {add} address %s/%u label %s", ipdevice->ifname,
460                                                 address, prefixlen, label);
461
462         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
463                 return;
464
465         if (g_slist_length(ipdevice->address_list) > 1)
466                 return;
467
468         for (list = g_list_first(ipconfig_list); list;
469                                                 list = g_list_next(list)) {
470                 struct connman_ipconfig *ipconfig = list->data;
471
472                 if (index != ipconfig->index)
473                         continue;
474
475                 if (ipconfig->ops->ip_bound)
476                         ipconfig->ops->ip_bound(ipconfig);
477         }
478 }
479
480 void __connman_ipconfig_deladdr(int index, const char *label,
481                                 unsigned char prefixlen, const char *address)
482 {
483         struct connman_ipdevice *ipdevice;
484         struct connman_ipaddress *ipaddress;
485         GList *list;
486
487         DBG("index %d", index);
488
489         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
490         if (ipdevice == NULL)
491                 return;
492
493         ipaddress = find_ipaddress(ipdevice, prefixlen, address);
494         if (ipaddress == NULL)
495                 return;
496
497         ipdevice->address_list = g_slist_remove(ipdevice->address_list,
498                                                                 ipaddress);
499
500         connman_ipaddress_free(ipaddress);
501
502         connman_info("%s {del} address %s/%u label %s", ipdevice->ifname,
503                                                 address, prefixlen, label);
504
505         if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
506                 return;
507
508         if (g_slist_length(ipdevice->address_list) > 0)
509                 return;
510
511         for (list = g_list_first(ipconfig_list); list;
512                                                 list = g_list_next(list)) {
513                 struct connman_ipconfig *ipconfig = list->data;
514
515                 if (index != ipconfig->index)
516                         continue;
517
518                 if (ipconfig->ops->ip_release)
519                         ipconfig->ops->ip_release(ipconfig);
520         }
521 }
522
523 void __connman_ipconfig_newroute(int index, unsigned char scope,
524                                         const char *dst, const char *gateway)
525 {
526         struct connman_ipdevice *ipdevice;
527
528         DBG("index %d", index);
529
530         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
531         if (ipdevice == NULL)
532                 return;
533
534         if (scope == 0 && g_strcmp0(dst, "0.0.0.0") == 0) {
535                 g_free(ipdevice->gateway);
536                 ipdevice->gateway = g_strdup(gateway);
537         }
538
539         connman_info("%s {add} route %s gw %s scope %u <%s>",
540                                         ipdevice->ifname, dst, gateway,
541                                                 scope, scope2str(scope));
542 }
543
544 void __connman_ipconfig_delroute(int index, unsigned char scope,
545                                         const char *dst, const char *gateway)
546 {
547         struct connman_ipdevice *ipdevice;
548
549         DBG("index %d", index);
550
551         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
552         if (ipdevice == NULL)
553                 return;
554
555         if (scope == 0 && g_strcmp0(dst, "0.0.0.0") == 0) {
556                 g_free(ipdevice->gateway);
557                 ipdevice->gateway = NULL;
558         }
559
560         connman_info("%s {del} route %s gw %s scope %u <%s>",
561                                         ipdevice->ifname, dst, gateway,
562                                                 scope, scope2str(scope));
563 }
564
565 void __connman_ipconfig_foreach(void (*function) (int index, void *user_data),
566                                                         void *user_data)
567 {
568         GList *list, *keys;
569
570         keys = g_hash_table_get_keys(ipdevice_hash);
571         if (keys == NULL)
572                 return;
573
574         for (list = g_list_first(keys); list; list = g_list_next(list)) {
575                 int index = GPOINTER_TO_INT(list->data);
576
577                 function(index, user_data);
578         }
579
580         g_list_free(keys);
581 }
582
583 unsigned short __connman_ipconfig_get_type(int index)
584 {
585         struct connman_ipdevice *ipdevice;
586
587         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
588         if (ipdevice == NULL)
589                 return ARPHRD_VOID;
590
591         return ipdevice->type;
592 }
593
594 unsigned int __connman_ipconfig_get_flags(int index)
595 {
596         struct connman_ipdevice *ipdevice;
597
598         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
599         if (ipdevice == NULL)
600                 return 0;
601
602         return ipdevice->flags;
603 }
604
605 const char *__connman_ipconfig_get_gateway(int index)
606 {
607         struct connman_ipdevice *ipdevice;
608
609         ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
610         if (ipdevice == NULL)
611                 return NULL;
612
613         return ipdevice->gateway;
614 }
615
616 /**
617  * connman_ipconfig_create:
618  *
619  * Allocate a new ipconfig structure.
620  *
621  * Returns: a newly-allocated #connman_ipconfig structure
622  */
623 struct connman_ipconfig *connman_ipconfig_create(int index)
624 {
625         struct connman_ipconfig *ipconfig;
626
627         DBG("index %d", index);
628
629         ipconfig = g_try_new0(struct connman_ipconfig, 1);
630         if (ipconfig == NULL)
631                 return NULL;
632
633         ipconfig->refcount = 1;
634
635         ipconfig->index = index;
636
637         ipconfig->address = connman_ipaddress_alloc();
638         if (ipconfig->address == NULL) {
639                 g_free(ipconfig);
640                 return NULL;
641         }
642
643         DBG("ipconfig %p", ipconfig);
644
645         return ipconfig;
646 }
647
648 /**
649  * connman_ipconfig_clone:
650  *
651  * Clone an ipconfig structure and create new reference.
652  *
653  * Returns: a newly-allocated #connman_ipconfig structure
654  */
655 struct connman_ipconfig *connman_ipconfig_clone(struct connman_ipconfig *ipconfig)
656 {
657         struct connman_ipconfig *ipconfig_clone;
658
659         DBG("ipconfig %p", ipconfig);
660
661         ipconfig_clone = g_try_new0(struct connman_ipconfig, 1);
662         if (ipconfig_clone == NULL)
663                 return NULL;
664
665         ipconfig_clone->refcount = 1;
666
667         ipconfig_clone->origin = connman_ipconfig_ref(ipconfig);
668
669         ipconfig_clone->index = -1;
670
671         return ipconfig_clone;
672 }
673
674 /**
675  * connman_ipconfig_ref:
676  * @ipconfig: ipconfig structure
677  *
678  * Increase reference counter of ipconfig
679  */
680 struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig)
681 {
682         g_atomic_int_inc(&ipconfig->refcount);
683
684         return ipconfig;
685 }
686
687 /**
688  * connman_ipconfig_unref:
689  * @ipconfig: ipconfig structure
690  *
691  * Decrease reference counter of ipconfig
692  */
693 void connman_ipconfig_unref(struct connman_ipconfig *ipconfig)
694 {
695         if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) {
696                 connman_ipconfig_set_ops(ipconfig, NULL);
697
698                 if (ipconfig->origin != NULL) {
699                         connman_ipconfig_unref(ipconfig->origin);
700                         ipconfig->origin = NULL;
701                 }
702
703                 connman_ipaddress_free(ipconfig->address);
704                 g_free(ipconfig->eth);
705                 g_free(ipconfig);
706         }
707 }
708
709 /**
710  * connman_ipconfig_get_data:
711  * @ipconfig: ipconfig structure
712  *
713  * Get private data pointer
714  */
715 void *connman_ipconfig_get_data(struct connman_ipconfig *ipconfig)
716 {
717         return ipconfig->ops_data;
718 }
719
720 /**
721  * connman_ipconfig_set_data:
722  * @ipconfig: ipconfig structure
723  * @data: data pointer
724  *
725  * Set private data pointer
726  */
727 void connman_ipconfig_set_data(struct connman_ipconfig *ipconfig, void *data)
728 {
729         ipconfig->ops_data = data;
730 }
731
732 /**
733  * connman_ipconfig_get_index:
734  * @ipconfig: ipconfig structure
735  *
736  * Get interface index
737  */
738 int connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
739 {
740         if (ipconfig->origin != NULL)
741                 return ipconfig->origin->index;
742
743         return ipconfig->index;
744 }
745
746 /**
747  * connman_ipconfig_get_ifname:
748  * @ipconfig: ipconfig structure
749  *
750  * Get interface name
751  */
752 const char *connman_ipconfig_get_ifname(struct connman_ipconfig *ipconfig)
753 {
754         struct connman_ipdevice *ipdevice;
755
756         if (ipconfig->index < 0)
757                 return NULL;
758
759         ipdevice = g_hash_table_lookup(ipdevice_hash,
760                                         GINT_TO_POINTER(ipconfig->index));
761         if (ipdevice == NULL)
762                 return NULL;
763
764         return ipdevice->ifname;
765 }
766
767 /**
768  * connman_ipconfig_set_ops:
769  * @ipconfig: ipconfig structure
770  * @ops: operation callbacks
771  *
772  * Set the operation callbacks
773  */
774 void connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
775                                 const struct connman_ipconfig_ops *ops)
776 {
777         if (ipconfig->ops != NULL)
778                 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
779
780         ipconfig->ops = ops;
781
782         if (ops != NULL)
783                 ipconfig_list = g_list_append(ipconfig_list, ipconfig);
784 }
785
786 /**
787  * connman_ipconfig_set_method:
788  * @ipconfig: ipconfig structure
789  * @method: configuration method
790  *
791  * Set the configuration method
792  */
793 int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
794                                         enum connman_ipconfig_method method)
795 {
796         ipconfig->method = method;
797
798         return 0;
799 }
800
801 /**
802  * connman_ipconfig_bind:
803  * @ipconfig: ipconfig structure
804  * @ipaddress: ipaddress structure
805  *
806  * Bind IP address details to configuration
807  */
808 void connman_ipconfig_bind(struct connman_ipconfig *ipconfig,
809                                         struct connman_ipaddress *ipaddress)
810 {
811         struct connman_ipconfig *origin;
812
813         origin = ipconfig->origin ? ipconfig->origin : ipconfig;
814
815         connman_ipaddress_copy(origin->address, ipaddress);
816
817         connman_inet_set_address(origin->index, origin->address);
818 }
819
820 int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
821 {
822         struct connman_ipdevice *ipdevice;
823
824         DBG("ipconfig %p", ipconfig);
825
826         if (ipconfig == NULL || ipconfig->index < 0)
827                 return -ENODEV;
828
829         ipdevice = g_hash_table_lookup(ipdevice_hash,
830                                         GINT_TO_POINTER(ipconfig->index));
831         if (ipdevice == NULL)
832                 return -ENXIO;
833
834         if (ipdevice->config != NULL)
835                 connman_ipconfig_unref(ipdevice->config);
836
837         ipdevice->config = connman_ipconfig_ref(ipconfig);
838
839         return 0;
840 }
841
842 int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
843 {
844         struct connman_ipdevice *ipdevice;
845
846         DBG("ipconfig %p", ipconfig);
847
848         if (ipconfig == NULL || ipconfig->index < 0)
849                 return -ENODEV;
850
851         ipdevice = g_hash_table_lookup(ipdevice_hash,
852                                         GINT_TO_POINTER(ipconfig->index));
853         if (ipdevice == NULL)
854                 return -ENXIO;
855
856         if (ipdevice->config == NULL || ipdevice->config != ipconfig)
857                 return -EINVAL;
858
859         connman_ipconfig_unref(ipdevice->config);
860         ipdevice->config = NULL;
861
862         return 0;
863 }
864
865 const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
866 {
867         switch (method) {
868         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
869                 break;
870         case CONNMAN_IPCONFIG_METHOD_IGNORE:
871                 return "ignore";
872         case CONNMAN_IPCONFIG_METHOD_STATIC:
873                 return "static";
874         case CONNMAN_IPCONFIG_METHOD_DHCP:
875                 return "dhcp";
876         }
877
878         return NULL;
879 }
880
881 enum connman_ipconfig_method __connman_ipconfig_string2method(const char *method)
882 {
883         if (g_strcmp0(method, "ignore") == 0)
884                 return CONNMAN_IPCONFIG_METHOD_IGNORE;
885         else if (g_strcmp0(method, "static") == 0)
886                 return CONNMAN_IPCONFIG_METHOD_STATIC;
887         else if (g_strcmp0(method, "dhcp") == 0)
888                 return CONNMAN_IPCONFIG_METHOD_DHCP;
889         else
890                 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
891 }
892
893 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
894                                                 DBusMessageIter *iter)
895 {
896         const char *str;
897
898         str = __connman_ipconfig_method2string(ipconfig->method);
899         if (str == NULL)
900                 return;
901
902         connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
903
904         if (ipconfig->address == NULL)
905                 return;
906
907         if (ipconfig->address->local != NULL) {
908                 struct in_addr netmask;
909                 char *mask;
910
911                 connman_dbus_dict_append_basic(iter, "Address",
912                                 DBUS_TYPE_STRING, &ipconfig->address->local);
913
914                 netmask.s_addr = ~0 << (32 - ipconfig->address->prefixlen);
915                 mask = inet_ntoa(netmask);
916                 connman_dbus_dict_append_basic(iter, "Netmask",
917                                                 DBUS_TYPE_STRING, &mask);
918         }
919 }
920
921 int __connman_ipconfig_set_ipv4(struct connman_ipconfig *ipconfig,
922                                 const char *key, DBusMessageIter *value)
923 {
924         int type = dbus_message_iter_get_arg_type(value);
925
926         DBG("ipconfig %p key %s type %d", ipconfig, key, type);
927
928         if (g_strcmp0(key, "Method") == 0) {
929                 const char *method;
930
931                 if (type != DBUS_TYPE_STRING)
932                         return -EINVAL;
933
934                 dbus_message_iter_get_basic(value, &method);
935
936                 ipconfig->method = __connman_ipconfig_string2method(method);
937         } else
938                 return -EINVAL;
939
940         return 0;
941 }
942
943 int __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
944                                                         DBusMessageIter *iter)
945 {
946         const char *method = "auto";
947
948         connman_dbus_dict_append_basic(iter, "Method",
949                                                 DBUS_TYPE_STRING, &method);
950
951         if (ipconfig->eth != NULL)
952                 connman_dbus_dict_append_basic(iter, "Address",
953                                         DBUS_TYPE_STRING, &ipconfig->eth);
954
955         if (ipconfig->mtu > 0)
956                 connman_dbus_dict_append_basic(iter, "MTU",
957                                         DBUS_TYPE_UINT16, &ipconfig->mtu);
958
959         return 0;
960 }
961
962 int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
963                 GKeyFile *keyfile, const char *identifier, const char *prefix)
964 {
965         DBG("ipconfig %p identifier %s", ipconfig, identifier);
966
967         return 0;
968 }
969
970 int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
971                 GKeyFile *keyfile, const char *identifier, const char *prefix)
972 {
973         DBG("ipconfig %p identifier %s", ipconfig, identifier);
974
975         return 0;
976 }
977
978 int __connman_ipconfig_init(void)
979 {
980         DBG("");
981
982         ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
983                                                         NULL, free_ipdevice);
984
985         return 0;
986 }
987
988 void __connman_ipconfig_cleanup(void)
989 {
990         DBG("");
991
992         g_hash_table_destroy(ipdevice_hash);
993         ipdevice_hash = NULL;
994 }