~ubuntu-branches/ubuntu/maverick/strongswan/maverick

« back to all changes in this revision

Viewing changes to src/charon/plugins/sql/pool.c

  • Committer: Bazaar Package Importer
  • Author(s): Rene Mayrhofer
  • Date: 2008-12-05 17:21:42 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20081205172142-9g77wgyzcj0blq7p
* New upstream release, fixes a MOBIKE issue.
  Closes: #507542: strongswan: endless loop
* Explicitly enable compilation with libcurl for CRL fetching
  Closes: #497756: strongswan: not compiled with curl support; crl 
                   fetching not available
* Enable compilation with SSH agent support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
host_t *start = NULL, *end = NULL;
37
37
 
38
38
/**
39
 
 * create a host from a blob
40
 
 */
41
 
static host_t *host_create_from_blob(chunk_t blob)
42
 
{
43
 
        return host_create_from_chunk(blob.len == 4 ? AF_INET : AF_INET6, blob, 0);
44
 
}
45
 
 
46
 
/**
47
39
 * calculate the size of a pool using start and end address chunk
48
40
 */
49
41
static u_int get_pool_size(chunk_t start, chunk_t end)
87
79
      name:   Name of the pool to resize\n\
88
80
      end:    New end address for the pool\n\
89
81
  \n\
90
 
  ipsec pool --leases <name> [--filter <filter>] [--utc]\n\
 
82
  ipsec pool --leases [--filter <filter>] [--utc]\n\
91
83
    Show lease information using filters:\n\
92
 
      name:   Name of the pool to show leases from\n\
93
84
      filter: Filter string containing comma separated key=value filters,\n\
94
85
              e.g. id=alice@strongswan.org,addr=1.1.1.1\n\
95
86
                  pool:   name of the pool\n\
100
91
      utc:    Show times in UTC instead of local time\n\
101
92
  \n\
102
93
  ipsec pool --purge <name>\n\
103
 
    Delete expired leases of a pool:\n\
 
94
    Delete lease history of a pool:\n\
104
95
      name:   Name of the pool to purge\n\
105
96
  \n");
106
97
        exit(0);
128
119
                {
129
120
                        if (!found)
130
121
                        {
131
 
                                printf("%8s %15s %15s %8s %6s %11s %11s\n",
132
 
                                           "name", "start", "end", "timeout", "size", "online", "leases");
 
122
                                printf("%8s %15s %15s %8s %6s %11s %11s\n", "name", "start",
 
123
                                           "end", "timeout", "size", "online", "usage");
133
124
                                found = TRUE;
134
125
                        }
135
126
                        
136
 
                        start = host_create_from_blob(start_chunk);
137
 
                        end = host_create_from_blob(end_chunk);
 
127
                        start = host_create_from_chunk(AF_UNSPEC, start_chunk, 0);
 
128
                        end = host_create_from_chunk(AF_UNSPEC, end_chunk, 0);
138
129
                        size = get_pool_size(start_chunk, end_chunk);
139
130
                        printf("%8s %15H %15H ", name, start, end);
140
131
                        if (timeout)
147
138
                        }
148
139
                        printf("%6d ", size);
149
140
                        /* get number of online hosts */
