~ubuntu-branches/ubuntu/oneiric/isc-dhcp/oneiric-security

« back to all changes in this revision

Viewing changes to server/db.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Pollock
  • Date: 2009-09-02 22:34:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090902223425-nypo7bkftxffq41m
Tags: upstream-4.1.0
ImportĀ upstreamĀ versionĀ 4.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* db.c
 
2
 
 
3
   Persistent database management routines for DHCPD... */
 
4
 
 
5
/*
 
6
 * Copyright (c) 2004-2008 by Internet Systems Consortium, Inc. ("ISC")
 
7
 * Copyright (c) 1995-2003 by Internet Software Consortium
 
8
 *
 
9
 * Permission to use, copy, modify, and distribute this software for any
 
10
 * purpose with or without fee is hereby granted, provided that the above
 
11
 * copyright notice and this permission notice appear in all copies.
 
12
 *
 
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 
15
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 
19
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
20
 *
 
21
 *   Internet Systems Consortium, Inc.
 
22
 *   950 Charter Street
 
23
 *   Redwood City, CA 94063
 
24
 *   <info@isc.org>
 
25
 *   http://www.isc.org/
 
26
 *
 
27
 * This software has been written for Internet Systems Consortium
 
28
 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
 
29
 * To learn more about Internet Systems Consortium, see
 
30
 * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
 
31
 * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
 
32
 * ``http://www.nominum.com''.
 
33
 */
 
34
 
 
35
#include "dhcpd.h"
 
36
#include <ctype.h>
 
37
#include <errno.h>
 
38
 
 
39
static isc_result_t write_binding_scope(FILE *db_file, struct binding *bnd,
 
40
                                        char *prepend);
 
41
 
 
42
FILE *db_file;
 
43
 
 
44
static int counting = 0;
 
45
static int count = 0;
 
46
TIME write_time;
 
47
int lease_file_is_corrupt = 0;
 
48
 
 
49
/* Write a single binding scope value in parsable format.
 
50
 */
 
51
 
 
52
static isc_result_t
 
53
write_binding_scope(FILE *db_file, struct binding *bnd, char *prepend) {
 
54
        char *s;
 
55
 
 
56
        if ((db_file == NULL) || (bnd == NULL) || (prepend == NULL))
 
57
                return ISC_R_INVALIDARG;
 
58
 
 
59
        if (bnd->value->type == binding_data) {
 
60
                if (bnd->value->value.data.data != NULL) {
 
61
                        s = quotify_buf(bnd->value->value.data.data,
 
62
                                        bnd->value->value.data.len, MDL);
 
63
                        if (s != NULL) {
 
64
                                errno = 0;
 
65
                                fprintf(db_file, "%sset %s = \"%s\";",
 
66
                                        prepend, bnd->name, s);
 
67
                                if (errno)
 
68
                                        return ISC_R_FAILURE;
 
69
 
 
70
                                dfree(s, MDL);
 
71
                        } else {
 
72
                            return ISC_R_FAILURE;
 
73
                        }
 
74
                }
 
75
        } else if (bnd->value->type == binding_numeric) {
 
76
                errno = 0;
 
77
                fprintf(db_file, "%sset %s = %%%ld;", prepend,
 
78
                        bnd->name, bnd->value->value.intval);
 
79
                if (errno)
 
80
                        return ISC_R_FAILURE;
 
81
        } else if (bnd->value->type == binding_boolean) {
 
82
                errno = 0;
 
83
                fprintf(db_file, "%sset %s = %s;", prepend, bnd->name,
 
84
                        bnd->value->value.intval ? "true" : "false");
 
85
                if (errno)
 
86
                        return ISC_R_FAILURE;
 
87
        } else if (bnd->value->type == binding_dns) {
 
88
                log_error("%s: persistent dns values not supported.",
 
89
                          bnd->name);
 
90
        } else if (bnd->value->type == binding_function) {
 
91
                log_error("%s: persistent functions not supported.",
 
92
                          bnd->name);
 
93
        } else {
 
94
                log_fatal("%s: unknown binding type %d", bnd->name,
 
95
                          bnd->value->type);
 
96
        }
 
97
 
 
98
        return ISC_R_SUCCESS;
 
99
}
 
100
 
 
101
/* Write the specified lease to the current lease database file. */
 
102
 
 
103
int write_lease (lease)
 
104
        struct lease *lease;
 
