Moving attr-sql plugin from libstrongswan to libhydra.
authorTobias Brunner <tobias@strongswan.org>
Wed, 24 Mar 2010 09:59:31 +0000 (10:59 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 24 Mar 2010 17:53:09 +0000 (18:53 +0100)
18 files changed:
configure.in
src/libcharon/Makefile.am
src/libhydra/Makefile.am
src/libhydra/plugins/attr_sql/.gitignore [new file with mode: 0644]
src/libhydra/plugins/attr_sql/Makefile.am [new file with mode: 0644]
src/libhydra/plugins/attr_sql/attr_sql_plugin.c [new file with mode: 0644]
src/libhydra/plugins/attr_sql/attr_sql_plugin.h [new file with mode: 0644]
src/libhydra/plugins/attr_sql/pool.c [new file with mode: 0644]
src/libhydra/plugins/attr_sql/sql_attribute.c [new file with mode: 0644]
src/libhydra/plugins/attr_sql/sql_attribute.h [new file with mode: 0644]
src/libstrongswan/Makefile.am
src/libstrongswan/plugins/attr_sql/.gitignore [deleted file]
src/libstrongswan/plugins/attr_sql/Makefile.am [deleted file]
src/libstrongswan/plugins/attr_sql/attr_sql_plugin.c [deleted file]
src/libstrongswan/plugins/attr_sql/attr_sql_plugin.h [deleted file]
src/libstrongswan/plugins/attr_sql/pool.c [deleted file]
src/libstrongswan/plugins/attr_sql/sql_attribute.c [deleted file]
src/libstrongswan/plugins/attr_sql/sql_attribute.h [deleted file]

index d7a0b20..09fa8c3 100644 (file)
@@ -632,11 +632,12 @@ if test x$integrity_test = xtrue; then
        )
 fi
 
-dnl ======================================
-dnl  collect all plugins for libstrongswan
-dnl ======================================
+dnl ==========================================================
+dnl  collect all plugins for libstrongswan, libhydra and pluto
+dnl ==========================================================
 
 libstrongswan_plugins=
+libhydra_plugins=
 pluto_plugins=
 
 if test x$test_vectors = xtrue; then
@@ -714,10 +715,6 @@ if test x$sqlite = xtrue; then
        libstrongswan_plugins=${libstrongswan_plugins}" sqlite"
        pluto_plugins=${pluto_plugins}" sqlite"
 fi
-if test x$attr_sql = xtrue -o x$sql = xtrue; then
-       libstrongswan_plugins=${libstrongswan_plugins}" attr-sql"
-       pluto_plugins=${pluto_plugins}" attr-sql"
-fi
 if test x$padlock = xtrue; then
        libstrongswan_plugins=${libstrongswan_plugins}" padlock"
 fi
@@ -746,8 +743,13 @@ if test x$gmp = xtrue; then
        libstrongswan_plugins=${libstrongswan_plugins}" gmp"
        pluto_plugins=${pluto_plugins}" gmp"
 fi
+if test x$attr_sql = xtrue -o x$sql = xtrue; then
+       libhydra_plugins=${libhydra_plugins}" attr-sql"
+       pluto_plugins=${pluto_plugins}" attr-sql"
+fi
 
 AC_SUBST(libstrongswan_plugins)
+AC_SUBST(libhydra_plugins)
 AC_SUBST(pluto_plugins)
 
 dnl =========================
