diff options
author | Alberto Gonzalez Iniesta <agi@inittab.org> | 2012-11-05 16:28:09 +0100 |
---|---|---|
committer | Alberto Gonzalez Iniesta <agi@inittab.org> | 2012-11-05 16:28:09 +0100 |
commit | 8dd0350e1607aa30f7a043c8d5ec7a7eeb874115 (patch) | |
tree | 566d0620eb693320cb121dfd93a5675fa704a30b /pool.c | |
parent | 349cfa7acb95abe865209a28e417ec74b56f9bba (diff) |
Imported Upstream version 2.3_rc1
Diffstat (limited to 'pool.c')
-rw-r--r-- | pool.c | 526 |
1 files changed, 0 insertions, 526 deletions
@@ -1,526 +0,0 @@ -/* - * OpenVPN -- An application to securely tunnel IP networks - * over a single TCP/UDP port, with support for SSL/TLS-based - * session authentication and key exchange, - * packet encryption, packet authentication, and - * packet compression. - * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> - * - * 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 (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "syshead.h" - -#include "pool.h" -#include "buffer.h" -#include "error.h" -#include "socket.h" -#include "otime.h" - -#include "memdbg.h" - -#if P2MP - -static void -ifconfig_pool_entry_free (struct ifconfig_pool_entry *ipe, bool hard) -{ - ipe->in_use = false; - if (hard && ipe->common_name) - { - free (ipe->common_name); - ipe->common_name = NULL; - } - if (hard) - ipe->last_release = 0; - else - ipe->last_release = now; -} - -static int -ifconfig_pool_find (struct ifconfig_pool *pool, const char *common_name) -{ - int i; - time_t earliest_release = 0; - int previous_usage = -1; - int new_usage = -1; - - for (i = 0; i < pool->size; ++i) - { - struct ifconfig_pool_entry *ipe = &pool->list[i]; - if (!ipe->in_use) - { - /* - * If duplicate_cn mode, take first available IP address - */ - if (pool->duplicate_cn) - { - new_usage = i; - break; - } - - /* - * Keep track of the unused IP address entry which - * was released earliest. - */ - if ((new_usage == -1 || ipe->last_release < earliest_release) && !ipe->fixed) - { - earliest_release = ipe->last_release; - new_usage = i; - } - - /* - * Keep track of a possible allocation to us - * from an earlier session. - */ - if (previous_usage < 0 - && common_name - && ipe->common_name - && !strcmp (common_name, ipe->common_name)) - previous_usage = i; - - } - } - - if (previous_usage >= 0) - return previous_usage; - - if (new_usage >= 0) - return new_usage; - - return -1; -} - -/* - * Verify start/end range - */ -bool -ifconfig_pool_verify_range (const int msglevel, const in_addr_t start, const in_addr_t end) -{ - struct gc_arena gc = gc_new (); - bool ret = true; - - if (start > end) - { - msg (msglevel, "--ifconfig-pool start IP [%s] is greater than end IP [%s]", - print_in_addr_t (start, 0, &gc), - print_in_addr_t (end, 0, &gc)); - ret = false; - } - if (end - start >= IFCONFIG_POOL_MAX) - { - msg (msglevel, "--ifconfig-pool address range is too large [%s -> %s]. Current maximum is %d addresses, as defined by IFCONFIG_POOL_MAX variable.", - print_in_addr_t (start, 0, &gc), - print_in_addr_t (end, 0, &gc), - IFCONFIG_POOL_MAX); - ret = false; - } - gc_free (&gc); - return ret; -} - -struct ifconfig_pool * -ifconfig_pool_init (int type, in_addr_t start, in_addr_t end, const bool duplicate_cn) -{ - struct gc_arena gc = gc_new (); - struct ifconfig_pool *pool = NULL; - - ASSERT (start <= end && end - start < IFCONFIG_POOL_MAX); - ALLOC_OBJ_CLEAR (pool, struct ifconfig_pool); - - pool->type = type; - pool->duplicate_cn = duplicate_cn; - - switch (type) - { - case IFCONFIG_POOL_30NET: - pool->base = start & ~3; - pool->size = (((end | 3) + 1) - pool->base) >> 2; - break; - case IFCONFIG_POOL_INDIV: - pool->base = start; - pool->size = end - start + 1; - break; - default: - ASSERT (0); - } - - ALLOC_ARRAY_CLEAR (pool->list, struct ifconfig_pool_entry, pool->size); - - msg (D_IFCONFIG_POOL, "IFCONFIG POOL: base=%s size=%d", - print_in_addr_t (pool->base, 0, &gc), - pool->size); - - gc_free (&gc); - return pool; -} - -void -ifconfig_pool_free (struct ifconfig_pool *pool) -{ - if (pool) - { - int i; - for (i = 0; i < pool->size; ++i) - ifconfig_pool_entry_free (&pool->list[i], true); - free (pool->list); - free (pool); - } -} - -ifconfig_pool_handle -ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, const char *common_name) -{ - int i; - - i = ifconfig_pool_find (pool, common_name); - if (i >= 0) - { - struct ifconfig_pool_entry *ipe = &pool->list[i]; - ASSERT (!ipe->in_use); - ifconfig_pool_entry_free (ipe, true); - ipe->in_use = true; - if (common_name) - ipe->common_name = string_alloc (common_name, NULL); - - switch (pool->type) - { - case IFCONFIG_POOL_30NET: - { - in_addr_t b = pool->base + (i << 2); - *local = b + 1; - *remote = b + 2; - break; - } - case IFCONFIG_POOL_INDIV: - { - in_addr_t b = pool->base + i; - *local = 0; - *remote = b; - break; - } - default: - ASSERT (0); - } - } - return i; -} - -bool -ifconfig_pool_release (struct ifconfig_pool* pool, ifconfig_pool_handle hand, const bool hard) -{ - bool ret = false; - if (pool && hand >= 0 && hand < pool->size) - { - ifconfig_pool_entry_free (&pool->list[hand], hard); - ret = true; - } - return ret; -} - -/* - * private access functions - */ - -static ifconfig_pool_handle -ifconfig_pool_ip_base_to_handle (const struct ifconfig_pool* pool, const in_addr_t addr) -{ - ifconfig_pool_handle ret = -1; - - switch (pool->type) - { - case IFCONFIG_POOL_30NET: - { - ret = (addr - pool->base) >> 2; - break; - } - case IFCONFIG_POOL_INDIV: - { - ret = (addr - pool->base); - break; - } - default: - ASSERT (0); - } - - if (ret < 0 || ret >= pool->size) - ret = -1; - - return ret; -} - -static in_addr_t -ifconfig_pool_handle_to_ip_base (const struct ifconfig_pool* pool, ifconfig_pool_handle hand) -{ - in_addr_t ret = 0; - - if (hand >= 0 && hand < pool->size) - { - switch (pool->type) - { - case IFCONFIG_POOL_30NET: - { - ret = pool->base + (hand << 2);; - break; - } - case IFCONFIG_POOL_INDIV: - { - ret = pool->base + hand; - break; - } - default: - ASSERT (0); - } - } - - return ret; -} - -static void -ifconfig_pool_set (struct ifconfig_pool* pool, const char *cn, const in_addr_t addr, const bool fixed) -{ - ifconfig_pool_handle h = ifconfig_pool_ip_base_to_handle (pool, addr); - if (h >= 0) - { - struct ifconfig_pool_entry *e = &pool->list[h]; - ifconfig_pool_entry_free (e, true); - e->in_use = false; - e->common_name = string_alloc (cn, NULL); - e->last_release = now; - e->fixed = fixed; - } -} - -static void -ifconfig_pool_list (const struct ifconfig_pool* pool, struct status_output *out) -{ - if (pool && out) - { - struct gc_arena gc = gc_new (); - int i; - - for (i = 0; i < pool->size; ++i) - { - const struct ifconfig_pool_entry *e = &pool->list[i]; - if (e->common_name) - { - const in_addr_t ip = ifconfig_pool_handle_to_ip_base (pool, i); - status_printf (out, "%s,%s", - e->common_name, - print_in_addr_t (ip, 0, &gc)); - } - } - gc_free (&gc); - } -} - -static void -ifconfig_pool_msg (const struct ifconfig_pool* pool, int msglevel) -{ - struct status_output *so = status_open (NULL, 0, msglevel, NULL, 0); - ASSERT (so); - status_printf (so, "IFCONFIG POOL LIST"); - ifconfig_pool_list (pool, so); - status_close (so); -} - -/* - * Deal with reading/writing the ifconfig pool database to a file - */ - -struct ifconfig_pool_persist * -ifconfig_pool_persist_init (const char *filename, int refresh_freq) -{ - struct ifconfig_pool_persist *ret; - - ASSERT (filename); - - ALLOC_OBJ_CLEAR (ret, struct ifconfig_pool_persist); - if (refresh_freq > 0) - { - ret->fixed = false; - ret->file = status_open (filename, refresh_freq, -1, NULL, STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE); - } - else - { - ret->fixed = true; - ret->file = status_open (filename, 0, -1, NULL, STATUS_OUTPUT_READ); - } - return ret; -} - -void -ifconfig_pool_persist_close (struct ifconfig_pool_persist *persist) -{ - if (persist) - { - if (persist->file) - status_close (persist->file); - free (persist); - } -} - -bool -ifconfig_pool_write_trigger (struct ifconfig_pool_persist *persist) -{ - if (persist->file) - return status_trigger (persist->file); - else - return false; -} - -void -ifconfig_pool_read (struct ifconfig_pool_persist *persist, struct ifconfig_pool *pool) -{ - const int buf_size = 128; - - update_time (); - if (persist && persist->file && pool) - { - struct gc_arena gc = gc_new (); - struct buffer in = alloc_buf_gc (256, &gc); - char *cn_buf; - char *ip_buf; - int line = 0; - - ALLOC_ARRAY_CLEAR_GC (cn_buf, char, buf_size, &gc); - ALLOC_ARRAY_CLEAR_GC (ip_buf, char, buf_size, &gc); - - while (true) - { - ASSERT (buf_init (&in, 0)); - if (!status_read (persist->file, &in)) - break; - ++line; - if (BLEN (&in)) - { - int c = *BSTR(&in); - if (c == '#' || c == ';') - continue; - if (buf_parse (&in, ',', cn_buf, buf_size) - && buf_parse (&in, ',', ip_buf, buf_size)) - { - bool succeeded; - const in_addr_t addr = getaddr (GETADDR_HOST_ORDER, ip_buf, 0, &succeeded, NULL); - if (succeeded) - { - ifconfig_pool_set (pool, cn_buf, addr, persist->fixed); - } - } - } - } - - ifconfig_pool_msg (pool, D_IFCONFIG_POOL); - - gc_free (&gc); - } -} - -void -ifconfig_pool_write (struct ifconfig_pool_persist *persist, const struct ifconfig_pool *pool) -{ - if (persist && persist->file && (status_rw_flags (persist->file) & STATUS_OUTPUT_WRITE) && pool) - { - status_reset (persist->file); - ifconfig_pool_list (pool, persist->file); - status_flush (persist->file); - } -} - -/* - * TESTING ONLY - */ - -#ifdef IFCONFIG_POOL_TEST - -#define DUP_CN - -void -ifconfig_pool_test (in_addr_t start, in_addr_t end) -{ - struct gc_arena gc = gc_new (); - struct ifconfig_pool *p = ifconfig_pool_init (IFCONFIG_POOL_30NET, start, end); - /*struct ifconfig_pool *p = ifconfig_pool_init (IFCONFIG_POOL_INDIV, start, end);*/ - ifconfig_pool_handle array[256]; - int i; - - CLEAR (array); - - msg (M_INFO | M_NOPREFIX, "************ 1"); - for (i = 0; i < (int) SIZE (array); ++i) - { - char *cn; - ifconfig_pool_handle h; - in_addr_t local, remote; - char buf[256]; - openvpn_snprintf (buf, sizeof(buf), "common-name-%d", i); -#ifdef DUP_CN - cn = NULL; -#else - cn = buf; -#endif - h = ifconfig_pool_acquire (p, &local, &remote, cn); - if (h < 0) - break; - msg (M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 1: l=%s r=%s cn=%s", - print_in_addr_t (local, 0, &gc), - print_in_addr_t (remote, 0, &gc), - cn); - array[i] = h; - - } - - msg (M_INFO | M_NOPREFIX, "************* 2"); - for (i = (int) SIZE (array) / 16; i < (int) SIZE (array) / 8; ++i) - { - msg (M_INFO, "Attempt to release %d cn=%s", array[i], p->list[i].common_name); - if (!ifconfig_pool_release (p, array[i])) - break; - msg (M_INFO, "Succeeded"); - } - - CLEAR (array); - - msg (M_INFO | M_NOPREFIX, "**************** 3"); - for (i = 0; i < (int) SIZE (array); ++i) - { - char *cn; - ifconfig_pool_handle h; - in_addr_t local, remote; - char buf[256]; - snprintf (buf, sizeof(buf), "common-name-%d", i+24); -#ifdef DUP_CN - cn = NULL; -#else - cn = buf; -#endif - h = ifconfig_pool_acquire (p, &local, &remote, cn); - if (h < 0) - break; - msg (M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 3: l=%s r=%s cn=%s", - print_in_addr_t (local, 0, &gc), - print_in_addr_t (remote, 0, &gc), - cn); - array[i] = h; - - } - - ifconfig_pool_free (p); - gc_free (&gc); -} - -#endif - -#endif |