[strongSwan-dev] [PATCH 4/4] ipsec pool --batch command
Heiko Hund
hhund at astaro.com
Tue Mar 16 21:11:52 CET 2010
Introduce the --batch command which reads several ipsec pool commands
and their arguments from a file or STDIN. Useful if you need to run
serveral commands atomically from a configuration daemon or likewise.
Signed-off-by: Heiko Hund <hhund at astaro.com>
---
src/libstrongswan/plugins/attr_sql/pool.c | 260 ++++++++++++++++++++++-------
1 files changed, 200 insertions(+), 60 deletions(-)
diff --git a/src/libstrongswan/plugins/attr_sql/pool.c b/src/libstrongswan/plugins/attr_sql/pool.c
index de1b12d..e8a8ce6 100644
--- a/src/libstrongswan/plugins/attr_sql/pool.c
+++ b/src/libstrongswan/plugins/attr_sql/pool.c
@@ -43,9 +43,45 @@ host_t *start = NULL, *end = NULL, *server = NULL;
bool replace_pool = FALSE;
/**
- * forward declaration
+ * 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
@@ -186,6 +222,18 @@ Usage:\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");
}
@@ -409,10 +457,8 @@ static void add(char *name, host_t *start, host_t *end, int timeout)
id = create_pool(name, start_addr, end_addr, timeout);
printf("allocating %d addresses... ", count);
fflush(stdout);
- if (db->get_driver(db) == DB_SQLITE)
- { /* run population in a transaction for sqlite */
- db->execute(db, NULL, "BEGIN TRANSACTION");
- }
+ /* run population in a transaction for sqlite */
+ begin_transaction();
while (TRUE)
{
db->execute(db, NULL,
@@ -425,10 +471,7 @@ static void add(char *name, host_t *start, host_t *end, int timeout)
}
chunk_increment(cur_addr);
}
- if (db->get_driver(db) == DB_SQLITE)
- {
- db->execute(db, NULL, "END TRANSACTION");
- }
+ commit_transaction();
printf("done.\n", count);
}
@@ -502,10 +545,8 @@ static void add_addresses(char *pool, char *path, int timeout)
host_t *addr;
FILE *file;
- if (db->get_driver(db) == DB_SQLITE)
- { /* run population in a transaction for sqlite */
- db->execute(db, NULL, "BEGIN TRANSACTION");
- }
+ /* 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),
@@ -546,10 +587,7 @@ static void add_addresses(char *pool, char *path, int timeout)
fclose(file);
}
- if (db->get_driver(db) == DB_SQLITE)
- {
- db->execute(db, NULL, "END TRANSACTION");
- }
+ commit_transaction();
printf("%d addresses done.\n", count);
}
@@ -763,10 +801,8 @@ static void resize(char *name, host_t *end)
printf("allocating %d new addresses... ", count);
fflush(stdout);
- if (db->get_driver(db) == DB_SQLITE)
- { /* run population in a transaction for sqlite */
- db->execute(db, NULL, "BEGIN TRANSACTION");
- }
+ /* run population in a transaction for sqlite */
+ begin_transaction();
while (count-- > 0)
{
chunk_increment(cur_addr);
@@ -775,10 +811,7 @@ static void resize(char *name, host_t *end)
"VALUES (?, ?, ?, ?, ?)",
DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
}
- if (db->get_driver(db) == DB_SQLITE)
- {
- db->execute(db, NULL, "END TRANSACTION");
- }
+ commit_transaction();
printf("done.\n", count);
}
@@ -1030,6 +1063,79 @@ static void purge(char *name)
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
*/
@@ -1041,9 +1147,9 @@ static void cleanup(void)
DESTROY_IF(server);
}
-int main(int argc, char *argv[])
+static void do_args(int argc, char *argv[])
{
- char *uri, *name = "", *filter = "", *addresses = NULL;
+ char *name = "", *filter = "", *addresses = NULL;
int timeout = 0;
bool utc = FALSE;
enum {
@@ -1056,41 +1162,12 @@ int main(int argc, char *argv[])
OP_DEL_ATTR,
OP_RESIZE,
OP_LEASES,
- OP_PURGE
+ OP_PURGE,
+ OP_BATCH
} operation = OP_UNDEF;
- atexit(library_deinit);
-
- /* initialize library */
- if (!library_init(NULL))
- {
- exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
- }
- if (lib->integrity &&
- !lib->integrity->check_file(lib->integrity, "pool", argv[0]))
- {
- fprintf(stderr, "integrity check of pool failed\n");
- exit(SS_RC_DAEMON_INTEGRITY);
- }
- if (!lib->plugins->load(lib->plugins, NULL,
- lib->settings->get_str(lib->settings, "pool.load", PLUGINS)))
- {
- exit(SS_RC_INITIALIZATION_FAILED);
- }
-
- uri = lib->settings->get_str(lib->settings, "libstrongswan.plugins.attr-sql.database", NULL);
- if (!uri)
- {
- fprintf(stderr, "database URI libstrongswan.plugins.attr-sql.database not set.\n");
- exit(SS_RC_INITIALIZATION_FAILED);
- }
- db = lib->db->create(lib->db, uri);
- if (!db)
- {
- fprintf(stderr, "opening database failed.\n");
- exit(SS_RC_INITIALIZATION_FAILED);
- }
- atexit(cleanup);
+ /* set option index to first argument */
+ optind = 1;
while (TRUE)
{
@@ -1107,6 +1184,7 @@ int main(int argc, char *argv[])
{ "resize", required_argument, NULL, 'r' },
{ "leases", no_argument, NULL, 'l' },
{ "purge", required_argument, NULL, 'p' },
+ { "batch", required_argument, NULL, 'b' },
{ "start", required_argument, NULL, 's' },
{ "end", required_argument, NULL, 'e' },
@@ -1159,7 +1237,17 @@ int main(int argc, char *argv[])
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)
{
@@ -1169,6 +1257,7 @@ int main(int argc, char *argv[])
}
continue;
case 'e':
+ DESTROY_IF(end);
end = host_create_from_string(optarg, 0);
if (end == NULL)
{
@@ -1193,6 +1282,7 @@ int main(int argc, char *argv[])
addresses = optarg;
continue;
case 'v':
+ DESTROY_IF(server);
server = host_create_from_string(optarg, 0);
if (server == NULL)
{
@@ -1263,10 +1353,60 @@ int main(int argc, char *argv[])
case OP_PURGE:
purge(name);
break;
+ case OP_BATCH:
+ if (name == NULL)
+ {
+ fprintf(stderr, "missing arguments.\n");
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ batch(argv[0], name);
+ break;
default:
usage();
exit(EXIT_FAILURE);
}
+}
+
+int main(int argc, char *argv[])
+{
+ char *uri;
+
+ atexit(library_deinit);
+
+ /* initialize library */
+ if (!library_init(NULL))
+ {
+ exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+ }
+ if (lib->integrity &&
+ !lib->integrity->check_file(lib->integrity, "pool", argv[0]))
+ {
+ fprintf(stderr, "integrity check of pool failed\n");
+ exit(SS_RC_DAEMON_INTEGRITY);
+ }
+ if (!lib->plugins->load(lib->plugins, NULL,
+ lib->settings->get_str(lib->settings, "pool.load", PLUGINS)))
+ {
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ uri = lib->settings->get_str(lib->settings, "libstrongswan.plugins.attr-sql.database", NULL);
+ if (!uri)
+ {
+ fprintf(stderr, "database URI libstrongswan.plugins.attr-sql.database not set.\n");
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+ db = lib->db->create(lib->db, uri);
+ if (!db)
+ {
+ fprintf(stderr, "opening database failed.\n");
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+ atexit(cleanup);
+
+ do_args(argc, argv);
+
exit(EXIT_SUCCESS);
}
--
1.6.5.7
More information about the Dev
mailing list