105
{
 
106
        int errors = 0;
 
107
        struct binding *b;
 
108
        char *s;
 
109
        const char *tval;
 
110
 
 
111
        /* If the lease file is corrupt, don't try to write any more leases
 
112
           until we've written a good lease file. */
 
113
        if (lease_file_is_corrupt)
 
114
                if (!new_lease_file ())
 
115
                        return 0;
 
116
 
 
117
        if (counting)
 
118
                ++count;
 
119
        errno = 0;
 
120
        fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
 
121
        if (errno) {
 
122
                ++errors;
 
123
        }
 
124
 
 
125
        if (lease->starts &&
 
126
            ((tval = print_time(lease->starts)) == NULL ||
 
127
             fprintf(db_file, "\n  starts %s", tval) < 0))
 
128
                ++errors;
 
129
 
 
130
        if (lease->ends &&
 
131
            ((tval = print_time(lease->ends)) == NULL ||
 
132
             fprintf(db_file, "\n  ends %s", tval) < 0))
 
133
                ++errors;
 
134
 
 
135
        if (lease->tstp &&
 
136
            ((tval = print_time(lease->tstp)) == NULL ||
 
137
             fprintf(db_file, "\n  tstp %s", tval) < 0))
 
138
                ++errors;
 
139
 
 
140
        if (lease->tsfp &&
 
141
            ((tval = print_time(lease->tsfp)) == NULL ||
 
142
             fprintf(db_file, "\n  tsfp %s", tval) < 0))
 
143
                ++errors;
 
144
 
 
145
        if (lease->atsfp &&
 
146
            ((tval = print_time(lease->atsfp)) == NULL ||
 
147
             fprintf(db_file, "\n  atsfp %s", tval) < 0))
 
148
                ++errors;
 
149
 
 
150
        if (lease->cltt &&
 
151
            ((tval = print_time(lease->cltt)) == NULL ||
 
152
             fprintf(db_file, "\n  cltt %s", tval) < 0))
 
153
                ++errors;
 
154
 
 
155
        if (fprintf (db_file, "\n  binding state %s;",
 
156
                 ((lease -> binding_state > 0 &&
 
157
                   lease -> binding_state <= FTS_LAST)
 
158
                  ? binding_state_names [lease -> binding_state - 1]
 
159
                  : "abandoned")) < 0)
 
160
                ++errors;
 
161
 
 
162
        if (lease -> binding_state != lease -> next_binding_state)
 
163
                if (fprintf (db_file, "\n  next binding state %s;",
 
164
                         ((lease -> next_binding_state > 0 &&
 
165
                           lease -> next_binding_state <= FTS_LAST)
 
166
                          ? (binding_state_names
 
167
                             [lease -> next_binding_state - 1])
 
168
                          : "abandoned")) < 0)
 
169
                        ++errors;
 
170
 
 
171
        if (lease->flags & RESERVED_LEASE)
 
172
                if (fprintf(db_file, "\n  reserved;") < 0)
 
173
                        ++errors;
 
174
 
 
175
        if (lease->flags & BOOTP_LEASE)
 
176
                if (fprintf(db_file, "\n  dynamic-bootp;") < 0)
 
177
                        ++errors;
 
178
 
 
179
        /* If this lease is billed to a class and is still valid,
 
180
           write it out. */
 
181
        if (lease -> billing_class && lease -> ends > cur_time) {
 
182
                if (!write_billing_class (lease -> billing_class)) {
 
183
                        log_error ("unable to write class %s",
 
184
                                   lease -> billing_class -> name);
 
185
                        ++errors;
 
186
                }
 
187
        }
 
188
 
 
189
        if (lease -> hardware_addr.hlen) {
 
190
                errno = 0;
 
191
                fprintf (db_file, "\n  hardware %s %s;",
 
192
                         hardware_types [lease -> hardware_addr.hbuf [0]],
 
193
                         print_hw_addr (lease -> hardware_addr.hbuf [0],
 
194
                                        lease -> hardware_addr.hlen - 1,
 
195
                                        &lease -> hardware_addr.hbuf [1]));
 
196
                if (errno)
 
197
                        ++errors;
 
198
        }
 
199
        if (lease -> uid_len) {
 
200
                s = quotify_buf (lease -> uid, lease -> uid_len, MDL);
 
201
                if (s) {
 
202
                        errno = 0;
 
203
                        fprintf (db_file, "\n  uid \"%s\";", s);
 
204
                        if (errno)
 
205
                                ++errors;
 
206
                        dfree (s, MDL);
 
207
                } else
 
208
                        ++errors;
 
209
        }
 
210
 
 
211
        if (lease->scope != NULL) {
 
212
            for (b = lease->scope->bindings; b; b = b->next) {
 
213
                if (!b->value)
 
214
                        continue;
 
215
 
 
216
                if (write_binding_scope(db_file, b, "\n  ") != ISC_R_SUCCESS)
 
217
                        ++errors;
 
218
            }
 
219
        }
 
220
 
 
221
        if (lease -> agent_options) {
 
222
            struct option_cache *oc;
 
223
            struct data_string ds;
 
224
            pair p;
 
225
 
 
226
            memset (&ds, 0, sizeof ds);
 
227
            for (p = lease -> agent_options -> first; p; p = p -> cdr) {
 
228
                oc = (struct option_cache *)p -> car;
 
229
                if (oc -> data.len) {
 
230
                errno = 0;
 
231
                fprintf (db_file, "\n  option agent.%s %s;",
 
232
                         oc -> option -> name,
 
233
                         pretty_print_option (oc -> option, oc -> data.data,
 
234
                                                oc -> data.len, 1, 1));
 
235
                if (errno)
 
236
                    ++errors;
 
237
                }
 
238
            }
 
239
        }
 
240
        if (lease -> client_hostname &&
 
241
            db_printable((unsigned char *)lease->client_hostname)) {
 
242
                s = quotify_string (lease -> client_hostname, MDL);
 
243
                if (s) {
 
244
                        errno = 0;
 
245
                        fprintf (db_file, "\n  client-hostname \"%s\";", s);
 
246
                        if (errno)
 
247
                                ++errors;
 
248
                        dfree (s, MDL);
 
249
                } else
 
250
                        ++errors;
 
251
        }
 
252
        if (lease -> on_expiry) {
 
253
                errno = 0;
 
254
                fprintf (db_file, "\n  on expiry%s {",
 
255
                         lease -> on_expiry == lease -> on_release
 
256
                         ? " or release" : "");
 
257
                write_statements (db_file, lease -> on_expiry, 4);
 
258
                /* XXX */
 
259
                fprintf (db_file, "\n  }");
 
260
                if (errno)
 
261
                        ++errors;
 
262
        }
 
263
        if (lease -> on_release && lease -> on_release != lease -> on_expiry) {
 
264
                errno = 0;
 
265
                fprintf (db_file, "\n  on release {");
 
266
                write_statements (db_file, lease -> on_release, 4);
 
267
                /* XXX */
 
268
                fprintf (db_file, "\n  }");
 
269
                if (errno)
 
270
                        ++errors;
 
271
        }
 
272
 
 
273
        errno = 0;
 
274
        fputs ("\n}\n", db_file);
 
275
        if (errno)
 
276
                ++errors;
 
277
 
 
278
        if (errors) {
 
279
                log_info ("write_lease: unable to write lease %s",
 
280
                      piaddr (lease -> ip_addr));
 
281
                lease_file_is_corrupt = 1;
 
282
        }
 
283
 
 
284
        return !errors;
 
285
}
 