150
 
                        lease = db->query(db, "SELECT COUNT(*) FROM leases "
151
 
                                                          "WHERE pool = ? AND released IS NULL",
 
141
                        lease = db->query(db, "SELECT COUNT(*) FROM addresses "
 
142
                                                          "WHERE pool = ? AND released = 0",
152
143
                                                          DB_UINT, id, DB_INT);
153
144
                        if (lease)
154
145
                        {
157
148
                        }
158
149
                        printf("%5d (%2d%%) ", online, online*100/size);
159
150
                        /* get number of online or valid lieases */
160
 
                        lease = db->query(db, "SELECT COUNT(*) FROM leases JOIN pools "
161
 
                                                          "ON leases.pool = pools.id "
162
 
                                                          "WHERE pools.id = ? "
163
 
                                                          "AND (released IS NULL OR released > ? - timeout) ",
164
 
                                                          DB_UINT, id, DB_UINT, time(NULL), DB_UINT);
 
151
                        lease = db->query(db, "SELECT COUNT(*) FROM addresses "
 
152
                                                          "WHERE addresses.pool = ? "
 
153
                                                          "AND ((? AND acquired != 0) "
 
154
                                                          "     OR released = 0 OR released > ?) ",
 
155
                                                          DB_UINT, id, DB_UINT, !timeout,
 
156
                                                          DB_UINT, time(NULL) - timeout, DB_UINT);
165
157
                        if (lease)
166
158
                        {
167
159
                                lease->enumerate(lease, &used);
183
175
}
184
176
 
185
177
/**
 
178
 * increment a chunk, as it would reprensent a network order integer
 
179
 */
 
180
static void increment_chunk(chunk_t chunk)
 
181
{
 
182
        int i;
 
183
        
 
184
        for (i = chunk.len - 1; i >= 0; i--)
 
185
        {
 
186
                if (++chunk.ptr[i] != 0)
 
187
                {
 
188
                        return;
 
189
                }
 
190
        }
 
191
}
 
192
 
 
193
/**
186
194
 * ipsec pool --add - add a new pool
187
195
 */
188
196
static void add(char *name, host_t *start, host_t *end, int timeout)
189
197
{
190
 
        chunk_t start_addr, end_addr;
 
198
        chunk_t start_addr, end_addr, cur_addr;
 
199
        u_int id, count;
191
200
        
192
201
        start_addr = start->get_address(start);
193
202
        end_addr = end->get_address(end);
 
203
        cur_addr = chunk_clonea(start_addr);
 
204
        count = get_pool_size(start_addr, end_addr);
194
205
 
195
206
        if (start_addr.len != end_addr.len ||
196
207
                memcmp(start_addr.ptr, end_addr.ptr, start_addr.len) > 0)
198
209
                fprintf(stderr, "invalid start/end pair specified.\n");
199
210
                exit(-1);
200
211
        }
201
 
        if (db->execute(db, NULL,
202
 
                        "INSERT INTO pools (name, start, end, next, timeout) "
203
 
                        "VALUES (?, ?, ?, ?, ?)",
 
212
        if (db->execute(db, &id,
 
213
                        "INSERT INTO pools (name, start, end, timeout) "
 
214
                        "VALUES (?, ?, ?, ?)",
204
215
                        DB_TEXT, name, DB_BLOB, start_addr,
205
 
                        DB_BLOB, end_addr, DB_BLOB, start_addr,
206
 
                        DB_INT, timeout*3600) != 1)
 
216
                        DB_BLOB, end_addr, DB_INT, timeout*3600) != 1)
207
217
        {
208
218
                fprintf(stderr, "creating pool failed.\n");
209
219
                exit(-1);
210
220
        }
 
221
        printf("allocating %d addresses... ", count);
 
222
        fflush(stdout);
 
223
        if (db->get_driver(db) == DB_SQLITE)
 
224
        {       /* run population in a transaction for sqlite */
 
225
                db->execute(db, NULL, "BEGIN TRANSACTION");
 
226
        }
 
227
        while (TRUE)
 
228
        {
 
229
                db->execute(db, NULL,
 
230
                        "INSERT INTO addresses (pool, address, identity, acquired, released) "
 
231
                        "VALUES (?, ?, ?, ?, ?)",
 
232
                        DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
 
233
                if (chunk_equals(cur_addr, end_addr))
 
234
                {
 
235
                        break;
 
236
                }
 
237
                increment_chunk(cur_addr);
 
238
        }
 
239
        if (db->get_driver(db) == DB_SQLITE)
 
240
        {
 
241
                db->execute(db, NULL, "END TRANSACTION");
 
242
        }
 
243
        printf("done.\n", count);
 
244
        
211
245
        exit(0);
212
246
}
213
247
 
231
265
        {
232
266
                found = TRUE;
233
267
                if (db->execute(db, NULL,
234
 
                                "DELETE FROM pools WHERE id = ?", DB_UINT, id) != 1 ||
235
 
                        db->execute(db, NULL,
236
 
                                "DELETE FROM leases WHERE pool = ?", DB_UINT, id) < 0)
 
268
                                "DELETE FROM leases WHERE address IN ("
 
269
                                " SELECT id FROM addresses WHERE pool = ?)", DB_UINT, id) < 0 ||
 
270
                        db->execute(db, NULL,
 
271
                                "DELETE FROM addresses WHERE pool = ?", DB_UINT, id) < 0 ||
 
272
                        db->execute(db, NULL,
 
273
                                "DELETE FROM pools WHERE id = ?", DB_UINT, id) < 0)
