]>
Commit | Line | Data |
---|---|---|
53027034 | 1 | /* |
bf23ca09 | 2 | * Copyright (C) 2011-2017 Tobias Brunner |
53027034 | 3 | * Copyright (C) 2008 Martin Willi |
19ef2aec TB |
4 | * |
5 | * Copyright (C) secunet Security Networks AG | |
53027034 MW |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2 of the License, or (at your | |
10 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | * for more details. | |
53027034 MW |
16 | */ |
17 | ||
18 | #define _GNU_SOURCE | |
19 | #include <getopt.h> | |
20 | #include <unistd.h> | |
21 | #include <stdio.h> | |
7051ef40 | 22 | #include <time.h> |
49a452e3 HH |
23 | #include <string.h> |
24 | #include <errno.h> | |
53027034 | 25 | |
f05b4272 | 26 | #include <utils/debug.h> |
53027034 | 27 | #include <library.h> |
8c33a189 | 28 | #include <collections/array.h> |
2e7cc07e | 29 | #include <networking/host.h> |
ec0b9ac9 | 30 | #include <utils/identification.h> |
645f3865 | 31 | #include <attributes/attributes.h> |
53027034 | 32 | |
ad6dbc41 AS |
33 | #include "pool_attributes.h" |
34 | #include "pool_usage.h" | |
35 | ||
53027034 MW |
36 | /** |
37 | * global database handle | |
38 | */ | |
39 | database_t *db; | |
40 | ||
7051ef40 | 41 | /** |
ad6dbc41 | 42 | * --start/--end addresses of various subcommands |
7051ef40 | 43 | */ |
b7019a5c | 44 | host_t *start_addr = NULL, *end_addr = NULL; |
645f3865 | 45 | |
ef9f69a2 HH |
46 | /** |
47 | * whether --add should --replace an existing pool | |
48 | */ | |
49 | bool replace_pool = FALSE; | |
50 | ||
51 | /** | |
437690f8 | 52 | * forward declarations |
ef9f69a2 HH |
53 | */ |
54 | static void del(char *name); | |
437690f8 HH |
55 | static void do_args(int argc, char *argv[]); |
56 | ||
ef9f69a2 HH |
57 | /** |
58 | * Create or replace a pool by name | |
59 | */ | |
bf23ca09 | 60 | static u_int create_pool(char *name, chunk_t start, chunk_t end, u_int timeout) |
ef9f69a2 HH |
61 | { |
62 | enumerator_t *e; | |
63 | int pool; | |
0a6fbe8f | 64 | bool exists; |
ef9f69a2 HH |
65 | |
66 | e = db->query(db, "SELECT id FROM pools WHERE name = ?", | |
67 | DB_TEXT, name, DB_UINT); | |
0a6fbe8f TB |
68 | exists = e && e->enumerate(e, &pool); |
69 | DESTROY_IF(e); | |
70 | ||
71 | if (exists) | |
ef9f69a2 | 72 | { |
0a6fbe8f | 73 | if (!replace_pool) |
ef9f69a2 HH |
74 | { |
75 | fprintf(stderr, "pool '%s' exists.\n", name); | |
a90ed06f | 76 | exit(EXIT_FAILURE); |
ef9f69a2 HH |
77 | } |
78 | del(name); | |
79 | } | |
ef9f69a2 HH |
80 | if (db->execute(db, &pool, |
81 | "INSERT INTO pools (name, start, end, timeout) VALUES (?, ?, ?, ?)", | |
82 | DB_TEXT, name, DB_BLOB, start, DB_BLOB, end, | |
bf23ca09 | 83 | DB_UINT, timeout) != 1) |
ef9f69a2 HH |
84 | { |
85 | fprintf(stderr, "creating pool failed.\n"); | |
a90ed06f | 86 | exit(EXIT_FAILURE); |
ef9f69a2 HH |
87 | } |
88 | ||
89 | return pool; | |
90 | } | |
91 | ||
645f3865 AS |
92 | /** |
93 | * instead of a pool handle a DNS or NBNS attribute | |
94 | */ | |
95 | static bool is_attribute(char *name) | |
96 | { | |
97 | return strcaseeq(name, "dns") || strcaseeq(name, "nbns") || | |
98 | strcaseeq(name, "wins"); | |
99 | } | |
100 | ||
2ba1f9e7 MW |
101 | /** |
102 | * calculate the size of a pool using start and end address chunk | |
103 | */ | |
104 | static u_int get_pool_size(chunk_t start, chunk_t end) | |
105 | { | |
106 | u_int *start_ptr, *end_ptr; | |
107 | ||
108 | if (start.len < sizeof(u_int) || end.len < sizeof(u_int)) | |
109 | { | |
7daf5226 | 110 | return 0; |
2ba1f9e7 MW |
111 | } |
112 | start_ptr = (u_int*)(start.ptr + start.len - sizeof(u_int)); | |
113 | end_ptr = (u_int*)(end.ptr + end.len - sizeof(u_int)); | |
114 | return ntohl(*end_ptr) - ntohl(*start_ptr) + 1; | |
115 | } | |
116 | ||
53027034 MW |
117 | /** |
118 | * ipsec pool --status - show pool overview | |
119 | */ | |
c7d81ad1 | 120 | static void status(void) |
53027034 | 121 | { |
645f3865 AS |
122 | enumerator_t *ns, *pool, *lease; |
123 | host_t *server; | |
124 | chunk_t value; | |
53027034 | 125 | bool found = FALSE; |
7daf5226 | 126 | |
645f3865 AS |
127 | /* enumerate IPv4 DNS servers */ |
128 | ns = db->query(db, "SELECT value FROM attributes WHERE type = ?", | |
129 | DB_INT, INTERNAL_IP4_DNS, DB_BLOB); | |
130 | if (ns) | |
131 | { | |
132 | while (ns->enumerate(ns, &value)) | |
133 | { | |
134 | if (!found) | |
135 | { | |
136 | printf("dns servers:"); | |
137 | found = TRUE; | |
138 | } | |
139 | server = host_create_from_chunk(AF_INET, value, 0); | |
140 | if (server) | |
141 | { | |
142 | printf(" %H", server); | |
143 | server->destroy(server); | |
144 | } | |
145 | } | |
146 | ns->destroy(ns); | |
147 | } | |
148 | ||
149 | /* enumerate IPv6 DNS servers */ | |
150 | ns = db->query(db, "SELECT value FROM attributes WHERE type = ?", | |
151 | DB_INT, INTERNAL_IP6_DNS, DB_BLOB); | |
152 | if (ns) | |
153 | { | |
154 | while (ns->enumerate(ns, &value)) | |
155 | { | |
156 | if (!found) | |
157 | { | |
158 | printf("dns servers:"); | |
159 | found = TRUE; | |
160 | } | |
161 | server = host_create_from_chunk(AF_INET6, value, 0); | |
162 | if (server) | |
163 | { | |
164 | printf(" %H", server); | |
165 | server->destroy(server); | |
166 | } | |
167 | } | |
168 | ns->destroy(ns); | |
169 | } | |
170 | if (found) | |
171 | { | |
172 | printf("\n"); | |
173 | } | |
174 | else | |
175 | { | |
176 | printf("no dns servers found.\n"); | |
177 | } | |
178 | found = FALSE; | |
179 | ||
180 | /* enumerate IPv4 NBNS servers */ | |
181 | ns = db->query(db, "SELECT value FROM attributes WHERE type = ?", | |
182 | DB_INT, INTERNAL_IP4_NBNS, DB_BLOB); | |
183 | if (ns) | |
184 | { | |
185 | while (ns->enumerate(ns, &value)) | |
186 | { | |
187 | if (!found) | |
188 | { | |
189 | printf("nbns servers:"); | |
190 | found = TRUE; | |
191 | } | |
192 | server = host_create_from_chunk(AF_INET, value, 0); | |
193 | if (server) | |
194 | { | |
195 | printf(" %H", server); | |
196 | server->destroy(server); | |
197 | } | |
198 | } | |
199 | ns->destroy(ns); | |
200 | } | |
201 | ||
202 | /* enumerate IPv6 NBNS servers */ | |
203 | ns = db->query(db, "SELECT value FROM attributes WHERE type = ?", | |
204 | DB_INT, INTERNAL_IP6_NBNS, DB_BLOB); | |
205 | if (ns) | |
206 | { | |
207 | while (ns->enumerate(ns, &value)) | |
208 | { | |
209 | if (!found) | |
210 | { | |
211 | printf("nbns servers:"); | |
212 | found = TRUE; | |
213 | } | |
214 | server = host_create_from_chunk(AF_INET6, value, 0); | |
215 | if (server) | |
216 | { | |
217 | printf(" %H", server); | |
218 | server->destroy(server); | |
219 | } | |
220 | } | |
221 | ns->destroy(ns); | |
222 | } | |
223 | if (found) | |
224 | { | |
225 | printf("\n"); | |
226 | } | |
227 | else | |
228 | { | |
229 | printf("no nbns servers found.\n"); | |
230 | } | |
231 | found = FALSE; | |
232 | ||
53027034 MW |
233 | pool = db->query(db, "SELECT id, name, start, end, timeout FROM pools", |
234 | DB_INT, DB_TEXT, DB_BLOB, DB_BLOB, DB_UINT); | |
235 | if (pool) | |
236 | { | |
237 | char *name; | |
238 | chunk_t start_chunk, end_chunk; | |
239 | host_t *start, *end; | |
2ba1f9e7 | 240 | u_int id, timeout, online = 0, used = 0, size = 0; |
7daf5226 | 241 | |
53027034 MW |
242 | while (pool->enumerate(pool, &id, &name, |
243 | &start_chunk, &end_chunk, &timeout)) | |
244 | { | |
245 | if (!found) | |
246 | { | |
875a8326 MW |
247 | printf("%8s %15s %15s %8s %6s %11s %11s\n", "name", "start", |
248 | "end", "timeout", "size", "online", "usage"); | |
53027034 MW |
249 | found = TRUE; |
250 | } | |
7daf5226 | 251 | |
b8cbb645 MW |
252 | start = host_create_from_chunk(AF_UNSPEC, start_chunk, 0); |
253 | end = host_create_from_chunk(AF_UNSPEC, end_chunk, 0); | |
49a452e3 HH |
254 | if (start->is_anyaddr(start) && end->is_anyaddr(end)) |
255 | { | |
256 | printf("%8s %15s %15s ", name, "n/a", "n/a"); | |
257 | } | |
258 | else | |
259 | { | |
260 | printf("%8s %15H %15H ", name, start, end); | |
261 | } | |
53027034 MW |
262 | if (timeout) |
263 | { | |
bf23ca09 TB |
264 | if (timeout >= 60 * 300) |
265 | { | |
266 | printf("%7dh ", timeout/3600); | |
267 | } | |
268 | else if (timeout >= 300) | |
269 | { | |
270 | printf("%7dm ", timeout/60); | |
271 | } | |
272 | else | |
273 | { | |
274 | printf("%7ds ", timeout); | |
275 | } | |
53027034 MW |
276 | } |
277 | else | |
278 | { | |
279 | printf("%8s ", "static"); | |
280 | } | |
49a452e3 HH |
281 | /* get total number of hosts in the pool */ |
282 | lease = db->query(db, "SELECT COUNT(*) FROM addresses " | |
283 | "WHERE pool = ?", DB_UINT, id, DB_INT); | |
284 | if (lease) | |
285 | { | |
286 | lease->enumerate(lease, &size); | |
287 | lease->destroy(lease); | |
288 | } | |
86685852 TB |
289 | if (!size) |
290 | { /* empty pool */ | |
291 | printf("%6d %11s %11s ", 0, "n/a", "n/a"); | |
292 | goto next_pool; | |
293 | } | |
89c87995 | 294 | printf("%6d ", size); |
2ba1f9e7 | 295 | /* get number of online hosts */ |
f7198e7e | 296 | lease = db->query(db, "SELECT COUNT(*) FROM addresses " |
a01ad993 | 297 | "WHERE pool = ? AND released = 0", |
7051ef40 MW |
298 | DB_UINT, id, DB_INT); |
299 | if (lease) | |
300 | { | |
301 | lease->enumerate(lease, &online); | |
302 | lease->destroy(lease); | |
303 | } | |
2ba1f9e7 | 304 | printf("%5d (%2d%%) ", online, online*100/size); |
86685852 | 305 | /* get number of online or valid leases */ |
875a8326 MW |
306 | lease = db->query(db, "SELECT COUNT(*) FROM addresses " |
307 | "WHERE addresses.pool = ? " | |
308 | "AND ((? AND acquired != 0) " | |
309 | " OR released = 0 OR released > ?) ", | |
310 | DB_UINT, id, DB_UINT, !timeout, | |
311 | DB_UINT, time(NULL) - timeout, DB_UINT); | |
2ba1f9e7 MW |
312 | if (lease) |
313 | { | |
314 | lease->enumerate(lease, &used); | |
315 | lease->destroy(lease); | |
316 | } | |
317 | printf("%5d (%2d%%) ", used, used*100/size); | |
7daf5226 | 318 | |
86685852 | 319 | next_pool: |
2ba1f9e7 | 320 | printf("\n"); |
53027034 MW |
321 | DESTROY_IF(start); |
322 | DESTROY_IF(end); | |
323 | } | |
324 | pool->destroy(pool); | |
325 | } | |
326 | if (!found) | |
327 | { | |
328 | printf("no pools found.\n"); | |
329 | } | |
53027034 MW |
330 | } |
331 | ||
332 | /** | |
333 | * ipsec pool --add - add a new pool | |
334 | */ | |
bf23ca09 | 335 | static void add(char *name, host_t *start, host_t *end, u_int timeout) |
53027034 | 336 | { |
b7019a5c | 337 | chunk_t start_chunk, end_chunk, cur_addr; |
f7198e7e | 338 | u_int id, count; |
7daf5226 | 339 | |
b7019a5c TB |
340 | start_chunk = start->get_address(start); |
341 | end_chunk = end->get_address(end); | |
342 | cur_addr = chunk_clonea(start_chunk); | |
343 | count = get_pool_size(start_chunk, end_chunk); | |
f3e11fc4 | 344 | |
b7019a5c TB |
345 | if (start_chunk.len != end_chunk.len || |
346 | memcmp(start_chunk.ptr, end_chunk.ptr, start_chunk.len) > 0) | |
f3e11fc4 MW |
347 | { |
348 | fprintf(stderr, "invalid start/end pair specified.\n"); | |
a90ed06f | 349 | exit(EXIT_FAILURE); |
f3e11fc4 | 350 | } |
b7019a5c | 351 | id = create_pool(name, start_chunk, end_chunk, timeout); |
f7198e7e MW |
352 | printf("allocating %d addresses... ", count); |
353 | fflush(stdout); | |
b283a6e9 | 354 | db->transaction(db, FALSE); |
875a8326 | 355 | while (TRUE) |
f7198e7e MW |
356 | { |
357 | db->execute(db, NULL, | |
358 | "INSERT INTO addresses (pool, address, identity, acquired, released) " | |
359 | "VALUES (?, ?, ?, ?, ?)", | |
360 | DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1); | |
b7019a5c | 361 | if (chunk_equals(cur_addr, end_chunk)) |
875a8326 MW |
362 | { |
363 | break; | |
364 | } | |
500f515a | 365 | chunk_increment(cur_addr); |
f7198e7e | 366 | } |
03c801cb | 367 | db->commit(db); |
7b125216 | 368 | printf("done.\n"); |
53027034 MW |
369 | } |
370 | ||
49a452e3 HH |
371 | static bool add_address(u_int pool_id, char *address_str, int *family) |
372 | { | |
373 | host_t *address; | |
374 | int user_id = 0; | |
375 | ||
376 | char *pos_eq = strchr(address_str, '='); | |
377 | if (pos_eq != NULL) | |
378 | { | |
49a452e3 | 379 | identification_t *id = identification_create_from_string(pos_eq + 1); |
ec7adea0 HH |
380 | user_id = get_identity(id); |
381 | id->destroy(id); | |
49a452e3 | 382 | |
ec7adea0 | 383 | if (user_id == 0) |
49a452e3 | 384 | { |
ec7adea0 | 385 | return FALSE; |
49a452e3 | 386 | } |
49a452e3 HH |
387 | *pos_eq = '\0'; |
388 | } | |
389 | ||
390 | address = host_create_from_string(address_str, 0); | |
391 | if (address == NULL) | |
392 | { | |
393 | fprintf(stderr, "invalid address '%s'.\n", address_str); | |
394 | return FALSE; | |
395 | } | |
e5143952 TB |
396 | if (family && *family != AF_UNSPEC && |
397 | *family != address->get_family(address)) | |
49a452e3 HH |
398 | { |
399 | fprintf(stderr, "invalid address family '%s'.\n", address_str); | |
00b9f755 | 400 | address->destroy(address); |
49a452e3 HH |
401 | return FALSE; |
402 | } | |
403 | ||
404 | if (db->execute(db, NULL, | |
405 | "INSERT INTO addresses " | |
406 | "(pool, address, identity, acquired, released) " | |
407 | "VALUES (?, ?, ?, ?, ?)", | |
408 | DB_UINT, pool_id, DB_BLOB, address->get_address(address), | |
409 | DB_UINT, user_id, DB_UINT, 0, DB_UINT, 1) != 1) | |
410 | { | |
411 | fprintf(stderr, "inserting address '%s' failed.\n", address_str); | |
00b9f755 | 412 | address->destroy(address); |
49a452e3 HH |
413 | return FALSE; |
414 | } | |
e5143952 TB |
415 | if (family) |
416 | { | |
417 | *family = address->get_family(address); | |
418 | } | |
49a452e3 HH |
419 | address->destroy(address); |
420 | ||
421 | return TRUE; | |
422 | } | |
423 | ||
bf23ca09 | 424 | static void add_addresses(char *pool, char *path, u_int timeout) |
49a452e3 HH |
425 | { |
426 | u_int pool_id, count = 0; | |
427 | int family = AF_UNSPEC; | |
428 | char address_str[512]; | |
429 | host_t *addr; | |
430 | FILE *file; | |
431 | ||
b283a6e9 | 432 | db->transaction(db, FALSE); |
49a452e3 HH |
433 | |
434 | addr = host_create_from_string("%any", 0); | |
ef9f69a2 HH |
435 | pool_id = create_pool(pool, addr->get_address(addr), |
436 | addr->get_address(addr), timeout); | |
49a452e3 HH |
437 | addr->destroy(addr); |
438 | ||
439 | file = (strcmp(path, "-") == 0 ? stdin : fopen(path, "r")); | |
440 | if (file == NULL) | |
441 | { | |
442 | fprintf(stderr, "opening '%s' failed: %s\n", path, strerror(errno)); | |
443 | exit(-1); | |
444 | } | |
445 | ||
446 | printf("starting allocation... "); | |
447 | fflush(stdout); | |
448 | ||
449 | while (fgets(address_str, sizeof(address_str), file)) | |
450 | { | |
451 | size_t addr_len = strlen(address_str); | |
452 | char *last_chr = address_str + addr_len - 1; | |
453 | if (*last_chr == '\n') | |
454 | { | |
455 | if (addr_len == 1) | |
456 | { /* end of input */ | |
457 | break; | |
458 | } | |
459 | *last_chr = '\0'; | |
460 | } | |
461 | if (add_address(pool_id, address_str, &family) == FALSE) | |
462 | { | |
00b9f755 TB |
463 | if (file != stdin) |
464 | { | |
465 | fclose(file); | |
466 | } | |
a90ed06f | 467 | exit(EXIT_FAILURE); |
49a452e3 HH |
468 | } |
469 | ++count; | |
470 | } | |
471 | ||
472 | if (file != stdin) | |
473 | { | |
474 | fclose(file); | |
475 | } | |
476 | ||
2ac772a5 TB |
477 | if (family == AF_INET6) |
478 | { /* update address family if necessary */ | |
479 | addr = host_create_from_string("%any6", 0); | |
480 | if (db->execute(db, NULL, | |
481 | "UPDATE pools SET start = ?, end = ? WHERE id = ?", | |
482 | DB_BLOB, addr->get_address(addr), | |
483 | DB_BLOB, addr->get_address(addr), DB_UINT, pool_id) <= 0) | |
484 | { | |
485 | addr->destroy(addr); | |
486 | fprintf(stderr, "updating pool address family failed.\n"); | |
487 | exit(EXIT_FAILURE); | |
488 | } | |
489 | addr->destroy(addr); | |
490 | } | |
491 | ||
03c801cb | 492 | db->commit(db); |
49a452e3 HH |
493 | |
494 | printf("%d addresses done.\n", count); | |
49a452e3 HH |
495 | } |
496 | ||
53027034 MW |
497 | /** |
498 | * ipsec pool --del - delete a pool | |
499 | */ | |
500 | static void del(char *name) | |
501 | { | |
502 | enumerator_t *query; | |
503 | u_int id; | |
504 | bool found = FALSE; | |
7daf5226 | 505 | |
53027034 MW |
506 | query = db->query(db, "SELECT id FROM pools WHERE name = ?", |
507 | DB_TEXT, name, DB_UINT); | |
508 | if (!query) | |
509 | { | |
510 | fprintf(stderr, "deleting pool failed.\n"); | |
a90ed06f | 511 | exit(EXIT_FAILURE); |
53027034 MW |
512 | } |
513 | while (query->enumerate(query, &id)) | |
514 | { | |
515 | found = TRUE; | |
516 | if (db->execute(db, NULL, | |
f7198e7e MW |
517 | "DELETE FROM leases WHERE address IN (" |
518 | " SELECT id FROM addresses WHERE pool = ?)", DB_UINT, id) < 0 || | |
519 | db->execute(db, NULL, | |
520 | "DELETE FROM addresses WHERE pool = ?", DB_UINT, id) < 0 || | |
53027034 | 521 | db->execute(db, NULL, |
f7198e7e | 522 | "DELETE FROM pools WHERE id = ?", DB_UINT, id) < 0) |
53027034 MW |
523 | { |
524 | fprintf(stderr, "deleting pool failed.\n"); | |
525 | query->destroy(query); | |
a90ed06f | 526 | exit(EXIT_FAILURE); |
53027034 MW |
527 | } |
528 | } | |
529 | query->destroy(query); | |
530 | if (!found) | |
531 | { | |
532 | fprintf(stderr, "pool '%s' not found.\n", name); | |
a90ed06f | 533 | exit(EXIT_FAILURE); |
53027034 | 534 | } |
53027034 MW |
535 | } |
536 | ||
645f3865 | 537 | /** |
7c11d10e | 538 | * ipsec pool --resize - resize a pool |
53027034 MW |
539 | */ |
540 | static void resize(char *name, host_t *end) | |
541 | { | |
f3e11fc4 | 542 | enumerator_t *query; |
f7198e7e MW |
543 | chunk_t old_addr, new_addr, cur_addr; |
544 | u_int id, count; | |
49a452e3 | 545 | host_t *old_end; |
7daf5226 | 546 | |
f7198e7e | 547 | new_addr = end->get_address(end); |
7daf5226 | 548 | |
f7198e7e MW |
549 | query = db->query(db, "SELECT id, end FROM pools WHERE name = ?", |
550 | DB_TEXT, name, DB_UINT, DB_BLOB); | |
551 | if (!query || !query->enumerate(query, &id, &old_addr)) | |
f3e11fc4 MW |
552 | { |
553 | DESTROY_IF(query); | |
554 | fprintf(stderr, "resizing pool failed.\n"); | |
a90ed06f | 555 | exit(EXIT_FAILURE); |
f3e11fc4 | 556 | } |
f7198e7e MW |
557 | if (old_addr.len != new_addr.len || |
558 | memcmp(new_addr.ptr, old_addr.ptr, old_addr.len) < 0) | |
f3e11fc4 | 559 | { |
f7198e7e | 560 | fprintf(stderr, "shrinking of pools not supported.\n"); |
f3e11fc4 | 561 | query->destroy(query); |
a90ed06f | 562 | exit(EXIT_FAILURE); |
f3e11fc4 | 563 | } |
f7198e7e MW |
564 | cur_addr = chunk_clonea(old_addr); |
565 | count = get_pool_size(old_addr, new_addr) - 1; | |
f3e11fc4 MW |
566 | query->destroy(query); |
567 | ||
49a452e3 HH |
568 | /* Check whether pool is resizable */ |
569 | old_end = host_create_from_chunk(AF_UNSPEC, old_addr, 0); | |
570 | if (old_end && old_end->is_anyaddr(old_end)) | |
571 | { | |
572 | fprintf(stderr, "pool is not resizable.\n"); | |
573 | old_end->destroy(old_end); | |
a90ed06f | 574 | exit(EXIT_FAILURE); |
49a452e3 HH |
575 | } |
576 | DESTROY_IF(old_end); | |
577 | ||
b283a6e9 | 578 | db->transaction(db, FALSE); |
53027034 MW |
579 | if (db->execute(db, NULL, |
580 | "UPDATE pools SET end = ? WHERE name = ?", | |
f7198e7e | 581 | DB_BLOB, new_addr, DB_TEXT, name) <= 0) |
53027034 MW |
582 | { |
583 | fprintf(stderr, "pool '%s' not found.\n", name); | |
a90ed06f | 584 | exit(EXIT_FAILURE); |
53027034 | 585 | } |
7daf5226 | 586 | |
f7198e7e MW |
587 | printf("allocating %d new addresses... ", count); |
588 | fflush(stdout); | |
f7198e7e MW |
589 | while (count-- > 0) |
590 | { | |
500f515a | 591 | chunk_increment(cur_addr); |
f7198e7e MW |
592 | db->execute(db, NULL, |
593 | "INSERT INTO addresses (pool, address, identity, acquired, released) " | |
594 | "VALUES (?, ?, ?, ?, ?)", | |
595 | DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1); | |
596 | } | |
03c801cb | 597 | db->commit(db); |
e5e5bcc9 | 598 | printf("done.\n"); |
7daf5226 | 599 | |
53027034 MW |
600 | } |
601 | ||
4fa74562 MW |
602 | /** |
603 | * create the lease query using the filter string | |
604 | */ | |
8c33a189 | 605 | static enumerator_t *create_lease_query(char *filter, array_t **to_free) |
4fa74562 MW |
606 | { |
607 | enumerator_t *query; | |
8c33a189 TB |
608 | chunk_t id_chunk = chunk_empty, addr_chunk = chunk_empty; |
609 | id_type_t id_type = 0; | |
4fa74562 MW |
610 | u_int tstamp = 0; |
611 | bool online = FALSE, valid = FALSE, expired = FALSE; | |
6649a3ca | 612 | char *value, *pos, *pool = NULL; |
4fa74562 MW |
613 | enum { |
614 | FIL_POOL = 0, | |
615 | FIL_ID, | |
616 | FIL_ADDR, | |
617 | FIL_TSTAMP, | |
618 | FIL_STATE, | |
619 | }; | |
620 | char *const token[] = { | |
621 | [FIL_POOL] = "pool", | |
622 | [FIL_ID] = "id", | |
623 | [FIL_ADDR] = "addr", | |
624 | [FIL_TSTAMP] = "tstamp", | |
625 | [FIL_STATE] = "status", | |
626 | NULL | |
627 | }; | |
7daf5226 | 628 | |
1e5522ff AS |
629 | /* if the filter string contains a distinguished name as a ID, we replace |
630 | * ", " by "/ " in order to not confuse the getsubopt parser */ | |
6649a3ca MW |
631 | pos = filter; |
632 | while ((pos = strchr(pos, ','))) | |
633 | { | |
634 | if (pos[1] == ' ') | |
635 | { | |
1e5522ff | 636 | pos[0] = '/'; |
6649a3ca MW |
637 | } |
638 | pos++; | |
639 | } | |
7daf5226 | 640 | |
4fa74562 MW |
641 | while (filter && *filter != '\0') |
642 | { | |
643 | switch (getsubopt(&filter, token, &value)) | |
644 | { | |
645 | case FIL_POOL: | |
646 | if (value) | |
647 | { | |
648 | pool = value; | |
649 | } | |
650 | break; | |
651 | case FIL_ID: | |
652 | if (value) | |
653 | { | |
8c33a189 TB |
654 | identification_t *id; |
655 | ||
4fa74562 | 656 | id = identification_create_from_string(value); |
8c33a189 TB |
657 | id_type = id->get_type(id); |
658 | id_chunk = chunk_clone(id->get_encoding(id)); | |
659 | array_insert_create(to_free, ARRAY_TAIL, id_chunk.ptr); | |
660 | id->destroy(id); | |
4fa74562 | 661 | } |
4fa74562 MW |
662 | break; |
663 | case FIL_ADDR: | |
664 | if (value) | |
665 | { | |
8c33a189 TB |
666 | host_t *addr; |
667 | ||
4fa74562 | 668 | addr = host_create_from_string(value, 0); |
8c33a189 TB |
669 | if (!addr) |
670 | { | |
671 | fprintf(stderr, "invalid 'addr' in filter string.\n"); | |
672 | exit(EXIT_FAILURE); | |
673 | } | |
674 | addr_chunk = chunk_clone(addr->get_address(addr)); | |
675 | array_insert_create(to_free, ARRAY_TAIL, addr_chunk.ptr); | |
676 | addr->destroy(addr); | |
4fa74562 MW |
677 | } |
678 | break; | |
679 | case FIL_TSTAMP: | |
680 | if (value) | |
681 | { | |
682 | tstamp = atoi(value); | |
683 | } | |
684 | if (tstamp == 0) | |
685 | { | |
686 | online = TRUE; | |
687 | } | |
688 | break; | |
689 | case FIL_STATE: | |
690 | if (value) | |
691 | { | |
692 | if (streq(value, "online")) | |
693 | { | |
694 | online = TRUE; | |
695 | } | |
696 | else if (streq(value, "valid")) | |
697 | { | |
698 | valid = TRUE; | |
699 | } | |
700 | else if (streq(value, "expired")) | |
701 | { | |
702 | expired = TRUE; | |
703 | } | |
704 | else | |
705 | { | |
706 | fprintf(stderr, "invalid 'state' in filter string.\n"); | |
a90ed06f | 707 | exit(EXIT_FAILURE); |
4fa74562 MW |
708 | } |
709 | } | |
710 | break; | |
711 | default: | |
712 | fprintf(stderr, "invalid filter string.\n"); | |
a90ed06f | 713 | exit(EXIT_FAILURE); |
4fa74562 MW |
714 | } |
715 | } | |
716 | query = db->query(db, | |
f7198e7e MW |
717 | "SELECT name, addresses.address, identities.type, " |
718 | "identities.data, leases.acquired, leases.released, timeout " | |
719 | "FROM leases JOIN addresses ON leases.address = addresses.id " | |
720 | "JOIN pools ON addresses.pool = pools.id " | |
4fa74562 MW |
721 | "JOIN identities ON leases.identity = identities.id " |
722 | "WHERE (? OR name = ?) " | |
723 | "AND (? OR (identities.type = ? AND identities.data = ?)) " | |
f7198e7e MW |
724 | "AND (? OR addresses.address = ?) " |
725 | "AND (? OR (? >= leases.acquired AND (? <= leases.released))) " | |
726 | "AND (? OR leases.released > ? - timeout) " | |
727 | "AND (? OR leases.released < ? - timeout) " | |
728 | "AND ? " | |
729 | "UNION " | |
730 | "SELECT name, address, identities.type, identities.data, " | |
731 | "acquired, released, timeout FROM addresses " | |
732 | "JOIN pools ON addresses.pool = pools.id " | |
733 | "JOIN identities ON addresses.identity = identities.id " | |
734 | "WHERE ? AND released = 0 " | |
735 | "AND (? OR name = ?) " | |
736 | "AND (? OR (identities.type = ? AND identities.data = ?)) " | |
737 | "AND (? OR address = ?)", | |
4fa74562 | 738 | DB_INT, pool == NULL, DB_TEXT, pool, |
8c33a189 TB |
739 | DB_INT, !id_chunk.ptr, |
740 | DB_INT, id_type, | |
741 | DB_BLOB, id_chunk, | |
742 | DB_INT, !addr_chunk.ptr, | |
743 | DB_BLOB, addr_chunk, | |
4fa74562 | 744 | DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp, |
4fa74562 MW |
745 | DB_INT, !valid, DB_INT, time(NULL), |
746 | DB_INT, !expired, DB_INT, time(NULL), | |
f7198e7e MW |
747 | DB_INT, !online, |
748 | /* union */ | |
749 | DB_INT, !(valid || expired), | |
750 | DB_INT, pool == NULL, DB_TEXT, pool, | |
8c33a189 TB |
751 | DB_INT, !id_chunk.ptr, |
752 | DB_INT, id_type, | |
753 | DB_BLOB, id_chunk, | |
754 | DB_INT, !addr_chunk.ptr, | |
755 | DB_BLOB, addr_chunk, | |
f7198e7e | 756 | /* res */ |
4fa74562 | 757 | DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT); |
4fa74562 MW |
758 | return query; |
759 | } | |
760 | ||
53027034 MW |
761 | /** |
762 | * ipsec pool --leases - show lease information of a pool | |
763 | */ | |
4fa74562 | 764 | static void leases(char *filter, bool utc) |
53027034 MW |
765 | { |
766 | enumerator_t *query; | |
8c33a189 | 767 | array_t *to_free = NULL; |
53027034 MW |
768 | chunk_t address_chunk, identity_chunk; |
769 | int identity_type; | |
4fa74562 | 770 | char *name; |
d12ad474 AS |
771 | u_int db_acquired, db_released, db_timeout; |
772 | time_t acquired, released, timeout; | |
53027034 MW |
773 | host_t *address; |
774 | identification_t *identity; | |
775 | bool found = FALSE; | |
7daf5226 | 776 | |
8c33a189 | 777 | query = create_lease_query(filter, &to_free); |
53027034 MW |
778 | if (!query) |
779 | { | |
780 | fprintf(stderr, "querying leases failed.\n"); | |
a90ed06f | 781 | exit(EXIT_FAILURE); |
53027034 | 782 | } |
7051ef40 | 783 | while (query->enumerate(query, &name, &address_chunk, &identity_type, |
d12ad474 | 784 | &identity_chunk, &db_acquired, &db_released, &db_timeout)) |
53027034 MW |
785 | { |
786 | if (!found) | |
787 | { | |
7dfb8a1b AS |
788 | int len = utc ? 25 : 21; |
789 | ||
53027034 | 790 | found = TRUE; |
6649a3ca MW |
791 | printf("%-8s %-15s %-7s %-*s %-*s %s\n", |
792 | "name", "address", "status", len, "start", len, "end", "identity"); | |
53027034 | 793 | } |
b8cbb645 | 794 | address = host_create_from_chunk(AF_UNSPEC, address_chunk, 0); |
53027034 | 795 | identity = identification_create_from_encoding(identity_type, identity_chunk); |
7daf5226 | 796 | |
d12ad474 AS |
797 | /* u_int is not always equal to time_t */ |
798 | acquired = (time_t)db_acquired; | |
799 | released = (time_t)db_released; | |
800 | timeout = (time_t)db_timeout; | |
801 | ||
6649a3ca MW |
802 | printf("%-8s %-15H ", name, address); |
803 | if (released == 0) | |
7051ef40 | 804 | { |
6649a3ca | 805 | printf("%-7s ", "online"); |
7051ef40 | 806 | } |
6649a3ca | 807 | else if (timeout == 0) |
7051ef40 | 808 | { |
6649a3ca | 809 | printf("%-7s ", "static"); |
7051ef40 | 810 | } |
6649a3ca | 811 | else if (released >= time(NULL) - timeout) |
7051ef40 | 812 | { |
6649a3ca | 813 | printf("%-7s ", "valid"); |
7051ef40 | 814 | } |
6649a3ca | 815 | else |
7051ef40 | 816 | { |
6649a3ca | 817 | printf("%-7s ", "expired"); |
7051ef40 | 818 | } |
7daf5226 | 819 | |
d25ce370 | 820 | printf(" %T ", &acquired, utc); |
6649a3ca | 821 | if (released) |
7051ef40 | 822 | { |
d25ce370 | 823 | printf("%T ", &released, utc); |
7051ef40 MW |
824 | } |
825 | else | |
826 | { | |
6649a3ca MW |
827 | printf(" "); |
828 | if (utc) | |
829 | { | |
830 | printf(" "); | |
831 | } | |
7051ef40 | 832 | } |
d24a74c5 | 833 | printf("%Y\n", identity); |
53027034 MW |
834 | DESTROY_IF(address); |
835 | identity->destroy(identity); | |
836 | } | |
837 | query->destroy(query); | |
8c33a189 TB |
838 | if (to_free) |
839 | { | |
840 | array_destroy_function(to_free, (void*)free, NULL); | |
841 | } | |
53027034 MW |
842 | if (!found) |
843 | { | |
844 | fprintf(stderr, "no matching leases found.\n"); | |
a90ed06f | 845 | exit(EXIT_FAILURE); |
53027034 | 846 | } |
53027034 MW |
847 | } |
848 | ||
7051ef40 MW |
849 | /** |
850 | * ipsec pool --purge - delete expired leases | |
851 | */ | |
852 | static void purge(char *name) | |
853 | { | |
f7198e7e | 854 | int purged = 0; |
7daf5226 | 855 | |
f7198e7e MW |
856 | purged = db->execute(db, NULL, |
857 | "DELETE FROM leases WHERE address IN (" | |
858 | " SELECT id FROM addresses WHERE pool IN (" | |
859 | " SELECT id FROM pools WHERE name = ?))", | |
860 | DB_TEXT, name); | |
861 | if (purged < 0) | |
7051ef40 | 862 | { |
f7198e7e | 863 | fprintf(stderr, "purging pool '%s' failed.\n", name); |
a90ed06f | 864 | exit(EXIT_FAILURE); |
7051ef40 | 865 | } |
7051ef40 | 866 | fprintf(stderr, "purged %d leases in pool '%s'.\n", purged, name); |
7051ef40 | 867 | } |
f3e11fc4 | 868 | |
437690f8 HH |
869 | #define ARGV_SIZE 32 |
870 | ||
871 | static void argv_add(char **argv, int argc, char *value) | |
872 | { | |
873 | if (argc >= ARGV_SIZE) | |
874 | { | |
875 | fprintf(stderr, "too many arguments: %s\n", value); | |
876 | exit(EXIT_FAILURE); | |
877 | } | |
878 | argv[argc] = value; | |
879 | } | |
880 | ||
881 | /** | |
882 | * ipsec pool --batch - read commands from a file | |
883 | */ | |
884 | static void batch(char *argv0, char *name) | |
885 | { | |
886 | char command[512]; | |
887 | ||
888 | FILE *file = strncmp(name, "-", 1) == 0 ? stdin : fopen(name, "r"); | |
889 | if (file == NULL) | |
890 | { | |
891 | fprintf(stderr, "opening '%s' failed: %s\n", name, strerror(errno)); | |
892 | exit(EXIT_FAILURE); | |
893 | } | |
894 | ||
b283a6e9 | 895 | db->transaction(db, FALSE); |
437690f8 HH |
896 | while (fgets(command, sizeof(command), file)) |
897 | { | |
898 | char *argv[ARGV_SIZE], *start; | |
899 | int i, argc = 0; | |
900 | size_t cmd_len = strlen(command); | |
901 | ||
902 | /* ignore empty lines */ | |
903 | if (cmd_len == 1 && *(command + cmd_len - 1) == '\n') | |
904 | { | |
905 | continue; | |
906 | } | |
907 | ||
908 | /* parse command into argv */ | |
909 | start = command; | |
910 | argv_add(argv, argc++, argv0); | |
911 | for (i = 0; i < cmd_len; ++i) | |
912 | { | |
913 | if (command[i] == ' ' || command[i] == '\n') | |
914 | { | |
915 | if (command + i == start) | |
916 | { | |
917 | /* ignore leading whitespace */ | |
918 | ++start; | |
919 | continue; | |
920 | } | |
921 | command[i] = '\0'; | |
922 | argv_add(argv, argc++, start); | |
923 | start = command + i + 1; | |
924 | } | |
925 | } | |
926 | if (strlen(start) > 0) | |
927 | { | |
928 | argv_add(argv, argc++, start); | |
929 | } | |
930 | argv_add(argv, argc, NULL); | |
931 | ||
932 | do_args(argc, argv); | |
933 | } | |
03c801cb | 934 | db->commit(db); |
437690f8 HH |
935 | |
936 | if (file != stdin) | |
937 | { | |
938 | fclose(file); | |
939 | } | |
940 | } | |
941 | ||
53027034 MW |
942 | /** |
943 | * atexit handler to close db on shutdown | |
944 | */ | |
7051ef40 | 945 | static void cleanup(void) |
53027034 MW |
946 | { |
947 | db->destroy(db); | |
b7019a5c TB |
948 | DESTROY_IF(start_addr); |
949 | DESTROY_IF(end_addr); | |
53027034 MW |
950 | } |
951 | ||
437690f8 | 952 | static void do_args(int argc, char *argv[]) |
53027034 | 953 | { |
ec7adea0 HH |
954 | char *name = "", *value = "", *filter = ""; |
955 | char *pool = NULL, *identity = NULL, *addresses = NULL; | |
ad6dbc41 | 956 | value_type_t value_type = VALUE_NONE; |
bf23ca09 | 957 | time_t timeout = 0; |
616b13c7 | 958 | bool utc = FALSE, hexout = FALSE; |
ad6dbc41 | 959 | |
53027034 | 960 | enum { |
a90ed06f | 961 | OP_UNDEF, |
53027034 MW |
962 | OP_USAGE, |
963 | OP_STATUS, | |
ad6dbc41 | 964 | OP_STATUS_ATTR, |
53027034 | 965 | OP_ADD, |
645f3865 | 966 | OP_ADD_ATTR, |
53027034 | 967 | OP_DEL, |
645f3865 | 968 | OP_DEL_ATTR, |
c2d10df6 | 969 | OP_SHOW_ATTR, |
53027034 MW |
970 | OP_RESIZE, |
971 | OP_LEASES, | |
437690f8 HH |
972 | OP_PURGE, |
973 | OP_BATCH | |
a90ed06f | 974 | } operation = OP_UNDEF; |
53027034 | 975 | |
0d59713d HH |
976 | /* reinit getopt state */ |
977 | optind = 0; | |
7daf5226 | 978 | |
53027034 MW |
979 | while (TRUE) |
980 | { | |
981 | int c; | |
7daf5226 | 982 | |
53027034 MW |
983 | struct option long_opts[] = { |
984 | { "help", no_argument, NULL, 'h' }, | |
7daf5226 | 985 | |
c7d81ad1 | 986 | { "utc", no_argument, NULL, 'u' }, |
53027034 MW |
987 | { "status", no_argument, NULL, 'w' }, |
988 | { "add", required_argument, NULL, 'a' }, | |
ef9f69a2 | 989 | { "replace", required_argument, NULL, 'c' }, |
53027034 MW |
990 | { "del", required_argument, NULL, 'd' }, |
991 | { "resize", required_argument, NULL, 'r' }, | |
4fa74562 | 992 | { "leases", no_argument, NULL, 'l' }, |
7051ef40 | 993 | { "purge", required_argument, NULL, 'p' }, |
ad6dbc41 AS |
994 | { "statusattr", no_argument, NULL, '1' }, |
995 | { "addattr", required_argument, NULL, '2' }, | |
996 | { "delattr", required_argument, NULL, '3' }, | |
c2d10df6 | 997 | { "showattr", no_argument, NULL, '4' }, |
437690f8 | 998 | { "batch", required_argument, NULL, 'b' }, |
7daf5226 | 999 | |
53027034 MW |
1000 | { "start", required_argument, NULL, 's' }, |
1001 | { "end", required_argument, NULL, 'e' }, | |
ad6dbc41 | 1002 | { "addresses", required_argument, NULL, 'y' }, |
53027034 MW |
1003 | { "timeout", required_argument, NULL, 't' }, |
1004 | { "filter", required_argument, NULL, 'f' }, | |
616b13c7 AS |
1005 | { "addr", required_argument, NULL, 'v' }, |
1006 | { "mask", required_argument, NULL, 'v' }, | |
645f3865 | 1007 | { "server", required_argument, NULL, 'v' }, |
ad6dbc41 AS |
1008 | { "subnet", required_argument, NULL, 'n' }, |
1009 | { "string", required_argument, NULL, 'g' }, | |
1010 | { "hex", required_argument, NULL, 'x' }, | |
616b13c7 | 1011 | { "hexout", no_argument, NULL, '5' }, |
ec7adea0 HH |
1012 | { "pool", required_argument, NULL, '6' }, |
1013 | { "identity", required_argument, NULL, '7' }, | |
53027034 MW |
1014 | { 0,0,0,0 } |
1015 | }; | |
7daf5226 | 1016 | |
53027034 MW |
1017 | c = getopt_long(argc, argv, "", long_opts, NULL); |
1018 | switch (c) | |
1019 | { | |
1020 | case EOF: | |
8fb4edc4 | 1021 | break; |
53027034 | 1022 | case 'h': |
a90ed06f | 1023 | operation = OP_USAGE; |
53027034 MW |
1024 | break; |
1025 | case 'w': | |
1026 | operation = OP_STATUS; | |
1027 | break; | |
ad6dbc41 AS |
1028 | case '1': |
1029 | operation = OP_STATUS_ATTR; | |
119fc2d3 | 1030 | break; |
6649a3ca MW |
1031 | case 'u': |
1032 | utc = TRUE; | |
1033 | continue; | |
ef9f69a2 HH |
1034 | case 'c': |
1035 | replace_pool = TRUE; | |
1036 | /* fallthrough */ | |
53027034 | 1037 | case 'a': |
53027034 | 1038 | name = optarg; |
645f3865 | 1039 | operation = is_attribute(name) ? OP_ADD_ATTR : OP_ADD; |
ef9f69a2 HH |
1040 | if (replace_pool && operation == OP_ADD_ATTR) |
1041 | { | |
ad6dbc41 AS |
1042 | fprintf(stderr, "invalid pool name: " |
1043 | "reserved for '%s' attribute.\n", optarg); | |
a90ed06f HH |
1044 | usage(); |
1045 | exit(EXIT_FAILURE); | |
ef9f69a2 | 1046 | } |
53027034 | 1047 | continue; |
ad6dbc41 AS |
1048 | case '2': |
1049 | name = optarg; | |
1050 | operation = OP_ADD_ATTR; | |
1051 | continue; | |
53027034 | 1052 | case 'd': |
53027034 | 1053 | name = optarg; |
645f3865 | 1054 | operation = is_attribute(name) ? OP_DEL_ATTR : OP_DEL; |
53027034 | 1055 | continue; |
ad6dbc41 AS |
1056 | case '3': |
1057 | name = optarg; | |
1058 | operation = OP_DEL_ATTR; | |
1059 | continue; | |
c2d10df6 AS |
1060 | case '4': |
1061 | operation = OP_SHOW_ATTR; | |
1062 | continue; | |
53027034 | 1063 | case 'r': |
53027034 | 1064 | name = optarg; |
645f3865 | 1065 | operation = OP_RESIZE; |
53027034 MW |
1066 | continue; |
1067 | case 'l': | |
1068 | operation = OP_LEASES; | |
53027034 | 1069 | continue; |
7051ef40 | 1070 | case 'p': |
7051ef40 | 1071 | name = optarg; |
645f3865 | 1072 | operation = OP_PURGE; |
7051ef40 | 1073 | continue; |
437690f8 HH |
1074 | case 'b': |
1075 | name = optarg; | |
1076 | if (operation == OP_BATCH) | |
1077 | { | |
1078 | fprintf(stderr, "--batch commands can not be nested\n"); | |
1079 | exit(EXIT_FAILURE); | |
1080 | } | |
1081 | operation = OP_BATCH; | |
1082 | continue; | |
53027034 | 1083 | case 's': |
b7019a5c TB |
1084 | DESTROY_IF(start_addr); |
1085 | start_addr = host_create_from_string(optarg, 0); | |
1086 | if (!start_addr) | |
53027034 MW |
1087 | { |
1088 | fprintf(stderr, "invalid start address: '%s'.\n", optarg); | |
a90ed06f HH |
1089 | usage(); |
1090 | exit(EXIT_FAILURE); | |
53027034 MW |
1091 | } |
1092 | continue; | |
1093 | case 'e': | |
b7019a5c TB |
1094 | DESTROY_IF(end_addr); |
1095 | end_addr = host_create_from_string(optarg, 0); | |
1096 | if (!end_addr) | |
53027034 MW |
1097 | { |
1098 | fprintf(stderr, "invalid end address: '%s'.\n", optarg); | |
a90ed06f HH |
1099 | usage(); |
1100 | exit(EXIT_FAILURE); | |
53027034 MW |
1101 | } |
1102 | continue; | |
1103 | case 't': | |
bf23ca09 | 1104 | if (!timespan_from_string(optarg, "h", &timeout)) |
53027034 MW |
1105 | { |
1106 | fprintf(stderr, "invalid timeout '%s'.\n", optarg); | |
a90ed06f HH |
1107 | usage(); |
1108 | exit(EXIT_FAILURE); | |
53027034 MW |
1109 | } |
1110 | continue; | |
1111 | case 'f': | |
1112 | filter = optarg; | |
1113 | continue; | |
ad6dbc41 | 1114 | case 'y': |
49a452e3 HH |
1115 | addresses = optarg; |
1116 | continue; | |
ad6dbc41 AS |
1117 | case 'g': |
1118 | value_type = VALUE_STRING; | |
1119 | value = optarg; | |
1120 | continue; | |
1121 | case 'n': | |
1122 | value_type = VALUE_SUBNET; | |
1123 | value = optarg; | |
1124 | continue; | |
645f3865 | 1125 | case 'v': |
ad6dbc41 AS |
1126 | value_type = VALUE_ADDR; |
1127 | value = optarg; | |
1128 | continue; | |
1129 | case 'x': | |
1130 | value_type = VALUE_HEX; | |
1131 | value = optarg; | |
645f3865 | 1132 | continue; |
616b13c7 AS |
1133 | case '5': |
1134 | hexout = TRUE; | |
1135 | continue; | |
ec7adea0 HH |
1136 | case '6': |
1137 | pool = optarg; | |
1138 | continue; | |
1139 | case '7': | |
1140 | identity = optarg; | |
1141 | continue; | |
53027034 | 1142 | default: |
a90ed06f HH |
1143 | usage(); |
1144 | exit(EXIT_FAILURE); | |
53027034 MW |
1145 | } |
1146 | break; | |
1147 | } | |
7daf5226 | 1148 | |
53027034 MW |
1149 | switch (operation) |
1150 | { | |
1151 | case OP_USAGE: | |
1152 | usage(); | |
1153 | break; | |
1154 | case OP_STATUS: | |
1155 | status(); | |
1156 | break; | |
ad6dbc41 | 1157 | case OP_STATUS_ATTR: |
616b13c7 | 1158 | status_attr(hexout); |
ad6dbc41 | 1159 | break; |
53027034 | 1160 | case OP_ADD: |
49a452e3 HH |
1161 | if (addresses != NULL) |
1162 | { | |
1163 | add_addresses(name, addresses, timeout); | |
1164 | } | |
b7019a5c | 1165 | else if (start_addr && end_addr) |
49a452e3 | 1166 | { |
b7019a5c | 1167 | add(name, start_addr, end_addr, timeout); |
49a452e3 HH |
1168 | } |
1169 | else | |
53027034 MW |
1170 | { |
1171 | fprintf(stderr, "missing arguments.\n"); | |
1172 | usage(); | |
a90ed06f | 1173 | exit(EXIT_FAILURE); |
53027034 | 1174 | } |
53027034 | 1175 | break; |
645f3865 | 1176 | case OP_ADD_ATTR: |
ad6dbc41 | 1177 | if (value_type == VALUE_NONE) |
645f3865 AS |
1178 | { |
1179 | fprintf(stderr, "missing arguments.\n"); | |
1180 | usage(); | |
a90ed06f | 1181 | exit(EXIT_FAILURE); |
645f3865 | 1182 | } |
ec7adea0 HH |
1183 | if (identity && !pool) |
1184 | { | |
1185 | fprintf(stderr, "--identity option can't be used without --pool.\n"); | |
1186 | usage(); | |
1187 | exit(EXIT_FAILURE); | |
1188 | } | |
1189 | add_attr(name, pool, identity, value, value_type); | |
645f3865 | 1190 | break; |
53027034 MW |
1191 | case OP_DEL: |
1192 | del(name); | |
1193 | break; | |
645f3865 | 1194 | case OP_DEL_ATTR: |
ec7adea0 HH |
1195 | if (identity && !pool) |
1196 | { | |
1197 | fprintf(stderr, "--identity option can't be used without --pool.\n"); | |
1198 | usage(); | |
1199 | exit(EXIT_FAILURE); | |
1200 | } | |
1201 | del_attr(name, pool, identity, value, value_type); | |
645f3865 | 1202 | break; |
c2d10df6 AS |
1203 | case OP_SHOW_ATTR: |
1204 | show_attr(); | |
1205 | break; | |
53027034 | 1206 | case OP_RESIZE: |
b7019a5c | 1207 | if (!end_addr) |
53027034 MW |
1208 | { |
1209 | fprintf(stderr, "missing arguments.\n"); | |
1210 | usage(); | |
a90ed06f | 1211 | exit(EXIT_FAILURE); |
53027034 | 1212 | } |
b7019a5c | 1213 | resize(name, end_addr); |
53027034 MW |
1214 | break; |
1215 | case OP_LEASES: | |
4fa74562 | 1216 | leases(filter, utc); |
53027034 | 1217 | break; |
7051ef40 MW |
1218 | case OP_PURGE: |
1219 | purge(name); | |
1220 | break; | |
437690f8 HH |
1221 | case OP_BATCH: |
1222 | if (name == NULL) | |
1223 | { | |
1224 | fprintf(stderr, "missing arguments.\n"); | |
1225 | usage(); | |
1226 | exit(EXIT_FAILURE); | |
1227 | } | |
1228 | batch(argv[0], name); | |
1229 | break; | |
a90ed06f HH |
1230 | default: |
1231 | usage(); | |
1232 | exit(EXIT_FAILURE); | |
53027034 | 1233 | } |
437690f8 HH |
1234 | } |
1235 | ||
1236 | int main(int argc, char *argv[]) | |
1237 | { | |
1238 | char *uri; | |
1239 | ||
1240 | atexit(library_deinit); | |
1241 | ||
1242 | /* initialize library */ | |
34d3bfcf | 1243 | if (!library_init(NULL, "pool")) |
437690f8 HH |
1244 | { |
1245 | exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); | |
1246 | } | |
1247 | if (lib->integrity && | |
1248 | !lib->integrity->check_file(lib->integrity, "pool", argv[0])) | |
1249 | { | |
1250 | fprintf(stderr, "integrity check of pool failed\n"); | |
1251 | exit(SS_RC_DAEMON_INTEGRITY); | |
1252 | } | |
b18a5317 | 1253 | if (!lib->plugins->load(lib->plugins, |
437690f8 HH |
1254 | lib->settings->get_str(lib->settings, "pool.load", PLUGINS))) |
1255 | { | |
1256 | exit(SS_RC_INITIALIZATION_FAILED); | |
1257 | } | |
eb9b375a TB |
1258 | /* TODO: make database URI or setting key configurable via command line */ |
1259 | uri = lib->settings->get_str(lib->settings, | |
1260 | "pool.database", | |
1261 | lib->settings->get_str(lib->settings, | |
1262 | "charon.plugins.attr-sql.database", | |
1263 | lib->settings->get_str(lib->settings, | |
1264 | "libhydra.plugins.attr-sql.database", NULL))); | |
437690f8 HH |
1265 | if (!uri) |
1266 | { | |
eb9b375a | 1267 | fprintf(stderr, "database URI pool.database not set.\n"); |
437690f8 HH |
1268 | exit(SS_RC_INITIALIZATION_FAILED); |
1269 | } | |
1270 | db = lib->db->create(lib->db, uri); | |
1271 | if (!db) | |
1272 | { | |
1273 | fprintf(stderr, "opening database failed.\n"); | |
1274 | exit(SS_RC_INITIALIZATION_FAILED); | |
1275 | } | |
1276 | atexit(cleanup); | |
1277 | ||
1278 | do_args(argc, argv); | |
1279 | ||
a90ed06f | 1280 | exit(EXIT_SUCCESS); |
53027034 | 1281 | } |