286
 
 
287
int write_host (host)
 
288
        struct host_decl *host;
 
289
{
 
290
        int errors = 0;
 
291
        int i;
 
292
        struct data_string ip_addrs;
 
293
 
 
294
        /* If the lease file is corrupt, don't try to write any more leases
 
295
           until we've written a good lease file. */
 
296
        if (lease_file_is_corrupt)
 
297
                if (!new_lease_file ())
 
298
                        return 0;
 
299
 
 
300
        if (!db_printable((unsigned char *)host->name))
 
301
                return 0;
 
302
 
 
303
        if (counting)
 
304
                ++count;
 
305
 
 
306
        errno = 0;
 
307
        fprintf (db_file, "host %s {", host -> name);
 
308
        if (errno)
 
309
                ++errors;
 
310
 
 
311
        if (host -> flags & HOST_DECL_DYNAMIC) {
 
312
                errno = 0;
 
313
                fprintf (db_file, "\n  dynamic;");
 
314
                if (errno)
 
315
                        ++errors;
 
316
        }
 
317
 
 
318
        if (host -> flags & HOST_DECL_DELETED) {
 
319
                errno = 0;
 
320
                fprintf (db_file, "\n  deleted;");
 
321
                if (errno)
 
322
                        ++errors;
 
323
        } else {
 
324
                if (host -> interface.hlen) {
 
325
                        errno = 0;
 
326
                        fprintf (db_file, "\n  hardware %s %s;",
 
327
                                 hardware_types [host -> interface.hbuf [0]],
 
328
                                 print_hw_addr (host -> interface.hbuf [0],
 
329
                                                host -> interface.hlen - 1,
 
330
                                                &host -> interface.hbuf [1]));
 
331
                        if (errno)
 
332
                                ++errors;
 
333
                }
 
334
                if (host -> client_identifier.len) {
 
335
                        int i;
 
336
                        errno = 0;
 
337
                        if (db_printable_len (host -> client_identifier.data,
 
338
                                              host -> client_identifier.len)) {
 
339
                                fprintf (db_file, "\n  uid \"%.*s\";",
 
340
                                         (int)host -> client_identifier.len,
 
341
                                         host -> client_identifier.data);
 
342
                                if (errno)
 
343
                                        ++errors;
 
344
                        } else {
 
345
                                fprintf (db_file,
 
346
                                         "\n  uid %2.2x",
 
347
                                         host -> client_identifier.data [0]);
 
348
                                if (errno)
 
349
                                        ++errors;
 
350
                                for (i = 1;
 
351
                                     i < host -> client_identifier.len; i++) {
 
352
                                        errno = 0;
 
353
                                        fprintf (db_file, ":%2.2x",
 
354
                                                 host ->
 
355
                                                 client_identifier.data [i]);
 
356
                                        if (errno)
 
357
                                                ++errors;
 
358
                                }
 
359
 
 
360
                                errno = 0;
 
361
                                fputc (';', db_file);
 
362
                                if (errno)
 
363
                                        ++errors;
 
364
                        }
 
365
                }
 
366
                
 
367
                memset (&ip_addrs, 0, sizeof ip_addrs);
 
368
                if (host -> fixed_addr &&
 
369
                    evaluate_option_cache (&ip_addrs, (struct packet *)0,
 
370
                                           (struct lease *)0,
 
371
                                           (struct client_state *)0,
 
372
                                           (struct option_state *)0,
 
373
                                           (struct option_state *)0,
 
374
                                           &global_scope,
 
375
                                           host -> fixed_addr, MDL)) {
 
376
                
 
377
                        errno = 0;
 
378
                        fprintf (db_file, "\n  fixed-address ");
 
379
                        if (errno)
 
380
                                ++errors;
 
381
                        for (i = 0; i < ip_addrs.len - 3; i += 4) {
 
382
 
 
383
                                errno = 0;
 
384
                                fprintf (db_file, "%u.%u.%u.%u%s",
 
385
                                         ip_addrs.data [i] & 0xff,
 
386
                                         ip_addrs.data [i + 1] & 0xff,
 
387
                                         ip_addrs.data [i + 2] & 0xff,
 
388
                                         ip_addrs.data [i + 3] & 0xff,
 
389
                                         i + 7 < ip_addrs.len ? "," : "");
 
390
                                if (errno)
 
391
                                        ++errors;
 
392
                        }
 
393
 
 
394
                        errno = 0;
 
395
                        fputc (';', db_file);
 
396
                        if (errno)
 
397
                                ++errors;
 
398
                }
 
399
 
 
400
                if (host -> named_group) {
 
401
                        errno = 0;
 
402
                        fprintf (db_file, "\n  group \"%s\";",
 
403
                                 host -> named_group -> name);
 
404
                        if (errno)
 
405
                                ++errors;
 
406
                }
 
407
 
 
408
                if (host -> group &&
 
409
                    (!host -> named_group ||
 
410
                     host -> group != host -> named_group -> group) &&
 
411
                    host -> group != root_group) {
 
412
                        errno = 0;
 
413
                        write_statements (db_file,
 
414
                                          host -> group -> statements, 8);
 
415
                        if (errno)
 
416
                                ++errors;
 
417
                }
 
418
        }
 
419
 
 
420
        errno = 0;
 
421
        fputs ("\n}\n", db_file);
 
422
        if (errno)
 
423
                ++errors;
 
424
 
 
425
        if (errors) {
 
426
                log_info ("write_host: unable to write host %s",
 
427
                          host -> name);
 
428
                lease_file_is_corrupt = 1;
 
429
        }
 
430
 
 
431
        return !errors;
 
432
}
 