237
274
                {
238
275
                        fprintf(stderr, "deleting pool failed.\n");
239
276
                        query->destroy(query);
255
292
static void resize(char *name, host_t *end)
256
293
{
257
294
        enumerator_t *query;
258
 
        chunk_t next_addr, end_addr;
259
 
        
260
 
        end_addr = end->get_address(end);
261
 
        
262
 
        query = db->query(db, "SELECT next FROM pools WHERE name = ?",
263
 
                                          DB_TEXT, name, DB_BLOB);
264
 
        if (!query || !query->enumerate(query, &next_addr))
 
295
        chunk_t old_addr, new_addr, cur_addr;
 
296
        u_int id, count;
 
297
        
 
298
        new_addr = end->get_address(end);
 
299
        
 
300
        query = db->query(db, "SELECT id, end FROM pools WHERE name = ?",
 
301
                                          DB_TEXT, name, DB_UINT, DB_BLOB);
 
302
        if (!query || !query->enumerate(query, &id, &old_addr))
265
303
        {
266
304
                DESTROY_IF(query);
267
305
                fprintf(stderr, "resizing pool failed.\n");
268
306
                exit(-1);
269
307
        }
270
 
        if (next_addr.len != end_addr.len ||
271
 
                memcmp(end_addr.ptr, next_addr.ptr, end_addr.len) < 0)
 
308
        if (old_addr.len != new_addr.len ||
 
309
                memcmp(new_addr.ptr, old_addr.ptr, old_addr.len) < 0)
272
310
        {
273
 
                end = host_create_from_blob(next_addr);
274
 
                fprintf(stderr, "pool addresses up to %H in use, resizing failed.\n", end);
275
 
                end->destroy(end);
 
311
                fprintf(stderr, "shrinking of pools not supported.\n");
276
312
                query->destroy(query);
277
313
                exit(-1);
278
314
        }
 
315
        cur_addr = chunk_clonea(old_addr);
 
316
        count = get_pool_size(old_addr, new_addr) - 1;
279
317
        query->destroy(query);
280
318
 
281
319
        if (db->execute(db, NULL,
282
320
                        "UPDATE pools SET end = ? WHERE name = ?",
283
 
                        DB_BLOB, end_addr, DB_TEXT, name) <= 0)
 
321
                        DB_BLOB, new_addr, DB_TEXT, name) <= 0)
284
322
        {
285
323
                fprintf(stderr, "pool '%s' not found.\n", name);
286
324
                exit(-1);
287
325
        }
 
326
        
 
327
        printf("allocating %d new addresses... ", count);
 
328
        fflush(stdout);
 
329
        if (db->get_driver(db) == DB_SQLITE)
 
330
        {       /* run population in a transaction for sqlite */
 
331
                db->execute(db, NULL, "BEGIN TRANSACTION");
 
332
        }
 
333
        while (count-- > 0)
 
334
        {
 
335
                increment_chunk(cur_addr);
 
336
                db->execute(db, NULL,
 
337
                        "INSERT INTO addresses (pool, address, identity, acquired, released) "
 
338
                        "VALUES (?, ?, ?, ?, ?)",
 
339
                        DB_UINT, id, DB_BLOB, cur_addr, DB_UINT, 0, DB_UINT, 0, DB_UINT, 1);
 
340
        }
 
341
        if (db->get_driver(db) == DB_SQLITE)
 
342
        {
 
343
                db->execute(db, NULL, "END TRANSACTION");
 
344
        }
 
345
        printf("done.\n", count);
 
346
        
288
347
        exit(0);
289
348
}
290
349
 
398
457
                }
399
458
        }
