3 Persistent database management routines for DHCPD... */
6 * Copyright (c) 2004-2016 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.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
33 #define LEASE_REWRITE_PERIOD 3600
35 static isc_result_t
write_binding_scope(FILE *db_file
, struct binding
*bnd
,
40 static int counting
= 0;
43 int lease_file_is_corrupt
= 0;
45 /* Write a single binding scope value in parsable format.
49 write_binding_scope(FILE *db_file
, struct binding
*bnd
, char *prepend
) {
52 if ((db_file
== NULL
) || (bnd
== NULL
) || (prepend
== NULL
))
53 return DHCP_R_INVALIDARG
;
55 if (bnd
->value
->type
== binding_data
) {
56 if (bnd
->value
->value
.data
.data
!= NULL
) {
57 s
= quotify_buf(bnd
->value
->value
.data
.data
,
58 bnd
->value
->value
.data
.len
, '"', MDL
);
61 fprintf(db_file
, "%sset %s = %s;",
62 prepend
, bnd
->name
, s
);
70 } else if (bnd
->value
->type
== binding_numeric
) {
72 fprintf(db_file
, "%sset %s = %%%ld;", prepend
,
73 bnd
->name
, bnd
->value
->value
.intval
);
76 } else if (bnd
->value
->type
== binding_boolean
) {
78 fprintf(db_file
, "%sset %s = %s;", prepend
, bnd
->name
,
79 bnd
->value
->value
.intval
? "true" : "false");
82 } else if (bnd
->value
->type
== binding_dns
) {
83 log_error("%s: persistent dns values not supported.",
85 } else if (bnd
->value
->type
== binding_function
) {
86 log_error("%s: persistent functions not supported.",
89 log_fatal("%s: unknown binding type %d", bnd
->name
,
96 /* Write the specified lease to the current lease database file. */
98 int write_lease (lease
)
106 /* If the lease file is corrupt, don't try to write any more leases
107 until we've written a good lease file. */
108 if (lease_file_is_corrupt
)
109 if (!new_lease_file ())
115 fprintf (db_file
, "lease %s {", piaddr (lease
-> ip_addr
));
121 ((tval
= print_time(lease
->starts
)) == NULL
||
122 fprintf(db_file
, "\n starts %s", tval
) < 0))
126 ((tval
= print_time(lease
->ends
)) == NULL
||
127 fprintf(db_file
, "\n ends %s", tval
) < 0))
131 ((tval
= print_time(lease
->tstp
)) == NULL
||
132 fprintf(db_file
, "\n tstp %s", tval
) < 0))
136 ((tval
= print_time(lease
->tsfp
)) == NULL
||
137 fprintf(db_file
, "\n tsfp %s", tval
) < 0))
141 ((tval
= print_time(lease
->atsfp
)) == NULL
||
142 fprintf(db_file
, "\n atsfp %s", tval
) < 0))
146 ((tval
= print_time(lease
->cltt
)) == NULL
||
147 fprintf(db_file
, "\n cltt %s", tval
) < 0))
150 if (fprintf (db_file
, "\n binding state %s;",
151 ((lease
-> binding_state
> 0 &&
152 lease
-> binding_state
<= FTS_LAST
)
153 ? binding_state_names
[lease
-> binding_state
- 1]
157 if (lease
-> binding_state
!= lease
-> next_binding_state
)
158 if (fprintf (db_file
, "\n next binding state %s;",
159 ((lease
-> next_binding_state
> 0 &&
160 lease
-> next_binding_state
<= FTS_LAST
)
161 ? (binding_state_names
162 [lease
-> next_binding_state
- 1])
167 * In this case, if the rewind state is not present in the lease file,
168 * the reader will use the current binding state as the most
169 * conservative (safest) state. So if the in-memory rewind state is
170 * for some reason invalid, the best thing to do is not to write a
171 * state and let the reader take on a safe state.
173 if ((lease
->binding_state
!= lease
->rewind_binding_state
) &&
174 (lease
->rewind_binding_state
> 0) &&
175 (lease
->rewind_binding_state
<= FTS_LAST
) &&
176 (fprintf(db_file
, "\n rewind binding state %s;",
177 binding_state_names
[lease
->rewind_binding_state
-1])) < 0)
180 if (lease
->flags
& RESERVED_LEASE
)
181 if (fprintf(db_file
, "\n reserved;") < 0)
184 if (lease
->flags
& BOOTP_LEASE
)
185 if (fprintf(db_file
, "\n dynamic-bootp;") < 0)
188 /* If this lease is billed to a class and is still valid,
190 if (lease
-> billing_class
&& lease
-> ends
> cur_time
) {
191 if (!write_billing_class (lease
-> billing_class
)) {
192 log_error ("unable to write class %s",
193 lease
-> billing_class
-> name
);
198 if (lease
-> hardware_addr
.hlen
) {
200 fprintf (db_file
, "\n hardware %s %s;",
201 hardware_types
[lease
-> hardware_addr
.hbuf
[0]],
202 print_hw_addr (lease
-> hardware_addr
.hbuf
[0],
203 lease
-> hardware_addr
.hlen
- 1,
204 &lease
-> hardware_addr
.hbuf
[1]));
208 if (lease
-> uid_len
) {
209 s
= format_lease_id(lease
->uid
, lease
->uid_len
, lease_id_format
,
213 fprintf (db_file
, "\n uid %s;", s
);
221 if (lease
->scope
!= NULL
) {
222 for (b
= lease
->scope
->bindings
; b
; b
= b
->next
) {
226 if (write_binding_scope(db_file
, b
, "\n ") != ISC_R_SUCCESS
)
231 if (lease
-> agent_options
) {
232 struct option_cache
*oc
;
233 struct data_string ds
;
236 memset (&ds
, 0, sizeof ds
);
237 for (p
= lease
-> agent_options
-> first
; p
; p
= p
-> cdr
) {
238 oc
= (struct option_cache
*)p
-> car
;
239 if (oc
-> data
.len
) {
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));
250 if (lease
-> client_hostname
&&
251 db_printable((unsigned char *)lease
->client_hostname
)) {
252 s
= quotify_string (lease
-> client_hostname
, MDL
);
255 fprintf (db_file
, "\n client-hostname \"%s\";", s
);
262 if (lease
->on_star
.on_expiry
) {
264 fprintf (db_file
, "\n on expiry%s {",
265 lease
->on_star
.on_expiry
== lease
->on_star
.on_release
266 ? " or release" : "");
267 write_statements (db_file
, lease
->on_star
.on_expiry
, 4);
269 fprintf (db_file
, "\n }");
273 if (lease
->on_star
.on_release
&&
274 lease
->on_star
.on_release
!= lease
->on_star
.on_expiry
) {
276 fprintf (db_file
, "\n on release {");
277 write_statements (db_file
, lease
->on_star
.on_release
, 4);
279 fprintf (db_file
, "\n }");
285 fputs ("\n}\n", db_file
);
290 log_info ("write_lease: unable to write lease %s",
291 piaddr (lease
-> ip_addr
));
292 lease_file_is_corrupt
= 1;
298 int write_host (host
)
299 struct host_decl
*host
;
303 struct data_string ip_addrs
;
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 ())
311 if (!db_printable((unsigned char *)host
->name
))
318 fprintf (db_file
, "host %s {", host
-> name
);
322 if (host
-> flags
& HOST_DECL_DYNAMIC
) {
324 fprintf (db_file
, "\n dynamic;");
329 if (host
-> flags
& HOST_DECL_DELETED
) {
331 fprintf (db_file
, "\n deleted;");
335 if (host
-> interface
.hlen
) {
337 fprintf (db_file
, "\n hardware %s %s;",
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]));
345 if (host
-> client_identifier
.len
) {
348 if (db_printable_len (host
-> client_identifier
.data
,
349 host
-> client_identifier
.len
)) {
350 fprintf (db_file
, "\n uid \"%.*s\";",
351 (int)host
-> client_identifier
.len
,
352 host
-> client_identifier
.data
);
358 host
-> client_identifier
.data
[0]);
362 i
< host
-> client_identifier
.len
; i
++) {
364 fprintf (db_file
, ":%2.2x",
366 client_identifier
.data
[i
]);
372 fputc (';', db_file
);
378 memset (&ip_addrs
, 0, sizeof ip_addrs
);
379 if (host
-> fixed_addr
&&
380 evaluate_option_cache (&ip_addrs
, (struct packet
*)0,
382 (struct client_state
*)0,
383 (struct option_state
*)0,
384 (struct option_state
*)0,
386 host
-> fixed_addr
, MDL
)) {
389 fprintf (db_file
, "\n fixed-address ");
392 for (i
= 0; i
< ip_addrs
.len
- 3; i
+= 4) {
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,
400 i
+ 7 < ip_addrs
.len
? "," : "");
405 /* We're done with ip_addrs so pitch it */
406 data_string_forget (&ip_addrs
, MDL
);
409 fputc (';', db_file
);
415 if (host
-> named_group
) {
417 fprintf (db_file
, "\n group \"%s\";",
418 host
-> named_group
-> name
);
424 (!host
-> named_group
||
425 host
-> group
!= host
-> named_group
-> group
) &&
426 host
-> group
!= root_group
) {
428 write_statements (db_file
,
429 host
-> group
-> statements
, 8);
436 fputs ("\n}\n", db_file
);
441 log_info ("write_host: unable to write host %s",
443 lease_file_is_corrupt
= 1;
449 int write_group (group
)
450 struct group_object
*group
;
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 ())
460 if (!db_printable((unsigned char *)group
->name
))
467 fprintf (db_file
, "group %s {", group
-> name
);
471 if (group
-> flags
& GROUP_OBJECT_DYNAMIC
) {
473 fprintf (db_file
, "\n dynamic;");
478 if (group
-> flags
& GROUP_OBJECT_STATIC
) {
480 fprintf (db_file
, "\n static;");
485 if (group
-> flags
& GROUP_OBJECT_DELETED
) {
487 fprintf (db_file
, "\n deleted;");
491 if (group
-> group
) {
493 write_statements (db_file
,
494 group
-> group
-> statements
, 8);
501 fputs ("\n}\n", db_file
);
506 log_info ("write_group: unable to write group %s",
508 lease_file_is_corrupt
= 1;
515 * Write an IA and the options it has.
518 write_ia(const struct ia_xx
*ia
) {
519 struct iasubopt
*iasubopt
;
522 char addr_buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff.255.255.255.255")];
523 const char *binding_state
;
529 * If the lease file is corrupt, don't try to write any more
530 * leases until we've written a good lease file.
532 if (lease_file_is_corrupt
) {
533 if (!new_lease_file()) {
542 s
= format_lease_id(ia
->iaid_duid
.data
, ia
->iaid_duid
.len
,
543 lease_id_format
, MDL
);
547 switch (ia
->ia_type
) {
549 fprintf_ret
= fprintf(db_file
, "ia-na %s {\n", s
);
552 fprintf_ret
= fprintf(db_file
, "ia-ta %s {\n", s
);
555 fprintf_ret
= fprintf(db_file
, "ia-pd %s {\n", s
);
558 log_error("Unknown ia type %u for %s at %s:%d",
559 (unsigned)ia
->ia_type
, s
, MDL
);
563 if (fprintf_ret
< 0) {
566 if (ia
->cltt
!= MIN_TIME
) {
567 tval
= print_time(ia
->cltt
);
571 if (fprintf(db_file
, " cltt %s\n", tval
) < 0) {
575 for (i
=0; i
<ia
->num_iasubopt
; i
++) {
576 iasubopt
= ia
->iasubopt
[i
];
578 inet_ntop(AF_INET6
, &iasubopt
->addr
,
579 addr_buf
, sizeof(addr_buf
));
580 if ((ia
->ia_type
!= D6O_IA_PD
) &&
581 (fprintf(db_file
, " iaaddr %s {\n", addr_buf
) < 0)) {
584 if ((ia
->ia_type
== D6O_IA_PD
) &&
585 (fprintf(db_file
, " iaprefix %s/%d {\n",
586 addr_buf
, (int)iasubopt
->plen
) < 0)) {
589 if ((iasubopt
->state
<= 0) || (iasubopt
->state
> FTS_LAST
)) {
590 log_fatal("Unknown iasubopt state %d at %s:%d",
591 iasubopt
->state
, MDL
);
593 binding_state
= binding_state_names
[iasubopt
->state
-1];
594 if (fprintf(db_file
, " binding state %s;\n",
595 binding_state
) < 0) {
598 if (fprintf(db_file
, " preferred-life %u;\n",
599 (unsigned)iasubopt
->prefer
) < 0) {
602 if (fprintf(db_file
, " max-life %u;\n",
603 (unsigned)iasubopt
->valid
) < 0) {
607 /* Note that from here on out, the \n is prepended to the
608 * next write, rather than appended to the current write.
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
);
615 tval
= print_time(iasubopt
->soft_lifetime_end_time
);
620 if (fprintf(db_file
, " ends %s", tval
) < 0) {
624 /* Write out any binding scopes: note that 'ends' above does
625 * not have \n on the end! We want that.
627 if (iasubopt
->scope
!= NULL
)
628 bnd
= iasubopt
->scope
->bindings
;
632 for (; bnd
!= NULL
; bnd
= bnd
->next
) {
633 if (bnd
->value
== NULL
)
636 /* We don't do a regular error_exit because the
637 * lease db is not corrupt in this case.
639 if (write_binding_scope(db_file
, bnd
,
640 "\n ") != ISC_R_SUCCESS
)
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)
651 write_statements(db_file
,
652 iasubopt
->on_star
.on_expiry
, 6);
653 if (fprintf(db_file
, "\n }") < 0)
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)
662 write_statements(db_file
,
663 iasubopt
->on_star
.on_release
, 6);
664 if (fprintf(db_file
, "\n }") < 0)
668 if (fprintf(db_file
, "\n }\n") < 0)
671 if (fprintf(db_file
, "}\n\n") < 0)
678 log_info("write_ia: unable to write ia");
679 lease_file_is_corrupt
= 1;
685 * Put a copy of the server DUID in the leases file.
688 write_server_duid(void) {
689 struct data_string server_duid
;
694 * Only write the DUID if it's been set.
696 if (!server_duid_isset()) {
701 * If the lease file is corrupt, don't try to write any more
702 * leases until we've written a good lease file.
704 if (lease_file_is_corrupt
) {
705 if (!new_lease_file()) {
711 * Get a copy of our server DUID and convert to a quoted string.
713 memset(&server_duid
, 0, sizeof(server_duid
));
714 copy_server_duid(&server_duid
, MDL
);
715 s
= format_lease_id(server_duid
.data
, server_duid
.len
, lease_id_format
,
717 data_string_forget(&server_duid
, MDL
);
723 * Write to the leases file.
725 fprintf_ret
= fprintf(db_file
, "server-duid %s;\n\n", s
);
727 if (fprintf_ret
< 0) {
732 * Check if we actually managed to write.
738 log_info("write_server_duid: unable to write server-duid");
739 lease_file_is_corrupt
= 1;
744 #if defined (FAILOVER_PROTOCOL)
745 int write_failover_state (dhcp_failover_state_t
*state
)
750 if (lease_file_is_corrupt
)
751 if (!new_lease_file ())
755 fprintf (db_file
, "\nfailover peer \"%s\" state {", state
-> name
);
759 tval
= print_time(state
->me
.stos
);
761 fprintf(db_file
, "\n my state %s at %s",
762 (state
->me
.state
== startup
) ?
763 dhcp_failover_state_name_print(state
->saved_state
) :
764 dhcp_failover_state_name_print(state
->me
.state
),
768 tval
= print_time(state
->partner
.stos
);
770 fprintf(db_file
, "\n partner state %s at %s",
771 dhcp_failover_state_name_print(state
->partner
.state
),
775 if (state
-> i_am
== secondary
) {
777 fprintf (db_file
, "\n mclt %ld;",
778 (unsigned long)state
-> mclt
);
784 fprintf (db_file
, "\n}\n");
789 log_info ("write_failover_state: unable to write state %s",
791 lease_file_is_corrupt
= 1;
801 const unsigned char *s
;
804 for (i
= 0; s
[i
]; i
++)
805 if (!isascii (s
[i
]) || !isprint (s
[i
])
806 || s
[i
] == '"' || s
[i
] == '\\')
811 int db_printable_len (s
, len
)
812 const unsigned char *s
;
817 for (i
= 0; i
< len
; i
++)
818 if (!isascii (s
[i
]) || !isprint (s
[i
]) ||
819 s
[i
] == '"' || s
[i
] == '\\')
824 static int print_hash_string(FILE *fp
, struct class *class)
828 for (i
= 0 ; i
< class->hash_string
.len
; i
++)
829 if (!isascii(class->hash_string
.data
[i
]) ||
830 !isprint(class->hash_string
.data
[i
]))
833 if (i
== class->hash_string
.len
) {
834 if (fprintf(fp
, " \"%.*s\"", (int)class->hash_string
.len
,
835 class->hash_string
.data
) <= 0) {
836 log_error("Failure writing hash string: %m");
840 if (fprintf(fp
, " %2.2x", class->hash_string
.data
[0]) <= 0) {
841 log_error("Failure writing hash string: %m");
844 for (i
= 1 ; i
< class->hash_string
.len
; i
++) {
845 if (fprintf(fp
, ":%2.2x",
846 class->hash_string
.data
[i
]) <= 0) {
847 log_error("Failure writing hash string: %m");
858 write_named_billing_class(const void *key
, unsigned len
, void *object
)
860 const unsigned char *name
= key
;
861 struct class *class = object
;
863 if (class->flags
& CLASS_DECL_DYNAMIC
) {
865 if (class->superclass
== 0) {
866 if (fprintf(db_file
, "class \"%s\" {\n", name
) <= 0)
867 return ISC_R_IOERROR
;
869 if (fprintf(db_file
, "subclass \"%s\"",
870 class->superclass
->name
) <= 0)
871 return ISC_R_IOERROR
;
872 if (!print_hash_string(db_file
, class))
873 return ISC_R_IOERROR
;
874 if (fprintf(db_file
, " {\n") <= 0)
875 return ISC_R_IOERROR
;
878 if ((class->flags
& CLASS_DECL_DELETED
) != 0) {
879 if (fprintf(db_file
, " deleted;\n") <= 0)
880 return ISC_R_IOERROR
;
882 if (fprintf(db_file
, " dynamic;\n") <= 0)
883 return ISC_R_IOERROR
;
886 if (class->lease_limit
> 0) {
887 if (fprintf(db_file
, " lease limit %d;\n",
888 class->lease_limit
) <= 0)
889 return ISC_R_IOERROR
;
892 if (class->expr
!= 0) {
893 if (fprintf(db_file
, " match if ") <= 0)
894 return ISC_R_IOERROR
;
897 write_expression(db_file
, class->expr
, 5, 5, 0);
899 return ISC_R_IOERROR
;
901 if (fprintf(db_file
, ";\n") <= 0)
902 return ISC_R_IOERROR
;
905 if (class->submatch
!= 0) {
906 if (class->spawning
) {
907 if (fprintf(db_file
, " spawn ") <= 0)
908 return ISC_R_IOERROR
;
910 if (fprintf(db_file
, " match ") <= 0)
911 return ISC_R_IOERROR
;
915 write_expression(db_file
, class->submatch
, 5, 5, 0);
917 return ISC_R_IOERROR
;
919 if (fprintf(db_file
, ";\n") <= 0)
920 return ISC_R_IOERROR
;
923 if (class->statements
!= 0) {
925 write_statements(db_file
, class->statements
, 8);
927 return ISC_R_IOERROR
;
930 /* XXXJAB this isn't right, but classes read in off the
931 leases file don't get the root group assigned to them
932 (due to clone_group() call). */
933 if (class->group
!= 0 && class->group
->authoritative
!= 0) {
935 write_statements(db_file
, class->group
->statements
, 8);
937 return ISC_R_IOERROR
;
940 if (fprintf(db_file
, "}\n\n") <= 0)
941 return ISC_R_IOERROR
;
944 if (class->hash
!= NULL
) { /* yep. recursive. god help us. */
945 /* XXX - cannot check error status of this...
946 * foo_hash_foreach returns a count of operations completed.
948 class_hash_foreach(class->hash
, write_named_billing_class
);
951 return ISC_R_SUCCESS
;
954 void write_billing_classes ()
956 struct collection
*lp
;
959 for (lp
= collections
; lp
; lp
= lp
-> next
) {
960 for (cp
= lp
-> classes
; cp
; cp
= cp
-> nic
) {
961 if (cp
-> spawning
&& cp
-> hash
) {
962 class_hash_foreach (cp
-> hash
, write_named_billing_class
);
968 /* Write a spawned class to the database file. */
970 int write_billing_class (class)
975 if (lease_file_is_corrupt
)
976 if (!new_lease_file ())
979 if (!class -> superclass
) {
981 fprintf (db_file
, "\n billing class \"%s\";", class -> name
);
985 if (fprintf(db_file
, "\n billing subclass \"%s\"",
986 class -> superclass
-> name
) < 0)
989 if (!print_hash_string(db_file
, class))
992 if (fprintf(db_file
, ";") < 0)
995 class -> dirty
= !errors
;
997 lease_file_is_corrupt
= 1;
1002 /* Commit leases after a timeout. */
1003 void commit_leases_timeout (void *foo
)
1008 /* Commit any leases that have been written out... */
1010 int commit_leases ()
1012 /* Commit any outstanding writes to the lease database file.
1013 We need to do this even if we're rewriting the file below,
1014 just in case the rewrite fails. */
1015 if (fflush (db_file
) == EOF
) {
1016 log_info("commit_leases: unable to commit, fflush(): %m");
1019 if ((dont_use_fsync
== 0) &&
1020 (fsync(fileno (db_file
)) < 0)) {
1021 log_info ("commit_leases: unable to commit, fsync(): %m");
1025 /* If we haven't rewritten the lease database in over an
1026 hour, rewrite it now. (The length of time should probably
1028 if (count
&& cur_time
- write_time
> LEASE_REWRITE_PERIOD
) {
1030 write_time
= cur_time
;
1037 * rewrite the lease file about once an hour
1038 * This is meant as a quick patch for ticket 24887. It allows
1039 * us to rotate the v6 lease file without adding too many fsync()
1040 * calls. In the future wes should revisit this area and add
1041 * something similar to the delayed ack code for v4.
1043 int commit_leases_timed()
1045 if ((count
!= 0) && (cur_time
- write_time
> LEASE_REWRITE_PERIOD
)) {
1046 return (commit_leases());
1051 void db_startup (testp
)
1054 isc_result_t status
;
1056 #if defined (TRACING)
1057 if (!trace_playback ()) {
1059 /* Unset authoring_byte_order so we'll know if it was specified
1060 in the lease file or not. */
1061 authoring_byte_order
= 0;
1063 /* Read in the existing lease file... */
1064 status
= read_conf_file (path_dhcpd_db
,
1065 (struct group
*)0, 0, 1);
1066 if (status
!= ISC_R_SUCCESS
) {
1067 /* XXX ignore status? */
1071 #if defined (TRACING)
1075 #if defined (TRACING)
1076 /* If we're playing back, there is no lease file, so we can't
1077 append it, so we create one immediately (maybe this isn't
1078 the best solution... */
1079 if (trace_playback ()) {
1084 db_file
= fopen (path_dhcpd_db
, "a");
1086 log_fatal ("Can't open %s for append.", path_dhcpd_db
);
1087 expire_all_pools ();
1088 #if defined (TRACING)
1089 if (trace_playback ())
1090 write_time
= cur_time
;
1097 #if defined(REPORT_HASH_PERFORMANCE)
1098 log_info("Host HW hash: %s", host_hash_report(host_hw_addr_hash
));
1099 log_info("Host UID hash: %s", host_hash_report(host_uid_hash
));
1100 log_info("Lease IP hash: %s",
1101 lease_ip_hash_report(lease_ip_addr_hash
));
1102 log_info("Lease UID hash: %s", lease_id_hash_report(lease_uid_hash
));
1103 log_info("Lease HW hash: %s",
1104 lease_id_hash_report(lease_hw_addr_hash
));
1108 int new_lease_file ()
1110 char newfname
[512];
1111 char backfname
[512];
1117 /* Make a temporary lease file... */
1120 db_validity
= lease_file_is_corrupt
;
1122 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1123 * This should never happen since the path is a configuration
1124 * variable from build-time or command-line. But if it should,
1125 * either by malice or ignorance, we panic, since the potential
1126 * for havoc is high.
1128 if (snprintf (newfname
, sizeof newfname
, "%s.%d",
1129 path_dhcpd_db
, (int)t
) >= sizeof newfname
)
1130 log_fatal("new_lease_file: lease file path too long");
1132 db_fd
= open (newfname
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0664);
1134 log_error ("Can't create new lease file: %m");
1138 #if defined (PARANOIA)
1140 * If we are currently root and plan to change the
1141 * uid and gid change the file information so we
1142 * can manipulate it later, after we've changed
1143 * our group and user (that is dropped privileges.)
1145 if ((set_uid
!= 0) && (geteuid() == 0) &&
1146 (set_gid
!= 0) && (getegid() == 0)) {
1147 if (fchown(db_fd
, set_uid
, set_gid
)) {
1148 log_fatal ("Can't chown new lease file: %m");
1151 #endif /* PARANOIA */
1153 if ((new_db_file
= fdopen(db_fd
, "w")) == NULL
) {
1154 log_error("Can't fdopen new lease file: %m");
1159 /* Close previous database, if any. */
1162 db_file
= new_db_file
;
1165 fprintf (db_file
, "# The format of this file is documented in the %s",
1166 "dhcpd.leases(5) manual page.\n");
1171 fprintf (db_file
, "# This lease file was written by isc-dhcp-%s\n\n",
1176 fprintf (db_file
, "# authoring-byte-order entry is generated,"
1177 " DO NOT DELETE\n");
1181 fprintf (db_file
, "authoring-byte-order %s;\n\n",
1182 (DHCP_BYTE_ORDER
== LITTLE_ENDIAN
?
1183 "little-endian" : "big-endian"));
1187 /* At this point we have a new lease file that, so far, could not
1188 * be described as either corrupt nor valid.
1190 lease_file_is_corrupt
= 0;
1192 /* Write out all the leases that we know of... */
1194 if (!write_leases ())
1197 #if defined (TRACING)
1198 if (!trace_playback ()) {
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.
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");
1210 /* Get the old database out of the way... */
1211 if (unlink (backfname
) < 0 && errno
!= ENOENT
) {
1212 log_error ("Can't remove old lease database backup %s: %m",
1216 if (link(path_dhcpd_db
, backfname
) < 0) {
1217 if (errno
== ENOENT
) {
1218 log_error("%s is missing - no lease db to backup.",
1221 log_error("Can't backup lease database %s to %s: %m",
1222 path_dhcpd_db
, backfname
);
1226 #if defined (TRACING)
1230 /* Move in the new file... */
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
);
1241 lease_file_is_corrupt
= db_validity
;
1243 (void)unlink (newfname
);
1247 int group_writer (struct group_object
*group
)
1249 if (!write_group (group
))
1251 if (!commit_leases ())