Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / network / stacks / AROSTCP / dhcp / server / db.c
blob92ae81ff0c8e52ae9f02e9eed17df62dd55754a4
1 /* db.c
3 Persistent database management routines for DHCPD... */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
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''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id$ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
40 #include "dhcpd.h"
41 #include <ctype.h>
42 #include "version.h"
44 FILE *db_file;
46 static int counting = 0;
47 static int count = 0;
48 TIME write_time;
49 int lease_file_is_corrupt = 0;
51 /* Write the specified lease to the current lease database file. */
53 int write_lease (lease)
54 struct lease *lease;
56 struct tm *t;
57 char tbuf [64];
58 int errors = 0;
59 int i;
60 struct binding *b;
61 char *s;
63 /* If the lease file is corrupt, don't try to write any more leases
64 until we've written a good lease file. */
65 if (lease_file_is_corrupt)
66 if (!new_lease_file ())
67 return 0;
69 if (counting)
70 ++count;
71 errno = 0;
72 fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
73 if (errno) {
74 ++errors;
77 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
78 somebody invents a time machine, I think we can safely disregard
79 it. */
80 if (lease -> starts) {
81 if (lease -> starts != MAX_TIME) {
82 t = gmtime (&lease -> starts);
83 /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
84 sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
85 t -> tm_wday, t -> tm_year + 1900,
86 t -> tm_mon + 1, t -> tm_mday,
87 t -> tm_hour, t -> tm_min, t -> tm_sec);
88 } else
89 strcpy (tbuf, "never;");
90 errno = 0;
91 fprintf (db_file, "\n starts %s", tbuf);
92 if (errno) {
93 ++errors;
97 if (lease -> ends) {
98 if (lease -> ends != MAX_TIME) {
99 t = gmtime (&lease -> ends);
100 /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
101 sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
102 t -> tm_wday, t -> tm_year + 1900,
103 t -> tm_mon + 1, t -> tm_mday,
104 t -> tm_hour, t -> tm_min, t -> tm_sec);
105 } else
106 strcpy (tbuf, "never;");
107 errno = 0;
108 fprintf (db_file, "\n ends %s", tbuf);
109 if (errno) {
110 ++errors;
114 if (lease -> tstp) {
115 t = gmtime (&lease -> tstp);
116 errno = 0;
117 fprintf (db_file, "\n tstp %d %d/%02d/%02d %02d:%02d:%02d;",
118 t -> tm_wday, t -> tm_year + 1900,
119 t -> tm_mon + 1, t -> tm_mday,
120 t -> tm_hour, t -> tm_min, t -> tm_sec);
121 if (errno) {
122 ++errors;
125 if (lease -> tsfp) {
126 t = gmtime (&lease -> tsfp);
127 errno = 0;
128 fprintf (db_file, "\n tsfp %d %d/%02d/%02d %02d:%02d:%02d;",
129 t -> tm_wday, t -> tm_year + 1900,
130 t -> tm_mon + 1, t -> tm_mday,
131 t -> tm_hour, t -> tm_min, t -> tm_sec);
132 if (errno) {
133 ++errors;
136 if (lease -> cltt) {
137 t = gmtime (&lease -> cltt);
138 errno = 0;
139 fprintf (db_file, "\n cltt %d %d/%02d/%02d %02d:%02d:%02d;",
140 t -> tm_wday, t -> tm_year + 1900,
141 t -> tm_mon + 1, t -> tm_mday,
142 t -> tm_hour, t -> tm_min, t -> tm_sec);
143 if (errno) {
144 ++errors;
148 if (lease -> binding_state == FTS_ACTIVE &&
149 (lease -> flags & BOOTP_LEASE)) {
150 fprintf (db_file, "\n binding state bootp;\n");
151 } else {
152 fprintf (db_file, "\n binding state %s;",
153 ((lease -> binding_state > 0 &&
154 lease -> binding_state <= FTS_LAST)
155 ? binding_state_names [lease -> binding_state - 1]
156 : "abandoned"));
159 if (lease -> binding_state != lease -> next_binding_state) {
160 if (lease -> next_binding_state == FTS_ACTIVE &&
161 (lease -> flags & BOOTP_LEASE))
162 fprintf (db_file, "\n next binding state bootp;\n");
163 else
164 fprintf (db_file, "\n next binding state %s;",
165 ((lease -> next_binding_state > 0 &&
166 lease -> next_binding_state <= FTS_LAST)
167 ? (binding_state_names
168 [lease -> next_binding_state - 1])
169 : "abandoned"));
172 /* If this lease is billed to a class and is still valid,
173 write it out. */
174 if (lease -> billing_class && lease -> ends > cur_time) {
175 if (!write_billing_class (lease -> billing_class)) {
176 log_error ("unable to write class %s",
177 lease -> billing_class -> name);
178 ++errors;
182 if (lease -> hardware_addr.hlen) {
183 errno = 0;
184 fprintf (db_file, "\n hardware %s %s;",
185 hardware_types [lease -> hardware_addr.hbuf [0]],
186 print_hw_addr (lease -> hardware_addr.hbuf [0],
187 lease -> hardware_addr.hlen - 1,
188 &lease -> hardware_addr.hbuf [1]));
189 if (errno) {
190 ++errors;
193 if (lease -> uid_len) {
194 int i;
195 s = quotify_buf (lease -> uid, lease -> uid_len, MDL);
196 if (s) {
197 fprintf (db_file, "\n uid \"%s\";", s);
198 if (errno)
199 ++errors;
200 dfree (s, MDL);
201 } else
202 ++errors;
204 if (lease -> scope) {
205 for (b = lease -> scope -> bindings; b; b = b -> next) {
206 if (!b -> value)
207 continue;
208 if (b -> value -> type == binding_data) {
209 if (b -> value -> value.data.data) {
210 s = quotify_buf (b -> value -> value.data.data,
211 b -> value -> value.data.len, MDL);
212 if (s) {
213 errno = 0;
214 fprintf (db_file, "\n set %s = \"%s\";",
215 b -> name, s);
216 if (errno)
217 ++errors;
218 dfree (s, MDL);
219 } else
220 ++errors;
222 } else if (b -> value -> type == binding_numeric) {
223 errno = 0;
224 fprintf (db_file, "\n set %s = %%%ld;",
225 b -> name, b -> value -> value.intval);
226 if (errno)
227 ++errors;
228 } else if (b -> value -> type == binding_boolean) {
229 errno = 0;
230 fprintf (db_file, "\n set %s = %s;",
231 b -> name,
232 b -> value -> value.intval ? "true" : "false");
233 if (errno)
234 ++errors;
235 } else if (b -> value -> type == binding_dns) {
236 log_error ("%s: persistent dns values not supported.",
237 b -> name);
238 } else if (b -> value -> type == binding_function) {
239 log_error ("%s: persistent functions not supported.",
240 b -> name);
241 } else {
242 log_error ("%s: unknown binding type %d",
243 b -> name, b -> value -> type);
247 if (lease -> agent_options) {
248 struct option_cache *oc;
249 struct data_string ds;
250 pair p;
252 memset (&ds, 0, sizeof ds);
253 for (p = lease -> agent_options -> first; p; p = p -> cdr) {
254 oc = (struct option_cache *)p -> car;
255 if (oc -> data.len) {
256 errno = 0;
257 fprintf (db_file, "\n option agent.%s %s;",
258 oc -> option -> name,
259 pretty_print_option (oc -> option, oc -> data.data,
260 oc -> data.len, 1, 1));
261 if (errno)
262 ++errors;
266 if (lease -> client_hostname &&
267 db_printable (lease -> client_hostname)) {
268 s = quotify_string (lease -> client_hostname, MDL);
269 if (s) {
270 errno = 0;
271 fprintf (db_file, "\n client-hostname \"%s\";", s);
272 if (errno)
273 ++errors;
274 dfree (s, MDL);
275 } else
276 ++errors;
278 if (lease -> on_expiry) {
279 errno = 0;
280 fprintf (db_file, "\n on expiry%s {",
281 lease -> on_expiry == lease -> on_release
282 ? " or release" : "");
283 if (errno)
284 ++errors;
285 write_statements (db_file, lease -> on_expiry, 4);
286 /* XXX */
287 fprintf (db_file, "\n }");
289 if (lease -> on_release && lease -> on_release != lease -> on_expiry) {
290 errno = 0;
291 fprintf (db_file, "\n on release {");
292 if (errno)
293 ++errors;
294 write_statements (db_file, lease -> on_release, 4);
295 /* XXX */
296 fprintf (db_file, "\n }");
298 errno = 0;
299 fputs ("\n}\n", db_file);
300 if (errno) {
301 ++errors;
303 if (errors)
304 log_info ("write_lease: unable to write lease %s",
305 piaddr (lease -> ip_addr));
306 if (errors)
307 lease_file_is_corrupt = 1;
308 return !errors;
311 int write_host (host)
312 struct host_decl *host;
314 int errors = 0;
315 int i;
316 struct data_string ip_addrs;
318 /* If the lease file is corrupt, don't try to write any more leases
319 until we've written a good lease file. */
320 if (lease_file_is_corrupt)
321 if (!new_lease_file ())
322 return 0;
324 if (!db_printable (host -> name))
325 return 0;
327 if (counting)
328 ++count;
329 errno = 0;
331 fprintf (db_file, "host %s {", host -> name);
332 if (errno) {
333 ++errors;
336 if (host -> flags & HOST_DECL_DYNAMIC) {
337 errno = 0;
338 fprintf (db_file, "\n dynamic;");
339 if (errno)
340 ++errors;
343 if (host -> flags & HOST_DECL_DELETED) {
344 errno = 0;
345 fprintf (db_file, "\n deleted;");
346 if (errno)
347 ++errors;
348 } else {
349 if (host -> interface.hlen) {
350 errno = 0;
351 fprintf (db_file, "\n hardware %s %s;",
352 hardware_types [host -> interface.hbuf [0]],
353 print_hw_addr (host -> interface.hbuf [0],
354 host -> interface.hlen - 1,
355 &host -> interface.hbuf [1]));
356 if (errno) {
357 ++errors;
360 if (host -> client_identifier.len) {
361 int i;
362 errno = 0;
363 if (db_printable_len (host -> client_identifier.data,
364 host -> client_identifier.len)) {
365 fprintf (db_file, "\n uid \"%.*s\";",
366 (int)host -> client_identifier.len,
367 host -> client_identifier.data);
368 } else {
369 fprintf (db_file,
370 "\n uid %2.2x",
371 host -> client_identifier.data [0]);
372 if (errno) {
373 ++errors;
375 for (i = 1;
376 i < host -> client_identifier.len; i++) {
377 errno = 0;
378 fprintf (db_file, ":%2.2x",
379 host ->
380 client_identifier.data [i]);
381 if (errno) {
382 ++errors;
385 putc (';', db_file);
389 memset (&ip_addrs, 0, sizeof ip_addrs);
390 if (host -> fixed_addr &&
391 evaluate_option_cache (&ip_addrs, (struct packet *)0,
392 (struct lease *)0,
393 (struct client_state *)0,
394 (struct option_state *)0,
395 (struct option_state *)0,
396 &global_scope,
397 host -> fixed_addr, MDL)) {
399 errno = 0;
400 fprintf (db_file, "\n fixed-address ");
401 if (errno) {
402 ++errors;
404 for (i = 0; i < ip_addrs.len - 3; i += 4) {
405 errno = 0;
406 fprintf (db_file, "%u.%u.%u.%u%s",
407 ip_addrs.data [i] & 0xff,
408 ip_addrs.data [i + 1] & 0xff,
409 ip_addrs.data [i + 2] & 0xff,
410 ip_addrs.data [i + 3] & 0xff,
411 i + 7 < ip_addrs.len ? "," : "");
412 if (errno) {
413 ++errors;
416 errno = 0;
417 fputc (';', db_file);
418 if (errno) {
419 ++errors;
423 if (host -> named_group) {
424 errno = 0;
425 fprintf (db_file, "\n group \"%s\";",
426 host -> named_group -> name);
427 if (errno) {
428 ++errors;
432 if (host -> group &&
433 (!host -> named_group ||
434 host -> group != host -> named_group -> group) &&
435 host -> group != root_group) {
436 errno = 0;
437 write_statements (db_file,
438 host -> group -> statements, 8);
439 if (errno) {
440 ++errors;
445 errno = 0;
446 fputs ("\n}\n", db_file);
447 if (errno) {
448 ++errors;
450 if (errors) {
451 log_info ("write_host: unable to write host %s",
452 host -> name);
453 lease_file_is_corrupt = 1;
455 return !errors;
458 int write_group (group)
459 struct group_object *group;
461 int errors = 0;
462 int i;
464 /* If the lease file is corrupt, don't try to write any more leases
465 until we've written a good lease file. */
466 if (lease_file_is_corrupt)
467 if (!new_lease_file ())
468 return 0;
470 if (!db_printable (group -> name))
471 return 0;
473 if (counting)
474 ++count;
475 errno = 0;
477 fprintf (db_file, "group %s {", group -> name);
478 if (errno) {
479 ++errors;
482 if (group -> flags & GROUP_OBJECT_DYNAMIC) {
483 errno = 0;
484 fprintf (db_file, "\n dynamic;");
485 if (errno)
486 ++errors;
489 if (group -> flags & GROUP_OBJECT_STATIC) {
490 errno = 0;
491 fprintf (db_file, "\n static;");
492 if (errno)
493 ++errors;
496 if (group -> flags & GROUP_OBJECT_DELETED) {
497 errno = 0;
498 fprintf (db_file, "\n deleted;");
499 if (errno)
500 ++errors;
501 } else {
502 if (group -> group) {
503 errno = 0;
504 write_statements (db_file,
505 group -> group -> statements, 8);
506 if (errno) {
507 ++errors;
512 errno = 0;
513 fputs ("\n}\n", db_file);
514 if (errno) {
515 ++errors;
517 if (errors) {
518 log_info ("write_group: unable to write group %s",
519 group -> name);
520 lease_file_is_corrupt = 1;
522 return !errors;
525 #if defined (FAILOVER_PROTOCOL)
526 int write_failover_state (dhcp_failover_state_t *state)
528 struct tm *t;
529 int errors = 0;
531 if (lease_file_is_corrupt)
532 if (!new_lease_file ())
533 return 0;
535 errno = 0;
536 fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
537 if (errno)
538 ++errors;
540 t = gmtime (&state -> me.stos);
541 errno = 0;
542 fprintf (db_file, "\n my state %s at %d %d/%02d/%02d %02d:%02d:%02d;",
543 /* Never record our state as "startup"! */
544 (state -> me.state == startup
545 ? dhcp_failover_state_name_print (state -> saved_state)
546 : dhcp_failover_state_name_print (state -> me.state)),
547 t -> tm_wday, t -> tm_year + 1900,
548 t -> tm_mon + 1, t -> tm_mday,
549 t -> tm_hour, t -> tm_min, t -> tm_sec);
550 if (errno)
551 ++errors;
553 t = gmtime (&state -> partner.stos);
554 errno = 0;
555 fprintf (db_file,
556 "\n partner state %s at %d %d/%02d/%02d %02d:%02d:%02d;",
557 dhcp_failover_state_name_print (state -> partner.state),
558 t -> tm_wday, t -> tm_year + 1900,
559 t -> tm_mon + 1, t -> tm_mday,
560 t -> tm_hour, t -> tm_min, t -> tm_sec);
561 if (errno)
562 ++errors;
564 if (state -> i_am == secondary) {
565 errno = 0;
566 fprintf (db_file, "\n mclt %ld;",
567 (unsigned long)state -> mclt);
568 if (errno)
569 ++errors;
571 fprintf (db_file, "\n}\n");
572 if (errno)
573 ++errors;
575 if (errors) {
576 log_info ("write_failover_state: unable to write state %s",
577 state -> name);
578 lease_file_is_corrupt = 1;
579 return 0;
581 return 1;
584 #endif
586 int db_printable (s)
587 const char *s;
589 int i;
590 for (i = 0; s [i]; i++)
591 if (!isascii (s [i]) || !isprint (s [i])
592 || s [i] == '"' || s [i] == '\\')
593 return 0;
594 return 1;
597 int db_printable_len (s, len)
598 const unsigned char *s;
599 unsigned len;
601 int i;
602 for (i = 0; i < len; i++)
603 if (!isascii (s [i]) || !isprint (s [i]) ||
604 s [i] == '"' || s [i] == '\\')
605 return 0;
606 return 1;
609 void write_named_billing_class (const char *name, unsigned len,
610 struct class *class)
612 /* XXX billing classes that are modified by OMAPI need
613 XXX to be detected and written out here. */
616 void write_billing_classes ()
618 struct collection *lp;
619 struct class *cp;
620 struct hash_bucket *bp;
621 int i;
623 for (lp = collections; lp; lp = lp -> next) {
624 for (cp = lp -> classes; cp; cp = cp -> nic) {
625 if (cp -> spawning && cp -> hash) {
626 class_hash_foreach (cp -> hash, write_named_billing_class);
632 /* Write a spawned class to the database file. */
634 int write_billing_class (class)
635 struct class *class;
637 int errors = 0;
638 int i;
640 if (lease_file_is_corrupt)
641 if (!new_lease_file ())
642 return 0;
644 if (!class -> superclass) {
645 errno = 0;
646 fprintf (db_file, "\n billing class \"%s\";", class -> name);
647 return !errno;
650 errno = 0;
651 fprintf (db_file, "\n billing subclass \"%s\"",
652 class -> superclass -> name);
653 if (errno)
654 ++errors;
656 for (i = 0; i < class -> hash_string.len; i++)
657 if (!isascii (class -> hash_string.data [i]) ||
658 !isprint (class -> hash_string.data [i]))
659 break;
660 if (i == class -> hash_string.len) {
661 errno = 0;
662 fprintf (db_file, " \"%.*s\";",
663 (int)class -> hash_string.len,
664 class -> hash_string.data);
665 if (errno)
666 ++errors;
667 } else {
668 errno = 0;
669 fprintf (db_file, " %2.2x", class -> hash_string.data [0]);
670 if (errno)
671 ++errors;
672 for (i = 1; i < class -> hash_string.len; i++) {
673 errno = 0;
674 fprintf (db_file, ":%2.2x",
675 class -> hash_string.data [i]);
676 if (errno)
677 ++errors;
679 errno = 0;
680 fprintf (db_file, ";");
681 if (errno)
682 ++errors;
685 class -> dirty = !errors;
686 if (errors)
687 lease_file_is_corrupt = 1;
688 return !errors;
691 /* Commit leases after a timeout. */
692 void commit_leases_timeout (void *foo)
694 commit_leases ();
697 /* Commit any leases that have been written out... */
699 int commit_leases ()
701 /* Commit any outstanding writes to the lease database file.
702 We need to do this even if we're rewriting the file below,
703 just in case the rewrite fails. */
704 if (fflush (db_file) == EOF) {
705 log_info ("commit_leases: unable to commit: %m");
706 return 0;
708 #ifndef FSYNC_MISSING
709 if (fsync (fileno (db_file)) < 0) {
710 log_info ("commit_leases: unable to commit: %m");
711 return 0;
713 #endif
715 /* If we haven't rewritten the lease database in over an
716 hour, rewrite it now. (The length of time should probably
717 be configurable. */
718 if (count && cur_time - write_time > 3600) {
719 count = 0;
720 write_time = cur_time;
721 new_lease_file ();
723 return 1;
726 void db_startup (testp)
727 int testp;
729 isc_result_t status;
731 #if defined (TRACING)
732 if (!trace_playback ()) {
733 #endif
734 /* Read in the existing lease file... */
735 status = read_conf_file (path_dhcpd_db,
736 (struct group *)0, 0, 1);
737 /* XXX ignore status? */
738 #if defined (TRACING)
740 #endif
742 #if defined (TRACING)
743 /* If we're playing back, there is no lease file, so we can't
744 append it, so we create one immediately (maybe this isn't
745 the best solution... */
746 if (trace_playback ()) {
747 new_lease_file ();
749 #endif
750 if (!testp) {
751 db_file = fopen (path_dhcpd_db, "a");
752 if (!db_file)
753 log_fatal ("Can't open %s for append.", path_dhcpd_db);
754 expire_all_pools ();
755 #if defined (TRACING)
756 if (trace_playback ())
757 write_time = cur_time;
758 else
759 #endif
760 GET_TIME (&write_time);
761 new_lease_file ();
765 int new_lease_file ()
767 char newfname [512];
768 char backfname [512];
769 TIME t;
770 int db_fd;
772 /* If we already have an open database, close it. */
773 if (db_file) {
774 fclose (db_file);
775 db_file = (FILE *)0;
778 /* Make a temporary lease file... */
779 GET_TIME (&t);
781 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
782 * This should never happen since the path is a configuration
783 * variable from build-time or command-line. But if it should,
784 * either by malice or ignorance, we panic, since the potential
785 * for havoc is high.
787 if (snprintf (newfname, sizeof newfname, "%s.%d",
788 path_dhcpd_db, (int)t) >= sizeof newfname)
789 log_fatal("new_lease_file: lease file path too long");
791 db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
792 if (db_fd < 0) {
793 log_error ("Can't create new lease file: %m");
794 return 0;
796 if ((db_file = fdopen (db_fd, "w")) == NULL) {
797 log_error ("Can't fdopen new lease file!");
798 goto fail;
801 /* Write an introduction so people don't complain about time
802 being off. */
803 errno = 0;
804 fprintf (db_file, "# All times in this file are in UTC (GMT), not %s",
805 "your local timezone. This is\n");
806 if (errno != 0)
807 goto fail;
808 fprintf (db_file, "# not a bug, so please don't ask about it. %s",
809 "There is no portable way to\n");
810 if (errno != 0)
811 goto fail;
812 fprintf (db_file, "# store leases in the local timezone, so please %s",
813 "don't request this as a\n");
814 if (errno != 0)
815 goto fail;
816 fprintf (db_file, "# feature. If this is inconvenient or %s",
817 "confusing to you, we sincerely\n");
818 if (errno != 0)
819 goto fail;
820 fprintf (db_file, "# apologize. Seriously, though - don't ask.\n");
821 if (errno != 0)
822 goto fail;
823 fprintf (db_file, "# The format of this file is documented in the %s",
824 "dhcpd.leases(5) manual page.\n");
825 if (errno != 0)
826 goto fail;
827 fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
828 DHCP_VERSION);
829 if (errno != 0)
830 goto fail;
832 /* Write out all the leases that we know of... */
833 counting = 0;
834 if (!write_leases ())
835 goto fail;
837 #if defined (TRACING)
838 if (!trace_playback ()) {
839 #endif
840 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
841 * This should never happen since the path is a configuration
842 * variable from build-time or command-line. But if it should,
843 * either by malice or ignorance, we panic, since the potential
844 * for havoc is too high.
846 if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
847 >= sizeof backfname)
848 log_fatal("new_lease_file: backup lease file path too long");
850 /* Get the old database out of the way... */
851 if (unlink (backfname) < 0 && errno != ENOENT) {
852 log_error ("Can't remove old lease database backup %s: %m",
853 backfname);
854 goto fail;
856 if (rename (path_dhcpd_db, backfname) < 0) {
857 log_error ("Can't backup lease database %s to %s: %m",
858 path_dhcpd_db, backfname);
859 goto fail;
861 #if defined (TRACING)
863 #endif
865 /* Move in the new file... */
866 if (rename (newfname, path_dhcpd_db) < 0) {
867 log_error ("Can't install new lease database %s to %s: %m",
868 newfname, path_dhcpd_db);
869 goto fail;
872 counting = 1;
873 lease_file_is_corrupt = 0;
874 return 1;
876 fail:
877 unlink (newfname);
878 lease_file_is_corrupt = 1;
879 return 0;
882 int group_writer (struct group_object *group)
884 if (!write_group (group))
885 return 0;
886 if (!commit_leases ())
887 return 0;
888 return 1;