2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 #include <utils/host.h>
29 * global database handle
34 * --start/--end addresses of various subcommands
36 host_t
*start
= NULL
, *end
= NULL
;
39 * create a host from a blob
41 static host_t
*host_create_from_blob(chunk_t blob
)
43 return host_create_from_chunk(blob
.len
== 4 ? AF_INET
: AF_INET6
, blob
, 0);
49 static void usage(void)
53 ipsec pool --status|--add|--del|--resize|--purge [options]\n\
55 ipsec pool --status\n\
56 Show a list of installed pools with statistics.\n\
58 ipsec pool --add <name> --start <start> --end <end> [--timeout <timeout>]\n\
59 Add a new pool to the database.\n\
60 name: Name of the pool, as used in ipsec.conf rightsourceip=%%name\n\
61 start: Start address of the pool\n\
62 end: End address of the pool\n\
63 timeout: Lease time in hours, 0 for static leases\n\
65 ipsec pool --del <name>\n\
66 Delete a pool from the database.\n\
67 name: Name of the pool to delete\n\
69 ipsec pool --resize <name> --end <end>\n\
70 Grow or shrink an existing pool.\n\
71 name: Name of the pool to resize\n\
72 end: New end address for the pool\n\
74 ipsec pool --leases <name> [--filter <filter>] [--utc]\n\
75 Show lease information using filters:\n\
76 name: Name of the pool to show leases from\n\
77 filter: Filter string - unimplemented\n\
78 utc: Show times in UTC instead of local time\n\
80 ipsec pool --purge <name>\n\
81 Delete expired leases of a pool:\n\
82 name: Name of the pool to purge\n\
88 * ipsec pool --status - show pool overview
90 static void status(void)
92 enumerator_t
*pool
, *lease
;
95 pool
= db
->query(db
, "SELECT id, name, start, end, timeout FROM pools",
96 DB_INT
, DB_TEXT
, DB_BLOB
, DB_BLOB
, DB_UINT
);
100 chunk_t start_chunk
, end_chunk
;
102 u_int id
, timeout
, online
= 0;
104 while (pool
->enumerate(pool
, &id
, &name
,
105 &start_chunk
, &end_chunk
, &timeout
))
109 printf("%8s %15s %15s %8s %6s\n",
110 "name", "start", "end", "lease", "online");
114 start
= host_create_from_blob(start_chunk
);
115 end
= host_create_from_blob(end_chunk
);
116 printf("%8s %15H %15H ", name
, start
, end
);
119 printf("%7dh ", timeout
/3600);
123 printf("%8s ", "static");
126 lease
= db
->query(db
, "SELECT COUNT(*) FROM leases "
127 "WHERE pool = ? AND released IS NULL",
128 DB_UINT
, id
, DB_INT
);
131 lease
->enumerate(lease
, &online
);
132 lease
->destroy(lease
);
134 printf("%6d\n", online
);
143 printf("no pools found.\n");
149 * ipsec pool --add - add a new pool
151 static void add(char *name
, host_t
*start
, host_t
*end
, int timeout
)
153 if (db
->execute(db
, NULL
,
154 "INSERT INTO pools (name, start, end, next, timeout) "
155 "VALUES (?, ?, ?, ?, ?)",
156 DB_TEXT
, name
, DB_BLOB
, start
->get_address(start
),
157 DB_BLOB
, end
->get_address(end
), DB_BLOB
, start
->get_address(start
),
158 DB_INT
, timeout
*3600) != 1)
160 fprintf(stderr
, "creating pool failed.\n");
167 * ipsec pool --del - delete a pool
169 static void del(char *name
)
175 query
= db
->query(db
, "SELECT id FROM pools WHERE name = ?",
176 DB_TEXT
, name
, DB_UINT
);
179 fprintf(stderr
, "deleting pool failed.\n");
182 while (query
->enumerate(query
, &id
))
185 if (db
->execute(db
, NULL
,
186 "DELETE FROM pools WHERE id = ?", DB_UINT
, id
) != 1 ||
187 db
->execute(db
, NULL
,
188 "DELETE FROM leases WHERE pool = ?", DB_UINT
, id
) < 0)
190 fprintf(stderr
, "deleting pool failed.\n");
191 query
->destroy(query
);
195 query
->destroy(query
);
198 fprintf(stderr
, "pool '%s' not found.\n", name
);
205 * ipsec pool --resize - resize a pool
207 static void resize(char *name
, host_t
*end
)
209 /* TODO: check for active leases if we are decreasing pool size */
210 if (db
->execute(db
, NULL
,
211 "UPDATE pools SET end = ? WHERE name = ?",
212 DB_BLOB
, end
->get_address(end
), DB_TEXT
, name
) <= 0)
214 fprintf(stderr
, "pool '%s' not found.\n", name
);
221 * ipsec pool --leases - show lease information of a pool
223 static void leases(char *name
, char *filter
, bool utc
)
226 chunk_t address_chunk
, identity_chunk
;
228 u_int acquired
, released
, timeout
;
230 identification_t
*identity
;
233 query
= db
->query(db
, "SELECT name, address, identities.type, "
234 "identities.data, acquired, released, timeout "
235 "FROM leases JOIN pools ON leases.pool = pools.id "
236 "JOIN identities ON leases.identity = identities.id ",
237 DB_TEXT
, DB_BLOB
, DB_INT
,
238 DB_BLOB
, DB_UINT
, DB_UINT
, DB_UINT
);
241 fprintf(stderr
, "querying leases failed.\n");
244 while (query
->enumerate(query
, &name
, &address_chunk
, &identity_type
,
245 &identity_chunk
, &acquired
, &released
, &timeout
))
249 int len
= utc ?
25 : 21;
252 printf("%-8s %15s %-33s %-*s %-*s %-7s\n",
253 "name", "address", "identity", len
, "start", len
, "end", "status");
255 address
= host_create_from_blob(address_chunk
);
256 identity
= identification_create_from_encoding(identity_type
, identity_chunk
);
258 printf("%-8s %15H %-32D %#T ", name
, address
, identity
, &acquired
, utc
);
261 printf("%#T ", &released
, utc
);
269 printf("%-7s\n", "online");
271 else if (timeout
== 0)
273 printf("%-7s\n", "static");
275 else if (released
>= time(NULL
) - timeout
)
277 printf("%-7s\n", "valid");
281 printf("%-7s\n", "expired");
284 identity
->destroy(identity
);
286 query
->destroy(query
);
289 fprintf(stderr
, "no matching leases found.\n");
296 * ipsec pool --purge - delete expired leases
298 static void purge(char *name
)
301 u_int id
, timeout
, purged
= 0;
303 query
= db
->query(db
, "SELECT id, timeout FROM pools WHERE name = ?",
304 DB_TEXT
, name
, DB_UINT
, DB_UINT
);
307 fprintf(stderr
, "purging pool failed.\n");
310 if (query
->enumerate(query
, &id
, &timeout
))
312 purged
= db
->execute(db
, NULL
,
313 "DELETE FROM leases WHERE pool = ? "
314 "AND released IS NOT NULL AND released < ?",
315 DB_UINT
, id
, DB_UINT
, time(NULL
) - timeout
);
317 query
->destroy(query
);
318 fprintf(stderr
, "purged %d leases in pool '%s'.\n", purged
, name
);
322 * atexit handler to close db on shutdown
324 static void cleanup(void)
332 * Logging hook for library logs, using stderr output
334 static void dbg_stderr(int level
, char *fmt
, ...)
341 vfprintf(stderr
, fmt
, args
);
342 fprintf(stderr
, "\n");
347 int main(int argc
, char *argv
[])
349 char *uri
, *name
= "", *filter
= "";
360 } operation
= OP_USAGE
;
363 library_init(STRONGSWAN_CONF
);
364 atexit(library_deinit
);
365 lib
->plugins
->load(lib
->plugins
, IPSEC_PLUGINDIR
,
366 lib
->settings
->get_str(lib
->settings
, "pool.load", PLUGINS
));
368 uri
= lib
->settings
->get_str(lib
->settings
, "charon.plugins.sql.database", NULL
);
371 fprintf(stderr
, "database URI charon.plugins.sql.database not set.\n");
374 db
= lib
->db
->create(lib
->db
, uri
);
377 fprintf(stderr
, "opening database failed.\n");
386 struct option long_opts
[] = {
387 { "help", no_argument
, NULL
, 'h' },
389 { "utc", no_argument
, NULL
, 'u' },
390 { "status", no_argument
, NULL
, 'w' },
391 { "add", required_argument
, NULL
, 'a' },
392 { "del", required_argument
, NULL
, 'd' },
393 { "resize", required_argument
, NULL
, 'r' },
394 { "leases", optional_argument
, NULL
, 'l' },
395 { "purge", required_argument
, NULL
, 'p' },
397 { "start", required_argument
, NULL
, 's' },
398 { "end", required_argument
, NULL
, 'e' },
399 { "timeout", required_argument
, NULL
, 't' },
400 { "filter", required_argument
, NULL
, 'f' },
404 c
= getopt_long(argc
, argv
, "", long_opts
, NULL
);
415 operation
= OP_STATUS
;
426 operation
= OP_RESIZE
;
430 operation
= OP_LEASES
;
434 operation
= OP_PURGE
;
438 start
= host_create_from_string(optarg
, 0);
441 fprintf(stderr
, "invalid start address: '%s'.\n", optarg
);
442 operation
= OP_USAGE
;
447 end
= host_create_from_string(optarg
, 0);
450 fprintf(stderr
, "invalid end address: '%s'.\n", optarg
);
451 operation
= OP_USAGE
;
456 timeout
= atoi(optarg
);
457 if (timeout
== 0 && strcmp(optarg
, "0") != 0)
459 fprintf(stderr
, "invalid timeout '%s'.\n", optarg
);
460 operation
= OP_USAGE
;
468 operation
= OP_USAGE
;
483 if (start
== NULL
|| end
== NULL
)
485 fprintf(stderr
, "missing arguments.\n");
488 add(name
, start
, end
, timeout
);
496 fprintf(stderr
, "missing arguments.\n");
502 leases(name
, filter
, utc
);