5 * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
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.
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.
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
29 #include <net/if_arp.h>
30 #include <linux/if_link.h>
35 #define IFF_LOWER_UP 0x10000
39 #include <connman/ipaddress.h>
43 struct connman_ipconfig {
46 enum connman_ipconfig_type type;
48 const struct connman_ipconfig_ops *ops;
51 enum connman_ipconfig_method method;
52 struct connman_ipaddress *address;
53 struct connman_ipaddress *system;
55 int ipv6_privacy_config;
56 char *last_dhcp_address;
57 char **last_dhcpv6_prefixes;
60 struct connman_ipdevice {
81 struct connman_ipconfig *config_ipv4;
82 struct connman_ipconfig *config_ipv6;
88 static GHashTable *ipdevice_hash = NULL;
89 static GList *ipconfig_list = NULL;
90 static bool is_ipv6_supported = false;
92 void __connman_ipconfig_clear_address(struct connman_ipconfig *ipconfig)
97 connman_ipaddress_clear(ipconfig->address);
100 static void free_address_list(struct connman_ipdevice *ipdevice)
104 for (list = ipdevice->address_list; list; list = list->next) {
105 struct connman_ipaddress *ipaddress = list->data;
107 connman_ipaddress_free(ipaddress);
111 g_slist_free(ipdevice->address_list);
112 ipdevice->address_list = NULL;
115 static struct connman_ipaddress *find_ipaddress(struct connman_ipdevice *ipdevice,
116 unsigned char prefixlen, const char *local)
120 for (list = ipdevice->address_list; list; list = list->next) {
121 struct connman_ipaddress *ipaddress = list->data;
123 if (g_strcmp0(ipaddress->local, local) == 0 &&
124 ipaddress->prefixlen == prefixlen)
131 const char *__connman_ipconfig_type2string(enum connman_ipconfig_type type)
134 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
135 case CONNMAN_IPCONFIG_TYPE_ALL:
137 case CONNMAN_IPCONFIG_TYPE_IPV4:
139 case CONNMAN_IPCONFIG_TYPE_IPV6:
146 static const char *type2str(unsigned short type)
151 case ARPHRD_LOOPBACK:
164 static const char *scope2str(unsigned char scope)
176 static bool get_ipv6_state(gchar *ifname)
181 bool enabled = false;
184 path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
186 path = g_strdup_printf(
187 "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
192 f = fopen(path, "r");
197 if (fscanf(f, "%d", &disabled) > 0)
205 static void set_ipv6_state(gchar *ifname, bool enable)
211 path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
213 path = g_strdup_printf(
214 "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
219 f = fopen(path, "r+");
234 static int get_ipv6_privacy(gchar *ifname)
243 path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
249 f = fopen(path, "r");
256 if (fscanf(f, "%d", &value) <= 0)
264 /* Enable the IPv6 privacy extension for stateless address autoconfiguration.
265 * The privacy extension is described in RFC 3041 and RFC 4941
267 static void set_ipv6_privacy(gchar *ifname, int value)
275 path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
284 f = fopen(path, "r+");
291 fprintf(f, "%d", value);
295 static int get_rp_filter(void)
298 int value = -EINVAL, tmp;
300 f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r");
303 if (fscanf(f, "%d", &tmp) == 1)
311 static void set_rp_filter(int value)
315 f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r+");
320 fprintf(f, "%d", value);
325 int __connman_ipconfig_set_rp_filter()
329 value = get_rp_filter();
336 connman_info("rp_filter set to 2 (loose mode routing), "
337 "old value was %d", value);
342 void __connman_ipconfig_unset_rp_filter(int old_value)
344 set_rp_filter(old_value);
346 connman_info("rp_filter restored to %d", old_value);
349 bool __connman_ipconfig_ipv6_privacy_enabled(struct connman_ipconfig *ipconfig)
354 return ipconfig->ipv6_privacy_config == 0 ? FALSE : TRUE;
357 bool __connman_ipconfig_ipv6_is_enabled(struct connman_ipconfig *ipconfig)
359 struct connman_ipdevice *ipdevice;
366 ipdevice = g_hash_table_lookup(ipdevice_hash,
367 GINT_TO_POINTER(ipconfig->index));
371 ifname = connman_inet_ifname(ipconfig->index);
372 ret = get_ipv6_state(ifname);
378 static void free_ipdevice(gpointer data)
380 struct connman_ipdevice *ipdevice = data;
381 char *ifname = connman_inet_ifname(ipdevice->index);
383 connman_info("%s {remove} index %d", ifname, ipdevice->index);
385 if (ipdevice->config_ipv4) {
386 __connman_ipconfig_unref(ipdevice->config_ipv4);
387 ipdevice->config_ipv4 = NULL;
390 if (ipdevice->config_ipv6) {
391 __connman_ipconfig_unref(ipdevice->config_ipv6);
392 ipdevice->config_ipv6 = NULL;
395 free_address_list(ipdevice);
396 g_free(ipdevice->ipv4_gateway);
397 g_free(ipdevice->ipv6_gateway);
398 g_free(ipdevice->pac);
400 g_free(ipdevice->address);
403 set_ipv6_state(ifname, ipdevice->ipv6_enabled);
404 set_ipv6_privacy(ifname, ipdevice->ipv6_privacy);
411 static void update_stats(struct connman_ipdevice *ipdevice,
412 const char *ifname, struct rtnl_link_stats *stats)
414 struct connman_service *service;
416 if (stats->rx_packets == 0 && stats->tx_packets == 0)
419 connman_info("%s {RX} %u packets %u bytes", ifname,
420 stats->rx_packets, stats->rx_bytes);
421 connman_info("%s {TX} %u packets %u bytes", ifname,
422 stats->tx_packets, stats->tx_bytes);
424 if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
427 service = __connman_service_lookup_from_index(ipdevice->index);
429 DBG("service %p", service);
434 ipdevice->rx_packets = stats->rx_packets;
435 ipdevice->tx_packets = stats->tx_packets;
436 ipdevice->rx_bytes = stats->rx_bytes;
437 ipdevice->tx_bytes = stats->tx_bytes;
438 ipdevice->rx_errors = stats->rx_errors;
439 ipdevice->tx_errors = stats->tx_errors;
440 ipdevice->rx_dropped = stats->rx_dropped;
441 ipdevice->tx_dropped = stats->tx_dropped;
443 __connman_service_notify(service,
444 ipdevice->rx_packets, ipdevice->tx_packets,
445 ipdevice->rx_bytes, ipdevice->tx_bytes,
446 ipdevice->rx_errors, ipdevice->tx_errors,
447 ipdevice->rx_dropped, ipdevice->tx_dropped);
450 void __connman_ipconfig_newlink(int index, unsigned short type,
451 unsigned int flags, const char *address,
453 struct rtnl_link_stats *stats)
455 struct connman_ipdevice *ipdevice;
456 GList *list, *ipconfig_copy;
458 bool up = false, down = false;
459 bool lower_up = false, lower_down = false;
462 DBG("index %d", index);
464 if (type == ARPHRD_LOOPBACK)
467 ifname = connman_inet_ifname(index);
469 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
473 ipdevice = g_try_new0(struct connman_ipdevice, 1);
477 ipdevice->index = index;
478 ipdevice->type = type;
480 ipdevice->ipv6_enabled = get_ipv6_state(ifname);
481 ipdevice->ipv6_privacy = get_ipv6_privacy(ifname);
483 ipdevice->address = g_strdup(address);
485 g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
487 connman_info("%s {create} index %d type %d <%s>", ifname,
488 index, type, type2str(type));
493 update_stats(ipdevice, ifname, stats);
495 if (flags == ipdevice->flags)
498 if ((ipdevice->flags & IFF_UP) != (flags & IFF_UP)) {
505 if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) !=
506 (flags & (IFF_RUNNING | IFF_LOWER_UP))) {
507 if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
508 (IFF_RUNNING | IFF_LOWER_UP))
510 else if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
514 ipdevice->flags = flags;
516 str = g_string_new(NULL);
521 g_string_append(str, "UP");
523 g_string_append(str, "DOWN");
525 if (flags & IFF_RUNNING)
526 g_string_append(str, ",RUNNING");
528 if (flags & IFF_LOWER_UP)
529 g_string_append(str, ",LOWER_UP");
531 connman_info("%s {update} flags %u <%s>", ifname, flags, str->str);
533 g_string_free(str, TRUE);
535 ipconfig_copy = g_list_copy(ipconfig_list);
537 for (list = g_list_first(ipconfig_copy); list;
538 list = g_list_next(list)) {
539 struct connman_ipconfig *ipconfig = list->data;
541 if (index != ipconfig->index)
547 if (up && ipconfig->ops->up)
548 ipconfig->ops->up(ipconfig, ifname);
549 if (lower_up && ipconfig->ops->lower_up)
550 ipconfig->ops->lower_up(ipconfig, ifname);
552 if (lower_down && ipconfig->ops->lower_down)
553 ipconfig->ops->lower_down(ipconfig, ifname);
554 if (down && ipconfig->ops->down)
555 ipconfig->ops->down(ipconfig, ifname);
558 g_list_free(ipconfig_copy);
564 void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats)
566 struct connman_ipdevice *ipdevice;
570 DBG("index %d", index);
572 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
576 ifname = connman_inet_ifname(index);
578 update_stats(ipdevice, ifname, stats);
580 for (list = g_list_first(ipconfig_list); list;
581 list = g_list_next(list)) {
582 struct connman_ipconfig *ipconfig = list->data;
584 if (index != ipconfig->index)
587 ipconfig->index = -1;
592 if (ipconfig->ops->lower_down)
593 ipconfig->ops->lower_down(ipconfig, ifname);
594 if (ipconfig->ops->down)
595 ipconfig->ops->down(ipconfig, ifname);
600 g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
603 static inline gint check_duplicate_address(gconstpointer a, gconstpointer b)
605 const struct connman_ipaddress *addr1 = a;
606 const struct connman_ipaddress *addr2 = b;
608 if (addr1->prefixlen != addr2->prefixlen)
609 return addr2->prefixlen - addr1->prefixlen;
611 return g_strcmp0(addr1->local, addr2->local);
614 int __connman_ipconfig_newaddr(int index, int family, const char *label,
615 unsigned char prefixlen, const char *address)
617 struct connman_ipdevice *ipdevice;
618 struct connman_ipaddress *ipaddress;
619 enum connman_ipconfig_type type;
623 DBG("index %d", index);
625 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
629 ipaddress = connman_ipaddress_alloc(family);
633 ipaddress->prefixlen = prefixlen;
634 ipaddress->local = g_strdup(address);
636 if (g_slist_find_custom(ipdevice->address_list, ipaddress,
637 check_duplicate_address)) {
638 connman_ipaddress_free(ipaddress);
642 if (family == AF_INET)
643 type = CONNMAN_IPCONFIG_TYPE_IPV4;
644 else if (family == AF_INET6)
645 type = CONNMAN_IPCONFIG_TYPE_IPV6;
649 ipdevice->address_list = g_slist_prepend(ipdevice->address_list,
652 ifname = connman_inet_ifname(index);
653 connman_info("%s {add} address %s/%u label %s family %d",
654 ifname, address, prefixlen, label, family);
656 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
657 __connman_ippool_newaddr(index, address, prefixlen);
659 if (ipdevice->config_ipv4 && family == AF_INET)
660 connman_ipaddress_copy_address(ipdevice->config_ipv4->system,
663 else if (ipdevice->config_ipv6 && family == AF_INET6)
664 connman_ipaddress_copy_address(ipdevice->config_ipv6->system,
669 if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
672 for (list = g_list_first(ipconfig_list); list;
673 list = g_list_next(list)) {
674 struct connman_ipconfig *ipconfig = list->data;
676 if (index != ipconfig->index)
679 if (type != ipconfig->type)
685 if (ipconfig->ops->ip_bound)
686 ipconfig->ops->ip_bound(ipconfig, ifname);
694 void __connman_ipconfig_deladdr(int index, int family, const char *label,
695 unsigned char prefixlen, const char *address)
697 struct connman_ipdevice *ipdevice;
698 struct connman_ipaddress *ipaddress;
699 enum connman_ipconfig_type type;
703 DBG("index %d", index);
705 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
709 ipaddress = find_ipaddress(ipdevice, prefixlen, address);
713 if (family == AF_INET)
714 type = CONNMAN_IPCONFIG_TYPE_IPV4;
715 else if (family == AF_INET6)
716 type = CONNMAN_IPCONFIG_TYPE_IPV6;
720 ipdevice->address_list = g_slist_remove(ipdevice->address_list,
723 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
724 __connman_ippool_deladdr(index, address, prefixlen);
726 connman_ipaddress_clear(ipaddress);
729 ifname = connman_inet_ifname(index);
730 connman_info("%s {del} address %s/%u label %s", ifname,
731 address, prefixlen, label);
733 if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
736 if (g_slist_length(ipdevice->address_list) > 0)
739 for (list = g_list_first(ipconfig_list); list;
740 list = g_list_next(list)) {
741 struct connman_ipconfig *ipconfig = list->data;
743 if (index != ipconfig->index)
746 if (type != ipconfig->type)
752 if (ipconfig->ops->ip_release)
753 ipconfig->ops->ip_release(ipconfig, ifname);
760 void __connman_ipconfig_newroute(int index, int family, unsigned char scope,
761 const char *dst, const char *gateway)
763 struct connman_ipdevice *ipdevice;
766 DBG("index %d", index);
768 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
772 ifname = connman_inet_ifname(index);
774 if (scope == 0 && (g_strcmp0(dst, "0.0.0.0") == 0 ||
775 g_strcmp0(dst, "::") == 0)) {
777 enum connman_ipconfig_type type;
779 if (family == AF_INET6) {
780 type = CONNMAN_IPCONFIG_TYPE_IPV6;
781 g_free(ipdevice->ipv6_gateway);
782 ipdevice->ipv6_gateway = g_strdup(gateway);
784 if (ipdevice->config_ipv6 &&
785 ipdevice->config_ipv6->system) {
786 g_free(ipdevice->config_ipv6->system->gateway);
787 ipdevice->config_ipv6->system->gateway =
790 } else if (family == AF_INET) {
791 type = CONNMAN_IPCONFIG_TYPE_IPV4;
792 g_free(ipdevice->ipv4_gateway);
793 ipdevice->ipv4_gateway = g_strdup(gateway);
795 if (ipdevice->config_ipv4 &&
796 ipdevice->config_ipv4->system) {
797 g_free(ipdevice->config_ipv4->system->gateway);
798 ipdevice->config_ipv4->system->gateway =
804 for (config_list = g_list_first(ipconfig_list); config_list;
805 config_list = g_list_next(config_list)) {
806 struct connman_ipconfig *ipconfig = config_list->data;
808 if (index != ipconfig->index)
811 if (type != ipconfig->type)
817 if (ipconfig->ops->route_set)
818 ipconfig->ops->route_set(ipconfig, ifname);
822 connman_info("%s {add} route %s gw %s scope %u <%s>",
823 ifname, dst, gateway, scope, scope2str(scope));
829 void __connman_ipconfig_delroute(int index, int family, unsigned char scope,
830 const char *dst, const char *gateway)
832 struct connman_ipdevice *ipdevice;
835 DBG("index %d", index);
837 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
841 ifname = connman_inet_ifname(index);
843 if (scope == 0 && (g_strcmp0(dst, "0.0.0.0") == 0 ||
844 g_strcmp0(dst, "::") == 0)) {
846 enum connman_ipconfig_type type;
848 if (family == AF_INET6) {
849 type = CONNMAN_IPCONFIG_TYPE_IPV6;
850 g_free(ipdevice->ipv6_gateway);
851 ipdevice->ipv6_gateway = NULL;
853 if (ipdevice->config_ipv6 &&
854 ipdevice->config_ipv6->system) {
855 g_free(ipdevice->config_ipv6->system->gateway);
856 ipdevice->config_ipv6->system->gateway = NULL;
858 } else if (family == AF_INET) {
859 type = CONNMAN_IPCONFIG_TYPE_IPV4;
860 g_free(ipdevice->ipv4_gateway);
861 ipdevice->ipv4_gateway = NULL;
863 if (ipdevice->config_ipv4 &&
864 ipdevice->config_ipv4->system) {
865 g_free(ipdevice->config_ipv4->system->gateway);
866 ipdevice->config_ipv4->system->gateway = NULL;
871 for (config_list = g_list_first(ipconfig_list); config_list;
872 config_list = g_list_next(config_list)) {
873 struct connman_ipconfig *ipconfig = config_list->data;
875 if (index != ipconfig->index)
878 if (type != ipconfig->type)
884 if (ipconfig->ops->route_unset)
885 ipconfig->ops->route_unset(ipconfig, ifname);
889 connman_info("%s {del} route %s gw %s scope %u <%s>",
890 ifname, dst, gateway, scope, scope2str(scope));
896 void __connman_ipconfig_foreach(void (*function) (int index, void *user_data),
901 keys = g_hash_table_get_keys(ipdevice_hash);
905 for (list = g_list_first(keys); list; list = g_list_next(list)) {
906 int index = GPOINTER_TO_INT(list->data);
908 function(index, user_data);
914 enum connman_ipconfig_type __connman_ipconfig_get_config_type(
915 struct connman_ipconfig *ipconfig)
917 return ipconfig ? ipconfig->type : CONNMAN_IPCONFIG_TYPE_UNKNOWN;
920 unsigned short __connman_ipconfig_get_type_from_index(int index)
922 struct connman_ipdevice *ipdevice;
924 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
928 return ipdevice->type;
931 unsigned int __connman_ipconfig_get_flags_from_index(int index)
933 struct connman_ipdevice *ipdevice;
935 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
939 return ipdevice->flags;
942 const char *__connman_ipconfig_get_gateway_from_index(int index,
943 enum connman_ipconfig_type type)
945 struct connman_ipdevice *ipdevice;
947 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
951 if (type != CONNMAN_IPCONFIG_TYPE_IPV6) {
952 if (ipdevice->ipv4_gateway)
953 return ipdevice->ipv4_gateway;
955 if (ipdevice->config_ipv4 &&
956 ipdevice->config_ipv4->address)
957 return ipdevice->config_ipv4->address->gateway;
960 if (type != CONNMAN_IPCONFIG_TYPE_IPV4) {
961 if (ipdevice->ipv6_gateway)
962 return ipdevice->ipv6_gateway;
964 if (ipdevice->config_ipv6 &&
965 ipdevice->config_ipv6->address)
966 return ipdevice->config_ipv6->address->gateway;
972 void __connman_ipconfig_set_index(struct connman_ipconfig *ipconfig, int index)
974 ipconfig->index = index;
977 const char *__connman_ipconfig_get_local(struct connman_ipconfig *ipconfig)
979 if (!ipconfig->address)
982 return ipconfig->address->local;
985 void __connman_ipconfig_set_local(struct connman_ipconfig *ipconfig,
988 if (!ipconfig->address)
991 g_free(ipconfig->address->local);
992 ipconfig->address->local = g_strdup(address);
995 const char *__connman_ipconfig_get_peer(struct connman_ipconfig *ipconfig)
997 if (!ipconfig->address)
1000 return ipconfig->address->peer;
1003 void __connman_ipconfig_set_peer(struct connman_ipconfig *ipconfig,
1004 const char *address)
1006 if (!ipconfig->address)
1009 g_free(ipconfig->address->peer);
1010 ipconfig->address->peer = g_strdup(address);
1013 const char *__connman_ipconfig_get_broadcast(struct connman_ipconfig *ipconfig)
1015 if (!ipconfig->address)
1018 return ipconfig->address->broadcast;
1021 void __connman_ipconfig_set_broadcast(struct connman_ipconfig *ipconfig,
1022 const char *broadcast)
1024 if (!ipconfig->address)
1027 g_free(ipconfig->address->broadcast);
1028 ipconfig->address->broadcast = g_strdup(broadcast);
1031 const char *__connman_ipconfig_get_gateway(struct connman_ipconfig *ipconfig)
1033 if (!ipconfig->address)
1036 return ipconfig->address->gateway;
1039 void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig,
1040 const char *gateway)
1044 if (!ipconfig->address)
1046 g_free(ipconfig->address->gateway);
1047 ipconfig->address->gateway = g_strdup(gateway);
1050 int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig)
1052 struct connman_service *service;
1056 if (!ipconfig->address)
1059 service = __connman_service_lookup_from_index(ipconfig->index);
1063 DBG("type %d gw %s peer %s", ipconfig->type,
1064 ipconfig->address->gateway, ipconfig->address->peer);
1066 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6 ||
1067 ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1068 return __connman_connection_gateway_add(service,
1069 ipconfig->address->gateway,
1071 ipconfig->address->peer);
1076 void __connman_ipconfig_gateway_remove(struct connman_ipconfig *ipconfig)
1078 struct connman_service *service;
1082 service = __connman_service_lookup_from_index(ipconfig->index);
1084 __connman_connection_gateway_remove(service, ipconfig->type);
1087 unsigned char __connman_ipconfig_get_prefixlen(struct connman_ipconfig *ipconfig)
1089 if (!ipconfig->address)
1092 return ipconfig->address->prefixlen;
1095 void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig,
1096 unsigned char prefixlen)
1098 if (!ipconfig->address)
1101 ipconfig->address->prefixlen = prefixlen;
1104 static struct connman_ipconfig *create_ipv6config(int index)
1106 struct connman_ipconfig *ipv6config;
1107 struct connman_ipdevice *ipdevice;
1109 ipv6config = g_try_new0(struct connman_ipconfig, 1);
1113 ipv6config->refcount = 1;
1115 ipv6config->index = index;
1116 ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6;
1118 if (!is_ipv6_supported)
1119 ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF;
1121 ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO;
1123 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1125 ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy;
1127 ipv6config->address = connman_ipaddress_alloc(AF_INET6);
1128 if (!ipv6config->address) {
1133 ipv6config->system = connman_ipaddress_alloc(AF_INET6);
1135 DBG("ipconfig %p index %d method %s", ipv6config, index,
1136 __connman_ipconfig_method2string(ipv6config->method));
1142 * connman_ipconfig_create:
1144 * Allocate a new ipconfig structure.
1146 * Returns: a newly-allocated #connman_ipconfig structure
1148 struct connman_ipconfig *__connman_ipconfig_create(int index,
1149 enum connman_ipconfig_type type)
1151 struct connman_ipconfig *ipconfig;
1153 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1154 return create_ipv6config(index);
1156 ipconfig = g_try_new0(struct connman_ipconfig, 1);
1160 ipconfig->refcount = 1;
1162 ipconfig->index = index;
1163 ipconfig->type = CONNMAN_IPCONFIG_TYPE_IPV4;
1165 ipconfig->address = connman_ipaddress_alloc(AF_INET);
1166 if (!ipconfig->address) {
1171 ipconfig->system = connman_ipaddress_alloc(AF_INET);
1173 DBG("ipconfig %p index %d", ipconfig, index);
1180 * connman_ipconfig_ref:
1181 * @ipconfig: ipconfig structure
1183 * Increase reference counter of ipconfig
1185 struct connman_ipconfig *
1186 __connman_ipconfig_ref_debug(struct connman_ipconfig *ipconfig,
1187 const char *file, int line, const char *caller)
1189 DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount + 1,
1190 file, line, caller);
1192 __sync_fetch_and_add(&ipconfig->refcount, 1);
1198 * connman_ipconfig_unref:
1199 * @ipconfig: ipconfig structure
1201 * Decrease reference counter of ipconfig
1203 void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig,
1204 const char *file, int line, const char *caller)
1209 DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount - 1,
1210 file, line, caller);
1212 if (__sync_fetch_and_sub(&ipconfig->refcount, 1) != 1)
1215 if (__connman_ipconfig_disable(ipconfig) < 0)
1216 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1218 __connman_ipconfig_set_ops(ipconfig, NULL);
1220 connman_ipaddress_free(ipconfig->system);
1221 connman_ipaddress_free(ipconfig->address);
1222 g_free(ipconfig->last_dhcp_address);
1223 g_strfreev(ipconfig->last_dhcpv6_prefixes);
1228 * connman_ipconfig_get_data:
1229 * @ipconfig: ipconfig structure
1231 * Get private data pointer
1233 void *__connman_ipconfig_get_data(struct connman_ipconfig *ipconfig)
1238 return ipconfig->ops_data;
1242 * connman_ipconfig_set_data:
1243 * @ipconfig: ipconfig structure
1244 * @data: data pointer
1246 * Set private data pointer
1248 void __connman_ipconfig_set_data(struct connman_ipconfig *ipconfig, void *data)
1250 ipconfig->ops_data = data;
1254 * connman_ipconfig_get_index:
1255 * @ipconfig: ipconfig structure
1257 * Get interface index
1259 int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
1264 return ipconfig->index;
1268 * connman_ipconfig_set_ops:
1269 * @ipconfig: ipconfig structure
1270 * @ops: operation callbacks
1272 * Set the operation callbacks
1274 void __connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
1275 const struct connman_ipconfig_ops *ops)
1277 ipconfig->ops = ops;
1281 * connman_ipconfig_set_method:
1282 * @ipconfig: ipconfig structure
1283 * @method: configuration method
1285 * Set the configuration method
1287 int __connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
1288 enum connman_ipconfig_method method)
1290 ipconfig->method = method;
1295 enum connman_ipconfig_method __connman_ipconfig_get_method(
1296 struct connman_ipconfig *ipconfig)
1299 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1301 return ipconfig->method;
1304 int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig)
1306 switch (ipconfig->method) {
1307 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1308 case CONNMAN_IPCONFIG_METHOD_OFF:
1310 case CONNMAN_IPCONFIG_METHOD_AUTO:
1311 case CONNMAN_IPCONFIG_METHOD_FIXED:
1312 case CONNMAN_IPCONFIG_METHOD_DHCP:
1313 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1314 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1315 return connman_inet_set_address(ipconfig->index,
1317 else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
1318 return connman_inet_set_ipv6_address(
1319 ipconfig->index, ipconfig->address);
1325 int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig)
1332 switch (ipconfig->method) {
1333 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1334 case CONNMAN_IPCONFIG_METHOD_OFF:
1336 case CONNMAN_IPCONFIG_METHOD_AUTO:
1337 case CONNMAN_IPCONFIG_METHOD_FIXED:
1338 case CONNMAN_IPCONFIG_METHOD_DHCP:
1339 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1340 err = __connman_ipconfig_address_unset(ipconfig);
1341 connman_ipaddress_clear(ipconfig->address);
1349 int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig)
1356 switch (ipconfig->method) {
1357 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1358 case CONNMAN_IPCONFIG_METHOD_OFF:
1360 case CONNMAN_IPCONFIG_METHOD_AUTO:
1361 case CONNMAN_IPCONFIG_METHOD_FIXED:
1362 case CONNMAN_IPCONFIG_METHOD_DHCP:
1363 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1364 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1365 err = connman_inet_clear_address(ipconfig->index,
1367 else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
1368 err = connman_inet_clear_ipv6_address(
1370 ipconfig->address->local,
1371 ipconfig->address->prefixlen);
1381 int __connman_ipconfig_set_proxy_autoconfig(struct connman_ipconfig *ipconfig,
1384 struct connman_ipdevice *ipdevice;
1386 if (!ipconfig || ipconfig->index < 0)
1389 ipdevice = g_hash_table_lookup(ipdevice_hash,
1390 GINT_TO_POINTER(ipconfig->index));
1394 g_free(ipdevice->pac);
1395 ipdevice->pac = g_strdup(url);
1400 const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipconfig)
1402 struct connman_ipdevice *ipdevice;
1404 if (!ipconfig || ipconfig->index < 0)
1407 ipdevice = g_hash_table_lookup(ipdevice_hash,
1408 GINT_TO_POINTER(ipconfig->index));
1412 return ipdevice->pac;
1415 void __connman_ipconfig_set_dhcp_address(struct connman_ipconfig *ipconfig,
1416 const char *address)
1421 g_free(ipconfig->last_dhcp_address);
1422 ipconfig->last_dhcp_address = g_strdup(address);
1425 char *__connman_ipconfig_get_dhcp_address(struct connman_ipconfig *ipconfig)
1430 return ipconfig->last_dhcp_address;
1433 void __connman_ipconfig_set_dhcpv6_prefixes(struct connman_ipconfig *ipconfig,
1439 g_strfreev(ipconfig->last_dhcpv6_prefixes);
1440 ipconfig->last_dhcpv6_prefixes = prefixes;
1443 char **__connman_ipconfig_get_dhcpv6_prefixes(struct connman_ipconfig *ipconfig)
1448 return ipconfig->last_dhcpv6_prefixes;
1451 static void disable_ipv6(struct connman_ipconfig *ipconfig)
1453 struct connman_ipdevice *ipdevice;
1458 ipdevice = g_hash_table_lookup(ipdevice_hash,
1459 GINT_TO_POINTER(ipconfig->index));
1463 ifname = connman_inet_ifname(ipconfig->index);
1465 set_ipv6_state(ifname, false);
1470 static void enable_ipv6(struct connman_ipconfig *ipconfig)
1472 struct connman_ipdevice *ipdevice;
1477 ipdevice = g_hash_table_lookup(ipdevice_hash,
1478 GINT_TO_POINTER(ipconfig->index));
1482 ifname = connman_inet_ifname(ipconfig->index);
1484 if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO)
1485 set_ipv6_privacy(ifname, ipconfig->ipv6_privacy_config);
1487 set_ipv6_state(ifname, true);
1492 void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig)
1494 if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1497 enable_ipv6(ipconfig);
1500 void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig)
1502 if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1505 disable_ipv6(ipconfig);
1508 bool __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig)
1513 switch (ipconfig->method) {
1514 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1515 case CONNMAN_IPCONFIG_METHOD_OFF:
1517 case CONNMAN_IPCONFIG_METHOD_AUTO:
1518 case CONNMAN_IPCONFIG_METHOD_FIXED:
1519 case CONNMAN_IPCONFIG_METHOD_DHCP:
1520 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1527 int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
1529 struct connman_ipdevice *ipdevice;
1530 bool up = false, down = false;
1531 bool lower_up = false, lower_down = false;
1532 enum connman_ipconfig_type type;
1535 DBG("ipconfig %p", ipconfig);
1537 if (!ipconfig || ipconfig->index < 0)
1540 ipdevice = g_hash_table_lookup(ipdevice_hash,
1541 GINT_TO_POINTER(ipconfig->index));
1545 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4) {
1546 if (ipdevice->config_ipv4 == ipconfig)
1548 type = CONNMAN_IPCONFIG_TYPE_IPV4;
1549 } else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
1550 if (ipdevice->config_ipv6 == ipconfig)
1552 type = CONNMAN_IPCONFIG_TYPE_IPV6;
1556 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
1557 ipdevice->config_ipv4) {
1558 ipconfig_list = g_list_remove(ipconfig_list,
1559 ipdevice->config_ipv4);
1561 connman_ipaddress_clear(ipdevice->config_ipv4->system);
1563 __connman_ipconfig_unref(ipdevice->config_ipv4);
1566 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
1567 ipdevice->config_ipv6) {
1568 ipconfig_list = g_list_remove(ipconfig_list,
1569 ipdevice->config_ipv6);
1571 connman_ipaddress_clear(ipdevice->config_ipv6->system);
1573 __connman_ipconfig_unref(ipdevice->config_ipv6);
1576 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1577 ipdevice->config_ipv4 = __connman_ipconfig_ref(ipconfig);
1578 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
1579 ipdevice->config_ipv6 = __connman_ipconfig_ref(ipconfig);
1581 enable_ipv6(ipdevice->config_ipv6);
1583 ipconfig_list = g_list_append(ipconfig_list, ipconfig);
1585 if (ipdevice->flags & IFF_UP)
1590 if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
1591 (IFF_RUNNING | IFF_LOWER_UP))
1593 else if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
1596 ifname = connman_inet_ifname(ipconfig->index);
1598 if (up && ipconfig->ops->up)
1599 ipconfig->ops->up(ipconfig, ifname);
1600 if (lower_up && ipconfig->ops->lower_up)
1601 ipconfig->ops->lower_up(ipconfig, ifname);
1603 if (lower_down && ipconfig->ops->lower_down)
1604 ipconfig->ops->lower_down(ipconfig, ifname);
1605 if (down && ipconfig->ops->down)
1606 ipconfig->ops->down(ipconfig, ifname);
1613 int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
1615 struct connman_ipdevice *ipdevice;
1617 DBG("ipconfig %p", ipconfig);
1619 if (!ipconfig || ipconfig->index < 0)
1622 ipdevice = g_hash_table_lookup(ipdevice_hash,
1623 GINT_TO_POINTER(ipconfig->index));
1627 if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
1630 if (ipdevice->config_ipv4 == ipconfig) {
1631 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1633 connman_ipaddress_clear(ipdevice->config_ipv4->system);
1634 __connman_ipconfig_unref(ipdevice->config_ipv4);
1635 ipdevice->config_ipv4 = NULL;
1639 if (ipdevice->config_ipv6 == ipconfig) {
1640 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1642 connman_ipaddress_clear(ipdevice->config_ipv6->system);
1643 __connman_ipconfig_unref(ipdevice->config_ipv6);
1644 ipdevice->config_ipv6 = NULL;
1651 const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
1654 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1656 case CONNMAN_IPCONFIG_METHOD_OFF:
1658 case CONNMAN_IPCONFIG_METHOD_FIXED:
1660 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1662 case CONNMAN_IPCONFIG_METHOD_DHCP:
1664 case CONNMAN_IPCONFIG_METHOD_AUTO:
1671 enum connman_ipconfig_method __connman_ipconfig_string2method(const char *method)
1673 if (g_strcmp0(method, "off") == 0)
1674 return CONNMAN_IPCONFIG_METHOD_OFF;
1675 else if (g_strcmp0(method, "fixed") == 0)
1676 return CONNMAN_IPCONFIG_METHOD_FIXED;
1677 else if (g_strcmp0(method, "manual") == 0)
1678 return CONNMAN_IPCONFIG_METHOD_MANUAL;
1679 else if (g_strcmp0(method, "dhcp") == 0)
1680 return CONNMAN_IPCONFIG_METHOD_DHCP;
1681 else if (g_strcmp0(method, "auto") == 0)
1682 return CONNMAN_IPCONFIG_METHOD_AUTO;
1684 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1687 static const char *privacy2string(int privacy)
1691 else if (privacy == 1)
1697 static int string2privacy(const char *privacy)
1699 if (g_strcmp0(privacy, "disabled") == 0)
1701 else if (g_strcmp0(privacy, "enabled") == 0)
1703 else if (g_strcmp0(privacy, "preferred") == 0)
1705 else if (g_strcmp0(privacy, "prefered") == 0)
1711 int __connman_ipconfig_ipv6_reset_privacy(struct connman_ipconfig *ipconfig)
1713 struct connman_ipdevice *ipdevice;
1719 ipdevice = g_hash_table_lookup(ipdevice_hash,
1720 GINT_TO_POINTER(ipconfig->index));
1724 err = __connman_ipconfig_ipv6_set_privacy(ipconfig, privacy2string(
1725 ipdevice->ipv6_privacy));
1730 int __connman_ipconfig_ipv6_set_privacy(struct connman_ipconfig *ipconfig,
1738 privacy = string2privacy(value);
1740 ipconfig->ipv6_privacy_config = privacy;
1742 enable_ipv6(ipconfig);
1747 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
1748 DBusMessageIter *iter)
1750 struct connman_ipaddress *append_addr = NULL;
1753 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
1756 str = __connman_ipconfig_method2string(ipconfig->method);
1760 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1762 switch (ipconfig->method) {
1763 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1764 case CONNMAN_IPCONFIG_METHOD_OFF:
1767 case CONNMAN_IPCONFIG_METHOD_FIXED:
1768 append_addr = ipconfig->address;
1771 case CONNMAN_IPCONFIG_METHOD_AUTO:
1772 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1773 case CONNMAN_IPCONFIG_METHOD_DHCP:
1774 append_addr = ipconfig->system;
1781 if (append_addr->local) {
1783 struct in_addr netmask;
1786 connman_dbus_dict_append_basic(iter, "Address",
1787 DBUS_TYPE_STRING, &append_addr->local);
1789 addr = 0xffffffff << (32 - append_addr->prefixlen);
1790 netmask.s_addr = htonl(addr);
1791 mask = inet_ntoa(netmask);
1792 connman_dbus_dict_append_basic(iter, "Netmask",
1793 DBUS_TYPE_STRING, &mask);
1796 if (append_addr->gateway)
1797 connman_dbus_dict_append_basic(iter, "Gateway",
1798 DBUS_TYPE_STRING, &append_addr->gateway);
1801 void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
1802 DBusMessageIter *iter,
1803 struct connman_ipconfig *ipconfig_ipv4)
1805 struct connman_ipaddress *append_addr = NULL;
1806 const char *str, *privacy;
1808 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1811 str = __connman_ipconfig_method2string(ipconfig->method);
1815 if (ipconfig_ipv4 &&
1816 ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1817 if (__connman_6to4_check(ipconfig_ipv4) == 1)
1821 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1823 switch (ipconfig->method) {
1824 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1825 case CONNMAN_IPCONFIG_METHOD_OFF:
1828 case CONNMAN_IPCONFIG_METHOD_FIXED:
1829 append_addr = ipconfig->address;
1832 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1833 case CONNMAN_IPCONFIG_METHOD_DHCP:
1834 case CONNMAN_IPCONFIG_METHOD_AUTO:
1835 append_addr = ipconfig->system;
1842 if (append_addr->local) {
1843 connman_dbus_dict_append_basic(iter, "Address",
1844 DBUS_TYPE_STRING, &append_addr->local);
1845 connman_dbus_dict_append_basic(iter, "PrefixLength",
1847 &append_addr->prefixlen);
1850 if (append_addr->gateway)
1851 connman_dbus_dict_append_basic(iter, "Gateway",
1852 DBUS_TYPE_STRING, &append_addr->gateway);
1854 privacy = privacy2string(ipconfig->ipv6_privacy_config);
1855 connman_dbus_dict_append_basic(iter, "Privacy",
1856 DBUS_TYPE_STRING, &privacy);
1859 void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig,
1860 DBusMessageIter *iter)
1862 const char *str, *privacy;
1864 str = __connman_ipconfig_method2string(ipconfig->method);
1868 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1870 switch (ipconfig->method) {
1871 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1872 case CONNMAN_IPCONFIG_METHOD_OFF:
1873 case CONNMAN_IPCONFIG_METHOD_DHCP:
1875 case CONNMAN_IPCONFIG_METHOD_FIXED:
1876 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1877 case CONNMAN_IPCONFIG_METHOD_AUTO:
1881 if (!ipconfig->address)
1884 if (ipconfig->address->local) {
1885 connman_dbus_dict_append_basic(iter, "Address",
1886 DBUS_TYPE_STRING, &ipconfig->address->local);
1887 connman_dbus_dict_append_basic(iter, "PrefixLength",
1889 &ipconfig->address->prefixlen);
1892 if (ipconfig->address->gateway)
1893 connman_dbus_dict_append_basic(iter, "Gateway",
1894 DBUS_TYPE_STRING, &ipconfig->address->gateway);
1896 privacy = privacy2string(ipconfig->ipv6_privacy_config);
1897 connman_dbus_dict_append_basic(iter, "Privacy",
1898 DBUS_TYPE_STRING, &privacy);
1901 void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig,
1902 DBusMessageIter *iter)
1906 str = __connman_ipconfig_method2string(ipconfig->method);
1910 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1912 switch (ipconfig->method) {
1913 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1914 case CONNMAN_IPCONFIG_METHOD_OFF:
1915 case CONNMAN_IPCONFIG_METHOD_DHCP:
1916 case CONNMAN_IPCONFIG_METHOD_AUTO:
1918 case CONNMAN_IPCONFIG_METHOD_FIXED:
1919 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1923 if (!ipconfig->address)
1926 if (ipconfig->address->local) {
1928 struct in_addr netmask;
1931 connman_dbus_dict_append_basic(iter, "Address",
1932 DBUS_TYPE_STRING, &ipconfig->address->local);
1934 addr = 0xffffffff << (32 - ipconfig->address->prefixlen);
1935 netmask.s_addr = htonl(addr);
1936 mask = inet_ntoa(netmask);
1937 connman_dbus_dict_append_basic(iter, "Netmask",
1938 DBUS_TYPE_STRING, &mask);
1941 if (ipconfig->address->gateway)
1942 connman_dbus_dict_append_basic(iter, "Gateway",
1943 DBUS_TYPE_STRING, &ipconfig->address->gateway);
1946 int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
1947 DBusMessageIter *array)
1949 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1950 const char *address = NULL, *netmask = NULL, *gateway = NULL,
1951 *privacy_string = NULL;
1952 int prefix_length = 0, privacy = 0;
1953 DBusMessageIter dict;
1956 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1959 dbus_message_iter_recurse(array, &dict);
1961 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1962 DBusMessageIter entry, value;
1966 dbus_message_iter_recurse(&dict, &entry);
1968 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1971 dbus_message_iter_get_basic(&entry, &key);
1972 dbus_message_iter_next(&entry);
1974 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1977 dbus_message_iter_recurse(&entry, &value);
1979 type = dbus_message_iter_get_arg_type(&value);
1981 if (g_str_equal(key, "Method")) {
1984 if (type != DBUS_TYPE_STRING)
1987 dbus_message_iter_get_basic(&value, &str);
1988 method = __connman_ipconfig_string2method(str);
1989 } else if (g_str_equal(key, "Address")) {
1990 if (type != DBUS_TYPE_STRING)
1993 dbus_message_iter_get_basic(&value, &address);
1994 } else if (g_str_equal(key, "PrefixLength")) {
1995 if (type != DBUS_TYPE_BYTE)
1998 dbus_message_iter_get_basic(&value, &prefix_length);
2000 if (prefix_length < 0 || prefix_length > 128)
2002 } else if (g_str_equal(key, "Netmask")) {
2003 if (type != DBUS_TYPE_STRING)
2006 dbus_message_iter_get_basic(&value, &netmask);
2007 } else if (g_str_equal(key, "Gateway")) {
2008 if (type != DBUS_TYPE_STRING)
2011 dbus_message_iter_get_basic(&value, &gateway);
2012 } else if (g_str_equal(key, "Privacy")) {
2013 if (type != DBUS_TYPE_STRING)
2016 dbus_message_iter_get_basic(&value, &privacy_string);
2017 privacy = string2privacy(privacy_string);
2020 dbus_message_iter_next(&dict);
2023 DBG("method %d address %s netmask %s gateway %s prefix_length %d "
2025 method, address, netmask, gateway, prefix_length,
2029 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2030 case CONNMAN_IPCONFIG_METHOD_FIXED:
2033 case CONNMAN_IPCONFIG_METHOD_OFF:
2034 ipconfig->method = method;
2038 case CONNMAN_IPCONFIG_METHOD_AUTO:
2039 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
2042 ipconfig->method = method;
2044 ipconfig->ipv6_privacy_config = privacy;
2048 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2049 switch (ipconfig->type) {
2050 case CONNMAN_IPCONFIG_TYPE_IPV4:
2053 case CONNMAN_IPCONFIG_TYPE_IPV6:
2056 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2057 case CONNMAN_IPCONFIG_TYPE_ALL:
2062 if ((address && connman_inet_check_ipaddress(address)
2065 connman_inet_check_ipaddress(netmask)
2068 connman_inet_check_ipaddress(gateway)
2072 ipconfig->method = method;
2074 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
2075 connman_ipaddress_set_ipv4(ipconfig->address,
2076 address, netmask, gateway);
2078 return connman_ipaddress_set_ipv6(
2079 ipconfig->address, address,
2080 prefix_length, gateway);
2084 case CONNMAN_IPCONFIG_METHOD_DHCP:
2085 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
2088 ipconfig->method = method;
2095 void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
2096 DBusMessageIter *iter)
2098 struct connman_ipdevice *ipdevice;
2099 const char *method = "auto";
2101 connman_dbus_dict_append_basic(iter, "Method",
2102 DBUS_TYPE_STRING, &method);
2104 ipdevice = g_hash_table_lookup(ipdevice_hash,
2105 GINT_TO_POINTER(ipconfig->index));
2109 if (ipconfig->index >= 0) {
2110 char *ifname = connman_inet_ifname(ipconfig->index);
2112 connman_dbus_dict_append_basic(iter, "Interface",
2113 DBUS_TYPE_STRING, &ifname);
2118 if (ipdevice->address)
2119 connman_dbus_dict_append_basic(iter, "Address",
2120 DBUS_TYPE_STRING, &ipdevice->address);
2122 if (ipdevice->mtu > 0)
2123 connman_dbus_dict_append_basic(iter, "MTU",
2124 DBUS_TYPE_UINT16, &ipdevice->mtu);
2127 int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
2128 GKeyFile *keyfile, const char *identifier, const char *prefix)
2134 DBG("ipconfig %p identifier %s", ipconfig, identifier);
2136 key = g_strdup_printf("%smethod", prefix);
2137 method = g_key_file_get_string(keyfile, identifier, key, NULL);
2139 switch (ipconfig->type) {
2140 case CONNMAN_IPCONFIG_TYPE_IPV4:
2141 ipconfig->method = CONNMAN_IPCONFIG_METHOD_DHCP;
2143 case CONNMAN_IPCONFIG_TYPE_IPV6:
2144 ipconfig->method = CONNMAN_IPCONFIG_METHOD_AUTO;
2146 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2147 case CONNMAN_IPCONFIG_TYPE_ALL:
2148 ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
2152 ipconfig->method = __connman_ipconfig_string2method(method);
2154 if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_UNKNOWN)
2155 ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
2157 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
2161 if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO ||
2162 ipconfig->method == CONNMAN_IPCONFIG_METHOD_MANUAL) {
2165 pprefix = g_strdup_printf("%sprivacy", prefix);
2166 privacy = g_key_file_get_string(keyfile, identifier,
2168 ipconfig->ipv6_privacy_config = string2privacy(privacy);
2173 pprefix = g_strdup_printf("%sDHCP.LastPrefixes", prefix);
2174 ipconfig->last_dhcpv6_prefixes =
2175 g_key_file_get_string_list(keyfile, identifier, pprefix,
2177 if (ipconfig->last_dhcpv6_prefixes && length == 0) {
2178 g_free(ipconfig->last_dhcpv6_prefixes);
2179 ipconfig->last_dhcpv6_prefixes = NULL;
2187 switch (ipconfig->method) {
2188 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2189 case CONNMAN_IPCONFIG_METHOD_OFF:
2192 case CONNMAN_IPCONFIG_METHOD_FIXED:
2193 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2195 key = g_strdup_printf("%snetmask_prefixlen", prefix);
2196 ipconfig->address->prefixlen = g_key_file_get_integer(
2197 keyfile, identifier, key, NULL);
2200 key = g_strdup_printf("%slocal_address", prefix);
2201 g_free(ipconfig->address->local);
2202 ipconfig->address->local = g_key_file_get_string(
2203 keyfile, identifier, key, NULL);
2206 key = g_strdup_printf("%speer_address", prefix);
2207 g_free(ipconfig->address->peer);
2208 ipconfig->address->peer = g_key_file_get_string(
2209 keyfile, identifier, key, NULL);
2212 key = g_strdup_printf("%sbroadcast_address", prefix);
2213 g_free(ipconfig->address->broadcast);
2214 ipconfig->address->broadcast = g_key_file_get_string(
2215 keyfile, identifier, key, NULL);
2218 key = g_strdup_printf("%sgateway", prefix);
2219 g_free(ipconfig->address->gateway);
2220 ipconfig->address->gateway = g_key_file_get_string(
2221 keyfile, identifier, key, NULL);
2225 case CONNMAN_IPCONFIG_METHOD_AUTO:
2227 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
2231 * If the last used method for IPv4 was AUTO then we
2232 * try first DHCP. We will try also to use the last
2233 * used DHCP address, if exits.
2235 __connman_ipconfig_set_method(ipconfig,
2236 CONNMAN_IPCONFIG_METHOD_DHCP);
2239 case CONNMAN_IPCONFIG_METHOD_DHCP:
2241 key = g_strdup_printf("%sDHCP.LastAddress", prefix);
2242 str = g_key_file_get_string(keyfile, identifier, key, NULL);
2244 g_free(ipconfig->last_dhcp_address);
2245 ipconfig->last_dhcp_address = str;
2255 int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
2256 GKeyFile *keyfile, const char *identifier, const char *prefix)
2261 method = __connman_ipconfig_method2string(ipconfig->method);
2263 DBG("ipconfig %p identifier %s method %s", ipconfig, identifier,
2266 key = g_strdup_printf("%smethod", prefix);
2267 g_key_file_set_string(keyfile, identifier, key, method);
2271 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
2272 const char *privacy;
2273 privacy = privacy2string(ipconfig->ipv6_privacy_config);
2274 key = g_strdup_printf("%sprivacy", prefix);
2275 g_key_file_set_string(keyfile, identifier, key, privacy);
2278 key = g_strdup_printf("%sDHCP.LastAddress", prefix);
2279 if (ipconfig->last_dhcp_address &&
2280 strlen(ipconfig->last_dhcp_address) > 0)
2281 g_key_file_set_string(keyfile, identifier, key,
2282 ipconfig->last_dhcp_address);
2284 g_key_file_remove_key(keyfile, identifier, key, NULL);
2287 key = g_strdup_printf("%sDHCP.LastPrefixes", prefix);
2288 if (ipconfig->last_dhcpv6_prefixes &&
2289 ipconfig->last_dhcpv6_prefixes[0]) {
2291 g_strv_length(ipconfig->last_dhcpv6_prefixes);
2293 g_key_file_set_string_list(keyfile, identifier, key,
2294 (const gchar **)ipconfig->last_dhcpv6_prefixes,
2297 g_key_file_remove_key(keyfile, identifier, key, NULL);
2301 switch (ipconfig->method) {
2302 case CONNMAN_IPCONFIG_METHOD_FIXED:
2303 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2305 case CONNMAN_IPCONFIG_METHOD_DHCP:
2306 key = g_strdup_printf("%sDHCP.LastAddress", prefix);
2307 if (ipconfig->last_dhcp_address &&
2308 strlen(ipconfig->last_dhcp_address) > 0)
2309 g_key_file_set_string(keyfile, identifier, key,
2310 ipconfig->last_dhcp_address);
2312 g_key_file_remove_key(keyfile, identifier, key, NULL);
2315 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2316 case CONNMAN_IPCONFIG_METHOD_OFF:
2317 case CONNMAN_IPCONFIG_METHOD_AUTO:
2321 key = g_strdup_printf("%snetmask_prefixlen", prefix);
2322 if (ipconfig->address->prefixlen != 0)
2323 g_key_file_set_integer(keyfile, identifier,
2324 key, ipconfig->address->prefixlen);
2327 key = g_strdup_printf("%slocal_address", prefix);
2328 if (ipconfig->address->local)
2329 g_key_file_set_string(keyfile, identifier,
2330 key, ipconfig->address->local);
2333 key = g_strdup_printf("%speer_address", prefix);
2334 if (ipconfig->address->peer)
2335 g_key_file_set_string(keyfile, identifier,
2336 key, ipconfig->address->peer);
2339 key = g_strdup_printf("%sbroadcast_address", prefix);
2340 if (ipconfig->address->broadcast)
2341 g_key_file_set_string(keyfile, identifier,
2342 key, ipconfig->address->broadcast);
2345 key = g_strdup_printf("%sgateway", prefix);
2346 if (ipconfig->address->gateway)
2347 g_key_file_set_string(keyfile, identifier,
2348 key, ipconfig->address->gateway);
2350 g_key_file_remove_key(keyfile, identifier, key, NULL);
2356 int __connman_ipconfig_init(void)
2360 ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2361 NULL, free_ipdevice);
2363 is_ipv6_supported = connman_inet_is_ipv6_supported();
2368 void __connman_ipconfig_cleanup(void)
2372 g_hash_table_destroy(ipdevice_hash);
2373 ipdevice_hash = NULL;