433
 
 
434
int write_group (group)
 
435
        struct group_object *group;
 
436
{
 
437
        int errors = 0;
 
438
 
 
439
        /* If the lease file is corrupt, don't try to write any more leases
 
440
           until we've written a good lease file. */
 
441
        if (lease_file_is_corrupt)
 
442
                if (!new_lease_file ())
 
443
                        return 0;
 
444
 
 
445
        if (!db_printable((unsigned char *)group->name))
 
446
                return 0;
 
447
 
 
448
        if (counting)
 
449
                ++count;
 
450
 
 
451
        errno = 0;
 
452
        fprintf (db_file, "group %s {", group -> name);
 
453
        if (errno)
 
454
                ++errors;
 
455
 
 
456
        if (group -> flags & GROUP_OBJECT_DYNAMIC) {
 
457
                errno = 0;
 
458
                fprintf (db_file, "\n  dynamic;");
 
459
                if (errno)
 
460
                        ++errors;
 
461
        }
 
462
 
 
463
        if (group -> flags & GROUP_OBJECT_STATIC) {
 
464
                errno = 0;
 
465
                fprintf (db_file, "\n  static;");
 
466
                if (errno)
 
467
                        ++errors;
 
468
        }
 
469
 
 
470
        if (group -> flags & GROUP_OBJECT_DELETED) {
 
471
                errno = 0;
 
472
                fprintf (db_file, "\n  deleted;");
 
473
                if (errno)
 
474
                        ++errors;
 
475
        } else {
 
476
                if (group -> group) {
 
477
                        errno = 0;
 
478
                        write_statements (db_file,
 
479
                                          group -> group -> statements, 8);
 
480
                        if (errno)
 
481
                                ++errors;
 
482
                }
 
483
        }
 
484
 
 
485
        errno = 0;
 
486
        fputs ("\n}\n", db_file);
 
487
        if (errno)
 
488
                ++errors;
 
489
 
 
490
        if (errors) {
 
491
                log_info ("write_group: unable to write group %s",
 
492
                          group -> name);
 
493
                lease_file_is_corrupt = 1;
 
494
        }
 
495
 
 
496
        return !errors;
 
497
}
 
498
 
 
499
/*
 
500
 * Write an IA and the options it has.
 
501
 */
 
502
int
 
503
write_ia(const struct ia_xx *ia) {
 
504
        struct iasubopt *iasubopt;
 
505
        struct binding *bnd;
 
506
        int i;
 
507
        char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff.255.255.255.255")];
 
508
        const char *binding_state;
 
509
        const char *tval;
 
510
        char *s;
 
511
        int fprintf_ret;
 
512
 
 
513
        /* 
 
514
         * If the lease file is corrupt, don't try to write any more 
 
515
         * leases until we've written a good lease file. 
 
516
         */
 
517
        if (lease_file_is_corrupt) {
 
518
                if (!new_lease_file()) {
 
519
                        return 0;
 
520
                }
 
521
        }
 
522
 
 
523
        if (counting) {
 
524
                ++count;
 
525
        }
 
526
 
 
527
        
 
528
        s = quotify_buf(ia->iaid_duid.data, ia->iaid_duid.len, MDL);
 
529
        if (s == NULL) {
 
530
                goto error_exit;
 
531
        }
 
532
        switch (ia->ia_type) {
 
533
        case D6O_IA_NA:
 
534
                fprintf_ret = fprintf(db_file, "ia-na \"%s\" {\n", s);
 
535
                break;
 
536
        case D6O_IA_TA:
 
537
                fprintf_ret = fprintf(db_file, "ia-ta \"%s\" {\n", s);
 
538
                break;
 
539
        case D6O_IA_PD:
 
540
                fprintf_ret = fprintf(db_file, "ia-pd \"%s\" {\n", s);
 
541
                break;
 
542
        default:
 
543
                log_error("Unknown ia type %u for \"%s\" at %s:%d",
 
544
                          (unsigned)ia->ia_type, s, MDL);
 
545
                fprintf_ret = -1;
 
546
        }
 
547
        dfree(s, MDL);
 
548
        if (fprintf_ret < 0) {
 
549
                goto error_exit;
 
550
        }
 
551
        if (ia->cltt != MIN_TIME) {
 
552
                tval = print_time(ia->cltt);
 
553
                if (tval == NULL) {
 
554
                        goto error_exit;
 
555
                }
 
556
                if (fprintf(db_file, "  cltt %s\n", tval) < 0) {
 
557
                        goto error_exit;
 
558
                }
 
559
        }
 
560
        for (i=0; i<ia->num_iasubopt; i++) {
 
561
                iasubopt = ia->iasubopt[i];
 
562
 
 
563
                inet_ntop(AF_INET6, &iasubopt->addr,
 
564
                          addr_buf, sizeof(addr_buf));
 
565
                if ((ia->ia_type != D6O_IA_PD) &&
 
566
                    (fprintf(db_file, "  iaaddr %s {\n", addr_buf) < 0)) {
 
567
                        goto error_exit;
 
568
                }
 
569
                if ((ia->ia_type == D6O_IA_PD) &&
 
570
                    (fprintf(db_file, "  iaprefix %s/%d {\n",
 
571
                             addr_buf, (int)iasubopt->plen) < 0)) {
 
572
                        goto error_exit;
 
573
                }
 
574
                if ((iasubopt->state <= 0) || (iasubopt->state > FTS_LAST)) {
 
575
                        log_fatal("Unknown iasubopt state %d at %s:%d", 
 
576
                                  iasubopt->state, MDL);
 
577
                }
 
578
                binding_state = binding_state_names[iasubopt->state-1];
 
579
                if (fprintf(db_file, "    binding state %s;\n", 
 
580
                            binding_state) < 0) {
 
581
                        goto error_exit;
 
582
                }
 
583
                if (fprintf(db_file, "    preferred-life %u\n",
 
584
                            (unsigned)iasubopt->prefer) < 0) {
 
585
                        goto error_exit;
 
586
                }
 
587
                if (fprintf(db_file, "    max-life %u\n",
 
588
                            (unsigned)iasubopt->valid) < 0) {
 
589
                        goto error_exit;
 
590
                }
 
591
 
 
592
                /* Note that from here on out, the \n is prepended to the
 
593
                 * next write, rather than appended to the current write.
 
594
                 */
 
595
                if ((iasubopt->state == FTS_ACTIVE) ||
 
596
                    (iasubopt->state == FTS_ABANDONED) ||
 
597
                    (iasubopt->hard_lifetime_end_time != 0)) {
 
598
                        tval = print_time(iasubopt->hard_lifetime_end_time);
 
599
                } else {
 
600
                        tval = print_time(iasubopt->soft_lifetime_end_time);
 
601
                }
 
602
                if (tval == NULL) {
 
603
                        goto error_exit;
 
604
                }
 
605
                if (fprintf(db_file, "    ends %s", tval) < 0) {
 
606
                        goto error_exit;
 
607
                }
 
608
 
 
609
                /* Write out any binding scopes: note that 'ends' above does
 
610
                 * not have \n on the end!  We want that.
 
611
                 */
 
612
                if (iasubopt->scope != NULL)
 
613
                        bnd = iasubopt->scope->bindings;
 
614
                else
 
615
                        bnd = NULL;
 
616
 
 
617
                for (; bnd != NULL ; bnd = bnd->next) {
 
618
                        if (bnd->value == NULL)
 
619
                                continue;
 
620
 
 
621
                        /* We don't do a regular error_exit because the
 
622
                         * lease db is not corrupt in this case.
 
623
                         */
 
624
                        if (write_binding_scope(db_file, bnd,
 
625
                                                "\n    ") != ISC_R_SUCCESS)
 
626
                                goto error_exit;
 
627
                                
 
628
                }
 
629
 
 
630
                if (fprintf(db_file, "\n  }\n") < 0)
 
631
                        goto error_exit;
 
632
        }
 
633
        if (fprintf(db_file, "}\n\n") < 0)
 
634
                goto error_exit;
 
635
 
 
636
        fflush(db_file);
 
637
        return 1;
 
638
 
 
639
error_exit:
 
640
        log_info("write_ia: unable to write ia");
 
641
        lease_file_is_corrupt = 1;
 
642
        return 0;
 
643
}
 
