1 /* db.c
2 
3    Persistent database management routines for DHCPD... */
4 
5 /*
6  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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  *   https://www.isc.org/
26  *
27  */
28 
29 #include "dhcpd.h"
30 #include <ctype.h>
31 #include <errno.h>
32 
33 #define LEASE_REWRITE_PERIOD 3600
34 
35 static isc_result_t write_binding_scope(FILE *db_file, struct binding *bnd,
36 					char *prepend);
37 
38 FILE *db_file;
39 
40 static int counting = 0;
41 static int count = 0;
42 TIME write_time;
43 int lease_file_is_corrupt = 0;
44 
45 /* Write a single binding scope value in parsable format.
46  */
47 
48 static isc_result_t
write_binding_scope(FILE * db_file,struct binding * bnd,char * prepend)49 write_binding_scope(FILE *db_file, struct binding *bnd, char *prepend) {
50 	char *s;
51 
52 	if ((db_file == NULL) || (bnd == NULL) || (prepend == NULL))
53 		return DHCP_R_INVALIDARG;
54 
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);
59 			if (s != NULL) {
60 				errno = 0;
61 				fprintf(db_file, "%sset %s = %s;",
62 					prepend, bnd->name, s);
63 				dfree(s, MDL);
64 				if (errno)
65 					return ISC_R_FAILURE;
66 			} else {
67 			    return ISC_R_FAILURE;
68 			}
69 		}
70 	} else if (bnd->value->type == binding_numeric) {
71 		errno = 0;
72 		fprintf(db_file, "%sset %s = %%%ld;", prepend,
73 			bnd->name, bnd->value->value.intval);
74 		if (errno)
75 			return ISC_R_FAILURE;
76 	} else if (bnd->value->type == binding_boolean) {
77 		errno = 0;
78 		fprintf(db_file, "%sset %s = %s;", prepend, bnd->name,
79 			bnd->value->value.intval ? "true" : "false");
80 		if (errno)
81 			return ISC_R_FAILURE;
82 	} else if (bnd->value->type == binding_dns) {
83 		log_error("%s: persistent dns values not supported.",
84 			  bnd->name);
85 	} else if (bnd->value->type == binding_function) {
86 		log_error("%s: persistent functions not supported.",
87 			  bnd->name);
88 	} else {
89 		log_fatal("%s: unknown binding type %d", bnd->name,
90 			  bnd->value->type);
91 	}
92 
93 	return ISC_R_SUCCESS;
94 }
95 
96 /* Write the specified lease to the current lease database file. */
97 
write_lease(lease)98 int write_lease (lease)
99 	struct lease *lease;
100 {
101 	int errors = 0;
102 	struct binding *b;
103 	char *s;
104 	const char *tval;
105 
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 (0))
110 			return 0;
111 
112 	if (counting)
113 		++count;
114 	errno = 0;
115 	fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
116 	if (errno) {
117 		++errors;
118 	}
119 
120 	if (lease->starts &&
121 	    ((tval = print_time(lease->starts)) == NULL ||
122 	     fprintf(db_file, "\n  starts %s", tval) < 0))
123 		++errors;
124 
125 	if (lease->ends &&
126 	    ((tval = print_time(lease->ends)) == NULL ||
127 	     fprintf(db_file, "\n  ends %s", tval) < 0))
128 		++errors;
129 
130 	if (lease->tstp &&
131 	    ((tval = print_time(lease->tstp)) == NULL ||
132 	     fprintf(db_file, "\n  tstp %s", tval) < 0))
133 		++errors;
134 
135 	if (lease->tsfp &&
136 	    ((tval = print_time(lease->tsfp)) == NULL ||
137 	     fprintf(db_file, "\n  tsfp %s", tval) < 0))
138 		++errors;
139 
140 	if (lease->atsfp &&
141 	    ((tval = print_time(lease->atsfp)) == NULL ||
142 	     fprintf(db_file, "\n  atsfp %s", tval) < 0))
143 		++errors;
144 
145 	if (lease->cltt &&
146 	    ((tval = print_time(lease->cltt)) == NULL ||
147 	     fprintf(db_file, "\n  cltt %s", tval) < 0))
148 		++errors;
149 
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]
154 		  : "abandoned")) < 0)
155                 ++errors;
156 
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])
163 			  : "abandoned")) < 0)
164                         ++errors;
165 
166 	/*
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.
172 	 */
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)
178 			++errors;
179 
180 	if (lease->flags & RESERVED_LEASE)
181 		if (fprintf(db_file, "\n  reserved;") < 0)
182                         ++errors;
183 
184 	if (lease->flags & BOOTP_LEASE)
185 		if (fprintf(db_file, "\n  dynamic-bootp;") < 0)
186                         ++errors;
187 
188 	/* If this lease is billed to a class and is still valid,
189 	   write it out. */
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);
194 			++errors;
195 		}
196 	}
197 
198 	if (lease -> hardware_addr.hlen) {
199 		errno = 0;
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]));
205 		if (errno)
206 			++errors;
207 	}
208 	if (lease -> uid_len) {
209 		s = format_lease_id(lease->uid, lease->uid_len, lease_id_format,
210 				    MDL);
211 		if (s) {
212 			errno = 0;
213 			fprintf (db_file, "\n  uid %s;", s);
214 			if (errno)
215 				++errors;
216 			dfree (s, MDL);
217 		} else
218 			++errors;
219 	}
220 
221 	if (lease->scope != NULL) {
222 	    for (b = lease->scope->bindings; b; b = b->next) {
223 		if (!b->value)
224 			continue;
225 
226 		if (write_binding_scope(db_file, b, "\n  ") != ISC_R_SUCCESS)
227 			++errors;
228 	    }
229 	}
230 
231 	if (lease -> agent_options) {
232 	    struct option_cache *oc;
233 	    struct data_string ds;
234 	    pair p;
235 
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) {
240 	    	errno = 0;
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));
245 	    	if (errno)
246 		    ++errors;
247 	        }
248 	    }
249 	}
250 	if (lease -> client_hostname &&
251 	    db_printable((unsigned char *)lease->client_hostname)) {
252 		s = quotify_string (lease -> client_hostname, MDL);
253 		if (s) {
254 			errno = 0;
255 			fprintf (db_file, "\n  client-hostname \"%s\";", s);
256 			if (errno)
257 				++errors;
258 			dfree (s, MDL);
259 		} else
260 			++errors;
261 	}
262 	if (lease->on_star.on_expiry) {
263 		errno = 0;
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);
268 		/* XXX */
269 		fprintf (db_file, "\n  }");
270 		if (errno)
271 			++errors;
272 	}
273 	if (lease->on_star.on_release &&
274 	    lease->on_star.on_release != lease->on_star.on_expiry) {
275 		errno = 0;
276 		fprintf (db_file, "\n  on release {");
277 		write_statements (db_file, lease->on_star.on_release, 4);
278 		/* XXX */
279 		fprintf (db_file, "\n  }");
280 		if (errno)
281 			++errors;
282 	}
283 
284 	errno = 0;
285 	fputs ("\n}\n", db_file);
286 	if (errno)
287 		++errors;
288 
289 	if (errors) {
290 		log_info ("write_lease: unable to write lease %s",
291 		      piaddr (lease -> ip_addr));
292 		lease_file_is_corrupt = 1;
293         }
294 
295 	return !errors;
296 }
297 
write_host(host)298 int write_host (host)
299 	struct host_decl *host;
300 {
301 	int errors = 0;
302 	int i;
303 	struct data_string ip_addrs;
304 
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 (0))
309 			return 0;
310 
311 	if (!db_printable((unsigned char *)host->name))
312 		return 0;
313 
314 	if (counting)
315 		++count;
316 
317 	errno = 0;
318 	fprintf (db_file, "host %s {", host -> name);
319 	if (errno)
320 		++errors;
321 
322 	if (host -> flags & HOST_DECL_DYNAMIC) {
323 		errno = 0;
324 		fprintf (db_file, "\n  dynamic;");
325 		if (errno)
326 			++errors;
327 	}
328 
329 	if (host -> flags & HOST_DECL_DELETED) {
330 		errno = 0;
331 		fprintf (db_file, "\n  deleted;");
332 		if (errno)
333 			++errors;
334 	} else {
335 		if (host -> interface.hlen) {
336 			errno = 0;
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]));
342 			if (errno)
343 				++errors;
344 		}
345 		if (host -> client_identifier.len) {
346 			int i;
347 			errno = 0;
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);
353 				if (errno)
354 					++errors;
355 			} else {
356 				fprintf (db_file,
357 					 "\n  uid %2.2x",
358 					 host -> client_identifier.data [0]);
359 				if (errno)
360 					++errors;
361 				for (i = 1;
362 				     i < host -> client_identifier.len; i++) {
363 					errno = 0;
364 					fprintf (db_file, ":%2.2x",
365 						 host ->
366 						 client_identifier.data [i]);
367 					if (errno)
368 						++errors;
369 				}
370 
371                                 errno = 0;
372 				fputc (';', db_file);
373 				if (errno)
374 					++errors;
375 			}
376 		}
377 
378 		memset (&ip_addrs, 0, sizeof ip_addrs);
379 		if (host -> fixed_addr &&
380 		    evaluate_option_cache (&ip_addrs, (struct packet *)0,
381 					   (struct lease *)0,
382 					   (struct client_state *)0,
383 					   (struct option_state *)0,
384 					   (struct option_state *)0,
385 					   &global_scope,
386 					   host -> fixed_addr, MDL)) {
387 
388 			errno = 0;
389 			fprintf (db_file, "\n  fixed-address ");
390 			if (errno)
391 				++errors;
392 			for (i = 0; i < ip_addrs.len - 3; i += 4) {
393 
394 				errno = 0;
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 ? "," : "");
401 				if (errno)
402 					++errors;
403 			}
404 
405 			/* We're done with ip_addrs so pitch it */
406 			data_string_forget (&ip_addrs, MDL);
407 
408 			errno = 0;
409 			fputc (';', db_file);
410 			if (errno)
411 				++errors;
412 
413 		}
414 
415 		if (host -> named_group) {
416 			errno = 0;
417 			fprintf (db_file, "\n  group \"%s\";",
418 				 host -> named_group -> name);
419 			if (errno)
420 				++errors;
421 		}
422 
423 		if (host -> group &&
424 		    (!host -> named_group ||
425 		     host -> group != host -> named_group -> group) &&
426 		    host -> group != root_group) {
427 			errno = 0;
428 			write_statements (db_file,
429 					  host -> group -> statements, 8);
430 			if (errno)
431 				++errors;
432 		}
433 	}
434 
435 	errno = 0;
436 	fputs ("\n}\n", db_file);
437 	if (errno)
438 		++errors;
439 
440 	if (errors) {
441 		log_info ("write_host: unable to write host %s",
442 			  host -> name);
443 		lease_file_is_corrupt = 1;
444 	}
445 
446 	return !errors;
447 }
448 
write_group(group)449 int write_group (group)
450 	struct group_object *group;
451 {
452 	int errors = 0;
453 
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 (0))
458 			return 0;
459 
460 	if (!db_printable((unsigned char *)group->name))
461 		return 0;
462 
463 	if (counting)
464 		++count;
465 
466 	errno = 0;
467 	fprintf (db_file, "group %s {", group -> name);
468 	if (errno)
469 		++errors;
470 
471 	if (group -> flags & GROUP_OBJECT_DYNAMIC) {
472 		errno = 0;
473 		fprintf (db_file, "\n  dynamic;");
474 		if (errno)
475 			++errors;
476 	}
477 
478 	if (group -> flags & GROUP_OBJECT_STATIC) {
479 		errno = 0;
480 		fprintf (db_file, "\n  static;");
481 		if (errno)
482 			++errors;
483 	}
484 
485 	if (group -> flags & GROUP_OBJECT_DELETED) {
486 		errno = 0;
487 		fprintf (db_file, "\n  deleted;");
488 		if (errno)
489 			++errors;
490 	} else {
491 		if (group -> group) {
492 			errno = 0;
493 			write_statements (db_file,
494 					  group -> group -> statements, 8);
495 			if (errno)
496 				++errors;
497 		}
498 	}
499 
500 	errno = 0;
501 	fputs ("\n}\n", db_file);
502 	if (errno)
503 		++errors;
504 
505 	if (errors) {
506 		log_info ("write_group: unable to write group %s",
507 			  group -> name);
508 		lease_file_is_corrupt = 1;
509 	}
510 
511 	return !errors;
512 }
513 
514 /*
515  * Write an IA and the options it has.
516  */
517 int
write_ia(const struct ia_xx * ia)518 write_ia(const struct ia_xx *ia) {
519 	struct iasubopt *iasubopt;
520 	struct binding *bnd;
521 	int i;
522 	char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff.255.255.255.255")];
523 	const char *binding_state;
524 	const char *tval;
525 	char *s;
526 	int fprintf_ret;
527 
528 #ifdef EUI_64
529 	/* If we're not writing EUI64 leases to the file, then
530 	* we can skip writing this IA provided all of its leases
531 	* are EUI64. (Not sure you can ever have a case where
532 	* they aren't but doesn't hurt to check) */
533 	if (ia->ia_type == D6O_IA_NA && !persist_eui64) {
534 		int i;
535 		for (i=0; i < ia->num_iasubopt; i++) {
536 			if (!ia->iasubopt[i]->ipv6_pool->ipv6_pond->use_eui_64)
537 			{
538 				break;
539 			}
540 		}
541 
542 		if (i == ia->num_iasubopt) {
543 			/* Their all EUI64 so we can skip it */
544 			return(1);
545 		}
546 	}
547 #endif
548 
549 	/*
550 	 * If the lease file is corrupt, don't try to write any more
551 	 * leases until we've written a good lease file.
552 	 */
553 	if (lease_file_is_corrupt) {
554 		if (!new_lease_file(0)) {
555 			return 0;
556 		}
557 	}
558 
559 	if (counting) {
560 		++count;
561 	}
562 
563 	s = format_lease_id(ia->iaid_duid.data, ia->iaid_duid.len,
564 			    lease_id_format, MDL);
565 	if (s == NULL) {
566 		goto error_exit;
567 	}
568 	switch (ia->ia_type) {
569 	case D6O_IA_NA:
570 		fprintf_ret = fprintf(db_file, "ia-na %s {\n", s);
571 		break;
572 	case D6O_IA_TA:
573 		fprintf_ret = fprintf(db_file, "ia-ta %s {\n", s);
574 		break;
575 	case D6O_IA_PD:
576 		fprintf_ret = fprintf(db_file, "ia-pd %s {\n", s);
577 		break;
578 	default:
579 		log_error("Unknown ia type %u for %s at %s:%d",
580 			  (unsigned)ia->ia_type, s, MDL);
581 		fprintf_ret = -1;
582 	}
583 	dfree(s, MDL);
584 	if (fprintf_ret < 0) {
585 		goto error_exit;
586 	}
587 	if (ia->cltt != MIN_TIME) {
588 		tval = print_time(ia->cltt);
589 		if (tval == NULL) {
590 			goto error_exit;
591 		}
592 		if (fprintf(db_file, "  cltt %s\n", tval) < 0) {
593 			goto error_exit;
594 		}
595 	}
596 	for (i=0; i<ia->num_iasubopt; i++) {
597 		iasubopt = ia->iasubopt[i];
598 
599 		inet_ntop(AF_INET6, &iasubopt->addr,
600 			  addr_buf, sizeof(addr_buf));
601 		if ((ia->ia_type != D6O_IA_PD) &&
602 		    (fprintf(db_file, "  iaaddr %s {\n", addr_buf) < 0)) {
603 			goto error_exit;
604 		}
605 		if ((ia->ia_type == D6O_IA_PD) &&
606 		    (fprintf(db_file, "  iaprefix %s/%d {\n",
607 			     addr_buf, (int)iasubopt->plen) < 0)) {
608 			goto error_exit;
609 		}
610 		if ((iasubopt->state <= 0) || (iasubopt->state > FTS_LAST)) {
611 			log_fatal("Unknown iasubopt state %d at %s:%d",
612 				  iasubopt->state, MDL);
613 		}
614 		binding_state = binding_state_names[iasubopt->state-1];
615 		if (fprintf(db_file, "    binding state %s;\n",
616 			    binding_state) < 0) {
617 			goto error_exit;
618 		}
619 		if (fprintf(db_file, "    preferred-life %u;\n",
620 			    (unsigned)iasubopt->prefer) < 0) {
621 			goto error_exit;
622 		}
623 		if (fprintf(db_file, "    max-life %u;\n",
624 			    (unsigned)iasubopt->valid) < 0) {
625 			goto error_exit;
626 		}
627 
628 		/* Note that from here on out, the \n is prepended to the
629 		 * next write, rather than appended to the current write.
630 		 */
631 		if ((iasubopt->state == FTS_ACTIVE) ||
632 		    (iasubopt->state == FTS_ABANDONED) ||
633 		    (iasubopt->hard_lifetime_end_time != 0)) {
634 			tval = print_time(iasubopt->hard_lifetime_end_time);
635 		} else {
636 			tval = print_time(iasubopt->soft_lifetime_end_time);
637 		}
638 		if (tval == NULL) {
639 			goto error_exit;
640 		}
641 		if (fprintf(db_file, "    ends %s", tval) < 0) {
642 			goto error_exit;
643 		}
644 
645 		/* Write out any binding scopes: note that 'ends' above does
646 		 * not have \n on the end!  We want that.
647 		 */
648 		if (iasubopt->scope != NULL)
649 			bnd = iasubopt->scope->bindings;
650 		else
651 			bnd = NULL;
652 
653 		for (; bnd != NULL ; bnd = bnd->next) {
654 			if (bnd->value == NULL)
655 				continue;
656 
657 			/* We don't do a regular error_exit because the
658 			 * lease db is not corrupt in this case.
659 			 */
660 			if (write_binding_scope(db_file, bnd,
661 						"\n    ") != ISC_R_SUCCESS)
662 				goto error_exit;
663 
664 		}
665 
666 		if (iasubopt->on_star.on_expiry) {
667 			if (fprintf(db_file, "\n    on expiry%s {",
668 				    iasubopt->on_star.on_expiry ==
669 				    iasubopt->on_star.on_release
670 				    ? " or release" : "") < 0)
671 				goto error_exit;
672 			write_statements(db_file,
673 					 iasubopt->on_star.on_expiry, 6);
674 			if (fprintf(db_file, "\n    }") < 0)
675 				goto error_exit;
676 		}
677 
678 		if (iasubopt->on_star.on_release &&
679 		    iasubopt->on_star.on_release !=
680 		    iasubopt->on_star.on_expiry) {
681 			if (fprintf(db_file, "\n    on release {") < 0)
682 				goto error_exit;
683 			write_statements(db_file,
684 					 iasubopt->on_star.on_release, 6);
685 			if (fprintf(db_file, "\n    }") < 0)
686 				goto error_exit;
687 		}
688 
689 		if (fprintf(db_file, "\n  }\n") < 0)
690                         goto error_exit;
691 	}
692 	if (fprintf(db_file, "}\n\n") < 0)
693                 goto error_exit;
694 
695 	fflush(db_file);
696 	return 1;
697 
698 error_exit:
699 	log_info("write_ia: unable to write ia");
700 	lease_file_is_corrupt = 1;
701 	return 0;
702 }
703 
704 #ifdef DHCPv6
705 /*
706  * Put a copy of the server DUID in the leases file.
707  */
708 int
write_server_duid(void)709 write_server_duid(void) {
710 	struct data_string server_duid;
711 	char *s;
712 	int fprintf_ret;
713 
714 	/*
715 	 * Only write the DUID if it's been set.
716 	 */
717 	if (!server_duid_isset()) {
718 		return 1;
719 	}
720 
721 	/*
722 	 * If the lease file is corrupt, don't try to write any more
723 	 * leases until we've written a good lease file.
724 	 */
725 	if (lease_file_is_corrupt) {
726 		if (!new_lease_file(0)) {
727 			return 0;
728 		}
729 	}
730 
731 	/*
732 	 * Get a copy of our server DUID and convert to a quoted string.
733 	 */
734 	memset(&server_duid, 0, sizeof(server_duid));
735 	copy_server_duid(&server_duid, MDL);
736 	s = format_lease_id(server_duid.data, server_duid.len, lease_id_format,
737 			    MDL);
738 	data_string_forget(&server_duid, MDL);
739 	if (s == NULL) {
740 		goto error_exit;
741 	}
742 
743 	/*
744 	 * Write to the leases file.
745 	 */
746 	fprintf_ret = fprintf(db_file, "server-duid %s;\n\n", s);
747 	dfree(s, MDL);
748 	if (fprintf_ret < 0) {
749 		goto error_exit;
750 	}
751 
752 	/*
753 	 * Check if we actually managed to write.
754 	 */
755 	fflush(db_file);
756 	return 1;
757 
758 error_exit:
759 	log_info("write_server_duid: unable to write server-duid");
760 	lease_file_is_corrupt = 1;
761 	return 0;
762 }
763 #endif /* DHCPv6 */
764 
765 #if defined (FAILOVER_PROTOCOL)
write_failover_state(dhcp_failover_state_t * state)766 int write_failover_state (dhcp_failover_state_t *state)
767 {
768 	int errors = 0;
769 	const char *tval;
770 
771 	if (lease_file_is_corrupt)
772 		if (!new_lease_file (0))
773 			return 0;
774 
775 	errno = 0;
776 	fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
777 	if (errno)
778 		++errors;
779 
780 	tval = print_time(state->me.stos);
781 	if (tval == NULL ||
782 	    fprintf(db_file, "\n  my state %s at %s",
783 		    (state->me.state == startup) ?
784 		    dhcp_failover_state_name_print(state->saved_state) :
785 		    dhcp_failover_state_name_print(state->me.state),
786 		    tval) < 0)
787 		++errors;
788 
789 	tval = print_time(state->partner.stos);
790 	if (tval == NULL ||
791 	    fprintf(db_file, "\n  partner state %s at %s",
792 		    dhcp_failover_state_name_print(state->partner.state),
793 		    tval) < 0)
794 		++errors;
795 
796 	if (state -> i_am == secondary) {
797 		errno = 0;
798 		fprintf (db_file, "\n  mclt %ld;",
799 			 (unsigned long)state -> mclt);
800 		if (errno)
801 			++errors;
802 	}
803 
804         errno = 0;
805 	fprintf (db_file, "\n}\n");
806 	if (errno)
807 		++errors;
808 
809 	if (errors) {
810 		log_info ("write_failover_state: unable to write state %s",
811 			  state -> name);
812 		lease_file_is_corrupt = 1;
813 		return 0;
814 	}
815 
816 	return 1;
817 
818 }
819 #endif
820 
db_printable(s)821 int db_printable (s)
822 	const unsigned char *s;
823 {
824 	int i;
825 	for (i = 0; s [i]; i++)
826 		if (!isascii (s [i]) || !isprint (s [i])
827 		    || s [i] == '"' || s [i] == '\\')
828 			return 0;
829 	return 1;
830 }
831 
db_printable_len(s,len)832 int db_printable_len (s, len)
833 	const unsigned char *s;
834 	unsigned len;
835 {
836 	int i;
837 
838 	for (i = 0; i < len; i++)
839 		if (!isascii (s [i]) || !isprint (s [i]) ||
840 		    s [i] == '"' || s [i] == '\\')
841 			return 0;
842 	return 1;
843 }
844 
print_hash_string(FILE * fp,struct class * class)845 static int print_hash_string(FILE *fp, struct class *class)
846 {
847 	int i;
848 
849 	for (i = 0 ; i < class->hash_string.len ; i++)
850 		if (!isascii(class->hash_string.data[i]) ||
851 		    !isprint(class->hash_string.data[i]))
852 			break;
853 
854 	if (i == class->hash_string.len) {
855 		if (fprintf(fp, " \"%.*s\"", (int)class->hash_string.len,
856 			    class->hash_string.data) <= 0) {
857 			log_error("Failure writing hash string: %m");
858 			return 0;
859 		}
860 	} else {
861 		if (fprintf(fp, " %2.2x", class->hash_string.data[0]) <= 0) {
862 			log_error("Failure writing hash string: %m");
863 			return 0;
864 		}
865 		for (i = 1 ; i < class->hash_string.len ; i++) {
866 			if (fprintf(fp, ":%2.2x",
867 				    class->hash_string.data[i]) <= 0) {
868 				log_error("Failure writing hash string: %m");
869 				return 0;
870 			}
871 		}
872 	}
873 
874 	return 1;
875 }
876 
877 
878 isc_result_t
write_named_billing_class(const void * key,unsigned len,void * object)879 write_named_billing_class(const void *key, unsigned len, void *object)
880 {
881 	const unsigned char *name = key;
882 	struct class *class = object;
883 
884 	if (class->flags & CLASS_DECL_DYNAMIC) {
885 		numclasseswritten++;
886 		if (class->superclass == 0) {
887 			if (fprintf(db_file, "class \"%s\" {\n", name) <= 0)
888 				return ISC_R_IOERROR;
889 		} else {
890 			if (fprintf(db_file, "subclass \"%s\"",
891 				    class->superclass->name) <= 0)
892 				return ISC_R_IOERROR;
893 			if (!print_hash_string(db_file, class))
894 				return ISC_R_IOERROR;
895 			if (fprintf(db_file, " {\n") <= 0)
896 				return ISC_R_IOERROR;
897 		}
898 
899 		if ((class->flags & CLASS_DECL_DELETED) != 0) {
900 			if (fprintf(db_file, "  deleted;\n") <= 0)
901 				return ISC_R_IOERROR;
902 		} else {
903 			if (fprintf(db_file, "  dynamic;\n") <= 0)
904 				return ISC_R_IOERROR;
905 		}
906 
907 		if (class->lease_limit > 0) {
908 			if (fprintf(db_file, "  lease limit %d;\n",
909 				    class->lease_limit) <= 0)
910 				return ISC_R_IOERROR;
911 		}
912 
913 		if (class->expr != 0) {
914 			if (fprintf(db_file, "  match if ") <= 0)
915 				return ISC_R_IOERROR;
916 
917                         errno = 0;
918 			write_expression(db_file, class->expr, 5, 5, 0);
919                         if (errno)
920                                 return ISC_R_IOERROR;
921 
922 			if (fprintf(db_file, ";\n") <= 0)
923 				return ISC_R_IOERROR;
924 		}
925 
926 		if (class->submatch != 0) {
927 			if (class->spawning) {
928 				if (fprintf(db_file, "  spawn ") <= 0)
929 					return ISC_R_IOERROR;
930 			} else {
931 				if (fprintf(db_file, "  match ") <= 0)
932 					return ISC_R_IOERROR;
933 			}
934 
935                         errno = 0;
936 			write_expression(db_file, class->submatch, 5, 5, 0);
937                         if (errno)
938                                 return ISC_R_IOERROR;
939 
940 			if (fprintf(db_file, ";\n") <= 0)
941 				return ISC_R_IOERROR;
942 		}
943 
944 		if (class->statements != 0) {
945                         errno = 0;
946 			write_statements(db_file, class->statements, 8);
947                         if (errno)
948                                 return ISC_R_IOERROR;
949 		}
950 
951 		/* XXXJAB this isn't right, but classes read in off the
952 		   leases file don't get the root group assigned to them
953 		   (due to clone_group() call). */
954 		if (class->group != 0 && class->group->authoritative != 0) {
955                         errno = 0;
956 			write_statements(db_file, class->group->statements, 8);
957                         if (errno)
958                                 return ISC_R_IOERROR;
959                 }
960 
961 		if (fprintf(db_file, "}\n\n") <= 0)
962 			return ISC_R_IOERROR;
963 	}
964 
965 	if (class->hash != NULL) {	/* yep. recursive. god help us. */
966 		/* XXX - cannot check error status of this...
967 		 * foo_hash_foreach returns a count of operations completed.
968 		 */
969 		class_hash_foreach(class->hash, write_named_billing_class);
970 	}
971 
972 	return ISC_R_SUCCESS;
973 }
974 
write_billing_classes()975 void write_billing_classes ()
976 {
977 	struct collection *lp;
978 	struct class *cp;
979 
980 	for (lp = collections; lp; lp = lp -> next) {
981 	    for (cp = lp -> classes; cp; cp = cp -> nic) {
982 		if (cp -> spawning && cp -> hash) {
983 		    class_hash_foreach (cp -> hash, write_named_billing_class);
984 		}
985 	    }
986 	}
987 }
988 
989 /* Write a spawned class to the database file. */
990 
write_billing_class(class)991 int write_billing_class (class)
992 	struct class *class;
993 {
994 	int errors = 0;
995 
996 	if (lease_file_is_corrupt)
997 		if (!new_lease_file (0))
998 			return 0;
999 
1000 	if (!class -> superclass) {
1001 		errno = 0;
1002 		fprintf (db_file, "\n  billing class \"%s\";", class -> name);
1003 		return !errno;
1004 	}
1005 
1006 	if (fprintf(db_file, "\n  billing subclass \"%s\"",
1007 		    class -> superclass -> name) < 0)
1008 		++errors;
1009 
1010 	if (!print_hash_string(db_file, class))
1011                 ++errors;
1012 
1013 	if (fprintf(db_file, ";") < 0)
1014                 ++errors;
1015 
1016 	class -> dirty = !errors;
1017 	if (errors)
1018 		lease_file_is_corrupt = 1;
1019 
1020 	return !errors;
1021 }
1022 
1023 /* Commit leases after a timeout. */
commit_leases_timeout(void * foo)1024 void commit_leases_timeout (void *foo)
1025 {
1026 	commit_leases ();
1027 }
1028 
1029 /* Commit any leases that have been written out... */
1030 
commit_leases()1031 int commit_leases ()
1032 {
1033 	/* Commit any outstanding writes to the lease database file.
1034 	   We need to do this even if we're rewriting the file below,
1035 	   just in case the rewrite fails. */
1036 	if (fflush (db_file) == EOF) {
1037 		log_info("commit_leases: unable to commit, fflush(): %m");
1038 		return (0);
1039 	}
1040 	if ((dont_use_fsync == 0) &&
1041 	    (fsync(fileno (db_file)) < 0)) {
1042 		log_info ("commit_leases: unable to commit, fsync(): %m");
1043 		return (0);
1044 	}
1045 
1046 	/* If we haven't rewritten the lease database in over an
1047 	   hour, rewrite it now.  (The length of time should probably
1048 	   be configurable. */
1049 	if (count && cur_time - write_time > LEASE_REWRITE_PERIOD) {
1050 		count = 0;
1051 		write_time = cur_time;
1052 		new_lease_file(0);
1053 	}
1054 	return (1);
1055 }
1056 
1057 /*
1058  * rewrite the lease file about once an hour
1059  * This is meant as a quick patch for ticket 24887.  It allows
1060  * us to rotate the v6 lease file without adding too many fsync()
1061  * calls.  In the future wes should revisit this area and add
1062  * something similar to the delayed ack code for v4.
1063  */
commit_leases_timed()1064 int commit_leases_timed()
1065 {
1066 	if ((count != 0) && (cur_time - write_time > LEASE_REWRITE_PERIOD)) {
1067 		return (commit_leases());
1068 	}
1069 	return (1);
1070 }
1071 
db_startup(int test_mode)1072 void db_startup (int test_mode)
1073 {
1074 	const char *current_db_path;
1075 	isc_result_t status;
1076 
1077 #if defined (TRACING)
1078 	if (!trace_playback ()) {
1079 #endif
1080 		/* Unset authoring_byte_order so we'll know if it was specified
1081 		   in the lease file or not. */
1082 		authoring_byte_order = 0;
1083 
1084 		/* Read in the existing lease file... */
1085 		status = read_conf_file (path_dhcpd_db,
1086 					 (struct group *)0, 0, 1);
1087 		if (status != ISC_R_SUCCESS) {
1088 			/* XXX ignore status? */
1089 			;
1090 		}
1091 
1092 #if defined (TRACING)
1093 	}
1094 #endif
1095 
1096 #if defined (TRACING)
1097 	/* If we're playing back, there is no lease file, so we can't
1098 	   append it, so we create one immediately (maybe this isn't
1099 	   the best solution... */
1100 	if (trace_playback ()) {
1101 		new_lease_file (0);
1102 	}
1103 #endif
1104 	/* expire_all_pools will cause writes to the "current" lease file.
1105 	* Therefore, in test mode we need to point db_file to a disposable
1106 	* file to protect the original lease file. */
1107 	current_db_path = (test_mode ? "/dev/null" : path_dhcpd_db);
1108 	db_file = fopen (current_db_path, "a");
1109 	if (!db_file) {
1110 		log_fatal ("Can't open %s for append.", current_db_path);
1111 	}
1112 
1113 	expire_all_pools ();
1114 #if defined (TRACING)
1115 	if (trace_playback ())
1116 		write_time = cur_time;
1117 	else
1118 #endif
1119 		time(&write_time);
1120 	new_lease_file (test_mode);
1121 
1122 #if defined(REPORT_HASH_PERFORMANCE)
1123 	log_info("Host HW hash:   %s", host_hash_report(host_hw_addr_hash));
1124 	log_info("Host UID hash:  %s", host_hash_report(host_uid_hash));
1125 	log_info("Lease IP hash:  %s",
1126 		 lease_ip_hash_report(lease_ip_addr_hash));
1127 	log_info("Lease UID hash: %s", lease_id_hash_report(lease_uid_hash));
1128 	log_info("Lease HW hash:  %s",
1129 		 lease_id_hash_report(lease_hw_addr_hash));
1130 #endif
1131 }
1132 
new_lease_file(int test_mode)1133 int new_lease_file (int test_mode)
1134 {
1135 	char newfname [512];
1136 	char backfname [512];
1137 	TIME t;
1138 	int db_fd;
1139 	int db_validity;
1140 	FILE *new_db_file;
1141 
1142 	/* Make a temporary lease file... */
1143 	time(&t);
1144 
1145 	db_validity = lease_file_is_corrupt;
1146 
1147 	/* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1148 	 * This should never happen since the path is a configuration
1149 	 * variable from build-time or command-line.  But if it should,
1150 	 * either by malice or ignorance, we panic, since the potential
1151 	 * for havoc is high.
1152 	 */
1153 	if (snprintf (newfname, sizeof newfname, "%s.%d",
1154 		     path_dhcpd_db, (int)t) >= sizeof newfname)
1155 		log_fatal("new_lease_file: lease file path too long");
1156 
1157 	db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
1158 	if (db_fd < 0) {
1159 		log_error ("Can't create new lease file: %m");
1160 		return 0;
1161 	}
1162 
1163 #if defined (PARANOIA)
1164 	/*
1165 	 * If we are currently root and plan to change the
1166 	 * uid and gid change the file information so we
1167 	 * can manipulate it later, after we've changed
1168 	 * our group and user (that is dropped privileges.)
1169 	 */
1170 	if ((set_uid != 0) && (geteuid() == 0) &&
1171 	    (set_gid != 0) && (getegid() == 0)) {
1172 		if (fchown(db_fd, set_uid, set_gid)) {
1173 			log_fatal ("Can't chown new lease file: %m");
1174 		}
1175 	}
1176 #endif /* PARANOIA */
1177 
1178 	if ((new_db_file = fdopen(db_fd, "w")) == NULL) {
1179 		log_error("Can't fdopen new lease file: %m");
1180 		close(db_fd);
1181 		goto fdfail;
1182 	}
1183 
1184 	/* Close previous database, if any. */
1185 	if (db_file)
1186 		fclose(db_file);
1187 	db_file = new_db_file;
1188 
1189 	errno = 0;
1190 	fprintf (db_file, "# The format of this file is documented in the %s",
1191 		 "dhcpd.leases(5) manual page.\n");
1192 
1193 	if (errno)
1194 		goto fail;
1195 
1196 	fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
1197 		 PACKAGE_VERSION);
1198 	if (errno)
1199 		goto fail;
1200 
1201 	fprintf (db_file, "# authoring-byte-order entry is generated,"
1202                           " DO NOT DELETE\n");
1203 	if (errno)
1204 		goto fail;
1205 
1206 	fprintf (db_file, "authoring-byte-order %s;\n\n",
1207 		 (DHCP_BYTE_ORDER == LITTLE_ENDIAN ?
1208 		  "little-endian" : "big-endian"));
1209 	if (errno)
1210 		goto fail;
1211 
1212 	/* At this point we have a new lease file that, so far, could not
1213 	 * be described as either corrupt nor valid.
1214 	 */
1215 	lease_file_is_corrupt = 0;
1216 
1217 	/* Write out all the leases that we know of... */
1218 	counting = 0;
1219 	if (!write_leases ())
1220 		goto fail;
1221 
1222 	if (test_mode) {
1223 		log_debug("Lease file test successful,"
1224 			  " removing temp lease file: %s",
1225 			  newfname);
1226 		(void)unlink (newfname);
1227 		return (1);
1228 	}
1229 
1230 #if defined (TRACING)
1231 	if (!trace_playback ()) {
1232 #endif
1233 	    /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1234 	     * This should never happen since the path is a configuration
1235 	     * variable from build-time or command-line.  But if it should,
1236 	     * either by malice or ignorance, we panic, since the potential
1237 	     * for havoc is too high.
1238 	     */
1239 	    if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
1240 			>= sizeof backfname)
1241 		log_fatal("new_lease_file: backup lease file path too long");
1242 
1243 	    /* Get the old database out of the way... */
1244 	    if (unlink (backfname) < 0 && errno != ENOENT) {
1245 		log_error ("Can't remove old lease database backup %s: %m",
1246 			   backfname);
1247 		goto fail;
1248 	    }
1249 	    if (link(path_dhcpd_db, backfname) < 0) {
1250 		if (errno == ENOENT) {
1251 			log_error("%s is missing - no lease db to backup.",
1252 				  path_dhcpd_db);
1253 		} else {
1254 			log_error("Can't backup lease database %s to %s: %m",
1255 				  path_dhcpd_db, backfname);
1256 			goto fail;
1257 		}
1258 	    }
1259 #if defined (TRACING)
1260 	}
1261 #endif
1262 
1263 	/* Move in the new file... */
1264 	if (rename (newfname, path_dhcpd_db) < 0) {
1265 		log_error ("Can't install new lease database %s to %s: %m",
1266 			   newfname, path_dhcpd_db);
1267 		goto fail;
1268 	}
1269 
1270 	counting = 1;
1271 	return 1;
1272 
1273       fail:
1274 	lease_file_is_corrupt = db_validity;
1275       fdfail:
1276 	(void)unlink (newfname);
1277 	return 0;
1278 }
1279 
group_writer(struct group_object * group)1280 int group_writer (struct group_object *group)
1281 {
1282 	if (!write_group (group))
1283 		return 0;
1284 	if (!commit_leases ())
1285 		return 0;
1286 	return 1;
1287 }
1288