summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/connman.h13
-rw-r--r--src/ippool.c78
-rw-r--r--src/tethering.c6
-rw-r--r--unit/test-ippool.c6
4 files changed, 93 insertions, 10 deletions
diff --git a/src/connman.h b/src/connman.h
index 557b1eb4..db58316d 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -707,6 +707,9 @@ int __connman_6to4_check(struct connman_ipconfig *ipconfig);
struct connman_ippool;
+typedef void (*ippool_collision_cb_t) (struct connman_ippool *pool,
+ void *user_data);
+
int __connman_ippool_init(void);
void __connman_ippool_cleanup(void);
@@ -720,11 +723,17 @@ struct connman_ippool *__connman_ippool_ref_debug(struct connman_ippool *pool,
void __connman_ippool_unref_debug(struct connman_ippool *pool,
const char *file, int line, const char *caller);
-struct connman_ippool *__connman_ippool_create(unsigned int start,
- unsigned int range);
+struct connman_ippool *__connman_ippool_create(int index,
+ unsigned int start,
+ unsigned int range,
+ ippool_collision_cb_t collision_cb,
+ void *user_data);
const char *__connman_ippool_get_gateway(struct connman_ippool *pool);
const char *__connman_ippool_get_broadcast(struct connman_ippool *pool);
const char *__connman_ippool_get_subnet_mask(struct connman_ippool *pool);
const char *__connman_ippool_get_start_ip(struct connman_ippool *pool);
const char *__connman_ippool_get_end_ip(struct connman_ippool *pool);
+
+void __connman_ippool_newaddr(int index, const char *address);
+void __connman_ippool_deladdr(int index, const char *address);
diff --git a/src/ippool.c b/src/ippool.c
index 085d06c5..a4819ee7 100644
--- a/src/ippool.c
+++ b/src/ippool.c
@@ -37,6 +37,7 @@
struct connman_ippool {
unsigned int refcount;
+ int index;
uint32_t block;
char *gateway;
@@ -44,9 +45,13 @@ struct connman_ippool {
char *start_ip;
char *end_ip;
char *subnet_mask;
+
+ ippool_collision_cb_t collision_cb;
+ void *user_data;
};
static GHashTable *hash_pool;
+static GHashTable *hash_addresses;
static uint32_t last_block;
static uint32_t block_16_bits;
static uint32_t block_20_bits;
@@ -156,6 +161,7 @@ static uint32_t find_free_block()
struct connman_ippool *pool;
uint32_t start;
uint32_t block;
+ uint32_t *key;
if (last_block == 0)
return block_16_bits;
@@ -176,18 +182,76 @@ static uint32_t find_free_block()
while (start != block) {
block = next_block(block);
- pool = g_hash_table_lookup(hash_pool, GUINT_TO_POINTER(block));
+ key = GUINT_TO_POINTER(block);
+ pool = g_hash_table_lookup(hash_pool, key);
if (pool != NULL)
continue;
+ if (g_hash_table_lookup(hash_addresses, key) != NULL)
+ continue;
+
return block;
}
return 0;
}
-struct connman_ippool *__connman_ippool_create(unsigned int start,
- unsigned int range)
+void __connman_ippool_newaddr(int index, const char *address)
+{
+ struct connman_ippool *pool;
+ struct in_addr inp;
+ uint32_t block;
+ uint32_t *key;
+ unsigned int count;
+
+ if (inet_aton(address, &inp) == 0)
+ return;
+
+ block = ntohl(inp.s_addr) & 0xffffff00;
+
+ key = GUINT_TO_POINTER(block);
+ count = GPOINTER_TO_UINT(g_hash_table_lookup(hash_addresses, key));
+ count = count + 1;
+ g_hash_table_replace(hash_addresses, key, GUINT_TO_POINTER(count));
+
+ pool = g_hash_table_lookup(hash_pool, key);
+ if (pool == NULL)
+ return;
+
+ if (pool->index == index)
+ return;
+
+ if (pool->collision_cb != NULL)
+ pool->collision_cb(pool, pool->user_data);
+}
+
+void __connman_ippool_deladdr(int index, const char *address)
+{
+ struct in_addr inp;
+ uint32_t block;
+ uint32_t *key;
+ unsigned int count;
+
+ if (inet_aton(address, &inp) == 0)
+ return;
+
+ block = ntohl(inp.s_addr) & 0xffffff00;
+
+ key = GUINT_TO_POINTER(block);
+ count = GPOINTER_TO_UINT(g_hash_table_lookup(hash_addresses, key));
+ count = count - 1;
+
+ if (count == 0)
+ g_hash_table_remove(hash_addresses, key);
+ else
+ g_hash_table_replace(hash_addresses, key, GUINT_TO_POINTER(count));
+}
+
+struct connman_ippool *__connman_ippool_create(int index,
+ unsigned int start,
+ unsigned int range,
+ ippool_collision_cb_t collision_cb,
+ void *user_data)
{
struct connman_ippool *pool;
uint32_t block;
@@ -208,7 +272,10 @@ struct connman_ippool *__connman_ippool_create(unsigned int start,
return NULL;
pool->refcount = 1;
+ pool->index = index;
pool->block = block;
+ pool->collision_cb = collision_cb;
+ pool->user_data = user_data;
last_block = block;
@@ -276,6 +343,8 @@ int __connman_ippool_init(void)
hash_pool = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
pool_free);
+ hash_addresses = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, NULL);
return 0;
}
@@ -286,4 +355,7 @@ void __connman_ippool_cleanup(void)
g_hash_table_destroy(hash_pool);
hash_pool = NULL;
+
+ g_hash_table_destroy(hash_addresses);
+ hash_addresses = NULL;
}
diff --git a/src/tethering.c b/src/tethering.c
index f7d40a1b..5c359dd4 100644
--- a/src/tethering.c
+++ b/src/tethering.c
@@ -329,6 +329,7 @@ static void disable_nat(const char *interface)
void __connman_tethering_set_enabled(void)
{
+ int index;
int err;
const char *gateway;
const char *broadcast;
@@ -346,7 +347,8 @@ void __connman_tethering_set_enabled(void)
if (err < 0)
return;
- dhcp_ippool = __connman_ippool_create(1, 253);
+ index = connman_inet_ifindex(BRIDGE_NAME);
+ dhcp_ippool = __connman_ippool_create(index, 1, 253, NULL, NULL);
if (dhcp_ippool == NULL) {
connman_error("Fail to create IP pool");
return;
@@ -583,7 +585,7 @@ int __connman_private_network_request(DBusMessage *msg, const char *owner)
pn->fd = fd;
pn->interface = iface;
pn->index = index;
- pn->pool = __connman_ippool_create(1, 1);
+ pn->pool = __connman_ippool_create(pn->fd, 1, 1, NULL, NULL);
if (pn->pool == NULL) {
errno = -ENOMEM;
goto error;
diff --git a/unit/test-ippool.c b/unit/test-ippool.c
index 8cbcf64a..e7f6de0e 100644
--- a/unit/test-ippool.c
+++ b/unit/test-ippool.c
@@ -51,11 +51,11 @@ static void test_ippool_basic0(void)
/* Test the IP range */
- pool = __connman_ippool_create(1, 500);
+ pool = __connman_ippool_create(23, 1, 500, NULL, NULL);
g_assert(pool == NULL);
for (i = 1; i < 254; i++) {
- pool = __connman_ippool_create(1, i);
+ pool = __connman_ippool_create(23, 1, i, NULL, NULL);
g_assert(pool);
gateway = __connman_ippool_get_gateway(pool);
@@ -103,7 +103,7 @@ static void test_ippool_basic1(void)
*/
while (TRUE) {
- pool = __connman_ippool_create(1, 100);
+ pool = __connman_ippool_create(23, 1, 100, NULL, NULL);
if (pool == NULL)
break;
i += 1;