5 * Copyright (C) 2012 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>
34 #include <arpa/inet.h>
37 #define IFF_LOWER_UP 0x10000
42 #include "../src/connman.h"
51 struct connman_ipaddress *address;
52 struct connman_ipaddress *system;
70 static GHashTable *ipdevice_hash = NULL;
72 struct connman_ipaddress *
73 __vpn_ipconfig_get_address(struct vpn_ipconfig *ipconfig)
78 return ipconfig->address;
81 const char *__vpn_ipconfig_get_peer(struct vpn_ipconfig *ipconfig)
83 if (!ipconfig->address)
86 return ipconfig->address->peer;
89 unsigned short __vpn_ipconfig_get_type_from_index(int index)
91 struct vpn_ipdevice *ipdevice;
93 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
97 return ipdevice->type;
100 unsigned int __vpn_ipconfig_get_flags_from_index(int index)
102 struct vpn_ipdevice *ipdevice;
104 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
108 return ipdevice->flags;
111 void __vpn_ipconfig_foreach(void (*function) (int index,
112 void *user_data), void *user_data)
116 keys = g_hash_table_get_keys(ipdevice_hash);
120 for (list = g_list_first(keys); list; list = g_list_next(list)) {
121 int index = GPOINTER_TO_INT(list->data);
123 function(index, user_data);
129 void __vpn_ipconfig_set_local(struct vpn_ipconfig *ipconfig,
132 if (!ipconfig->address)
135 g_free(ipconfig->address->local);
136 ipconfig->address->local = g_strdup(address);
139 const char *__vpn_ipconfig_get_local(struct vpn_ipconfig *ipconfig)
141 if (!ipconfig->address)
144 return ipconfig->address->local;
147 void __vpn_ipconfig_set_peer(struct vpn_ipconfig *ipconfig,
150 if (!ipconfig->address)
153 g_free(ipconfig->address->peer);
154 ipconfig->address->peer = g_strdup(address);
157 void __vpn_ipconfig_set_broadcast(struct vpn_ipconfig *ipconfig,
158 const char *broadcast)
160 if (!ipconfig->address)
163 g_free(ipconfig->address->broadcast);
164 ipconfig->address->broadcast = g_strdup(broadcast);
167 void __vpn_ipconfig_set_gateway(struct vpn_ipconfig *ipconfig,
172 if (!ipconfig->address)
174 g_free(ipconfig->address->gateway);
175 ipconfig->address->gateway = g_strdup(gateway);
179 __vpn_ipconfig_get_gateway(struct vpn_ipconfig *ipconfig)
181 if (!ipconfig->address)
184 return ipconfig->address->gateway;
187 void __vpn_ipconfig_set_prefixlen(struct vpn_ipconfig *ipconfig,
188 unsigned char prefixlen)
190 if (!ipconfig->address)
193 ipconfig->address->prefixlen = prefixlen;
197 __vpn_ipconfig_get_prefixlen(struct vpn_ipconfig *ipconfig)
199 if (!ipconfig->address)
202 return ipconfig->address->prefixlen;
205 int __vpn_ipconfig_address_add(struct vpn_ipconfig *ipconfig, int family)
207 DBG("ipconfig %p family %d", ipconfig, family);
212 if (family == AF_INET)
213 return connman_inet_set_address(ipconfig->index,
215 else if (family == AF_INET6)
216 return connman_inet_set_ipv6_address(ipconfig->index,
222 int __vpn_ipconfig_gateway_add(struct vpn_ipconfig *ipconfig, int family)
224 DBG("ipconfig %p family %d", ipconfig, family);
226 if (!ipconfig || !ipconfig->address)
229 DBG("family %d gw %s peer %s", family,
230 ipconfig->address->gateway, ipconfig->address->peer);
232 if (family == AF_INET)
233 connman_inet_add_host_route(ipconfig->index,
234 ipconfig->address->gateway,
235 ipconfig->address->peer);
236 else if (family == AF_INET6)
237 connman_inet_add_ipv6_host_route(ipconfig->index,
238 ipconfig->address->gateway,
239 ipconfig->address->peer);
246 void __vpn_ipconfig_unref_debug(struct vpn_ipconfig *ipconfig,
247 const char *file, int line, const char *caller)
252 DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount - 1,
255 if (__sync_fetch_and_sub(&ipconfig->refcount, 1) != 1)
258 connman_ipaddress_free(ipconfig->system);
259 connman_ipaddress_free(ipconfig->address);
263 static struct vpn_ipconfig *create_ipv6config(int index)
265 struct vpn_ipconfig *ipv6config;
267 DBG("index %d", index);
269 ipv6config = g_try_new0(struct vpn_ipconfig, 1);
273 ipv6config->refcount = 1;
275 ipv6config->index = index;
276 ipv6config->enabled = false;
277 ipv6config->family = AF_INET6;
279 ipv6config->address = connman_ipaddress_alloc(AF_INET6);
280 if (!ipv6config->address) {
285 ipv6config->system = connman_ipaddress_alloc(AF_INET6);
287 DBG("ipconfig %p", ipv6config);
292 struct vpn_ipconfig *__vpn_ipconfig_create(int index, int family)
294 struct vpn_ipconfig *ipconfig;
296 if (family == AF_INET6)
297 return create_ipv6config(index);
299 DBG("index %d", index);
301 ipconfig = g_try_new0(struct vpn_ipconfig, 1);
305 ipconfig->refcount = 1;
307 ipconfig->index = index;
308 ipconfig->enabled = false;
309 ipconfig->family = family;
311 ipconfig->address = connman_ipaddress_alloc(AF_INET);
312 if (!ipconfig->address) {
317 ipconfig->system = connman_ipaddress_alloc(AF_INET);
319 DBG("ipconfig %p", ipconfig);
324 void __vpn_ipconfig_set_index(struct vpn_ipconfig *ipconfig, int index)
326 ipconfig->index = index;
329 static const char *type2str(unsigned short type)
334 case ARPHRD_LOOPBACK:
347 void __vpn_ipconfig_newlink(int index, unsigned short type,
351 struct rtnl_link_stats *stats)
353 struct vpn_ipdevice *ipdevice;
356 if (type == ARPHRD_LOOPBACK)
359 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
363 ipdevice = g_try_new0(struct vpn_ipdevice, 1);
367 ipdevice->index = index;
368 ipdevice->ifname = connman_inet_ifname(index);
369 ipdevice->type = type;
371 ipdevice->address = g_strdup(address);
373 g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
375 connman_info("%s {create} index %d type %d <%s>", ipdevice->ifname,
376 index, type, type2str(type));
381 if (flags == ipdevice->flags)
384 ipdevice->flags = flags;
386 str = g_string_new(NULL);
391 g_string_append(str, "UP");
393 g_string_append(str, "DOWN");
395 if (flags & IFF_RUNNING)
396 g_string_append(str, ",RUNNING");
398 if (flags & IFF_LOWER_UP)
399 g_string_append(str, ",LOWER_UP");
401 connman_info("%s {update} flags %u <%s>", ipdevice->ifname,
404 g_string_free(str, TRUE);
407 void __vpn_ipconfig_dellink(int index, struct rtnl_link_stats *stats)
409 struct vpn_ipdevice *ipdevice;
411 DBG("index %d", index);
413 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
417 g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
420 static void free_ipdevice(gpointer data)
422 struct vpn_ipdevice *ipdevice = data;
424 connman_info("%s {remove} index %d", ipdevice->ifname,
427 g_free(ipdevice->ipv4_gateway);
428 g_free(ipdevice->ipv6_gateway);
429 g_free(ipdevice->pac);
431 g_free(ipdevice->address);
433 g_free(ipdevice->ifname);
437 int __vpn_ipconfig_init(void)
441 ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
442 NULL, free_ipdevice);
447 void __vpn_ipconfig_cleanup(void)
451 g_hash_table_destroy(ipdevice_hash);
452 ipdevice_hash = NULL;