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);
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>\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\
79 ipsec pool --purge <name>\n\
80 Delete expired leases of a pool:\n\
81 name: Name of the pool to purge\n\
87 * ipsec pool --status - show pool overview
91 enumerator_t
*pool
, *lease
;
94 pool
= db
->query(db
, "SELECT id, name, start, end, timeout FROM pools",
95 DB_INT
, DB_TEXT
, DB_BLOB
, DB_BLOB
, DB_UINT
);
99 chunk_t start_chunk
, end_chunk
;
101 u_int id
, timeout
, online
= 0;
103 while (pool
->enumerate(pool
, &id
, &name
,
104 &start_chunk
, &end_chunk
, &timeout
))
108 printf("%8s %15s %15s %8s %6s\n",
109 "name", "start", "end", "lease", "online");
113 start
= host_create_from_blob(start_chunk
);
114 end
= host_create_from_blob(end_chunk
);
115 printf("%8s %15H %15H ", name
, start
, end
);
118 printf("%7dh ", timeout
/3600);
122 printf("%8s ", "static");
125 lease
= db
->query(db
, "SELECT COUNT(*) FROM leases "
126 "WHERE pool = ? AND released IS NULL",
127 DB_UINT
, id
, DB_INT
);
130 lease
->enumerate(lease
, &online
);
131 lease
->destroy(lease
);
133 printf("%6d\n", online
);
142 printf("no pools found.\n");
148 * ipsec pool --add - add a new pool
150 static void add(char *name
, host_t
*start
, host_t
*end
, int timeout
)
152 if (db
->execute(db
, NULL
,
153 "INSERT INTO pools (name, start, end, next, timeout) "
154 "VALUES (?, ?, ?, ?, ?)",
155 DB_TEXT
, name
, DB_BLOB
, start
->get_address(start
),
156 DB_BLOB
, end
->get_address(end
), DB_BLOB
, start
->get_address(start
),
157 DB_INT
, timeout
*3600) != 1)
159 fprintf(stderr
, "creating pool failed.\n");
166 * ipsec pool --del - delete a pool
168 static void del(char *name
)
174 query
= db
->query(db
, "SELECT id FROM pools WHERE name = ?",
175 DB_TEXT
, name
, DB_UINT
);
178 fprintf(stderr
, "deleting pool failed.\n");
181 while (query
->enumerate(query
, &id
))
184 if (db
->execute(db
, NULL
,
185 "DELETE FROM pools WHERE id = ?", DB_UINT
, id
) != 1 ||
186 db
->execute(db
, NULL
,
187 "DELETE FROM leases WHERE pool = ?", DB_UINT
, id
) < 0)
189 fprintf(stderr
, "deleting pool failed.\n");
190 query
->destroy(query
);
194 query
->destroy(query
);
197 fprintf(stderr
, "pool '%s' not found.\n", name
);
204 * ipsec pool --resize - resize a pool
206 static void resize(char *name
, host_t
*end
)
208 /* TODO: check for active leases if we are decreasing pool size */
209 if (db
->execute(db
, NULL
,
210 "UPDATE pools SET end = ? WHERE name = ?",
211 DB_BLOB
, end
->get_address(end
), DB_TEXT
, name
) <= 0)
213 fprintf(stderr
, "pool '%s' not found.\n", name
);
220 * ipsec pool --leases - show lease information of a pool
222 static void leases(char *name
, char *filter
)
225 chunk_t address_chunk
, identity_chunk
;
227 u_int acquired
, released
, timeout
;
229 identification_t
*identity
;
232 query
= db
->query(db
, "SELECT name, address, identities.type, "
233 "identities.data, acquired, released, timeout "
234 "FROM leases JOIN pools ON leases.pool = pools.id "
235 "JOIN identities ON leases.identity = identities.id ",
236 DB_TEXT
, DB_BLOB
, DB_INT
,
237 DB_BLOB
, DB_UINT
, DB_UINT
, DB_UINT
);
240 fprintf(stderr
, "querying leases failed.\n");
243 while (query
->enumerate(query
, &name
, &address_chunk
, &identity_type
,
244 &identity_chunk
, &acquired
, &released
, &timeout
))
249 printf("%-8s %15s %-33s %-25s %-25s %-7s\n",
250 "name", "address", "identity", "start", "end", "status");
252 address
= host_create_from_blob(address_chunk
);
253 identity
= identification_create_from_encoding(identity_type
, identity_chunk
);
255 printf("%-8s %15H %-32D %T ", name
, address
, identity
, &acquired
);
258 printf("%T ", &released
);
266 printf("%-7s\n", "online");
268 else if (timeout
== 0)
270 printf("%-7s\n", "static");
272 else if (released
>= time(NULL
) - timeout
)
274 printf("%-7s\n", "valid");
278 printf("%-7s\n", "expired");
281 identity
->destroy(identity
);
283 query
->destroy(query
);
286 fprintf(stderr
, "no matching leases found.\n");
293 * ipsec pool --purge - delete expired leases
295 static void purge(char *name
)
298 u_int id
, timeout
, purged
= 0;
300 query
= db
->query(db
, "SELECT id, timeout FROM pools WHERE name = ?",
301 DB_TEXT
, name
, DB_UINT
, DB_UINT
);
304 fprintf(stderr
, "purging pool failed.\n");
307 if (query
->enumerate(query
, &id
, &timeout
))
309 purged
= db
->execute(db
, NULL
,
310 "DELETE FROM leases WHERE pool = ? "
311 "AND released IS NOT NULL AND released < ?",
312 DB_UINT
, id
, DB_UINT
, time(NULL
) - timeout
);
314 query
->destroy(query
);
315 fprintf(stderr
, "purged %d leases in pool '%s'.\n", purged
, name
);
319 * atexit handler to close db on shutdown
321 static void cleanup(void)
329 * Logging hook for library logs, using stderr output
331 static void dbg_stderr(int level
, char *fmt
, ...)
338 vfprintf(stderr
, fmt
, args
);
339 fprintf(stderr
, "\n");
344 int main(int argc
, char *argv
[])
346 char *uri
, *name
= "", *filter
= "";
356 } operation
= OP_USAGE
;
359 library_init(STRONGSWAN_CONF
);
360 atexit(library_deinit
);
361 lib
->plugins
->load(lib
->plugins
, IPSEC_PLUGINDIR
,
362 lib
->settings
->get_str(lib
->settings
, "pool.load", PLUGINS
));
364 uri
= lib
->settings
->get_str(lib
->settings
, "charon.plugins.sql.database", NULL
);
367 fprintf(stderr
, "database URI charon.plugins.sql.database not set.\n");
370 db
= lib
->db
->create(lib
->db
, uri
);
373 fprintf(stderr
, "opening database failed.\n");
382 struct option long_opts
[] = {
383 { "help", no_argument
, NULL
, 'h' },
385 { "status", no_argument
, NULL
, 'w' },
386 { "add", required_argument
, NULL
, 'a' },
387 { "del", required_argument
, NULL
, 'd' },
388 { "resize", required_argument
, NULL
, 'r' },
389 { "leases", optional_argument
, NULL
, 'l' },
390 { "purge", required_argument
, NULL
, 'p' },
392 { "start", required_argument
, NULL
, 's' },
393 { "end", required_argument
, NULL
, 'e' },
394 { "timeout", required_argument
, NULL
, 't' },
395 { "filter", required_argument
, NULL
, 'f' },
399 c
= getopt_long(argc
, argv
, "", long_opts
, NULL
);
407 operation
= OP_STATUS
;
418 operation
= OP_RESIZE
;
422 operation
= OP_LEASES
;
426 operation
= OP_PURGE
;
430 start
= host_create_from_string(optarg
, 0);
433 fprintf(stderr
, "invalid start address: '%s'.\n", optarg
);
434 operation
= OP_USAGE
;
439 end
= host_create_from_string(optarg
, 0);
442 fprintf(stderr
, "invalid end address: '%s'.\n", optarg
);
443 operation
= OP_USAGE
;
448 timeout
= atoi(optarg
);
449 if (timeout
== 0 && strcmp(optarg
, "0") != 0)
451 fprintf(stderr
, "invalid timeout '%s'.\n", optarg
);
452 operation
= OP_USAGE
;
460 operation
= OP_USAGE
;
475 if (start
== NULL
|| end
== NULL
)
477 fprintf(stderr
, "missing arguments.\n");
480 add(name
, start
, end
, timeout
);
488 fprintf(stderr
, "missing arguments.\n");
494 leases(name
, filter
);