---
 src/connman.h   |    6 ++++
 src/ippool.c    |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/tethering.c |    9 +++---
 3 files changed, 87 insertions(+), 4 deletions(-)

diff --git a/src/connman.h b/src/connman.h
index 47f29b7..7f113f9 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -652,15 +652,21 @@ void __connman_6to4_remove(struct connman_ipconfig 
*ipconfig);
 int __connman_6to4_check(struct connman_ipconfig *ipconfig);
 
 struct connman_ippool;
+typedef void (*ippool_cb_t) (void *user_data);
 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,
+                                               ippool_cb_t cb,
+                                               void *user_data,
                                                const char **gateway,
                                                const char **broadcast,
                                                const char **start_ip,
                                                const char **end_ip,
                                                const char **subnet_mask,
                                                int *err);
+struct connman_ippool *__connman_ippool_notify(const char *name,
+                                               const char *ip,
+                                               int *err);
diff --git a/src/ippool.c b/src/ippool.c
index 1f47029..4c09dae 100644
--- a/src/ippool.c
+++ b/src/ippool.c
@@ -37,15 +37,20 @@
 
 #define BLOCK_24_BITS inet_addr("10.0.0.0")
 #define BLOCK_20_BITS inet_addr("172.16.0.0")
+#define BLOCK_20_BITS_END inet_addr("172.32.0.0")
 /* We start at 254 by default to avoid common addresses */
 #define BLOCK_16_BITS inet_addr("192.168.254.0")
+#define REAL_BLOCK_16_BITS inet_addr("192.168.0.0")
 
 struct connman_ippool {
        char *name;
        uint16_t static_range;  /* Number of static adresses */
        uint16_t range;         /* Number of dynamic addresses */
+       uint8_t refcount;
        uint32_t block;
        uint32_t subnet_mask;
+       ippool_cb_t cb;
+       void *user_data;
 };
 
 static GHashTable *hash_pool;
@@ -135,9 +140,73 @@ static uint32_t find_free_block()
        return 0;
 }
 
+static gboolean is_private_block(uint32_t block)
+{
+       return ((block & 0xffff0000) == ntohl(REAL_BLOCK_16_BITS)) ||
+               ((block & 0xff000000) == ntohl(BLOCK_24_BITS)) ||
+               (((block & 0xffff0000) >= ntohl(BLOCK_20_BITS)) &&
+               ((block & 0xffff0000) <= ntohl(BLOCK_20_BITS_END)));
+}
+
+struct connman_ippool *__connman_ippool_notify(const char *name,
+                                               const char *ip,
+                                               int *err)
+{
+       struct connman_ippool *pool;
+       struct in_addr inp;
+       uint32_t block;
+
+       if (inet_aton(ip, &inp) == 0) {
+               *err = -ENXIO;
+               return NULL;
+       }
+
+       /*
+        * In case of connection to a cellular network, ConnMan will be
+        * notified by oFono of the public IP used, so there is no need to
+        * store such IP address into the hash_pool.
+        */
+       if (is_private_block(ntohl(inp.s_addr)) == FALSE) {
+               connman_info("IP %s is not a private\n", ip);
+               return NULL;
+       }
+
+       block = htonl(ntohl(inp.s_addr) & 0xffffff00);
+       pool = g_hash_table_lookup(hash_pool, &block);
+       if (pool == NULL) {
+               pool = g_try_new0(struct connman_ippool, 1);
+               if (pool == NULL) {
+                       *err = -ENOMEM;
+                       return NULL;
+               }
+
+               pool->refcount++;
+       } else {
+               pool->refcount++;
+               if (pool->cb != NULL)
+                       pool->cb(pool->user_data);
+
+               g_free(pool->name);
+               pool->name = g_strdup(name);
+       }
+
+       pool->static_range = 1;
+       pool->range = 0;
+       pool->cb = NULL;
+       pool->user_data = NULL;
+       pool->block = block;
+       pool->subnet_mask = SUBNET_MASK_24;
+
+       g_hash_table_insert(hash_pool, &pool->block, pool);
+
+       return pool;
+}
+
 struct connman_ippool *__connman_ippool_create(const char *name,
                                                uint16_t static_range,
                                                uint16_t range,
+                                               ippool_cb_t cb,
+                                               void *user_data,
                                                const char **gateway,
                                                const char **broadcast,
                                                const char **start_ip,
@@ -162,9 +231,12 @@ struct connman_ippool *__connman_ippool_create(const char 
*name,
                return NULL;
        }
 
+       pool->refcount++;
        pool->name = g_strdup(name);
        pool->static_range = static_range;
        pool->range = range;
+       pool->cb = cb;
+       pool->user_data = user_data;
        pool->block = block;
        pool->subnet_mask = SUBNET_MASK_24;
 
@@ -195,6 +267,10 @@ static void pool_free(gpointer data)
 {
        struct connman_ippool *pool = data;
 
+       pool->refcount--;
+       if (pool->refcount > 0)
+               return;
+
        g_free(pool->name);
        g_free(pool);
        pool = NULL;
diff --git a/src/tethering.c b/src/tethering.c
index 75dcce2..c1a10ee 100644
--- a/src/tethering.c
+++ b/src/tethering.c
@@ -348,9 +348,10 @@ void __connman_tethering_set_enabled(void)
                        return;
 
                dhcp_pool = __connman_ippool_create(BRIDGE_NAME, 100, 100,
-                                                       &gateway, &broadcast,
-                                                       &start_ip, &end_ip,
-                                                       &subnet, &err);
+                                                       NULL, NULL, &gateway,
+                                                       &broadcast, &start_ip,
+                                                       &end_ip, &subnet,
+                                                       &err);
                if (dhcp_pool == NULL) {
                        connman_error("Fail to create pool with error %d",
                                        err);
@@ -576,7 +577,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(iface, 1, 0, NULL, NULL,
+       pn->pool = __connman_ippool_create(iface, 1, 0, NULL, NULL, NULL, NULL,
                                                &pn->server_ip, &pn->peer_ip,
                                                &pn->subnet_mask, &err);
        if (pn->pool == NULL)
-- 
1.7.1

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to