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 static struct vpn_ipconfig *create_ipv6config(int index)
262 struct vpn_ipconfig *ipv6config;
264 DBG("index %d", index);
266 ipv6config = g_try_new0(struct vpn_ipconfig, 1);
267 if (ipv6config == NULL)
270 ipv6config->refcount = 1;
272 ipv6config->index = index;
273 ipv6config->enabled = FALSE;
274 ipv6config->family = AF_INET6;
276 ipv6config->address = connman_ipaddress_alloc(AF_INET6);
277 if (ipv6config->address == NULL) {
282 ipv6config->system = connman_ipaddress_alloc(AF_INET6);
284 DBG("ipconfig %p", ipv6config);
289 struct vpn_ipconfig *__vpn_ipconfig_create(int index, int family)
291 struct vpn_ipconfig *ipconfig;
293 if (family == AF_INET6)
294 return create_ipv6config(index);
296 DBG("index %d", index);
298 ipconfig = g_try_new0(struct vpn_ipconfig, 1);
299 if (ipconfig == NULL)
302 ipconfig->refcount = 1;
304 ipconfig->index = index;
305 ipconfig->enabled = FALSE;
306 ipconfig->family = family;
308 ipconfig->address = connman_ipaddress_alloc(AF_INET);
309 if (ipconfig->address == NULL) {
314 ipconfig->system = connman_ipaddress_alloc(AF_INET);
316 DBG("ipconfig %p", ipconfig);
321 void __vpn_ipconfig_set_index(struct vpn_ipconfig *ipconfig, int index)
323 ipconfig->index = index;
326 static const char *type2str(unsigned short type)
331 case ARPHRD_LOOPBACK:
344 void __vpn_ipconfig_newlink(int index, unsigned short type,
348 struct rtnl_link_stats *stats)
350 struct vpn_ipdevice *ipdevice;
353 if (type == ARPHRD_LOOPBACK)
356 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
357 if (ipdevice != NULL)
360 ipdevice = g_try_new0(struct vpn_ipdevice, 1);
361 if (ipdevice == NULL)
364 ipdevice->index = index;
365 ipdevice->ifname = connman_inet_ifname(index);
366 ipdevice->type = type;
368 ipdevice->address = g_strdup(address);
370 g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
372 connman_info("%s {create} index %d type %d <%s>", ipdevice->ifname,
373 index, type, type2str(type));
378 if (flags == ipdevice->flags)
381 ipdevice->flags = flags;
383 str = g_string_new(NULL);
388 g_string_append(str, "UP");
390 g_string_append(str, "DOWN");
392 if (flags & IFF_RUNNING)
393 g_string_append(str, ",RUNNING");
395 if (flags & IFF_LOWER_UP)
396 g_string_append(str, ",LOWER_UP");
398 connman_info("%s {update} flags %u <%s>", ipdevice->ifname,
401 g_string_free(str, TRUE);
404 void __vpn_ipconfig_dellink(int index, struct rtnl_link_stats *stats)
406 struct vpn_ipdevice *ipdevice;
408 DBG("index %d", index);
410 ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
411 if (ipdevice == NULL)
414 g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
417 static void free_ipdevice(gpointer data)
419 struct vpn_ipdevice *ipdevice = data;
421 connman_info("%s {remove} index %d", ipdevice->ifname,
424 g_free(ipdevice->ipv4_gateway);
425 g_free(ipdevice->ipv6_gateway);
426 g_free(ipdevice->pac);
428 g_free(ipdevice->address);
430 g_free(ipdevice->ifname);
434 int __vpn_ipconfig_init(void)
438 ipdevice_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
439 NULL, free_ipdevice);
444 void __vpn_ipconfig_cleanup(void)
448 g_hash_table_destroy(ipdevice_hash);
449 ipdevice_hash = NULL;