Added support of WPA3-SAE security mode.
[platform/upstream/connman.git] / src / ippool.c
old mode 100644 (file)
new mode 100755 (executable)
index b513b09..cea1dcc
@@ -2,8 +2,8 @@
  *
  *  Connection Manager
  *
- *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
- *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
+ *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2012-2014  BMW Car IT GmbH.
  *
  *  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
@@ -24,7 +24,6 @@
 #include <config.h>
 #endif
 
-#include <getopt.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -59,7 +58,6 @@ struct connman_ippool {
 };
 
 GSList *allocated_blocks;
-GHashTable *pool_hash;
 
 static uint32_t last_block;
 static uint32_t block_16_bits;
@@ -82,7 +80,7 @@ __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)
 {
-       if (pool == NULL)
+       if (!pool)
                return;
 
        DBG("%p ref %d by %s:%d:%s()", pool, pool->refcount - 1,
@@ -91,7 +89,18 @@ void __connman_ippool_unref_debug(struct connman_ippool *pool,
        if (__sync_fetch_and_sub(&pool->refcount, 1) != 1)
                return;
 
-       g_hash_table_remove(pool_hash, pool);
+       if (pool->info) {
+               allocated_blocks = g_slist_remove(allocated_blocks, pool->info);
+               g_free(pool->info);
+       }
+
+       g_free(pool->gateway);
+       g_free(pool->broadcast);
+       g_free(pool->start_ip);
+       g_free(pool->end_ip);
+       g_free(pool->subnet_mask);
+
+       g_free(pool);
 }
 
 static char *get_ip(uint32_t ip)
@@ -170,7 +179,7 @@ static uint32_t get_free_block(unsigned int size)
        struct address_info *info;
        uint32_t block;
        GSList *list;
-       connman_bool_t collision;
+       bool collision;
 
        /*
         * Instead starting always from the 16 bit block, we start
@@ -182,23 +191,23 @@ static uint32_t get_free_block(unsigned int size)
         * To only thing we have to make sure is that we terminated if
         * there is no block left.
         */
-       if (last_block == 0)
-               block = block_16_bits;
+       if (last_block)
+               block = last_block;
        else
-               block = next_block(last_block);
+               block = block_16_bits;
 
        do {
-               collision = FALSE;
-               for (list = allocated_blocks; list != NULL; list = list->next) {
+               collision = false;
+               for (list = allocated_blocks; list; list = list->next) {
                        info = list->data;
 
                        if (info->start <= block && block <= info->end) {
-                               collision = TRUE;
+                               collision = true;
                                break;
                        }
                }
 
-               if (collision == FALSE)
+               if (!collision)
                        return block;
 
                block = next_block(block);
@@ -211,7 +220,7 @@ static struct address_info *lookup_info(int index, uint32_t start)
 {
        GSList *list;
 
-       for (list = allocated_blocks; list != NULL; list = list->next) {
+       for (list = allocated_blocks; list; list = list->next) {
                struct address_info *info = list->data;
 
                if (info->index == index && info->start == start)
@@ -221,26 +230,18 @@ static struct address_info *lookup_info(int index, uint32_t start)
        return NULL;
 }
 
-static connman_bool_t is_private_address(uint32_t address)
+static bool is_private_address(uint32_t address)
 {
-       uint32_t val;
+       unsigned int a, b;
 
-       if ((address & 0xff000000) == block_24_bits)
-               return TRUE;
+       a = (address & 0xff000000) >> 24;
+       b = (address & 0x00ff0000) >> 16;
 
-       if ((address & 0xffff0000) == block_20_bits) {
-               val = (address & 0x00ff0000) >> 16;
+       if (a == 10 || (a == 192 && b == 168) ||
+                                       (a == 172 && (b >= 16 && b <= 31)))
+               return true;
 
-               if (val < 16 || val > 31)
-                       return FALSE;
-
-               return TRUE;
-       }
-
-       if ((address & 0xffffff00) == block_16_bits)
-               return TRUE;
-
-       return FALSE;
+       return false;
 }
 
 void __connman_ippool_newaddr(int index, const char *address,
@@ -255,19 +256,23 @@ void __connman_ippool_newaddr(int index, const char *address,
                return;
 
        start = ntohl(inp.s_addr);
-       if (is_private_address(start) == FALSE)
+       if (!is_private_address(start))
                return;
 
-       mask = ~(0xffffffff >> prefixlen);
+       if (prefixlen >= 32)
+               mask = 0xffffffff;
+       else
+               mask = ~(0xffffffff >> prefixlen);
+
        start = start & mask;
        end = start | ~mask;
 
        info = lookup_info(index, start);
-       if (info != NULL)
+       if (info)
                goto update;
 
        info = g_try_new0(struct address_info, 1);
-       if (info == NULL)
+       if (!info)
                return;
 
        info->index = index;
@@ -279,7 +284,7 @@ void __connman_ippool_newaddr(int index, const char *address,
 update:
        info->use_count = info->use_count + 1;
 
-       if (info->use_count > 1 || info->pool != NULL) {
+       if (info->use_count > 1 || info->pool) {
                /*
                 * We need only to check for the first IP in a block for
                 * collisions.
@@ -287,16 +292,16 @@ update:
                return;
        }
 
-       for (list = allocated_blocks; list != NULL; list = list->next) {
+       for (list = allocated_blocks; list; list = list->next) {
                it = list->data;
 
                if (it == info)
                        continue;
 
-               if (!(it->start <= info->start || info->start <= it->end))
+               if (!(info->start >= it->start && info->start <= it->end))
                        continue;
 
-               if (it->pool->collision_cb != NULL)
+               if (it->pool && it->pool->collision_cb)
                        it->pool->collision_cb(it->pool, it->pool->user_data);
 
                return;
@@ -314,27 +319,28 @@ void __connman_ippool_deladdr(int index, const char *address,
                return;
 
        start = ntohl(inp.s_addr);
-       if (is_private_address(start) == FALSE)
+       if (!is_private_address(start))
                return;
 
        mask = ~(0xffffffff >> prefixlen);
        start = start & mask;
 
        info = lookup_info(index, start);
-       if (info == NULL) {
+       if (!info) {
                /* In theory this should never happen */
                connman_error("Inconsistent IP pool management (start not found)");
                return;
        }
 
        info->use_count = info->use_count - 1;
-       if (info->pool != NULL)
+       if (info->pool)
                return;
 
        if (info->use_count > 0)
                return;
 
        allocated_blocks = g_slist_remove(allocated_blocks, info);
+       g_free(info);
 }
 
 struct connman_ippool *__connman_ippool_create(int index,
@@ -365,11 +371,11 @@ struct connman_ippool *__connman_ippool_create(int index,
        }
 
        pool = g_try_new0(struct connman_ippool, 1);
-       if (pool == NULL)
+       if (!pool)
                return NULL;
 
        info = g_try_new0(struct address_info, 1);
-       if (info == NULL) {
+       if (!info) {
                g_free(pool);
                return NULL;
        }
@@ -397,7 +403,6 @@ struct connman_ippool *__connman_ippool_create(int index,
        pool->end_ip = get_ip(block + start + range);
 
        allocated_blocks = g_slist_prepend(allocated_blocks, info);
-       g_hash_table_insert(pool_hash, pool, pool);
 
        return pool;
 }
@@ -427,24 +432,6 @@ const char *__connman_ippool_get_subnet_mask(struct connman_ippool *pool)
        return pool->subnet_mask;
 }
 
-static void pool_free(gpointer data)
-{
-       struct connman_ippool *pool = data;
-
-       if (pool->info != NULL) {
-               allocated_blocks = g_slist_remove(allocated_blocks, pool->info);
-               g_free(pool->info);
-       }
-
-       g_free(pool->gateway);
-       g_free(pool->broadcast);
-       g_free(pool->start_ip);
-       g_free(pool->end_ip);
-       g_free(pool->subnet_mask);
-
-       g_free(pool);
-}
-
 int __connman_ippool_init(void)
 {
        DBG("");
@@ -454,9 +441,6 @@ int __connman_ippool_init(void)
        block_24_bits = ntohl(inet_addr("10.0.0.0"));
        subnet_mask_24 = ntohl(inet_addr("255.255.255.0"));
 
-       pool_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
-                                       pool_free);
-
        return 0;
 }
 
@@ -464,9 +448,7 @@ void __connman_ippool_cleanup(void)
 {
        DBG("");
 
-       g_hash_table_destroy(pool_hash);
-       pool_hash = NULL;
-
-       g_slist_free(allocated_blocks);
+       g_slist_free_full(allocated_blocks, g_free);
        last_block = 0;
+       allocated_blocks = NULL;
 }