644
 
 
645
#ifdef DHCPv6
 
646
/*
 
647
 * Put a copy of the server DUID in the leases file.
 
648
 */
 
649
int
 
650
write_server_duid(void) {
 
651
        struct data_string server_duid;
 
652
        char *s;
 
653
        int fprintf_ret;
 
654
 
 
655
        /*
 
656
         * Only write the DUID if it's been set.
 
657
         */
 
658
        if (!server_duid_isset()) {
 
659
                return 1;
 
660
        }
 
661
 
 
662
        /* 
 
663
         * If the lease file is corrupt, don't try to write any more 
 
664
         * leases until we've written a good lease file. 
 
665
         */
 
666
        if (lease_file_is_corrupt) {
 
667
                if (!new_lease_file()) {
 
668
                        return 0;
 
669
                }
 
670
        }
 
671
 
 
672
        /*
 
673
         * Get a copy of our server DUID and convert to a quoted string.
 
674
         */
 
675
        memset(&server_duid, 0, sizeof(server_duid));
 
676
        copy_server_duid(&server_duid, MDL);
 
677
        s = quotify_buf(server_duid.data, server_duid.len, MDL);
 
678
        data_string_forget(&server_duid, MDL);
 
679
        if (s == NULL) {
 
680
                goto error_exit;
 
681
        }
 
682
 
 
683
        /*
 
684
         * Write to the leases file.
 
685
         */
 
686
        fprintf_ret = fprintf(db_file, "server-duid \"%s\";\n\n", s);
 
687
        dfree(s, MDL);
 
688
        if (fprintf_ret < 0) {
 
689
                goto error_exit;
 
690
        }
 
691
 
 
692
        /*
 
693
         * Check if we actually managed to write.
 
694
         */
 
695
        fflush(db_file);
 
696
        return 1;
 
697
 
 
698
error_exit:
 
699
        log_info("write_server_duid: unable to write server-duid");
 
700
        lease_file_is_corrupt = 1;
 
701
        return 0;
 
702
}
 
703
#endif /* DHCPv6 */
 
704
 
 
705
#if defined (FAILOVER_PROTOCOL)
 
706
int write_failover_state (dhcp_failover_state_t *state)
 
