Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / dhcp / server / db.c
blob684702ffafd777d22d6e1eec338436eb5d463d73
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: db.c,v 1.6 2005/08/11 17:13:30 drochner Exp $ 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 struct binding *b;
60 char *s;
62 /* If the lease file is corrupt, don't try to write any more leases
63 until we've written a good lease file. */
64 if (lease_file_is_corrupt)
65 if (!new_lease_file ())
66 return 0;
68 if (counting)
69 ++count;
70 errno = 0;
71 fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
72 if (errno) {
73 ++errors;
76 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
77 somebody invents a time machine, I think we can safely disregard
78 it. */
79 if (lease -> starts) {
80 if (lease -> starts != MAX_TIME) {
81 t = gmtime (&lease -> starts);
82 /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
83 sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
84 t -> tm_wday, t -> tm_year + 1900,
85 t -> tm_mon + 1, t -> tm_mday,
86 t -> tm_hour, t -> tm_min, t -> tm_sec);
87 } else
88 strcpy (tbuf, "never;");
89 errno = 0;
90 fprintf (db_file, "\n starts %s", tbuf);
91 if (errno) {
92 ++errors;
96 if (lease -> ends) {
97 if (lease -> ends != MAX_TIME) {
98 t = gmtime (&lease -> ends);
99 /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
100 sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
101 t -> tm_wday, t -> tm_year + 1900,
102 t -> tm_mon + 1, t -> tm_mday,
103 t -> tm_hour, t -> tm_min, t -> tm_sec);
104 } else
105 strcpy (tbuf, "never;");
106 errno = 0;
107 fprintf (db_file, "\n ends %s", tbuf);
108 if (errno) {
109 ++errors;
113 if (lease -> tstp) {
114 t = gmtime (&lease -> tstp);
115 errno = 0;
116 fprintf (db_file, "\n tstp %d %d/%02d/%02d %02d:%02d:%02d;",
117 t -> tm_wday, t -> tm_year + 1900,
118 t -> tm_mon + 1, t -> tm_mday,
119 t -> tm_hour, t -> tm_min, t -> tm_sec);
120 if (errno) {
121 ++errors;
124 if (lease -> tsfp) {
125 t = gmtime (&lease -> tsfp);
126 errno = 0;
127 fprintf (db_file, "\n tsfp %d %d/%02d/%02d %02d:%02d:%02d;",
128 t -> tm_wday, t -> tm_year + 1900,
129 t -> tm_mon + 1, t -> tm_mday,
130 t -> tm_hour, t -> tm_min, t -> tm_sec);
131 if (errno) {
132 ++errors;
135 if (lease -> cltt) {
136 t = gmtime (&lease -> cltt);
137 errno = 0;
138 fprintf (db_file, "\n cltt %d %d/%02d/%02d %02d:%02d:%02d;",
139 t -> tm_wday, t -> tm_year + 1900,
140 t -> tm_mon + 1, t -> tm_mday,
141 t -> tm_hour, t -> tm_min, t -> tm_sec);
142 if (errno) {
143 ++errors;
147 if (lease -> binding_state == FTS_ACTIVE &&
148 (lease -> flags & BOOTP_LEASE)) {
149 fprintf (db_file, "\n binding state bootp;\n");
150 } else {
151 fprintf (db_file, "\n binding state %s;",
152 ((lease -> binding_state > 0 &&
153 lease -> binding_state <= FTS_LAST)
154 ? binding_state_names [lease -> binding_state - 1]
155 : "abandoned"));
158 if (lease -> binding_state != lease -> next_binding_state) {
159 if (lease -> next_binding_state == FTS_ACTIVE &&
160 (lease -> flags & BOOTP_LEASE))
161 fprintf (db_file, "\n next binding state bootp;\n");
162 else
163 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"));
171 /* If this lease is billed to a class and is still valid,
172 write it out. */
173 if (lease -> billing_class && lease -> ends > cur_time) {
174 if (!write_billing_class (lease -> billing_class)) {
175 log_error ("unable to write class %s",
176 lease -> billing_class -> name);
177 ++errors;
181 if (lease -> hardware_addr.hlen) {
182 errno = 0;
183 fprintf (db_file, "\n hardware %s %s;",
184 hardware_types [lease -> hardware_addr.hbuf [0]],
185 print_hw_addr (lease -> hardware_addr.hbuf [0],
186 lease -> hardware_addr.hlen - 1,
187 &lease -> hardware_addr.hbuf [1]));
188 if (errno) {
189 ++errors;
192 if (lease -> uid_len) {
193 s = quotify_buf (lease -> uid, lease -> uid_len, MDL);
194 if (s) {
195 fprintf (db_file, "\n uid \"%s\";", s);
196 if (errno)
197 ++errors;
198 dfree (s, MDL);
199 } else
200 ++errors;
202 if (lease -> scope) {
203 for (b = lease -> scope -> bindings; b; b = b -> next) {
204 if (!b -> value)
205 continue;
206 if (b -> value -> type == binding_data) {
207 if (b -> value -> value.data.data) {
208 s = quotify_buf (b -> value -> value.data.data,
209 b -> value -> value.data.len, MDL);
210 if (s) {
211 errno = 0;
212 fprintf (db_file, "\n set %s = \"%s\";",
213 b -> name, s);
214 if (errno)
215 ++errors;
216 dfree (s, MDL);
217 } else
218 ++errors;
220 } else if (b -> value -> type == binding_numeric) {
221 errno = 0;
222 fprintf (db_file, "\n set %s = %%%ld;",
223 b -> name, b -> value -> value.intval);
224 if (errno)
225 ++errors;
226 } else if (b -> value -> type == binding_boolean) {
227 errno = 0;
228 fprintf (db_file, "\n set %s = %s;",
229 b -> name,
230 b -> value -> value.intval ? "true" : "false");
231 if (errno)
232 ++errors;
233 } else if (b -> value -> type == binding_dns) {
234 log_error ("%s: persistent dns values not supported.",
235 b -> name);
236 } else if (b -> value -> type == binding_function) {
237 log_error ("%s: persistent functions not supported.",
238 b -> name);
239 } else {
240 log_error ("%s: unknown binding type %d",
241 b -> name, b -> value -> type);
245 if (lease -> agent_options) {
246 struct option_cache *oc;
247 struct data_string ds;
248 pair p;
250 memset (&ds, 0, sizeof ds);
251 for (p = lease -> agent_options -> first; p; p = p -> cdr) {
252 oc = (struct option_cache *)p -> car;
253 if (oc -> data.len) {
254 errno = 0;
255 fprintf (db_file, "\n option agent.%s %s;",
256 oc -> option -> name,
257 pretty_print_option (oc -> option, oc -> data.data,
258 oc -> data.len, 1, 1));
259 if (errno)
260 ++errors;
264 if (lease -> client_hostname &&
265 db_printable (lease -> client_hostname)) {
266 s = quotify_string (lease -> client_hostname, MDL);
267 if (s) {
268 errno = 0;
269 fprintf (db_file, "\n client-hostname \"%s\";", s);
270 if (errno)
271 ++errors;
272 dfree (s, MDL);
273 } else
274 ++errors;
276 if (lease -> on_expiry) {
277 errno = 0;
278 fprintf (db_file, "\n on expiry%s {",
279 lease -> on_expiry == lease -> on_release
280 ? " or release" : "");
281 if (errno)
282 ++errors;
283 write_statements (db_file, lease -> on_expiry, 4);
284 /* XXX */
285 fprintf (db_file, "\n }");
287 if (lease -> on_release && lease -> on_release != lease -> on_expiry) {
288 errno = 0;
289 fprintf (db_file, "\n on release {");
290 if (errno)
291 ++errors;
292 write_statements (db_file, lease -> on_release, 4);
293 /* XXX */
294 fprintf (db_file, "\n }");
296 errno = 0;
297 fputs ("\n}\n", db_file);
298 if (errno) {
299 ++errors;
301 if (errors)
302 log_info ("write_lease: unable to write lease %s",
303 piaddr (lease -> ip_addr));
304 if (errors)
305 lease_file_is_corrupt = 1;
306 return !errors;
309 int write_host (host)
310 struct host_decl *host;
312 int errors = 0;
313 int i;
314 struct data_string ip_addrs;
316 /* If the lease file is corrupt, don't try to write any more leases
317 until we've written a good lease file. */
318 if (lease_file_is_corrupt)
319 if (!new_lease_file ())
320 return 0;
322 if (!db_printable (host -> name))
323 return 0;
325 if (counting)
326 ++count;
327 errno = 0;
329 fprintf (db_file, "host %s {", host -> name);
330 if (errno) {
331 ++errors;
334 if (host -> flags & HOST_DECL_DYNAMIC) {
335 errno = 0;
336 fprintf (db_file, "\n dynamic;");
337 if (errno)
338 ++errors;
341 if (host -> flags & HOST_DECL_DELETED) {
342 errno = 0;
343 fprintf (db_file, "\n deleted;");
344 if (errno)
345 ++errors;
346 } else {
347 if (host -> interface.hlen) {
348 errno = 0;
349 fprintf (db_file, "\n hardware %s %s;",
350 hardware_types [host -> interface.hbuf [0]],
351 print_hw_addr (host -> interface.hbuf [0],
352 host -> interface.hlen - 1,
353 &host -> interface.hbuf [1]));
354 if (errno) {
355 ++errors;
358 if (host -> client_identifier.len) {
359 int i;
360 errno = 0;
361 if (db_printable_len (host -> client_identifier.data,
362 host -> client_identifier.len)) {
363 fprintf (db_file, "\n uid \"%.*s\";",
364 (int)host -> client_identifier.len,
365 host -> client_identifier.data);
366 } else {
367 fprintf (db_file,
368 "\n uid %2.2x",
369 host -> client_identifier.data [0]);
370 if (errno) {
371 ++errors;
373 for (i = 1;
374 i < host -> client_identifier.len; i++) {
375 errno = 0;
376 fprintf (db_file, ":%2.2x",
377 host ->
378 client_identifier.data [i]);
379 if (errno) {
380 ++errors;
383 putc (';', db_file);
387 memset (&ip_addrs, 0, sizeof ip_addrs);
388 if (host -> fixed_addr &&
389 evaluate_option_cache (&ip_addrs, (struct packet *)0,
390 (struct lease *)0,
391 (struct client_state *)0,
392 (struct option_state *)0,
393 (struct option_state *)0,
394 &global_scope,
395 host -> fixed_addr, MDL)) {
397 errno = 0;
398 fprintf (db_file, "\n fixed-address ");
399 if (errno) {
400 ++errors;
402 for (i = 0; i < ip_addrs.len - 3; i += 4) {
403 errno = 0;
404 fprintf (db_file, "%u.%u.%u.%u%s",
405 ip_addrs.data [i] & 0xff,
406 ip_addrs.data [i + 1] & 0xff,
407 ip_addrs.data [i + 2] & 0xff,
408 ip_addrs.data [i + 3] & 0xff,
409 i + 7 < ip_addrs.len ? "," : "");
410 if (errno) {
411 ++errors;
414 errno = 0;
415 fputc (';', db_file);
416 if (errno) {
417 ++errors;
421 if (host -> named_group) {
422 errno = 0;
423 fprintf (db_file, "\n group \"%s\";",
424 host -> named_group -> name);
425 if (errno) {
426 ++errors;
430 if (host -> group &&
431 (!host -> named_group ||
432 host -> group != host -> named_group -> group) &&
433 host -> group != root_group) {
434 errno = 0;
435 write_statements (db_file,
436 host -> group -> statements, 8);
437 if (errno) {
438 ++errors;
443 errno = 0;
444 fputs ("\n}\n", db_file);
445 if (errno) {
446 ++errors;
448 if (errors) {
449 log_info ("write_host: unable to write host %s",
450 host -> name);
451 lease_file_is_corrupt = 1;
453 return !errors;
456 int write_group (group)
457 struct group_object *group;
459 int errors = 0;
461 /* If the lease file is corrupt, don't try to write any more leases
462 until we've written a good lease file. */
463 if (lease_file_is_corrupt)
464 if (!new_lease_file ())
465 return 0;
467 if (!db_printable (group -> name))
468 return 0;
470 if (counting)
471 ++count;
472 errno = 0;
474 fprintf (db_file, "group %s {", group -> name);
475 if (errno) {
476 ++errors;
479 if (group -> flags & GROUP_OBJECT_DYNAMIC) {
480 errno = 0;
481 fprintf (db_file, "\n dynamic;");
482 if (errno)
483 ++errors;
486 if (group -> flags & GROUP_OBJECT_STATIC) {
487 errno = 0;
488 fprintf (db_file, "\n static;");
489 if (errno)
490 ++errors;
493 if (group -> flags & GROUP_OBJECT_DELETED) {
494 errno = 0;
495 fprintf (db_file, "\n deleted;");
496 if (errno)
497 ++errors;
498 } else {
499 if (group -> group) {
500 errno = 0;
501 write_statements (db_file,
502 group -> group -> statements, 8);
503 if (errno) {
504 ++errors;
509 errno = 0;
510 fputs ("\n}\n", db_file);
511 if (errno) {
512 ++errors;
514 if (errors) {
515 log_info ("write_group: unable to write group %s",
516 group -> name);
517 lease_file_is_corrupt = 1;
519 return !errors;
522 #if defined (FAILOVER_PROTOCOL)
523 int write_failover_state (dhcp_failover_state_t *state)
525 struct tm *t;
526 int errors = 0;
528 if (lease_file_is_corrupt)
529 if (!new_lease_file ())
530 return 0;
532 errno = 0;
533 fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
534 if (errno)
535 ++errors;
537 t = gmtime (&state -> me.stos);
538 errno = 0;
539 fprintf (db_file, "\n my state %s at %d %d/%02d/%02d %02d:%02d:%02d;",
540 /* Never record our state as "startup"! */
541 (state -> me.state == startup
542 ? dhcp_failover_state_name_print (state -> saved_state)
543 : dhcp_failover_state_name_print (state -> me.state)),
544 t -> tm_wday, t -> tm_year + 1900,
545 t -> tm_mon + 1, t -> tm_mday,
546 t -> tm_hour, t -> tm_min, t -> tm_sec);
547 if (errno)
548 ++errors;
550 t = gmtime (&state -> partner.stos);
551 errno = 0;
552 fprintf (db_file,
553 "\n partner state %s at %d %d/%02d/%02d %02d:%02d:%02d;",
554 dhcp_failover_state_name_print (state -> partner.state),
555 t -> tm_wday, t -> tm_year + 1900,
556 t -> tm_mon + 1, t -> tm_mday,
557 t -> tm_hour, t -> tm_min, t -> tm_sec);
558 if (errno)
559 ++errors;
561 if (state -> i_am == secondary) {
562 errno = 0;
563 fprintf (db_file, "\n mclt %ld;",
564 (unsigned long)state -> mclt);
565 if (errno)
566 ++errors;
568 fprintf (db_file, "\n}\n");
569 if (errno)
570 ++errors;
572 if (errors) {
573 log_info ("write_failover_state: unable to write state %s",
574 state -> name);
575 lease_file_is_corrupt = 1;
576 return 0;
578 return 1;
581 #endif
583 int db_printable (s)
584 const char *s;
586 int i;
587 for (i = 0; s [i]; i++)
588 if (!isascii (s [i]) || !isprint ((unsigned char)s [i])
589 || s [i] == '"' || s [i] == '\\')
590 return 0;
591 return 1;
594 int db_printable_len (s, len)
595 const unsigned char *s;
596 unsigned len;
598 int i;
599 for (i = 0; i < len; i++)
600 if (!isascii (s [i]) || !isprint (s [i]) ||
601 s [i] == '"' || s [i] == '\\')
602 return 0;
603 return 1;
606 void write_named_billing_class (const char *name, unsigned len,
607 struct class *class)
609 /* XXX billing classes that are modified by OMAPI need
610 XXX to be detected and written out here. */
613 void write_billing_classes ()
615 struct collection *lp;
616 struct class *cp;
618 for (lp = collections; lp; lp = lp -> next) {
619 for (cp = lp -> classes; cp; cp = cp -> nic) {
620 if (cp -> spawning && cp -> hash) {
621 class_hash_foreach (cp -> hash, write_named_billing_class);
627 /* Write a spawned class to the database file. */
629 int write_billing_class (class)
630 struct class *class;
632 int errors = 0;
633 int i;
635 if (lease_file_is_corrupt)
636 if (!new_lease_file ())
637 return 0;
639 if (!class -> superclass) {
640 errno = 0;
641 fprintf (db_file, "\n billing class \"%s\";", class -> name);
642 return !errno;
645 errno = 0;
646 fprintf (db_file, "\n billing subclass \"%s\"",
647 class -> superclass -> name);
648 if (errno)
649 ++errors;
651 for (i = 0; i < class -> hash_string.len; i++)
652 if (!isascii (class -> hash_string.data [i]) ||
653 !isprint (class -> hash_string.data [i]))
654 break;
655 if (i == class -> hash_string.len) {
656 errno = 0;
657 fprintf (db_file, " \"%.*s\";",
658 (int)class -> hash_string.len,
659 class -> hash_string.data);
660 if (errno)
661 ++errors;
662 } else {
663 errno = 0;
664 fprintf (db_file, " %2.2x", class -> hash_string.data [0]);
665 if (errno)
666 ++errors;
667 for (i = 1; i < class -> hash_string.len; i++) {
668 errno = 0;
669 fprintf (db_file, ":%2.2x",
670 class -> hash_string.data [i]);
671 if (errno)
672 ++errors;
674 errno = 0;
675 fprintf (db_file, ";");
676 if (errno)
677 ++errors;
680 class -> dirty = !errors;
681 if (errors)
682 lease_file_is_corrupt = 1;
683 return !errors;
686 /* Commit leases after a timeout. */
687 void commit_leases_timeout (void *foo)
689 commit_leases ();
692 /* Commit any leases that have been written out... */
694 int commit_leases ()
696 /* Commit any outstanding writes to the lease database file.
697 We need to do this even if we're rewriting the file below,
698 just in case the rewrite fails. */
699 if (fflush (db_file) == EOF) {
700 log_info ("commit_leases: unable to commit: %m");
701 return 0;
703 if (fsync (fileno (db_file)) < 0) {
704 log_info ("commit_leases: unable to commit: %m");
705 return 0;
708 /* If we haven't rewritten the lease database in over an
709 hour, rewrite it now. (The length of time should probably
710 be configurable. */
711 if (count && cur_time - write_time > 3600) {
712 count = 0;
713 write_time = cur_time;
714 new_lease_file ();
716 return 1;
719 void db_startup (testp)
720 int testp;
722 isc_result_t status;
724 #if defined (TRACING)
725 if (!trace_playback ()) {
726 #endif
727 /* Read in the existing lease file... */
728 status = read_conf_file (path_dhcpd_db,
729 (struct group *)0, 0, 1);
730 /* XXX ignore status? */
731 #if defined (TRACING)
733 #endif
735 #if defined (TRACING)
736 /* If we're playing back, there is no lease file, so we can't
737 append it, so we create one immediately (maybe this isn't
738 the best solution... */
739 if (trace_playback ()) {
740 new_lease_file ();
742 #endif
743 if (!testp) {
744 db_file = fopen (path_dhcpd_db, "a");
745 if (!db_file)
746 log_fatal ("Can't open %s for append.", path_dhcpd_db);
747 expire_all_pools ();
748 #if defined (TRACING)
749 if (trace_playback ())
750 write_time = cur_time;
751 else
752 #endif
753 GET_TIME (&write_time);
754 new_lease_file ();
758 int new_lease_file ()
760 char newfname [512];
761 char backfname [512];
762 TIME t;
763 int db_fd;
765 /* If we already have an open database, close it. */
766 if (db_file) {
767 fclose (db_file);
768 db_file = (FILE *)0;
771 /* Make a temporary lease file... */
772 GET_TIME (&t);
774 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
775 * This should never happen since the path is a configuration
776 * variable from build-time or command-line. But if it should,
777 * either by malice or ignorance, we panic, since the potential
778 * for havoc is high.
780 if (snprintf (newfname, sizeof newfname, "%s.%d",
781 path_dhcpd_db, (int)t) >= sizeof newfname)
782 log_fatal("new_lease_file: lease file path too long");
784 db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
785 if (db_fd < 0) {
786 log_error ("Can't create new lease file: %m");
787 return 0;
789 if ((db_file = fdopen (db_fd, "w")) == NULL) {
790 log_error ("Can't fdopen new lease file!");
791 goto fail;
794 /* Write an introduction so people don't complain about time
795 being off. */
796 errno = 0;
797 fprintf (db_file, "# All times in this file are in UTC (GMT), not %s",
798 "your local timezone. This is\n");
799 if (errno != 0)
800 goto fail;
801 fprintf (db_file, "# not a bug, so please don't ask about it. %s",
802 "There is no portable way to\n");
803 if (errno != 0)
804 goto fail;
805 fprintf (db_file, "# store leases in the local timezone, so please %s",
806 "don't request this as a\n");
807 if (errno != 0)
808 goto fail;
809 fprintf (db_file, "# feature. If this is inconvenient or %s",
810 "confusing to you, we sincerely\n");
811 if (errno != 0)
812 goto fail;
813 fprintf (db_file, "# apologize. Seriously, though - don't ask.\n");
814 if (errno != 0)
815 goto fail;
816 fprintf (db_file, "# The format of this file is documented in the %s",
817 "dhcpd.leases(5) manual page.\n");
818 if (errno != 0)
819 goto fail;
820 fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
821 DHCP_VERSION);
822 if (errno != 0)
823 goto fail;
825 /* Write out all the leases that we know of... */
826 counting = 0;
827 if (!write_leases ())
828 goto fail;
830 #if defined (TRACING)
831 if (!trace_playback ()) {
832 #endif
833 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
834 * This should never happen since the path is a configuration
835 * variable from build-time or command-line. But if it should,
836 * either by malice or ignorance, we panic, since the potential
837 * for havoc is too high.
839 if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
840 >= sizeof backfname)
841 log_fatal("new_lease_file: backup lease file path too long");
843 /* Get the old database out of the way... */
844 if (unlink (backfname) < 0 && errno != ENOENT) {
845 log_error ("Can't remove old lease database backup %s: %m",
846 backfname);
847 goto fail;
849 if (link (path_dhcpd_db, backfname) < 0) {
850 log_error ("Can't backup lease database %s to %s: %m",
851 path_dhcpd_db, backfname);
852 goto fail;
854 #if defined (TRACING)
856 #endif
858 /* Move in the new file... */
859 if (rename (newfname, path_dhcpd_db) < 0) {
860 log_error ("Can't install new lease database %s to %s: %m",
861 newfname, path_dhcpd_db);
862 goto fail;
865 counting = 1;
866 lease_file_is_corrupt = 0;
867 return 1;
869 fail:
870 unlink (newfname);
871 lease_file_is_corrupt = 1;
872 return 0;
875 int group_writer (struct group_object *group)
877 if (!write_group (group))
878 return 0;
879 if (!commit_leases ())
880 return 0;
881 return 1;