- Hide the following characters '(', ')', '{', '}' inside of #defines
[dragonfly.git] / contrib / dhcp-3.0 / server / db.c
1 /* db.c
2
3    Persistent database management routines for DHCPD... */
4
5 /*
6  * Copyright (c) 2004 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 #ifndef lint
36 static char copyright[] =
37 "$Id: db.c,v 1.63.2.11 2004/06/17 20:54:40 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #include "dhcpd.h"
41 #include <ctype.h>
42 #include "version.h"
43
44 FILE *db_file;
45
46 static int counting = 0;
47 static int count = 0;
48 TIME write_time;
49 int lease_file_is_corrupt = 0;
50
51 /* Write the specified lease to the current lease database file. */
52
53 int write_lease (lease)
54         struct lease *lease;
55 {
56         struct tm *t;
57         char tbuf [64];
58         int errors = 0;
59         int i;
60         struct binding *b;
61         char *s;
62
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;
68
69         if (counting)
70                 ++count;
71         errno = 0;
72         fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
73         if (errno) {
74                 ++errors;
75         }
76
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;
94                 }
95         }
96
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;
111                 }
112         }
113
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;
123                 }
124         }
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;
134                 }
135         }
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;
145                 }
146         }
147
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"));
157         }
158
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"));
170         }
171
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;
179                 }
180         }
181
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;
191                 }
192         }
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;
203         }
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;
221                     }
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);
244                 }
245             }
246         }
247         if (lease -> agent_options) {
248             struct option_cache *oc;
249             struct data_string ds;
250             pair p;
251
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;
263                 }
264             }
265         }
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;
277         }
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  }");
288         }
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  }");
297         }
298         errno = 0;
299         fputs ("\n}\n", db_file);
300         if (errno) {
301                 ++errors;
302         }
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;
309 }
310
311 int write_host (host)
312         struct host_decl *host;
313 {
314         int errors = 0;
315         int i;
316         struct data_string ip_addrs;
317
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;
323
324         if (!db_printable (host -> name))
325                 return 0;
326
327         if (counting)
328                 ++count;
329         errno = 0;
330
331         fprintf (db_file, "host %s {", host -> name);
332         if (errno) {
333                 ++errors;
334         }
335
336         if (host -> flags & HOST_DECL_DYNAMIC) {
337                 errno = 0;
338                 fprintf (db_file, "\n  dynamic;");
339                 if (errno)
340                         ++errors;
341         }
342
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;
358                         }
359                 }
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;
374                                 }
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;
383                                         }
384                                 }
385                                 putc (';', db_file);
386                         }
387                 }
388                 
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)) {
398                 
399                         errno = 0;
400                         fprintf (db_file, "\n  fixed-address ");
401                         if (errno) {
402                                 ++errors;
403                         }
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;
414                                 }
415                         }
416                         errno = 0;
417                         fputc (';', db_file);
418                         if (errno) {
419                                 ++errors;
420                         }
421                 }
422
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;
429                         }
430                 }
431
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;
441                         }
442                 }
443         }
444
445         errno = 0;
446         fputs ("\n}\n", db_file);
447         if (errno) {
448                 ++errors;
449         }
450         if (errors) {
451                 log_info ("write_host: unable to write host %s",
452                           host -> name);
453                 lease_file_is_corrupt = 1;
454         }
455         return !errors;
456 }
457
458 int write_group (group)
459         struct group_object *group;
460 {
461         int errors = 0;
462         int i;
463
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;
469
470         if (!db_printable (group -> name))
471                 return 0;
472
473         if (counting)
474                 ++count;
475         errno = 0;
476
477         fprintf (db_file, "group %s {", group -> name);
478         if (errno) {
479                 ++errors;
480         }
481
482         if (group -> flags & GROUP_OBJECT_DYNAMIC) {
483                 errno = 0;
484                 fprintf (db_file, "\n  dynamic;");
485                 if (errno)
486                         ++errors;
487         }
488
489         if (group -> flags & GROUP_OBJECT_STATIC) {
490                 errno = 0;
491                 fprintf (db_file, "\n  static;");
492                 if (errno)
493                         ++errors;
494         }
495
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;
508                         }
509                 }
510         }
511
512         errno = 0;
513         fputs ("\n}\n", db_file);
514         if (errno) {
515                 ++errors;
516         }
517         if (errors) {
518                 log_info ("write_group: unable to write group %s",
519                           group -> name);
520                 lease_file_is_corrupt = 1;
521         }
522         return !errors;
523 }
524
525 #if defined (FAILOVER_PROTOCOL)
526 int write_failover_state (dhcp_failover_state_t *state)
527 {
528         struct tm *t;
529         int errors = 0;
530
531         if (lease_file_is_corrupt)
532                 if (!new_lease_file ())
533                         return 0;
534
535         errno = 0;
536         fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
537         if (errno)
538                 ++errors;
539
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;
552
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;
563
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;
570         }
571         fprintf (db_file, "\n}\n");
572         if (errno)
573                 ++errors;
574
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;
580         }
581         return 1;
582
583 }
584 #endif
585
586 int db_printable (s)
587         const char *s;
588 {
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;
595 }
596
597 int db_printable_len (s, len)
598         const unsigned char *s;
599         unsigned len;
600 {
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;
607 }
608
609 void write_named_billing_class (const char *name, unsigned len,
610                                 struct class *class)
611 {
612         /* XXX billing classes that are modified by OMAPI need
613            XXX to be detected and written out here. */
614 }
615
616 void write_billing_classes ()
617 {
618         struct collection *lp;
619         struct class *cp;
620         struct hash_bucket *bp;
621         int i;
622
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);
627                 }
628             }
629         }
630 }
631
632 /* Write a spawned class to the database file. */
633
634 int write_billing_class (class)
635         struct class *class;
636 {
637         int errors = 0;
638         int i;
639
640         if (lease_file_is_corrupt)
641                 if (!new_lease_file ())
642                         return 0;
643
644         if (!class -> superclass) {
645                 errno = 0;
646                 fprintf (db_file, "\n  billing class \"%s\";", class -> name);
647                 return !errno;
648         }
649
650         errno = 0;
651         fprintf (db_file, "\n  billing subclass \"%s\"",
652                  class -> superclass -> name);
653         if (errno)
654                 ++errors;
655
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;
678                 }
679                 errno = 0;
680                 fprintf (db_file, ";");
681                 if (errno)
682                         ++errors;
683         }
684
685         class -> dirty = !errors;
686         if (errors)
687                 lease_file_is_corrupt = 1;
688         return !errors;
689 }
690
691 /* Commit leases after a timeout. */
692 void commit_leases_timeout (void *foo)
693 {
694         commit_leases ();
695 }
696
697 /* Commit any leases that have been written out... */
698
699 int commit_leases ()
700 {
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;
707         }
708         if (fsync (fileno (db_file)) < 0) {
709                 log_info ("commit_leases: unable to commit: %m");
710                 return 0;
711         }
712
713         /* If we haven't rewritten the lease database in over an
714            hour, rewrite it now.  (The length of time should probably
715            be configurable. */
716         if (count && cur_time - write_time > 3600) {
717                 count = 0;
718                 write_time = cur_time;
719                 new_lease_file ();
720         }
721         return 1;
722 }
723
724 void db_startup (testp)
725         int testp;
726 {
727         isc_result_t status;
728
729 #if defined (TRACING)
730         if (!trace_playback ()) {
731 #endif
732                 /* Read in the existing lease file... */
733                 status = read_conf_file (path_dhcpd_db,
734                                          (struct group *)0, 0, 1);
735                 /* XXX ignore status? */
736 #if defined (TRACING)
737         }
738 #endif
739
740 #if defined (TRACING)
741         /* If we're playing back, there is no lease file, so we can't
742            append it, so we create one immediately (maybe this isn't
743            the best solution... */
744         if (trace_playback ()) {
745                 new_lease_file ();
746         }
747 #endif
748         if (!testp) {
749                 db_file = fopen (path_dhcpd_db, "a");
750                 if (!db_file)
751                         log_fatal ("Can't open %s for append.", path_dhcpd_db);
752                 expire_all_pools ();
753 #if defined (TRACING)
754                 if (trace_playback ())
755                         write_time = cur_time;
756                 else
757 #endif
758                         GET_TIME (&write_time);
759                 new_lease_file ();
760         }
761 }
762
763 int new_lease_file ()
764 {
765         char newfname [512];
766         char backfname [512];
767         TIME t;
768         int db_fd;
769
770         /* If we already have an open database, close it. */
771         if (db_file) {
772                 fclose (db_file);
773                 db_file = (FILE *)0;
774         }
775
776         /* Make a temporary lease file... */
777         GET_TIME (&t);
778
779         /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
780          * This should never happen since the path is a configuration
781          * variable from build-time or command-line.  But if it should,
782          * either by malice or ignorance, we panic, since the potential
783          * for havoc is high.
784          */
785         if (snprintf (newfname, sizeof newfname, "%s.%d",
786                      path_dhcpd_db, (int)t) >= sizeof newfname)
787                 log_fatal("new_lease_file: lease file path too long");
788
789         db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
790         if (db_fd < 0) {
791                 log_error ("Can't create new lease file: %m");
792                 return 0;
793         }
794         if ((db_file = fdopen (db_fd, "w")) == NULL) {
795                 log_error ("Can't fdopen new lease file!");
796                 goto fail;
797         }
798
799         /* Write an introduction so people don't complain about time
800            being off. */
801         errno = 0;
802         fprintf (db_file, "# All times in this file are in UTC (GMT), not %s",
803                  "your local timezone.   This is\n");
804         if (errno != 0)
805                 goto fail;
806         fprintf (db_file, "# not a bug, so please don't ask about it.   %s",
807                  "There is no portable way to\n");
808         if (errno != 0)
809                 goto fail;
810         fprintf (db_file, "# store leases in the local timezone, so please %s",
811                  "don't request this as a\n");
812         if (errno != 0)
813                 goto fail;
814         fprintf (db_file, "# feature.   If this is inconvenient or %s",
815                  "confusing to you, we sincerely\n");
816         if (errno != 0)
817                 goto fail;
818         fprintf (db_file, "# apologize.   Seriously, though - don't ask.\n");
819         if (errno != 0)
820                 goto fail;
821         fprintf (db_file, "# The format of this file is documented in the %s",
822                  "dhcpd.leases(5) manual page.\n");
823         if (errno != 0)
824                 goto fail;
825         fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
826                  DHCP_VERSION);
827         if (errno != 0)
828                 goto fail;
829
830         /* Write out all the leases that we know of... */
831         counting = 0;
832         if (!write_leases ())
833                 goto fail;
834
835 #if defined (TRACING)
836         if (!trace_playback ()) {
837 #endif
838             /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
839              * This should never happen since the path is a configuration
840              * variable from build-time or command-line.  But if it should,
841              * either by malice or ignorance, we panic, since the potential
842              * for havoc is too high.
843              */
844             if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
845                         >= sizeof backfname)
846                 log_fatal("new_lease_file: backup lease file path too long");
847
848             /* Get the old database out of the way... */
849             if (unlink (backfname) < 0 && errno != ENOENT) {
850                 log_error ("Can't remove old lease database backup %s: %m",
851                            backfname);
852                 goto fail;
853             }
854             if (link (path_dhcpd_db, backfname) < 0) {
855                 log_error ("Can't backup lease database %s to %s: %m",
856                            path_dhcpd_db, backfname);
857                 goto fail;
858             }
859 #if defined (TRACING)
860         }
861 #endif
862         
863         /* Move in the new file... */
864         if (rename (newfname, path_dhcpd_db) < 0) {
865                 log_error ("Can't install new lease database %s to %s: %m",
866                            newfname, path_dhcpd_db);
867                 goto fail;
868         }
869
870         counting = 1;
871         lease_file_is_corrupt = 0;
872         return 1;
873
874       fail:
875         unlink (newfname);
876         lease_file_is_corrupt = 1;
877         return 0;
878 }
879
880 int group_writer (struct group_object *group)
881 {
882         if (!write_group (group))
883                 return 0;
884         if (!commit_leases ())
885                 return 0;
886         return 1;
887 }