3
Persistent database management routines for DHCPD... */
6
* Copyright (c) 2004-2008 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
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''.
39
static isc_result_t write_binding_scope(FILE *db_file, struct binding *bnd,
44
static int counting = 0;
47
int lease_file_is_corrupt = 0;
49
/* Write a single binding scope value in parsable format.
53
write_binding_scope(FILE *db_file, struct binding *bnd, char *prepend) {
56
if ((db_file == NULL) || (bnd == NULL) || (prepend == NULL))
57
return ISC_R_INVALIDARG;
59
if (bnd->value->type == binding_data) {
60
if (bnd->value->value.data.data != NULL) {
61
s = quotify_buf(bnd->value->value.data.data,
62
bnd->value->value.data.len, MDL);
65
fprintf(db_file, "%sset %s = \"%s\";",
66
prepend, bnd->name, s);
75
} else if (bnd->value->type == binding_numeric) {
77
fprintf(db_file, "%sset %s = %%%ld;", prepend,
78
bnd->name, bnd->value->value.intval);
81
} else if (bnd->value->type == binding_boolean) {
83
fprintf(db_file, "%sset %s = %s;", prepend, bnd->name,
84
bnd->value->value.intval ? "true" : "false");
87
} else if (bnd->value->type == binding_dns) {
88
log_error("%s: persistent dns values not supported.",
90
} else if (bnd->value->type == binding_function) {
91
log_error("%s: persistent functions not supported.",
94
log_fatal("%s: unknown binding type %d", bnd->name,
101
/* Write the specified lease to the current lease database file. */
103
int write_lease (lease)
111
/* If the lease file is corrupt, don't try to write any more leases
112
until we've written a good lease file. */
113
if (lease_file_is_corrupt)
114
if (!new_lease_file ())
120
fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
126
((tval = print_time(lease->starts)) == NULL ||
127
fprintf(db_file, "\n starts %s", tval) < 0))
131
((tval = print_time(lease->ends)) == NULL ||
132
fprintf(db_file, "\n ends %s", tval) < 0))
136
((tval = print_time(lease->tstp)) == NULL ||
137
fprintf(db_file, "\n tstp %s", tval) < 0))
141
((tval = print_time(lease->tsfp)) == NULL ||
142
fprintf(db_file, "\n tsfp %s", tval) < 0))
146
((tval = print_time(lease->atsfp)) == NULL ||
147
fprintf(db_file, "\n atsfp %s", tval) < 0))
151
((tval = print_time(lease->cltt)) == NULL ||
152
fprintf(db_file, "\n cltt %s", tval) < 0))
155
if (fprintf (db_file, "\n binding state %s;",
156
((lease -> binding_state > 0 &&
157
lease -> binding_state <= FTS_LAST)
158
? binding_state_names [lease -> binding_state - 1]
162
if (lease -> binding_state != lease -> next_binding_state)
163
if (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])
171
if (lease->flags & RESERVED_LEASE)
172
if (fprintf(db_file, "\n reserved;") < 0)
175
if (lease->flags & BOOTP_LEASE)
176
if (fprintf(db_file, "\n dynamic-bootp;") < 0)
179
/* If this lease is billed to a class and is still valid,
181
if (lease -> billing_class && lease -> ends > cur_time) {
182
if (!write_billing_class (lease -> billing_class)) {
183
log_error ("unable to write class %s",
184
lease -> billing_class -> name);
189
if (lease -> hardware_addr.hlen) {
191
fprintf (db_file, "\n hardware %s %s;",
192
hardware_types [lease -> hardware_addr.hbuf [0]],
193
print_hw_addr (lease -> hardware_addr.hbuf [0],
194
lease -> hardware_addr.hlen - 1,
195
&lease -> hardware_addr.hbuf [1]));
199
if (lease -> uid_len) {
200
s = quotify_buf (lease -> uid, lease -> uid_len, MDL);
203
fprintf (db_file, "\n uid \"%s\";", s);
211
if (lease->scope != NULL) {
212
for (b = lease->scope->bindings; b; b = b->next) {
216
if (write_binding_scope(db_file, b, "\n ") != ISC_R_SUCCESS)
221
if (lease -> agent_options) {
222
struct option_cache *oc;
223
struct data_string ds;
226
memset (&ds, 0, sizeof ds);
227
for (p = lease -> agent_options -> first; p; p = p -> cdr) {
228
oc = (struct option_cache *)p -> car;
229
if (oc -> data.len) {
231
fprintf (db_file, "\n option agent.%s %s;",
232
oc -> option -> name,
233
pretty_print_option (oc -> option, oc -> data.data,
234
oc -> data.len, 1, 1));
240
if (lease -> client_hostname &&
241
db_printable((unsigned char *)lease->client_hostname)) {
242
s = quotify_string (lease -> client_hostname, MDL);
245
fprintf (db_file, "\n client-hostname \"%s\";", s);
252
if (lease -> on_expiry) {
254
fprintf (db_file, "\n on expiry%s {",
255
lease -> on_expiry == lease -> on_release
256
? " or release" : "");
257
write_statements (db_file, lease -> on_expiry, 4);
259
fprintf (db_file, "\n }");
263
if (lease -> on_release && lease -> on_release != lease -> on_expiry) {
265
fprintf (db_file, "\n on release {");
266
write_statements (db_file, lease -> on_release, 4);
268
fprintf (db_file, "\n }");
274
fputs ("\n}\n", db_file);
279
log_info ("write_lease: unable to write lease %s",
280
piaddr (lease -> ip_addr));
281
lease_file_is_corrupt = 1;
287
int write_host (host)
288
struct host_decl *host;
292
struct data_string ip_addrs;
294
/* If the lease file is corrupt, don't try to write any more leases
295
until we've written a good lease file. */
296
if (lease_file_is_corrupt)
297
if (!new_lease_file ())
300
if (!db_printable((unsigned char *)host->name))
307
fprintf (db_file, "host %s {", host -> name);
311
if (host -> flags & HOST_DECL_DYNAMIC) {
313
fprintf (db_file, "\n dynamic;");
318
if (host -> flags & HOST_DECL_DELETED) {
320
fprintf (db_file, "\n deleted;");
324
if (host -> interface.hlen) {
326
fprintf (db_file, "\n hardware %s %s;",
327
hardware_types [host -> interface.hbuf [0]],
328
print_hw_addr (host -> interface.hbuf [0],
329
host -> interface.hlen - 1,
330
&host -> interface.hbuf [1]));
334
if (host -> client_identifier.len) {
337
if (db_printable_len (host -> client_identifier.data,
338
host -> client_identifier.len)) {
339
fprintf (db_file, "\n uid \"%.*s\";",
340
(int)host -> client_identifier.len,
341
host -> client_identifier.data);
347
host -> client_identifier.data [0]);
351
i < host -> client_identifier.len; i++) {
353
fprintf (db_file, ":%2.2x",
355
client_identifier.data [i]);
361
fputc (';', db_file);
367
memset (&ip_addrs, 0, sizeof ip_addrs);
368
if (host -> fixed_addr &&
369
evaluate_option_cache (&ip_addrs, (struct packet *)0,
371
(struct client_state *)0,
372
(struct option_state *)0,
373
(struct option_state *)0,
375
host -> fixed_addr, MDL)) {
378
fprintf (db_file, "\n fixed-address ");
381
for (i = 0; i < ip_addrs.len - 3; i += 4) {
384
fprintf (db_file, "%u.%u.%u.%u%s",
385
ip_addrs.data [i] & 0xff,
386
ip_addrs.data [i + 1] & 0xff,
387
ip_addrs.data [i + 2] & 0xff,
388
ip_addrs.data [i + 3] & 0xff,
389
i + 7 < ip_addrs.len ? "," : "");
395
fputc (';', db_file);
400
if (host -> named_group) {
402
fprintf (db_file, "\n group \"%s\";",
403
host -> named_group -> name);
409
(!host -> named_group ||
410
host -> group != host -> named_group -> group) &&
411
host -> group != root_group) {
413
write_statements (db_file,
414
host -> group -> statements, 8);
421
fputs ("\n}\n", db_file);
426
log_info ("write_host: unable to write host %s",
428
lease_file_is_corrupt = 1;
434
int write_group (group)
435
struct group_object *group;
439
/* If the lease file is corrupt, don't try to write any more leases
440
until we've written a good lease file. */
441
if (lease_file_is_corrupt)
442
if (!new_lease_file ())
445
if (!db_printable((unsigned char *)group->name))
452
fprintf (db_file, "group %s {", group -> name);
456
if (group -> flags & GROUP_OBJECT_DYNAMIC) {
458
fprintf (db_file, "\n dynamic;");
463
if (group -> flags & GROUP_OBJECT_STATIC) {
465
fprintf (db_file, "\n static;");
470
if (group -> flags & GROUP_OBJECT_DELETED) {
472
fprintf (db_file, "\n deleted;");
476
if (group -> group) {
478
write_statements (db_file,
479
group -> group -> statements, 8);
486
fputs ("\n}\n", db_file);
491
log_info ("write_group: unable to write group %s",
493
lease_file_is_corrupt = 1;
500
* Write an IA and the options it has.
503
write_ia(const struct ia_xx *ia) {
504
struct iasubopt *iasubopt;
507
char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff.255.255.255.255")];
508
const char *binding_state;
514
* If the lease file is corrupt, don't try to write any more
515
* leases until we've written a good lease file.
517
if (lease_file_is_corrupt) {
518
if (!new_lease_file()) {
528
s = quotify_buf(ia->iaid_duid.data, ia->iaid_duid.len, MDL);
532
switch (ia->ia_type) {
534
fprintf_ret = fprintf(db_file, "ia-na \"%s\" {\n", s);
537
fprintf_ret = fprintf(db_file, "ia-ta \"%s\" {\n", s);
540
fprintf_ret = fprintf(db_file, "ia-pd \"%s\" {\n", s);
543
log_error("Unknown ia type %u for \"%s\" at %s:%d",
544
(unsigned)ia->ia_type, s, MDL);
548
if (fprintf_ret < 0) {
551
if (ia->cltt != MIN_TIME) {
552
tval = print_time(ia->cltt);
556
if (fprintf(db_file, " cltt %s\n", tval) < 0) {
560
for (i=0; i<ia->num_iasubopt; i++) {
561
iasubopt = ia->iasubopt[i];
563
inet_ntop(AF_INET6, &iasubopt->addr,
564
addr_buf, sizeof(addr_buf));
565
if ((ia->ia_type != D6O_IA_PD) &&
566
(fprintf(db_file, " iaaddr %s {\n", addr_buf) < 0)) {
569
if ((ia->ia_type == D6O_IA_PD) &&
570
(fprintf(db_file, " iaprefix %s/%d {\n",
571
addr_buf, (int)iasubopt->plen) < 0)) {
574
if ((iasubopt->state <= 0) || (iasubopt->state > FTS_LAST)) {
575
log_fatal("Unknown iasubopt state %d at %s:%d",
576
iasubopt->state, MDL);
578
binding_state = binding_state_names[iasubopt->state-1];
579
if (fprintf(db_file, " binding state %s;\n",
580
binding_state) < 0) {
583
if (fprintf(db_file, " preferred-life %u\n",
584
(unsigned)iasubopt->prefer) < 0) {
587
if (fprintf(db_file, " max-life %u\n",
588
(unsigned)iasubopt->valid) < 0) {
592
/* Note that from here on out, the \n is prepended to the
593
* next write, rather than appended to the current write.
595
if ((iasubopt->state == FTS_ACTIVE) ||
596
(iasubopt->state == FTS_ABANDONED) ||
597
(iasubopt->hard_lifetime_end_time != 0)) {
598
tval = print_time(iasubopt->hard_lifetime_end_time);
600
tval = print_time(iasubopt->soft_lifetime_end_time);
605
if (fprintf(db_file, " ends %s", tval) < 0) {
609
/* Write out any binding scopes: note that 'ends' above does
610
* not have \n on the end! We want that.
612
if (iasubopt->scope != NULL)
613
bnd = iasubopt->scope->bindings;
617
for (; bnd != NULL ; bnd = bnd->next) {
618
if (bnd->value == NULL)
621
/* We don't do a regular error_exit because the
622
* lease db is not corrupt in this case.
624
if (write_binding_scope(db_file, bnd,
625
"\n ") != ISC_R_SUCCESS)
630
if (fprintf(db_file, "\n }\n") < 0)
633
if (fprintf(db_file, "}\n\n") < 0)
640
log_info("write_ia: unable to write ia");
641
lease_file_is_corrupt = 1;
647
* Put a copy of the server DUID in the leases file.
650
write_server_duid(void) {
651
struct data_string server_duid;
656
* Only write the DUID if it's been set.
658
if (!server_duid_isset()) {
663
* If the lease file is corrupt, don't try to write any more
664
* leases until we've written a good lease file.
666
if (lease_file_is_corrupt) {
667
if (!new_lease_file()) {
673
* Get a copy of our server DUID and convert to a quoted string.
675
memset(&server_duid, 0, sizeof(server_duid));
676
copy_server_duid(&server_duid, MDL);
677
s = quotify_buf(server_duid.data, server_duid.len, MDL);
678
data_string_forget(&server_duid, MDL);
684
* Write to the leases file.
686
fprintf_ret = fprintf(db_file, "server-duid \"%s\";\n\n", s);
688
if (fprintf_ret < 0) {
693
* Check if we actually managed to write.
699
log_info("write_server_duid: unable to write server-duid");
700
lease_file_is_corrupt = 1;
705
#if defined (FAILOVER_PROTOCOL)
706
int write_failover_state (dhcp_failover_state_t *state)
711
if (lease_file_is_corrupt)
712
if (!new_lease_file ())
716
fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
720
tval = print_time(state->me.stos);
722
fprintf(db_file, "\n my state %s at %s",
723
(state->me.state == startup) ?
724
dhcp_failover_state_name_print(state->saved_state) :
725
dhcp_failover_state_name_print(state->me.state),
729
tval = print_time(state->partner.stos);
731
fprintf(db_file, "\n partner state %s at %s",
732
dhcp_failover_state_name_print(state->partner.state),
736
if (state -> i_am == secondary) {
738
fprintf (db_file, "\n mclt %ld;",
739
(unsigned long)state -> mclt);
745
fprintf (db_file, "\n}\n");
750
log_info ("write_failover_state: unable to write state %s",
752
lease_file_is_corrupt = 1;
762
const unsigned char *s;
765
for (i = 0; s [i]; i++)
766
if (!isascii (s [i]) || !isprint (s [i])
767
|| s [i] == '"' || s [i] == '\\')
772
int db_printable_len (s, len)
773
const unsigned char *s;
778
for (i = 0; i < len; i++)
779
if (!isascii (s [i]) || !isprint (s [i]) ||
780
s [i] == '"' || s [i] == '\\')
785
static int print_hash_string(FILE *fp, struct class *class)
789
for (i = 0 ; i < class->hash_string.len ; i++)
790
if (!isascii(class->hash_string.data[i]) ||
791
!isprint(class->hash_string.data[i]))
794
if (i == class->hash_string.len) {
795
if (fprintf(fp, " \"%.*s\"", (int)class->hash_string.len,
796
class->hash_string.data) <= 0) {
797
log_error("Failure writing hash string: %m");
801
if (fprintf(fp, " %2.2x", class->hash_string.data[0]) <= 0) {
802
log_error("Failure writing hash string: %m");
805
for (i = 1 ; i < class->hash_string.len ; i++) {
806
if (fprintf(fp, ":%2.2x",
807
class->hash_string.data[i]) <= 0) {
808
log_error("Failure writing hash string: %m");
819
write_named_billing_class(const void *key, unsigned len, void *object)
821
const unsigned char *name = key;
822
struct class *class = object;
824
if (class->flags & CLASS_DECL_DYNAMIC) {
826
if (class->superclass == 0) {
827
if (fprintf(db_file, "class \"%s\" {\n", name) <= 0)
828
return ISC_R_IOERROR;
830
if (fprintf(db_file, "subclass \"%s\"",
831
class->superclass->name) <= 0)
832
return ISC_R_IOERROR;
833
if (!print_hash_string(db_file, class))
834
return ISC_R_IOERROR;
835
if (fprintf(db_file, " {\n") <= 0)
836
return ISC_R_IOERROR;
839
if ((class->flags & CLASS_DECL_DELETED) != 0) {
840
if (fprintf(db_file, " deleted;\n") <= 0)
841
return ISC_R_IOERROR;
843
if (fprintf(db_file, " dynamic;\n") <= 0)
844
return ISC_R_IOERROR;
847
if (class->lease_limit > 0) {
848
if (fprintf(db_file, " lease limit %d;\n",
849
class->lease_limit) <= 0)
850
return ISC_R_IOERROR;
853
if (class->expr != 0) {
854
if (fprintf(db_file, " match if ") <= 0)
855
return ISC_R_IOERROR;
858
write_expression(db_file, class->expr, 5, 5, 0);
860
return ISC_R_IOERROR;
862
if (fprintf(db_file, ";\n") <= 0)
863
return ISC_R_IOERROR;
866
if (class->submatch != 0) {
867
if (class->spawning) {
868
if (fprintf(db_file, " spawn ") <= 0)
869
return ISC_R_IOERROR;
871
if (fprintf(db_file, " match ") <= 0)
872
return ISC_R_IOERROR;
876
write_expression(db_file, class->submatch, 5, 5, 0);
878
return ISC_R_IOERROR;
880
if (fprintf(db_file, ";\n") <= 0)
881
return ISC_R_IOERROR;
884
if (class->statements != 0) {
886
write_statements(db_file, class->statements, 8);
888
return ISC_R_IOERROR;
891
/* XXXJAB this isn't right, but classes read in off the
892
leases file don't get the root group assigned to them
893
(due to clone_group() call). */
894
if (class->group != 0 && class->group->authoritative != 0) {
896
write_statements(db_file, class->group->statements, 8);
898
return ISC_R_IOERROR;
901
if (fprintf(db_file, "}\n\n") <= 0)
902
return ISC_R_IOERROR;
905
if (class->hash != NULL) { /* yep. recursive. god help us. */
906
/* XXX - cannot check error status of this...
907
* foo_hash_foreach returns a count of operations completed.
909
class_hash_foreach(class->hash, write_named_billing_class);
912
return ISC_R_SUCCESS;
915
void write_billing_classes ()
917
struct collection *lp;
920
for (lp = collections; lp; lp = lp -> next) {
921
for (cp = lp -> classes; cp; cp = cp -> nic) {
922
if (cp -> spawning && cp -> hash) {
923
class_hash_foreach (cp -> hash, write_named_billing_class);
929
/* Write a spawned class to the database file. */
931
int write_billing_class (class)
936
if (lease_file_is_corrupt)
937
if (!new_lease_file ())
940
if (!class -> superclass) {
942
fprintf (db_file, "\n billing class \"%s\";", class -> name);
946
if (fprintf(db_file, "\n billing subclass \"%s\"",
947
class -> superclass -> name) < 0)
950
if (!print_hash_string(db_file, class))
953
if (fprintf(db_file, ";") < 0)
956
class -> dirty = !errors;
958
lease_file_is_corrupt = 1;
963
/* Commit leases after a timeout. */
964
void commit_leases_timeout (void *foo)
969
/* Commit any leases that have been written out... */
973
/* Commit any outstanding writes to the lease database file.
974
We need to do this even if we're rewriting the file below,
975
just in case the rewrite fails. */
976
if (fflush (db_file) == EOF) {
977
log_info ("commit_leases: unable to commit: %m");
980
if (fsync (fileno (db_file)) < 0) {
981
log_info ("commit_leases: unable to commit: %m");
985
/* send out all deferred ACKs now */
986
flush_ackqueue(NULL);
988
/* If we haven't rewritten the lease database in over an
989
hour, rewrite it now. (The length of time should probably
991
if (count && cur_time - write_time > 3600) {
993
write_time = cur_time;
999
void db_startup (testp)
1002
isc_result_t status;
1004
#if defined (TRACING)
1005
if (!trace_playback ()) {
1007
/* Read in the existing lease file... */
1008
status = read_conf_file (path_dhcpd_db,
1009
(struct group *)0, 0, 1);
1010
/* XXX ignore status? */
1011
#if defined (TRACING)
1015
#if defined (TRACING)
1016
/* If we're playing back, there is no lease file, so we can't
1017
append it, so we create one immediately (maybe this isn't
1018
the best solution... */
1019
if (trace_playback ()) {
1024
db_file = fopen (path_dhcpd_db, "a");
1026
log_fatal ("Can't open %s for append.", path_dhcpd_db);
1027
expire_all_pools ();
1028
#if defined (TRACING)
1029
if (trace_playback ())
1030
write_time = cur_time;
1037
#if defined(REPORT_HASH_PERFORMANCE)
1038
log_info("Host HW hash: %s", host_hash_report(host_hw_addr_hash));
1039
log_info("Host UID hash: %s", host_hash_report(host_uid_hash));
1040
log_info("Lease IP hash: %s",
1041
lease_ip_hash_report(lease_ip_addr_hash));
1042
log_info("Lease UID hash: %s", lease_id_hash_report(lease_uid_hash));
1043
log_info("Lease HW hash: %s",
1044
lease_id_hash_report(lease_hw_addr_hash));
1048
int new_lease_file ()
1050
char newfname [512];
1051
char backfname [512];
1057
/* Make a temporary lease file... */
1060
db_validity = lease_file_is_corrupt;
1062
/* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1063
* This should never happen since the path is a configuration
1064
* variable from build-time or command-line. But if it should,
1065
* either by malice or ignorance, we panic, since the potential
1066
* for havoc is high.
1068
if (snprintf (newfname, sizeof newfname, "%s.%d",
1069
path_dhcpd_db, (int)t) >= sizeof newfname)
1070
log_fatal("new_lease_file: lease file path too long");
1072
db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
1074
log_error ("Can't create new lease file: %m");
1077
if ((new_db_file = fdopen(db_fd, "w")) == NULL) {
1078
log_error("Can't fdopen new lease file: %m");
1083
/* Close previous database, if any. */
1086
db_file = new_db_file;
1089
fprintf (db_file, "# The format of this file is documented in the %s",
1090
"dhcpd.leases(5) manual page.\n");
1094
fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
1099
/* At this point we have a new lease file that, so far, could not
1100
* be described as either corrupt nor valid.
1102
lease_file_is_corrupt = 0;
1104
/* Write out all the leases that we know of... */
1106
if (!write_leases ())
1109
#if defined (TRACING)
1110
if (!trace_playback ()) {
1112
/* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1113
* This should never happen since the path is a configuration
1114
* variable from build-time or command-line. But if it should,
1115
* either by malice or ignorance, we panic, since the potential
1116
* for havoc is too high.
1118
if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
1119
>= sizeof backfname)
1120
log_fatal("new_lease_file: backup lease file path too long");
1122
/* Get the old database out of the way... */
1123
if (unlink (backfname) < 0 && errno != ENOENT) {
1124
log_error ("Can't remove old lease database backup %s: %m",
1128
if (link(path_dhcpd_db, backfname) < 0) {
1129
if (errno == ENOENT) {
1130
log_error("%s is missing - no lease db to backup.",
1133
log_error("Can't backup lease database %s to %s: %m",
1134
path_dhcpd_db, backfname);
1138
#if defined (TRACING)
1142
/* Move in the new file... */
1143
if (rename (newfname, path_dhcpd_db) < 0) {
1144
log_error ("Can't install new lease database %s to %s: %m",
1145
newfname, path_dhcpd_db);
1153
lease_file_is_corrupt = db_validity;
1159
int group_writer (struct group_object *group)
1161
if (!write_group (group))
1163
if (!commit_leases ())