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