--- Makefile.am | 3 +- src/connman.h | 14 ++++ src/ippool.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 2 + 4 files changed, 236 insertions(+), 1 deletions(-) create mode 100644 src/ippool.c
diff --git a/Makefile.am b/Makefile.am index de634c6..12c8237 100644 --- a/Makefile.am +++ b/Makefile.am @@ -79,7 +79,8 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \ src/storage.c src/dbus.c src/config.c \ src/technology.c src/counter.c src/location.c \ src/session.c src/tethering.c src/wpad.c src/wispr.c \ - src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c + src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c \ + src/ippool.c src_connmand_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \ @CAPNG_LIBS@ @XTABLES_LIBS@ -lresolv -ldl diff --git a/src/connman.h b/src/connman.h index b7dc002..47f29b7 100644 --- a/src/connman.h +++ b/src/connman.h @@ -650,3 +650,17 @@ void __connman_dnsproxy_flush(void); int __connman_6to4_probe(struct connman_service *service); void __connman_6to4_remove(struct connman_ipconfig *ipconfig); int __connman_6to4_check(struct connman_ipconfig *ipconfig); + +struct connman_ippool; +int __connman_ippool_init(void); +void __connman_ippool_cleanup(void); +void __connman_ippool_remove(struct connman_ippool *pool); +struct connman_ippool *__connman_ippool_create(const char *name, + uint16_t static_range, + uint16_t range, + const char **gateway, + const char **broadcast, + const char **start_ip, + const char **end_ip, + const char **subnet_mask, + int *err); diff --git a/src/ippool.c b/src/ippool.c new file mode 100644 index 0000000..1f47029 --- /dev/null +++ b/src/ippool.c @@ -0,0 +1,218 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2007-2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <getopt.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/errno.h> +#include <sys/socket.h> + +#include "connman.h" + +#define SUBNET_MASK_24 inet_addr("255.255.255.0") + +#define BLOCK_24_BITS inet_addr("10.0.0.0") +#define BLOCK_20_BITS inet_addr("172.16.0.0") +/* We start at 254 by default to avoid common addresses */ +#define BLOCK_16_BITS inet_addr("192.168.254.0") + +struct connman_ippool { + char *name; + uint16_t static_range; /* Number of static adresses */ + uint16_t range; /* Number of dynamic addresses */ + uint32_t block; + uint32_t subnet_mask; +}; + +static GHashTable *hash_pool; + +void __connman_ippool_remove(struct connman_ippool *pool) +{ + g_hash_table_remove(hash_pool, &pool->block); +} + +static char *get_ip(uint32_t ip) +{ + struct in_addr addr; + + addr.s_addr = ip; + + return g_strdup(inet_ntoa(addr)); +} + +static gboolean next_block(uint32_t *block) +{ + uint32_t next; + + next = (*block & 0x0000ff00) >> 8; + if (next < 255) { + next++; + if (next == 255 && ((*block & 0xffffff00) == + ntohl(BLOCK_16_BITS))) { + *block = ntohl(BLOCK_20_BITS); + + return TRUE; + } else if (next == 255 && ((*block & 0xffff0000) >= + ntohl(BLOCK_20_BITS))) { + next = (*block & 0x00ff0000) >> 16; + if (next >= 16 && next < 33) { + next++; + if (next == 33) { + *block = ntohl(BLOCK_24_BITS); + + return TRUE; + } + + *block = (*block & 0xff000000) | + ((next << 16) & 0x00ff0000); + } + } else if (next == 255 && ((*block & 0xff000000) == + ntohl(BLOCK_24_BITS))) { + next = (*block & 0x00ff0000) >> 16; + if (next < 255) { + next++; + if (next == 255) + return FALSE; + + *block = (*block & 0xff000000) | + ((next << 16) & 0x00ff0000); + + return TRUE; + } + } + + *block = (*block & 0xffff0000) | ((next << 8) & 0x0000ff00); + + return TRUE; + } + + return FALSE; +} + +static uint32_t find_free_block() +{ + struct connman_ippool *pool; + uint32_t new_block = ntohl(BLOCK_16_BITS); + uint32_t first_block = BLOCK_16_BITS; + + pool = g_hash_table_lookup(hash_pool, &first_block); + if (pool == NULL) + return first_block; + + while (next_block(&new_block) == TRUE) { + uint32_t key = htonl(new_block); + pool = g_hash_table_lookup(hash_pool, &key); + if (pool != NULL) + continue; + + return key; + } + + return 0; +} + +struct connman_ippool *__connman_ippool_create(const char *name, + uint16_t static_range, + uint16_t range, + const char **gateway, + const char **broadcast, + const char **start_ip, + const char **end_ip, + const char **subnet_mask, + int *err) +{ + struct connman_ippool *pool; + uint32_t block; + + /* TODO: manage block size > 254 to set subnet mask appropriately */ + if ((static_range + range) > 254) + goto error; + + block = find_free_block(); + if (block == 0) + goto error; + + pool = g_try_new0(struct connman_ippool, 1); + if (pool == NULL) { + *err = -ENOMEM; + return NULL; + } + + pool->name = g_strdup(name); + pool->static_range = static_range; + pool->range = range; + pool->block = block; + pool->subnet_mask = SUBNET_MASK_24; + + g_hash_table_insert(hash_pool, &pool->block, pool); + + if (range != 0) { + *gateway = get_ip(htonl(ntohl(block) + 1)); + *broadcast = get_ip(htonl(ntohl(block) + 255)); + *start_ip = get_ip(htonl(ntohl(block) + static_range)); + *end_ip = get_ip(htonl(ntohl(block) + range + static_range)); + } else { + *start_ip = get_ip(htonl(ntohl(block) + 1)); + *end_ip = get_ip(htonl(ntohl(block) + 1 + static_range)); + } + + *subnet_mask = get_ip(pool->subnet_mask); + + *err = 0; + + return pool; + +error: + *err = -EINVAL; + return NULL; +} + +static void pool_free(gpointer data) +{ + struct connman_ippool *pool = data; + + g_free(pool->name); + g_free(pool); + pool = NULL; +} + +int __connman_ippool_init(void) +{ + DBG(""); + + hash_pool = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, + pool_free); + + return 0; +} + +void __connman_ippool_cleanup(void) +{ + DBG(""); + + g_hash_table_destroy(hash_pool); +} diff --git a/src/main.c b/src/main.c index 959a43f..2ecb06a 100644 --- a/src/main.c +++ b/src/main.c @@ -343,6 +343,7 @@ int main(int argc, char *argv[]) __connman_device_init(option_device, option_nodevice); __connman_agent_init(); + __connman_ippool_init(); __connman_iptables_init(); __connman_tethering_init(); __connman_counter_init(); @@ -402,6 +403,7 @@ int main(int argc, char *argv[]) __connman_agent_cleanup(); __connman_tethering_cleanup(); __connman_iptables_cleanup(); + __connman_ippool_cleanup(); __connman_device_cleanup(); __connman_network_cleanup(); __connman_service_cleanup(); -- 1.7.1 _______________________________________________ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman