pool: Move the pool utility to its own directory in src
authorTobias Brunner <tobias@strongswan.org>
Thu, 5 Sep 2013 16:00:48 +0000 (18:00 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 11 Oct 2013 13:16:05 +0000 (15:16 +0200)
16 files changed:
configure.ac
src/Makefile.am
src/libhydra/plugins/attr_sql/.gitignore [deleted file]
src/libhydra/plugins/attr_sql/Makefile.am
src/libhydra/plugins/attr_sql/pool.c [deleted file]
src/libhydra/plugins/attr_sql/pool_attributes.c [deleted file]
src/libhydra/plugins/attr_sql/pool_attributes.h [deleted file]
src/libhydra/plugins/attr_sql/pool_usage.c [deleted file]
src/libhydra/plugins/attr_sql/pool_usage.h [deleted file]
src/pool/.gitignore [new file with mode: 0644]
src/pool/Makefile.am [new file with mode: 0644]
src/pool/pool.c [new file with mode: 0644]
src/pool/pool_attributes.c [new file with mode: 0644]
src/pool/pool_attributes.h [new file with mode: 0644]
src/pool/pool_usage.c [new file with mode: 0644]
src/pool/pool_usage.h [new file with mode: 0644]

index 0f55816..66cbfa9 100644 (file)
@@ -1478,6 +1478,7 @@ AC_CONFIG_FILES([
        src/scepclient/Makefile
        src/pki/Makefile
        src/pki/man/Makefile
+       src/pool/Makefile
        src/dumm/Makefile
        src/dumm/ext/extconf.rb
        src/libfast/Makefile
index 8ed45ac..218c943 100644 (file)
@@ -100,6 +100,10 @@ if USE_INTEGRITY_TEST
   SUBDIRS += checksum
 endif
 
+if USE_ATTR_SQL
+  SUBDIRS += pool
+endif
+
 if USE_TKM
   SUBDIRS += charon-tkm
 endif
diff --git a/src/libhydra/plugins/attr_sql/.gitignore b/src/libhydra/plugins/attr_sql/.gitignore
deleted file mode 100644 (file)
index eae4e6a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-pool
index 4c369a2..d126bb0 100644 (file)
@@ -1,7 +1,6 @@
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/libstrongswan \
-       -I$(top_srcdir)/src/libhydra \
-       -DPLUGINS=\""${pool_plugins}\""
+       -I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
        -rdynamic
@@ -17,10 +16,3 @@ libstrongswan_attr_sql_la_SOURCES = \
        sql_attribute.h sql_attribute.c
 
 libstrongswan_attr_sql_la_LDFLAGS = -module -avoid-version
-
-ipsec_PROGRAMS = pool
-pool_SOURCES = pool.c pool_attributes.c pool_attributes.h \
-                          pool_usage.h pool_usage.c
-pool_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
-                        $(top_builddir)/src/libhydra/libhydra.la
-pool.o :       $(top_builddir)/config.status
diff --git a/src/libhydra/plugins/attr_sql/pool.c b/src/libhydra/plugins/attr_sql/pool.c
deleted file mode 100644 (file)
index 4e7c48e..0000000
+++ /dev/null
@@ -1,1287 +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 <utils/debug.h>
-#include <library.h>
-#include <networking/host.h>
-#include <utils/identification.h>
-#include <attributes/attributes.h>
-
-#include "pool_attributes.h"
-#include "pool_usage.h"
-
-/**
- * global database handle
- */
-database_t *db;
-
-/**
- * --start/--end addresses of various subcommands
- */
-host_t *start = NULL, *end = 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");
-}
-
-/**
- * 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;
-}
-
-/**
- * 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);
-                       }
-                       if (!size)
-                       {       /* empty pool */
-                               printf("%6d %11s %11s ", 0, "n/a", "n/a");
-                               goto next_pool;
-                       }
-                       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 leases */
-                       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);
-
-next_pool:
-                       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");
-}
-
-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)
-       {
-               identification_t *id = identification_create_from_string(pos_eq + 1);
-               user_id = get_identity(id);
-               id->destroy(id);
-
-               if (user_id == 0)
-               {
-                       return FALSE;
-               }
-               *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 != AF_UNSPEC &&
-               *family != address->get_family(address))
-       {
-               fprintf(stderr, "invalid address family '%s'.\n", address_str);
-               address->destroy(address);
-               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);
-               address->destroy(address);
-               return FALSE;
-       }
-       if (family)
-       {
-               *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)
-               {
-                       if (file != stdin)
-                       {
-                               fclose(file);
-                       }
-                       exit(EXIT_FAILURE);
-               }
-               ++count;
-       }
-
-       if (file != stdin)
-       {
-               fclose(file);
-       }
-
-       if (family == AF_INET6)
-       {       /* update address family if necessary */
-               addr = host_create_from_string("%any6", 0);
-               if (db->execute(db, NULL,
-                                       "UPDATE pools SET start = ?, end = ? WHERE id = ?",
-                                       DB_BLOB, addr->get_address(addr),
-                                       DB_BLOB, addr->get_address(addr), DB_UINT, pool_id) <= 0)
-               {
-                       addr->destroy(addr);
-                       fprintf(stderr, "updating pool address family failed.\n");
-                       exit(EXIT_FAILURE);
-               }
-               addr->destroy(addr);
-       }
-
-       commit_transaction();
-
-       printf("%d addresses done.\n", count);
-}
-
-/**
- * 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 --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");
-
-}
-
-/**
- * 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);
-}
-
-static void do_args(int argc, char *argv[])
-{
-       char *name = "", *value = "", *filter = "";
-       char *pool = NULL, *identity = NULL, *addresses = NULL;
-       value_type_t value_type = VALUE_NONE;
-       int timeout = 0;
-       bool utc = FALSE, hexout = FALSE;
-
-       enum {
-               OP_UNDEF,
-               OP_USAGE,
-               OP_STATUS,
-               OP_STATUS_ATTR,
-               OP_ADD,
-               OP_ADD_ATTR,
-               OP_DEL,
-               OP_DEL_ATTR,
-               OP_SHOW_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' },
-                       { "statusattr", no_argument, NULL, '1' },
-                       { "addattr", required_argument, NULL, '2' },
-                       { "delattr", required_argument, NULL, '3' },
-                       { "showattr", no_argument, NULL, '4' },
-                       { "batch", required_argument, NULL, 'b' },
-
-                       { "start", required_argument, NULL, 's' },
-                       { "end", required_argument, NULL, 'e' },
-                       { "addresses", required_argument, NULL, 'y' },
-                       { "timeout", required_argument, NULL, 't' },
-                       { "filter", required_argument, NULL, 'f' },
-                       { "addr", required_argument, NULL, 'v' },
-                       { "mask", required_argument, NULL, 'v' },
-                       { "server", required_argument, NULL, 'v' },
-                       { "subnet", required_argument, NULL, 'n' },
-                       { "string", required_argument, NULL, 'g' },
-                       { "hex", required_argument, NULL, 'x' },
-                       { "hexout", no_argument, NULL, '5' },
-                       { "pool", required_argument, NULL, '6' },
-                       { "identity", required_argument, NULL, '7' },
-                       { 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 '1':
-                               operation = OP_STATUS_ATTR;
-                               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: "
-                                                                       "reserved for '%s' attribute.\n", optarg);
-                                       usage();
-                                       exit(EXIT_FAILURE);
-                               }
-                               continue;
-                       case '2':
-                               name = optarg;
-                               operation = OP_ADD_ATTR;
-                               continue;
-                       case 'd':
-                               name = optarg;
-                               operation = is_attribute(name) ? OP_DEL_ATTR : OP_DEL;
-                               continue;
-                       case '3':
-                               name = optarg;
-                               operation = OP_DEL_ATTR;
-                               continue;
-                       case '4':
-                               operation = OP_SHOW_ATTR;
-                               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 'y':
-                               addresses = optarg;
-                               continue;
-                       case 'g':
-                               value_type = VALUE_STRING;
-                               value = optarg;
-                               continue;
-                       case 'n':
-                               value_type = VALUE_SUBNET;
-                               value = optarg;
-                               continue;
-                       case 'v':
-                               value_type = VALUE_ADDR;
-                               value = optarg;
-                               continue;
-                       case 'x':
-                               value_type = VALUE_HEX;
-                               value = optarg;
-                               continue;
-                       case '5':
-                               hexout = TRUE;
-                               continue;
-                       case '6':
-                               pool = optarg;
-                               continue;
-                       case '7':
-                               identity = optarg;
-                               continue;
-                       default:
-                               usage();
-                               exit(EXIT_FAILURE);
-                               break;
-               }
-               break;
-       }
-
-       switch (operation)
-       {
-               case OP_USAGE:
-                       usage();
-                       break;
-               case OP_STATUS:
-                       status();
-                       break;
-               case OP_STATUS_ATTR:
-                       status_attr(hexout);
-                       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 (value_type == VALUE_NONE)
-                       {
-                               fprintf(stderr, "missing arguments.\n");
-                               usage();
-                               exit(EXIT_FAILURE);
-                       }
-                       if (identity && !pool)
-                       {
-                               fprintf(stderr, "--identity option can't be used without --pool.\n");
-                               usage();
-                               exit(EXIT_FAILURE);
-                       }
-                       add_attr(name, pool, identity, value, value_type);
-                       break;
-               case OP_DEL:
-                       del(name);
-                       break;
-               case OP_DEL_ATTR:
-                       if (identity && !pool)
-                       {
-                               fprintf(stderr, "--identity option can't be used without --pool.\n");
-                               usage();
-                               exit(EXIT_FAILURE);
-                       }
-                       del_attr(name, pool, identity, value, value_type);
-                       break;
-               case OP_SHOW_ATTR:
-                       show_attr();
-                       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,
-                       lib->settings->get_str(lib->settings, "pool.load", PLUGINS)))
-       {
-               exit(SS_RC_INITIALIZATION_FAILED);
-       }
-
-       uri = lib->settings->get_str(lib->settings, "libhydra.plugins.attr-sql.database", NULL);
-       if (!uri)
-       {
-               fprintf(stderr, "database URI libhydra.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/pool_attributes.c b/src/libhydra/plugins/attr_sql/pool_attributes.c
deleted file mode 100644 (file)
index 1d1ba8f..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Andreas Steffen
- * 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 <string.h>
-
-#include <library.h>
-#include <networking/host.h>
-
-#include "pool_attributes.h"
-#include "pool_usage.h"
-
-/**
- * global database handle
- */
-extern database_t *db;
-
-#define UNITY_NETWORK_LEN      14
-
-ENUM(value_type_names, VALUE_HEX, VALUE_SUBNET,
-       "hex",
-       "string",
-       "addr",
-       "subnet"
-);
-
-typedef struct attr_info_t attr_info_t;
-
-struct attr_info_t {
-       char*                           keyword;
-       value_type_t                    value_type;
-       configuration_attribute_type_t  type;
-       configuration_attribute_type_t  type_ip6;
-};
-
-static const attr_info_t attr_info[] = {
-       { "internal_ip4_netmask", VALUE_ADDR,   INTERNAL_IP4_NETMASK, 0 },
-       { "internal_ip6_netmask", VALUE_ADDR,   INTERNAL_IP6_NETMASK, 0 },
-       { "netmask",              VALUE_ADDR,   INTERNAL_IP4_NETMASK,
-                                                                                       INTERNAL_IP6_NETMASK    },
-       { "internal_ip4_dns",     VALUE_ADDR,   INTERNAL_IP4_DNS,     0 },
-       { "internal_ip6_dns",     VALUE_ADDR,   INTERNAL_IP6_DNS,     0 },
-       { "dns",                  VALUE_ADDR,   INTERNAL_IP4_DNS,
-                                                                                       INTERNAL_IP6_DNS        },
-       { "internal_ip4_nbns",    VALUE_ADDR,   INTERNAL_IP4_NBNS,    0 },
-       { "internal_ip6_nbns",    VALUE_ADDR,   INTERNAL_IP6_NBNS,    0 },
-       { "nbns",                 VALUE_ADDR,   INTERNAL_IP4_NBNS,
-                                                                                       INTERNAL_IP6_NBNS       },
-       { "wins",                 VALUE_ADDR,   INTERNAL_IP4_NBNS,
-                                                                                       INTERNAL_IP6_NBNS       },
-       { "internal_ip4_dhcp",    VALUE_ADDR,   INTERNAL_IP4_DHCP,    0 },
-       { "internal_ip6_dhcp",    VALUE_ADDR,   INTERNAL_IP6_DHCP,    0 },
-       { "dhcp",                 VALUE_ADDR,   INTERNAL_IP4_DHCP,
-                                                                                       INTERNAL_IP6_DHCP       },
-       { "internal_ip4_server",  VALUE_ADDR,   INTERNAL_IP4_SERVER,  0 },
-       { "internal_ip6_server",  VALUE_ADDR,   INTERNAL_IP6_SERVER,  0 },
-       { "server",               VALUE_ADDR,   INTERNAL_IP4_SERVER,
-                                                                                       INTERNAL_IP6_SERVER     },
-       { "application_version",  VALUE_STRING, APPLICATION_VERSION,  0 },
-       { "version",              VALUE_STRING, APPLICATION_VERSION,  0 },
-       { "unity_banner",         VALUE_STRING, UNITY_BANNER,         0 },
-       { "banner",               VALUE_STRING, UNITY_BANNER,         0 },
-       { "unity_def_domain",     VALUE_STRING, UNITY_DEF_DOMAIN,     0 },
-       { "unity_splitdns_name",  VALUE_STRING, UNITY_SPLITDNS_NAME,  0 },
-       { "unity_split_include",  VALUE_SUBNET, UNITY_SPLIT_INCLUDE,  0 },
-       { "unity_split_exclude",  VALUE_SUBNET, UNITY_LOCAL_LAN,      0 },
-       { "unity_local_lan",      VALUE_SUBNET, UNITY_LOCAL_LAN,      0 },
-};
-
-/**
- * Determine the type of the attribute and its value
- */
-static bool parse_attributes(char *name, char *value, value_type_t *value_type,
-                                                        configuration_attribute_type_t *type,
-                                                        configuration_attribute_type_t *type_ip6,
-                                                        chunk_t *blob)
-{
-       host_t *addr = NULL, *mask = NULL;
-       chunk_t addr_chunk, mask_chunk, blob_next;
-       char *text = "", *pos_addr, *pos_mask, *pos_next, *endptr;
-       int i;
-
-       switch (*value_type)
-       {
-               case VALUE_STRING:
-                       *blob = chunk_create(value, strlen(value));
-                       *blob = chunk_clone(*blob);
-                       break;
-               case VALUE_HEX:
-                       *blob = chunk_from_hex(chunk_create(value, strlen(value)), NULL);
-                       break;
-               case VALUE_ADDR:
-                       addr = host_create_from_string(value, 0);
-                       if (addr == NULL)
-                       {
-                               fprintf(stderr, "invalid IP address: '%s'.\n", value);
-                               return FALSE;
-                       }
-                       addr_chunk = addr->get_address(addr);
-                       *blob = chunk_clone(addr_chunk);
-                       break;
-               case VALUE_SUBNET:
-                       *blob = chunk_empty;
-                       pos_next = value;
-
-                       do
-                       {
-                               pos_addr = pos_next;
-                               pos_next = strchr(pos_next, ',');
-                               if (pos_next)
-                               {
-                                       *pos_next = '\0';
-                                       pos_next += 1;
-                               }
-                               pos_mask = strchr(pos_addr, '/');
-                               if (pos_mask == NULL)
-                               {
-                                       fprintf(stderr, "invalid IPv4 subnet: '%s'.\n", pos_addr);
-                                       free(blob->ptr);
-                                       return FALSE;
-                               }
-                               *pos_mask = '\0';
-                               pos_mask += 1;
-                               addr = host_create_from_string(pos_addr, 0);
-                               mask = host_create_from_string(pos_mask, 0);
-                               if (addr == NULL || addr->get_family(addr) != AF_INET ||
-                                       mask == NULL || mask->get_family(addr) != AF_INET)
-                               {
-                                       fprintf(stderr, "invalid IPv4 subnet: '%s/%s'.\n",
-                                                                       pos_addr, pos_mask);
-                                       DESTROY_IF(addr);
-                                       DESTROY_IF(mask);
-                                       free(blob->ptr);
-                                       return FALSE;
-                               }
-                               addr_chunk = addr->get_address(addr);
-                               mask_chunk = mask->get_address(mask);
-                               blob_next = chunk_alloc(blob->len + UNITY_NETWORK_LEN);
-                               memcpy(blob_next.ptr, blob->ptr, blob->len);
-                               pos_addr = blob_next.ptr + blob->len;
-                               memset(pos_addr, 0x00, UNITY_NETWORK_LEN);
-                               memcpy(pos_addr,     addr_chunk.ptr, 4);
-                               memcpy(pos_addr + 4, mask_chunk.ptr, 4);
-                               addr->destroy(addr);
-                               addr = NULL;
-                               mask->destroy(mask);
-                               chunk_free(blob);
-                               *blob = blob_next;
-                       }
-                       while (pos_next);
-                       break;
-               case VALUE_NONE:
-                       *blob = chunk_empty;
-                       break;
-       }
-
-       /* init the attribute type */
-       *type     = 0;
-       *type_ip6 = 0;
-
-       for (i = 0; i < countof(attr_info); i++)
-       {
-               if (strcaseeq(name, attr_info[i].keyword))
-               {
-                       *type      = attr_info[i].type;
-                       *type_ip6  = attr_info[i].type_ip6;
-
-                       if (*value_type == VALUE_NONE)
-                       {
-                               *value_type = attr_info[i].value_type;
-                               return TRUE;
-                       }
-
-                       if (*value_type != attr_info[i].value_type &&
-                               *value_type != VALUE_HEX)
-                       {
-                               switch (attr_info[i].value_type)
-                               {
-                                       case VALUE_STRING:
-                                               text = "a string";
-                                               break;
-                                       case VALUE_HEX:
-                                               text = "a hex";
-                                               break;
-                                       case VALUE_ADDR:
-                                               text = "an IP address";
-                                               break;
-                                       case VALUE_SUBNET:
-                                               text = "a subnet";
-                                               break;
-                                       case VALUE_NONE:
-                                               text = "no";
-                                               break;
-                               }
-                               fprintf(stderr, "the %s attribute requires %s value.\n",
-                                                                name, text);
-                               DESTROY_IF(addr);
-                               free(blob->ptr);
-                               return FALSE;
-                       }
-
-                       if (*value_type == VALUE_ADDR)
-                       {
-                               *type = (addr->get_family(addr) == AF_INET) ?
-                                                       attr_info[i].type : attr_info[i].type_ip6;
-                               addr->destroy(addr);
-                       }
-                       else if (*value_type == VALUE_HEX)
-                       {
-                               *value_type = attr_info[i].value_type;
-
-                               if (*value_type == VALUE_ADDR)
-                               {
-                                       if (blob->len == 16)
-                                       {
-                                               *type = attr_info[i].type_ip6;
-                                       }
-                                       else if (blob->len != 4)
-                                       {
-                                               fprintf(stderr, "the %s attribute requires "
-                                                                               "a valid IP address.\n", name);
-                                               free(blob->ptr);
-                                               return FALSE;
-                                       }
-                               }
-                       }
-                       return TRUE;
-               }
-       }
-
-       /* clean up */
-       DESTROY_IF(addr);
-
-       /* is the attribute type numeric? */
-       *type = strtol(name, &endptr, 10);
-
-       if (*endptr != '\0')
-       {
-               fprintf(stderr, "the %s attribute is not recognized.\n", name);
-               free(blob->ptr);
-               return FALSE;
-       }
-       if (*type < 1 || *type > 32767)
-       {
-               fprintf(stderr, "the attribute type must lie in the range 1..32767.\n");
-               free(blob->ptr);
-               return FALSE;
-       }
-       if (*value_type == VALUE_NONE)
-       {
-               *value_type = VALUE_HEX;
-       }
-       return TRUE;
-}
-
-/**
- * Lookup/insert an attribute pool by name
- */
-static u_int get_attr_pool(char *name)
-{
-       enumerator_t *e;
-       u_int row = 0;
-
-       /* look for an existing attribute pool in the table */
-       e = db->query(db, "SELECT id FROM attribute_pools WHERE name = ?",
-                                 DB_TEXT, name, DB_UINT);
-       if (e && e->enumerate(e, &row))
-       {
-               e->destroy(e);
-               return row;
-       }
-       DESTROY_IF(e);
-       /* not found, insert new one */
-       if (db->execute(db, &row, "INSERT INTO attribute_pools (name) VALUES (?)",
-                                       DB_TEXT, name) != 1)
-       {
-               fprintf(stderr, "creating attribute pool '%s' failed.\n", name);
-               return 0;
-       }
-       return row;
-}
-
-/**
- * Lookup/insert an identity
- */
-u_int get_identity(identification_t *id)
-{
-       enumerator_t *e;
-       u_int row;
-
-       /* 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, &row))
-       {
-               e->destroy(e);
-               return row;
-       }
-       DESTROY_IF(e);
-       /* not found, insert new one */
-       if (db->execute(db, &row, "INSERT INTO identities (type,data) VALUES (?,?)",
-                                 DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) != 1)
-       {
-               fprintf(stderr, "creating id '%Y' failed.\n", id);
-               return 0;
-       }
-       return row;
-}
-
-/**
- * ipsec pool --addattr <type> - add attribute entry
- */
-void add_attr(char *name, char *pool, char *identity,
-                         char *value, value_type_t value_type)
-{
-       configuration_attribute_type_t type, type_ip6;
-       u_int pool_id = 0, identity_id = 0;
-       char id_pool_str[128] = "";
-       chunk_t blob;
-       bool success;
-
-       if (pool)
-       {
-               pool_id = get_attr_pool(pool);
-               if (pool_id == 0)
-               {
-                       exit(EXIT_FAILURE);
-               }
-
-               if (identity)
-               {
-                       identification_t *id;
-
-                       id = identification_create_from_string(identity);
-                       identity_id = get_identity(id);
-                       id->destroy(id);
-                       if (identity_id == 0)
-                       {
-                               exit(EXIT_FAILURE);
-                       }
-                       snprintf(id_pool_str, sizeof(id_pool_str),
-                                        " for '%s' in pool '%s'", identity, pool);
-               }
-               else
-               {
-                       snprintf(id_pool_str, sizeof(id_pool_str), " in pool '%s'", pool);
-               }
-       }
-
-       if (value_type == VALUE_NONE)
-       {
-               fprintf(stderr, "the value of the %s attribute is missing.\n", name);
-               usage();
-       }
-       if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob))
-       {
-               exit(EXIT_FAILURE);
-       }
-
-       success = db->execute(db, NULL,
-                               "INSERT INTO attributes (identity, pool, type, value) "
-                               "VALUES (?, ?, ?, ?)", DB_UINT, identity_id, DB_UINT, pool_id,
-                               DB_INT, type, DB_BLOB, blob) == 1;
-       free(blob.ptr);
-
-       if (success)
-       {
-               printf("added %s attribute (%N)%s.\n", name,
-                          configuration_attribute_type_names, type, id_pool_str);
-       }
-       else
-       {
-               fprintf(stderr, "adding %s attribute (%N)%s failed.\n", name,
-                                               configuration_attribute_type_names, type, id_pool_str);
-       }
-}
-
-/**
- * ipsec pool --delattr <type> - delete attribute entry
- */
-void del_attr(char *name, char *pool, char *identity,
-                         char *value, value_type_t value_type)
-{
-       configuration_attribute_type_t type, type_ip6, type_db;
-       u_int pool_id = 0, identity_id = 0;
-       char id_pool_str[128] = "";
-       chunk_t blob, blob_db;
-       u_int id;
-       enumerator_t *query;
-       bool found = FALSE;
-
-       if (pool)
-       {
-               pool_id = get_attr_pool(pool);
-               if (pool_id == 0)
-               {
-                       exit(EXIT_FAILURE);
-               }
-
-               if (identity)
-               {
-                       identification_t *id;
-
-                       id = identification_create_from_string(identity);
-                       identity_id = get_identity(id);
-                       id->destroy(id);
-                       if (identity_id == 0)
-                       {
-                               exit(EXIT_FAILURE);
-                       }
-                       snprintf(id_pool_str, sizeof(id_pool_str),
-                                        " for '%s' in pool '%s'", identity, pool);
-               }
-               else
-               {
-                       snprintf(id_pool_str, sizeof(id_pool_str), " in pool '%s'", pool);
-               }
-       }
-
-       if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob))
-       {
-               exit(EXIT_FAILURE);
-       }
-
-       if (blob.len > 0)
-       {
-               query = db->query(db,
-                                       "SELECT id, type, value FROM attributes "
-                                       "WHERE identity = ? AND pool = ? AND type = ? AND value = ?",
-                                       DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
-                                       DB_BLOB, blob, DB_UINT, DB_INT, DB_BLOB);
-       }
-       else if (type_ip6 == 0)
-       {
-               query = db->query(db,
-                                       "SELECT id, type, value FROM attributes "
-                                       "WHERE identity = ? AND pool = ? AND type = ?",
-                                       DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
-                                       DB_UINT, DB_INT, DB_BLOB);
-       }
-       else
-       {
-               query = db->query(db,
-                                       "SELECT id, type, value FROM attributes "
-                                       "WHERE identity = ? AND pool = ? AND (type = ? OR type = ?)",
-                                       DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
-                                       DB_INT, type_ip6, DB_UINT, DB_INT, DB_BLOB);
-       }
-
-       if (!query)
-       {
-               fprintf(stderr, "deleting '%s' attribute (%N)%s failed.\n",
-                               name, configuration_attribute_type_names, type, id_pool_str);
-               free(blob.ptr);
-               exit(EXIT_FAILURE);
-       }
-
-       while (query->enumerate(query, &id, &type_db, &blob_db))
-       {
-               host_t *server = NULL;
-
-               found = TRUE;
-
-               if (value_type == VALUE_ADDR)
-               {
-                       int family = (type_db == type_ip6) ? AF_INET6 : AF_INET;
-
-                       server = host_create_from_chunk(family, blob_db, 0);
-               }
-
-               if (db->execute(db, NULL,
-                                       "DELETE FROM attributes WHERE id = ?",
-                                        DB_UINT, id) != 1)
-               {
-                       if (server)
-                       {
-                               fprintf(stderr, "deleting %s server %H%s failed\n",
-                                               name, server, id_pool_str);
-                               server->destroy(server);
-                       }
-                       else if (value_type == VALUE_STRING)
-                       {
-                               fprintf(stderr, "deleting %s attribute (%N) with value '%.*s'%s failed.\n",
-                                                               name, configuration_attribute_type_names, type,
-                                                               (int)blob_db.len, blob_db.ptr, id_pool_str);
-                       }
-
-                       else
-                       {
-                               fprintf(stderr, "deleting %s attribute (%N) with value %#B%s failed.\n",
-                                                               name, configuration_attribute_type_names, type,
-                                                               &blob_db, id_pool_str);
-                       }
-                       query->destroy(query);
-                       free(blob.ptr);
-                       exit(EXIT_FAILURE);
-               }
-               if (server)
-               {
-                       printf("deleted %s server %H%s\n", name, server, id_pool_str);
-                       server->destroy(server);
-               }
-               else if (value_type == VALUE_STRING)
-               {
-                       printf("deleted %s attribute (%N) with value '%.*s'%s.\n",
-                                  name, configuration_attribute_type_names, type,
-                                  (int)blob_db.len, blob_db.ptr, id_pool_str);
-               }
-               else
-               {
-                       printf("deleted %s attribute (%N) with value %#B%s.\n",
-                                  name, configuration_attribute_type_names, type,
-                                  &blob_db, id_pool_str);
-               }
-       }
-       query->destroy(query);
-
-       if (!found)
-       {
-               if (blob.len == 0)
-               {
-                       if (type_ip6 == 0)
-                       {
-                               fprintf(stderr, "no %s attribute (%N) was found%s.\n", name,
-                                               configuration_attribute_type_names, type, id_pool_str);
-                       }
-                       else
-                       {
-                               fprintf(stderr, "no %s attribute%s was found.\n",
-                                               name, id_pool_str);
-                       }
-               }
-               else
-               {
-                       if (value_type == VALUE_ADDR)
-                       {
-                               host_t *server = host_create_from_chunk(AF_UNSPEC, blob, 0);
-
-                               fprintf(stderr, "the %s server %H%s was not found.\n", name,
-                                                                server, id_pool_str);
-                               server->destroy(server);
-                       }
-                       else
-                       {
-                               fprintf(stderr, "the %s attribute (%N) with value '%.*s'%s "
-                                                               "was not found.\n", name,
-                                                                configuration_attribute_type_names, type,
-                                                                (int)blob.len, blob.ptr, id_pool_str);
-                       }
-               }
-       }
-       free(blob.ptr);
-}
-
-/**
- * ipsec pool --statusattr - show all attribute entries
- */
-void status_attr(bool hexout)
-{
-       configuration_attribute_type_t type;
-       value_type_t value_type;
-       chunk_t value, addr_chunk, mask_chunk, identity_chunk;
-       identification_t *identity;
-       enumerator_t *enumerator;
-       host_t *addr, *mask;
-       char type_name[30];
-       bool first = TRUE;
-       int i, identity_type;
-       char *pool_name;
-
-       /* enumerate over all attributes */
-       enumerator = db->query(db,
-                                       "SELECT attributes.type, attribute_pools.name, "
-                                       "identities.type, identities.data, attributes.value "
-                                       "FROM attributes "
-                                       "LEFT OUTER JOIN identities "
-                                       "ON attributes.identity = identities.id "
-                                       "LEFT OUTER JOIN attribute_pools "
-                                       "ON attributes.pool = attribute_pools.id "
-                                       "ORDER BY attributes.type, attribute_pools.name, "
-                                       "identities.type, identities.data, attributes.value",
-                                       DB_INT, DB_TEXT, DB_INT, DB_BLOB, DB_BLOB);
-       if (enumerator)
-       {
-               while (enumerator->enumerate(enumerator, &type,&pool_name,
-                                                                        &identity_type, &identity_chunk, &value))
-               {
-                       if (first)
-                       {
-                               printf(" type  description           pool       "
-                                          " identity              value\n");
-                               first = FALSE;
-                       }
-                       snprintf(type_name, sizeof(type_name), "%N",
-                                        configuration_attribute_type_names, type);
-                       if (type_name[0] == '(')
-                       {
-                               type_name[0] = '\0';
-                       }
-                       printf("%5d  %-20s ",type, type_name);
-
-                       printf(" %-10s ", (pool_name ? pool_name : ""));
-
-                       if (identity_type)
-                       {
-                               identity = identification_create_from_encoding(identity_type, identity_chunk);
-                               printf(" %-20.20Y ", identity);
-                               identity->destroy(identity);
-                       }
-                       else
-                       {
-                               printf("                      ");
-                       }
-
-                       value_type = VALUE_HEX;
-                       if (!hexout)
-                       {
-                               for (i = 0; i < countof(attr_info); i++)
-                               {
-                                       if (type == attr_info[i].type)
-                                       {
-                                               value_type = attr_info[i].value_type;
-                                               break;
-                                       }
-                               }
-                       }
-                       switch (value_type)
-                       {
-                               case VALUE_ADDR:
-                                       addr = host_create_from_chunk(AF_UNSPEC, value, 0);
-                                       if (addr)
-                                       {
-                                               printf(" %H\n", addr);
-                                               addr->destroy(addr);
-                                       }
-                                       else
-                                       {
-                                               /* value cannot be represented as an IP address */
-                                               printf(" %#B\n", &value);
-                                       }
-                                       break;
-                               case VALUE_SUBNET:
-                                       if (value.len % UNITY_NETWORK_LEN == 0)
-                                       {
-                                               for (i = 0; i < value.len / UNITY_NETWORK_LEN; i++)
-                                               {
-                                                       addr_chunk = chunk_create(value.ptr + i*UNITY_NETWORK_LEN, 4);
-                                                       addr = host_create_from_chunk(AF_INET, addr_chunk, 0);
-                                                       mask_chunk = chunk_create(addr_chunk.ptr + 4, 4);
-                                                       mask = host_create_from_chunk(AF_INET, mask_chunk, 0);
-                                                       printf("%s%H/%H", (i > 0) ? "," : " ", addr, mask);
-                                                       addr->destroy(addr);
-                                                       mask->destroy(mask);
-                                               }
-                                               printf("\n");
-                                       }
-                                       else
-                                       {
-                                               /* value cannot be represented as a list of subnets */
-                                               printf(" %#B\n", &value);
-                                       }
-                                       break;
-                               case VALUE_STRING:
-                                       printf("\"%.*s\"\n", (int)value.len, value.ptr);
-                                       break;
-                               case VALUE_HEX:
-                               default:
-                                       printf(" %#B\n", &value);
-                       }
-               }
-               enumerator->destroy(enumerator);
-       }
-}
-
-/**
- * ipsec pool --showattr - show all supported attribute keywords
- */
-void show_attr(void)
-{
-       int i;
-
-       for (i = 0; i < countof(attr_info); i++)
-       {
-               char value_name[10];
-
-
-               snprintf(value_name, sizeof(value_name), "%N",
-                       value_type_names, attr_info[i].value_type);
-
-               printf("%-20s  --%-6s  (%N",
-                               attr_info[i].keyword, value_name,
-                               configuration_attribute_type_names, attr_info[i].type);
-
-               if (attr_info[i].type_ip6)
-               {
-                       printf(", %N)\n",
-                               configuration_attribute_type_names, attr_info[i].type_ip6);
-               }
-               else
-               {
-                       printf(")\n");
-               }
-       }
-}
-
diff --git a/src/libhydra/plugins/attr_sql/pool_attributes.h b/src/libhydra/plugins/attr_sql/pool_attributes.h
deleted file mode 100644 (file)
index a42291f..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Andreas Steffen
- * 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.
- */
-
-#ifndef POOL_ATTRIBUTES_H_
-#define POOL_ATTRIBUTES_H_
-
-#include <attributes/attributes.h>
-
-typedef enum value_type_t value_type_t;
-
-enum value_type_t {
-       VALUE_NONE,
-       VALUE_HEX,
-       VALUE_STRING,
-       VALUE_ADDR,
-       VALUE_SUBNET
-};
-
-/**
- * enum names for value_type_t.
- */
-extern enum_name_t *value_type_names;
-
-/**
- * lookup/insert an identity
- */
-u_int get_identity(identification_t *id);
-
-/**
- * ipsec pool --addattr <type>  - add attribute entry
- */
-void add_attr(char *name, char *pool, char *identity,
-                         char *value, value_type_t value_type);
-
-/**
- * ipsec pool --delattr <type>  - delete attribute entry
- */
-void del_attr(char *name, char *pool, char *identity,
-                         char *value, value_type_t value_type);
-
-/**
- * ipsec pool --statusattr      - show all attribute entries
- */
-void status_attr(bool hexout);
-
-/**
- * ipsec pool --showattr - show all supported attribute keywords
- */
-void show_attr(void);
-
-#endif /* POOL_ATTRIBUTES_H_ */
-
-
diff --git a/src/libhydra/plugins/attr_sql/pool_usage.c b/src/libhydra/plugins/attr_sql/pool_usage.c
deleted file mode 100644 (file)
index 985bc3a..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Copyright (C) 2009-2010 Andreas Steffen
- * 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 <stdio.h>
-
-/**
- * print pool usage info
- */
-void usage(void)
-{
-       printf("\
-Usage:\n\
-  ipsec pool --status|--add|--replace|--del|--resize|--leases|--purge [options]\n\
-  ipsec pool --showattr|--statusattr|--addattr|--delattr [options]\n\
-  \n\
-  ipsec pool --status\n\
-    Show a list of installed pools with statistics plus nameserver info.\n\
-  \n\
-  ipsec pool --statusattr [--hexout]\n\
-    Show a list of all attributes stored in the database with the values\n\
-    converted to the correct format if the type is known by --showattr or\n\
-    in hex format otherwise.\n\
-      hexout:  Output all values in hex format\n\
-  \n\
-  ipsec pool --showattr\n\
-    Show a keyword list of the major attribute types.\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 --addattr <type> [--pool <name> [--identity <id>]]\n\
-             --addr|--mask|--server|--subnet|--string|--hex <value>\n\
-    Add a new attribute to the database. Attributes can be bundled by using\n\
-    the --pool and --identity options. If a bundle matches a peer the contained\n\
-    attributes are sent to that peer instead of the global ones.\n\
-      type:    a keyword from --showattr or a number from the range 1..32767\n\
-      name:    the name of the pool this attribute is added to\n\
-      id:      identity of the peer this attribute is bound to\n\
-      addr:    IPv4 or IPv6 address\n\
-      mask:    IPv4 or IPv6 netmask (synonym for --addr)\n\
-      server:  IPv4 or IPv6 address of a server (synonym for --addr)\n\
-      subnet:  IPv4 subnet[s] given by network/mask[,network/mask,...]\n\
-      string:  value of a string-type attribute\n\
-      hex:     hex value of any attribute\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 --delattr <type> [--pool <name> [--identity <id>]]\n\
-             [--addr|--mask|--server|--subnet|--string|--hex <value>]\n\
-    Delete a specific or all attributes of a given type from the database.\n\
-      type:    a keyword from --showattr or a number from the range 1..32767\n\
-      name:    the name of the pool this attribute is added to\n\
-      id:      identity of the peer this attribute is bound to\n\
-      addr:    IPv4 or IPv6 address\n\
-      mask:    IPv4 or IPv6 netmask (synonym for --addr)\n\
-      server:  IPv4 or IPv6 address of a server (synonym for --addr)\n\
-      subnet:  IPv4 subnet[s] given by network/mask[,network/mask,...]\n\
-      string:  value of a string-type attribute\n\
-      hex:     hex value of any attribute\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");
-}
-
diff --git a/src/libhydra/plugins/attr_sql/pool_usage.h b/src/libhydra/plugins/attr_sql/pool_usage.h
deleted file mode 100644 (file)
index a98b0d6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Copyright (C) 2009-2010 Andreas Steffen
- * 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.
- */
-
-#ifndef POOL_USAGE_H_
-#define POOL_USAGE_H_
-
-/**
- * print pool usage info
- */
-void usage(void);
-
-
-#endif /* POOL_USAGE_H_ */
diff --git a/src/pool/.gitignore b/src/pool/.gitignore
new file mode 100644 (file)
index 0000000..eae4e6a
--- /dev/null
@@ -0,0 +1 @@
+pool
diff --git a/src/pool/Makefile.am b/src/pool/Makefile.am
new file mode 100644 (file)
index 0000000..8b429a4
--- /dev/null
@@ -0,0 +1,16 @@
+ipsec_PROGRAMS = pool
+
+pool_SOURCES = \
+       pool.c pool_attributes.c pool_attributes.h \
+       pool_usage.h pool_usage.c
+
+pool.o :       $(top_builddir)/config.status
+
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/src/libstrongswan \
+       -I$(top_srcdir)/src/libhydra \
+       -DPLUGINS=\""${pool_plugins}\""
+
+pool_LDADD = \
+       $(top_builddir)/src/libstrongswan/libstrongswan.la \
+       $(top_builddir)/src/libhydra/libhydra.la
diff --git a/src/pool/pool.c b/src/pool/pool.c
new file mode 100644 (file)
index 0000000..831b3c4
--- /dev/null
@@ -0,0 +1,1286 @@
+/*
+ * 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 <utils/debug.h>
+#include <library.h>
+#include <networking/host.h>
+#include <utils/identification.h>
+#include <attributes/attributes.h>
+
+#include "pool_attributes.h"
+#include "pool_usage.h"
+
+/**
+ * global database handle
+ */
+database_t *db;
+
+/**
+ * --start/--end addresses of various subcommands
+ */
+host_t *start = NULL, *end = 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");
+}
+
+/**
+ * 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;
+}
+
+/**
+ * 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);
+                       }
+                       if (!size)
+                       {       /* empty pool */
+                               printf("%6d %11s %11s ", 0, "n/a", "n/a");
+                               goto next_pool;
+                       }
+                       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 leases */
+                       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);
+
+next_pool:
+                       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");
+}
+
+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)
+       {
+               identification_t *id = identification_create_from_string(pos_eq + 1);
+               user_id = get_identity(id);
+               id->destroy(id);
+
+               if (user_id == 0)
+               {
+                       return FALSE;
+               }
+               *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 != AF_UNSPEC &&
+               *family != address->get_family(address))
+       {
+               fprintf(stderr, "invalid address family '%s'.\n", address_str);
+               address->destroy(address);
+               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);
+               address->destroy(address);
+               return FALSE;
+       }
+       if (family)
+       {
+               *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)
+               {
+                       if (file != stdin)
+                       {
+                               fclose(file);
+                       }
+                       exit(EXIT_FAILURE);
+               }
+               ++count;
+       }
+
+       if (file != stdin)
+       {
+               fclose(file);
+       }
+
+       if (family == AF_INET6)
+       {       /* update address family if necessary */
+               addr = host_create_from_string("%any6", 0);
+               if (db->execute(db, NULL,
+                                       "UPDATE pools SET start = ?, end = ? WHERE id = ?",
+                                       DB_BLOB, addr->get_address(addr),
+                                       DB_BLOB, addr->get_address(addr), DB_UINT, pool_id) <= 0)
+               {
+                       addr->destroy(addr);
+                       fprintf(stderr, "updating pool address family failed.\n");
+                       exit(EXIT_FAILURE);
+               }
+               addr->destroy(addr);
+       }
+
+       commit_transaction();
+
+       printf("%d addresses done.\n", count);
+}
+
+/**
+ * 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 --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");
+
+}
+
+/**
+ * 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);
+}
+
+static void do_args(int argc, char *argv[])
+{
+       char *name = "", *value = "", *filter = "";
+       char *pool = NULL, *identity = NULL, *addresses = NULL;
+       value_type_t value_type = VALUE_NONE;
+       int timeout = 0;
+       bool utc = FALSE, hexout = FALSE;
+
+       enum {
+               OP_UNDEF,
+               OP_USAGE,
+               OP_STATUS,
+               OP_STATUS_ATTR,
+               OP_ADD,
+               OP_ADD_ATTR,
+               OP_DEL,
+               OP_DEL_ATTR,
+               OP_SHOW_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' },
+                       { "statusattr", no_argument, NULL, '1' },
+                       { "addattr", required_argument, NULL, '2' },
+                       { "delattr", required_argument, NULL, '3' },
+                       { "showattr", no_argument, NULL, '4' },
+                       { "batch", required_argument, NULL, 'b' },
+
+                       { "start", required_argument, NULL, 's' },
+                       { "end", required_argument, NULL, 'e' },
+                       { "addresses", required_argument, NULL, 'y' },
+                       { "timeout", required_argument, NULL, 't' },
+                       { "filter", required_argument, NULL, 'f' },
+                       { "addr", required_argument, NULL, 'v' },
+                       { "mask", required_argument, NULL, 'v' },
+                       { "server", required_argument, NULL, 'v' },
+                       { "subnet", required_argument, NULL, 'n' },
+                       { "string", required_argument, NULL, 'g' },
+                       { "hex", required_argument, NULL, 'x' },
+                       { "hexout", no_argument, NULL, '5' },
+                       { "pool", required_argument, NULL, '6' },
+                       { "identity", required_argument, NULL, '7' },
+                       { 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 '1':
+                               operation = OP_STATUS_ATTR;
+                               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: "
+                                                                       "reserved for '%s' attribute.\n", optarg);
+                                       usage();
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
+                       case '2':
+                               name = optarg;
+                               operation = OP_ADD_ATTR;
+                               continue;
+                       case 'd':
+                               name = optarg;
+                               operation = is_attribute(name) ? OP_DEL_ATTR : OP_DEL;
+                               continue;
+                       case '3':
+                               name = optarg;
+                               operation = OP_DEL_ATTR;
+                               continue;
+                       case '4':
+                               operation = OP_SHOW_ATTR;
+                               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 'y':
+                               addresses = optarg;
+                               continue;
+                       case 'g':
+                               value_type = VALUE_STRING;
+                               value = optarg;
+                               continue;
+                       case 'n':
+                               value_type = VALUE_SUBNET;
+                               value = optarg;
+                               continue;
+                       case 'v':
+                               value_type = VALUE_ADDR;
+                               value = optarg;
+                               continue;
+                       case 'x':
+                               value_type = VALUE_HEX;
+                               value = optarg;
+                               continue;
+                       case '5':
+                               hexout = TRUE;
+                               continue;
+                       case '6':
+                               pool = optarg;
+                               continue;
+                       case '7':
+                               identity = optarg;
+                               continue;
+                       default:
+                               usage();
+                               exit(EXIT_FAILURE);
+                               break;
+               }
+               break;
+       }
+
+       switch (operation)
+       {
+               case OP_USAGE:
+                       usage();
+                       break;
+               case OP_STATUS:
+                       status();
+                       break;
+               case OP_STATUS_ATTR:
+                       status_attr(hexout);
+                       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 (value_type == VALUE_NONE)
+                       {
+                               fprintf(stderr, "missing arguments.\n");
+                               usage();
+                               exit(EXIT_FAILURE);
+                       }
+                       if (identity && !pool)
+                       {
+                               fprintf(stderr, "--identity option can't be used without --pool.\n");
+                               usage();
+                               exit(EXIT_FAILURE);
+                       }
+                       add_attr(name, pool, identity, value, value_type);
+                       break;
+               case OP_DEL:
+                       del(name);
+                       break;
+               case OP_DEL_ATTR:
+                       if (identity && !pool)
+                       {
+                               fprintf(stderr, "--identity option can't be used without --pool.\n");
+                               usage();
+                               exit(EXIT_FAILURE);
+                       }
+                       del_attr(name, pool, identity, value, value_type);
+                       break;
+               case OP_SHOW_ATTR:
+                       show_attr();
+                       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,
+                       lib->settings->get_str(lib->settings, "pool.load", PLUGINS)))
+       {
+               exit(SS_RC_INITIALIZATION_FAILED);
+       }
+
+       uri = lib->settings->get_str(lib->settings, "libhydra.plugins.attr-sql.database", NULL);
+       if (!uri)
+       {
+               fprintf(stderr, "database URI libhydra.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/pool/pool_attributes.c b/src/pool/pool_attributes.c
new file mode 100644 (file)
index 0000000..72af4f4
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2009-2010 Andreas Steffen
+ * 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 <string.h>
+
+#include <library.h>
+#include <networking/host.h>
+
+#include "pool_attributes.h"
+#include "pool_usage.h"
+
+/**
+ * global database handle
+ */
+extern database_t *db;
+
+#define UNITY_NETWORK_LEN      14
+
+ENUM(value_type_names, VALUE_HEX, VALUE_SUBNET,
+       "hex",
+       "string",
+       "addr",
+       "subnet"
+);
+
+typedef struct attr_info_t attr_info_t;
+
+struct attr_info_t {
+       char*                           keyword;
+       value_type_t                    value_type;
+       configuration_attribute_type_t  type;
+       configuration_attribute_type_t  type_ip6;
+};
+
+static const attr_info_t attr_info[] = {
+       { "internal_ip4_netmask", VALUE_ADDR,   INTERNAL_IP4_NETMASK, 0 },
+       { "internal_ip6_netmask", VALUE_ADDR,   INTERNAL_IP6_NETMASK, 0 },
+       { "netmask",              VALUE_ADDR,   INTERNAL_IP4_NETMASK,
+                                                                                       INTERNAL_IP6_NETMASK    },
+       { "internal_ip4_dns",     VALUE_ADDR,   INTERNAL_IP4_DNS,     0 },
+       { "internal_ip6_dns",     VALUE_ADDR,   INTERNAL_IP6_DNS,     0 },
+       { "dns",                  VALUE_ADDR,   INTERNAL_IP4_DNS,
+                                                                                       INTERNAL_IP6_DNS        },
+       { "internal_ip4_nbns",    VALUE_ADDR,   INTERNAL_IP4_NBNS,    0 },
+       { "internal_ip6_nbns",    VALUE_ADDR,   INTERNAL_IP6_NBNS,    0 },
+       { "nbns",                 VALUE_ADDR,   INTERNAL_IP4_NBNS,
+                                                                                       INTERNAL_IP6_NBNS       },
+       { "wins",                 VALUE_ADDR,   INTERNAL_IP4_NBNS,
+                                                                                       INTERNAL_IP6_NBNS       },
+       { "internal_ip4_dhcp",    VALUE_ADDR,   INTERNAL_IP4_DHCP,    0 },
+       { "internal_ip6_dhcp",    VALUE_ADDR,   INTERNAL_IP6_DHCP,    0 },
+       { "dhcp",                 VALUE_ADDR,   INTERNAL_IP4_DHCP,
+                                                                                       INTERNAL_IP6_DHCP       },
+       { "internal_ip4_server",  VALUE_ADDR,   INTERNAL_IP4_SERVER,  0 },
+       { "internal_ip6_server",  VALUE_ADDR,   INTERNAL_IP6_SERVER,  0 },
+       { "server",               VALUE_ADDR,   INTERNAL_IP4_SERVER,
+                                                                                       INTERNAL_IP6_SERVER     },
+       { "application_version",  VALUE_STRING, APPLICATION_VERSION,  0 },
+       { "version",              VALUE_STRING, APPLICATION_VERSION,  0 },
+       { "unity_banner",         VALUE_STRING, UNITY_BANNER,         0 },
+       { "banner",               VALUE_STRING, UNITY_BANNER,         0 },
+       { "unity_def_domain",     VALUE_STRING, UNITY_DEF_DOMAIN,     0 },
+       { "unity_splitdns_name",  VALUE_STRING, UNITY_SPLITDNS_NAME,  0 },
+       { "unity_split_include",  VALUE_SUBNET, UNITY_SPLIT_INCLUDE,  0 },
+       { "unity_split_exclude",  VALUE_SUBNET, UNITY_LOCAL_LAN,      0 },
+       { "unity_local_lan",      VALUE_SUBNET, UNITY_LOCAL_LAN,      0 },
+};
+
+/**
+ * Determine the type of the attribute and its value
+ */
+static bool parse_attributes(char *name, char *value, value_type_t *value_type,
+                                                        configuration_attribute_type_t *type,
+                                                        configuration_attribute_type_t *type_ip6,
+                                                        chunk_t *blob)
+{
+       host_t *addr = NULL, *mask = NULL;
+       chunk_t addr_chunk, mask_chunk, blob_next;
+       char *text = "", *pos_addr, *pos_mask, *pos_next, *endptr;
+       int i;
+
+       switch (*value_type)
+       {
+               case VALUE_STRING:
+                       *blob = chunk_create(value, strlen(value));
+                       *blob = chunk_clone(*blob);
+                       break;
+               case VALUE_HEX:
+                       *blob = chunk_from_hex(chunk_create(value, strlen(value)), NULL);
+                       break;
+               case VALUE_ADDR:
+                       addr = host_create_from_string(value, 0);
+                       if (addr == NULL)
+                       {
+                               fprintf(stderr, "invalid IP address: '%s'.\n", value);
+                               return FALSE;
+                       }
+                       addr_chunk = addr->get_address(addr);
+                       *blob = chunk_clone(addr_chunk);
+                       break;
+               case VALUE_SUBNET:
+                       *blob = chunk_empty;
+                       pos_next = value;
+
+                       do
+                       {
+                               pos_addr = pos_next;
+                               pos_next = strchr(pos_next, ',');
+                               if (pos_next)
+                               {
+                                       *pos_next = '\0';
+                                       pos_next += 1;
+                               }
+                               pos_mask = strchr(pos_addr, '/');
+                               if (pos_mask == NULL)
+                               {
+                                       fprintf(stderr, "invalid IPv4 subnet: '%s'.\n", pos_addr);
+                                       free(blob->ptr);
+                                       return FALSE;
+                               }
+                               *pos_mask = '\0';
+                               pos_mask += 1;
+                               addr = host_create_from_string(pos_addr, 0);
+                               mask = host_create_from_string(pos_mask, 0);
+                               if (addr == NULL || addr->get_family(addr) != AF_INET ||
+                                       mask == NULL || mask->get_family(addr) != AF_INET)
+                               {
+                                       fprintf(stderr, "invalid IPv4 subnet: '%s/%s'.\n",
+                                                                       pos_addr, pos_mask);
+                                       DESTROY_IF(addr);
+                                       DESTROY_IF(mask);
+                                       free(blob->ptr);
+                                       return FALSE;
+                               }
+                               addr_chunk = addr->get_address(addr);
+                               mask_chunk = mask->get_address(mask);
+                               blob_next = chunk_alloc(blob->len + UNITY_NETWORK_LEN);
+                               memcpy(blob_next.ptr, blob->ptr, blob->len);
+                               pos_addr = blob_next.ptr + blob->len;
+                               memset(pos_addr, 0x00, UNITY_NETWORK_LEN);
+                               memcpy(pos_addr,     addr_chunk.ptr, 4);
+                               memcpy(pos_addr + 4, mask_chunk.ptr, 4);
+                               addr->destroy(addr);
+                               addr = NULL;
+                               mask->destroy(mask);
+                               chunk_free(blob);
+                               *blob = blob_next;
+                       }
+                       while (pos_next);
+                       break;
+               case VALUE_NONE:
+                       *blob = chunk_empty;
+                       break;
+       }
+
+       /* init the attribute type */
+       *type     = 0;
+       *type_ip6 = 0;
+
+       for (i = 0; i < countof(attr_info); i++)
+       {
+               if (strcaseeq(name, attr_info[i].keyword))
+               {
+                       *type      = attr_info[i].type;
+                       *type_ip6  = attr_info[i].type_ip6;
+
+                       if (*value_type == VALUE_NONE)
+                       {
+                               *value_type = attr_info[i].value_type;
+                               return TRUE;
+                       }
+
+                       if (*value_type != attr_info[i].value_type &&
+                               *value_type != VALUE_HEX)
+                       {
+                               switch (attr_info[i].value_type)
+                               {
+                                       case VALUE_STRING:
+                                               text = "a string";
+                                               break;
+                                       case VALUE_HEX:
+                                               text = "a hex";
+                                               break;
+                                       case VALUE_ADDR:
+                                               text = "an IP address";
+                                               break;
+                                       case VALUE_SUBNET:
+                                               text = "a subnet";
+                                               break;
+                                       case VALUE_NONE:
+                                               text = "no";
+                                               break;
+                               }
+                               fprintf(stderr, "the %s attribute requires %s value.\n",
+                                                                name, text);
+                               DESTROY_IF(addr);
+                               free(blob->ptr);
+                               return FALSE;
+                       }
+
+                       if (*value_type == VALUE_ADDR)
+                       {
+                               *type = (addr->get_family(addr) == AF_INET) ?
+                                                       attr_info[i].type : attr_info[i].type_ip6;
+                               addr->destroy(addr);
+                       }
+                       else if (*value_type == VALUE_HEX)
+                       {
+                               *value_type = attr_info[i].value_type;
+
+                               if (*value_type == VALUE_ADDR)
+                               {
+                                       if (blob->len == 16)
+                                       {
+                                               *type = attr_info[i].type_ip6;
+                                       }
+                                       else if (blob->len != 4)
+                                       {
+                                               fprintf(stderr, "the %s attribute requires "
+                                                                               "a valid IP address.\n", name);
+                                               free(blob->ptr);
+                                               return FALSE;
+                                       }
+                               }
+                       }
+                       return TRUE;
+               }
+       }
+
+       /* clean up */
+       DESTROY_IF(addr);
+
+       /* is the attribute type numeric? */
+       *type = strtol(name, &endptr, 10);
+
+       if (*endptr != '\0')
+       {
+               fprintf(stderr, "the %s attribute is not recognized.\n", name);
+               free(blob->ptr);
+               return FALSE;
+       }
+       if (*type < 1 || *type > 32767)
+       {
+               fprintf(stderr, "the attribute type must lie in the range 1..32767.\n");
+               free(blob->ptr);
+               return FALSE;
+       }
+       if (*value_type == VALUE_NONE)
+       {
+               *value_type = VALUE_HEX;
+       }
+       return TRUE;
+}
+
+/**
+ * Lookup/insert an attribute pool by name
+ */
+static u_int get_attr_pool(char *name)
+{
+       enumerator_t *e;
+       u_int row = 0;
+
+       /* look for an existing attribute pool in the table */
+       e = db->query(db, "SELECT id FROM attribute_pools WHERE name = ?",
+                                 DB_TEXT, name, DB_UINT);
+       if (e && e->enumerate(e, &row))
+       {
+               e->destroy(e);
+               return row;
+       }
+       DESTROY_IF(e);
+       /* not found, insert new one */
+       if (db->execute(db, &row, "INSERT INTO attribute_pools (name) VALUES (?)",
+                                       DB_TEXT, name) != 1)
+       {
+               fprintf(stderr, "creating attribute pool '%s' failed.\n", name);
+               return 0;
+       }
+       return row;
+}
+
+/**
+ * Lookup/insert an identity
+ */
+u_int get_identity(identification_t *id)
+{
+       enumerator_t *e;
+       u_int row;
+
+       /* 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, &row))
+       {
+               e->destroy(e);
+               return row;
+       }
+       DESTROY_IF(e);
+       /* not found, insert new one */
+       if (db->execute(db, &row, "INSERT INTO identities (type,data) VALUES (?,?)",
+                                 DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) != 1)
+       {
+               fprintf(stderr, "creating id '%Y' failed.\n", id);
+               return 0;
+       }
+       return row;
+}
+
+/**
+ * ipsec pool --addattr <type> - add attribute entry
+ */
+void add_attr(char *name, char *pool, char *identity,
+                         char *value, value_type_t value_type)
+{
+       configuration_attribute_type_t type, type_ip6;
+       u_int pool_id = 0, identity_id = 0;
+       char id_pool_str[128] = "";
+       chunk_t blob;
+       bool success;
+
+       if (pool)
+       {
+               pool_id = get_attr_pool(pool);
+               if (pool_id == 0)
+               {
+                       exit(EXIT_FAILURE);
+               }
+
+               if (identity)
+               {
+                       identification_t *id;
+
+                       id = identification_create_from_string(identity);
+                       identity_id = get_identity(id);
+                       id->destroy(id);
+                       if (identity_id == 0)
+                       {
+                               exit(EXIT_FAILURE);
+                       }
+                       snprintf(id_pool_str, sizeof(id_pool_str),
+                                        " for '%s' in pool '%s'", identity, pool);
+               }
+               else
+               {
+                       snprintf(id_pool_str, sizeof(id_pool_str), " in pool '%s'", pool);
+               }
+       }
+
+       if (value_type == VALUE_NONE)
+       {
+               fprintf(stderr, "the value of the %s attribute is missing.\n", name);
+               usage();
+       }
+       if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob))
+       {
+               exit(EXIT_FAILURE);
+       }
+
+       success = db->execute(db, NULL,
+                               "INSERT INTO attributes (identity, pool, type, value) "
+                               "VALUES (?, ?, ?, ?)", DB_UINT, identity_id, DB_UINT, pool_id,
+                               DB_INT, type, DB_BLOB, blob) == 1;
+       free(blob.ptr);
+
+       if (success)
+       {
+               printf("added %s attribute (%N)%s.\n", name,
+                          configuration_attribute_type_names, type, id_pool_str);
+       }
+       else
+       {
+               fprintf(stderr, "adding %s attribute (%N)%s failed.\n", name,
+                                               configuration_attribute_type_names, type, id_pool_str);
+       }
+}
+
+/**
+ * ipsec pool --delattr <type> - delete attribute entry
+ */
+void del_attr(char *name, char *pool, char *identity,
+                         char *value, value_type_t value_type)
+{
+       configuration_attribute_type_t type, type_ip6, type_db;
+       u_int pool_id = 0, identity_id = 0;
+       char id_pool_str[128] = "";
+       chunk_t blob, blob_db;
+       u_int id;
+       enumerator_t *query;
+       bool found = FALSE;
+
+       if (pool)
+       {
+               pool_id = get_attr_pool(pool);
+               if (pool_id == 0)
+               {
+                       exit(EXIT_FAILURE);
+               }
+
+               if (identity)
+               {
+                       identification_t *id;
+
+                       id = identification_create_from_string(identity);
+                       identity_id = get_identity(id);
+                       id->destroy(id);
+                       if (identity_id == 0)
+                       {
+                               exit(EXIT_FAILURE);
+                       }
+                       snprintf(id_pool_str, sizeof(id_pool_str),
+                                        " for '%s' in pool '%s'", identity, pool);
+               }
+               else
+               {
+                       snprintf(id_pool_str, sizeof(id_pool_str), " in pool '%s'", pool);
+               }
+       }
+
+       if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob))
+       {
+               exit(EXIT_FAILURE);
+       }
+
+       if (blob.len > 0)
+       {
+               query = db->query(db,
+                                       "SELECT id, type, value FROM attributes "
+                                       "WHERE identity = ? AND pool = ? AND type = ? AND value = ?",
+                                       DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
+                                       DB_BLOB, blob, DB_UINT, DB_INT, DB_BLOB);
+       }
+       else if (type_ip6 == 0)
+       {
+               query = db->query(db,
+                                       "SELECT id, type, value FROM attributes "
+                                       "WHERE identity = ? AND pool = ? AND type = ?",
+                                       DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
+                                       DB_UINT, DB_INT, DB_BLOB);
+       }
+       else
+       {
+               query = db->query(db,
+                                       "SELECT id, type, value FROM attributes "
+                                       "WHERE identity = ? AND pool = ? AND (type = ? OR type = ?)",
+                                       DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
+                                       DB_INT, type_ip6, DB_UINT, DB_INT, DB_BLOB);
+       }
+
+       if (!query)
+       {
+               fprintf(stderr, "deleting '%s' attribute (%N)%s failed.\n",
+                               name, configuration_attribute_type_names, type, id_pool_str);
+               free(blob.ptr);
+               exit(EXIT_FAILURE);
+       }
+
+       while (query->enumerate(query, &id, &type_db, &blob_db))
+       {
+               host_t *server = NULL;
+
+               found = TRUE;
+
+               if (value_type == VALUE_ADDR)
+               {
+                       int family = (type_db == type_ip6) ? AF_INET6 : AF_INET;
+
+                       server = host_create_from_chunk(family, blob_db, 0);
+               }
+
+               if (db->execute(db, NULL,
+                                       "DELETE FROM attributes WHERE id = ?",
+                                        DB_UINT, id) != 1)
+               {
+                       if (server)
+                       {
+                               fprintf(stderr, "deleting %s server %H%s failed\n",
+                                               name, server, id_pool_str);
+                               server->destroy(server);
+                       }
+                       else if (value_type == VALUE_STRING)
+                       {
+                               fprintf(stderr, "deleting %s attribute (%N) with value '%.*s'%s failed.\n",
+                                                               name, configuration_attribute_type_names, type,
+                                                               (int)blob_db.len, blob_db.ptr, id_pool_str);
+                       }
+
+                       else
+                       {
+                               fprintf(stderr, "deleting %s attribute (%N) with value %#B%s failed.\n",
+                                                               name, configuration_attribute_type_names, type,
+                                                               &blob_db, id_pool_str);
+                       }
+                       query->destroy(query);
+                       free(blob.ptr);
+                       exit(EXIT_FAILURE);
+               }
+               if (server)
+               {
+                       printf("deleted %s server %H%s\n", name, server, id_pool_str);
+                       server->destroy(server);
+               }
+               else if (value_type == VALUE_STRING)
+               {
+                       printf("deleted %s attribute (%N) with value '%.*s'%s.\n",
+                                  name, configuration_attribute_type_names, type,
+                                  (int)blob_db.len, blob_db.ptr, id_pool_str);
+               }
+               else
+               {
+                       printf("deleted %s attribute (%N) with value %#B%s.\n",
+                                  name, configuration_attribute_type_names, type,
+                                  &blob_db, id_pool_str);
+               }
+       }
+       query->destroy(query);
+
+       if (!found)
+       {
+               if (blob.len == 0)
+               {
+                       if (type_ip6 == 0)
+                       {
+                               fprintf(stderr, "no %s attribute (%N) was found%s.\n", name,
+                                               configuration_attribute_type_names, type, id_pool_str);
+                       }
+                       else
+                       {
+                               fprintf(stderr, "no %s attribute%s was found.\n",
+                                               name, id_pool_str);
+                       }
+               }
+               else
+               {
+                       if (value_type == VALUE_ADDR)
+                       {
+                               host_t *server = host_create_from_chunk(AF_UNSPEC, blob, 0);
+
+                               fprintf(stderr, "the %s server %H%s was not found.\n", name,
+                                                                server, id_pool_str);
+                               server->destroy(server);
+                       }
+                       else
+                       {
+                               fprintf(stderr, "the %s attribute (%N) with value '%.*s'%s "
+                                                               "was not found.\n", name,
+                                                                configuration_attribute_type_names, type,
+                                                                (int)blob.len, blob.ptr, id_pool_str);
+                       }
+               }
+       }
+       free(blob.ptr);
+}
+
+/**
+ * ipsec pool --statusattr - show all attribute entries
+ */
+void status_attr(bool hexout)
+{
+       configuration_attribute_type_t type;
+       value_type_t value_type;
+       chunk_t value, addr_chunk, mask_chunk, identity_chunk;
+       identification_t *identity;
+       enumerator_t *enumerator;
+       host_t *addr, *mask;
+       char type_name[30];
+       bool first = TRUE;
+       int i, identity_type;
+       char *pool_name;
+
+       /* enumerate over all attributes */
+       enumerator = db->query(db,
+                                       "SELECT attributes.type, attribute_pools.name, "
+                                       "identities.type, identities.data, attributes.value "
+                                       "FROM attributes "
+                                       "LEFT OUTER JOIN identities "
+                                       "ON attributes.identity = identities.id "
+                                       "LEFT OUTER JOIN attribute_pools "
+                                       "ON attributes.pool = attribute_pools.id "
+                                       "ORDER BY attributes.type, attribute_pools.name, "
+                                       "identities.type, identities.data, attributes.value",
+                                       DB_INT, DB_TEXT, DB_INT, DB_BLOB, DB_BLOB);
+       if (enumerator)
+       {
+               while (enumerator->enumerate(enumerator, &type,&pool_name,
+                                                                        &identity_type, &identity_chunk, &value))
+               {
+                       if (first)
+                       {
+                               printf(" type  description           pool       "
+                                          " identity              value\n");
+                               first = FALSE;
+                       }
+                       snprintf(type_name, sizeof(type_name), "%N",
+                                        configuration_attribute_type_names, type);
+                       if (type_name[0] == '(')
+                       {
+                               type_name[0] = '\0';
+                       }
+                       printf("%5d  %-20s ",type, type_name);
+
+                       printf(" %-10s ", (pool_name ? pool_name : ""));
+
+                       if (identity_type)
+                       {
+                               identity = identification_create_from_encoding(identity_type, identity_chunk);
+                               printf(" %-20.20Y ", identity);
+                               identity->destroy(identity);
+                       }
+                       else
+                       {
+                               printf("                      ");
+                       }
+
+                       value_type = VALUE_HEX;
+                       if (!hexout)
+                       {
+                               for (i = 0; i < countof(attr_info); i++)
+                               {
+                                       if (type == attr_info[i].type)
+                                       {
+                                               value_type = attr_info[i].value_type;
+                                               break;
+                                       }
+                               }
+                       }
+                       switch (value_type)
+                       {
+                               case VALUE_ADDR:
+                                       addr = host_create_from_chunk(AF_UNSPEC, value, 0);
+                                       if (addr)
+                                       {
+                                               printf(" %H\n", addr);
+                                               addr->destroy(addr);
+                                       }
+                                       else
+                                       {
+                                               /* value cannot be represented as an IP address */
+                                               printf(" %#B\n", &value);
+                                       }
+                                       break;
+                               case VALUE_SUBNET:
+                                       if (value.len % UNITY_NETWORK_LEN == 0)
+                                       {
+                                               for (i = 0; i < value.len / UNITY_NETWORK_LEN; i++)
+                                               {
+                                                       addr_chunk = chunk_create(value.ptr + i*UNITY_NETWORK_LEN, 4);
+                                                       addr = host_create_from_chunk(AF_INET, addr_chunk, 0);
+                                                       mask_chunk = chunk_create(addr_chunk.ptr + 4, 4);
+                                                       mask = host_create_from_chunk(AF_INET, mask_chunk, 0);
+                                                       printf("%s%H/%H", (i > 0) ? "," : " ", addr, mask);
+                                                       addr->destroy(addr);
+                                                       mask->destroy(mask);
+                                               }
+                                               printf("\n");
+                                       }
+                                       else
+                                       {
+                                               /* value cannot be represented as a list of subnets */
+                                               printf(" %#B\n", &value);
+                                       }
+                                       break;
+                               case VALUE_STRING:
+                                       printf("\"%.*s\"\n", (int)value.len, value.ptr);
+                                       break;
+                               case VALUE_HEX:
+                               default:
+                                       printf(" %#B\n", &value);
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+}
+
+/**
+ * ipsec pool --showattr - show all supported attribute keywords
+ */
+void show_attr(void)
+{
+       int i;
+
+       for (i = 0; i < countof(attr_info); i++)
+       {
+               char value_name[10];
+
+
+               snprintf(value_name, sizeof(value_name), "%N",
+                       value_type_names, attr_info[i].value_type);
+
+               printf("%-20s  --%-6s  (%N",
+                               attr_info[i].keyword, value_name,
+                               configuration_attribute_type_names, attr_info[i].type);
+
+               if (attr_info[i].type_ip6)
+               {
+                       printf(", %N)\n",
+                               configuration_attribute_type_names, attr_info[i].type_ip6);
+               }
+               else
+               {
+                       printf(")\n");
+               }
+       }
+}
diff --git a/src/pool/pool_attributes.h b/src/pool/pool_attributes.h
new file mode 100644 (file)
index 0000000..6a5af33
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2009-2010 Andreas Steffen
+ * 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.
+ */
+
+#ifndef POOL_ATTRIBUTES_H_
+#define POOL_ATTRIBUTES_H_
+
+#include <attributes/attributes.h>
+
+typedef enum value_type_t value_type_t;
+
+enum value_type_t {
+       VALUE_NONE,
+       VALUE_HEX,
+       VALUE_STRING,
+       VALUE_ADDR,
+       VALUE_SUBNET
+};
+
+/**
+ * enum names for value_type_t.
+ */
+extern enum_name_t *value_type_names;
+
+/**
+ * lookup/insert an identity
+ */
+u_int get_identity(identification_t *id);
+
+/**
+ * ipsec pool --addattr <type>  - add attribute entry
+ */
+void add_attr(char *name, char *pool, char *identity,
+                         char *value, value_type_t value_type);
+
+/**
+ * ipsec pool --delattr <type>  - delete attribute entry
+ */
+void del_attr(char *name, char *pool, char *identity,
+                         char *value, value_type_t value_type);
+
+/**
+ * ipsec pool --statusattr      - show all attribute entries
+ */
+void status_attr(bool hexout);
+
+/**
+ * ipsec pool --showattr - show all supported attribute keywords
+ */
+void show_attr(void);
+
+#endif /* POOL_ATTRIBUTES_H_ */
diff --git a/src/pool/pool_usage.c b/src/pool/pool_usage.c
new file mode 100644 (file)
index 0000000..7622cfa
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2009-2010 Andreas Steffen
+ * 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 <stdio.h>
+
+/**
+ * print pool usage info
+ */
+void usage(void)
+{
+       printf("\
+Usage:\n\
+  ipsec pool --status|--add|--replace|--del|--resize|--leases|--purge [options]\n\
+  ipsec pool --showattr|--statusattr|--addattr|--delattr [options]\n\
+  \n\
+  ipsec pool --status\n\
+    Show a list of installed pools with statistics plus nameserver info.\n\
+  \n\
+  ipsec pool --statusattr [--hexout]\n\
+    Show a list of all attributes stored in the database with the values\n\
+    converted to the correct format if the type is known by --showattr or\n\
+    in hex format otherwise.\n\
+      hexout:  Output all values in hex format\n\
+  \n\
+  ipsec pool --showattr\n\
+    Show a keyword list of the major attribute types.\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 --addattr <type> [--pool <name> [--identity <id>]]\n\
+             --addr|--mask|--server|--subnet|--string|--hex <value>\n\
+    Add a new attribute to the database. Attributes can be bundled by using\n\
+    the --pool and --identity options. If a bundle matches a peer the contained\n\
+    attributes are sent to that peer instead of the global ones.\n\
+      type:    a keyword from --showattr or a number from the range 1..32767\n\
+      name:    the name of the pool this attribute is added to\n\
+      id:      identity of the peer this attribute is bound to\n\
+      addr:    IPv4 or IPv6 address\n\
+      mask:    IPv4 or IPv6 netmask (synonym for --addr)\n\
+      server:  IPv4 or IPv6 address of a server (synonym for --addr)\n\
+      subnet:  IPv4 subnet[s] given by network/mask[,network/mask,...]\n\
+      string:  value of a string-type attribute\n\
+      hex:     hex value of any attribute\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 --delattr <type> [--pool <name> [--identity <id>]]\n\
+             [--addr|--mask|--server|--subnet|--string|--hex <value>]\n\
+    Delete a specific or all attributes of a given type from the database.\n\
+      type:    a keyword from --showattr or a number from the range 1..32767\n\
+      name:    the name of the pool this attribute is added to\n\
+      id:      identity of the peer this attribute is bound to\n\
+      addr:    IPv4 or IPv6 address\n\
+      mask:    IPv4 or IPv6 netmask (synonym for --addr)\n\
+      server:  IPv4 or IPv6 address of a server (synonym for --addr)\n\
+      subnet:  IPv4 subnet[s] given by network/mask[,network/mask,...]\n\
+      string:  value of a string-type attribute\n\
+      hex:     hex value of any attribute\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");
+}
diff --git a/src/pool/pool_usage.h b/src/pool/pool_usage.h
new file mode 100644 (file)
index 0000000..0082ef6
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2009-2010 Andreas Steffen
+ * 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.
+ */
+
+#ifndef POOL_USAGE_H_
+#define POOL_USAGE_H_
+
+/**
+ * print pool usage info
+ */
+void usage(void);
+
+#endif /* POOL_USAGE_H_ */