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 struct ipconfig_store {
94 static GHashTable *ipdevice_hash = NULL;
95 static GList *ipconfig_list = NULL;
96 static bool is_ipv6_supported = false;
98 static void store_set_str(struct ipconfig_store *store,
99 const char *key, const char *val)
104 if (!val || strlen(val) == 0)
107 pk = g_strdup_printf("%s%s", store->prefix, key);
108 g_key_file_set_string(store->file, store->group, pk, val);
112 static char *store_get_str(struct ipconfig_store *store, const char *key)
116 pk = g_strdup_printf("%s%s", store->prefix, key);
117 val = g_key_file_get_string(store->file, store->group, pk, NULL);
123 static void store_set_strs(struct ipconfig_store *store,
124 const char *key, char **val)
132 len = g_strv_length(val);
136 pk = g_strdup_printf("%s%s", store->prefix, key);
137 g_key_file_set_string_list(store->file, store->group,
138 pk, (const gchar **)val, len);
142 static char **store_get_strs(struct ipconfig_store *store, const char *key)
147 pk = g_strdup_printf("%s%s", store->prefix, key);
148 val = g_key_file_get_string_list(store->file, store->group,
152 if (val && len == 0) {
160 static void store_set_int(struct ipconfig_store *store,
161 const char *key, int val)
168 pk = g_strdup_printf("%s%s", store->prefix, key);
169 g_key_file_set_integer(store->file, store->group, pk, val);
173 static int store_get_int(struct ipconfig_store *store, const char *key)
178 pk = g_strdup_printf("%s%s", store->prefix, key);
179 val = g_key_file_get_integer(store->file, store->group, pk, 0);
185 static void free_address_list(struct connman_ipdevice *ipdevice)
189 for (list = ipdevice->address_list; list; list = list->next) {
190 struct connman_ipaddress *ipaddress = list->data;
192 connman_ipaddress_free(ipaddress);
196 g_slist_free(ipdevice->address_list);
197 ipdevice->address_list = NULL;
200 static struct connman_ipaddress *find_ipaddress(struct connman_ipdevice *ipdevice,
201 unsigned char prefixlen, const char *local)
205 for (list = ipdevice->address_list; list; list = list->next) {
206 struct connman_ipaddress *ipaddress = list->data;
208 if (g_strcmp0(ipaddress->local, local) == 0 &&
209 ipaddress->prefixlen == prefixlen)
216 const char *__connman_ipconfig_type2string(enum connman_ipconfig_type type)
219 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
220 case CONNMAN_IPCONFIG_TYPE_ALL:
222 case CONNMAN_IPCONFIG_TYPE_IPV4:
224 case CONNMAN_IPCONFIG_TYPE_IPV6:
231 static const char *type2str(unsigned short type)
236 case ARPHRD_LOOPBACK:
249 static const char *scope2str(unsigned char scope)
261 static bool get_ipv6_state(gchar *ifname)
266 bool enabled = false;
269 path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
271 path = g_strdup_printf(
272 "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
277 f = fopen(path, "r");
282 if (fscanf(f, "%d", &disabled) > 0)
290 static void set_ipv6_state(gchar *ifname, bool enable)
296 path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
298 path = g_strdup_printf(
299 "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
304 f = fopen(path, "r+");
319 static int get_ipv6_privacy(gchar *ifname)
328 path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
334 f = fopen(path, "r");
341 if (fscanf(f, "%d", &value) <= 0)
349 /* Enable the IPv6 privacy extension for stateless address autoconfiguration.
350 * The privacy extension is described in RFC 3041 and RFC 4941
352 static void set_ipv6_privacy(gchar *ifname, int value)
360 path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
369 f = fopen(path, "r+");
376 fprintf(f, "%d", value);
380 static int get_rp_filter(void)
383 int value = -EINVAL, tmp;
385 f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r");
388 if (fscanf(f, "%d", &tmp) == 1)
396 static void set_rp_filter(int value)
400 f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r+");
405 fprintf(f, "%d", value);
410 int __connman_ipconfig_set_rp_filter()
414 value = get_rp_filter();
421 connman_info("rp_filter set to 2 (loose mode routing), "
422 "old value was %d", value);
427 void __connman_ipconfig_unset_rp_filter(int old_value)
429 set_rp_filter(old_value);
431 connman_info("rp_filter restored to %d", old_value);
434 bool __connman_ipconfig_ipv6_privacy_enabled(struct connman_ipconfig *ipconfig)
439 return ipconfig->ipv6_privacy_config == 0 ? FALSE : TRUE;
442 bool __connman_ipconfig_ipv6_is_enabled(struct connman_ipconfig *ipconfig)
444 struct connman_ipdevice *ipdevice;
451 ipdevice = g_hash_table_lookup(ipdevice_hash,
452 GINT_TO_POINTER(ipconfig->index));
456 ifname = connman_inet_ifname(ipconfig->index);
457 ret = get_ipv6_state(ifname);
463 static void free_ipdevice(gpointer data)
465 struct connman_ipdevice *ipdevice = data;
466 char *ifname = connman_inet_ifname(ipdevice->index);
468 connman_info("%s {remove} index %d", ifname, ipdevice->index);
470 if (ipdevice->config_ipv4) {
471 __connman_ipconfig_unref(ipdevice->config_ipv4);
472 ipdevice->config_ipv4 = NULL;
475 if (ipdevice->config_ipv6) {
476 __connman_ipconfig_unref(ipdevice->config_ipv6);
477 ipdevice->config_ipv6 = NULL;
480 free_address_list(ipdevice);
481 g_free(ipdevice->ipv4_gateway);
482 g_free(ipdevice->ipv6_gateway);
483 g_free(ipdevice->pac);
485 g_free(ipdevice->address);
488 set_ipv6_state(ifname, ipdevice->ipv6_enabled);
489 set_ipv6_privacy(ifname, ipdevice->ipv6_privacy);
496 static void update_stats(struct connman_ipdevice *ipdevice,
497 const char *ifname, struct rtnl_link_stats *stats)
499 struct connman_service *service;
501 if (stats->rx_packets == 0 && stats->tx_packets == 0)
504 connman_info("%s {RX} %u packets %u bytes", ifname,
505 stats->rx_packets, stats->rx_bytes);
506 connman_info("%s {TX} %u packets %u bytes", ifname,
507 stats->tx_packets, stats->tx_bytes);
509 if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
512 service = __connman_service_lookup_from_index(ipdevice->index);
514 DBG("service %p", service);
519 ipdevice->rx_packets = stats->rx_packets;
520 ipdevice->tx_packets = stats->tx_packets;
521 ipdevice->rx_bytes = stats->rx_bytes;
522 ipdevice->tx_bytes = stats->tx_bytes;
523 ipdevice->rx_errors = stats->rx_errors;
524 ipdevice->tx_errors = stats->tx_errors;
525 ipdevice->rx_dropped = stats->rx_dropped;
526 ipdevice->tx_dropped = stats->tx_dropped;
528 __connman_service_notify(service,
529 ipdevice->rx_packets, ipdevice->tx_packets,
530 ipdevice->rx_bytes, ipdevice->tx_bytes,
531 ipdevice->rx_errors, ipdevice->tx_errors,
532 ipdevice->rx_dropped, ipdevice->tx_dropped);
535 void __connman_ipconfig_newlink(int index, unsigned short type,
536 unsigned int flags, const char *address,
538 struct rtnl_link_stats *stats)
540 struct connman_ipdevice *ipdevice;
541 GList *list, *ipconfig_copy;
543 bool up = false, down = false;
544 bool lower_up = false, lower_down = false;
547 DBG("index %d", index);
549 if (type == ARPHRD_LOOPBACK)
552 ifname = connman_inet_ifname(index);
554 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
558 ipdevice = g_try_new0(struct connman_ipdevice, 1);
562 ipdevice->index = index;
563 ipdevice->type = type;
565 ipdevice->ipv6_enabled = get_ipv6_state(ifname);
566 ipdevice->ipv6_privacy = get_ipv6_privacy(ifname);
568 ipdevice->address = g_strdup(address);
570 g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
572 connman_info("%s {create} index %d type %d <%s>", ifname,
573 index, type, type2str(type));
578 update_stats(ipdevice, ifname, stats);
580 if (flags == ipdevice->flags)
583 if ((ipdevice->flags & IFF_UP) != (flags & IFF_UP)) {
590 if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) !=
591 (flags & (IFF_RUNNING | IFF_LOWER_UP))) {
592 if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
593 (IFF_RUNNING | IFF_LOWER_UP))
595 else if ((flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
599 ipdevice->flags = flags;
601 str = g_string_new(NULL);
606 g_string_append(str, "UP");
608 g_string_append(str, "DOWN");
610 if (flags & IFF_RUNNING)
611 g_string_append(str, ",RUNNING");
613 if (flags & IFF_LOWER_UP)
614 g_string_append(str, ",LOWER_UP");
616 connman_info("%s {update} flags %u <%s>", ifname, flags, str->str);
618 g_string_free(str, TRUE);
620 ipconfig_copy = g_list_copy(ipconfig_list);
622 for (list = g_list_first(ipconfig_copy); list;
623 list = g_list_next(list)) {
624 struct connman_ipconfig *ipconfig = list->data;
626 if (index != ipconfig->index)
632 if (up && ipconfig->ops->up)
633 ipconfig->ops->up(ipconfig, ifname);
634 if (lower_up && ipconfig->ops->lower_up)
635 ipconfig->ops->lower_up(ipconfig, ifname);
637 if (lower_down && ipconfig->ops->lower_down)
638 ipconfig->ops->lower_down(ipconfig, ifname);
639 if (down && ipconfig->ops->down)
640 ipconfig->ops->down(ipconfig, ifname);
643 g_list_free(ipconfig_copy);
649 void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats)
651 struct connman_ipdevice *ipdevice;
655 DBG("index %d", index);
657 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
661 ifname = connman_inet_ifname(index);
663 update_stats(ipdevice, ifname, stats);
665 for (list = g_list_first(ipconfig_list); list;
666 list = g_list_next(list)) {
667 struct connman_ipconfig *ipconfig = list->data;
669 if (index != ipconfig->index)
672 ipconfig->index = -1;
677 if (ipconfig->ops->lower_down)
678 ipconfig->ops->lower_down(ipconfig, ifname);
679 if (ipconfig->ops->down)
680 ipconfig->ops->down(ipconfig, ifname);
685 g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
688 static inline gint check_duplicate_address(gconstpointer a, gconstpointer b)
690 const struct connman_ipaddress *addr1 = a;
691 const struct connman_ipaddress *addr2 = b;
693 if (addr1->prefixlen != addr2->prefixlen)
694 return addr2->prefixlen - addr1->prefixlen;
696 return g_strcmp0(addr1->local, addr2->local);
699 int __connman_ipconfig_newaddr(int index, int family, const char *label,
700 unsigned char prefixlen, const char *address)
702 struct connman_ipdevice *ipdevice;
703 struct connman_ipaddress *ipaddress;
704 enum connman_ipconfig_type type;
708 DBG("index %d", index);
710 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
714 ipaddress = connman_ipaddress_alloc(family);
718 ipaddress->prefixlen = prefixlen;
719 ipaddress->local = g_strdup(address);
721 if (g_slist_find_custom(ipdevice->address_list, ipaddress,
722 check_duplicate_address)) {
723 connman_ipaddress_free(ipaddress);
727 if (family == AF_INET)
728 type = CONNMAN_IPCONFIG_TYPE_IPV4;
729 else if (family == AF_INET6)
730 type = CONNMAN_IPCONFIG_TYPE_IPV6;
734 ipdevice->address_list = g_slist_prepend(ipdevice->address_list,
737 ifname = connman_inet_ifname(index);
738 connman_info("%s {add} address %s/%u label %s family %d",
739 ifname, address, prefixlen, label, family);
741 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
742 __connman_ippool_newaddr(index, address, prefixlen);
744 if (ipdevice->config_ipv4 && family == AF_INET)
745 connman_ipaddress_copy_address(ipdevice->config_ipv4->system,
748 else if (ipdevice->config_ipv6 && family == AF_INET6)
749 connman_ipaddress_copy_address(ipdevice->config_ipv6->system,
754 if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
757 for (list = g_list_first(ipconfig_list); list;
758 list = g_list_next(list)) {
759 struct connman_ipconfig *ipconfig = list->data;
761 if (index != ipconfig->index)
764 if (type != ipconfig->type)
770 if (ipconfig->ops->ip_bound)
771 ipconfig->ops->ip_bound(ipconfig, ifname);
779 void __connman_ipconfig_deladdr(int index, int family, const char *label,
780 unsigned char prefixlen, const char *address)
782 struct connman_ipdevice *ipdevice;
783 struct connman_ipaddress *ipaddress;
784 enum connman_ipconfig_type type;
788 DBG("index %d", index);
790 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
794 ipaddress = find_ipaddress(ipdevice, prefixlen, address);
798 if (family == AF_INET)
799 type = CONNMAN_IPCONFIG_TYPE_IPV4;
800 else if (family == AF_INET6)
801 type = CONNMAN_IPCONFIG_TYPE_IPV6;
805 ipdevice->address_list = g_slist_remove(ipdevice->address_list,
808 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
809 __connman_ippool_deladdr(index, address, prefixlen);
811 connman_ipaddress_clear(ipaddress);
814 ifname = connman_inet_ifname(index);
815 connman_info("%s {del} address %s/%u label %s", ifname,
816 address, prefixlen, label);
818 if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
821 if (g_slist_length(ipdevice->address_list) > 0)
824 for (list = g_list_first(ipconfig_list); list;
825 list = g_list_next(list)) {
826 struct connman_ipconfig *ipconfig = list->data;
828 if (index != ipconfig->index)
831 if (type != ipconfig->type)
837 if (ipconfig->ops->ip_release)
838 ipconfig->ops->ip_release(ipconfig, ifname);
845 void __connman_ipconfig_newroute(int index, int family, unsigned char scope,
846 const char *dst, const char *gateway)
848 struct connman_ipdevice *ipdevice;
851 DBG("index %d", index);
853 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
857 ifname = connman_inet_ifname(index);
859 if (scope == 0 && (g_strcmp0(dst, "0.0.0.0") == 0 ||
860 g_strcmp0(dst, "::") == 0)) {
862 enum connman_ipconfig_type type;
864 if (family == AF_INET6) {
865 type = CONNMAN_IPCONFIG_TYPE_IPV6;
866 g_free(ipdevice->ipv6_gateway);
867 ipdevice->ipv6_gateway = g_strdup(gateway);
869 if (ipdevice->config_ipv6 &&
870 ipdevice->config_ipv6->system) {
871 g_free(ipdevice->config_ipv6->system->gateway);
872 ipdevice->config_ipv6->system->gateway =
875 } else if (family == AF_INET) {
876 type = CONNMAN_IPCONFIG_TYPE_IPV4;
877 g_free(ipdevice->ipv4_gateway);
878 ipdevice->ipv4_gateway = g_strdup(gateway);
880 if (ipdevice->config_ipv4 &&
881 ipdevice->config_ipv4->system) {
882 g_free(ipdevice->config_ipv4->system->gateway);
883 ipdevice->config_ipv4->system->gateway =
889 for (config_list = g_list_first(ipconfig_list); config_list;
890 config_list = g_list_next(config_list)) {
891 struct connman_ipconfig *ipconfig = config_list->data;
893 if (index != ipconfig->index)
896 if (type != ipconfig->type)
902 if (ipconfig->ops->route_set)
903 ipconfig->ops->route_set(ipconfig, ifname);
907 connman_info("%s {add} route %s gw %s scope %u <%s>",
908 ifname, dst, gateway, scope, scope2str(scope));
914 void __connman_ipconfig_delroute(int index, int family, unsigned char scope,
915 const char *dst, const char *gateway)
917 struct connman_ipdevice *ipdevice;
920 DBG("index %d", index);
922 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
926 ifname = connman_inet_ifname(index);
928 if (scope == 0 && (g_strcmp0(dst, "0.0.0.0") == 0 ||
929 g_strcmp0(dst, "::") == 0)) {
931 enum connman_ipconfig_type type;
933 if (family == AF_INET6) {
934 type = CONNMAN_IPCONFIG_TYPE_IPV6;
935 g_free(ipdevice->ipv6_gateway);
936 ipdevice->ipv6_gateway = NULL;
938 if (ipdevice->config_ipv6 &&
939 ipdevice->config_ipv6->system) {
940 g_free(ipdevice->config_ipv6->system->gateway);
941 ipdevice->config_ipv6->system->gateway = NULL;
943 } else if (family == AF_INET) {
944 type = CONNMAN_IPCONFIG_TYPE_IPV4;
945 g_free(ipdevice->ipv4_gateway);
946 ipdevice->ipv4_gateway = NULL;
948 if (ipdevice->config_ipv4 &&
949 ipdevice->config_ipv4->system) {
950 g_free(ipdevice->config_ipv4->system->gateway);
951 ipdevice->config_ipv4->system->gateway = NULL;
956 for (config_list = g_list_first(ipconfig_list); config_list;
957 config_list = g_list_next(config_list)) {
958 struct connman_ipconfig *ipconfig = config_list->data;
960 if (index != ipconfig->index)
963 if (type != ipconfig->type)
969 if (ipconfig->ops->route_unset)
970 ipconfig->ops->route_unset(ipconfig, ifname);
974 connman_info("%s {del} route %s gw %s scope %u <%s>",
975 ifname, dst, gateway, scope, scope2str(scope));
981 void __connman_ipconfig_foreach(void (*function) (int index, void *user_data),
986 keys = g_hash_table_get_keys(ipdevice_hash);
990 for (list = g_list_first(keys); list; list = g_list_next(list)) {
991 int index = GPOINTER_TO_INT(list->data);
993 function(index, user_data);
999 enum connman_ipconfig_type __connman_ipconfig_get_config_type(
1000 struct connman_ipconfig *ipconfig)
1002 return ipconfig ? ipconfig->type : CONNMAN_IPCONFIG_TYPE_UNKNOWN;
1005 unsigned short __connman_ipconfig_get_type_from_index(int index)
1007 struct connman_ipdevice *ipdevice;
1009 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1013 return ipdevice->type;
1016 unsigned int __connman_ipconfig_get_flags_from_index(int index)
1018 struct connman_ipdevice *ipdevice;
1020 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1024 return ipdevice->flags;
1027 const char *__connman_ipconfig_get_gateway_from_index(int index,
1028 enum connman_ipconfig_type type)
1030 struct connman_ipdevice *ipdevice;
1032 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1036 if (type != CONNMAN_IPCONFIG_TYPE_IPV6) {
1037 if (ipdevice->ipv4_gateway)
1038 return ipdevice->ipv4_gateway;
1040 if (ipdevice->config_ipv4 &&
1041 ipdevice->config_ipv4->address)
1042 return ipdevice->config_ipv4->address->gateway;
1045 if (type != CONNMAN_IPCONFIG_TYPE_IPV4) {
1046 if (ipdevice->ipv6_gateway)
1047 return ipdevice->ipv6_gateway;
1049 if (ipdevice->config_ipv6 &&
1050 ipdevice->config_ipv6->address)
1051 return ipdevice->config_ipv6->address->gateway;
1057 void __connman_ipconfig_set_index(struct connman_ipconfig *ipconfig, int index)
1059 ipconfig->index = index;
1062 const char *__connman_ipconfig_get_local(struct connman_ipconfig *ipconfig)
1064 if (!ipconfig->address)
1067 return ipconfig->address->local;
1070 void __connman_ipconfig_set_local(struct connman_ipconfig *ipconfig,
1071 const char *address)
1073 if (!ipconfig->address)
1076 g_free(ipconfig->address->local);
1077 ipconfig->address->local = g_strdup(address);
1080 const char *__connman_ipconfig_get_peer(struct connman_ipconfig *ipconfig)
1082 if (!ipconfig->address)
1085 return ipconfig->address->peer;
1088 void __connman_ipconfig_set_peer(struct connman_ipconfig *ipconfig,
1089 const char *address)
1091 if (!ipconfig->address)
1094 g_free(ipconfig->address->peer);
1095 ipconfig->address->peer = g_strdup(address);
1098 const char *__connman_ipconfig_get_broadcast(struct connman_ipconfig *ipconfig)
1100 if (!ipconfig->address)
1103 return ipconfig->address->broadcast;
1106 void __connman_ipconfig_set_broadcast(struct connman_ipconfig *ipconfig,
1107 const char *broadcast)
1109 if (!ipconfig->address)
1112 g_free(ipconfig->address->broadcast);
1113 ipconfig->address->broadcast = g_strdup(broadcast);
1116 const char *__connman_ipconfig_get_gateway(struct connman_ipconfig *ipconfig)
1118 if (!ipconfig->address)
1121 return ipconfig->address->gateway;
1124 void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig,
1125 const char *gateway)
1129 if (!ipconfig->address)
1131 g_free(ipconfig->address->gateway);
1132 ipconfig->address->gateway = g_strdup(gateway);
1135 int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig)
1137 struct connman_service *service;
1141 if (!ipconfig->address)
1144 service = __connman_service_lookup_from_index(ipconfig->index);
1148 DBG("type %d gw %s peer %s", ipconfig->type,
1149 ipconfig->address->gateway, ipconfig->address->peer);
1151 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6 ||
1152 ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1153 return __connman_connection_gateway_add(service,
1154 ipconfig->address->gateway,
1156 ipconfig->address->peer);
1161 void __connman_ipconfig_gateway_remove(struct connman_ipconfig *ipconfig)
1163 struct connman_service *service;
1167 service = __connman_service_lookup_from_index(ipconfig->index);
1169 __connman_connection_gateway_remove(service, ipconfig->type);
1172 unsigned char __connman_ipconfig_get_prefixlen(struct connman_ipconfig *ipconfig)
1174 if (!ipconfig->address)
1177 return ipconfig->address->prefixlen;
1180 void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig,
1181 unsigned char prefixlen)
1183 if (!ipconfig->address)
1186 ipconfig->address->prefixlen = prefixlen;
1189 static struct connman_ipconfig *create_ipv6config(int index)
1191 struct connman_ipconfig *ipv6config;
1192 struct connman_ipdevice *ipdevice;
1194 ipv6config = g_try_new0(struct connman_ipconfig, 1);
1198 ipv6config->refcount = 1;
1200 ipv6config->index = index;
1201 ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6;
1203 if (!is_ipv6_supported)
1204 ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF;
1206 ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO;
1208 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
1210 ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy;
1212 ipv6config->address = connman_ipaddress_alloc(AF_INET6);
1213 if (!ipv6config->address) {
1218 ipv6config->system = connman_ipaddress_alloc(AF_INET6);
1220 DBG("ipconfig %p index %d method %s", ipv6config, index,
1221 __connman_ipconfig_method2string(ipv6config->method));
1227 * connman_ipconfig_create:
1229 * Allocate a new ipconfig structure.
1231 * Returns: a newly-allocated #connman_ipconfig structure
1233 struct connman_ipconfig *__connman_ipconfig_create(int index,
1234 enum connman_ipconfig_type type)
1236 struct connman_ipconfig *ipconfig;
1238 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1239 return create_ipv6config(index);
1241 ipconfig = g_try_new0(struct connman_ipconfig, 1);
1245 ipconfig->refcount = 1;
1247 ipconfig->index = index;
1248 ipconfig->type = CONNMAN_IPCONFIG_TYPE_IPV4;
1250 ipconfig->address = connman_ipaddress_alloc(AF_INET);
1251 if (!ipconfig->address) {
1256 ipconfig->system = connman_ipaddress_alloc(AF_INET);
1258 DBG("ipconfig %p index %d", ipconfig, index);
1265 * connman_ipconfig_ref:
1266 * @ipconfig: ipconfig structure
1268 * Increase reference counter of ipconfig
1270 struct connman_ipconfig *
1271 __connman_ipconfig_ref_debug(struct connman_ipconfig *ipconfig,
1272 const char *file, int line, const char *caller)
1274 DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount + 1,
1275 file, line, caller);
1277 __sync_fetch_and_add(&ipconfig->refcount, 1);
1283 * connman_ipconfig_unref:
1284 * @ipconfig: ipconfig structure
1286 * Decrease reference counter of ipconfig
1288 void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig,
1289 const char *file, int line, const char *caller)
1294 DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount - 1,
1295 file, line, caller);
1297 if (__sync_fetch_and_sub(&ipconfig->refcount, 1) != 1)
1300 if (__connman_ipconfig_disable(ipconfig) < 0)
1301 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1303 __connman_ipconfig_set_ops(ipconfig, NULL);
1305 connman_ipaddress_free(ipconfig->system);
1306 connman_ipaddress_free(ipconfig->address);
1307 g_free(ipconfig->last_dhcp_address);
1308 g_strfreev(ipconfig->last_dhcpv6_prefixes);
1313 * connman_ipconfig_get_data:
1314 * @ipconfig: ipconfig structure
1316 * Get private data pointer
1318 void *__connman_ipconfig_get_data(struct connman_ipconfig *ipconfig)
1323 return ipconfig->ops_data;
1327 * connman_ipconfig_set_data:
1328 * @ipconfig: ipconfig structure
1329 * @data: data pointer
1331 * Set private data pointer
1333 void __connman_ipconfig_set_data(struct connman_ipconfig *ipconfig, void *data)
1335 ipconfig->ops_data = data;
1339 * connman_ipconfig_get_index:
1340 * @ipconfig: ipconfig structure
1342 * Get interface index
1344 int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
1349 return ipconfig->index;
1353 * connman_ipconfig_set_ops:
1354 * @ipconfig: ipconfig structure
1355 * @ops: operation callbacks
1357 * Set the operation callbacks
1359 void __connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
1360 const struct connman_ipconfig_ops *ops)
1362 ipconfig->ops = ops;
1366 * connman_ipconfig_set_method:
1367 * @ipconfig: ipconfig structure
1368 * @method: configuration method
1370 * Set the configuration method
1372 int __connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
1373 enum connman_ipconfig_method method)
1375 ipconfig->method = method;
1380 enum connman_ipconfig_method __connman_ipconfig_get_method(
1381 struct connman_ipconfig *ipconfig)
1384 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1386 return ipconfig->method;
1389 int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig)
1391 switch (ipconfig->method) {
1392 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1393 case CONNMAN_IPCONFIG_METHOD_OFF:
1395 case CONNMAN_IPCONFIG_METHOD_AUTO:
1396 case CONNMAN_IPCONFIG_METHOD_FIXED:
1397 case CONNMAN_IPCONFIG_METHOD_DHCP:
1398 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1399 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1400 return connman_inet_set_address(ipconfig->index,
1402 else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
1403 return connman_inet_set_ipv6_address(
1404 ipconfig->index, ipconfig->address);
1410 int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig)
1417 switch (ipconfig->method) {
1418 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1419 case CONNMAN_IPCONFIG_METHOD_OFF:
1421 case CONNMAN_IPCONFIG_METHOD_AUTO:
1422 case CONNMAN_IPCONFIG_METHOD_DHCP:
1423 err = __connman_ipconfig_address_unset(ipconfig);
1424 connman_ipaddress_clear(ipconfig->address);
1427 case CONNMAN_IPCONFIG_METHOD_FIXED:
1428 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1429 return __connman_ipconfig_address_unset(ipconfig);
1435 int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig)
1442 switch (ipconfig->method) {
1443 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1444 case CONNMAN_IPCONFIG_METHOD_OFF:
1446 case CONNMAN_IPCONFIG_METHOD_AUTO:
1447 case CONNMAN_IPCONFIG_METHOD_FIXED:
1448 case CONNMAN_IPCONFIG_METHOD_DHCP:
1449 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1450 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
1451 err = connman_inet_clear_address(ipconfig->index,
1453 else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
1454 err = connman_inet_clear_ipv6_address(
1456 ipconfig->address->local,
1457 ipconfig->address->prefixlen);
1467 int __connman_ipconfig_set_proxy_autoconfig(struct connman_ipconfig *ipconfig,
1470 struct connman_ipdevice *ipdevice;
1472 if (!ipconfig || ipconfig->index < 0)
1475 ipdevice = g_hash_table_lookup(ipdevice_hash,
1476 GINT_TO_POINTER(ipconfig->index));
1480 g_free(ipdevice->pac);
1481 ipdevice->pac = g_strdup(url);
1486 const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipconfig)
1488 struct connman_ipdevice *ipdevice;
1490 if (!ipconfig || ipconfig->index < 0)
1493 ipdevice = g_hash_table_lookup(ipdevice_hash,
1494 GINT_TO_POINTER(ipconfig->index));
1498 return ipdevice->pac;
1501 void __connman_ipconfig_set_dhcp_address(struct connman_ipconfig *ipconfig,
1502 const char *address)
1507 g_free(ipconfig->last_dhcp_address);
1508 ipconfig->last_dhcp_address = g_strdup(address);
1511 char *__connman_ipconfig_get_dhcp_address(struct connman_ipconfig *ipconfig)
1516 return ipconfig->last_dhcp_address;
1519 void __connman_ipconfig_set_dhcpv6_prefixes(struct connman_ipconfig *ipconfig,
1525 g_strfreev(ipconfig->last_dhcpv6_prefixes);
1526 ipconfig->last_dhcpv6_prefixes = prefixes;
1529 char **__connman_ipconfig_get_dhcpv6_prefixes(struct connman_ipconfig *ipconfig)
1534 return ipconfig->last_dhcpv6_prefixes;
1537 static void disable_ipv6(struct connman_ipconfig *ipconfig)
1539 struct connman_ipdevice *ipdevice;
1544 ipdevice = g_hash_table_lookup(ipdevice_hash,
1545 GINT_TO_POINTER(ipconfig->index));
1549 ifname = connman_inet_ifname(ipconfig->index);
1551 set_ipv6_state(ifname, false);
1556 static void enable_ipv6(struct connman_ipconfig *ipconfig)
1558 struct connman_ipdevice *ipdevice;
1563 ipdevice = g_hash_table_lookup(ipdevice_hash,
1564 GINT_TO_POINTER(ipconfig->index));
1568 ifname = connman_inet_ifname(ipconfig->index);
1570 if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO)
1571 set_ipv6_privacy(ifname, ipconfig->ipv6_privacy_config);
1573 set_ipv6_state(ifname, true);
1578 void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig)
1580 if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1583 enable_ipv6(ipconfig);
1586 void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig)
1588 if (!ipconfig || ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1591 disable_ipv6(ipconfig);
1594 bool __connman_ipconfig_is_usable(struct connman_ipconfig *ipconfig)
1599 switch (ipconfig->method) {
1600 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1601 case CONNMAN_IPCONFIG_METHOD_OFF:
1603 case CONNMAN_IPCONFIG_METHOD_AUTO:
1604 case CONNMAN_IPCONFIG_METHOD_FIXED:
1605 case CONNMAN_IPCONFIG_METHOD_DHCP:
1606 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1613 int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
1615 struct connman_ipdevice *ipdevice;
1616 bool up = false, down = false;
1617 bool lower_up = false, lower_down = false;
1618 enum connman_ipconfig_type type;
1621 DBG("ipconfig %p", ipconfig);
1623 if (!ipconfig || ipconfig->index < 0)
1626 ipdevice = g_hash_table_lookup(ipdevice_hash,
1627 GINT_TO_POINTER(ipconfig->index));
1631 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4) {
1632 if (ipdevice->config_ipv4 == ipconfig)
1634 type = CONNMAN_IPCONFIG_TYPE_IPV4;
1635 } else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
1636 if (ipdevice->config_ipv6 == ipconfig)
1638 type = CONNMAN_IPCONFIG_TYPE_IPV6;
1642 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
1643 ipdevice->config_ipv4) {
1644 ipconfig_list = g_list_remove(ipconfig_list,
1645 ipdevice->config_ipv4);
1647 connman_ipaddress_clear(ipdevice->config_ipv4->system);
1649 __connman_ipconfig_unref(ipdevice->config_ipv4);
1652 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
1653 ipdevice->config_ipv6) {
1654 ipconfig_list = g_list_remove(ipconfig_list,
1655 ipdevice->config_ipv6);
1657 connman_ipaddress_clear(ipdevice->config_ipv6->system);
1659 __connman_ipconfig_unref(ipdevice->config_ipv6);
1662 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1663 ipdevice->config_ipv4 = __connman_ipconfig_ref(ipconfig);
1664 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
1665 ipdevice->config_ipv6 = __connman_ipconfig_ref(ipconfig);
1667 enable_ipv6(ipdevice->config_ipv6);
1669 ipconfig_list = g_list_append(ipconfig_list, ipconfig);
1671 if (ipdevice->flags & IFF_UP)
1676 if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
1677 (IFF_RUNNING | IFF_LOWER_UP))
1679 else if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) == 0)
1682 ifname = connman_inet_ifname(ipconfig->index);
1684 if (up && ipconfig->ops->up)
1685 ipconfig->ops->up(ipconfig, ifname);
1686 if (lower_up && ipconfig->ops->lower_up)
1687 ipconfig->ops->lower_up(ipconfig, ifname);
1689 if (lower_down && ipconfig->ops->lower_down)
1690 ipconfig->ops->lower_down(ipconfig, ifname);
1691 if (down && ipconfig->ops->down)
1692 ipconfig->ops->down(ipconfig, ifname);
1699 int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
1701 struct connman_ipdevice *ipdevice;
1703 DBG("ipconfig %p", ipconfig);
1705 if (!ipconfig || ipconfig->index < 0)
1708 ipdevice = g_hash_table_lookup(ipdevice_hash,
1709 GINT_TO_POINTER(ipconfig->index));
1713 if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
1716 if (ipdevice->config_ipv4 == ipconfig) {
1717 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1719 connman_ipaddress_clear(ipdevice->config_ipv4->system);
1720 __connman_ipconfig_unref(ipdevice->config_ipv4);
1721 ipdevice->config_ipv4 = NULL;
1725 if (ipdevice->config_ipv6 == ipconfig) {
1726 ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
1728 connman_ipaddress_clear(ipdevice->config_ipv6->system);
1729 __connman_ipconfig_unref(ipdevice->config_ipv6);
1730 ipdevice->config_ipv6 = NULL;
1737 const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method)
1740 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1742 case CONNMAN_IPCONFIG_METHOD_OFF:
1744 case CONNMAN_IPCONFIG_METHOD_FIXED:
1746 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1748 case CONNMAN_IPCONFIG_METHOD_DHCP:
1750 case CONNMAN_IPCONFIG_METHOD_AUTO:
1757 enum connman_ipconfig_method __connman_ipconfig_string2method(const char *method)
1759 if (g_strcmp0(method, "off") == 0)
1760 return CONNMAN_IPCONFIG_METHOD_OFF;
1761 else if (g_strcmp0(method, "fixed") == 0)
1762 return CONNMAN_IPCONFIG_METHOD_FIXED;
1763 else if (g_strcmp0(method, "manual") == 0)
1764 return CONNMAN_IPCONFIG_METHOD_MANUAL;
1765 else if (g_strcmp0(method, "dhcp") == 0)
1766 return CONNMAN_IPCONFIG_METHOD_DHCP;
1767 else if (g_strcmp0(method, "auto") == 0)
1768 return CONNMAN_IPCONFIG_METHOD_AUTO;
1770 return CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1773 static const char *privacy2string(int privacy)
1777 else if (privacy == 1)
1783 static int string2privacy(const char *privacy)
1785 if (g_strcmp0(privacy, "disabled") == 0)
1787 else if (g_strcmp0(privacy, "enabled") == 0)
1789 else if (g_strcmp0(privacy, "preferred") == 0)
1791 else if (g_strcmp0(privacy, "prefered") == 0)
1797 int __connman_ipconfig_ipv6_reset_privacy(struct connman_ipconfig *ipconfig)
1799 struct connman_ipdevice *ipdevice;
1805 ipdevice = g_hash_table_lookup(ipdevice_hash,
1806 GINT_TO_POINTER(ipconfig->index));
1810 err = __connman_ipconfig_ipv6_set_privacy(ipconfig, privacy2string(
1811 ipdevice->ipv6_privacy));
1816 int __connman_ipconfig_ipv6_set_privacy(struct connman_ipconfig *ipconfig,
1824 privacy = string2privacy(value);
1826 ipconfig->ipv6_privacy_config = privacy;
1828 enable_ipv6(ipconfig);
1833 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
1834 DBusMessageIter *iter)
1836 struct connman_ipaddress *append_addr = NULL;
1839 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
1842 str = __connman_ipconfig_method2string(ipconfig->method);
1846 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1848 switch (ipconfig->method) {
1849 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1850 case CONNMAN_IPCONFIG_METHOD_OFF:
1853 case CONNMAN_IPCONFIG_METHOD_FIXED:
1854 append_addr = ipconfig->address;
1857 case CONNMAN_IPCONFIG_METHOD_AUTO:
1858 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1859 case CONNMAN_IPCONFIG_METHOD_DHCP:
1860 append_addr = ipconfig->system;
1867 if (append_addr->local) {
1869 struct in_addr netmask;
1872 connman_dbus_dict_append_basic(iter, "Address",
1873 DBUS_TYPE_STRING, &append_addr->local);
1875 addr = 0xffffffff << (32 - append_addr->prefixlen);
1876 netmask.s_addr = htonl(addr);
1877 mask = inet_ntoa(netmask);
1878 connman_dbus_dict_append_basic(iter, "Netmask",
1879 DBUS_TYPE_STRING, &mask);
1882 if (append_addr->gateway)
1883 connman_dbus_dict_append_basic(iter, "Gateway",
1884 DBUS_TYPE_STRING, &append_addr->gateway);
1887 void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
1888 DBusMessageIter *iter,
1889 struct connman_ipconfig *ipconfig_ipv4)
1891 struct connman_ipaddress *append_addr = NULL;
1892 const char *str, *privacy;
1894 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
1897 str = __connman_ipconfig_method2string(ipconfig->method);
1901 if (ipconfig_ipv4 &&
1902 ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1903 if (__connman_6to4_check(ipconfig_ipv4) == 1)
1907 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1909 switch (ipconfig->method) {
1910 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1911 case CONNMAN_IPCONFIG_METHOD_OFF:
1914 case CONNMAN_IPCONFIG_METHOD_FIXED:
1915 append_addr = ipconfig->address;
1918 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1919 case CONNMAN_IPCONFIG_METHOD_DHCP:
1920 case CONNMAN_IPCONFIG_METHOD_AUTO:
1921 append_addr = ipconfig->system;
1928 if (append_addr->local) {
1929 connman_dbus_dict_append_basic(iter, "Address",
1930 DBUS_TYPE_STRING, &append_addr->local);
1931 connman_dbus_dict_append_basic(iter, "PrefixLength",
1933 &append_addr->prefixlen);
1936 if (append_addr->gateway)
1937 connman_dbus_dict_append_basic(iter, "Gateway",
1938 DBUS_TYPE_STRING, &append_addr->gateway);
1940 privacy = privacy2string(ipconfig->ipv6_privacy_config);
1941 connman_dbus_dict_append_basic(iter, "Privacy",
1942 DBUS_TYPE_STRING, &privacy);
1945 void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig,
1946 DBusMessageIter *iter)
1948 const char *str, *privacy;
1950 str = __connman_ipconfig_method2string(ipconfig->method);
1954 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1956 switch (ipconfig->method) {
1957 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1958 case CONNMAN_IPCONFIG_METHOD_OFF:
1959 case CONNMAN_IPCONFIG_METHOD_DHCP:
1961 case CONNMAN_IPCONFIG_METHOD_FIXED:
1962 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1963 case CONNMAN_IPCONFIG_METHOD_AUTO:
1967 if (!ipconfig->address)
1970 if (ipconfig->address->local) {
1971 connman_dbus_dict_append_basic(iter, "Address",
1972 DBUS_TYPE_STRING, &ipconfig->address->local);
1973 connman_dbus_dict_append_basic(iter, "PrefixLength",
1975 &ipconfig->address->prefixlen);
1978 if (ipconfig->address->gateway)
1979 connman_dbus_dict_append_basic(iter, "Gateway",
1980 DBUS_TYPE_STRING, &ipconfig->address->gateway);
1982 privacy = privacy2string(ipconfig->ipv6_privacy_config);
1983 connman_dbus_dict_append_basic(iter, "Privacy",
1984 DBUS_TYPE_STRING, &privacy);
1987 void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig,
1988 DBusMessageIter *iter)
1992 str = __connman_ipconfig_method2string(ipconfig->method);
1996 connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
1998 switch (ipconfig->method) {
1999 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2000 case CONNMAN_IPCONFIG_METHOD_OFF:
2001 case CONNMAN_IPCONFIG_METHOD_DHCP:
2002 case CONNMAN_IPCONFIG_METHOD_AUTO:
2004 case CONNMAN_IPCONFIG_METHOD_FIXED:
2005 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2009 if (!ipconfig->address)
2012 if (ipconfig->address->local) {
2014 struct in_addr netmask;
2017 connman_dbus_dict_append_basic(iter, "Address",
2018 DBUS_TYPE_STRING, &ipconfig->address->local);
2020 addr = 0xffffffff << (32 - ipconfig->address->prefixlen);
2021 netmask.s_addr = htonl(addr);
2022 mask = inet_ntoa(netmask);
2023 connman_dbus_dict_append_basic(iter, "Netmask",
2024 DBUS_TYPE_STRING, &mask);
2027 if (ipconfig->address->gateway)
2028 connman_dbus_dict_append_basic(iter, "Gateway",
2029 DBUS_TYPE_STRING, &ipconfig->address->gateway);
2032 int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
2033 DBusMessageIter *array)
2035 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
2036 const char *address = NULL, *netmask = NULL, *gateway = NULL,
2037 *privacy_string = NULL;
2038 int prefix_length = 0, privacy = 0;
2039 DBusMessageIter dict;
2042 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
2045 dbus_message_iter_recurse(array, &dict);
2047 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2048 DBusMessageIter entry, value;
2052 dbus_message_iter_recurse(&dict, &entry);
2054 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2057 dbus_message_iter_get_basic(&entry, &key);
2058 dbus_message_iter_next(&entry);
2060 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2063 dbus_message_iter_recurse(&entry, &value);
2065 type = dbus_message_iter_get_arg_type(&value);
2067 if (g_str_equal(key, "Method")) {
2070 if (type != DBUS_TYPE_STRING)
2073 dbus_message_iter_get_basic(&value, &str);
2074 method = __connman_ipconfig_string2method(str);
2075 } else if (g_str_equal(key, "Address")) {
2076 if (type != DBUS_TYPE_STRING)
2079 dbus_message_iter_get_basic(&value, &address);
2080 } else if (g_str_equal(key, "PrefixLength")) {
2081 if (type != DBUS_TYPE_BYTE)
2084 dbus_message_iter_get_basic(&value, &prefix_length);
2086 if (prefix_length < 0 || prefix_length > 128)
2088 } else if (g_str_equal(key, "Netmask")) {
2089 if (type != DBUS_TYPE_STRING)
2092 dbus_message_iter_get_basic(&value, &netmask);
2093 } else if (g_str_equal(key, "Gateway")) {
2094 if (type != DBUS_TYPE_STRING)
2097 dbus_message_iter_get_basic(&value, &gateway);
2098 } else if (g_str_equal(key, "Privacy")) {
2099 if (type != DBUS_TYPE_STRING)
2102 dbus_message_iter_get_basic(&value, &privacy_string);
2103 privacy = string2privacy(privacy_string);
2106 dbus_message_iter_next(&dict);
2109 DBG("method %d address %s netmask %s gateway %s prefix_length %d "
2111 method, address, netmask, gateway, prefix_length,
2115 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2116 case CONNMAN_IPCONFIG_METHOD_FIXED:
2119 case CONNMAN_IPCONFIG_METHOD_OFF:
2120 ipconfig->method = method;
2124 case CONNMAN_IPCONFIG_METHOD_AUTO:
2125 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
2128 ipconfig->method = method;
2130 ipconfig->ipv6_privacy_config = privacy;
2134 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2135 switch (ipconfig->type) {
2136 case CONNMAN_IPCONFIG_TYPE_IPV4:
2139 case CONNMAN_IPCONFIG_TYPE_IPV6:
2142 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2143 case CONNMAN_IPCONFIG_TYPE_ALL:
2148 if ((address && connman_inet_check_ipaddress(address)
2151 connman_inet_check_ipaddress(netmask)
2154 connman_inet_check_ipaddress(gateway)
2158 ipconfig->method = method;
2160 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
2161 connman_ipaddress_set_ipv4(ipconfig->address,
2162 address, netmask, gateway);
2164 return connman_ipaddress_set_ipv6(
2165 ipconfig->address, address,
2166 prefix_length, gateway);
2170 case CONNMAN_IPCONFIG_METHOD_DHCP:
2171 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
2174 ipconfig->method = method;
2181 void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
2182 DBusMessageIter *iter)
2184 struct connman_ipdevice *ipdevice;
2185 const char *method = "auto";
2187 connman_dbus_dict_append_basic(iter, "Method",
2188 DBUS_TYPE_STRING, &method);
2190 ipdevice = g_hash_table_lookup(ipdevice_hash,
2191 GINT_TO_POINTER(ipconfig->index));
2195 if (ipconfig->index >= 0) {
2196 char *ifname = connman_inet_ifname(ipconfig->index);
2198 connman_dbus_dict_append_basic(iter, "Interface",
2199 DBUS_TYPE_STRING, &ifname);
2204 if (ipdevice->address)
2205 connman_dbus_dict_append_basic(iter, "Address",
2206 DBUS_TYPE_STRING, &ipdevice->address);
2208 if (ipdevice->mtu > 0)
2209 connman_dbus_dict_append_basic(iter, "MTU",
2210 DBUS_TYPE_UINT16, &ipdevice->mtu);
2213 void __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
2214 GKeyFile *keyfile, const char *identifier, const char *prefix)
2218 struct ipconfig_store is = { .file = keyfile,
2219 .group = identifier,
2222 DBG("ipconfig %p identifier %s", ipconfig, identifier);
2224 method = store_get_str(&is, "method");
2226 switch (ipconfig->type) {
2227 case CONNMAN_IPCONFIG_TYPE_IPV4:
2228 ipconfig->method = CONNMAN_IPCONFIG_METHOD_DHCP;
2231 case CONNMAN_IPCONFIG_TYPE_IPV6:
2232 ipconfig->method = CONNMAN_IPCONFIG_METHOD_AUTO;
2235 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2236 case CONNMAN_IPCONFIG_TYPE_ALL:
2237 ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
2241 ipconfig->method = __connman_ipconfig_string2method(method);
2245 if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_UNKNOWN)
2246 ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
2248 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
2249 if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO ||
2250 ipconfig->method == CONNMAN_IPCONFIG_METHOD_MANUAL) {
2253 privacy = store_get_str(&is, "privacy");
2254 ipconfig->ipv6_privacy_config = string2privacy(privacy);
2258 g_strfreev(ipconfig->last_dhcpv6_prefixes);
2259 ipconfig->last_dhcpv6_prefixes =
2260 store_get_strs(&is, "DHCP.LastPrefixes");
2264 switch (ipconfig->method) {
2265 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2266 case CONNMAN_IPCONFIG_METHOD_OFF:
2269 case CONNMAN_IPCONFIG_METHOD_FIXED:
2270 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2271 ipconfig->address->prefixlen =
2272 store_get_int(&is, "netmask_prefixlen");
2274 g_free(ipconfig->address->local);
2275 ipconfig->address->local =
2276 store_get_str(&is, "local_address");
2278 g_free(ipconfig->address->peer);
2279 ipconfig->address->peer =
2280 store_get_str(&is, "peer_address");
2282 g_free(ipconfig->address->broadcast);
2283 ipconfig->address->broadcast =
2284 store_get_str(&is, "broadcast_address");
2286 g_free(ipconfig->address->gateway);
2287 ipconfig->address->gateway =
2288 store_get_str(&is, "gateway");
2291 case CONNMAN_IPCONFIG_METHOD_AUTO:
2292 if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
2296 * If the last used method for IPv4 was AUTO then we
2297 * try first DHCP. We will try also to use the last
2298 * used DHCP address, if exits.
2300 __connman_ipconfig_set_method(ipconfig,
2301 CONNMAN_IPCONFIG_METHOD_DHCP);
2304 case CONNMAN_IPCONFIG_METHOD_DHCP:
2305 str = store_get_str(&is, "DHCP.LastAddress");
2307 g_free(ipconfig->last_dhcp_address);
2308 ipconfig->last_dhcp_address = str;
2315 void __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
2316 GKeyFile *keyfile, const char *identifier, const char *prefix)
2319 struct ipconfig_store is = { .file = keyfile,
2320 .group = identifier,
2323 method = __connman_ipconfig_method2string(ipconfig->method);
2324 DBG("ipconfig %p identifier %s method %s", ipconfig, identifier,
2326 store_set_str(&is, "method", method);
2328 if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) {
2329 store_set_str(&is, "privacy",
2330 privacy2string(ipconfig->ipv6_privacy_config));
2332 store_set_str(&is, "DHCP.LastAddress",
2333 ipconfig->last_dhcp_address);
2335 store_set_strs(&is, "DHCP.LastPrefixes",
2336 ipconfig->last_dhcpv6_prefixes);
2339 switch (ipconfig->method) {
2340 case CONNMAN_IPCONFIG_METHOD_FIXED:
2341 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2344 case CONNMAN_IPCONFIG_METHOD_DHCP:
2345 store_set_str(&is, "DHCP.LastAddress",
2346 ipconfig->last_dhcp_address);
2349 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2350 case CONNMAN_IPCONFIG_METHOD_OFF:
2351 case CONNMAN_IPCONFIG_METHOD_AUTO:
2355 store_set_int(&is, "netmask_prefixlen", ipconfig->address->prefixlen);
2356 store_set_str(&is, "local_address", ipconfig->address->local);
2357 store_set_str(&is, "peer_address", ipconfig->address->peer);
2358 store_set_str(&is, "broadcast_address", ipconfig->address->broadcast);
2359 store_set_str(&is, "gateway", ipconfig->address->gateway);
2362 int __connman_ipconfig_init(void)
2366 ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2367 NULL, free_ipdevice);
2369 is_ipv6_supported = connman_inet_is_ipv6_supported();
2374 void __connman_ipconfig_cleanup(void)
2378 g_hash_table_destroy(ipdevice_hash);
2379 ipdevice_hash = NULL;