---
 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

Reply via email to