707
{
 
708
        int errors = 0;
 
709
        const char *tval;
 
710
 
 
711
        if (lease_file_is_corrupt)
 
712
                if (!new_lease_file ())
 
713
                        return 0;
 
714
 
 
715
        errno = 0;
 
716
        fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
 
717
        if (errno)
 
718
                ++errors;
 
719
 
 
720
        tval = print_time(state->me.stos);
 
721
        if (tval == NULL ||
 
722
            fprintf(db_file, "\n  my state %s at %s",
 
723
                    (state->me.state == startup) ?
 
724
                    dhcp_failover_state_name_print(state->saved_state) :
 
725
                    dhcp_failover_state_name_print(state->me.state),
 
726
                    tval) < 0)
 
727
                ++errors;
 
728
 
 
729
        tval = print_time(state->partner.stos);
 
730
        if (tval == NULL ||
 
731
            fprintf(db_file, "\n  partner state %s at %s",
 
732
                    dhcp_failover_state_name_print(state->partner.state),
 
733
                    tval) < 0)
 
734
                ++errors;
 
735
 
 
736
        if (state -> i_am == secondary) {
 
737
                errno = 0;
 
738
                fprintf (db_file, "\n  mclt %ld;",
 
739
                         (unsigned long)state -> mclt);
 
740
                if (errno)
 
741
                        ++errors;
 
742
        }
 
743
 
 
744
        errno = 0;
 
745
        fprintf (db_file, "\n}\n");
 
746
        if (errno)
 
747
                ++errors;
 
748
 
 
749
        if (errors) {
 
750
                log_info ("write_failover_state: unable to write state %s",
 
751
                          state -> name);
 
752
                lease_file_is_corrupt = 1;
 
753
                return 0;
 
754
        }
 
755
 
 
756
        return 1;
 
757
 
 
758
}
 
759
#endif
 
760
 
 
761
int db_printable (s)
 
762
        const unsigned char *s;
 
763
{
 
764
        int i;
 
765
        for (i = 0; s [i]; i++)
 
766
                if (!isascii (s [i]) || !isprint (s [i])
 
767
                    || s [i] == '"' || s [i] == '\\')
 
768
                        return 0;
 
769
        return 1;
 
770
}
 
771
 
 
772
int db_printable_len (s, len)
 
773
        const unsigned char *s;
 
774
        unsigned len;
 
775
{
 
776
        int i;
 
777
 
 
778
        for (i = 0; i < len; i++)
 
779
                if (!isascii (s [i]) || !isprint (s [i]) ||
 
780
                    s [i] == '"' || s [i] == '\\')
 
781
                        return 0;
 
782
        return 1;
 
783
}
 
784
 
 
785
static int print_hash_string(FILE *fp, struct class *class)
 
786
{
 
787
        int i;
 
788
 
 
789
        for (i = 0 ; i < class->hash_string.len ; i++)
 
790
                if (!isascii(class->hash_string.data[i]) ||
 
791
                    !isprint(class->hash_string.data[i]))
 
792
                        break;
 
793
 
 
794
        if (i == class->hash_string.len) {
 
795
                if (fprintf(fp, " \"%.*s\"", (int)class->hash_string.len,
 
796
                            class->hash_string.data) <= 0) {
 
797
                        log_error("Failure writing hash string: %m");
 
798
                        return 0;
 
799
                }
 
800
        } else {
 
801
                if (fprintf(fp, " %2.2x", class->hash_string.data[0]) <= 0) {
 
802
                        log_error("Failure writing hash string: %m");
 
803
                        return 0;
 
804
                }
 
805
                for (i = 1 ; i < class->hash_string.len ; i++) {
 
806
                        if (fprintf(fp, ":%2.2x",
 
807
                                    class->hash_string.data[i]) <= 0) {
 
808
                                log_error("Failure writing hash string: %m");
 
809
                                return 0;
 
810
                        }
 
811
                }
 
812
        }
 
813
 
 
814
        return 1;
 
815
}
 
816
 
 
817
 
 
818
isc_result_t
 
819
write_named_billing_class(const void *key, unsigned len, void *object)
 
820
{
 
821
        const unsigned char *name = key;
 
822
        struct class *class = object;
 
823
 
 
824
        if (class->flags & CLASS_DECL_DYNAMIC) {
 
825
                numclasseswritten++;
 
826
                if (class->superclass == 0) {
 
827
                        if (fprintf(db_file, "class \"%s\" {\n", name) <= 0)
 
828
                                return ISC_R_IOERROR;
 
829
                } else {
 
830
                        if (fprintf(db_file, "subclass \"%s\"",
 
831
                                    class->superclass->name) <= 0)
 
832
                                return ISC_R_IOERROR;
 
833
                        if (!print_hash_string(db_file, class))
 
834
                                return ISC_R_IOERROR;
 
835
                        if (fprintf(db_file, " {\n") <= 0)
 
836
                                return ISC_R_IOERROR;
 
837
                }
 
838
 
 
839
                if ((class->flags & CLASS_DECL_DELETED) != 0) {
 
840
                        if (fprintf(db_file, "  deleted;\n") <= 0)
 
841
                                return ISC_R_IOERROR;
 
842
                } else {
 
843
                        if (fprintf(db_file, "  dynamic;\n") <= 0)
 
844
                                return ISC_R_IOERROR;
 
845
                }
 
846
        
 
847
                if (class->lease_limit > 0) {
 
848
                        if (fprintf(db_file, "  lease limit %d;\n",
 
849
                                    class->lease_limit) <= 0)
 
850
                                return ISC_R_IOERROR;
 
851
                }
 
852
 
 
853
                if (class->expr != 0) {
 
854
                        if (fprintf(db_file, "  match if ") <= 0)
 
855
                                return ISC_R_IOERROR;
 
856
 
 
857
                        errno = 0;                                       
 
858
                        write_expression(db_file, class->expr, 5, 5, 0);
 
859
                        if (errno)
 
860
                                return ISC_R_IOERROR;
 
861
 
 
862
                        if (fprintf(db_file, ";\n") <= 0)
 
863
                                return ISC_R_IOERROR;
 
864
                }
 
865
 
 
866
                if (class->submatch != 0) {
 
867
                        if (class->spawning) {
 
868
                                if (fprintf(db_file, "  spawn ") <= 0)
 
869
                                        return ISC_R_IOERROR;
 
870
                        } else {
 
871
                                if (fprintf(db_file, "  match ") <= 0)
 
872
                                        return ISC_R_IOERROR;
 
873
                        }
 
874
 
 
875
                        errno = 0;
 
876
                        write_expression(db_file, class->submatch, 5, 5, 0);
 
877
                        if (errno)
 
878
                                return ISC_R_IOERROR;
 
879
 
 
880
                        if (fprintf(db_file, ";\n") <= 0)
 
881
                                return ISC_R_IOERROR;
 
882
                }
 
883
        
 
884
                if (class->statements != 0) {
 
885
                        errno = 0;
 
886
                        write_statements(db_file, class->statements, 8);
 
887
                        if (errno)
 
888
                                return ISC_R_IOERROR;
 
889
                }
 
890
 
 
891
                /* XXXJAB this isn't right, but classes read in off the
 
892
                   leases file don't get the root group assigned to them
 
893
                   (due to clone_group() call). */
 
894
                if (class->group != 0 && class->group->authoritative != 0) {
 
895
                        errno = 0;
 
896
                        write_statements(db_file, class->group->statements, 8);
 
897
                        if (errno)
 
898
                                return ISC_R_IOERROR;
 
899
                }
 
900
 
 
901
                if (fprintf(db_file, "}\n\n") <= 0)
 
902
                        return ISC_R_IOERROR;
 
903
        }
 
904
 
 
905
        if (class->hash != NULL) {      /* yep. recursive. god help us. */
 
906
                /* XXX - cannot check error status of this...
 
907
                 * foo_hash_foreach returns a count of operations completed.
 
908
                 */
 
909
                class_hash_foreach(class->hash, write_named_billing_class);
 
910
        }
 
911
 
 
912
        return ISC_R_SUCCESS;
 
913
}
 
