]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/dhcpd.c
- A few lines of code that were failover-specific were moved within
[thirdparty/dhcp.git] / server / dhcpd.c
1 /* dhcpd.c
2
3 DHCP Server Daemon. */
4
5 /*
6 * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
26 *
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
33 */
34
35 #ifndef lint
36 static char ocopyright[] =
37 "$Id: dhcpd.c,v 1.121 2006/07/17 15:21:45 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
38 #endif
39
40 static char copyright[] =
41 "Copyright 2004-2006 Internet Systems Consortium.";
42 static char arr [] = "All rights reserved.";
43 static char message [] = "Internet Systems Consortium DHCP Server";
44 static char url [] = "For info, please visit http://www.isc.org/sw/dhcp/";
45
46 #include "dhcpd.h"
47 #include "version.h"
48 #include <omapip/omapip_p.h>
49
50 static void usage PROTO ((void));
51
52 struct iaddr server_identifier;
53 int server_identifier_matched;
54
55 #if defined (NSUPDATE)
56
57 /* This stuff is always executed to figure the default values for certain
58 ddns variables. */
59
60 char std_nsupdate [] = " \n\
61 option server.ddns-hostname = \n\
62 pick (option fqdn.hostname, option host-name); \n\
63 option server.ddns-domainname = config-option domain-name; \n\
64 option server.ddns-ttl = encode-int(lease-time / 2, 32); \n\
65 option server.ddns-rev-domainname = \"in-addr.arpa.\";";
66
67 /* This is the old-style name service updater that is executed
68 whenever a lease is committed. It does not follow the DHCP-DNS
69 draft at all. */
70
71 char old_nsupdate [] = " \n\
72 on commit { \n\
73 if (not static and \n\
74 ((config-option server.ddns-updates = null) or \n\
75 (config-option server.ddns-updates != 0))) { \n\
76 set new-ddns-fwd-name = \n\
77 concat (pick (config-option server.ddns-hostname, \n\
78 option host-name), \".\", \n\
79 pick (config-option server.ddns-domainname, \n\
80 config-option domain-name)); \n\
81 if (defined (ddns-fwd-name) and ddns-fwd-name != new-ddns-fwd-name) { \n\
82 switch (ns-update (delete (IN, A, ddns-fwd-name, leased-address))) { \n\
83 case NOERROR: \n\
84 unset ddns-fwd-name; \n\
85 on expiry or release { \n\
86 } \n\
87 } \n\
88 } \n\
89 \n\
90 if (not defined (ddns-fwd-name)) { \n\
91 set ddns-fwd-name = new-ddns-fwd-name; \n\
92 if defined (ddns-fwd-name) { \n\
93 switch (ns-update (not exists (IN, A, ddns-fwd-name, null), \n\
94 add (IN, A, ddns-fwd-name, leased-address, \n\
95 lease-time / 2))) { \n\
96 default: \n\
97 unset ddns-fwd-name; \n\
98 break; \n\
99 \n\
100 case NOERROR: \n\
101 set ddns-rev-name = \n\
102 concat (binary-to-ascii (10, 8, \".\", \n\
103 reverse (1, \n\
104 leased-address)), \".\", \n\
105 pick (config-option server.ddns-rev-domainname, \n\
106 \"in-addr.arpa.\")); \n\
107 switch (ns-update (delete (IN, PTR, ddns-rev-name, null), \n\
108 add (IN, PTR, ddns-rev-name, ddns-fwd-name, \n\
109 lease-time / 2))) \n\
110 { \n\
111 default: \n\
112 unset ddns-rev-name; \n\
113 on release or expiry { \n\
114 switch (ns-update (delete (IN, A, ddns-fwd-name, \n\
115 leased-address))) { \n\
116 case NOERROR: \n\
117 unset ddns-fwd-name; \n\
118 break; \n\
119 } \n\
120 on release or expiry; \n\
121 } \n\
122 break; \n\
123 \n\
124 case NOERROR: \n\
125 on release or expiry { \n\
126 switch (ns-update (delete (IN, PTR, ddns-rev-name, null))) {\n\
127 case NOERROR: \n\
128 unset ddns-rev-name; \n\
129 break; \n\
130 } \n\
131 switch (ns-update (delete (IN, A, ddns-fwd-name, \n\
132 leased-address))) { \n\
133 case NOERROR: \n\
134 unset ddns-fwd-name; \n\
135 break; \n\
136 } \n\
137 on release or expiry; \n\
138 } \n\
139 } \n\
140 } \n\
141 } \n\
142 } \n\
143 unset new-ddns-fwd-name; \n\
144 } \n\
145 }";
146
147 int ddns_update_style;
148 #endif /* NSUPDATE */
149
150 const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
151 const char *path_dhcpd_db = _PATH_DHCPD_DB;
152 const char *path_dhcpd_pid = _PATH_DHCPD_PID;
153
154 int dhcp_max_agent_option_packet_length = DHCP_MTU_MAX;
155
156 static omapi_auth_key_t *omapi_key = (omapi_auth_key_t *)0;
157 int omapi_port;
158
159 #if defined (TRACING)
160 trace_type_t *trace_srandom;
161 #endif
162
163 static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) {
164 return ISC_R_SUCCESS;
165 }
166
167 static isc_result_t verify_auth (omapi_object_t *p, omapi_auth_key_t *a) {
168 if (a != omapi_key)
169 return ISC_R_INVALIDKEY;
170 return ISC_R_SUCCESS;
171 }
172
173 static void omapi_listener_start (void *foo)
174 {
175 omapi_object_t *listener;
176 isc_result_t result;
177
178 listener = (omapi_object_t *)0;
179 result = omapi_generic_new (&listener, MDL);
180 if (result != ISC_R_SUCCESS)
181 log_fatal ("Can't allocate new generic object: %s",
182 isc_result_totext (result));
183 result = omapi_protocol_listen (listener,
184 (unsigned)omapi_port, 1);
185 if (result == ISC_R_SUCCESS && omapi_key)
186 result = omapi_protocol_configure_security
187 (listener, verify_addr, verify_auth);
188 if (result != ISC_R_SUCCESS) {
189 log_error ("Can't start OMAPI protocol: %s",
190 isc_result_totext (result));
191 add_timeout (cur_time + 5, omapi_listener_start, 0, 0, 0);
192 }
193 omapi_object_dereference (&listener, MDL);
194 }
195
196 int main (argc, argv, envp)
197 int argc;
198 char **argv, **envp;
199 {
200 int fd;
201 int i, status;
202 struct servent *ent;
203 char *s;
204 int cftest = 0;
205 int lftest = 0;
206 #ifndef DEBUG
207 int pidfilewritten = 0;
208 int pid;
209 char pbuf [20];
210 int daemon = 1;
211 #endif
212 int quiet = 0;
213 char *server = (char *)0;
214 isc_result_t result;
215 unsigned seed;
216 struct interface_info *ip;
217 struct parse *parse;
218 int lose;
219 omapi_object_t *auth;
220 struct tsig_key *key;
221 omapi_typed_data_t *td;
222 int no_dhcpd_conf = 0;
223 int no_dhcpd_db = 0;
224 int no_dhcpd_pid = 0;
225 #if defined (TRACING)
226 char *traceinfile = (char *)0;
227 char *traceoutfile = (char *)0;
228 #endif
229
230 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
231 2 (stderr) are open. To do this, we assume that when we
232 open a file the lowest available file decriptor is used. */
233 fd = open("/dev/null", O_RDWR);
234 if (fd == 0)
235 fd = open("/dev/null", O_RDWR);
236 if (fd == 1)
237 fd = open("/dev/null", O_RDWR);
238 if (fd == 2)
239 log_perror = 0; /* No sense logging to /dev/null. */
240 else if (fd != -1)
241 close(fd);
242
243 /* Set up the client classification system. */
244 classification_setup ();
245
246 /* Initialize the omapi system. */
247 result = omapi_init ();
248 if (result != ISC_R_SUCCESS)
249 log_fatal ("Can't initialize OMAPI: %s",
250 isc_result_totext (result));
251
252 /* Set up the OMAPI wrappers for common objects. */
253 dhcp_db_objects_setup ();
254 /* Set up the OMAPI wrappers for various server database internal
255 objects. */
256 dhcp_common_objects_setup ();
257
258 /* Initially, log errors to stderr as well as to syslogd. */
259 #ifdef SYSLOG_4_2
260 openlog ("dhcpd", LOG_NDELAY);
261 log_priority = DHCPD_LOG_FACILITY;
262 #else
263 openlog ("dhcpd", LOG_NDELAY, DHCPD_LOG_FACILITY);
264 #endif
265
266 for (i = 1; i < argc; i++) {
267 if (!strcmp (argv [i], "-p")) {
268 if (++i == argc)
269 usage ();
270 for (s = argv [i]; *s; s++)
271 if (!isdigit (*s))
272 log_fatal ("%s: not a valid UDP port",
273 argv [i]);
274 status = atoi (argv [i]);
275 if (status < 1 || status > 65535)
276 log_fatal ("%s: not a valid UDP port",
277 argv [i]);
278 local_port = htons (status);
279 log_debug ("binding to user-specified port %d",
280 ntohs (local_port));
281 } else if (!strcmp (argv [i], "-f")) {
282 #ifndef DEBUG
283 daemon = 0;
284 #endif
285 } else if (!strcmp (argv [i], "-d")) {
286 #ifndef DEBUG
287 daemon = 0;
288 #endif
289 log_perror = -1;
290 } else if (!strcmp (argv [i], "-s")) {
291 if (++i == argc)
292 usage ();
293 server = argv [i];
294 } else if (!strcmp (argv [i], "-cf")) {
295 if (++i == argc)
296 usage ();
297 path_dhcpd_conf = argv [i];
298 no_dhcpd_conf = 1;
299 } else if (!strcmp (argv [i], "-lf")) {
300 if (++i == argc)
301 usage ();
302 path_dhcpd_db = argv [i];
303 no_dhcpd_db = 1;
304 } else if (!strcmp (argv [i], "-pf")) {
305 if (++i == argc)
306 usage ();
307 path_dhcpd_pid = argv [i];
308 no_dhcpd_pid = 1;
309 } else if (!strcmp (argv [i], "-t")) {
310 /* test configurations only */
311 #ifndef DEBUG
312 daemon = 0;
313 #endif
314 cftest = 1;
315 log_perror = -1;
316 } else if (!strcmp (argv [i], "-T")) {
317 /* test configurations and lease file only */
318 #ifndef DEBUG
319 daemon = 0;
320 #endif
321 cftest = 1;
322 lftest = 1;
323 log_perror = -1;
324 } else if (!strcmp (argv [i], "-q")) {
325 quiet = 1;
326 quiet_interface_discovery = 1;
327 } else if (!strcmp (argv [i], "--version")) {
328 log_info ("isc-dhcpd-%s", DHCP_VERSION);
329 exit (0);
330 #if defined (TRACING)
331 } else if (!strcmp (argv [i], "-tf")) {
332 if (++i == argc)
333 usage ();
334 traceoutfile = argv [i];
335 } else if (!strcmp (argv [i], "-play")) {
336 if (++i == argc)
337 usage ();
338 traceinfile = argv [i];
339 trace_replay_init ();
340 #endif /* TRACING */
341 } else if (argv [i][0] == '-') {
342 usage ();
343 } else {
344 struct interface_info *tmp =
345 (struct interface_info *)0;
346 result = interface_allocate (&tmp, MDL);
347 if (result != ISC_R_SUCCESS)
348 log_fatal ("Insufficient memory to %s %s: %s",
349 "record interface", argv [i],
350 isc_result_totext (result));
351 strcpy (tmp -> name, argv [i]);
352 if (interfaces) {
353 interface_reference (&tmp -> next,
354 interfaces, MDL);
355 interface_dereference (&interfaces, MDL);
356 }
357 interface_reference (&interfaces, tmp, MDL);
358 tmp -> flags = INTERFACE_REQUESTED;
359 }
360 }
361
362 if (!no_dhcpd_conf && (s = getenv ("PATH_DHCPD_CONF"))) {
363 path_dhcpd_conf = s;
364 }
365 if (!no_dhcpd_db && (s = getenv ("PATH_DHCPD_DB"))) {
366 path_dhcpd_db = s;
367 }
368 if (!no_dhcpd_pid && (s = getenv ("PATH_DHCPD_PID"))) {
369 path_dhcpd_pid = s;
370 }
371
372 if (!quiet) {
373 log_info ("%s %s", message, DHCP_VERSION);
374 log_info (copyright);
375 log_info (arr);
376 log_info (url);
377 } else {
378 quiet = 0;
379 log_perror = 0;
380 }
381
382 #if defined (TRACING)
383 trace_init (set_time, MDL);
384 if (traceoutfile) {
385 result = trace_begin (traceoutfile, MDL);
386 if (result != ISC_R_SUCCESS)
387 log_fatal ("Unable to begin trace: %s",
388 isc_result_totext (result));
389 }
390 interface_trace_setup ();
391 parse_trace_setup ();
392 trace_srandom = trace_type_register ("random-seed", (void *)0,
393 trace_seed_input,
394 trace_seed_stop, MDL);
395 #endif
396
397 /* Default to the DHCP/BOOTP port. */
398 if (!local_port)
399 {
400 if ((s = getenv ("DHCPD_PORT"))) {
401 local_port = htons (atoi (s));
402 log_debug ("binding to environment-specified port %d",
403 ntohs (local_port));
404 } else {
405 ent = getservbyname ("dhcp", "udp");
406 if (!ent)
407 local_port = htons (67);
408 else
409 local_port = ent -> s_port;
410 #ifndef __CYGWIN32__ /* XXX */
411 endservent ();
412 #endif
413 }
414 }
415
416 remote_port = htons (ntohs (local_port) + 1);
417
418 if (server) {
419 if (!inet_aton (server, &limited_broadcast)) {
420 struct hostent *he;
421 he = gethostbyname (server);
422 if (he) {
423 memcpy (&limited_broadcast,
424 he -> h_addr_list [0],
425 sizeof limited_broadcast);
426 } else
427 limited_broadcast.s_addr = INADDR_BROADCAST;
428 }
429 } else {
430 limited_broadcast.s_addr = INADDR_BROADCAST;
431 }
432
433 /* Get the current time... */
434 GET_TIME (&cur_time);
435
436 /* Set up the initial dhcp option universe. */
437 initialize_common_option_spaces ();
438 initialize_server_option_spaces ();
439
440 /* Add the ddns update style enumeration prior to parsing. */
441 add_enumeration (&ddns_styles);
442 add_enumeration (&syslog_enum);
443
444 if (!group_allocate (&root_group, MDL))
445 log_fatal ("Can't allocate root group!");
446 root_group -> authoritative = 0;
447
448 /* Set up various hooks. */
449 dhcp_interface_setup_hook = dhcpd_interface_setup_hook;
450 bootp_packet_handler = do_packet;
451
452 #if defined (NSUPDATE)
453 /* Set up the standard name service updater routine. */
454 parse = (struct parse *)0;
455 status = new_parse (&parse, -1,
456 std_nsupdate, (sizeof std_nsupdate) - 1,
457 "standard name service update routine", 0);
458 if (status != ISC_R_SUCCESS)
459 log_fatal ("can't begin parsing name service updater!");
460
461 lose = 0;
462 if (!(parse_executable_statements
463 (&root_group -> statements, parse, &lose, context_any))) {
464 end_parse (&parse);
465 log_fatal ("can't parse standard name service updater!");
466 }
467 end_parse (&parse);
468 #endif
469
470 /* Initialize icmp support... */
471 if (!cftest && !lftest)
472 icmp_startup (1, lease_pinged);
473
474 #if defined (TRACING)
475 if (traceinfile) {
476 if (!no_dhcpd_db) {
477 log_error ("%s", "");
478 log_error ("** You must specify a lease file with -lf.");
479 log_error (" Dhcpd will not overwrite your default");
480 log_fatal (" lease file when playing back a trace. **");
481 }
482 trace_file_replay (traceinfile);
483
484 #if defined (DEBUG_MEMORY_LEAKAGE) && \
485 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
486 free_everything ();
487 omapi_print_dmalloc_usage_by_caller ();
488 #endif
489
490 exit (0);
491 }
492 #endif
493
494 /* Read the dhcpd.conf file... */
495 if (readconf () != ISC_R_SUCCESS)
496 log_fatal ("Configuration file errors encountered -- exiting");
497
498 postconf_initialization (quiet);
499
500 /* test option should cause an early exit */
501 if (cftest && !lftest)
502 exit(0);
503
504 group_write_hook = group_writer;
505
506 /* Start up the database... */
507 db_startup (lftest);
508
509 if (lftest)
510 exit (0);
511
512 /* Discover all the network interfaces and initialize them. */
513 discover_interfaces (DISCOVER_SERVER);
514
515 /* Make up a seed for the random number generator from current
516 time plus the sum of the last four bytes of each
517 interface's hardware address interpreted as an integer.
518 Not much entropy, but we're booting, so we're not likely to
519 find anything better. */
520 seed = 0;
521 for (ip = interfaces; ip; ip = ip -> next) {
522 int junk;
523 memcpy (&junk,
524 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
525 sizeof seed], sizeof seed);
526 seed += junk;
527 }
528 srandom (seed + cur_time);
529 #if defined (TRACING)
530 trace_seed_stash (trace_srandom, seed + cur_time);
531 #endif
532 postdb_startup ();
533
534 #ifndef DEBUG
535 if (daemon) {
536 /* First part of becoming a daemon... */
537 if ((pid = fork ()) < 0)
538 log_fatal ("Can't fork daemon: %m");
539 else if (pid)
540 exit (0);
541 }
542
543 /* Read previous pid file. */
544 if ((i = open (path_dhcpd_pid, O_RDONLY)) >= 0) {
545 status = read (i, pbuf, (sizeof pbuf) - 1);
546 close (i);
547 if (status > 0) {
548 pbuf [status] = 0;
549 pid = atoi (pbuf);
550
551 /* If the previous server process is not still running,
552 write a new pid file immediately. */
553 if (pid && (pid == getpid() || kill (pid, 0) < 0)) {
554 unlink (path_dhcpd_pid);
555 if ((i = open (path_dhcpd_pid,
556 O_WRONLY | O_CREAT, 0644)) >= 0) {
557 sprintf (pbuf, "%d\n", (int)getpid ());
558 write (i, pbuf, strlen (pbuf));
559 close (i);
560 pidfilewritten = 1;
561 }
562 } else
563 log_fatal ("There's already a DHCP server running.");
564 }
565 }
566
567 /* If we were requested to log to stdout on the command line,
568 keep doing so; otherwise, stop. */
569 if (log_perror == -1)
570 log_perror = 1;
571 else
572 log_perror = 0;
573
574 if (daemon) {
575 /* Become session leader and get pid... */
576 pid = setsid();
577
578 /* Close standard I/O descriptors. */
579 close(0);
580 close(1);
581 close(2);
582
583 /* Reopen them on /dev/null. */
584 open("/dev/null", O_RDWR);
585 open("/dev/null", O_RDWR);
586 open("/dev/null", O_RDWR);
587 log_perror = 0; /* No sense logging to /dev/null. */
588 }
589
590 /* If we didn't write the pid file earlier because we found a
591 process running the logged pid, but we made it to here,
592 meaning nothing is listening on the bootp port, then write
593 the pid file out - what's in it now is bogus anyway. */
594 if (!pidfilewritten) {
595 unlink (path_dhcpd_pid);
596 if ((i = open (path_dhcpd_pid,
597 O_WRONLY | O_CREAT, 0644)) >= 0) {
598 sprintf (pbuf, "%d\n", (int)getpid ());
599 write (i, pbuf, strlen (pbuf));
600 close (i);
601 pidfilewritten = 1;
602 }
603 }
604 #endif /* !DEBUG */
605
606 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
607 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
608 dmalloc_cutoff_generation = dmalloc_generation;
609 dmalloc_longterm = dmalloc_outstanding;
610 dmalloc_outstanding = 0;
611 #endif
612
613 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
614 dump_rc_history ();
615 #endif
616
617 omapi_set_int_value ((omapi_object_t *)dhcp_control_object,
618 (omapi_object_t *)0, "state", server_running);
619
620 /* Receive packets and dispatch them... */
621 dispatch ();
622
623 /* Not reached */
624 return 0;
625 }
626
627 void postconf_initialization (int quiet)
628 {
629 struct option_state *options = (struct option_state *)0;
630 struct data_string db;
631 struct option_cache *oc;
632 char *s;
633 isc_result_t result;
634 struct parse *parse;
635 int tmp;
636
637 /* Now try to get the lease file name. */
638 option_state_allocate (&options, MDL);
639
640 execute_statements_in_scope ((struct binding_value **)0,
641 (struct packet *)0,
642 (struct lease *)0,
643 (struct client_state *)0,
644 (struct option_state *)0,
645 options, &global_scope,
646 root_group,
647 (struct group *)0);
648 memset (&db, 0, sizeof db);
649 oc = lookup_option (&server_universe, options, SV_LEASE_FILE_NAME);
650 if (oc &&
651 evaluate_option_cache (&db, (struct packet *)0,
652 (struct lease *)0, (struct client_state *)0,
653 options, (struct option_state *)0,
654 &global_scope, oc, MDL)) {
655 s = dmalloc (db.len + 1, MDL);
656 if (!s)
657 log_fatal ("no memory for lease db filename.");
658 memcpy (s, db.data, db.len);
659 s [db.len] = 0;
660 data_string_forget (&db, MDL);
661 path_dhcpd_db = s;
662 }
663
664 oc = lookup_option (&server_universe, options, SV_PID_FILE_NAME);
665 if (oc &&
666 evaluate_option_cache (&db, (struct packet *)0,
667 (struct lease *)0, (struct client_state *)0,
668 options, (struct option_state *)0,
669 &global_scope, oc, MDL)) {
670 s = dmalloc (db.len + 1, MDL);
671 if (!s)
672 log_fatal ("no memory for lease db filename.");
673 memcpy (s, db.data, db.len);
674 s [db.len] = 0;
675 data_string_forget (&db, MDL);
676 path_dhcpd_pid = s;
677 }
678
679 omapi_port = -1;
680 oc = lookup_option (&server_universe, options, SV_OMAPI_PORT);
681 if (oc &&
682 evaluate_option_cache (&db, (struct packet *)0,
683 (struct lease *)0, (struct client_state *)0,
684 options, (struct option_state *)0,
685 &global_scope, oc, MDL)) {
686 if (db.len == 2) {
687 omapi_port = getUShort (db.data);
688 } else
689 log_fatal ("invalid omapi port data length");
690 data_string_forget (&db, MDL);
691 }
692
693 oc = lookup_option (&server_universe, options, SV_OMAPI_KEY);
694 if (oc &&
695 evaluate_option_cache (&db, (struct packet *)0,
696 (struct lease *)0, (struct client_state *)0,
697 options,
698 (struct option_state *)0,
699 &global_scope, oc, MDL)) {
700 s = dmalloc (db.len + 1, MDL);
701 if (!s)
702 log_fatal ("no memory for OMAPI key filename.");
703 memcpy (s, db.data, db.len);
704 s [db.len] = 0;
705 data_string_forget (&db, MDL);
706 result = omapi_auth_key_lookup_name (&omapi_key, s);
707 dfree (s, MDL);
708 if (result != ISC_R_SUCCESS)
709 log_fatal ("OMAPI key %s: %s",
710 s, isc_result_totext (result));
711 }
712
713 oc = lookup_option (&server_universe, options, SV_LOCAL_PORT);
714 if (oc &&
715 evaluate_option_cache (&db, (struct packet *)0,
716 (struct lease *)0, (struct client_state *)0,
717 options,
718 (struct option_state *)0,
719 &global_scope, oc, MDL)) {
720 if (db.len == 2) {
721 local_port = htons (getUShort (db.data));
722 } else
723 log_fatal ("invalid local port data length");
724 data_string_forget (&db, MDL);
725 }
726
727 oc = lookup_option (&server_universe, options, SV_REMOTE_PORT);
728 if (oc &&
729 evaluate_option_cache (&db, (struct packet *)0,
730 (struct lease *)0, (struct client_state *)0,
731 options, (struct option_state *)0,
732 &global_scope, oc, MDL)) {
733 if (db.len == 2) {
734 remote_port = htons (getUShort (db.data));
735 } else
736 log_fatal ("invalid remote port data length");
737 data_string_forget (&db, MDL);
738 }
739
740 oc = lookup_option (&server_universe, options,
741 SV_LIMITED_BROADCAST_ADDRESS);
742 if (oc &&
743 evaluate_option_cache (&db, (struct packet *)0,
744 (struct lease *)0, (struct client_state *)0,
745 options, (struct option_state *)0,
746 &global_scope, oc, MDL)) {
747 if (db.len == 4) {
748 memcpy (&limited_broadcast, db.data, 4);
749 } else
750 log_fatal ("invalid remote port data length");
751 data_string_forget (&db, MDL);
752 }
753
754 oc = lookup_option (&server_universe, options,
755 SV_LOCAL_ADDRESS);
756 if (oc &&
757 evaluate_option_cache (&db, (struct packet *)0,
758 (struct lease *)0, (struct client_state *)0,
759 options, (struct option_state *)0,
760 &global_scope, oc, MDL)) {
761 if (db.len == 4) {
762 memcpy (&local_address, db.data, 4);
763 } else
764 log_fatal ("invalid remote port data length");
765 data_string_forget (&db, MDL);
766 }
767
768 oc = lookup_option (&server_universe, options, SV_DDNS_UPDATE_STYLE);
769 if (oc) {
770 if (evaluate_option_cache (&db, (struct packet *)0,
771 (struct lease *)0,
772 (struct client_state *)0,
773 options,
774 (struct option_state *)0,
775 &global_scope, oc, MDL)) {
776 if (db.len == 1) {
777 ddns_update_style = db.data [0];
778 } else
779 log_fatal ("invalid dns update type");
780 data_string_forget (&db, MDL);
781 }
782 } else {
783 log_info ("%s", "");
784 log_error ("** You must add a global ddns-update-style %s%s.",
785 "statement to ", path_dhcpd_conf);
786 log_error (" To get the same behaviour as in 3.0b2pl11 %s",
787 "and previous");
788 log_error (" versions, add a line that says \"%s\"",
789 "ddns-update-style ad-hoc;");
790 log_fatal (" Please read the dhcpd.conf manual page %s",
791 "for more information. **");
792 }
793
794 oc = lookup_option (&server_universe, options, SV_LOG_FACILITY);
795 if (oc) {
796 if (evaluate_option_cache (&db, (struct packet *)0,
797 (struct lease *)0,
798 (struct client_state *)0,
799 options,
800 (struct option_state *)0,
801 &global_scope, oc, MDL)) {
802 if (db.len == 1) {
803 closelog ();
804 #ifdef SYSLOG_4_2
805 openlog ("dhcpd", LOG_NDELAY);
806 log_priority = db.data [0];
807 #else
808 openlog ("dhcpd",
809 LOG_NDELAY, db.data [0]);
810 #endif
811 /* Log the startup banner into the new
812 log file. */
813 if (!quiet) {
814 /* Don't log to stderr twice. */
815 tmp = log_perror;
816 log_perror = 0;
817 log_info ("%s %s",
818 message, DHCP_VERSION);
819 log_info (copyright);
820 log_info (arr);
821 log_info (url);
822 log_perror = tmp;
823 }
824 } else
825 log_fatal ("invalid log facility");
826 data_string_forget (&db, MDL);
827 }
828 }
829
830 /* Don't need the options anymore. */
831 option_state_dereference (&options, MDL);
832
833 #if defined (NSUPDATE)
834 /* If old-style ddns updates have been requested, parse the
835 old-style ddns updater. */
836 if (ddns_update_style == 1) {
837 struct executable_statement **e, *s;
838
839 if (root_group -> statements) {
840 s = (struct executable_statement *)0;
841 if (!executable_statement_allocate (&s, MDL))
842 log_fatal ("no memory for ddns updater");
843 executable_statement_reference
844 (&s -> next, root_group -> statements, MDL);
845 executable_statement_dereference
846 (&root_group -> statements, MDL);
847 executable_statement_reference
848 (&root_group -> statements, s, MDL);
849 s -> op = statements_statement;
850 e = &s -> data.statements;
851 executable_statement_dereference (&s, MDL);
852 } else {
853 e = &root_group -> statements;
854 }
855
856 /* Set up the standard name service updater routine. */
857 parse = (struct parse *)0;
858 result = new_parse (&parse, -1,
859 old_nsupdate, (sizeof old_nsupdate) - 1,
860 "old name service update routine", 0);
861 if (result != ISC_R_SUCCESS)
862 log_fatal ("can't begin parsing old ddns updater!");
863
864 tmp = 0;
865 if (!(parse_executable_statements (e, parse,
866 &tmp, context_any))) {
867 end_parse (&parse);
868 log_fatal ("can't parse standard ddns updater!");
869 }
870 end_parse (&parse);
871 }
872 #endif
873 }
874
875 void postdb_startup (void)
876 {
877 /* Initialize the omapi listener state. */
878 if (omapi_port != -1) {
879 omapi_listener_start (0);
880 }
881
882 #if defined (FAILOVER_PROTOCOL)
883 /* Initialize the failover listener state. */
884 dhcp_failover_startup ();
885 #endif
886 }
887
888 /* Print usage message. */
889
890 static void usage ()
891 {
892 log_info ("%s %s", message, DHCP_VERSION);
893 log_info (copyright);
894 log_info (arr);
895
896 log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f]%s%s%s%s",
897 "\n [-cf config-file] [-lf lease-file]",
898 #if defined (TRACING)
899 "\n [-tf trace-output-file]",
900 "\n [-play trace-input-file]",
901 #else
902 "", "",
903 #endif /* TRACING */
904 "\n [-t] [-T] [-s server] [if0 [...ifN]]");
905 }
906
907 void lease_pinged (from, packet, length)
908 struct iaddr from;
909 u_int8_t *packet;
910 int length;
911 {
912 struct lease *lp;
913
914 /* Don't try to look up a pinged lease if we aren't trying to
915 ping one - otherwise somebody could easily make us churn by
916 just forging repeated ICMP EchoReply packets for us to look
917 up. */
918 if (!outstanding_pings)
919 return;
920
921 lp = (struct lease *)0;
922 if (!find_lease_by_ip_addr (&lp, from, MDL)) {
923 log_debug ("unexpected ICMP Echo Reply from %s",
924 piaddr (from));
925 return;
926 }
927
928 if (!lp -> state) {
929 #if defined (FAILOVER_PROTOCOL)
930 if (!lp -> pool ||
931 !lp -> pool -> failover_peer)
932 #endif
933 log_debug ("ICMP Echo Reply for %s late or spurious.",
934 piaddr (from));
935 goto out;
936 }
937
938 if (lp -> ends > cur_time) {
939 log_debug ("ICMP Echo reply while lease %s valid.",
940 piaddr (from));
941 }
942
943 /* At this point it looks like we pinged a lease and got a
944 response, which shouldn't have happened. */
945 data_string_forget (&lp -> state -> parameter_request_list, MDL);
946 free_lease_state (lp -> state, MDL);
947 lp -> state = (struct lease_state *)0;
948
949 abandon_lease (lp, "pinged before offer");
950 cancel_timeout (lease_ping_timeout, lp);
951 --outstanding_pings;
952 out:
953 lease_dereference (&lp, MDL);
954 }
955
956 void lease_ping_timeout (vlp)
957 void *vlp;
958 {
959 struct lease *lp = vlp;
960
961 #if defined (DEBUG_MEMORY_LEAKAGE)
962 unsigned long previous_outstanding = dmalloc_outstanding;
963 #endif
964
965 --outstanding_pings;
966 dhcp_reply (lp);
967
968 #if defined (DEBUG_MEMORY_LEAKAGE)
969 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
970 dmalloc_generation,
971 dmalloc_outstanding - previous_outstanding,
972 dmalloc_outstanding, dmalloc_longterm);
973 #endif
974 #if defined (DEBUG_MEMORY_LEAKAGE)
975 dmalloc_dump_outstanding ();
976 #endif
977 }
978
979 int dhcpd_interface_setup_hook (struct interface_info *ip, struct iaddr *ia)
980 {
981 struct subnet *subnet;
982 struct shared_network *share;
983 isc_result_t status;
984
985 /* Special case for fallback network - not sure why this is
986 necessary. */
987 if (!ia) {
988 const char *fnn = "fallback-net";
989 char *s;
990 status = shared_network_allocate (&ip -> shared_network, MDL);
991 if (status != ISC_R_SUCCESS)
992 log_fatal ("No memory for shared subnet: %s",
993 isc_result_totext (status));
994 ip -> shared_network -> name = dmalloc (strlen (fnn) + 1, MDL);
995 strcpy (ip -> shared_network -> name, fnn);
996 return 1;
997 }
998
999 /* If there's a registered subnet for this address,
1000 connect it together... */
1001 subnet = (struct subnet *)0;
1002 if (find_subnet (&subnet, *ia, MDL)) {
1003 /* If this interface has multiple aliases on the same
1004 subnet, ignore all but the first we encounter. */
1005 if (!subnet -> interface) {
1006 interface_reference (&subnet -> interface, ip, MDL);
1007 subnet -> interface_address = *ia;
1008 } else if (subnet -> interface != ip) {
1009 log_error ("Multiple interfaces match the %s: %s %s",
1010 "same subnet",
1011 subnet -> interface -> name, ip -> name);
1012 }
1013 share = subnet -> shared_network;
1014 if (ip -> shared_network &&
1015 ip -> shared_network != share) {
1016 log_fatal ("Interface %s matches multiple shared %s",
1017 ip -> name, "networks");
1018 } else {
1019 if (!ip -> shared_network)
1020 shared_network_reference
1021 (&ip -> shared_network, share, MDL);
1022 }
1023
1024 if (!share -> interface) {
1025 interface_reference (&share -> interface, ip, MDL);
1026 } else if (share -> interface != ip) {
1027 log_error ("Multiple interfaces match the %s: %s %s",
1028 "same shared network",
1029 share -> interface -> name, ip -> name);
1030 }
1031 subnet_dereference (&subnet, MDL);
1032 }
1033 return 1;
1034 }
1035
1036 static TIME shutdown_time;
1037 static int omapi_connection_count;
1038 enum dhcp_shutdown_state shutdown_state;
1039
1040 isc_result_t dhcp_io_shutdown (omapi_object_t *obj, void *foo)
1041 {
1042 /* Shut down all listeners. */
1043 if (shutdown_state == shutdown_listeners &&
1044 obj -> type == omapi_type_listener &&
1045 obj -> inner &&
1046 obj -> inner -> type == omapi_type_protocol_listener) {
1047 omapi_listener_destroy (obj, MDL);
1048 return ISC_R_SUCCESS;
1049 }
1050
1051 /* Shut down all existing omapi connections. */
1052 if (obj -> type == omapi_type_connection &&
1053 obj -> inner &&
1054 obj -> inner -> type == omapi_type_protocol) {
1055 if (shutdown_state == shutdown_drop_omapi_connections) {
1056 omapi_disconnect (obj, 1);
1057 }
1058 omapi_connection_count++;
1059 if (shutdown_state == shutdown_omapi_connections) {
1060 omapi_disconnect (obj, 0);
1061 return ISC_R_SUCCESS;
1062 }
1063 }
1064
1065 /* Shutdown all DHCP interfaces. */
1066 if (obj -> type == dhcp_type_interface &&
1067 shutdown_state == shutdown_dhcp) {
1068 dhcp_interface_remove (obj, (omapi_object_t *)0);
1069 return ISC_R_SUCCESS;
1070 }
1071 return ISC_R_SUCCESS;
1072 }
1073
1074 static isc_result_t dhcp_io_shutdown_countdown (void *vlp)
1075 {
1076 dhcp_failover_state_t *state;
1077 #if defined (FAILOVER_PROTOCOL)
1078 int failover_connection_count = 0;
1079 #endif
1080
1081 oncemore:
1082 if (shutdown_state == shutdown_listeners ||
1083 shutdown_state == shutdown_omapi_connections ||
1084 shutdown_state == shutdown_drop_omapi_connections ||
1085 shutdown_state == shutdown_dhcp) {
1086 omapi_connection_count = 0;
1087 omapi_io_state_foreach (dhcp_io_shutdown, 0);
1088 }
1089
1090 if ((shutdown_state == shutdown_listeners ||
1091 shutdown_state == shutdown_omapi_connections ||
1092 shutdown_state == shutdown_drop_omapi_connections) &&
1093 omapi_connection_count == 0) {
1094 shutdown_state = shutdown_dhcp;
1095 shutdown_time = cur_time;
1096 goto oncemore;
1097 } else if (shutdown_state == shutdown_listeners &&
1098 cur_time - shutdown_time > 4) {
1099 shutdown_state = shutdown_omapi_connections;
1100 shutdown_time = cur_time;
1101 } else if (shutdown_state == shutdown_omapi_connections &&
1102 cur_time - shutdown_time > 4) {
1103 shutdown_state = shutdown_drop_omapi_connections;
1104 shutdown_time = cur_time;
1105 } else if (shutdown_state == shutdown_drop_omapi_connections &&
1106 cur_time - shutdown_time > 4) {
1107 shutdown_state = shutdown_dhcp;
1108 shutdown_time = cur_time;
1109 goto oncemore;
1110 } else if (shutdown_state == shutdown_dhcp &&
1111 cur_time - shutdown_time > 4) {
1112 shutdown_state = shutdown_done;
1113 shutdown_time = cur_time;
1114 }
1115
1116 #if defined (FAILOVER_PROTOCOL)
1117 /* Set all failover peers into the shutdown state. */
1118 if (shutdown_state == shutdown_dhcp) {
1119 for (state = failover_states; state; state = state -> next) {
1120 if (state -> me.state == normal) {
1121 dhcp_failover_set_state (state, shut_down);
1122 failover_connection_count++;
1123 }
1124 if (state -> me.state == shut_down &&
1125 state -> partner.state != partner_down)
1126 failover_connection_count++;
1127 }
1128 }
1129
1130 if (shutdown_state == shutdown_done) {
1131 for (state = failover_states; state; state = state -> next) {
1132 if (state -> me.state == shut_down) {
1133 if (state -> link_to_peer)
1134 dhcp_failover_link_dereference (&state -> link_to_peer,
1135 MDL);
1136 dhcp_failover_set_state (state, recover);
1137 }
1138 }
1139 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1140 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1141 free_everything ();
1142 omapi_print_dmalloc_usage_by_caller ();
1143 #endif
1144 exit (0);
1145 }
1146 #else
1147 if (shutdown_state == shutdown_done) {
1148 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1149 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1150 free_everything ();
1151 omapi_print_dmalloc_usage_by_caller ();
1152 #endif
1153 exit (0);
1154 }
1155 #endif
1156 if (shutdown_state == shutdown_dhcp &&
1157 #if defined(FAILOVER_PROTOCOL)
1158 !failover_connection_count &&
1159 #endif
1160 ISC_TRUE) {
1161 shutdown_state = shutdown_done;
1162 shutdown_time = cur_time;
1163 goto oncemore;
1164 }
1165 add_timeout (cur_time + 1,
1166 (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
1167 return ISC_R_SUCCESS;
1168 }
1169
1170 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
1171 control_object_state_t newstate)
1172 {
1173 if (newstate == server_shutdown) {
1174 shutdown_time = cur_time;
1175 shutdown_state = shutdown_listeners;
1176 dhcp_io_shutdown_countdown (0);
1177 return ISC_R_SUCCESS;
1178 }
1179 return ISC_R_INVALIDARG;
1180 }