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"
50 connman_bool_t enabled;
51 struct connman_ipaddress *address;
52 struct connman_ipaddress *system;
70 static GHashTable *ipdevice_hash = NULL;
72 unsigned char __vpn_ipconfig_netmask_prefix_len(const char *netmask)
81 mask = inet_network(netmask);
84 /* a valid netmask must be 2^n - 1 */
85 if ((host & (host + 1)) != 0)
89 for (; mask; mask <<= 1)
95 const char *__vpn_ipconfig_get_peer(struct vpn_ipconfig *ipconfig)
97 if (ipconfig->address == NULL)
100 return ipconfig->address->peer;
103 unsigned short __vpn_ipconfig_get_type_from_index(int index)
105 struct vpn_ipdevice *ipdevice;
107 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
108 if (ipdevice == NULL)
111 return ipdevice->type;
114 unsigned int __vpn_ipconfig_get_flags_from_index(int index)
116 struct vpn_ipdevice *ipdevice;
118 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
119 if (ipdevice == NULL)
122 return ipdevice->flags;
125 void __vpn_ipconfig_foreach(void (*function) (int index,
126 void *user_data), void *user_data)
130 keys = g_hash_table_get_keys(ipdevice_hash);
134 for (list = g_list_first(keys); list; list = g_list_next(list)) {
135 int index = GPOINTER_TO_INT(list->data);
137 function(index, user_data);
143 void __vpn_ipconfig_set_local(struct vpn_ipconfig *ipconfig,
146 if (ipconfig->address == NULL)
149 g_free(ipconfig->address->local);
150 ipconfig->address->local = g_strdup(address);
153 const char *__vpn_ipconfig_get_local(struct vpn_ipconfig *ipconfig)
155 if (ipconfig->address == NULL)
158 return ipconfig->address->local;
161 void __vpn_ipconfig_set_peer(struct vpn_ipconfig *ipconfig,
164 if (ipconfig->address == NULL)
167 g_free(ipconfig->address->peer);
168 ipconfig->address->peer = g_strdup(address);
171 void __vpn_ipconfig_set_broadcast(struct vpn_ipconfig *ipconfig,
172 const char *broadcast)
174 if (ipconfig->address == NULL)
177 g_free(ipconfig->address->broadcast);
178 ipconfig->address->broadcast = g_strdup(broadcast);
181 void __vpn_ipconfig_set_gateway(struct vpn_ipconfig *ipconfig,
186 if (ipconfig->address == NULL)
188 g_free(ipconfig->address->gateway);
189 ipconfig->address->gateway = g_strdup(gateway);
193 __vpn_ipconfig_get_gateway(struct vpn_ipconfig *ipconfig)
195 if (ipconfig->address == NULL)
198 return ipconfig->address->gateway;
201 void __vpn_ipconfig_set_prefixlen(struct vpn_ipconfig *ipconfig,
202 unsigned char prefixlen)
204 if (ipconfig->address == NULL)
207 ipconfig->address->prefixlen = prefixlen;
211 __vpn_ipconfig_get_prefixlen(struct vpn_ipconfig *ipconfig)
213 if (ipconfig->address == NULL)
216 return ipconfig->address->prefixlen;
219 int __vpn_ipconfig_address_add(struct vpn_ipconfig *ipconfig, int family)
221 DBG("ipconfig %p family %d", ipconfig, family);
223 if (ipconfig == NULL)
226 if (family == AF_INET)
227 return connman_inet_set_address(ipconfig->index,
229 else if (family == AF_INET6)
230 return connman_inet_set_ipv6_address(ipconfig->index,
236 int __vpn_ipconfig_gateway_add(struct vpn_ipconfig *ipconfig, int family)
238 DBG("ipconfig %p family %d", ipconfig, family);
240 if (ipconfig == NULL || ipconfig->address == NULL)
243 DBG("family %d gw %s peer %s", family,
244 ipconfig->address->gateway, ipconfig->address->peer);
246 if (family == AF_INET)
247 connman_inet_add_host_route(ipconfig->index,
248 ipconfig->address->gateway,
249 ipconfig->address->peer);
250 else if (family == AF_INET6)
251 connman_inet_add_ipv6_host_route(ipconfig->index,
252 ipconfig->address->gateway,
253 ipconfig->address->peer);
260 void __vpn_ipconfig_unref_debug(struct vpn_ipconfig *ipconfig,
261 const char *file, int line, const char *caller)
263 if (ipconfig == NULL)
266 DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount - 1,
269 if (__sync_fetch_and_sub(&ipconfig->refcount, 1) != 1)
272 connman_ipaddress_free(ipconfig->system);
273 connman_ipaddress_free(ipconfig->address);
277 static struct vpn_ipconfig *create_ipv6config(int index)
279 struct vpn_ipconfig *ipv6config;
281 DBG("index %d", index);
283 ipv6config = g_try_new0(struct vpn_ipconfig, 1);
284 if (ipv6config == NULL)
287 ipv6config->refcount = 1;
289 ipv6config->index = index;
290 ipv6config->enabled = FALSE;
291 ipv6config->family = AF_INET6;
293 ipv6config->address = connman_ipaddress_alloc(AF_INET6);
294 if (ipv6config->address == NULL) {
299 ipv6config->system = connman_ipaddress_alloc(AF_INET6);
301 DBG("ipconfig %p", ipv6config);
306 struct vpn_ipconfig *__vpn_ipconfig_create(int index, int family)
308 struct vpn_ipconfig *ipconfig;
310 if (family == AF_INET6)
311 return create_ipv6config(index);
313 DBG("index %d", index);
315 ipconfig = g_try_new0(struct vpn_ipconfig, 1);
316 if (ipconfig == NULL)
319 ipconfig->refcount = 1;
321 ipconfig->index = index;
322 ipconfig->enabled = FALSE;
323 ipconfig->family = family;
325 ipconfig->address = connman_ipaddress_alloc(AF_INET);
326 if (ipconfig->address == NULL) {
331 ipconfig->system = connman_ipaddress_alloc(AF_INET);
333 DBG("ipconfig %p", ipconfig);
338 void __vpn_ipconfig_set_index(struct vpn_ipconfig *ipconfig, int index)
340 ipconfig->index = index;
343 static const char *type2str(unsigned short type)
348 case ARPHRD_LOOPBACK:
361 void __vpn_ipconfig_newlink(int index, unsigned short type,
365 struct rtnl_link_stats *stats)
367 struct vpn_ipdevice *ipdevice;
370 if (type == ARPHRD_LOOPBACK)
373 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
374 if (ipdevice != NULL)
377 ipdevice = g_try_new0(struct vpn_ipdevice, 1);
378 if (ipdevice == NULL)
381 ipdevice->index = index;
382 ipdevice->ifname = connman_inet_ifname(index);
383 ipdevice->type = type;
385 ipdevice->address = g_strdup(address);
387 g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
389 connman_info("%s {create} index %d type %d <%s>", ipdevice->ifname,
390 index, type, type2str(type));
395 if (flags == ipdevice->flags)
398 ipdevice->flags = flags;
400 str = g_string_new(NULL);
405 g_string_append(str, "UP");
407 g_string_append(str, "DOWN");
409 if (flags & IFF_RUNNING)
410 g_string_append(str, ",RUNNING");
412 if (flags & IFF_LOWER_UP)
413 g_string_append(str, ",LOWER_UP");
415 connman_info("%s {update} flags %u <%s>", ipdevice->ifname,
418 g_string_free(str, TRUE);
421 void __vpn_ipconfig_dellink(int index, struct rtnl_link_stats *stats)
423 struct vpn_ipdevice *ipdevice;
425 DBG("index %d", index);
427 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
428 if (ipdevice == NULL)
431 g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
434 static void free_ipdevice(gpointer data)
436 struct vpn_ipdevice *ipdevice = data;
438 connman_info("%s {remove} index %d", ipdevice->ifname,
441 g_free(ipdevice->ipv4_gateway);
442 g_free(ipdevice->ipv6_gateway);
443 g_free(ipdevice->pac);
445 g_free(ipdevice->address);
447 g_free(ipdevice->ifname);
451 int __vpn_ipconfig_init(void)
455 ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
456 NULL, free_ipdevice);
461 void __vpn_ipconfig_cleanup(void)
465 g_hash_table_destroy(ipdevice_hash);
466 ipdevice_hash = NULL;