diff options
Diffstat (limited to '')
-rw-r--r-- | lease.c | 105 | ||||
-rw-r--r-- | radix-trie.c | 92 | ||||
-rw-r--r-- | radix-trie.h | 5 |
3 files changed, 94 insertions, 108 deletions
@@ -17,15 +17,12 @@ #define TIME_T_MAX (((time_t)1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1 -static struct ip_pool pools; +static struct ip_pool pool; static time_t gexpires = TIME_T_MAX; KHASH_MAP_INIT_WGKEY(leaseht, struct wg_dynamic_lease *) khash_t(leaseht) * leases_ht; -static uint64_t totall_ipv6; -static uint32_t totalh_ipv6, total_ipv4; - static time_t get_monotonic_time() { struct timespec monotime; @@ -51,9 +48,9 @@ void leases_init(char *fname) leases_ht = kh_init(leaseht); - ipp_init(&pools); + ipp_init(&pool); - /* TODO: initialize pools properly from routes */ + /* TODO: initialize pool properly from routes */ struct in_addr pool1_v4, pool2_v4; struct in6_addr pool1_v6, pool2_v6; inet_pton(AF_INET, "192.168.4.0", &pool1_v4); @@ -61,87 +58,72 @@ void leases_init(char *fname) inet_pton(AF_INET6, "2001:db8:1234::", &pool1_v6); inet_pton(AF_INET6, "2001:db8:7777::", &pool2_v6); - ipp_addpool_v4(&pools, &pool1_v4, 28); - ipp_addpool_v4(&pools, &pool2_v4, 27); - ipp_addpool_v6(&pools, &pool1_v6, 124); - ipp_addpool_v6(&pools, &pool2_v6, 124); - - total_ipv4 = ipp_gettotal_v4(&pools); - totall_ipv6 = ipp_gettotal_v6(&pools, &totalh_ipv6); + ipp_addpool_v4(&pool, &pool1_v4, 28); + ipp_addpool_v4(&pool, &pool2_v4, 27); + ipp_addpool_v6(&pool, &pool1_v6, 124); + ipp_addpool_v6(&pool, &pool2_v6, 124); } void leases_free() { kh_destroy(leaseht, leases_ht); - ipp_free(&pools); + ipp_free(&pool); } struct wg_dynamic_lease *new_lease(wg_key pubkey, uint32_t leasetime, struct in_addr *ipv4, struct in6_addr *ipv6) { struct wg_dynamic_lease *lease, *parent; - uint64_t index_low; - uint32_t index, index_high; + uint64_t index_l; + uint32_t index, index_h; struct timespec tp; khiter_t k; int ret; + bool wants_ipv4 = !ipv4 || ipv4->s_addr; + bool wants_ipv6 = !ipv6 || !IN6_IS_ADDR_UNSPECIFIED(ipv6); lease = malloc(sizeof *lease); if (!lease) fatal("malloc()"); - if (!ipv4 || ipv4->s_addr) { - if (total_ipv4 == 0) - return NULL; + if (wants_ipv4 && !pool.total_ipv4) + return NULL; /* no ipv4 addresses available */ - --total_ipv4; - } - if (!ipv6 || !IN6_IS_ADDR_UNSPECIFIED(ipv6)) { - if (totalh_ipv6 == 0 && totall_ipv6 == 0) { - if (!ipv4 || ipv4->s_addr) - ++total_ipv4; + if (wants_ipv6 && !pool.totalh_ipv6 && !pool.totall_ipv6) + return NULL; /* no ipv6 addresses available */ - return NULL; - } - - if (totall_ipv6 == 0) - --totalh_ipv6; - - --totall_ipv6; - } - - if (!ipv4 || ipv4->s_addr) { + if (wants_ipv4) { if (!ipv4) { - index = random_bounded(total_ipv4); - debug("new_lease(v4): %u of %u\n", index, total_ipv4); - ipp_addnth_v4(&pools, &lease->ipv4, index); + index = random_bounded(pool.total_ipv4 - 1); + debug("new_lease(v4): %u of %u\n", index, + pool.total_ipv4); + + ipp_addnth_v4(&pool, &lease->ipv4, index); } else { - if (ipp_add_v4(&pools, ipv4, 32)) + if (ipp_add_v4(&pool, ipv4, 32)) return NULL; + memcpy(&lease->ipv4, ipv4, sizeof *ipv4); } } - if (!ipv6 || !IN6_IS_ADDR_UNSPECIFIED(ipv6)) { - if (!ipv6) { - if (totalh_ipv6 > 0) { - index_low = random_bounded(UINT64_MAX); - if (totall_ipv6 - index_low > totall_ipv6) - --totalh_ipv6; - index_high = random_bounded(totalh_ipv6); + if (wants_ipv6) { + if (!ipv6) { + if (pool.totalh_ipv6 > 0) { + index_l = random_bounded(UINT64_MAX); + index_h = random_bounded(pool.totalh_ipv6 - 1); } else { - index_low = random_bounded(totall_ipv6); - index_high = 0; + index_l = random_bounded(pool.totall_ipv6 - 1); + index_h = 0; } - debug("new_lease(v6): %u:%ju of %u:%ju\n", index_high, - index_low, totalh_ipv6, totall_ipv6); - ipp_addnth_v6(&pools, &lease->ipv6, index_low, - index_high); + debug("new_lease(v6): %u:%ju of %u:%ju\n", index_h, + index_l, pool.totalh_ipv6, pool.totall_ipv6); + ipp_addnth_v6(&pool, &lease->ipv6, index_l, index_h); } else { - if (ipp_add_v6(&pools, ipv6, 128)) { + if (ipp_add_v6(&pool, ipv6, 128)) { if (!ipv4 || ipv4->s_addr) - ipp_del_v4(&pools, ipv4, 32); + ipp_del_v4(&pool, ipv4, 32); return NULL; } @@ -215,16 +197,11 @@ int leases_refresh() struct in6_addr *ipv6 = &(*pp)->ipv6; time_t expires = (*pp)->start_mono + (*pp)->leasetime; if (cur_time >= expires) { - if (ipv4->s_addr) { - ipp_del_v4(&pools, ipv4, 32); - ++total_ipv4; - } - if (!IN6_IS_ADDR_UNSPECIFIED(ipv6)) { - ipp_del_v6(&pools, ipv6, 128); - ++totall_ipv6; - if (totall_ipv6 == 0) - ++totalh_ipv6; - } + if (ipv4->s_addr) + ipp_del_v4(&pool, ipv4, 32); + + if (!IN6_IS_ADDR_UNSPECIFIED(ipv6)) + ipp_del_v6(&pool, ipv6, 128); tmp = *pp; *pp = (*pp)->next; diff --git a/radix-trie.c b/radix-trie.c index f88d5f9..062490f 100644 --- a/radix-trie.c +++ b/radix-trie.c @@ -475,6 +475,7 @@ void ipp_init(struct ip_pool *pool) { pool->ip4_root = pool->ip6_root = NULL; pool->ip4_pool = pool->ip6_pool = NULL; + pool->totall_ipv6 = pool->totalh_ipv6 = pool->total_ipv4 = 0; } void ipp_free(struct ip_pool *pool) @@ -497,86 +498,90 @@ void ipp_free(struct ip_pool *pool) int ipp_add_v4(struct ip_pool *pool, const struct in_addr *ip, uint8_t cidr) { - return insert_v4(&pool->ip4_root, ip, cidr); + int ret = insert_v4(&pool->ip4_root, ip, cidr); + if (!ret) + --pool->total_ipv4; + + return ret; } int ipp_add_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr) { - return insert_v6(&pool->ip6_root, ip, cidr); + int ret = insert_v6(&pool->ip6_root, ip, cidr); + if (!ret) { + if (pool->totall_ipv6 == 0) + --pool->totalh_ipv6; + + --pool->totall_ipv6; + } + + return ret; } int ipp_del_v4(struct ip_pool *pool, const struct in_addr *ip, uint8_t cidr) { uint8_t key[4] __aligned(__alignof(uint32_t)); + int ret; + swap_endian(key, (const uint8_t *)ip, 32); + ret = remove_node(pool->ip4_root, key, cidr); + if (!ret) + ++pool->total_ipv4; - return remove_node(pool->ip4_root, key, cidr); + return ret; } int ipp_del_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr) { uint8_t key[16] __aligned(__alignof(uint64_t)); + int ret; + swap_endian(key, (const uint8_t *)ip, 128); + ret = remove_node(pool->ip6_root, key, cidr); + if (!ret) { + ++pool->totall_ipv6; + if (pool->totall_ipv6 == 0) + ++pool->totalh_ipv6; + } - return remove_node(pool->ip6_root, key, cidr); + return ret; } int ipp_addpool_v4(struct ip_pool *pool, const struct in_addr *ip, uint8_t cidr) { uint8_t key[4] __aligned(__alignof(uint32_t)); + int ret; if (cidr <= 0 || cidr >= 32) return -1; swap_endian(key, (const uint8_t *)ip, 32); - return ipp_addpool(&pool->ip4_pool, &pool->ip4_root, 32, key, cidr); + ret = ipp_addpool(&pool->ip4_pool, &pool->ip4_root, 32, key, cidr); + if (!ret) + pool->total_ipv4 += 1 << (32 - cidr); + + return ret; } int ipp_addpool_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr) { uint8_t key[16] __aligned(__alignof(uint64_t)); + int ret; - if (cidr <= 0 || cidr < 64 || cidr >= 128) + if (cidr < 64 || cidr >= 128) return -1; swap_endian(key, (const uint8_t *)ip, 128); - return ipp_addpool(&pool->ip6_pool, &pool->ip6_root, 128, key, cidr); -} - -uint32_t ipp_gettotal_v4(struct ip_pool *pool) -{ - struct radix_pool *current = pool->ip4_pool; - uint32_t total = 0; - - for (current = pool->ip4_pool; current; current = current->next) - total += current->node->left + current->node->right; - - return total; -} - -uint64_t ipp_gettotal_v6(struct ip_pool *pool, uint32_t *high) -{ - struct radix_pool *current = pool->ip6_pool; - uint64_t t_low = 0, tmp; - uint32_t t_high = 0; - - while (current) { - if (current->node->left == 0 && current->node->right == 0) { - current = current->next; - continue; - } - - tmp = t_low + current->node->left + current->node->right; - if (tmp <= t_low) - ++t_high; - - t_low = tmp; - current = current->next; + ret = ipp_addpool(&pool->ip6_pool, &pool->ip6_root, 128, key, cidr); + if (!ret) { + uint64_t tmp = pool->totall_ipv6; + pool->totall_ipv6 += (cidr <= 64) ? 0 : 1 << (128 - cidr); + if (pool->totall_ipv6 <= tmp) + ++pool->totalh_ipv6; } - *high = t_high; - return t_low; + return ret; } void ipp_addnth_v4(struct ip_pool *pool, struct in_addr *dest, uint32_t index) @@ -593,6 +598,7 @@ void ipp_addnth_v4(struct ip_pool *pool, struct in_addr *dest, uint32_t index) BUG_ON(!current); add_nth(current->node, 32, index, (uint8_t *)&dest->s_addr); + --pool->total_ipv4; } void ipp_addnth_v6(struct ip_pool *pool, struct in6_addr *dest, @@ -621,7 +627,11 @@ void ipp_addnth_v6(struct ip_pool *pool, struct in6_addr *dest, current = current->next; } - BUG_ON(!pool || index_high); + BUG_ON(!current || index_high); add_nth(current->node, 128, index_low, (uint8_t *)&dest->s6_addr); + if (pool->totall_ipv6 == 0) + --pool->totalh_ipv6; + + --pool->totall_ipv6; } diff --git a/radix-trie.h b/radix-trie.h index 9475cdb..60d383b 100644 --- a/radix-trie.h +++ b/radix-trie.h @@ -11,6 +11,8 @@ #include <stdint.h> struct ip_pool { + uint64_t totall_ipv6; + uint32_t totalh_ipv6, total_ipv4; struct radix_node *ip4_root, *ip6_root; struct radix_pool *ip4_pool, *ip6_pool; }; @@ -24,9 +26,6 @@ int ipp_add_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr); int ipp_del_v4(struct ip_pool *pool, const struct in_addr *ip, uint8_t cidr); int ipp_del_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr); -uint32_t ipp_gettotal_v4(struct ip_pool *pool); -uint64_t ipp_gettotal_v6(struct ip_pool *pool, uint32_t *high); - void ipp_addnth_v4(struct ip_pool *pool, struct in_addr *dest, uint32_t index); void ipp_addnth_v6(struct ip_pool *pool, struct in6_addr *dest, uint32_t index_low, uint64_t index_high); |