@@ -892,13 +894,13 @@ AC_OUTPUT(
        src/libstrongswan/plugins/ldap/Makefile
        src/libstrongswan/plugins/mysql/Makefile
        src/libstrongswan/plugins/sqlite/Makefile
-       src/libstrongswan/plugins/attr_sql/Makefile
        src/libstrongswan/plugins/padlock/Makefile
        src/libstrongswan/plugins/openssl/Makefile
        src/libstrongswan/plugins/gcrypt/Makefile
        src/libstrongswan/plugins/agent/Makefile
        src/libstrongswan/plugins/test_vectors/Makefile
        src/libhydra/Makefile
+       src/libhydra/plugins/attr_sql/Makefile
        src/libfreeswan/Makefile
        src/libsimaka/Makefile
        src/pluto/Makefile
index 274aa17..f8dd0e5 100644 (file)
@@ -133,7 +133,7 @@ else
 SUBDIRS = .
 endif
 
-PLUGINS = ${libstrongswan_plugins}
+PLUGINS = ${libstrongswan_plugins} ${libhydra_plugins}
 
 if USE_LOAD_TESTER
   SUBDIRS += plugins/load_tester
index 702ee3e..f558326 100644 (file)
@@ -21,10 +21,10 @@ else
 SUBDIRS = .
 endif
 
-#if USE_FOO
-#  SUBDIRS += plugins/foo
-#if MONOLITHIC
-#  libhydra_la_LIBADD += plugins/foo/libstrongswan-foo.la
-#endif
-#endif
+if USE_ATTR_SQL
+  SUBDIRS += plugins/attr_sql
+if MONOLITHIC
+  libhydra_la_LIBADD += plugins/attr_sql/libstrongswan-attr-sql.la
+endif
+endif
 
diff --git a/src/libhydra/plugins/attr_sql/.gitignore b/src/libhydra/plugins/attr_sql/.gitignore
new file mode 100644 (file)
index 0000000..eae4e6a
--- /dev/null
@@ -0,0 +1 @@
+pool
diff --git a/src/libhydra/plugins/attr_sql/Makefile.am b/src/libhydra/plugins/attr_sql/Makefile.am
new file mode 100644 (file)
index 0000000..9d73f2e
--- /dev/null
@@ -0,0 +1,22 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+       -rdynamic \
+       -DPLUGINS=\""${libstrongswan_plugins}\""
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-attr-sql.la
+else
+plugin_LTLIBRARIES = libstrongswan-attr-sql.la
+endif
+
+libstrongswan_attr_sql_la_SOURCES = \
+       attr_sql_plugin.h attr_sql_plugin.c \
+       sql_attribute.h sql_attribute.c
+
+libstrongswan_attr_sql_la_LDFLAGS = -module -avoid-version
+
+ipsec_PROGRAMS = pool
+pool_SOURCES = pool.c
+pool_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
diff --git a/src/libhydra/plugins/attr_sql/attr_sql_plugin.c b/src/libhydra/plugins/attr_sql/attr_sql_plugin.c
new file mode 100644 (file)
index 0000000..5d3d737
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include <library.h>
+#include <debug.h>
+
+#include "attr_sql_plugin.h"
+#include "sql_attribute.h"
+
+typedef struct private_attr_sql_plugin_t private_attr_sql_plugin_t;
+
+/**
+ * private data of attr_sql plugin
+ */
+struct private_attr_sql_plugin_t {
+
+       /**
+        * implements plugin interface
+        */
+       attr_sql_plugin_t public;
+
+       /**
+        * database connection instance
+        */
+       database_t *db;
+
+       /**
+        * configuration attributes
+        */
+       sql_attribute_t *attribute;
+
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_attr_sql_plugin_t *this)
+{
+       lib->attributes->remove_provider(lib->attributes, &this->attribute->provider);
+       this->attribute->destroy(this->attribute);
+       this->db->destroy(this->db);
+       free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *attr_sql_plugin_create()
+{
+       char *uri;
+       private_attr_sql_plugin_t *this;
+
+       uri = lib->settings->get_str(lib->settings, "libstrongswan.plugins.attr-sql.database", NULL);
+       if (!uri)
+       {
+               DBG1("attr-sql plugin: database URI not set");
+               return NULL;
+       }
+
+       this = malloc_thing(private_attr_sql_plugin_t);
+
+       this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+       this->db = lib->db->create(lib->db, uri);
+       if (!this->db)
+       {
+               DBG1("attr-sql plugin failed to connect to database");
+               free(this);
+               return NULL;
+       }
+       this->attribute = sql_attribute_create(this->db);
+       lib->attributes->add_provider(lib->attributes, &this->attribute->provider);
+
+       return &this->public.plugin;
+}
+
diff --git a/src/libhydra/plugins/attr_sql/attr_sql_plugin.h b/src/libhydra/plugins/attr_sql/attr_sql_plugin.h
new file mode 100644 (file)
index 0000000..12837ff
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup attr_sql attr_sql
+ * @ingroup plugins
+ *
+ * @defgroup sql_plugin sql_plugin
+ * @{ @ingroup attr_sql
+ */
+
+#ifndef ATTR_SQL_PLUGIN_H_
+#define ATTR_SQL_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct attr_sql_plugin_t attr_sql_plugin_t;
+
+/**
+ * SQL database attribute configuration plugin
+ */
+struct attr_sql_plugin_t {
+
+       /**
+        * implements plugin interface
+        */
+       plugin_t plugin;
+};
+
+#endif /** ATTR_SQL_PLUGIN_H_ @}*/
diff --git a/src/libhydra/plugins/attr_sql/pool.c b/src/libhydra/plugins/attr_sql/pool.c
new file mode 100644 (file)
index 0000000..5ecf80b
--- /dev/null
@@ -0,0 +1,1402 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+#include <debug.h>
+#include <library.h>
+#include <utils/host.h>
+#include <utils/identification.h>
+#include <attributes/attributes.h>
+
+/**
+ * global database handle
+ */
+database_t *db;
+
+/**
+ * --start/--end/--server addresses of various subcommands
+ */
+host_t *start = NULL, *end = NULL, *server = NULL;
+
+/**
+ * whether --add should --replace an existing pool
+ */
+bool replace_pool = FALSE;
+
+/**
+ * forward declarations
+ */
+static void del(char *name);
+static void do_args(int argc, char *argv[]);
+
+/**
+ * nesting counter for database transaction functions
+ */
+int nested_transaction = 0;
+
+/**
+ * start a database transaction
+ */
+static void begin_transaction()
+{
+       if (db->get_driver(db) == DB_SQLITE)
+       {
+               if (!nested_transaction)
+               {
+                       db->execute(db, NULL, "BEGIN EXCLUSIVE TRANSACTION");
+               }
+               ++nested_transaction;
+       }
+}
+
+/**
+ * commit a database transaction
+ */
+static void commit_transaction()
+{
+       if (db->get_driver(db) == DB_SQLITE)
+       {
+               --nested_transaction;
+               if (!nested_transaction)
+               {
+                       db->execute(db, NULL, "END TRANSACTION");
+               }
+       }
+}
+
+/**
+ * Create or replace a pool by name
+ */
+static u_int create_pool(char *name, chunk_t start, chunk_t end, int timeout)
+{
+       enumerator_t *e;
+       int pool;
+
+       e = db->query(db, "SELECT id FROM pools WHERE name = ?",
+                       DB_TEXT, name, DB_UINT);
+       if (e && e->enumerate(e, &pool))
+       {
+               if (replace_pool == FALSE)
+               {
+                       fprintf(stderr, "pool '%s' exists.\n", name);
+                       e->destroy(e);
+                       exit(EXIT_FAILURE);
+               }
+               del(name);
+       }
+       DESTROY_IF(e);
+       if (db->execute(db, &pool,
+                       "INSERT INTO pools (name, start, end, timeout) VALUES (?, ?, ?, ?)",
+                       DB_TEXT, name, DB_BLOB, start, DB_BLOB, end,
+                       DB_INT, timeout*3600) != 1)
+       {
+               fprintf(stderr, "creating pool failed.\n");
+               exit(EXIT_FAILURE);
+       }
+
+       return pool;
+}
+
+/**
+ * instead of a pool handle a DNS or NBNS attribute
+ */
+static bool is_attribute(char *name)
+{
+       return strcaseeq(name, "dns") || strcaseeq(name, "nbns") ||
+                  strcaseeq(name, "wins");
+}
+
+/**
+ * determine configuration attribute type
+ */
+static configuration_attribute_type_t get_attribute_type(char *name, host_t* addr)
+{
+       if (strcaseeq(name, "dns"))
+       {
+               return (addr->get_family(addr) == AF_INET) ? INTERNAL_IP4_DNS :
+                                                                                                        INTERNAL_IP6_DNS;
+       }
+       else
+       {
+               return (addr->get_family(addr) == AF_INET) ? INTERNAL_IP4_NBNS :
+                                                                                                        INTERNAL_IP6_NBNS;
+       }
+}
+
+/**
+ * calculate the size of a pool using start and end address chunk
+ */
+static u_int get_pool_size(chunk_t start, chunk_t end)
+{
+       u_int *start_ptr, *end_ptr;
+
+       if (start.len < sizeof(u_int) || end.len < sizeof(u_int))
+       {
+               return 0;
+       }
+       start_ptr = (u_int*)(start.ptr + start.len - sizeof(u_int));
+       end_ptr = (u_int*)(end.ptr + end.len - sizeof(u_int));
+       return ntohl(*end_ptr) -  ntohl(*start_ptr) + 1;
+}
+
+/**
+ * print usage info
+ */
+static void usage(void)
+{
+       printf("\
+Usage:\n\
+  ipsec pool --status|--add|--replace|--del|--resize|--purge [options]\n\
+  \n\
+  ipsec pool --status\n\
+    Show a list of installed pools with statistics.\n\
+  \n\
+  ipsec pool --add <name> --start <start> --end <end> [--timeout <timeout>]\n\
+  ipsec pool --replace <name> --start <start> --end <end> [--timeout <timeout>]\n\
+    Add a new pool to or replace an existing pool in the database.\n\
+      name:    Name of the pool, as used in ipsec.conf rightsourceip=%%name\n\
+      start:   Start address of the pool\n\
+      end:     End address of the pool\n\
+      timeout: Lease time in hours, 0 for static leases\n\
+  \n\
+  ipsec pool --add <name> --addresses <file> [--timeout <timeout>]\n\
+  ipsec pool --replace <name> --addresses <file> [--timeout <timeout>]\n\
+    Add a new pool to or replace an existing pool in the database.\n\
+      name:    Name of the pool, as used in ipsec.conf rightsourceip=%%name\n\
+      file:    File newline separated addresses for the pool are read from.\n\
+               Optionally each address can be pre-assigned to a roadwarrior\n\
+               identity, e.g. 10.231.14.2=alice@strongswan.org.\n\
+               If a - (hyphen) is given instead of a file name, the addresses\n\
+               are read from STDIN. Reading addresses stops at the end of file\n\
+               or an empty line. Pools created with this command can not be\n\
+               resized.\n\
+      timeout: Lease time in hours, 0 for static leases\n\
+  \n\
+  ipsec pool --add dns|nbns|wins --server <server>\n\
+    Add a new DNS or NBNS server to the database.\n\
+      server:  IP address of the name server\n\
+  \n\
+  ipsec pool --del <name>\n\
+    Delete a pool from the database.\n\
+      name:    Name of the pool to delete\n\
+  \n\
+  ipsec pool --del dns|nbns|wins [--server <server>]\n\
+    Delete a specific or all DNS or NBNS servers from the database.\n\
+      server:  IP address of the name server to delete\n\
+  \n\
+  ipsec pool --resize <name> --end <end>\n\
+    Grow or shrink an existing pool.\n\
+      name:    Name of the pool to resize\n\
+      end:     New end address for the pool\n\
+  \n\
+  ipsec pool --leases [--filter <filter>] [--utc]\n\
+    Show lease information using filters:\n\
+      filter:  Filter string containing comma separated key=value filters,\n\
+               e.g. id=alice@strongswan.org,addr=1.1.1.1\n\
+                  pool:   name of the pool\n\
+                  id:     assigned identity of the lease\n\
+                  addr:   lease IP address\n\
+                  tstamp: UNIX timestamp when lease was valid, as integer\n\
+                  status: status of the lease: online|valid|expired\n\
+      utc:    Show times in UTC instead of local time\n\
+  \n\
+  ipsec pool --purge <name>\n\
+    Delete lease history of a pool:\n\
+      name:    Name of the pool to purge\n\
+  \n\
+  ipsec pool --batch <file>\n\
+    Read commands from a file and execute them atomically.\n\
+      file:    File to read the newline separated commands from. Commands\n\
+               appear as they are written on the command line, e.g.\n\
+                  --replace mypool --start 10.0.0.1 --end 10.0.0.254\n\
+                  --del dns\n\
+                  --add dns --server 10.1.0.1\n\
+                  --add dns --server 10.1.1.1\n\
+               If a - (hyphen) is given as a file name, the commands are read\n\
+               from STDIN. Readin commands stops at the end of file. Empty\n\
+               lines are ignored. The file may not contain a --batch command.\n\
+  \n");
+}
+
+/**
+ * ipsec pool --status - show pool overview
+ */
+static void status(void)
+{
+       enumerator_t *ns, *pool, *lease;
+       host_t *server;
+       chunk_t value;
+       bool found = FALSE;
+
+       /* enumerate IPv4 DNS servers */
+       ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
+                                  DB_INT, INTERNAL_IP4_DNS, DB_BLOB);
+       if (ns)
+       {
+               while (ns->enumerate(ns, &value))
+               {
+                       if (!found)
+                       {
+                               printf("dns servers:");
+                               found = TRUE;
+                       }
+                       server = host_create_from_chunk(AF_INET, value, 0);
+                       if (server)
+                       {
+                               printf(" %H", server);
+                               server->destroy(server);
+                       }
+               }
+               ns->destroy(ns);
+       }
+
+       /* enumerate IPv6 DNS servers */
+       ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
+                                  DB_INT, INTERNAL_IP6_DNS, DB_BLOB);
+       if (ns)
+       {
+               while (ns->enumerate(ns, &value))
+               {
+                       if (!found)
+                       {
+                               printf("dns servers:");
+                               found = TRUE;
+                       }
+                       server = host_create_from_chunk(AF_INET6, value, 0);
+                       if (server)
+                       {
+                               printf(" %H", server);
+                               server->destroy(server);
+                       }
+               }
+               ns->destroy(ns);
+       }
+       if (found)
+       {
+               printf("\n");
+       }
+       else
+       {
+               printf("no dns servers found.\n");
+       }
+       found = FALSE;
+
+       /* enumerate IPv4 NBNS servers */
+       ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
+                                  DB_INT, INTERNAL_IP4_NBNS, DB_BLOB);
+       if (ns)
+       {
+               while (ns->enumerate(ns, &value))
+               {
+                       if (!found)
+                       {
+                               printf("nbns servers:");
+                               found = TRUE;
+                       }
+                       server = host_create_from_chunk(AF_INET, value, 0);
+                       if (server)
+                       {
+                               printf(" %H", server);
+                               server->destroy(server);
+                       }
+               }
+               ns->destroy(ns);
+       }
+
+       /* enumerate IPv6 NBNS servers */
+       ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
+                                  DB_INT, INTERNAL_IP6_NBNS, DB_BLOB);
+       if (ns)
+       {
+               while (ns->enumerate(ns, &value))
+               {
+                       if (!found)
+                       {
+                               printf("nbns servers:");
+                               found = TRUE;
+                       }
+                       server = host_create_from_chunk(AF_INET6, value, 0);
+                       if (server)
+                       {
+                               printf(" %H", server);
+                               server->destroy(server);
+                       }
+               }
+               ns->destroy(ns);
+       }
+       if (found)
+       {
+               printf("\n");
+       }
+       else
+       {
+               printf("no nbns servers found.\n");
+       }
+       found = FALSE;
+
+       pool = db->query(db, "SELECT id, name, start, end, timeout FROM pools",
+                                        DB_INT, DB_TEXT, DB_BLOB, DB_BLOB, DB_UINT);
+       if (pool)
+       {
+               char *name;
+               chunk_t start_chunk, end_chunk;
+               host_t *start, *end;
+               u_int id, timeout, online = 0, used = 0, size = 0;
+
+               while (pool->enumerate(pool, &id, &name,
+                                                          &start_chunk, &end_chunk, &timeout))
+               {
+                       if (!found)
+                       {
+                               printf("%8s %15s %15s %8s %6s %11s %11s\n", "name", "start",
+                                          "end", "timeout", "size", "online", "usage");
+                               found = TRUE;
+                       }
+
+                       start = host_create_from_chunk(AF_UNSPEC, start_chunk, 0);
+                       end = host_create_from_chunk(AF_UNSPEC, end_chunk, 0);
+                       if (start->is_anyaddr(start) && end->is_anyaddr(end))
+                       {
+                               printf("%8s %15s %15s ", name, "n/a", "n/a");
+                       }
+                       else
+                       {
+                               printf("%8s %15H %15H ", name, start, end);
+                       }
+                       if (timeout)
+                       {
+                               printf("%7dh ", timeout/3600);
+                       }
+                       else
+                       {
+                               printf("%8s ", "static");
+                       }
+                       /* get total number of hosts in the pool */
+                       lease = db->query(db, "SELECT COUNT(*) FROM addresses "
+                                                         "WHERE pool = ?", DB_UINT, id, DB_INT);
+                       if (lease)
+                       {
+                               lease->enumerate(lease, &size);
+                               lease->destroy(lease);
+                       }
+                       printf("%6d ", size);
+                       /* get number of online hosts */
+                       lease = db->query(db, "SELECT COUNT(*) FROM addresses "
+                                                         "WHERE pool = ? AND released = 0",
+                                                         DB_UINT, id, DB_INT);
+                       if (lease)
+                       {
+                               lease->enumerate(lease, &online);
+                               lease->destroy(lease);
+                       }
+                       printf("%5d (%2d%%) ", online, online*100/size);
+                       /* get number of online or valid lieases */
+                       lease = db->query(db, "SELECT COUNT(*) FROM addresses "
+                                                         "WHERE addresses.pool = ? "
+                                                         "AND ((? AND acquired != 0) "
+                                                         "     OR released = 0 OR released > ?) ",
+                                                         DB_UINT, id, DB_UINT, !timeout,
+                                                         DB_UINT, time(NULL) - timeout, DB_UINT);
+                       if (lease)
+                       {
+                               lease->enumerate(lease, &used);
+                               lease->destroy(lease);
+                       }
+                       printf("%5d (%2d%%) ", used, used*100/size);
+
+                       printf("\n");
+                       DESTROY_IF(start);
+                       DESTROY_IF(end);
+               }
+               pool->destroy(pool);
+       }
+       if (!found)
+       {
+               printf("no pools found.\n");
+       }
+}
+
+/**
+ * ipsec pool --add - add a new pool
+ */
+static void add(char *name, host_t *start, host_t *end, int timeout)
+{
+       chunk_t start_addr, end_addr, cur_addr;
+       u_int id, count;
+
+       start_addr = start->get_address(start);
+       end_addr = end->get_address(end);
+       cur_addr = chunk_clonea(start_addr);
+       count = get_pool_size(start_addr, end_addr);
+
+       if (start_addr.len != end_addr.len ||
+               memcmp(start_addr.ptr, end_addr.ptr, start_addr.len) > 0)
+       {
+               fprintf(stderr, "invalid start/end pair specified.\n");
+               exit(EXIT_FAILURE);
+       }
+       id = create_pool(name, start_addr, end_addr, timeout);
+       printf("allocating %d addresses... ", count);
+       fflush(stdout);
+       /* run population in a transaction for sqlite */
+       begin_transaction();
+       while (TRUE)
+       {
+               db->execute(db, NULL,
+                       "INSERT INTO addresses (pool, address, identity, acquired, released) "
+                       "VALUES (?, ?, ?, ?, ?)",
+                       DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
+               if (chunk_equals(cur_addr, end_addr))
+               {
+                       break;
+               }
+               chunk_increment(cur_addr);
+       }
+       commit_transaction();
+       printf("done.\n", count);
+}
+
+static bool add_address(u_int pool_id, char *address_str, int *family)
+{
+       host_t *address;
+       int user_id = 0;
+
+       char *pos_eq = strchr(address_str, '=');
+       if (pos_eq != NULL)
+       {
+               enumerator_t *e;
+               identification_t *id = identification_create_from_string(pos_eq + 1);
+
+               /* look for peer identity in the identities table */
+               e = db->query(db,
+                               "SELECT id FROM identities WHERE type = ? AND data = ?",
+                               DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
+                               DB_UINT);
+
+               if (!e || !e->enumerate(e, &user_id))
+               {
+                       /* not found, insert new one */
+                       if (db->execute(db, &user_id,
+                                       "INSERT INTO identities (type, data) VALUES (?, ?)",
+                                       DB_INT, id->get_type(id),
+                                       DB_BLOB, id->get_encoding(id)) != 1)
+                       {
+                               fprintf(stderr, "creating id '%s' failed.\n", pos_eq + 1);
+                               return FALSE;
+                       }
+               }
+               DESTROY_IF(e);
+               id->destroy(id);
+               *pos_eq = '\0';
+       }
+
+       address = host_create_from_string(address_str, 0);
+       if (address == NULL)
+       {
+               fprintf(stderr, "invalid address '%s'.\n", address_str);
+               return FALSE;
+       }
+       if (family && *family && *family != address->get_family(address))
+       {
+               fprintf(stderr, "invalid address family '%s'.\n", address_str);
+               return FALSE;
+       }
+
+       if (db->execute(db, NULL,
+                       "INSERT INTO addresses "
+                       "(pool, address, identity, acquired, released) "
+                       "VALUES (?, ?, ?, ?, ?)",
+                       DB_UINT, pool_id, DB_BLOB, address->get_address(address),
+                       DB_UINT, user_id, DB_UINT, 0, DB_UINT, 1) != 1)
+       {
+               fprintf(stderr, "inserting address '%s' failed.\n", address_str);
+               return FALSE;
+       }
+       *family = address->get_family(address);
+       address->destroy(address);
+
+       return TRUE;
+}
+
+static void add_addresses(char *pool, char *path, int timeout)
+{
+       u_int pool_id, count = 0;
+       int family = AF_UNSPEC;
+       char address_str[512];
+       host_t *addr;
+       FILE *file;
+
+       /* run population in a transaction for sqlite */
+       begin_transaction();
+
+       addr = host_create_from_string("%any", 0);
+       pool_id = create_pool(pool, addr->get_address(addr),
+                                                 addr->get_address(addr), timeout);
+       addr->destroy(addr);
+
+       file = (strcmp(path, "-") == 0 ? stdin : fopen(path, "r"));
+       if (file == NULL)
+       {
+               fprintf(stderr, "opening '%s' failed: %s\n", path, strerror(errno));
+               exit(-1);
+       }
+
+       printf("starting allocation... ");
+       fflush(stdout);
+
+       while (fgets(address_str, sizeof(address_str), file))
+       {
+               size_t addr_len = strlen(address_str);
+               char *last_chr = address_str + addr_len - 1;
+               if (*last_chr == '\n')
+               {
+                       if (addr_len == 1)
+                       {       /* end of input */
+                               break;
+                       }
+                       *last_chr = '\0';
+               }
+               if (add_address(pool_id, address_str, &family) == FALSE)
+               {
+                       exit(EXIT_FAILURE);
+               }
+               ++count;
+       }
+
+       if (file != stdin)
+       {
+               fclose(file);
+       }
+
+       commit_transaction();
+
+       printf("%d addresses done.\n", count);
+}
+
+/**
+ * ipsec pool --add dns|nbns|wins - add a DNS or NBNS server entry
+ */
+static void add_attr(char *name, host_t *server)
+{
+       configuration_attribute_type_t type;
+       chunk_t value;
+
+       type = get_attribute_type(name, server);
+       value = server->get_address(server);
+       if (db->execute(db, NULL,
+                       "INSERT INTO attributes (type, value) VALUES (?, ?)",
+                       DB_INT, type, DB_BLOB, value) != 1)
+       {
+               fprintf(stderr, "adding %s server %H failed.\n", name, server);
+               exit(EXIT_FAILURE);
+       }
+       printf("added %s server %H\n", name, server);
+}
+
+/**
+ * ipsec pool --del - delete a pool
+ */
+static void del(char *name)
+{
+       enumerator_t *query;
+       u_int id;
+       bool found = FALSE;
+
+       query = db->query(db, "SELECT id FROM pools WHERE name = ?",
+                                         DB_TEXT, name, DB_UINT);
+       if (!query)
+       {
+               fprintf(stderr, "deleting pool failed.\n");
+               exit(EXIT_FAILURE);
+       }
+       while (query->enumerate(query, &id))
+       {
+               found = TRUE;
+               if (db->execute(db, NULL,
+                               "DELETE FROM leases WHERE address IN ("
+                               " SELECT id FROM addresses WHERE pool = ?)", DB_UINT, id) < 0 ||
+                       db->execute(db, NULL,
+                               "DELETE FROM addresses WHERE pool = ?", DB_UINT, id) < 0 ||
+                       db->execute(db, NULL,
+                               "DELETE FROM pools WHERE id = ?", DB_UINT, id) < 0)
+               {
+                       fprintf(stderr, "deleting pool failed.\n");
+                       query->destroy(query);
+                       exit(EXIT_FAILURE);
+               }
+       }
+       query->destroy(query);
+       if (!found)
+       {
+               fprintf(stderr, "pool '%s' not found.\n", name);
+               exit(EXIT_FAILURE);
+       }
+}
+
+/**
+ * ipsec pool --del dns|nbns|wins - delete a DNS or NBNS server entry
+ */
+static void del_attr(char *name, host_t *server)
+{
+       configuration_attribute_type_t type;
+       chunk_t value;
+       u_int id;
+       enumerator_t *query;
+       bool found = FALSE;
+
+       if (server)
+       {
+               type = get_attribute_type(name, server);
+               value = server->get_address(server);
+               query = db->query(db,
+                                       "SELECT id, type, value FROM attributes "
+                                       "WHERE type = ? AND value = ?",
+                                       DB_INT, type, DB_BLOB, value,
+                                       DB_UINT, DB_INT, DB_BLOB);
+       }
+       else
+       {
+               configuration_attribute_type_t type_ip4, type_ip6;
+
+               if (strcaseeq(name, "dns"))
+               {
+                       type_ip4 = INTERNAL_IP4_DNS;
+                       type_ip6 = INTERNAL_IP6_DNS;
+               }
+               else
+               {
+                       type_ip4 = INTERNAL_IP4_NBNS;
+                       type_ip6 = INTERNAL_IP6_NBNS;
+               }
+
+               query = db->query(db,
+                                       "SELECT id, type, value FROM attributes "
+                                       "WHERE type = ? OR type = ?",
+                                       DB_INT, type_ip4, DB_INT, type_ip6,
+                                       DB_UINT, DB_INT, DB_BLOB);
+       }
+       if (!query)
+       {
+               fprintf(stderr, "deleting %s servers failed.\n", name);
+               exit(EXIT_FAILURE);
+       }
+
+       while (query->enumerate(query, &id, &type, &value))
+       {
+               int family;
+               host_t *host;
+
+               found = TRUE;
+               family = (type == INTERNAL_IP4_DNS || type == INTERNAL_IP4_NBNS) ?
+                                 AF_INET : AF_INET6;
+               host = host_create_from_chunk(family, value, 0);
+               if (db->execute(db, NULL,
+                                       "DELETE FROM attributes WHERE id = ?",
+                                        DB_UINT, id) != 1)
+               {
+                       fprintf(stderr, "deleting %s server %H failed\n", name, host);
+                       query->destroy(query);
+                       DESTROY_IF(host);
+                       exit(EXIT_FAILURE);
+               }
+               printf("deleted %s server %H\n", name, host);
+               DESTROY_IF(host);
+       }
+       query->destroy(query);
+
+       if (!found && server)
+       {
+               printf("%s server %H not found\n", name, server);
+               exit(EXIT_FAILURE);
+       }
+       else if (!found)
+       {
+               printf("no %s servers found\n", name);
+       }
+}
+
+/**
+ * ipsec pool --resize - resize a pool
+ */
+static void resize(char *name, host_t *end)
+{
+       enumerator_t *query;
+       chunk_t old_addr, new_addr, cur_addr;
+       u_int id, count;
+       host_t *old_end;
+
+       new_addr = end->get_address(end);
+
+       query = db->query(db, "SELECT id, end FROM pools WHERE name = ?",
+                                         DB_TEXT, name, DB_UINT, DB_BLOB);
+       if (!query || !query->enumerate(query, &id, &old_addr))
+       {
+               DESTROY_IF(query);
+               fprintf(stderr, "resizing pool failed.\n");
+               exit(EXIT_FAILURE);
+       }
+       if (old_addr.len != new_addr.len ||
+               memcmp(new_addr.ptr, old_addr.ptr, old_addr.len) < 0)
+       {
+               fprintf(stderr, "shrinking of pools not supported.\n");
+               query->destroy(query);
+               exit(EXIT_FAILURE);
+       }
+       cur_addr = chunk_clonea(old_addr);
+       count = get_pool_size(old_addr, new_addr) - 1;
+       query->destroy(query);
+
+       /* Check whether pool is resizable */
+       old_end = host_create_from_chunk(AF_UNSPEC, old_addr, 0);
+       if (old_end && old_end->is_anyaddr(old_end))
+       {
+               fprintf(stderr, "pool is not resizable.\n");
+               old_end->destroy(old_end);
+               exit(EXIT_FAILURE);
+       }
+       DESTROY_IF(old_end);
+
+       if (db->execute(db, NULL,
+                       "UPDATE pools SET end = ? WHERE name = ?",
+                       DB_BLOB, new_addr, DB_TEXT, name) <= 0)
+       {
+               fprintf(stderr, "pool '%s' not found.\n", name);
+               exit(EXIT_FAILURE);
+       }
+
+       printf("allocating %d new addresses... ", count);
+       fflush(stdout);
+       /* run population in a transaction for sqlite */
+       begin_transaction();
+       while (count-- > 0)
+       {
+               chunk_increment(cur_addr);
+               db->execute(db, NULL,
+                       "INSERT INTO addresses (pool, address, identity, acquired, released) "
+                       "VALUES (?, ?, ?, ?, ?)",
+                       DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
+       }
+       commit_transaction();
+       printf("done.\n", count);
+
+}
+
+/**
+ * create the lease query using the filter string
+ */
+static enumerator_t *create_lease_query(char *filter)
+{
+       enumerator_t *query;
+       identification_t *id = NULL;
+       host_t *addr = NULL;
+       u_int tstamp = 0;
+       bool online = FALSE, valid = FALSE, expired = FALSE;
+       char *value, *pos, *pool = NULL;
+       enum {
+               FIL_POOL = 0,
+               FIL_ID,
+               FIL_ADDR,
+               FIL_TSTAMP,
+               FIL_STATE,
+       };
+       char *const token[] = {
+               [FIL_POOL] = "pool",
+               [FIL_ID] = "id",
+               [FIL_ADDR] = "addr",
+               [FIL_TSTAMP] = "tstamp",
+               [FIL_STATE] = "status",
+               NULL
+       };
+
+       /* if the filter string contains a distinguished name as a ID, we replace
+        * ", " by "/ " in order to not confuse the getsubopt parser */
+       pos = filter;
+       while ((pos = strchr(pos, ',')))
+       {
+               if (pos[1] == ' ')
+               {
+                       pos[0] = '/';
+               }
+               pos++;
+       }
+
+       while (filter && *filter != '\0')
+       {
+               switch (getsubopt(&filter, token, &value))
+               {
+                       case FIL_POOL:
+                               if (value)
+                               {
+                                       pool = value;
+                               }
+                               break;
+                       case FIL_ID:
+                               if (value)
+                               {
+                                       id = identification_create_from_string(value);
+                               }
+                               break;
+                       case FIL_ADDR:
+                               if (value)
+                               {
+                                       addr = host_create_from_string(value, 0);
+                               }
+                               if (!addr)
+                               {
+                                       fprintf(stderr, "invalid 'addr' in filter string.\n");
+                                       exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case FIL_TSTAMP:
+                               if (value)
+                               {
+                                       tstamp = atoi(value);
+                               }
+                               if (tstamp == 0)
+                               {
+                                       online = TRUE;
+                               }
+                               break;
+                       case FIL_STATE:
+                               if (value)
+                               {
+                                       if (streq(value, "online"))
+                                       {
+                                               online = TRUE;
+                                       }
+                                       else if (streq(value, "valid"))
+                                       {
+                                               valid = TRUE;
+                                       }
+                                       else if (streq(value, "expired"))
+                                       {
+                                               expired = TRUE;
+                                       }
+                                       else
+                                       {
+                                               fprintf(stderr, "invalid 'state' in filter string.\n");
+                                               exit(EXIT_FAILURE);
+                                       }
+                               }
+                               break;
+                       default:
+                               fprintf(stderr, "invalid filter string.\n");
+                               exit(EXIT_FAILURE);
+                               break;
+               }
+       }
+       query = db->query(db,
+                               "SELECT name, addresses.address, identities.type, "
+                               "identities.data, leases.acquired, leases.released, timeout "
+                               "FROM leases JOIN addresses ON leases.address = addresses.id "
+                               "JOIN pools ON addresses.pool = pools.id "
+                               "JOIN identities ON leases.identity = identities.id "
+                               "WHERE (? OR name = ?) "
+                               "AND (? OR (identities.type = ? AND identities.data = ?)) "
+                               "AND (? OR addresses.address = ?) "
+                               "AND (? OR (? >= leases.acquired AND (? <= leases.released))) "
+                               "AND (? OR leases.released > ? - timeout) "
+                               "AND (? OR leases.released < ? - timeout) "
+                               "AND ? "
+                               "UNION "
+                               "SELECT name, address, identities.type, identities.data, "
+                               "acquired, released, timeout FROM addresses "
+                               "JOIN pools ON addresses.pool = pools.id "
+                               "JOIN identities ON addresses.identity = identities.id "
+                               "WHERE ? AND released = 0 "
+                               "AND (? OR name = ?) "
+                               "AND (? OR (identities.type = ? AND identities.data = ?)) "
+                               "AND (? OR address = ?)",
+                               DB_INT, pool == NULL, DB_TEXT, pool,
+                               DB_INT, id == NULL,
+                                       DB_INT, id ? id->get_type(id) : 0,
+                                       DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
+                               DB_INT, addr == NULL,
+                                       DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
+                               DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp,
+                               DB_INT, !valid, DB_INT, time(NULL),
+                               DB_INT, !expired, DB_INT, time(NULL),
+                               DB_INT, !online,
+                               /* union */
+                               DB_INT, !(valid || expired),
+                               DB_INT, pool == NULL, DB_TEXT, pool,
+                               DB_INT, id == NULL,
+                                       DB_INT, id ? id->get_type(id) : 0,
+                                       DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
+                               DB_INT, addr == NULL,
+                                       DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
+                               /* res */
+                               DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT);
+       /* id and addr leak but we can't destroy them until query is destroyed. */
+       return query;
+}
+
+/**
+ * ipsec pool --leases - show lease information of a pool
+ */
+static void leases(char *filter, bool utc)
+{
+       enumerator_t *query;
+       chunk_t address_chunk, identity_chunk;
+       int identity_type;
+       char *name;
+       u_int db_acquired, db_released, db_timeout;
+       time_t acquired, released, timeout;
+       host_t *address;
+       identification_t *identity;
+       bool found = FALSE;
+
+       query = create_lease_query(filter);
+       if (!query)
+       {
+               fprintf(stderr, "querying leases failed.\n");
+               exit(EXIT_FAILURE);
+       }
+       while (query->enumerate(query, &name, &address_chunk, &identity_type,
+                                                       &identity_chunk, &db_acquired, &db_released, &db_timeout))
+       {
+               if (!found)
+               {
+                       int len = utc ? 25 : 21;
+
+                       found = TRUE;
+                       printf("%-8s %-15s %-7s  %-*s %-*s %s\n",
+                                  "name", "address", "status", len, "start", len, "end", "identity");
+               }
+               address = host_create_from_chunk(AF_UNSPEC, address_chunk, 0);
+               identity = identification_create_from_encoding(identity_type, identity_chunk);
+
+               /* u_int is not always equal to time_t */
+               acquired = (time_t)db_acquired;
+               released = (time_t)db_released;
+               timeout  = (time_t)db_timeout;
+
+               printf("%-8s %-15H ", name, address);
+               if (released == 0)
+               {
+                       printf("%-7s ", "online");
+               }
+               else if (timeout == 0)
+               {
+                       printf("%-7s ", "static");
+               }
+               else if (released >= time(NULL) - timeout)
+               {
+                       printf("%-7s ", "valid");
+               }
+               else
+               {
+                       printf("%-7s ", "expired");
+               }
+
+               printf(" %T  ", &acquired, utc);
+               if (released)
+               {
+                       printf("%T  ", &released, utc);
+               }
+               else
+               {
+                       printf("                      ");
+                       if (utc)
+                       {
+                               printf("    ");
+                       }
+               }
+               printf("%Y\n", identity);
+               DESTROY_IF(address);
+               identity->destroy(identity);
+       }
+       query->destroy(query);
+       if (!found)
+       {
+               fprintf(stderr, "no matching leases found.\n");
+               exit(EXIT_FAILURE);
+       }
+}
+
+/**
+ * ipsec pool --purge - delete expired leases
+ */
+static void purge(char *name)
+{
+       int purged = 0;
+
+       purged = db->execute(db, NULL,
+                               "DELETE FROM leases WHERE address IN ("
+                               " SELECT id FROM addresses WHERE pool IN ("
+                               "  SELECT id FROM pools WHERE name = ?))",
+                               DB_TEXT, name);
+       if (purged < 0)
+       {
+               fprintf(stderr, "purging pool '%s' failed.\n", name);
+               exit(EXIT_FAILURE);
+       }
+       fprintf(stderr, "purged %d leases in pool '%s'.\n", purged, name);
+}
+
+#define ARGV_SIZE 32
+
+static void argv_add(char **argv, int argc, char *value)
+{
+       if (argc >= ARGV_SIZE)
+       {
+               fprintf(stderr, "too many arguments: %s\n", value);
+               exit(EXIT_FAILURE);
+       }
+       argv[argc] = value;
+}
+
+/**
+ * ipsec pool --batch - read commands from a file
+ */
+static void batch(char *argv0, char *name)
+{
+       char command[512];
+
+       FILE *file = strncmp(name, "-", 1) == 0 ? stdin : fopen(name, "r");
+       if (file == NULL)
+       {
+               fprintf(stderr, "opening '%s' failed: %s\n", name, strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       begin_transaction();
+       while (fgets(command, sizeof(command), file))
+       {
+               char *argv[ARGV_SIZE], *start;
+               int i, argc = 0;
+               size_t cmd_len = strlen(command);
+
+               /* ignore empty lines */
+               if (cmd_len == 1 && *(command + cmd_len - 1) == '\n')
+               {
+                       continue;
+               }
+
+               /* parse command into argv */
+               start = command;
+               argv_add(argv, argc++, argv0);
+               for (i = 0; i < cmd_len; ++i)
+               {
+                       if (command[i] == ' ' || command[i] == '\n')
+                       {
+                               if (command + i == start)
+                               {
+                                       /* ignore leading whitespace */
+                                       ++start;
+                                       continue;
+                               }
+                               command[i] = '\0';
+                               argv_add(argv, argc++, start);
+                               start = command + i + 1;
+                       }
+               }
+               if (strlen(start) > 0)
+               {
+                       argv_add(argv, argc++, start);
+               }
+               argv_add(argv, argc, NULL);
+
+               do_args(argc, argv);
+       }
+       commit_transaction();
+
+       if (file != stdin)
+       {
+               fclose(file);
+       }
+}
+
+/**
+ * atexit handler to close db on shutdown
+ */
+static void cleanup(void)
+{
+       db->destroy(db);
+       DESTROY_IF(start);
+       DESTROY_IF(end);
+       DESTROY_IF(server);
+}
+
+static void do_args(int argc, char *argv[])
+{
+       char *name = "", *filter = "", *addresses = NULL;
+       int timeout = 0;
+       bool utc = FALSE;
+       enum {
+               OP_UNDEF,
+               OP_USAGE,
+               OP_STATUS,
+               OP_ADD,
+               OP_ADD_ATTR,
+               OP_DEL,
+               OP_DEL_ATTR,
+               OP_RESIZE,
+               OP_LEASES,
+               OP_PURGE,
+               OP_BATCH
+       } operation = OP_UNDEF;
+
+       /* reinit getopt state */
+       optind = 0;
+
+       while (TRUE)
+       {
+               int c;
+
+               struct option long_opts[] = {
+                       { "help", no_argument, NULL, 'h' },
+
+                       { "utc", no_argument, NULL, 'u' },
+                       { "status", no_argument, NULL, 'w' },
+                       { "add", required_argument, NULL, 'a' },
+                       { "replace", required_argument, NULL, 'c' },
+                       { "del", required_argument, NULL, 'd' },
+                       { "resize", required_argument, NULL, 'r' },
+                       { "leases", no_argument, NULL, 'l' },
+                       { "purge", required_argument, NULL, 'p' },
+                       { "batch", required_argument, NULL, 'b' },
+
+                       { "start", required_argument, NULL, 's' },
+                       { "end", required_argument, NULL, 'e' },
+                       { "addresses", required_argument, NULL, 'x' },
+                       { "timeout", required_argument, NULL, 't' },
+                       { "filter", required_argument, NULL, 'f' },
+                       { "server", required_argument, NULL, 'v' },
+                       { 0,0,0,0 }
+               };
+
+               c = getopt_long(argc, argv, "", long_opts, NULL);
+               switch (c)
+               {
+                       case EOF:
+                               break;
+                       case 'h':
+                               operation = OP_USAGE;
+                               break;
+                       case 'w':
+                               operation = OP_STATUS;
+                               break;
+                       case 'u':
+                               utc = TRUE;
+                               continue;
+                       case 'c':
+                               replace_pool = TRUE;
+                               /* fallthrough */
+                       case 'a':
+                               name = optarg;
+                               operation = is_attribute(name) ? OP_ADD_ATTR : OP_ADD;
+                               if (replace_pool && operation == OP_ADD_ATTR)
+                               {
+                                       fprintf(stderr, "invalid pool name: '%s'.\n", optarg);
+                                       usage();
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
+                       case 'd':
+                               name = optarg;
+                               operation = is_attribute(name) ? OP_DEL_ATTR : OP_DEL;
+                               continue;
+                       case 'r':
+                               name = optarg;
+                               operation = OP_RESIZE;
+                               continue;
+                       case 'l':
+                               operation = OP_LEASES;
+                               continue;
+                       case 'p':
+                               name = optarg;
+                               operation = OP_PURGE;
+                               continue;
+                       case 'b':
+                               name = optarg;
+                               if (operation == OP_BATCH)
+                               {
+                                       fprintf(stderr, "--batch commands can not be nested\n");
+                                       exit(EXIT_FAILURE);
+                               }
+                               operation = OP_BATCH;
+                               continue;
+                       case 's':
+                               DESTROY_IF(start);
+                               start = host_create_from_string(optarg, 0);
+                               if (start == NULL)
+                               {
+                                       fprintf(stderr, "invalid start address: '%s'.\n", optarg);
+                                       usage();
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
+                       case 'e':
+                               DESTROY_IF(end);
+                               end = host_create_from_string(optarg, 0);
+                               if (end == NULL)
+                               {
+                                       fprintf(stderr, "invalid end address: '%s'.\n", optarg);
+                                       usage();
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
+                       case 't':
+                               timeout = atoi(optarg);
+                               if (timeout == 0 && strcmp(optarg, "0") != 0)
+                               {
+                                       fprintf(stderr, "invalid timeout '%s'.\n", optarg);
+                                       usage();
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
+                       case 'f':
+                               filter = optarg;
+                               continue;
+                       case 'x':
+                               addresses = optarg;
+                               continue;
+                       case 'v':
+                               DESTROY_IF(server);
+                               server = host_create_from_string(optarg, 0);
+                               if (server == NULL)
+                               {
+                                       fprintf(stderr, "invalid server address: '%s'.\n", optarg);
+                                       usage();
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
+                       default:
+                               usage();
+                               exit(EXIT_FAILURE);
+                               break;
+               }
+               break;
+       }
+
+       switch (operation)
+       {
+               case OP_USAGE:
+                       usage();
+                       break;
+               case OP_STATUS:
+                       status();
+                       break;
+               case OP_ADD:
+                       if (addresses != NULL)
+                       {
+                               add_addresses(name, addresses, timeout);
+                       }
+                       else if (start != NULL && end != NULL)
+                       {
+                               add(name, start, end, timeout);
+                       }
+                       else
+                       {
+                               fprintf(stderr, "missing arguments.\n");
+                               usage();
+                               exit(EXIT_FAILURE);
+                       }
+                       break;
+               case OP_ADD_ATTR:
+                       if (server == NULL)
+                       {
+                               fprintf(stderr, "missing arguments.\n");
+                               usage();
+                               exit(EXIT_FAILURE);
+                       }
+                       add_attr(name, server);
+                       break;
+               case OP_DEL:
+                       del(name);
+                       break;
+               case OP_DEL_ATTR:
+                       del_attr(name, server);
+                       break;
+               case OP_RESIZE:
+                       if (end == NULL)
+                       {
+                               fprintf(stderr, "missing arguments.\n");
+                               usage();
+                               exit(EXIT_FAILURE);
+                       }
+                       resize(name, end);
+                       break;
+               case OP_LEASES:
+                       leases(filter, utc);
+                       break;
+               case OP_PURGE:
+                       purge(name);
+                       break;
+               case OP_BATCH:
+                       if (name == NULL)
+                       {
+                               fprintf(stderr, "missing arguments.\n");
+                               usage();
+                               exit(EXIT_FAILURE);
+                       }
+                       batch(argv[0], name);
+                       break;
+               default:
+                       usage();
+                       exit(EXIT_FAILURE);
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       char *uri;
+
+       atexit(library_deinit);
+
+       /* initialize library */
+       if (!library_init(NULL))
+       {
+               exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+       }
+       if (lib->integrity &&
+               !lib->integrity->check_file(lib->integrity, "pool", argv[0]))
+       {
+               fprintf(stderr, "integrity check of pool failed\n");
+               exit(SS_RC_DAEMON_INTEGRITY);
+       }
+       if (!lib->plugins->load(lib->plugins, NULL,
+                       lib->settings->get_str(lib->settings, "pool.load", PLUGINS)))
+       {
+               exit(SS_RC_INITIALIZATION_FAILED);
+       }
+
+       uri = lib->settings->get_str(lib->settings, "libstrongswan.plugins.attr-sql.database", NULL);
+       if (!uri)
+       {
+               fprintf(stderr, "database URI libstrongswan.plugins.attr-sql.database not set.\n");
+               exit(SS_RC_INITIALIZATION_FAILED);
+       }
+       db = lib->db->create(lib->db, uri);
+       if (!db)
+       {
+               fprintf(stderr, "opening database failed.\n");
+               exit(SS_RC_INITIALIZATION_FAILED);
+       }
+       atexit(cleanup);
+
+       do_args(argc, argv);
+
+       exit(EXIT_SUCCESS);
+}
+
diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c
new file mode 100644 (file)
index 0000000..a89195b
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include <time.h>
+
+#include <debug.h>
+#include <library.h>
+
+#include "sql_attribute.h"
+
+typedef struct private_sql_attribute_t private_sql_attribute_t;
+
+/**
+ * private data of sql_attribute
+ */
+struct private_sql_attribute_t {
+
+       /**
+        * public functions
+        */
+       sql_attribute_t public;
+
+       /**
+        * database connection
+        */
+       database_t *db;
+
+       /**
+        * wheter to record lease history in lease table
+        */
+       bool history;
+};
+
+/**
+ * lookup/insert an identity
+ */
+static u_int get_identity(private_sql_attribute_t *this, identification_t *id)
+{
+       enumerator_t *e;
+       u_int row;
+
+       /* look for peer identity in the identities table */
+       e = this->db->query(this->db,
+                                               "SELECT id FROM identities WHERE type = ? AND data = ?",
+                                               DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
+                                               DB_UINT);
+
+       if (e && e->enumerate(e, &row))
+       {
+               e->destroy(e);
+               return row;
+       }
+       DESTROY_IF(e);
+       /* not found, insert new one */
+       if (this->db->execute(this->db, &row,
+                                 "INSERT INTO identities (type, data) VALUES (?, ?)",
+                                 DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) == 1)
+       {
+               return row;
+       }
+       return 0;
+}
+
+/**
+ * Lookup pool by name
+ */
+static u_int get_pool(private_sql_attribute_t *this, char *name, u_int *timeout)
+{
+       enumerator_t *e;
+       u_int pool;
+
+       e = this->db->query(this->db, "SELECT id, timeout FROM pools WHERE name = ?",
+                                               DB_TEXT, name, DB_UINT, DB_UINT);
+       if (e && e->enumerate(e, &pool, timeout))
+       {
+               e->destroy(e);
+               return pool;
+       }
+       DESTROY_IF(e);
+       return 0;
+}
+
+/**
+ * Look up an existing lease
+ */
+static host_t* check_lease(private_sql_attribute_t *this, char *name,
+                                                  u_int pool, u_int identity)
+{
+       while (TRUE)
+       {
+               u_int id;
+               chunk_t address;
+               enumerator_t *e;
+               time_t now = time(NULL);
+
+               e = this->db->query(this->db,
+                               "SELECT id, address FROM addresses "
+                               "WHERE pool = ? AND identity = ? AND released != 0 LIMIT 1",
+                               DB_UINT, pool, DB_UINT, identity, DB_UINT, DB_BLOB);
+               if (!e || !e->enumerate(e, &id, &address))
+               {
+                       DESTROY_IF(e);
+                       break;
+               }
+               address = chunk_clonea(address);
+               e->destroy(e);
+
+               if (this->db->execute(this->db, NULL,
+                               "UPDATE addresses SET acquired = ?, released = 0 "
+                               "WHERE id = ? AND identity = ? AND released != 0",
+                               DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0)
+               {
+                       host_t *host;
+
+                       host = host_create_from_chunk(AF_UNSPEC, address, 0);
+                       if (host)
+                       {
+                               DBG1("acquired existing lease for address %H in pool '%s'",
+                                        host, name);
+                               return host;
+                       }
+               }
+       }
+       return NULL;
+}
+
+/**
+ * We check for unallocated addresses or expired leases. First we select an
+ * address as a candidate, but double check later on if it is still available
+ * during the update operation. This allows us to work without locking.
+ */
+static host_t* get_lease(private_sql_attribute_t *this, char *name,
+                                                u_int pool, u_int timeout, u_int identity)
+{
+       while (TRUE)
+       {
+               u_int id;
+               chunk_t address;
+               enumerator_t *e;
+               time_t now = time(NULL);
+               int hits;
+
+               if (timeout)
+               {
+                       /* check for an expired lease */
+                       e = this->db->query(this->db,
+                               "SELECT id, address FROM addresses "
+                               "WHERE pool = ? AND released != 0 AND released < ? LIMIT 1",
+                               DB_UINT, pool, DB_UINT, now - timeout, DB_UINT, DB_BLOB);
+               }
+               else
+               {
+                       /* with static leases, check for an unallocated address */
+                       e = this->db->query(this->db,
+                               "SELECT id, address FROM addresses "
+                               "WHERE pool = ? AND identity = 0 LIMIT 1",
+                               DB_UINT, pool, DB_UINT, DB_BLOB);
+
+               }
+
+               if (!e || !e->enumerate(e, &id, &address))
+               {
+                       DESTROY_IF(e);
+                       break;
+               }
+               address = chunk_clonea(address);
+               e->destroy(e);
+
+               if (timeout)
+               {
+                       hits = this->db->execute(this->db, NULL,
+                                               "UPDATE addresses SET "
+                                               "acquired = ?, released = 0, identity = ? "
+                                               "WHERE id = ? AND released != 0 AND released < ?",
+                                               DB_UINT, now, DB_UINT, identity,
+                                               DB_UINT, id, DB_UINT, now - timeout);
+               }
+               else
+               {
+                       hits = this->db->execute(this->db, NULL,
+                                               "UPDATE addresses SET "
+                                               "acquired = ?, released = 0, identity = ? "
+                                               "WHERE id = ? AND identity = 0",
+                                               DB_UINT, now, DB_UINT, identity, DB_UINT, id);
+               }
+               if (hits > 0)
+               {
+                       host_t *host;
+
+                       host = host_create_from_chunk(AF_UNSPEC, address, 0);
+                       if (host)
+                       {
+                               DBG1("acquired new lease for address %H in pool '%s'",
+                                        host, name);
+                               return host;
+                       }
+               }
+       }
+       DBG1("no available address found in pool '%s'", name);
+       return NULL;
+}
+
+/**
+ * Implementation of attribute_provider_t.acquire_address
+ */
+static host_t* acquire_address(private_sql_attribute_t *this,
+                                                          char *names, identification_t *id,
+                                                          host_t *requested)
+{
+       host_t *address = NULL;
+       u_int identity, pool, timeout;
+
+       identity = get_identity(this, id);
+       if (identity)
+       {
+               /* check for a single pool first (no concatenation and enumeration) */
+               if (strchr(names, ',') == NULL)
+               {
+                       pool = get_pool(this, names, &timeout);
+                       if (pool)
+                       {
+                               /* check for an existing lease */
+                               address = check_lease(this, names, pool, identity);
+                               if (address == NULL)
+                               {
+                                       /* get an unallocated address or expired lease */
+                                       address = get_lease(this, names, pool, timeout, identity);
+                               }
+                       }
+               }
+               else
+               {
+                       enumerator_t *enumerator;
+                       char *name;
+
+                       /* in a first step check for an existing lease over all pools */
+                       enumerator = enumerator_create_token(names, ",", " ");
+                       while (enumerator->enumerate(enumerator, &name))
+                       {
+                               pool = get_pool(this, name, &timeout);
+                               if (pool)
+                               {
+                                       address = check_lease(this, name, pool, identity);
+                                       if (address)
+                                       {
+                                               enumerator->destroy(enumerator);
+                                               return address;
+                                       }
+                               }
+                       }
+                       enumerator->destroy(enumerator);
+
+                       /* in a second step get an unallocated address or expired lease */
+                       enumerator = enumerator_create_token(names, ",", " ");
+                       while (enumerator->enumerate(enumerator, &name))
+                       {
+                               pool = get_pool(this, name, &timeout);
+                               if (pool)
+                               {
+                                       address = get_lease(this, name, pool, timeout, identity);
+                                       if (address)
+                                       {
+                                               break;
+                                       }
+                               }
+                       }
+                       enumerator->destroy(enumerator);
+               }
+       }
+       return address;
+}
+
+/**
+ * Implementation of attribute_provider_t.release_address
+ */
+static bool release_address(private_sql_attribute_t *this,
+                                                       char *name, host_t *address, identification_t *id)
+{
+       enumerator_t *enumerator;
+       bool found = FALSE;
+       time_t now = time(NULL);
+
+       enumerator = enumerator_create_token(name, ",", " ");
+       while (enumerator->enumerate(enumerator, &name))
+       {
+               u_int pool, timeout;
+
+               pool = get_pool(this, name, &timeout);
+               if (pool)
+               {
+                       if (this->history)
+                       {
+                               this->db->execute(this->db, NULL,
+                                       "INSERT INTO leases (address, identity, acquired, released)"
+                                       " SELECT id, identity, acquired, ? FROM addresses "
+                                       " WHERE pool = ? AND address = ?",
+                                       DB_UINT, now, DB_UINT, pool,
+                                       DB_BLOB, address->get_address(address));
+                       }
+                       if (this->db->execute(this->db, NULL,
+                                       "UPDATE addresses SET released = ? WHERE "
+                                       "pool = ? AND address = ?", DB_UINT, time(NULL),
+                                       DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0)
+                       {
+                               found = TRUE;
+                               break;
+                       }
+               }
+       }
+       enumerator->destroy(enumerator);
+       return found;
+}
+
+/**
+ * Implementation of sql_attribute_t.create_attribute_enumerator
+ */
+static enumerator_t* create_attribute_enumerator(private_sql_attribute_t *this,
+                                                                                       identification_t *id, host_t *vip)
+{
+       if (vip)
+       {
+               enumerator_t *enumerator;
+
+               enumerator = this->db->query(this->db,
+                                               "SELECT type, value FROM attributes", DB_INT, DB_BLOB);
+               if (enumerator)
+               {
+                       return enumerator;
+               }
+       }
+       return enumerator_create_empty();
+}
+
+/**
+ * Implementation of sql_attribute_t.destroy
+ */
+static void destroy(private_sql_attribute_t *this)
+{
+       free(this);
+}
+
+/*
+ * see header file
+ */
+sql_attribute_t *sql_attribute_create(database_t *db)
+{
+       private_sql_attribute_t *this = malloc_thing(private_sql_attribute_t);
+       time_t now = time(NULL);
+
+       this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address;
+       this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
+       this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *host))create_attribute_enumerator;
+       this->public.destroy = (void(*)(sql_attribute_t*))destroy;
+
+       this->db = db;
+       this->history = lib->settings->get_bool(lib->settings,
+                                               "libstrongswan.plugins.attr-sql.lease_history", TRUE);
+
+       /* close any "online" leases in the case we crashed */
+       if (this->history)
+       {
+               this->db->execute(this->db, NULL,
+                                       "INSERT INTO leases (address, identity, acquired, released)"
+                                       " SELECT id, identity, acquired, ? FROM addresses "
+                                       " WHERE released = 0", DB_UINT, now);
+       }
+       this->db->execute(this->db, NULL,
+                                         "UPDATE addresses SET released = ? WHERE released = 0",
+                                         DB_UINT, now);
+       return &this->public;
+}
+
diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.h b/src/libhydra/plugins/attr_sql/sql_attribute.h
new file mode 100644 (file)
index 0000000..ca87eb2
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup sql_attribute sql_attribute
+ * @{ @ingroup attr_sql
+ */
+
+#ifndef SQL_ATTRIBUTE_H_
+#define SQL_ATTRIBUTE_H_
+
+#include <attributes/attribute_provider.h>
+#include <database/database.h>
+
+typedef struct sql_attribute_t sql_attribute_t;
+
+/**
+ * SQL database based IKEv2 cfg attribute provider.
+ */
+struct sql_attribute_t {
+
+       /**
+        * Implements attribute provider interface
+        */
+       attribute_provider_t provider;
+
+       /**
+        * Destroy a sql_attribute instance.
+        */
+       void (*destroy)(sql_attribute_t *this);
+};
+
+/**
+ * Create a sql_attribute instance.
+ */
+sql_attribute_t *sql_attribute_create(database_t *db);
+
+#endif /** SQL_ATTRIBUTE_H_ @}*/
index 2b80e61..5620ff7 100644 (file)
@@ -269,13 +269,6 @@ if MONOLITHIC
 endif
 endif
 
-if USE_ATTR_SQL
-  SUBDIRS += plugins/attr_sql
-if MONOLITHIC
-  libstrongswan_la_LIBADD += plugins/attr_sql/libstrongswan-attr-sql.la
-endif
-endif
-
 if USE_PADLOCK
   SUBDIRS += plugins/padlock
 if MONOLITHIC
diff --git a/src/libstrongswan/plugins/attr_sql/.gitignore b/src/libstrongswan/plugins/attr_sql/.gitignore
deleted file mode 100644 (file)
index eae4e6a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-pool
diff --git a/src/libstrongswan/plugins/attr_sql/Makefile.am b/src/libstrongswan/plugins/attr_sql/Makefile.am
deleted file mode 100644 (file)
index 9d73f2e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-
-INCLUDES = -I$(top_srcdir)/src/libstrongswan
-
-AM_CFLAGS = \
-       -rdynamic \
-       -DPLUGINS=\""${libstrongswan_plugins}\""
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-attr-sql.la
-else
-plugin_LTLIBRARIES = libstrongswan-attr-sql.la
-endif
-
-libstrongswan_attr_sql_la_SOURCES = \
-       attr_sql_plugin.h attr_sql_plugin.c \
-       sql_attribute.h sql_attribute.c
-
-libstrongswan_attr_sql_la_LDFLAGS = -module -avoid-version
-
-ipsec_PROGRAMS = pool
-pool_SOURCES = pool.c
-pool_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
diff --git a/src/libstrongswan/plugins/attr_sql/attr_sql_plugin.c b/src/libstrongswan/plugins/attr_sql/attr_sql_plugin.c
deleted file mode 100644 (file)
index 5d3d737..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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.
- */
-
-#include <library.h>
-#include <debug.h>
-
-#include "attr_sql_plugin.h"
-#include "sql_attribute.h"
-
-typedef struct private_attr_sql_plugin_t private_attr_sql_plugin_t;
-
-/**
- * private data of attr_sql plugin
- */
-struct private_attr_sql_plugin_t {
-
-       /**
-        * implements plugin interface
-        */
-       attr_sql_plugin_t public;
-
-       /**
-        * database connection instance
-        */
-       database_t *db;
-
-       /**
-        * configuration attributes
-        */
-       sql_attribute_t *attribute;
-
-};
-
-/**
- * Implementation of plugin_t.destroy
- */
-static void destroy(private_attr_sql_plugin_t *this)
-{
-       lib->attributes->remove_provider(lib->attributes, &this->attribute->provider);
-       this->attribute->destroy(this->attribute);
-       this->db->destroy(this->db);
-       free(this);
-}
-
-/*
- * see header file
- */
-plugin_t *attr_sql_plugin_create()
-{
-       char *uri;
-       private_attr_sql_plugin_t *this;
-
-       uri = lib->settings->get_str(lib->settings, "libstrongswan.plugins.attr-sql.database", NULL);
-       if (!uri)
-       {
-               DBG1("attr-sql plugin: database URI not set");
-               return NULL;
-       }
-
-       this = malloc_thing(private_attr_sql_plugin_t);
-
-       this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
-
-       this->db = lib->db->create(lib->db, uri);
-       if (!this->db)
-       {
-               DBG1("attr-sql plugin failed to connect to database");
-               free(this);
-               return NULL;
-       }
-       this->attribute = sql_attribute_create(this->db);
-       lib->attributes->add_provider(lib->attributes, &this->attribute->provider);
-
-       return &this->public.plugin;
-}
-
diff --git a/src/libstrongswan/plugins/attr_sql/attr_sql_plugin.h b/src/libstrongswan/plugins/attr_sql/attr_sql_plugin.h
deleted file mode 100644 (file)
index 12837ff..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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.
- */
-
-/**
- * @defgroup attr_sql attr_sql
- * @ingroup plugins
- *
- * @defgroup sql_plugin sql_plugin
- * @{ @ingroup attr_sql
- */
-
-#ifndef ATTR_SQL_PLUGIN_H_
-#define ATTR_SQL_PLUGIN_H_
-
-#include <plugins/plugin.h>
-
-typedef struct attr_sql_plugin_t attr_sql_plugin_t;
-
-/**
- * SQL database attribute configuration plugin
- */
-struct attr_sql_plugin_t {
-
-       /**
-        * implements plugin interface
-        */
-       plugin_t plugin;
-};
-
-#endif /** ATTR_SQL_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/attr_sql/pool.c b/src/libstrongswan/plugins/attr_sql/pool.c
deleted file mode 100644 (file)
index 5ecf80b..0000000
+++ /dev/null
@@ -1,1402 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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.
- */
-
-#define _GNU_SOURCE
-#include <getopt.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <time.h>
-#include <string.h>
-#include <errno.h>
-
-#include <debug.h>
-#include <library.h>
-#include <utils/host.h>
-#include <utils/identification.h>
-#include <attributes/attributes.h>
-
-/**
- * global database handle
- */
-database_t *db;
-
-/**
- * --start/--end/--server addresses of various subcommands
- */
-host_t *start = NULL, *end = NULL, *server = NULL;
-
-/**
- * whether --add should --replace an existing pool
- */
-bool replace_pool = FALSE;
-
-/**
- * forward declarations
- */
-static void del(char *name);
-static void do_args(int argc, char *argv[]);
-
-/**
- * nesting counter for database transaction functions
- */
-int nested_transaction = 0;
-
-/**
- * start a database transaction
- */
-static void begin_transaction()
-{
-       if (db->get_driver(db) == DB_SQLITE)
-       {
-               if (!nested_transaction)
-               {
-                       db->execute(db, NULL, "BEGIN EXCLUSIVE TRANSACTION");
-               }
-               ++nested_transaction;
-       }
-}
-
-/**
- * commit a database transaction
- */
-static void commit_transaction()
-{
-       if (db->get_driver(db) == DB_SQLITE)
-       {
-               --nested_transaction;
-               if (!nested_transaction)
-               {
-                       db->execute(db, NULL, "END TRANSACTION");
-               }
-       }
-}
-
-/**
- * Create or replace a pool by name
- */
-static u_int create_pool(char *name, chunk_t start, chunk_t end, int timeout)
-{
-       enumerator_t *e;
-       int pool;
-
-       e = db->query(db, "SELECT id FROM pools WHERE name = ?",
-                       DB_TEXT, name, DB_UINT);
-       if (e && e->enumerate(e, &pool))
-       {
-               if (replace_pool == FALSE)
-               {
-                       fprintf(stderr, "pool '%s' exists.\n", name);
-                       e->destroy(e);
-                       exit(EXIT_FAILURE);
-               }
-               del(name);
-       }
-       DESTROY_IF(e);
-       if (db->execute(db, &pool,
-                       "INSERT INTO pools (name, start, end, timeout) VALUES (?, ?, ?, ?)",
-                       DB_TEXT, name, DB_BLOB, start, DB_BLOB, end,
-                       DB_INT, timeout*3600) != 1)
-       {
-               fprintf(stderr, "creating pool failed.\n");
-               exit(EXIT_FAILURE);
-       }
-
-       return pool;
-}
-
-/**
- * instead of a pool handle a DNS or NBNS attribute
- */
-static bool is_attribute(char *name)
-{
-       return strcaseeq(name, "dns") || strcaseeq(name, "nbns") ||
-                  strcaseeq(name, "wins");
-}
-
-/**
- * determine configuration attribute type
- */
-static configuration_attribute_type_t get_attribute_type(char *name, host_t* addr)
-{
-       if (strcaseeq(name, "dns"))
-       {
-               return (addr->get_family(addr) == AF_INET) ? INTERNAL_IP4_DNS :
-                                                                                                        INTERNAL_IP6_DNS;
-       }
-       else
-       {
-               return (addr->get_family(addr) == AF_INET) ? INTERNAL_IP4_NBNS :
-                                                                                                        INTERNAL_IP6_NBNS;
-       }
-}
-
-/**
- * calculate the size of a pool using start and end address chunk
- */
-static u_int get_pool_size(chunk_t start, chunk_t end)
-{
-       u_int *start_ptr, *end_ptr;
-
-       if (start.len < sizeof(u_int) || end.len < sizeof(u_int))
-       {
-               return 0;
-       }
-       start_ptr = (u_int*)(start.ptr + start.len - sizeof(u_int));
-       end_ptr = (u_int*)(end.ptr + end.len - sizeof(u_int));
-       return ntohl(*end_ptr) -  ntohl(*start_ptr) + 1;
-}
-
-/**
- * print usage info
- */
-static void usage(void)
-{
-       printf("\
-Usage:\n\
-  ipsec pool --status|--add|--replace|--del|--resize|--purge [options]\n\
-  \n\
-  ipsec pool --status\n\
-    Show a list of installed pools with statistics.\n\
-  \n\
-  ipsec pool --add <name> --start <start> --end <end> [--timeout <timeout>]\n\
-  ipsec pool --replace <name> --start <start> --end <end> [--timeout <timeout>]\n\
-    Add a new pool to or replace an existing pool in the database.\n\
-      name:    Name of the pool, as used in ipsec.conf rightsourceip=%%name\n\
-      start:   Start address of the pool\n\
-      end:     End address of the pool\n\
-      timeout: Lease time in hours, 0 for static leases\n\
-  \n\
-  ipsec pool --add <name> --addresses <file> [--timeout <timeout>]\n\
-  ipsec pool --replace <name> --addresses <file> [--timeout <timeout>]\n\
-    Add a new pool to or replace an existing pool in the database.\n\
-      name:    Name of the pool, as used in ipsec.conf rightsourceip=%%name\n\
-      file:    File newline separated addresses for the pool are read from.\n\
-               Optionally each address can be pre-assigned to a roadwarrior\n\
-               identity, e.g. 10.231.14.2=alice@strongswan.org.\n\
-               If a - (hyphen) is given instead of a file name, the addresses\n\
-               are read from STDIN. Reading addresses stops at the end of file\n\
-               or an empty line. Pools created with this command can not be\n\
-               resized.\n\
-      timeout: Lease time in hours, 0 for static leases\n\
-  \n\
-  ipsec pool --add dns|nbns|wins --server <server>\n\
-    Add a new DNS or NBNS server to the database.\n\
-      server:  IP address of the name server\n\
-  \n\
-  ipsec pool --del <name>\n\
-    Delete a pool from the database.\n\
-      name:    Name of the pool to delete\n\
-  \n\
-  ipsec pool --del dns|nbns|wins [--server <server>]\n\
-    Delete a specific or all DNS or NBNS servers from the database.\n\
-      server:  IP address of the name server to delete\n\
-  \n\
-  ipsec pool --resize <name> --end <end>\n\
-    Grow or shrink an existing pool.\n\
-      name:    Name of the pool to resize\n\
-      end:     New end address for the pool\n\
-  \n\
-  ipsec pool --leases [--filter <filter>] [--utc]\n\
-    Show lease information using filters:\n\
-      filter:  Filter string containing comma separated key=value filters,\n\
-               e.g. id=alice@strongswan.org,addr=1.1.1.1\n\
-                  pool:   name of the pool\n\
-                  id:     assigned identity of the lease\n\
-                  addr:   lease IP address\n\
-                  tstamp: UNIX timestamp when lease was valid, as integer\n\
-                  status: status of the lease: online|valid|expired\n\
-      utc:    Show times in UTC instead of local time\n\
-  \n\
-  ipsec pool --purge <name>\n\
-    Delete lease history of a pool:\n\
-      name:    Name of the pool to purge\n\
-  \n\
-  ipsec pool --batch <file>\n\
-    Read commands from a file and execute them atomically.\n\
-      file:    File to read the newline separated commands from. Commands\n\
-               appear as they are written on the command line, e.g.\n\
-                  --replace mypool --start 10.0.0.1 --end 10.0.0.254\n\
-                  --del dns\n\
-                  --add dns --server 10.1.0.1\n\
-                  --add dns --server 10.1.1.1\n\
-               If a - (hyphen) is given as a file name, the commands are read\n\
-               from STDIN. Readin commands stops at the end of file. Empty\n\
-               lines are ignored. The file may not contain a --batch command.\n\
-  \n");
-}
-
-/**
- * ipsec pool --status - show pool overview
- */
-static void status(void)
-{
-       enumerator_t *ns, *pool, *lease;
-       host_t *server;
-       chunk_t value;
-       bool found = FALSE;
-
-       /* enumerate IPv4 DNS servers */
-       ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
-                                  DB_INT, INTERNAL_IP4_DNS, DB_BLOB);
-       if (ns)
-       {
-               while (ns->enumerate(ns, &value))
-               {
-                       if (!found)
-                       {
-                               printf("dns servers:");
-                               found = TRUE;
-                       }
-                       server = host_create_from_chunk(AF_INET, value, 0);
-                       if (server)
-                       {
-                               printf(" %H", server);
-                               server->destroy(server);
-                       }
-               }
-               ns->destroy(ns);
-       }
-
-       /* enumerate IPv6 DNS servers */
-       ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
-                                  DB_INT, INTERNAL_IP6_DNS, DB_BLOB);
-       if (ns)
-       {
-               while (ns->enumerate(ns, &value))
-               {
-                       if (!found)
-                       {
-                               printf("dns servers:");
-                               found = TRUE;
-                       }
-                       server = host_create_from_chunk(AF_INET6, value, 0);
-                       if (server)
-                       {
-                               printf(" %H", server);
-                               server->destroy(server);
-                       }
-               }
-               ns->destroy(ns);
-       }
-       if (found)
-       {
-               printf("\n");
-       }
-       else
-       {
-               printf("no dns servers found.\n");
-       }
-       found = FALSE;
-
-       /* enumerate IPv4 NBNS servers */
-       ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
-                                  DB_INT, INTERNAL_IP4_NBNS, DB_BLOB);
-       if (ns)
-       {
-               while (ns->enumerate(ns, &value))
-               {
-                       if (!found)
-                       {
-                               printf("nbns servers:");
-                               found = TRUE;
-                       }
-                       server = host_create_from_chunk(AF_INET, value, 0);
-                       if (server)
-                       {
-                               printf(" %H", server);
-                               server->destroy(server);
-                       }
-               }
-               ns->destroy(ns);
-       }
-
-       /* enumerate IPv6 NBNS servers */
-       ns = db->query(db, "SELECT value FROM attributes WHERE type = ?",
-                                  DB_INT, INTERNAL_IP6_NBNS, DB_BLOB);
-       if (ns)
-       {
-               while (ns->enumerate(ns, &value))
-               {
-                       if (!found)
-                       {
-                               printf("nbns servers:");
-                               found = TRUE;
-                       }
-                       server = host_create_from_chunk(AF_INET6, value, 0);
-                       if (server)
-                       {
-                               printf(" %H", server);
-                               server->destroy(server);
-                       }
-               }
-               ns->destroy(ns);
-       }
-       if (found)
-       {
-               printf("\n");
-       }
-       else
-       {
-               printf("no nbns servers found.\n");
-       }
-       found = FALSE;
-
-       pool = db->query(db, "SELECT id, name, start, end, timeout FROM pools",
-                                        DB_INT, DB_TEXT, DB_BLOB, DB_BLOB, DB_UINT);
-       if (pool)
-       {
-               char *name;
-               chunk_t start_chunk, end_chunk;
-               host_t *start, *end;
-               u_int id, timeout, online = 0, used = 0, size = 0;
-
-               while (pool->enumerate(pool, &id, &name,
-                                                          &start_chunk, &end_chunk, &timeout))
-               {
-                       if (!found)
-                       {
-                               printf("%8s %15s %15s %8s %6s %11s %11s\n", "name", "start",
-                                          "end", "timeout", "size", "online", "usage");
-                               found = TRUE;
-                       }
-
-                       start = host_create_from_chunk(AF_UNSPEC, start_chunk, 0);
-                       end = host_create_from_chunk(AF_UNSPEC, end_chunk, 0);
-                       if (start->is_anyaddr(start) && end->is_anyaddr(end))
-                       {
-                               printf("%8s %15s %15s ", name, "n/a", "n/a");
-                       }
-                       else
-                       {
-                               printf("%8s %15H %15H ", name, start, end);
-                       }
-                       if (timeout)
-                       {
-                               printf("%7dh ", timeout/3600);
-                       }
-                       else
-                       {
-                               printf("%8s ", "static");
-                       }
-                       /* get total number of hosts in the pool */
-                       lease = db->query(db, "SELECT COUNT(*) FROM addresses "
-                                                         "WHERE pool = ?", DB_UINT, id, DB_INT);
-                       if (lease)
-                       {
-                               lease->enumerate(lease, &size);
-                               lease->destroy(lease);
-                       }
-                       printf("%6d ", size);
-                       /* get number of online hosts */
-                       lease = db->query(db, "SELECT COUNT(*) FROM addresses "
-                                                         "WHERE pool = ? AND released = 0",
-                                                         DB_UINT, id, DB_INT);
-                       if (lease)
-                       {
-                               lease->enumerate(lease, &online);
-                               lease->destroy(lease);
-                       }
-                       printf("%5d (%2d%%) ", online, online*100/size);
-                       /* get number of online or valid lieases */
-                       lease = db->query(db, "SELECT COUNT(*) FROM addresses "
-                                                         "WHERE addresses.pool = ? "
-                                                         "AND ((? AND acquired != 0) "
-                                                         "     OR released = 0 OR released > ?) ",
-                                                         DB_UINT, id, DB_UINT, !timeout,
-                                                         DB_UINT, time(NULL) - timeout, DB_UINT);
-                       if (lease)
-                       {
-                               lease->enumerate(lease, &used);
-                               lease->destroy(lease);
-                       }
-                       printf("%5d (%2d%%) ", used, used*100/size);
-
-                       printf("\n");
-                       DESTROY_IF(start);
-                       DESTROY_IF(end);
-               }
-               pool->destroy(pool);
-       }
-       if (!found)
-       {
-               printf("no pools found.\n");
-       }
-}
-
-/**
- * ipsec pool --add - add a new pool
- */
-static void add(char *name, host_t *start, host_t *end, int timeout)
-{
-       chunk_t start_addr, end_addr, cur_addr;
-       u_int id, count;
-
-       start_addr = start->get_address(start);
-       end_addr = end->get_address(end);
-       cur_addr = chunk_clonea(start_addr);
-       count = get_pool_size(start_addr, end_addr);
-
-       if (start_addr.len != end_addr.len ||
-               memcmp(start_addr.ptr, end_addr.ptr, start_addr.len) > 0)
-       {
-               fprintf(stderr, "invalid start/end pair specified.\n");
-               exit(EXIT_FAILURE);
-       }
-       id = create_pool(name, start_addr, end_addr, timeout);
-       printf("allocating %d addresses... ", count);
-       fflush(stdout);
-       /* run population in a transaction for sqlite */
-       begin_transaction();
-       while (TRUE)
-       {
-               db->execute(db, NULL,
-                       "INSERT INTO addresses (pool, address, identity, acquired, released) "
-                       "VALUES (?, ?, ?, ?, ?)",
-                       DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
-               if (chunk_equals(cur_addr, end_addr))
-               {
-                       break;
-               }
-               chunk_increment(cur_addr);
-       }
-       commit_transaction();
-       printf("done.\n", count);
-}
-
-static bool add_address(u_int pool_id, char *address_str, int *family)
-{
-       host_t *address;
-       int user_id = 0;
-
-       char *pos_eq = strchr(address_str, '=');
-       if (pos_eq != NULL)
-       {
-               enumerator_t *e;
-               identification_t *id = identification_create_from_string(pos_eq + 1);
-
-               /* look for peer identity in the identities table */
-               e = db->query(db,
-                               "SELECT id FROM identities WHERE type = ? AND data = ?",
-                               DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
-                               DB_UINT);
-
-               if (!e || !e->enumerate(e, &user_id))
-               {
-                       /* not found, insert new one */
-                       if (db->execute(db, &user_id,
-                                       "INSERT INTO identities (type, data) VALUES (?, ?)",
-                                       DB_INT, id->get_type(id),
-                                       DB_BLOB, id->get_encoding(id)) != 1)
-                       {
-                               fprintf(stderr, "creating id '%s' failed.\n", pos_eq + 1);
-                               return FALSE;
-                       }
-               }
-               DESTROY_IF(e);
-               id->destroy(id);
-               *pos_eq = '\0';
-       }
-
-       address = host_create_from_string(address_str, 0);
-       if (address == NULL)
-       {
-               fprintf(stderr, "invalid address '%s'.\n", address_str);
-               return FALSE;
-       }
-       if (family && *family && *family != address->get_family(address))
-       {
-               fprintf(stderr, "invalid address family '%s'.\n", address_str);
-               return FALSE;
-       }
-
-       if (db->execute(db, NULL,
-                       "INSERT INTO addresses "
-                       "(pool, address, identity, acquired, released) "
-                       "VALUES (?, ?, ?, ?, ?)",
-                       DB_UINT, pool_id, DB_BLOB, address->get_address(address),
-                       DB_UINT, user_id, DB_UINT, 0, DB_UINT, 1) != 1)
-       {
-               fprintf(stderr, "inserting address '%s' failed.\n", address_str);
-               return FALSE;
-       }
-       *family = address->get_family(address);
-       address->destroy(address);
-
-       return TRUE;
-}
-
-static void add_addresses(char *pool, char *path, int timeout)
-{
-       u_int pool_id, count = 0;
-       int family = AF_UNSPEC;
-       char address_str[512];
-       host_t *addr;
-       FILE *file;
-
-       /* run population in a transaction for sqlite */
-       begin_transaction();
-
-       addr = host_create_from_string("%any", 0);
-       pool_id = create_pool(pool, addr->get_address(addr),
-                                                 addr->get_address(addr), timeout);
-       addr->destroy(addr);
-
-       file = (strcmp(path, "-") == 0 ? stdin : fopen(path, "r"));
-       if (file == NULL)
-       {
-               fprintf(stderr, "opening '%s' failed: %s\n", path, strerror(errno));
-               exit(-1);
-       }
-
-       printf("starting allocation... ");
-       fflush(stdout);
-
-       while (fgets(address_str, sizeof(address_str), file))
-       {
-               size_t addr_len = strlen(address_str);
-               char *last_chr = address_str + addr_len - 1;
-               if (*last_chr == '\n')
-               {
-                       if (addr_len == 1)
-                       {       /* end of input */
-                               break;
-                       }
-                       *last_chr = '\0';
-               }
-               if (add_address(pool_id, address_str, &family) == FALSE)
-               {
-                       exit(EXIT_FAILURE);
-               }
-               ++count;
-       }
-
-       if (file != stdin)
-       {
-               fclose(file);
-       }
-
-       commit_transaction();
-
-       printf("%d addresses done.\n", count);
-}
-
-/**
- * ipsec pool --add dns|nbns|wins - add a DNS or NBNS server entry
- */
-static void add_attr(char *name, host_t *server)
-{
-       configuration_attribute_type_t type;
-       chunk_t value;
-
-       type = get_attribute_type(name, server);
-       value = server->get_address(server);
-       if (db->execute(db, NULL,
-                       "INSERT INTO attributes (type, value) VALUES (?, ?)",
-                       DB_INT, type, DB_BLOB, value) != 1)
-       {
-               fprintf(stderr, "adding %s server %H failed.\n", name, server);
-               exit(EXIT_FAILURE);
-       }
-       printf("added %s server %H\n", name, server);
-}
-
-/**
- * ipsec pool --del - delete a pool
- */
-static void del(char *name)
-{
-       enumerator_t *query;
-       u_int id;
-       bool found = FALSE;
-
-       query = db->query(db, "SELECT id FROM pools WHERE name = ?",
-                                         DB_TEXT, name, DB_UINT);
-       if (!query)
-       {
-               fprintf(stderr, "deleting pool failed.\n");
-               exit(EXIT_FAILURE);
-       }
-       while (query->enumerate(query, &id))
-       {
-               found = TRUE;
-               if (db->execute(db, NULL,
-                               "DELETE FROM leases WHERE address IN ("
-                               " SELECT id FROM addresses WHERE pool = ?)", DB_UINT, id) < 0 ||
-                       db->execute(db, NULL,
-                               "DELETE FROM addresses WHERE pool = ?", DB_UINT, id) < 0 ||
-                       db->execute(db, NULL,
-                               "DELETE FROM pools WHERE id = ?", DB_UINT, id) < 0)
-               {
-                       fprintf(stderr, "deleting pool failed.\n");
-                       query->destroy(query);
-                       exit(EXIT_FAILURE);
-               }
-       }
-       query->destroy(query);
-       if (!found)
-       {
-               fprintf(stderr, "pool '%s' not found.\n", name);
-               exit(EXIT_FAILURE);
-       }
-}
-
-/**
- * ipsec pool --del dns|nbns|wins - delete a DNS or NBNS server entry
- */
-static void del_attr(char *name, host_t *server)
-{
-       configuration_attribute_type_t type;
-       chunk_t value;
-       u_int id;
-       enumerator_t *query;
-       bool found = FALSE;
-
-       if (server)
-       {
-               type = get_attribute_type(name, server);
-               value = server->get_address(server);
-               query = db->query(db,
-                                       "SELECT id, type, value FROM attributes "
-                                       "WHERE type = ? AND value = ?",
-                                       DB_INT, type, DB_BLOB, value,
-                                       DB_UINT, DB_INT, DB_BLOB);
-       }
-       else
-       {
-               configuration_attribute_type_t type_ip4, type_ip6;
-
-               if (strcaseeq(name, "dns"))
-               {
-                       type_ip4 = INTERNAL_IP4_DNS;
-                       type_ip6 = INTERNAL_IP6_DNS;
-               }
-               else
-               {
-                       type_ip4 = INTERNAL_IP4_NBNS;
-                       type_ip6 = INTERNAL_IP6_NBNS;
-               }
-
-               query = db->query(db,
-                                       "SELECT id, type, value FROM attributes "
-                                       "WHERE type = ? OR type = ?",
-                                       DB_INT, type_ip4, DB_INT, type_ip6,
-                                       DB_UINT, DB_INT, DB_BLOB);
-       }
-       if (!query)
-       {
-               fprintf(stderr, "deleting %s servers failed.\n", name);
-               exit(EXIT_FAILURE);
-       }
-
-       while (query->enumerate(query, &id, &type, &value))
-       {
-               int family;
-               host_t *host;
-
-               found = TRUE;
-               family = (type == INTERNAL_IP4_DNS || type == INTERNAL_IP4_NBNS) ?
-                                 AF_INET : AF_INET6;
-               host = host_create_from_chunk(family, value, 0);
-               if (db->execute(db, NULL,
-                                       "DELETE FROM attributes WHERE id = ?",
-                                        DB_UINT, id) != 1)
-               {
-                       fprintf(stderr, "deleting %s server %H failed\n", name, host);
-                       query->destroy(query);
-                       DESTROY_IF(host);
-                       exit(EXIT_FAILURE);
-               }
-               printf("deleted %s server %H\n", name, host);
-               DESTROY_IF(host);
-       }
-       query->destroy(query);
-
-       if (!found && server)
-       {
-               printf("%s server %H not found\n", name, server);
-               exit(EXIT_FAILURE);
-       }
-       else if (!found)
-       {
-               printf("no %s servers found\n", name);
-       }
-}
-
-/**
- * ipsec pool --resize - resize a pool
- */
-static void resize(char *name, host_t *end)
-{
-       enumerator_t *query;
-       chunk_t old_addr, new_addr, cur_addr;
-       u_int id, count;
-       host_t *old_end;
-
-       new_addr = end->get_address(end);
-
-       query = db->query(db, "SELECT id, end FROM pools WHERE name = ?",
-                                         DB_TEXT, name, DB_UINT, DB_BLOB);
-       if (!query || !query->enumerate(query, &id, &old_addr))
-       {
-               DESTROY_IF(query);
-               fprintf(stderr, "resizing pool failed.\n");
-               exit(EXIT_FAILURE);
-       }
-       if (old_addr.len != new_addr.len ||
-               memcmp(new_addr.ptr, old_addr.ptr, old_addr.len) < 0)
-       {
-               fprintf(stderr, "shrinking of pools not supported.\n");
-               query->destroy(query);
-               exit(EXIT_FAILURE);
-       }
-       cur_addr = chunk_clonea(old_addr);
-       count = get_pool_size(old_addr, new_addr) - 1;
-       query->destroy(query);
-
-       /* Check whether pool is resizable */
-       old_end = host_create_from_chunk(AF_UNSPEC, old_addr, 0);
-       if (old_end && old_end->is_anyaddr(old_end))
-       {
-               fprintf(stderr, "pool is not resizable.\n");
-               old_end->destroy(old_end);
-               exit(EXIT_FAILURE);
-       }
-       DESTROY_IF(old_end);
-
-       if (db->execute(db, NULL,
-                       "UPDATE pools SET end = ? WHERE name = ?",
-                       DB_BLOB, new_addr, DB_TEXT, name) <= 0)
-       {
-               fprintf(stderr, "pool '%s' not found.\n", name);
-               exit(EXIT_FAILURE);
-       }
-
-       printf("allocating %d new addresses... ", count);
-       fflush(stdout);
-       /* run population in a transaction for sqlite */
-       begin_transaction();
-       while (count-- > 0)
-       {
-               chunk_increment(cur_addr);
-               db->execute(db, NULL,
-                       "INSERT INTO addresses (pool, address, identity, acquired, released) "
-                       "VALUES (?, ?, ?, ?, ?)",
-                       DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
-       }
-       commit_transaction();
-       printf("done.\n", count);
-
-}
-
-/**
- * create the lease query using the filter string
- */
-static enumerator_t *create_lease_query(char *filter)
-{
-       enumerator_t *query;
-       identification_t *id = NULL;
-       host_t *addr = NULL;
-       u_int tstamp = 0;
-       bool online = FALSE, valid = FALSE, expired = FALSE;
-       char *value, *pos, *pool = NULL;
-       enum {
-               FIL_POOL = 0,
-               FIL_ID,
-               FIL_ADDR,
-               FIL_TSTAMP,
-               FIL_STATE,
-       };
-       char *const token[] = {
-               [FIL_POOL] = "pool",
-               [FIL_ID] = "id",
-               [FIL_ADDR] = "addr",
-               [FIL_TSTAMP] = "tstamp",
-               [FIL_STATE] = "status",
-               NULL
-       };
-
-       /* if the filter string contains a distinguished name as a ID, we replace
-        * ", " by "/ " in order to not confuse the getsubopt parser */
-       pos = filter;
-       while ((pos = strchr(pos, ',')))
-       {
-               if (pos[1] == ' ')
-               {
-                       pos[0] = '/';
-               }
-               pos++;
-       }
-
-       while (filter && *filter != '\0')
-       {
-               switch (getsubopt(&filter, token, &value))
-               {
-                       case FIL_POOL:
-                               if (value)
-                               {
-                                       pool = value;
-                               }
-                               break;
-                       case FIL_ID:
-                               if (value)
-                               {
-                                       id = identification_create_from_string(value);
-                               }
-                               break;
-                       case FIL_ADDR:
-                               if (value)
-                               {
-                                       addr = host_create_from_string(value, 0);
-                               }
-                               if (!addr)
-                               {
-                                       fprintf(stderr, "invalid 'addr' in filter string.\n");
-                                       exit(EXIT_FAILURE);
-                               }
-                               break;
-                       case FIL_TSTAMP:
-                               if (value)
-                               {
-                                       tstamp = atoi(value);
-                               }
-                               if (tstamp == 0)
-                               {
-                                       online = TRUE;
-                               }
-                               break;
-                       case FIL_STATE:
-                               if (value)
-                               {
-                                       if (streq(value, "online"))
-                                       {
-                                               online = TRUE;
-                                       }
-                                       else if (streq(value, "valid"))
-                                       {
-                                               valid = TRUE;
-                                       }
-                                       else if (streq(value, "expired"))
-                                       {
-                                               expired = TRUE;
-                                       }
-                                       else
-                                       {
-                                               fprintf(stderr, "invalid 'state' in filter string.\n");
-                                               exit(EXIT_FAILURE);
-                                       }
-                               }
-                               break;
-                       default:
-                               fprintf(stderr, "invalid filter string.\n");
-                               exit(EXIT_FAILURE);
-                               break;
-               }
-       }
-       query = db->query(db,
-                               "SELECT name, addresses.address, identities.type, "
-                               "identities.data, leases.acquired, leases.released, timeout "
-                               "FROM leases JOIN addresses ON leases.address = addresses.id "
-                               "JOIN pools ON addresses.pool = pools.id "
-                               "JOIN identities ON leases.identity = identities.id "
-                               "WHERE (? OR name = ?) "
-                               "AND (? OR (identities.type = ? AND identities.data = ?)) "
-                               "AND (? OR addresses.address = ?) "
-                               "AND (? OR (? >= leases.acquired AND (? <= leases.released))) "
-                               "AND (? OR leases.released > ? - timeout) "
-                               "AND (? OR leases.released < ? - timeout) "
-                               "AND ? "
-                               "UNION "
-                               "SELECT name, address, identities.type, identities.data, "
-                               "acquired, released, timeout FROM addresses "
-                               "JOIN pools ON addresses.pool = pools.id "
-                               "JOIN identities ON addresses.identity = identities.id "
-                               "WHERE ? AND released = 0 "
-                               "AND (? OR name = ?) "
-                               "AND (? OR (identities.type = ? AND identities.data = ?)) "
-                               "AND (? OR address = ?)",
-                               DB_INT, pool == NULL, DB_TEXT, pool,
-                               DB_INT, id == NULL,
-                                       DB_INT, id ? id->get_type(id) : 0,
-                                       DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
-                               DB_INT, addr == NULL,
-                                       DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
-                               DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp,
-                               DB_INT, !valid, DB_INT, time(NULL),
-                               DB_INT, !expired, DB_INT, time(NULL),
-                               DB_INT, !online,
-                               /* union */
-                               DB_INT, !(valid || expired),
-                               DB_INT, pool == NULL, DB_TEXT, pool,
-                               DB_INT, id == NULL,
-                                       DB_INT, id ? id->get_type(id) : 0,
-                                       DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
-                               DB_INT, addr == NULL,
-                                       DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
-                               /* res */
-                               DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT);
-       /* id and addr leak but we can't destroy them until query is destroyed. */
-       return query;
-}
-
-/**
- * ipsec pool --leases - show lease information of a pool
- */
-static void leases(char *filter, bool utc)
-{
-       enumerator_t *query;
-       chunk_t address_chunk, identity_chunk;
-       int identity_type;
-       char *name;
-       u_int db_acquired, db_released, db_timeout;
-       time_t acquired, released, timeout;
-       host_t *address;
-       identification_t *identity;
-       bool found = FALSE;
-
-       query = create_lease_query(filter);
-       if (!query)
-       {
-               fprintf(stderr, "querying leases failed.\n");
-               exit(EXIT_FAILURE);
-       }
-       while (query->enumerate(query, &name, &address_chunk, &identity_type,
-                                                       &identity_chunk, &db_acquired, &db_released, &db_timeout))
-       {
-               if (!found)
-               {
-                       int len = utc ? 25 : 21;
-
-                       found = TRUE;
-                       printf("%-8s %-15s %-7s  %-*s %-*s %s\n",
-                                  "name", "address", "status", len, "start", len, "end", "identity");
-               }
-               address = host_create_from_chunk(AF_UNSPEC, address_chunk, 0);
-               identity = identification_create_from_encoding(identity_type, identity_chunk);
-
-               /* u_int is not always equal to time_t */
-               acquired = (time_t)db_acquired;
-               released = (time_t)db_released;
-               timeout  = (time_t)db_timeout;
-
-               printf("%-8s %-15H ", name, address);
-               if (released == 0)
-               {
-                       printf("%-7s ", "online");
-               }
-               else if (timeout == 0)
-               {
-                       printf("%-7s ", "static");
-               }
-               else if (released >= time(NULL) - timeout)
-               {
-                       printf("%-7s ", "valid");
-               }
-               else
-               {
-                       printf("%-7s ", "expired");
-               }
-
-               printf(" %T  ", &acquired, utc);
-               if (released)
-               {
-                       printf("%T  ", &released, utc);
-               }
-               else
-               {
-                       printf("                      ");
-                       if (utc)
-                       {
-                               printf("    ");
-                       }
-               }
-               printf("%Y\n", identity);
-               DESTROY_IF(address);
-               identity->destroy(identity);
-       }
-       query->destroy(query);
-       if (!found)
-       {
-               fprintf(stderr, "no matching leases found.\n");
-               exit(EXIT_FAILURE);
-       }
-}
-
-/**
- * ipsec pool --purge - delete expired leases
- */
-static void purge(char *name)
-{
-       int purged = 0;
-
-       purged = db->execute(db, NULL,
-                               "DELETE FROM leases WHERE address IN ("
-                               " SELECT id FROM addresses WHERE pool IN ("
-                               "  SELECT id FROM pools WHERE name = ?))",
-                               DB_TEXT, name);
-       if (purged < 0)
-       {
-               fprintf(stderr, "purging pool '%s' failed.\n", name);
-               exit(EXIT_FAILURE);
-       }
-       fprintf(stderr, "purged %d leases in pool '%s'.\n", purged, name);
-}
-
-#define ARGV_SIZE 32
-
-static void argv_add(char **argv, int argc, char *value)
-{
-       if (argc >= ARGV_SIZE)
-       {
-               fprintf(stderr, "too many arguments: %s\n", value);
-               exit(EXIT_FAILURE);
-       }
-       argv[argc] = value;
-}
-
-/**
- * ipsec pool --batch - read commands from a file
- */
-static void batch(char *argv0, char *name)
-{
-       char command[512];
-
-       FILE *file = strncmp(name, "-", 1) == 0 ? stdin : fopen(name, "r");
-       if (file == NULL)
-       {
-               fprintf(stderr, "opening '%s' failed: %s\n", name, strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-       begin_transaction();
-       while (fgets(command, sizeof(command), file))
-       {
-               char *argv[ARGV_SIZE], *start;
-               int i, argc = 0;
-               size_t cmd_len = strlen(command);
-
-               /* ignore empty lines */
-               if (cmd_len == 1 && *(command + cmd_len - 1) == '\n')
-               {
-                       continue;
-               }
-
-               /* parse command into argv */
-               start = command;
-               argv_add(argv, argc++, argv0);
-               for (i = 0; i < cmd_len; ++i)
-               {
-                       if (command[i] == ' ' || command[i] == '\n')
-                       {
-                               if (command + i == start)
-                               {
-                                       /* ignore leading whitespace */
-                                       ++start;
-                                       continue;
-                               }
-                               command[i] = '\0';
-                               argv_add(argv, argc++, start);
-                               start = command + i + 1;
-                       }
-               }
-               if (strlen(start) > 0)
-               {
-                       argv_add(argv, argc++, start);
-               }
-               argv_add(argv, argc, NULL);
-
-               do_args(argc, argv);
-       }
-       commit_transaction();
-
-       if (file != stdin)
-       {
-               fclose(file);
-       }
-}
-
-/**
- * atexit handler to close db on shutdown
- */
-static void cleanup(void)
-{
-       db->destroy(db);
-       DESTROY_IF(start);
-       DESTROY_IF(end);
-       DESTROY_IF(server);
-}
-
-static void do_args(int argc, char *argv[])
-{
-       char *name = "", *filter = "", *addresses = NULL;
-       int timeout = 0;
-       bool utc = FALSE;
-       enum {
-               OP_UNDEF,
-               OP_USAGE,
-               OP_STATUS,
-               OP_ADD,
-               OP_ADD_ATTR,
-               OP_DEL,
-               OP_DEL_ATTR,
-               OP_RESIZE,
-               OP_LEASES,
-               OP_PURGE,
-               OP_BATCH
-       } operation = OP_UNDEF;
-
-       /* reinit getopt state */
-       optind = 0;
-
-       while (TRUE)
-       {
-               int c;
-
-               struct option long_opts[] = {
-                       { "help", no_argument, NULL, 'h' },
-
-                       { "utc", no_argument, NULL, 'u' },
-                       { "status", no_argument, NULL, 'w' },
-                       { "add", required_argument, NULL, 'a' },
-                       { "replace", required_argument, NULL, 'c' },
-                       { "del", required_argument, NULL, 'd' },
-                       { "resize", required_argument, NULL, 'r' },
-                       { "leases", no_argument, NULL, 'l' },
-                       { "purge", required_argument, NULL, 'p' },
-                       { "batch", required_argument, NULL, 'b' },
-
-                       { "start", required_argument, NULL, 's' },
-                       { "end", required_argument, NULL, 'e' },
-                       { "addresses", required_argument, NULL, 'x' },
-                       { "timeout", required_argument, NULL, 't' },
-                       { "filter", required_argument, NULL, 'f' },
-                       { "server", required_argument, NULL, 'v' },
-                       { 0,0,0,0 }
-               };
-
-               c = getopt_long(argc, argv, "", long_opts, NULL);
-               switch (c)
-               {
-                       case EOF:
-                               break;
-                       case 'h':
-                               operation = OP_USAGE;
-                               break;
-                       case 'w':
-                               operation = OP_STATUS;
-                               break;
-                       case 'u':
-                               utc = TRUE;
-                               continue;
-                       case 'c':
-                               replace_pool = TRUE;
-                               /* fallthrough */
-                       case 'a':
-                               name = optarg;
-                               operation = is_attribute(name) ? OP_ADD_ATTR : OP_ADD;
-                               if (replace_pool && operation == OP_ADD_ATTR)
-                               {
-                                       fprintf(stderr, "invalid pool name: '%s'.\n", optarg);
-                                       usage();
-                                       exit(EXIT_FAILURE);
-                               }
-                               continue;
-                       case 'd':
-                               name = optarg;
-                               operation = is_attribute(name) ? OP_DEL_ATTR : OP_DEL;
-                               continue;
-                       case 'r':
-                               name = optarg;
-                               operation = OP_RESIZE;
-                               continue;
-                       case 'l':
-                               operation = OP_LEASES;
-                               continue;
-                       case 'p':
-                               name = optarg;
-                               operation = OP_PURGE;
-                               continue;
-                       case 'b':
-                               name = optarg;
-                               if (operation == OP_BATCH)
-                               {
-                                       fprintf(stderr, "--batch commands can not be nested\n");
-                                       exit(EXIT_FAILURE);
-                               }
-                               operation = OP_BATCH;
-                               continue;
-                       case 's':
-                               DESTROY_IF(start);
-                               start = host_create_from_string(optarg, 0);
-                               if (start == NULL)
-                               {
-                                       fprintf(stderr, "invalid start address: '%s'.\n", optarg);
-                                       usage();
-                                       exit(EXIT_FAILURE);
-                               }
-                               continue;
-                       case 'e':
-                               DESTROY_IF(end);
-                               end = host_create_from_string(optarg, 0);
-                               if (end == NULL)
-                               {
-                                       fprintf(stderr, "invalid end address: '%s'.\n", optarg);
-                                       usage();
-                                       exit(EXIT_FAILURE);
-                               }
-                               continue;
-                       case 't':
-                               timeout = atoi(optarg);
-                               if (timeout == 0 && strcmp(optarg, "0") != 0)
-                               {
-                                       fprintf(stderr, "invalid timeout '%s'.\n", optarg);
-                                       usage();
-                                       exit(EXIT_FAILURE);
-                               }
-                               continue;
-                       case 'f':
-                               filter = optarg;
-                               continue;
-                       case 'x':
-                               addresses = optarg;
-                               continue;
-                       case 'v':
-                               DESTROY_IF(server);
-                               server = host_create_from_string(optarg, 0);
-                               if (server == NULL)
-                               {
-                                       fprintf(stderr, "invalid server address: '%s'.\n", optarg);
-                                       usage();
-                                       exit(EXIT_FAILURE);
-                               }
-                               continue;
-                       default:
-                               usage();
-                               exit(EXIT_FAILURE);
-                               break;
-               }
-               break;
-       }
-
-       switch (operation)
-       {
-               case OP_USAGE:
-                       usage();
-                       break;
-               case OP_STATUS:
-                       status();
-                       break;
-               case OP_ADD:
-                       if (addresses != NULL)
-                       {
-                               add_addresses(name, addresses, timeout);
-                       }
-                       else if (start != NULL && end != NULL)
-                       {
-                               add(name, start, end, timeout);
-                       }
-                       else
-                       {
-                               fprintf(stderr, "missing arguments.\n");
-                               usage();
-                               exit(EXIT_FAILURE);
-                       }
-                       break;
-               case OP_ADD_ATTR:
-                       if (server == NULL)
-                       {
-                               fprintf(stderr, "missing arguments.\n");
-                               usage();
-                               exit(EXIT_FAILURE);
-                       }
-                       add_attr(name, server);
-                       break;
-               case OP_DEL:
-                       del(name);
-                       break;
-               case OP_DEL_ATTR:
-                       del_attr(name, server);
-                       break;
-               case OP_RESIZE:
-                       if (end == NULL)
-                       {
-                               fprintf(stderr, "missing arguments.\n");
-                               usage();
-                               exit(EXIT_FAILURE);
-                       }
-                       resize(name, end);
-                       break;
-               case OP_LEASES:
-                       leases(filter, utc);
-                       break;
-               case OP_PURGE:
-                       purge(name);
-                       break;
-               case OP_BATCH:
-                       if (name == NULL)
-                       {
-                               fprintf(stderr, "missing arguments.\n");
-                               usage();
-                               exit(EXIT_FAILURE);
-                       }
-                       batch(argv[0], name);
-                       break;
-               default:
-                       usage();
-                       exit(EXIT_FAILURE);
-       }
-}
-
-int main(int argc, char *argv[])
-{
-       char *uri;
-
-       atexit(library_deinit);
-
-       /* initialize library */
-       if (!library_init(NULL))
-       {
-               exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
-       }
-       if (lib->integrity &&
-               !lib->integrity->check_file(lib->integrity, "pool", argv[0]))
-       {
-               fprintf(stderr, "integrity check of pool failed\n");
-               exit(SS_RC_DAEMON_INTEGRITY);
-       }
-       if (!lib->plugins->load(lib->plugins, NULL,
-                       lib->settings->get_str(lib->settings, "pool.load", PLUGINS)))
-       {
-               exit(SS_RC_INITIALIZATION_FAILED);
-       }
-
-       uri = lib->settings->get_str(lib->settings, "libstrongswan.plugins.attr-sql.database", NULL);
-       if (!uri)
-       {
-               fprintf(stderr, "database URI libstrongswan.plugins.attr-sql.database not set.\n");
-               exit(SS_RC_INITIALIZATION_FAILED);
-       }
-       db = lib->db->create(lib->db, uri);
-       if (!db)
-       {
-               fprintf(stderr, "opening database failed.\n");
-               exit(SS_RC_INITIALIZATION_FAILED);
-       }
-       atexit(cleanup);
-
-       do_args(argc, argv);
-
-       exit(EXIT_SUCCESS);
-}
-
diff --git a/src/libstrongswan/plugins/attr_sql/sql_attribute.c b/src/libstrongswan/plugins/attr_sql/sql_attribute.c
deleted file mode 100644 (file)
index a89195b..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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.
- */
-
-#include <time.h>
-
-#include <debug.h>
-#include <library.h>
-
-#include "sql_attribute.h"
-
-typedef struct private_sql_attribute_t private_sql_attribute_t;
-
-/**
- * private data of sql_attribute
- */
-struct private_sql_attribute_t {
-
-       /**
-        * public functions
-        */
-       sql_attribute_t public;
-
-       /**
-        * database connection
-        */
-       database_t *db;
-
-       /**
-        * wheter to record lease history in lease table
-        */
-       bool history;
-};
-
-/**
- * lookup/insert an identity
- */
-static u_int get_identity(private_sql_attribute_t *this, identification_t *id)
-{
-       enumerator_t *e;
-       u_int row;
-
-       /* look for peer identity in the identities table */
-       e = this->db->query(this->db,
-                                               "SELECT id FROM identities WHERE type = ? AND data = ?",
-                                               DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
-                                               DB_UINT);
-
-       if (e && e->enumerate(e, &row))
-       {
-               e->destroy(e);
-               return row;
-       }
-       DESTROY_IF(e);
-       /* not found, insert new one */
-       if (this->db->execute(this->db, &row,
-                                 "INSERT INTO identities (type, data) VALUES (?, ?)",
-                                 DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) == 1)
-       {
-               return row;
-       }
-       return 0;
-}
-
-/**
- * Lookup pool by name
- */
-static u_int get_pool(private_sql_attribute_t *this, char *name, u_int *timeout)
-{
-       enumerator_t *e;
-       u_int pool;
-
-       e = this->db->query(this->db, "SELECT id, timeout FROM pools WHERE name = ?",
-                                               DB_TEXT, name, DB_UINT, DB_UINT);
-       if (e && e->enumerate(e, &pool, timeout))
-       {
-               e->destroy(e);
-               return pool;
-       }
-       DESTROY_IF(e);
-       return 0;
-}
-
-/**
- * Look up an existing lease
- */
-static host_t* check_lease(private_sql_attribute_t *this, char *name,
-                                                  u_int pool, u_int identity)
-{
-       while (TRUE)
-       {
-               u_int id;
-               chunk_t address;
-               enumerator_t *e;
-               time_t now = time(NULL);
-
-               e = this->db->query(this->db,
-                               "SELECT id, address FROM addresses "
-                               "WHERE pool = ? AND identity = ? AND released != 0 LIMIT 1",
-                               DB_UINT, pool, DB_UINT, identity, DB_UINT, DB_BLOB);
-               if (!e || !e->enumerate(e, &id, &address))
-               {
-                       DESTROY_IF(e);
-                       break;
-               }
-               address = chunk_clonea(address);
-               e->destroy(e);
-
-               if (this->db->execute(this->db, NULL,
-                               "UPDATE addresses SET acquired = ?, released = 0 "
-                               "WHERE id = ? AND identity = ? AND released != 0",
-                               DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0)
-               {
-                       host_t *host;
-
-                       host = host_create_from_chunk(AF_UNSPEC, address, 0);
-                       if (host)
-                       {
-                               DBG1("acquired existing lease for address %H in pool '%s'",
-                                        host, name);
-                               return host;
-                       }
-               }
-       }
-       return NULL;
-}
-
-/**
- * We check for unallocated addresses or expired leases. First we select an
- * address as a candidate, but double check later on if it is still available
- * during the update operation. This allows us to work without locking.
- */
-static host_t* get_lease(private_sql_attribute_t *this, char *name,
-                                                u_int pool, u_int timeout, u_int identity)
-{
-       while (TRUE)
-       {
-               u_int id;
-               chunk_t address;
-               enumerator_t *e;
-               time_t now = time(NULL);
-               int hits;
-
-               if (timeout)
-               {
-                       /* check for an expired lease */
-                       e = this->db->query(this->db,
-                               "SELECT id, address FROM addresses "
-                               "WHERE pool = ? AND released != 0 AND released < ? LIMIT 1",
-                               DB_UINT, pool, DB_UINT, now - timeout, DB_UINT, DB_BLOB);
-               }
-               else
-               {
-                       /* with static leases, check for an unallocated address */
-                       e = this->db->query(this->db,
-                               "SELECT id, address FROM addresses "
-                               "WHERE pool = ? AND identity = 0 LIMIT 1",
-                               DB_UINT, pool, DB_UINT, DB_BLOB);
-
-               }
-
-               if (!e || !e->enumerate(e, &id, &address))
-               {
-                       DESTROY_IF(e);
-                       break;
-               }
-               address = chunk_clonea(address);
-               e->destroy(e);
-
-               if (timeout)
-               {
-                       hits = this->db->execute(this->db, NULL,
-                                               "UPDATE addresses SET "
-                                               "acquired = ?, released = 0, identity = ? "
-                                               "WHERE id = ? AND released != 0 AND released < ?",
-                                               DB_UINT, now, DB_UINT, identity,
-                                               DB_UINT, id, DB_UINT, now - timeout);
-               }
-               else
-               {
-                       hits = this->db->execute(this->db, NULL,
-                                               "UPDATE addresses SET "
-                                               "acquired = ?, released = 0, identity = ? "
-                                               "WHERE id = ? AND identity = 0",
-                                               DB_UINT, now, DB_UINT, identity, DB_UINT, id);
-               }
-               if (hits > 0)
-               {
-                       host_t *host;
-
-                       host = host_create_from_chunk(AF_UNSPEC, address, 0);
-                       if (host)
-                       {
-                               DBG1("acquired new lease for address %H in pool '%s'",
-                                        host, name);
-                               return host;
-                       }
-               }
-       }
-       DBG1("no available address found in pool '%s'", name);
-       return NULL;
-}
-
-/**
- * Implementation of attribute_provider_t.acquire_address
- */
-static host_t* acquire_address(private_sql_attribute_t *this,
-                                                          char *names, identification_t *id,
-                                                          host_t *requested)
-{
-       host_t *address = NULL;
-       u_int identity, pool, timeout;
-
-       identity = get_identity(this, id);
-       if (identity)
-       {
-               /* check for a single pool first (no concatenation and enumeration) */
-               if (strchr(names, ',') == NULL)
-               {
-                       pool = get_pool(this, names, &timeout);
-                       if (pool)
-                       {
-                               /* check for an existing lease */
-                               address = check_lease(this, names, pool, identity);
-                               if (address == NULL)
-                               {
-                                       /* get an unallocated address or expired lease */
-                                       address = get_lease(this, names, pool, timeout, identity);
-                               }
-                       }
-               }
-               else
-               {
-                       enumerator_t *enumerator;
-                       char *name;
-
-                       /* in a first step check for an existing lease over all pools */
-                       enumerator = enumerator_create_token(names, ",", " ");
-                       while (enumerator->enumerate(enumerator, &name))
-                       {
-                               pool = get_pool(this, name, &timeout);
-                               if (pool)
-                               {
-                                       address = check_lease(this, name, pool, identity);
-                                       if (address)
-                                       {
-                                               enumerator->destroy(enumerator);
-                                               return address;
-                                       }
-                               }
-                       }
-                       enumerator->destroy(enumerator);
-
-                       /* in a second step get an unallocated address or expired lease */
-                       enumerator = enumerator_create_token(names, ",", " ");
-                       while (enumerator->enumerate(enumerator, &name))
-                       {
-                               pool = get_pool(this, name, &timeout);
-                               if (pool)
-                               {
-                                       address = get_lease(this, name, pool, timeout, identity);
-                                       if (address)
-                                       {
-                                               break;
-                                       }
-                               }
-                       }
-                       enumerator->destroy(enumerator);
-               }
-       }
-       return address;
-}
-
-/**
- * Implementation of attribute_provider_t.release_address
- */
-static bool release_address(private_sql_attribute_t *this,
-                                                       char *name, host_t *address, identification_t *id)
-{
-       enumerator_t *enumerator;
-       bool found = FALSE;
-       time_t now = time(NULL);
-
-       enumerator = enumerator_create_token(name, ",", " ");
-       while (enumerator->enumerate(enumerator, &name))
-       {
-               u_int pool, timeout;
-
-               pool = get_pool(this, name, &timeout);
-               if (pool)
-               {
-                       if (this->history)
-                       {
-                               this->db->execute(this->db, NULL,
-                                       "INSERT INTO leases (address, identity, acquired, released)"
-                                       " SELECT id, identity, acquired, ? FROM addresses "
-                                       " WHERE pool = ? AND address = ?",
-                                       DB_UINT, now, DB_UINT, pool,
-                                       DB_BLOB, address->get_address(address));
-                       }
-                       if (this->db->execute(this->db, NULL,
-                                       "UPDATE addresses SET released = ? WHERE "
-                                       "pool = ? AND address = ?", DB_UINT, time(NULL),
-                                       DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0)
-                       {
-                               found = TRUE;
-                               break;
-                       }
-               }
-       }
-       enumerator->destroy(enumerator);
-       return found;
-}
-
-/**
- * Implementation of sql_attribute_t.create_attribute_enumerator
- */
-static enumerator_t* create_attribute_enumerator(private_sql_attribute_t *this,
-                                                                                       identification_t *id, host_t *vip)
-{
-       if (vip)
-       {
-               enumerator_t *enumerator;
-
-               enumerator = this->db->query(this->db,
-                                               "SELECT type, value FROM attributes", DB_INT, DB_BLOB);
-               if (enumerator)
-               {
-                       return enumerator;
-               }
-       }
-       return enumerator_create_empty();
-}
-
-/**
- * Implementation of sql_attribute_t.destroy
- */
-static void destroy(private_sql_attribute_t *this)
-{
-       free(this);
-}
-
-/*
- * see header file
- */
-sql_attribute_t *sql_attribute_create(database_t *db)
-{
-       private_sql_attribute_t *this = malloc_thing(private_sql_attribute_t);
-       time_t now = time(NULL);
-
-       this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address;
-       this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
-       this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *host))create_attribute_enumerator;
-       this->public.destroy = (void(*)(sql_attribute_t*))destroy;
-
-       this->db = db;
-       this->history = lib->settings->get_bool(lib->settings,
-                                               "libstrongswan.plugins.attr-sql.lease_history", TRUE);
-
-       /* close any "online" leases in the case we crashed */
-       if (this->history)
-       {
-               this->db->execute(this->db, NULL,
-                                       "INSERT INTO leases (address, identity, acquired, released)"
-                                       " SELECT id, identity, acquired, ? FROM addresses "
-                                       " WHERE released = 0", DB_UINT, now);
-       }
-       this->db->execute(this->db, NULL,
-                                         "UPDATE addresses SET released = ? WHERE released = 0",
-                                         DB_UINT, now);
-       return &this->public;
-}
-
diff --git a/src/libstrongswan/plugins/attr_sql/sql_attribute.h b/src/libstrongswan/plugins/attr_sql/sql_attribute.h
deleted file mode 100644 (file)
index ca87eb2..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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.
- */
-
-/**
- * @defgroup sql_attribute sql_attribute
- * @{ @ingroup attr_sql
- */
-
-#ifndef SQL_ATTRIBUTE_H_
-#define SQL_ATTRIBUTE_H_
-
-#include <attributes/attribute_provider.h>
-#include <database/database.h>
-
-typedef struct sql_attribute_t sql_attribute_t;
-
-/**
- * SQL database based IKEv2 cfg attribute provider.
- */
-struct sql_attribute_t {
-
-       /**
-        * Implements attribute provider interface
-        */
-       attribute_provider_t provider;
-
-       /**
-        * Destroy a sql_attribute instance.
-        */
-       void (*destroy)(sql_attribute_t *this);
-};
-
-/**
- * Create a sql_attribute instance.
- */
-sql_attribute_t *sql_attribute_create(database_t *db);
-
-#endif /** SQL_ATTRIBUTE_H_ @}*/