914
 
 
915
void write_billing_classes ()
 
916
{
 
917
        struct collection *lp;
 
918
        struct class *cp;
 
919
 
 
920
        for (lp = collections; lp; lp = lp -> next) {
 
921
            for (cp = lp -> classes; cp; cp = cp -> nic) {
 
922
                if (cp -> spawning && cp -> hash) {
 
923
                    class_hash_foreach (cp -> hash, write_named_billing_class);
 
924
                }
 
925
            }
 
926
        }
 
927
}
 
928
 
 
929
/* Write a spawned class to the database file. */
 
930
 
 
931
int write_billing_class (class)
 
932
        struct class *class;
 
933
{
 
934
        int errors = 0;
 
935
 
 
936
        if (lease_file_is_corrupt)
 
937
                if (!new_lease_file ())
 
938
                        return 0;
 
939
 
 
940
        if (!class -> superclass) {
 
941
                errno = 0;
 
942
                fprintf (db_file, "\n  billing class \"%s\";", class -> name);
 
943
                return !errno;
 
944
        }
 
945
 
 
946
        if (fprintf(db_file, "\n  billing subclass \"%s\"",
 
947
                    class -> superclass -> name) < 0)
 
948
                ++errors;
 
949
 
 
950
        if (!print_hash_string(db_file, class))
 
951
                ++errors;
 
952
 
 
953
        if (fprintf(db_file, ";") < 0)
 
954
                ++errors;
 
955
 
 
956
        class -> dirty = !errors;
 
957
        if (errors)
 
958
                lease_file_is_corrupt = 1;
 
959
 
 
960
        return !errors;
 
961
}
 
962
 
 
963
/* Commit leases after a timeout. */
 
964
void commit_leases_timeout (void *foo)
 
965
{
 
966
        commit_leases ();
 
967
}
 
968
 
 
969
/* Commit any leases that have been written out... */
 
970
 
 
971
int commit_leases ()
 
972
{
 
973
        /* Commit any outstanding writes to the lease database file.
 
974
           We need to do this even if we're rewriting the file below,
 
975
           just in case the rewrite fails. */
 
976
        if (fflush (db_file) == EOF) {
 
977
                log_info ("commit_leases: unable to commit: %m");
 
978
                return 0;
 
979
        }
 
980
        if (fsync (fileno (db_file)) < 0) {
 
981
                log_info ("commit_leases: unable to commit: %m");
 
982
                return 0;
 
983
        }
 
984
 
 
985
        /* send out all deferred ACKs now */
 
986
        flush_ackqueue(NULL);
 
987
 
 
988
        /* If we haven't rewritten the lease database in over an
 
989
           hour, rewrite it now.  (The length of time should probably
 
990
           be configurable. */
 
991
        if (count && cur_time - write_time > 3600) {
 
992
                count = 0;
 
993
                write_time = cur_time;
 
994
                new_lease_file ();
 
995
        }
 
996
        return 1;
 
997
}
 
998
 
 
999
void db_startup (testp)
 
1000
        int testp;
 
