From 4b8b1354cea559844d7cbf2e460e90dab3655fad Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 5 Sep 2013 17:03:11 +0200 Subject: attr-sql: Don't use database transactions in create_attribute_enumerator There could, of course, be race conditions when enumerating the attributes, but those probably don't matter (e.g. missing an attribute that was concurrently added). Transactions are more intended to revert multiple changes if anything fails in the process. --- src/libhydra/plugins/attr_sql/sql_attribute.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/libhydra/plugins/attr_sql') diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c index e91e1ed15..cad5bfae3 100644 --- a/src/libhydra/plugins/attr_sql/sql_attribute.c +++ b/src/libhydra/plugins/attr_sql/sql_attribute.c @@ -346,8 +346,6 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, u_int count; char *name; - this->db->execute(this->db, NULL, "BEGIN EXCLUSIVE TRANSACTION"); - /* in a first step check for attributes that match name and id */ if (id) { @@ -418,8 +416,6 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, pool_enumerator->destroy(pool_enumerator); } - this->db->execute(this->db, NULL, "END TRANSACTION"); - /* lastly try to find global attributes */ if (!attr_enumerator) { @@ -474,4 +470,3 @@ sql_attribute_t *sql_attribute_create(database_t *db) DB_UINT, now); return &this->public; } - -- cgit v1.2.3 From 5abe3c52d396339f3e1ac5f5a63cb8a4dfa0209d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 13 Sep 2013 13:25:49 +0200 Subject: attr-sql: Handle concurrent insertion of identities If the same identity is added concurrently by two threads (or by the pool utility) INSERT might fail even though the SELECT was unsuccessful before. We are currently not able to lock the identities table in a portable way (something like SELECT ... FOR UPDATE on MySQL). --- src/libhydra/plugins/attr_sql/sql_attribute.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/libhydra/plugins/attr_sql') diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c index cad5bfae3..20c606ef3 100644 --- a/src/libhydra/plugins/attr_sql/sql_attribute.c +++ b/src/libhydra/plugins/attr_sql/sql_attribute.c @@ -50,19 +50,24 @@ static u_int get_identity(private_sql_attribute_t *this, identification_t *id) { enumerator_t *e; u_int row; + int try = 0; +retry: /* look for peer identity in the identities table */ e = this->db->query(this->db, "SELECT id FROM identities WHERE type = ? AND data = ?", DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), DB_UINT); - if (e && e->enumerate(e, &row)) { e->destroy(e); return row; } DESTROY_IF(e); + if (try > 0) + { + return 0; + } /* not found, insert new one */ if (this->db->execute(this->db, &row, "INSERT INTO identities (type, data) VALUES (?, ?)", @@ -70,7 +75,12 @@ static u_int get_identity(private_sql_attribute_t *this, identification_t *id) { return row; } - return 0; + /* the INSERT could fail due to the UNIQUE constraint, if the identity was + * added concurrently by another thread or the pool utility, + * therefore try finding it again. a nicer fix would be to use locking + * on the database, but our API currently not supports that */ + try++; + goto retry; } /** -- cgit v1.2.3 From ec6ad6b08616b9d3e1a3b3dffc06d56f65179a06 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 5 Sep 2013 18:00:48 +0200 Subject: pool: Move the pool utility to its own directory in src --- src/libhydra/plugins/attr_sql/.gitignore | 1 - src/libhydra/plugins/attr_sql/Makefile.am | 10 +- src/libhydra/plugins/attr_sql/pool.c | 1287 ----------------------- src/libhydra/plugins/attr_sql/pool_attributes.c | 717 ------------- src/libhydra/plugins/attr_sql/pool_attributes.h | 65 -- src/libhydra/plugins/attr_sql/pool_usage.c | 127 --- src/libhydra/plugins/attr_sql/pool_usage.h | 26 - 7 files changed, 1 insertion(+), 2232 deletions(-) delete mode 100644 src/libhydra/plugins/attr_sql/.gitignore delete mode 100644 src/libhydra/plugins/attr_sql/pool.c delete mode 100644 src/libhydra/plugins/attr_sql/pool_attributes.c delete mode 100644 src/libhydra/plugins/attr_sql/pool_attributes.h delete mode 100644 src/libhydra/plugins/attr_sql/pool_usage.c delete mode 100644 src/libhydra/plugins/attr_sql/pool_usage.h (limited to 'src/libhydra/plugins/attr_sql') diff --git a/src/libhydra/plugins/attr_sql/.gitignore b/src/libhydra/plugins/attr_sql/.gitignore deleted file mode 100644 index eae4e6ad0..000000000 --- a/src/libhydra/plugins/attr_sql/.gitignore +++ /dev/null @@ -1 +0,0 @@ -pool diff --git a/src/libhydra/plugins/attr_sql/Makefile.am b/src/libhydra/plugins/attr_sql/Makefile.am index 4c369a2bd..d126bb035 100644 --- a/src/libhydra/plugins/attr_sql/Makefile.am +++ b/src/libhydra/plugins/attr_sql/Makefile.am @@ -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 index 4e7c48e23..000000000 --- a/src/libhydra/plugins/attr_sql/pool.c +++ /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 . - * - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#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 index 1d1ba8f58..000000000 --- a/src/libhydra/plugins/attr_sql/pool_attributes.c +++ /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 . - * - * 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 - -#include -#include - -#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 - 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 - 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 index a42291f57..000000000 --- a/src/libhydra/plugins/attr_sql/pool_attributes.h +++ /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 . - * - * 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 - -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 - add attribute entry - */ -void add_attr(char *name, char *pool, char *identity, - char *value, value_type_t value_type); - -/** - * ipsec pool --delattr - 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 index 985bc3ae8..000000000 --- a/src/libhydra/plugins/attr_sql/pool_usage.c +++ /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 . - * - * 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 - -/** - * 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 --start --end [--timeout ]\n\ - ipsec pool --replace --start --end [--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 --addresses [--timeout ]\n\ - ipsec pool --replace --addresses [--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 [--pool [--identity ]]\n\ - --addr|--mask|--server|--subnet|--string|--hex \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 \n\ - Delete a pool from the database.\n\ - name: Name of the pool to delete\n\ - \n\ - ipsec pool --delattr [--pool [--identity ]]\n\ - [--addr|--mask|--server|--subnet|--string|--hex ]\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 --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 ] [--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 \n\ - Delete lease history of a pool:\n\ - name: Name of the pool to purge\n\ - \n\ - ipsec pool --batch \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 index a98b0d680..000000000 --- a/src/libhydra/plugins/attr_sql/pool_usage.h +++ /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 . - * - * 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_ */ -- cgit v1.2.3 From bd085dd978b2dc7891c0d8486dd883e76e15e9a3 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 10 Oct 2013 11:02:16 +0200 Subject: attr-sql: Use a serializable transaction when inserting identities --- src/libhydra/plugins/attr_sql/sql_attribute.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'src/libhydra/plugins/attr_sql') diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c index 20c606ef3..0a06c419f 100644 --- a/src/libhydra/plugins/attr_sql/sql_attribute.c +++ b/src/libhydra/plugins/attr_sql/sql_attribute.c @@ -50,9 +50,8 @@ static u_int get_identity(private_sql_attribute_t *this, identification_t *id) { enumerator_t *e; u_int row; - int try = 0; -retry: + this->db->transaction(this->db, TRUE); /* look for peer identity in the identities table */ e = this->db->query(this->db, "SELECT id FROM identities WHERE type = ? AND data = ?", @@ -61,26 +60,20 @@ retry: if (e && e->enumerate(e, &row)) { e->destroy(e); + this->db->commit(this->db); return row; } DESTROY_IF(e); - if (try > 0) - { - return 0; - } /* not found, insert new one */ if (this->db->execute(this->db, &row, "INSERT INTO identities (type, data) VALUES (?, ?)", DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) == 1) { + this->db->commit(this->db); return row; } - /* the INSERT could fail due to the UNIQUE constraint, if the identity was - * added concurrently by another thread or the pool utility, - * therefore try finding it again. a nicer fix would be to use locking - * on the database, but our API currently not supports that */ - try++; - goto retry; + this->db->rollback(this->db); + return 0; } /** -- cgit v1.2.3