400
459
        query = db->query(db,
401
 
                                "SELECT name, address, identities.type, "
402
 
                                "identities.data, acquired, released, timeout "
403
 
                                "FROM leases JOIN pools ON leases.pool = pools.id "
 
460
                                "SELECT name, addresses.address, identities.type, "
 
461
                                "identities.data, leases.acquired, leases.released, timeout "
 
462
                                "FROM leases JOIN addresses ON leases.address = addresses.id "
 
463
                                "JOIN pools ON addresses.pool = pools.id "
404
464
                                "JOIN identities ON leases.identity = identities.id "
405
465
                                "WHERE (? OR name = ?) "
406
466
                                "AND (? OR (identities.type = ? AND identities.data = ?)) "
407
 
                                "AND (? OR address = ?) "
408
 
                                "AND (? OR (? >= acquired AND (? <= released OR released IS NULL))) "
409
 
                                "AND (? OR released IS NULL) "
410
 
                                "AND (? OR released > ? - timeout) "
411
 
                                "AND (? OR released < ? - timeout)",
 
467
                                "AND (? OR addresses.address = ?) "
 
468
                                "AND (? OR (? >= leases.acquired AND (? <= leases.released))) "
 
469
                                "AND (? OR leases.released > ? - timeout) "
 
470
                                "AND (? OR leases.released < ? - timeout) "
 
471
                                "AND ? "
 
472
                                "UNION "
 
473
                                "SELECT name, address, identities.type, identities.data, "
 
474
                                "acquired, released, timeout FROM addresses "
 
475
                                "JOIN pools ON addresses.pool = pools.id "
 
476
                                "JOIN identities ON addresses.identity = identities.id "
 
477
                                "WHERE ? AND released = 0 "
 
478
                                "AND (? OR name = ?) "
 
479
                                "AND (? OR (identities.type = ? AND identities.data = ?)) "
 
480
                                "AND (? OR address = ?)",
412
481
                                DB_INT, pool == NULL, DB_TEXT, pool,
413
482
                                DB_INT, id == NULL,
414
483
                                        DB_INT, id ? id->get_type(id) : 0,
416
485
                                DB_INT, addr == NULL,
417
486
                                        DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
418
487
                                DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp,
419
 
                                DB_INT, !online,
420
488
                                DB_INT, !valid, DB_INT, time(NULL),
421
489
                                DB_INT, !expired, DB_INT, time(NULL),
 
490
                                DB_INT, !online,
 
491
                                /* union */
 
492
                                DB_INT, !(valid || expired),
 
493
                                DB_INT, pool == NULL, DB_TEXT, pool,
 
494
                                DB_INT, id == NULL,
 
495
                                        DB_INT, id ? id->get_type(id) : 0,
 
496
                                        DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
 
497
                                DB_INT, addr == NULL,
 
498
                                        DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
 
499
                                /* res */
422
500
                                DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT);
423
501
        /* id and addr leak but we can't destroy them until query is destroyed. */
424
502
        return query;
455
533
                        printf("%-8s %-15s %-7s  %-*s %-*s %s\n",
456
534
                                   "name", "address", "status", len, "start", len, "end", "identity");
457
535
                }
458
 
                address = host_create_from_blob(address_chunk);
 
536
                address = host_create_from_chunk(AF_UNSPEC, address_chunk, 0);
459
537
                identity = identification_create_from_encoding(identity_type, identity_chunk);
460
538
                
461
539
                printf("%-8s %-15H ", name, address);
507
585
 */
508
586
static void purge(char *name)
509
587
{
510
 
        enumerator_t *query;
511
 
        u_int id, timeout, purged = 0;
 
588
        int purged = 0;
512
589
        
513
 
        query = db->query(db, "SELECT id, timeout FROM pools WHERE name = ?",
514
 
                                          DB_TEXT, name, DB_UINT, DB_UINT);
515
 
        if (!query)
 
590
        purged = db->execute(db, NULL,
 
591
                                "DELETE FROM leases WHERE address IN ("
 
592
                                " SELECT id FROM addresses WHERE pool IN ("
 
593
                                "  SELECT id FROM pools WHERE name = ?))",
 
594
                                DB_TEXT, name);
 
595
        if (purged < 0)
516
596
        {
517
 
                fprintf(stderr, "purging pool failed.\n");
 
597
                fprintf(stderr, "purging pool '%s' failed.\n", name);
518
598
                exit(-1);
519
599
        }
520
 
        /* we have to keep one lease if we purge. It wouldn't be reallocateable
521
 
         * as we move on the "next" address for speedy allocation */
522
 
        if (query->enumerate(query, &id, &timeout))
523
 
        {
524
 
                timeout = time(NULL) - timeout;
525
 
                purged = db->execute(db, NULL,
526
 
                                        "DELETE FROM leases WHERE pool = ? "
527
 
                                        "AND released IS NOT NULL AND released < ? AND id NOT IN ("
528
 
                                        " SELECT id FROM leases "
529
 
                                        " WHERE released IS NOT NULL and released < ? "
530
 
                                        " GROUP BY address)",
531
 
                                        DB_UINT, id, DB_UINT, timeout, DB_UINT, timeout);
532
 
        }
533
 
        query->destroy(query);
534
600
        fprintf(stderr, "purged %d leases in pool '%s'.\n", purged, name);
535
601
        exit(0);
536
602
}