1001
{
 
1002
        isc_result_t status;
 
1003
 
 
1004
#if defined (TRACING)
 
1005
        if (!trace_playback ()) {
 
1006
#endif
 
1007
                /* Read in the existing lease file... */
 
1008
                status = read_conf_file (path_dhcpd_db,
 
1009
                                         (struct group *)0, 0, 1);
 
1010
                /* XXX ignore status? */
 
1011
#if defined (TRACING)
 
1012
        }
 
1013
#endif
 
1014
 
 
1015
#if defined (TRACING)
 
1016
        /* If we're playing back, there is no lease file, so we can't
 
1017
           append it, so we create one immediately (maybe this isn't
 
1018
           the best solution... */
 
1019
        if (trace_playback ()) {
 
1020
                new_lease_file ();
 
1021
        }
 
1022
#endif
 
1023
        if (!testp) {
 
1024
                db_file = fopen (path_dhcpd_db, "a");
 
1025
                if (!db_file)
 
1026
                        log_fatal ("Can't open %s for append.", path_dhcpd_db);
 
1027
                expire_all_pools ();
 
1028
#if defined (TRACING)
 
1029
                if (trace_playback ())
 
1030
                        write_time = cur_time;
 
1031
                else
 
1032
#endif
 
1033
                        time(&write_time);
 
1034
                new_lease_file ();
 
1035
        }
 
1036
 
 
1037
#if defined(REPORT_HASH_PERFORMANCE)
 
1038
        log_info("Host HW hash:   %s", host_hash_report(host_hw_addr_hash));
 
1039
        log_info("Host UID hash:  %s", host_hash_report(host_uid_hash));
 
1040
        log_info("Lease IP hash:  %s",
 
1041
                 lease_ip_hash_report(lease_ip_addr_hash));
 
1042
        log_info("Lease UID hash: %s", lease_id_hash_report(lease_uid_hash));
 
1043
        log_info("Lease HW hash:  %s",
 
1044
                 lease_id_hash_report(lease_hw_addr_hash));
 
1045
#endif
 
1046
}
 
1047
 
 
1048
int new_lease_file ()
 
1049
{
 
1050
        char newfname [512];
 
1051
        char backfname [512];
 
1052
        TIME t;
 
1053
        int db_fd;
 
1054
        int db_validity;
 
1055
        FILE *new_db_file;
 
1056
 
 
1057
        /* Make a temporary lease file... */
 
1058
        time(&t);
 
1059
 
 
1060
        db_validity = lease_file_is_corrupt;
 
1061
 
 
1062
        /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
 
1063
         * This should never happen since the path is a configuration
 
1064
         * variable from build-time or command-line.  But if it should,
 
1065
         * either by malice or ignorance, we panic, since the potential
 
1066
         * for havoc is high.
 
1067
         */
 
1068
        if (snprintf (newfname, sizeof newfname, "%s.%d",
 
1069
                     path_dhcpd_db, (int)t) >= sizeof newfname)
 
1070
                log_fatal("new_lease_file: lease file path too long");
 
1071
 
 
1072
        db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
 
1073
        if (db_fd < 0) {
 
1074
                log_error ("Can't create new lease file: %m");
 
1075
                return 0;
 
1076
        }
 
1077
        if ((new_db_file = fdopen(db_fd, "w")) == NULL) {
 
1078
                log_error("Can't fdopen new lease file: %m");
 
1079
                close(db_fd);
 
1080
                goto fdfail;
 
1081
        }
 
1082
 
 
1083
        /* Close previous database, if any. */
 
1084
        if (db_file)
 
1085
                fclose(db_file);
 
1086
        db_file = new_db_file;
 
1087
 
 
1088
        errno = 0;
 
1089
        fprintf (db_file, "# The format of this file is documented in the %s",
 
1090
                 "dhcpd.leases(5) manual page.\n");
 
1091
        if (errno)
 
1092
                goto fail;
 
1093
 
 
1094
        fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
 
1095
                 PACKAGE_VERSION);
 
1096
        if (errno)
 
1097
                goto fail;
 
1098
 
 
1099
        /* At this point we have a new lease file that, so far, could not
 
1100
         * be described as either corrupt nor valid.
 
1101
         */
 
1102
        lease_file_is_corrupt = 0;
 
1103
 
 
1104
        /* Write out all the leases that we know of... */
 
1105
        counting = 0;
 
1106
        if (!write_leases ())
 
1107
                goto fail;
 
1108
 
 
1109
#if defined (TRACING)
 
1110
        if (!trace_playback ()) {
 
1111
#endif
 
1112
            /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
 
1113
             * This should never happen since the path is a configuration
 
1114
             * variable from build-time or command-line.  But if it should,
 
1115
             * either by malice or ignorance, we panic, since the potential
 
1116
             * for havoc is too high.
 
1117
             */
 
1118
            if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
 
1119
                        >= sizeof backfname)
 
1120
                log_fatal("new_lease_file: backup lease file path too long");
 
1121
 
 
1122
            /* Get the old database out of the way... */
 
1123
            if (unlink (backfname) < 0 && errno != ENOENT) {
 
1124
                log_error ("Can't remove old lease database backup %s: %m",
 
1125
                           backfname);
 
1126
                goto fail;
 
1127
            }
 
1128
            if (link(path_dhcpd_db, backfname) < 0) {
 
1129
                if (errno == ENOENT) {
 
1130
                        log_error("%s is missing - no lease db to backup.",
 
1131
                                  path_dhcpd_db);
 
1132
                } else {
 
1133
                        log_error("Can't backup lease database %s to %s: %m",
 
1134
                                  path_dhcpd_db, backfname);
 
1135
                        goto fail;
 
1136
                }
 
1137
            }
 
1138
#if defined (TRACING)
 
1139
        }
 
1140
#endif
 
1141
        
 
1142
        /* Move in the new file... */
 
1143
        if (rename (newfname, path_dhcpd_db) < 0) {
 
1144
                log_error ("Can't install new lease database %s to %s: %m",
 
1145
                           newfname, path_dhcpd_db);
 
1146
                goto fail;
 
1147
        }
 
1148
 
 
1149
        counting = 1;
 
1150
        return 1;
 
1151
 
 
1152
      fail:
 
1153
        lease_file_is_corrupt = db_validity;
 
1154
      fdfail:
 
1155
        unlink (newfname);
 
1156
        return 0;
 
1157
}
 
1158
 
 
1159
int group_writer (struct group_object *group)
 
1160
{
 
1161
        if (!write_group (group))
 
1162
                return 0;
 
1163
        if (!commit_leases ())
 
1164
                return 0;
 
1165
        return 1;
 
1166
}