]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/db.c
Fix compilation errors introduced in the last set of checkins.
[thirdparty/dhcp.git] / server / db.c
CommitLineData
1358b874
TL
1/* db.c
2
3 Persistent database management routines for DHCPD... */
4
5/*
f39b6e00
TL
6 * Copyright (c) 1996-1999 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
1358b874 12 *
f39b6e00 13 * http://www.isc.org/isc-license-1.0.html.
1358b874 14 *
f39b6e00
TL
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
1358b874 18 *
f39b6e00
TL
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
1358b874
TL
21 */
22
23#ifndef lint
24static char copyright[] =
4bd8800e 25"$Id: db.c,v 1.42 2000/01/26 14:56:18 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
1358b874
TL
26#endif /* not lint */
27
28#include "dhcpd.h"
0ebffe9c 29#include <ctype.h>
1358b874
TL
30
31FILE *db_file;
32
08804a9a
TL
33static int counting = 0;
34static int count = 0;
35TIME write_time;
36
1358b874
TL
37/* Write the specified lease to the current lease database file. */
38
39int write_lease (lease)
40 struct lease *lease;
41{
42 struct tm *t;
43 char tbuf [64];
a3115043 44 int errors = 0;
6fdff3b8 45 int i;
ea4eec7e 46 struct binding *b;
1358b874 47
08804a9a
TL
48 if (counting)
49 ++count;
1358b874 50 errno = 0;
a3115043
TL
51 fprintf (db_file, "lease %s {\n", piaddr (lease -> ip_addr));
52 if (errno) {
53 ++errors;
54 }
1358b874 55
3f165a40
TL
56 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
57 somebody invents a time machine, I think we can safely disregard
58 it. */
612fded7
TL
59 if (lease -> starts != MAX_TIME) {
60 t = gmtime (&lease -> starts);
61 sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
62 t -> tm_wday, t -> tm_year + 1900,
63 t -> tm_mon + 1, t -> tm_mday,
64 t -> tm_hour, t -> tm_min, t -> tm_sec);
65 } else
b5fa877f 66 strcpy (tbuf, "never;");
a3115043 67 errno = 0;
d00855e0 68 fprintf (db_file, " starts %s\n", tbuf);
a3115043
TL
69 if (errno) {
70 ++errors;
71 }
1358b874 72
612fded7
TL
73 if (lease -> ends != MAX_TIME) {
74 t = gmtime (&lease -> ends);
75 sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
76 t -> tm_wday, t -> tm_year + 1900,
77 t -> tm_mon + 1, t -> tm_mday,
78 t -> tm_hour, t -> tm_min, t -> tm_sec);
79 } else
b5fa877f 80 strcpy (tbuf, "never;");
a3115043 81 errno = 0;
d00855e0 82 fprintf (db_file, " ends %s", tbuf);
a3115043
TL
83 if (errno) {
84 ++errors;
85 }
1358b874 86
ea4eec7e
TL
87 if (lease -> tstp) {
88 t = gmtime (&lease -> tstp);
89 errno = 0;
d00855e0 90 fprintf (db_file, "\n tstp %d %d/%02d/%02d %02d:%02d:%02d;",
ea4eec7e
TL
91 t -> tm_wday, t -> tm_year + 1900,
92 t -> tm_mon + 1, t -> tm_mday,
93 t -> tm_hour, t -> tm_min, t -> tm_sec);
94 if (errno) {
95 ++errors;
96 }
fa674baf 97 }
ea4eec7e
TL
98 if (lease -> tsfp) {
99 t = gmtime (&lease -> tsfp);
100 errno = 0;
d00855e0 101 fprintf (db_file, "\n tsfp %d %d/%02d/%02d %02d:%02d:%02d;",
ea4eec7e
TL
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 if (errno) {
106 ++errors;
107 }
fa674baf
TL
108 }
109
110 if (lease -> flags & PEER_IS_OWNER) {
111 errno = 0;
d00855e0 112 fprintf (db_file, "\n peer is owner;");
fa674baf
TL
113 if (errno) {
114 ++errors;
115 }
116 }
fa674baf 117
e2bfe7b3
TL
118 /* If this lease is billed to a class and is still valid,
119 write it out. */
120 if (lease -> billing_class && lease -> ends > cur_time)
121 if (!write_billing_class (lease -> billing_class))
122 ++errors;
123
1358b874 124 if (lease -> hardware_addr.hlen) {
a3115043 125 errno = 0;
d00855e0 126 fprintf (db_file, "\n hardware %s %s;",
fa674baf
TL
127 hardware_types [lease -> hardware_addr.hbuf [0]],
128 print_hw_addr (lease -> hardware_addr.hbuf [0],
129 lease -> hardware_addr.hlen - 1,
130 &lease -> hardware_addr.hbuf [1]));
a3115043
TL
131 if (errno) {
132 ++errors;
133 }
1358b874
TL
134 }
135 if (lease -> uid_len) {
136 int i;
b1b7b521 137 if (db_printable_len ((const char *)lease -> uid,
77a5f871 138 lease -> uid_len)) {
d00855e0 139 fprintf (db_file, "\n uid \"%*s\";",
b1b7b521 140 lease -> uid_len, lease -> uid);
daaeeac1 141 } else {
a3115043 142 errno = 0;
d00855e0 143 fprintf (db_file, "\n uid %2.2x", lease -> uid [0]);
a3115043
TL
144 if (errno) {
145 ++errors;
146 }
daaeeac1
TL
147 for (i = 1; i < lease -> uid_len; i++) {
148 errno = 0;
149 fprintf (db_file, ":%2.2x", lease -> uid [i]);
150 if (errno) {
151 ++errors;
152 }
153 }
154 putc (';', db_file);
a3115043 155 }
a3115043
TL
156 }
157 if (lease -> flags & BOOTP_LEASE) {
158 errno = 0;
d00855e0 159 fprintf (db_file, "\n dynamic-bootp;");
a3115043 160 if (errno) {
4006d804
TL
161 ++errors;
162 }
163 }
164 if (lease -> flags & ABANDONED_LEASE) {
165 errno = 0;
d00855e0 166 fprintf (db_file, "\n abandoned;");
4006d804 167 if (errno) {
a3115043 168 ++errors;
00d6d87c
TL
169 }
170 }
d00855e0
TL
171 for (b = lease -> scope.bindings; b; b = b -> next) {
172 if (b -> value.data) {
173 if (db_printable_len (b -> value.data,
174 b -> value.len)) {
ea4eec7e 175 errno = 0;
d00855e0
TL
176 fprintf (db_file, "\n set %s = \"%.*s\";",
177 b -> name,
178 (int)b -> value.len, b -> value.data);
ea4eec7e
TL
179 } else {
180 errno = 0;
d00855e0 181 fprintf (db_file, "\n set %s = ", b -> name);
ea4eec7e
TL
182 if (errno) {
183 ++errors;
184 }
185 for (i = 0; i < b -> value.len; i++) {
186 errno = 0;
187 fprintf (db_file, "%2.2x%s",
188 b -> value.data [i],
189 i + 1 == b -> value.len
d00855e0 190 ? "" : ":");
ea4eec7e
TL
191 if (errno) {
192 ++errors;
193 }
194 }
195 putc (';', db_file);
196 }
d00855e0 197 }
0ebffe9c
TL
198 }
199 if (lease -> client_hostname &&
200 db_printable (lease -> client_hostname)) {
00d6d87c 201 errno = 0;
d00855e0 202 fprintf (db_file, "\n client-hostname \"%s\";",
00d6d87c
TL
203 lease -> client_hostname);
204 if (errno) {
205 ++errors;
206 }
207 }
0ebffe9c 208 if (lease -> hostname && db_printable (lease -> hostname)) {
00d6d87c 209 errno = 0;
d00855e0 210 fprintf (db_file, "\n hostname \"%s\";",
36b65b9c 211 lease -> hostname);
00d6d87c
TL
212 if (errno) {
213 ++errors;
a3115043
TL
214 }
215 }
fa098be8
TL
216 if (lease -> on_expiry) {
217 errno = 0;
d00855e0 218 fprintf (db_file, "\n on expiry%s {",
ea4eec7e 219 lease -> on_expiry == lease -> on_release
d00855e0 220 ? " or release" : "");
fa098be8
TL
221 if (errno)
222 ++errors;
d00855e0 223 write_statements (db_file, lease -> on_expiry, 4);
fa098be8 224 /* XXX */
d00855e0 225 fprintf (db_file, "\n }");
fa098be8 226 }
ea4eec7e 227 if (lease -> on_release && lease -> on_release != lease -> on_expiry) {
fa098be8 228 errno = 0;
d00855e0 229 fprintf (db_file, "\n on release {");
fa098be8
TL
230 if (errno)
231 ++errors;
d00855e0 232 write_statements (db_file, lease -> on_release, 4);
fa098be8 233 /* XXX */
d00855e0 234 fprintf (db_file, "\n }");
fa098be8 235 }
a3115043
TL
236 errno = 0;
237 fputs ("\n}\n", db_file);
238 if (errno) {
239 ++errors;
1358b874 240 }
a3115043 241 if (errors)
8ae2d595 242 log_info ("write_lease: unable to write lease %s",
a3115043
TL
243 piaddr (lease -> ip_addr));
244 return !errors;
1358b874
TL
245}
246
612fded7
TL
247int write_host (host)
248 struct host_decl *host;
249{
250 int errors = 0;
251 int i;
252 struct data_string ip_addrs;
253
254 if (!db_printable (host -> name))
255 return 0;
256
257 if (counting)
258 ++count;
259 errno = 0;
260
261 fprintf (db_file, "host %s {", host -> name);
262 if (errno) {
263 ++errors;
264 }
265
fafd89d2 266 if (host -> flags & HOST_DECL_DYNAMIC) {
612fded7 267 errno = 0;
d00855e0 268 fprintf (db_file, "\n dynamic;");
fafd89d2 269 if (errno)
612fded7 270 ++errors;
612fded7 271 }
fafd89d2
TL
272
273 if (host -> flags & HOST_DECL_DELETED) {
612fded7 274 errno = 0;
d00855e0 275 fprintf (db_file, "\n deleted;");
fafd89d2 276 if (errno)
612fded7 277 ++errors;
fafd89d2
TL
278 } else {
279 if (host -> interface.hlen) {
280 errno = 0;
d00855e0 281 fprintf (db_file, "\n hardware %s %s;",
fa674baf
TL
282 hardware_types [host -> interface.hbuf [0]],
283 print_hw_addr (host -> interface.hbuf [0],
284 host -> interface.hlen - 1,
285 &host -> interface.hbuf [1]));
fafd89d2
TL
286 if (errno) {
287 ++errors;
288 }
612fded7 289 }
fafd89d2
TL
290 if (host -> client_identifier.len) {
291 int i;
612fded7 292 errno = 0;
b1b7b521 293 if (db_printable_len ((const char *)
77a5f871 294 host -> client_identifier.data,
daaeeac1 295 host -> client_identifier.len)) {
d00855e0 296 fprintf (db_file, "\n uid \"%*s\";",
daaeeac1
TL
297 host -> client_identifier.len,
298 host -> client_identifier.data);
299 } else {
300 fprintf (db_file,
d00855e0 301 "\n uid %2.2x",
daaeeac1 302 host -> client_identifier.data [0]);
fafd89d2
TL
303 if (errno) {
304 ++errors;
305 }
daaeeac1
TL
306 for (i = 1;
307 i < host -> client_identifier.len; i++) {
308 errno = 0;
309 fprintf (db_file, ":%2.2x",
310 host ->
311 client_identifier.data [i]);
312 if (errno) {
313 ++errors;
314 }
315 }
316 putc (';', db_file);
fafd89d2 317 }
612fded7 318 }
612fded7 319
daaeeac1 320 memset (&ip_addrs, 0, sizeof ip_addrs);
fafd89d2
TL
321 if (host -> fixed_addr &&
322 evaluate_option_cache (&ip_addrs, (struct packet *)0,
323 (struct lease *)0,
324 (struct option_state *)0,
325 (struct option_state *)0,
d00855e0 326 &global_scope,
4bd8800e 327 host -> fixed_addr, MDL)) {
fafd89d2 328
daaeeac1 329 errno = 0;
d00855e0 330 fprintf (db_file, "\n fixed-address ");
612fded7
TL
331 if (errno) {
332 ++errors;
333 }
fafd89d2 334 for (i = 0; i < ip_addrs.len - 3; i += 4) {
daaeeac1
TL
335 errno = 0;
336 fprintf (db_file, "%d.%d.%d.%d%s",
fafd89d2
TL
337 ip_addrs.data [i],
338 ip_addrs.data [i + 1],
339 ip_addrs.data [i + 2],
340 ip_addrs.data [i + 3],
341 i + 7 < ip_addrs.len ? "," : "");
342 if (errno) {
343 ++errors;
344 }
345 }
daaeeac1
TL
346 errno = 0;
347 fputc (';', db_file);
348 if (errno) {
349 ++errors;
350 }
351 }
352
353 if (host -> named_group) {
354 errno = 0;
d00855e0 355 fprintf (db_file, "\n group \"%s\";",
daaeeac1
TL
356 host -> named_group -> name);
357 if (errno) {
358 ++errors;
359 }
360 }
361
d70e89d4
TL
362 if (host -> group &&
363 (!host -> named_group ||
dff4af5c
TL
364 host -> group != host -> named_group -> group) &&
365 host -> group != &root_group) {
daaeeac1
TL
366 errno = 0;
367 write_statements (db_file,
368 host -> group -> statements, 8);
369 if (errno) {
370 ++errors;
371 }
612fded7
TL
372 }
373 }
374
375 errno = 0;
376 fputs ("\n}\n", db_file);
377 if (errno) {
378 ++errors;
379 }
380 if (errors)
381 log_info ("write_host: unable to write host %s",
382 host -> name);
383 return !errors;
384}
385
daaeeac1
TL
386int write_group (group)
387 struct group_object *group;
388{
3b7c3de9
TL
389 int errors = 0;
390 int i;
391
392 if (!db_printable (group -> name))
393 return 0;
394
395 if (counting)
396 ++count;
397 errno = 0;
398
399 fprintf (db_file, "group %s {", group -> name);
400 if (errno) {
401 ++errors;
402 }
403
404 if (group -> flags & GROUP_OBJECT_DYNAMIC) {
405 errno = 0;
d00855e0 406 fprintf (db_file, "\n dynamic;");
3b7c3de9
TL
407 if (errno)
408 ++errors;
409 }
410
411 if (group -> flags & GROUP_OBJECT_STATIC) {
412 errno = 0;
d00855e0 413 fprintf (db_file, "\n static;");
3b7c3de9
TL
414 if (errno)
415 ++errors;
416 }
417
418 if (group -> flags & GROUP_OBJECT_DELETED) {
419 errno = 0;
d00855e0 420 fprintf (db_file, "\n deleted;");
3b7c3de9
TL
421 if (errno)
422 ++errors;
423 } else {
424 if (group -> group) {
425 errno = 0;
426 write_statements (db_file,
427 group -> group -> statements, 8);
428 if (errno) {
429 ++errors;
430 }
431 }
432 }
433
434 errno = 0;
435 fputs ("\n}\n", db_file);
436 if (errno) {
437 ++errors;
438 }
439 if (errors)
440 log_info ("write_group: unable to write group %s",
441 group -> name);
442 return !errors;
daaeeac1
TL
443}
444
0ebffe9c 445int db_printable (s)
b1b7b521 446 const char *s;
0ebffe9c
TL
447{
448 int i;
449 for (i = 0; s [i]; i++)
450 if (!isascii (s [i]) || !isprint (s [i]))
451 return 0;
452 return 1;
453}
454
daaeeac1 455int db_printable_len (s, len)
b1b7b521
TL
456 const char *s;
457 unsigned len;
daaeeac1
TL
458{
459 int i;
460 for (i = 0; i < len; i++)
461 if (!isascii (s [i]) || !isprint (s [i]))
462 return 0;
463 return 1;
464}
465
e2bfe7b3
TL
466/* Write a spawned class to the database file. */
467
468int write_billing_class (class)
469 struct class *class;
470{
471 int errors = 0;
472 int i;
473
474 if (!class -> superclass) {
475 errno = 0;
d00855e0 476 fprintf (db_file, "\n billing class \"%s\";", class -> name);
e2bfe7b3
TL
477 return !errno;
478 }
479
480 errno = 0;
d00855e0 481 fprintf (db_file, "\n billing subclass \"%s\"",
e2bfe7b3
TL
482 class -> superclass -> name);
483 if (errno)
484 ++errors;
485
486 for (i = 0; i < class -> hash_string.len; i++)
487 if (!isascii (class -> hash_string.data [i]) ||
488 !isprint (class -> hash_string.data [i]))
489 break;
490 if (i == class -> hash_string.len) {
491 errno = 0;
b1b7b521 492 fprintf (db_file, " \"%*s\";",
e2bfe7b3
TL
493 class -> hash_string.len,
494 class -> hash_string.data);
495 if (errno)
496 ++errors;
497 } else {
498 errno = 0;
499 fprintf (db_file, " %2.2x", class -> hash_string.data [0]);
500 if (errno)
501 ++errors;
502 for (i = 1; i < class -> hash_string.len; i++) {
503 errno = 0;
504 fprintf (db_file, ":%2.2x",
505 class -> hash_string.data [i]);
506 if (errno)
507 ++errors;
508 }
509 errno = 0;
510 fprintf (db_file, ";");
511 if (errno)
512 ++errors;
513 }
514
515 class -> dirty = 0;
516 return !errors;
517}
518
1358b874
TL
519/* Commit any leases that have been written out... */
520
521int commit_leases ()
522{
a3115043
TL
523 /* Commit any outstanding writes to the lease database file.
524 We need to do this even if we're rewriting the file below,
525 just in case the rewrite fails. */
526 if (fflush (db_file) == EOF) {
8ae2d595 527 log_info ("commit_leases: unable to commit: %m");
a3115043
TL
528 return 0;
529 }
530 if (fsync (fileno (db_file)) < 0) {
8ae2d595 531 log_info ("commit_leases: unable to commit: %m");
a3115043
TL
532 return 0;
533 }
534
08804a9a
TL
535 /* If we've written more than a thousand leases or if
536 we haven't rewritten the lease database in over an
537 hour, rewrite it now. */
538 if (count > 1000 || (count && cur_time - write_time > 3600)) {
539 count = 0;
540 write_time = cur_time;
541 new_lease_file ();
08804a9a 542 }
1358b874
TL
543 return 1;
544}
545
3b7c3de9
TL
546void db_startup (testp)
547 int testp;
1358b874
TL
548{
549 /* Read in the existing lease file... */
550 read_leases ();
551
3b7c3de9 552 if (!testp) {
96359f83 553 db_file = fopen (path_dhcpd_db, "a");
05743349 554 expire_all_pools ();
3b7c3de9
TL
555 GET_TIME (&write_time);
556 new_lease_file ();
557 }
1358b874
TL
558}
559
560void new_lease_file ()
561{
562 char newfname [512];
563 char backfname [512];
564 TIME t;
30856538 565 int db_fd;
1358b874
TL
566
567 /* If we already have an open database, close it. */
568 if (db_file) {
569 fclose (db_file);
570 }
571
572 /* Make a temporary lease file... */
b16b7f33
TL
573 GET_TIME (&t);
574 sprintf (newfname, "%s.%d", path_dhcpd_db, (int)t);
30856538
TL
575 db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
576 if (db_fd < 0) {
8ae2d595 577 log_fatal ("Can't create new lease file: %m");
30856538
TL
578 }
579 if ((db_file = fdopen (db_fd, "w")) == NULL) {
8ae2d595 580 log_fatal ("Can't fdopen new lease file!");
1358b874
TL
581 }
582
8f65e88d
TL
583 /* Write an introduction so people don't complain about time
584 being off. */
585 fprintf (db_file, "# All times in this file are in UTC (GMT), not %s",
586 "your local timezone. This is\n");
587 fprintf (db_file, "# not a bug, so please don't ask about it. %s",
468746fe
TL
588 "There is no portable way to\n");
589 fprintf (db_file, "# store leases in the local timezone, so please %s",
590 "don't request this as a\n");
591 fprintf (db_file, "# feature. If this is inconvenient or %s",
592 "confusing to you, we sincerely\n");
593 fprintf (db_file, "# apologize. Seriously, though - don't ask.\n");
594 fprintf (db_file, "# The format of this file is documented in the %s",
595 "dhcpd.leases(5) manual page.\n\n");
8f65e88d 596
1358b874 597 /* Write out all the leases that we know of... */
08804a9a 598 counting = 0;
1358b874
TL
599 write_leases ();
600
601 /* Get the old database out of the way... */
e2ac5814 602 sprintf (backfname, "%s~", path_dhcpd_db);
a3115043 603 if (unlink (backfname) < 0 && errno != ENOENT)
8ae2d595 604 log_fatal ("Can't remove old lease database backup %s: %m",
a3115043 605 backfname);
e2ac5814 606 if (link (path_dhcpd_db, backfname) < 0)
8ae2d595 607 log_fatal ("Can't backup lease database %s to %s: %m",
e2ac5814 608 path_dhcpd_db, backfname);
1358b874
TL
609
610 /* Move in the new file... */
e2ac5814 611 if (rename (newfname, path_dhcpd_db) < 0)
8ae2d595 612 log_fatal ("Can't install new lease database %s to %s: %m",
e2ac5814 613 newfname, path_dhcpd_db);
08804a9a
TL
614
615 counting = 1;
1358b874 616}