6 * Copyright (c) 2004-2015 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
29 static const char copyright
[] =
30 "Copyright 2004-2015 Internet Systems Consortium.";
31 static const char arr
[] = "All rights reserved.";
32 static const char message
[] = "Internet Systems Consortium DHCP Server";
33 static const char url
[] =
34 "For info, please visit https://www.isc.org/software/dhcp/";
37 #include <omapip/omapip_p.h>
42 #include <sys/types.h>
46 #if defined (PARANOIA)
47 # include <sys/types.h>
50 /* get around the ISC declaration of group */
51 # define group real_group
55 /* global values so db.c can look at them */
61 static void usage(void);
64 struct iaddr server_identifier
;
65 int server_identifier_matched
;
67 #if defined (NSUPDATE)
69 /* This stuff is always executed to figure the default values for certain
71 char std_nsupdate
[] = " \n\
72 option server.ddns-hostname = \n\
73 pick (option fqdn.hostname, option host-name, config-option host-name); \n\
74 option server.ddns-domainname = config-option domain-name; \n\
75 option server.ddns-rev-domainname = \"in-addr.arpa.\";";
78 int ddns_update_style
;
79 int dont_use_fsync
= 0; /* 0 = default, use fsync, 1 = don't use fsync */
80 int server_id_check
= 0; /* 0 = default, don't check server id, 1 = do check */
81 int prefix_length_mode
= PLM_EXACT
;
83 const char *path_dhcpd_conf
= _PATH_DHCPD_CONF
;
84 const char *path_dhcpd_db
= _PATH_DHCPD_DB
;
85 const char *path_dhcpd_pid
= _PATH_DHCPD_PID
;
86 /* False (default) => we write and use a pid file */
87 isc_boolean_t no_pid_file
= ISC_FALSE
;
89 int dhcp_max_agent_option_packet_length
= DHCP_MTU_MAX
;
91 static omapi_auth_key_t
*omapi_key
= (omapi_auth_key_t
*)0;
95 trace_type_t
*trace_srandom
;
100 static isc_result_t
verify_addr (omapi_object_t
*l
, omapi_addr_t
*addr
) {
101 return ISC_R_SUCCESS
;
104 static isc_result_t
verify_auth (omapi_object_t
*p
, omapi_auth_key_t
*a
) {
106 return DHCP_R_INVALIDKEY
;
107 return ISC_R_SUCCESS
;
110 static void omapi_listener_start (void *foo
)
112 omapi_object_t
*listener
;
116 listener
= (omapi_object_t
*)0;
117 result
= omapi_generic_new (&listener
, MDL
);
118 if (result
!= ISC_R_SUCCESS
)
119 log_fatal ("Can't allocate new generic object: %s",
120 isc_result_totext (result
));
121 result
= omapi_protocol_listen (listener
,
122 (unsigned)omapi_port
, 1);
123 if (result
== ISC_R_SUCCESS
&& omapi_key
)
124 result
= omapi_protocol_configure_security
125 (listener
, verify_addr
, verify_auth
);
126 if (result
!= ISC_R_SUCCESS
) {
127 log_error ("Can't start OMAPI protocol: %s",
128 isc_result_totext (result
));
129 tv
.tv_sec
= cur_tv
.tv_sec
+ 5;
130 tv
.tv_usec
= cur_tv
.tv_usec
;
131 add_timeout (&tv
, omapi_listener_start
, 0, 0, 0);
133 omapi_object_dereference (&listener
, MDL
);
138 /* Note: If we add unit tests to test setup_chroot it will
139 * need to be moved to be outside the ifndef UNIT_TEST block.
142 #if defined (PARANOIA)
143 /* to be used in one of two possible scenarios */
144 static void setup_chroot (char *chroot_dir
) {
146 log_fatal ("you must be root to use chroot");
148 if (chroot(chroot_dir
)) {
149 log_fatal ("chroot(\"%s\"): %m", chroot_dir
);
152 /* probably permission denied */
153 log_fatal ("chdir(\"/\"): %m");
156 #endif /* PARANOIA */
159 main(int argc
, char **argv
) {
172 char *server
= (char *)0;
175 struct interface_info
*ip
;
176 #if defined (NSUPDATE)
180 int no_dhcpd_conf
= 0;
182 int no_dhcpd_pid
= 0;
184 int local_family_set
= 0;
186 #if defined (TRACING)
187 char *traceinfile
= (char *)0;
188 char *traceoutfile
= (char *)0;
191 #if defined (PARANOIA)
194 char *set_chroot
= 0;
195 #endif /* PARANOIA */
203 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
204 2 (stderr) are open. To do this, we assume that when we
205 open a file the lowest available file descriptor is used. */
206 fd
= open("/dev/null", O_RDWR
);
208 fd
= open("/dev/null", O_RDWR
);
210 fd
= open("/dev/null", O_RDWR
);
212 log_perror
= 0; /* No sense logging to /dev/null. */
216 /* Set up the isc and dns library managers */
217 status
= dhcp_context_create(DHCP_CONTEXT_PRE_DB
,
219 if (status
!= ISC_R_SUCCESS
)
220 log_fatal("Can't initialize context: %s",
221 isc_result_totext(status
));
223 /* Set up the client classification system. */
224 classification_setup ();
226 /* Initialize the omapi system. */
227 result
= omapi_init ();
228 if (result
!= ISC_R_SUCCESS
)
229 log_fatal ("Can't initialize OMAPI: %s",
230 isc_result_totext (result
));
232 /* Set up the OMAPI wrappers for common objects. */
233 dhcp_db_objects_setup ();
234 /* Set up the OMAPI wrappers for various server database internal
236 dhcp_common_objects_setup ();
238 /* Initially, log errors to stderr as well as to syslogd. */
239 openlog (isc_file_basename(progname
),
240 DHCP_LOG_OPTIONS
, DHCPD_LOG_FACILITY
);
242 for (i
= 1; i
< argc
; i
++) {
243 if (!strcmp (argv
[i
], "-p")) {
246 local_port
= validate_port (argv
[i
]);
247 log_debug ("binding to user-specified port %d",
249 } else if (!strcmp (argv
[i
], "-f")) {
253 } else if (!strcmp (argv
[i
], "-d")) {
258 } else if (!strcmp (argv
[i
], "-s")) {
262 #if defined (PARANOIA)
263 } else if (!strcmp (argv
[i
], "-user")) {
267 } else if (!strcmp (argv
[i
], "-group")) {
270 set_group
= argv
[i
];
271 } else if (!strcmp (argv
[i
], "-chroot")) {
274 set_chroot
= argv
[i
];
275 #endif /* PARANOIA */
276 } else if (!strcmp (argv
[i
], "-cf")) {
279 path_dhcpd_conf
= argv
[i
];
281 } else if (!strcmp (argv
[i
], "-lf")) {
284 path_dhcpd_db
= argv
[i
];
286 } else if (!strcmp (argv
[i
], "-pf")) {
289 path_dhcpd_pid
= argv
[i
];
291 } else if (!strcmp(argv
[i
], "--no-pid")) {
292 no_pid_file
= ISC_TRUE
;
293 } else if (!strcmp (argv
[i
], "-t")) {
294 /* test configurations only */
300 } else if (!strcmp (argv
[i
], "-T")) {
301 /* test configurations and lease file only */
308 } else if (!strcmp (argv
[i
], "-q")) {
310 quiet_interface_discovery
= 1;
312 } else if (!strcmp(argv
[i
], "-4")) {
313 if (local_family_set
&& (local_family
!= AF_INET
)) {
314 log_fatal("Server cannot run in both IPv4 and "
315 "IPv6 mode at the same time.");
317 local_family
= AF_INET
;
318 local_family_set
= 1;
319 } else if (!strcmp(argv
[i
], "-6")) {
320 if (local_family_set
&& (local_family
!= AF_INET6
)) {
321 log_fatal("Server cannot run in both IPv4 and "
322 "IPv6 mode at the same time.");
324 local_family
= AF_INET6
;
325 local_family_set
= 1;
327 } else if (!strcmp (argv
[i
], "--version")) {
328 const char vstring
[] = "isc-dhcpd-";
329 IGNORE_RET(write(STDERR_FILENO
, vstring
,
331 IGNORE_RET(write(STDERR_FILENO
,
333 strlen(PACKAGE_VERSION
)));
334 IGNORE_RET(write(STDERR_FILENO
, "\n", 1));
336 #if defined (TRACING)
337 } else if (!strcmp (argv
[i
], "-tf")) {
340 traceoutfile
= argv
[i
];
341 } else if (!strcmp (argv
[i
], "-play")) {
344 traceinfile
= argv
[i
];
345 trace_replay_init ();
347 } else if (argv
[i
][0] == '-') {
350 struct interface_info
*tmp
=
351 (struct interface_info
*)0;
352 if (strlen(argv
[i
]) >= sizeof(tmp
->name
))
353 log_fatal("%s: interface name too long "
355 argv
[i
], (long)strlen(argv
[i
]));
356 result
= interface_allocate (&tmp
, MDL
);
357 if (result
!= ISC_R_SUCCESS
)
358 log_fatal ("Insufficient memory to %s %s: %s",
359 "record interface", argv
[i
],
360 isc_result_totext (result
));
361 strcpy (tmp
-> name
, argv
[i
]);
363 interface_reference (&tmp
-> next
,
365 interface_dereference (&interfaces
, MDL
);
367 interface_reference (&interfaces
, tmp
, MDL
);
368 tmp
-> flags
= INTERFACE_REQUESTED
;
372 if (!no_dhcpd_conf
&& (s
= getenv ("PATH_DHCPD_CONF"))) {
377 if (local_family
== AF_INET6
) {
378 /* DHCPv6: override DHCPv4 lease and pid filenames */
380 if ((s
= getenv ("PATH_DHCPD6_DB")))
383 path_dhcpd_db
= _PATH_DHCPD6_DB
;
386 if ((s
= getenv ("PATH_DHCPD6_PID")))
389 path_dhcpd_pid
= _PATH_DHCPD6_PID
;
394 if (!no_dhcpd_db
&& (s
= getenv ("PATH_DHCPD_DB"))) {
397 if (!no_dhcpd_pid
&& (s
= getenv ("PATH_DHCPD_PID"))) {
404 * convert relative path names to absolute, for files that need
405 * to be reopened after chdir() has been called
407 if (path_dhcpd_db
[0] != '/') {
408 const char *path
= path_dhcpd_db
;
409 path_dhcpd_db
= realpath(path_dhcpd_db
, NULL
);
410 if (path_dhcpd_db
== NULL
)
411 log_fatal("Failed to get realpath for %s: %s", path
,
416 log_info("%s %s", message
, PACKAGE_VERSION
);
417 log_info (copyright
);
424 #if defined (TRACING)
425 trace_init (set_time
, MDL
);
427 result
= trace_begin (traceoutfile
, MDL
);
428 if (result
!= ISC_R_SUCCESS
)
429 log_fatal ("Unable to begin trace: %s",
430 isc_result_totext (result
));
432 interface_trace_setup ();
433 parse_trace_setup ();
434 trace_srandom
= trace_type_register ("random-seed", (void *)0,
436 trace_seed_stop
, MDL
);
437 #if defined (NSUPDATE)
439 #endif /* NSUPDATE */
442 #if defined (PARANOIA)
443 /* get user and group info if those options were given */
445 struct passwd
*tmp_pwd
;
448 log_fatal ("you must be root to set user");
450 if (!(tmp_pwd
= getpwnam(set_user
)))
451 log_fatal ("no such user: %s", set_user
);
453 set_uid
= tmp_pwd
->pw_uid
;
455 /* use the user's group as the default gid */
457 set_gid
= tmp_pwd
->pw_gid
;
461 /* get around the ISC declaration of group */
462 #define group real_group
463 struct group
*tmp_grp
;
466 log_fatal ("you must be root to set group");
468 if (!(tmp_grp
= getgrnam(set_group
)))
469 log_fatal ("no such group: %s", set_group
);
471 set_gid
= tmp_grp
->gr_gid
;
475 # if defined (EARLY_CHROOT)
476 if (set_chroot
) setup_chroot (set_chroot
);
477 # endif /* EARLY_CHROOT */
478 #endif /* PARANOIA */
480 /* Default to the DHCP/BOOTP port. */
483 if ((s
= getenv ("DHCPD_PORT"))) {
484 local_port
= validate_port (s
);
485 log_debug ("binding to environment-specified port %d",
488 if (local_family
== AF_INET
) {
489 ent
= getservbyname("dhcp", "udp");
491 local_port
= htons(67);
493 local_port
= ent
->s_port
;
496 /* INSIST(local_family == AF_INET6); */
497 ent
= getservbyname("dhcpv6-server", "udp");
499 local_port
= htons(547);
501 local_port
= ent
->s_port
;
504 #ifndef __CYGWIN32__ /* XXX */
510 if (local_family
== AF_INET
) {
511 remote_port
= htons(ntohs(local_port
) + 1);
513 /* INSIST(local_family == AF_INET6); */
514 ent
= getservbyname("dhcpv6-client", "udp");
516 remote_port
= htons(546);
518 remote_port
= ent
->s_port
;
523 if (local_family
!= AF_INET
) {
524 log_fatal("You can only specify address to send "
525 "replies to when running an IPv4 server.");
527 if (!inet_aton (server
, &limited_broadcast
)) {
529 he
= gethostbyname (server
);
531 memcpy (&limited_broadcast
,
532 he
-> h_addr_list
[0],
533 sizeof limited_broadcast
);
535 limited_broadcast
.s_addr
= INADDR_BROADCAST
;
538 limited_broadcast
.s_addr
= INADDR_BROADCAST
;
541 /* Get the current time... */
542 gettimeofday(&cur_tv
, NULL
);
544 /* Set up the initial dhcp option universe. */
545 initialize_common_option_spaces ();
546 initialize_server_option_spaces ();
548 /* Add the ddns update style enumeration prior to parsing. */
549 add_enumeration (&ddns_styles
);
550 add_enumeration (&syslog_enum
);
551 #if defined (LDAP_CONFIGURATION)
552 add_enumeration (&ldap_methods
);
553 #if defined (LDAP_USE_SSL)
554 add_enumeration (&ldap_ssl_usage_enum
);
555 add_enumeration (&ldap_tls_reqcert_enum
);
556 add_enumeration (&ldap_tls_crlcheck_enum
);
560 if (!group_allocate (&root_group
, MDL
))
561 log_fatal ("Can't allocate root group!");
562 root_group
-> authoritative
= 0;
564 /* Set up various hooks. */
565 dhcp_interface_setup_hook
= dhcpd_interface_setup_hook
;
566 bootp_packet_handler
= do_packet
;
568 add_enumeration (&prefix_length_modes
);
569 dhcpv6_packet_handler
= do_packet6
;
572 #if defined (NSUPDATE)
573 /* Set up the standard name service updater routine. */
575 status
= new_parse(&parse
, -1, std_nsupdate
, sizeof(std_nsupdate
) - 1,
576 "standard name service update routine", 0);
577 if (status
!= ISC_R_SUCCESS
)
578 log_fatal ("can't begin parsing name service updater!");
582 if (!(parse_executable_statements(&root_group
->statements
,
583 parse
, &lose
, context_any
))) {
585 log_fatal("can't parse standard name service updater!");
591 /* Initialize icmp support... */
592 if (!cftest
&& !lftest
)
593 icmp_startup (1, lease_pinged
);
595 #if defined (TRACING)
598 log_error ("%s", "");
599 log_error ("** You must specify a lease file with -lf.");
600 log_error (" Dhcpd will not overwrite your default");
601 log_fatal (" lease file when playing back a trace. **");
603 trace_file_replay (traceinfile
);
605 #if defined (DEBUG_MEMORY_LEAKAGE) && \
606 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
608 omapi_print_dmalloc_usage_by_caller ();
616 /* set up DHCPv6 hashes */
617 if (!ia_new_hash(&ia_na_active
, DEFAULT_HASH_SIZE
, MDL
)) {
618 log_fatal("Out of memory creating hash for active IA_NA.");
620 if (!ia_new_hash(&ia_ta_active
, DEFAULT_HASH_SIZE
, MDL
)) {
621 log_fatal("Out of memory creating hash for active IA_TA.");
623 if (!ia_new_hash(&ia_pd_active
, DEFAULT_HASH_SIZE
, MDL
)) {
624 log_fatal("Out of memory creating hash for active IA_PD.");
628 /* Read the dhcpd.conf file... */
629 if (readconf () != ISC_R_SUCCESS
)
630 log_fatal ("Configuration file errors encountered -- exiting");
632 postconf_initialization (quiet
);
634 #if defined (PARANOIA) && !defined (EARLY_CHROOT)
635 if (set_chroot
) setup_chroot (set_chroot
);
636 #endif /* PARANOIA && !EARLY_CHROOT */
639 /* log info about ipv6_ponds with large address ranges */
640 report_jumbo_ranges();
643 /* test option should cause an early exit */
644 if (cftest
&& !lftest
)
648 * First part of dealing with pid files. Check to see if
649 * we should continue running or not. We run if:
650 * - we are testing the lease file out
651 * - we don't have a pid file to check
652 * - there is no other process running
654 if ((lftest
== 0) && (no_pid_file
== ISC_FALSE
)) {
655 /*Read previous pid file. */
656 if ((i
= open(path_dhcpd_pid
, O_RDONLY
)) >= 0) {
657 status
= read(i
, pbuf
, (sizeof pbuf
) - 1);
664 * If there was a previous server process and
665 * it is still running, abort
668 (pid
!= getpid() && kill(pid
, 0) == 0))
669 log_fatal("There's already a "
670 "DHCP server running.");
675 group_write_hook
= group_writer
;
677 /* Start up the database... */
683 /* Discover all the network interfaces and initialize them. */
684 discover_interfaces(DISCOVER_SERVER
);
688 * Remove addresses from our pools that we should not issue
691 * We currently have no support for this in IPv4. It is not
692 * as important in IPv4, as making pools with ranges that
693 * leave out interfaces and hosts is fairly straightforward
694 * using range notation, but not so handy with CIDR notation.
696 if (local_family
== AF_INET6
) {
697 mark_hosts_unavailable();
698 mark_phosts_unavailable();
699 mark_interfaces_unavailable();
703 /* Make up a seed for the random number generator from current
704 time plus the sum of the last four bytes of each
705 interface's hardware address interpreted as an integer.
706 Not much entropy, but we're booting, so we're not likely to
707 find anything better. */
709 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
712 &ip
-> hw_address
.hbuf
[ip
-> hw_address
.hlen
-
713 sizeof seed
], sizeof seed
);
716 srandom (seed
+ cur_time
);
717 #if defined (TRACING)
718 trace_seed_stash (trace_srandom
, seed
+ cur_time
);
724 * Set server DHCPv6 identifier - we go in order:
725 * dhcp6.server-id in the config file
726 * server-duid from the lease file
727 * server-duid from the config file (the config file is read first
728 * and the lease file overwrites the config file information)
730 * In all cases we write it out to the lease file.
731 * See dhcpv6.c for discussion of setting DUID.
733 if ((set_server_duid_from_option() != ISC_R_SUCCESS
) &&
734 (!server_duid_isset()) &&
735 (generate_new_server_duid() != ISC_R_SUCCESS
)) {
736 log_fatal("Unable to set server identifier.");
743 /* First part of becoming a daemon... */
744 if ((pid
= fork ()) < 0)
745 log_fatal ("Can't fork daemon: %m");
751 * Second part of dealing with pid files. Now
752 * that we have forked we can write our pid if
755 if (no_pid_file
== ISC_FALSE
) {
756 i
= open(path_dhcpd_pid
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
758 sprintf(pbuf
, "%d\n", (int) getpid());
759 IGNORE_RET(write(i
, pbuf
, strlen(pbuf
)));
762 log_error("Can't create PID file %s: %m.",
767 #if defined (PARANOIA)
768 /* change uid to the specified one */
771 if (setgroups (0, (void *)0))
772 log_fatal ("setgroups: %m");
773 if (setgid (set_gid
))
774 log_fatal ("setgid(%d): %m", (int) set_gid
);
778 if (setuid (set_uid
))
779 log_fatal ("setuid(%d): %m", (int) set_uid
);
781 #endif /* PARANOIA */
783 /* If we were requested to log to stdout on the command line,
784 keep doing so; otherwise, stop. */
785 if (log_perror
== -1)
791 /* Become session leader and get pid... */
794 /* Close standard I/O descriptors. */
799 /* Reopen them on /dev/null. */
800 (void) open("/dev/null", O_RDWR
);
801 (void) open("/dev/null", O_RDWR
);
802 (void) open("/dev/null", O_RDWR
);
803 log_perror
= 0; /* No sense logging to /dev/null. */
805 IGNORE_RET (chdir("/"));
809 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
810 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
811 dmalloc_cutoff_generation
= dmalloc_generation
;
812 dmalloc_longterm
= dmalloc_outstanding
;
813 dmalloc_outstanding
= 0;
816 omapi_set_int_value ((omapi_object_t
*)dhcp_control_object
,
817 (omapi_object_t
*)0, "state", server_running
);
819 #if defined(ENABLE_GENTLE_SHUTDOWN)
820 /* no signal handlers until we deal with the side effects */
821 /* install signal handlers */
822 signal(SIGINT
, dhcp_signal_handler
); /* control-c */
823 signal(SIGTERM
, dhcp_signal_handler
); /* kill */
826 /* Log that we are about to start working */
827 log_info("Server starting service.");
830 * Receive packets and dispatch them...
831 * dispatch() will never return.
835 /* Let's return status code */
838 #endif /* !UNIT_TEST */
840 void postconf_initialization (int quiet
)
842 struct option_state
*options
= NULL
;
843 struct data_string db
;
844 struct option_cache
*oc
;
848 #if defined (NSUPDATE)
849 struct in_addr local4
, *local4_ptr
= NULL
;
850 struct in6_addr local6
, *local6_ptr
= NULL
;
853 /* Now try to get the lease file name. */
854 option_state_allocate(&options
, MDL
);
856 execute_statements_in_scope(NULL
, NULL
, NULL
, NULL
, NULL
,
857 options
, &global_scope
, root_group
,
859 memset(&db
, 0, sizeof db
);
860 oc
= lookup_option(&server_universe
, options
, SV_LEASE_FILE_NAME
);
862 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
863 &global_scope
, oc
, MDL
)) {
864 s
= dmalloc(db
.len
+ 1, MDL
);
866 log_fatal("no memory for lease db filename.");
867 memcpy(s
, db
.data
, db
.len
);
869 data_string_forget(&db
, MDL
);
873 oc
= lookup_option(&server_universe
, options
, SV_PID_FILE_NAME
);
875 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
876 &global_scope
, oc
, MDL
)) {
877 s
= dmalloc(db
.len
+ 1, MDL
);
879 log_fatal("no memory for pid filename.");
880 memcpy(s
, db
.data
, db
.len
);
882 data_string_forget(&db
, MDL
);
887 if (local_family
== AF_INET6
) {
889 * Override lease file name with dhcpv6 lease file name,
890 * if it was set; then, do the same with the pid file name
892 oc
= lookup_option(&server_universe
, options
,
893 SV_DHCPV6_LEASE_FILE_NAME
);
895 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
896 &global_scope
, oc
, MDL
)) {
897 s
= dmalloc(db
.len
+ 1, MDL
);
899 log_fatal("no memory for lease db filename.");
900 memcpy(s
, db
.data
, db
.len
);
902 data_string_forget(&db
, MDL
);
906 oc
= lookup_option(&server_universe
, options
,
907 SV_DHCPV6_PID_FILE_NAME
);
909 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
910 &global_scope
, oc
, MDL
)) {
911 s
= dmalloc(db
.len
+ 1, MDL
);
913 log_fatal("no memory for pid filename.");
914 memcpy(s
, db
.data
, db
.len
);
916 data_string_forget(&db
, MDL
);
923 oc
= lookup_option(&server_universe
, options
, SV_OMAPI_PORT
);
925 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
926 &global_scope
, oc
, MDL
)) {
928 omapi_port
= getUShort(db
.data
);
930 log_fatal("invalid omapi port data length");
931 data_string_forget(&db
, MDL
);
934 oc
= lookup_option(&server_universe
, options
, SV_OMAPI_KEY
);
936 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
937 &global_scope
, oc
, MDL
)) {
938 s
= dmalloc(db
.len
+ 1, MDL
);
940 log_fatal("no memory for OMAPI key filename.");
941 memcpy(s
, db
.data
, db
.len
);
943 data_string_forget(&db
, MDL
);
944 result
= omapi_auth_key_lookup_name(&omapi_key
, s
);
946 if (result
!= ISC_R_SUCCESS
)
947 log_fatal("OMAPI key %s: %s",
948 s
, isc_result_totext (result
));
951 oc
= lookup_option(&server_universe
, options
, SV_LOCAL_PORT
);
953 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
954 &global_scope
, oc
, MDL
)) {
956 local_port
= htons(getUShort (db
.data
));
958 log_fatal("invalid local port data length");
959 data_string_forget(&db
, MDL
);
962 oc
= lookup_option(&server_universe
, options
, SV_REMOTE_PORT
);
964 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
965 &global_scope
, oc
, MDL
)) {
967 remote_port
= htons(getUShort (db
.data
));
969 log_fatal("invalid remote port data length");
970 data_string_forget(&db
, MDL
);
973 oc
= lookup_option(&server_universe
, options
,
974 SV_LIMITED_BROADCAST_ADDRESS
);
976 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
977 &global_scope
, oc
, MDL
)) {
979 memcpy(&limited_broadcast
, db
.data
, 4);
981 log_fatal("invalid broadcast address data length");
982 data_string_forget(&db
, MDL
);
985 oc
= lookup_option(&server_universe
, options
, SV_LOCAL_ADDRESS
);
987 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
988 &global_scope
, oc
, MDL
)) {
990 memcpy(&local_address
, db
.data
, 4);
992 log_fatal("invalid local address data length");
993 data_string_forget(&db
, MDL
);
996 oc
= lookup_option(&server_universe
, options
, SV_DDNS_UPDATE_STYLE
);
998 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
999 &global_scope
, oc
, MDL
)) {
1001 ddns_update_style
= db
.data
[0];
1003 log_fatal("invalid dns update type");
1004 data_string_forget(&db
, MDL
);
1007 ddns_update_style
= DDNS_UPDATE_STYLE_NONE
;
1009 #if defined (NSUPDATE)
1010 /* We no longer support ad_hoc, tell the user */
1011 if (ddns_update_style
== DDNS_UPDATE_STYLE_AD_HOC
) {
1012 log_fatal("ddns-update-style ad_hoc no longer supported");
1015 oc
= lookup_option(&server_universe
, options
, SV_DDNS_LOCAL_ADDRESS4
);
1017 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1018 &global_scope
, oc
, MDL
)) {
1020 memcpy(&local4
, db
.data
, 4);
1021 local4_ptr
= &local4
;
1023 data_string_forget(&db
, MDL
);
1027 oc
= lookup_option(&server_universe
, options
, SV_DDNS_LOCAL_ADDRESS6
);
1029 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1030 &global_scope
, oc
, MDL
)) {
1032 memcpy(&local6
, db
.data
, 16);
1033 local6_ptr
= &local6
;
1035 data_string_forget(&db
, MDL
);
1039 if (dhcp_context_create(DHCP_CONTEXT_POST_DB
, local4_ptr
, local6_ptr
)
1041 log_fatal("Unable to complete ddns initialization");
1044 /* If we don't have support for updates compiled in tell the user */
1045 if (ddns_update_style
!= DDNS_UPDATE_STYLE_NONE
) {
1046 log_fatal("Support for ddns-update-style not compiled in");
1051 log_info ("Config file: %s", path_dhcpd_conf
);
1052 log_info ("Database file: %s", path_dhcpd_db
);
1053 log_info ("PID file: %s", path_dhcpd_pid
);
1056 oc
= lookup_option(&server_universe
, options
, SV_LOG_FACILITY
);
1058 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1059 &global_scope
, oc
, MDL
)) {
1062 openlog(isc_file_basename(progname
),
1063 DHCP_LOG_OPTIONS
, db
.data
[0]);
1064 /* Log the startup banner into the new
1066 /* Don't log to stderr twice. */
1069 log_info("%s %s", message
, PACKAGE_VERSION
);
1070 log_info(copyright
);
1075 log_fatal("invalid log facility");
1076 data_string_forget(&db
, MDL
);
1080 #if defined(DELAYED_ACK)
1081 oc
= lookup_option(&server_universe
, options
, SV_DELAYED_ACK
);
1083 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1084 &global_scope
, oc
, MDL
)) {
1086 max_outstanding_acks
= htons(getUShort(db
.data
));
1088 log_fatal("invalid max delayed ACK count ");
1090 data_string_forget(&db
, MDL
);
1093 oc
= lookup_option(&server_universe
, options
, SV_MAX_ACK_DELAY
);
1095 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1096 &global_scope
, oc
, MDL
)) {
1100 log_fatal("invalid max ack delay configuration");
1102 timeval
= getULong(db
.data
);
1103 max_ack_delay_secs
= timeval
/ 1000000;
1104 max_ack_delay_usecs
= timeval
% 1000000;
1106 data_string_forget(&db
, MDL
);
1110 oc
= lookup_option(&server_universe
, options
, SV_DONT_USE_FSYNC
);
1112 evaluate_boolean_option_cache(NULL
, NULL
, NULL
, NULL
, options
, NULL
,
1113 &global_scope
, oc
, MDL
)) {
1115 log_error("Not using fsync() to flush lease writes");
1118 oc
= lookup_option(&server_universe
, options
, SV_SERVER_ID_CHECK
);
1120 evaluate_boolean_option_cache(NULL
, NULL
, NULL
, NULL
, options
, NULL
,
1121 &global_scope
, oc
, MDL
)) {
1122 log_info("Setting server-id-check true");
1123 server_id_check
= 1;
1126 oc
= lookup_option(&server_universe
, options
, SV_PREFIX_LEN_MODE
);
1128 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1129 &global_scope
, oc
, MDL
)) {
1131 prefix_length_mode
= db
.data
[0];
1133 log_fatal("invalid prefix-len-mode");
1136 data_string_forget(&db
, MDL
);
1139 #if defined (BINARY_LEASES)
1140 if (local_family
== AF_INET
) {
1141 log_info("Source compiled to use binary-leases");
1145 /* Don't need the options anymore. */
1146 option_state_dereference(&options
, MDL
);
1149 void postdb_startup (void)
1151 /* Initialize the omapi listener state. */
1152 if (omapi_port
!= -1) {
1153 omapi_listener_start (0);
1156 #if defined (FAILOVER_PROTOCOL)
1157 /* Initialize the failover listener state. */
1158 dhcp_failover_startup ();
1162 * Begin our lease timeout background task.
1164 schedule_all_ipv6_lease_timeouts();
1167 /* Print usage message. */
1171 log_info("%s %s", message
, PACKAGE_VERSION
);
1172 log_info(copyright
);
1175 log_fatal("Usage: %s [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
1177 " [-4|-6] [-cf config-file] [-lf lease-file]\n"
1179 " [-cf config-file] [-lf lease-file]\n"
1181 #if defined (PARANOIA)
1182 /* meld into the following string */
1183 " [-user user] [-group group] [-chroot dir]\n"
1184 #endif /* PARANOIA */
1185 #if defined (TRACING)
1186 " [-tf trace-output-file]\n"
1187 " [-play trace-input-file]\n"
1188 #endif /* TRACING */
1189 " [-pf pid-file] [--no-pid] [-s server]\n"
1191 isc_file_basename(progname
));
1195 void lease_pinged (from
, packet
, length
)
1202 /* Don't try to look up a pinged lease if we aren't trying to
1203 ping one - otherwise somebody could easily make us churn by
1204 just forging repeated ICMP EchoReply packets for us to look
1206 if (!outstanding_pings
)
1209 lp
= (struct lease
*)0;
1210 if (!find_lease_by_ip_addr (&lp
, from
, MDL
)) {
1211 log_debug ("unexpected ICMP Echo Reply from %s",
1217 #if defined (FAILOVER_PROTOCOL)
1219 !lp
-> pool
-> failover_peer
)
1221 log_debug ("ICMP Echo Reply for %s late or spurious.",
1226 if (lp
-> ends
> cur_time
) {
1227 log_debug ("ICMP Echo reply while lease %s valid.",
1231 /* At this point it looks like we pinged a lease and got a
1232 response, which shouldn't have happened. */
1233 data_string_forget (&lp
-> state
-> parameter_request_list
, MDL
);
1234 free_lease_state (lp
-> state
, MDL
);
1235 lp
-> state
= (struct lease_state
*)0;
1237 abandon_lease (lp
, "pinged before offer");
1238 cancel_timeout (lease_ping_timeout
, lp
);
1239 --outstanding_pings
;
1241 lease_dereference (&lp
, MDL
);
1244 void lease_ping_timeout (vlp
)
1247 struct lease
*lp
= vlp
;
1249 #if defined (DEBUG_MEMORY_LEAKAGE)
1250 unsigned long previous_outstanding
= dmalloc_outstanding
;
1253 --outstanding_pings
;
1256 #if defined (DEBUG_MEMORY_LEAKAGE)
1257 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
1259 dmalloc_outstanding
- previous_outstanding
,
1260 dmalloc_outstanding
, dmalloc_longterm
);
1262 #if defined (DEBUG_MEMORY_LEAKAGE)
1263 dmalloc_dump_outstanding ();
1267 int dhcpd_interface_setup_hook (struct interface_info
*ip
, struct iaddr
*ia
)
1269 struct subnet
*subnet
;
1270 struct shared_network
*share
;
1271 isc_result_t status
;
1273 /* Special case for fallback network - not sure why this is
1276 const char *fnn
= "fallback-net";
1277 status
= shared_network_allocate (&ip
-> shared_network
, MDL
);
1278 if (status
!= ISC_R_SUCCESS
)
1279 log_fatal ("No memory for shared subnet: %s",
1280 isc_result_totext (status
));
1281 ip
-> shared_network
-> name
= dmalloc (strlen (fnn
) + 1, MDL
);
1282 if (!ip
-> shared_network
-> name
)
1283 log_fatal("no memory for shared network");
1284 strcpy (ip
-> shared_network
-> name
, fnn
);
1288 /* If there's a registered subnet for this address,
1289 connect it together... */
1290 subnet
= (struct subnet
*)0;
1291 if (find_subnet (&subnet
, *ia
, MDL
)) {
1292 /* If this interface has multiple aliases on the same
1293 subnet, ignore all but the first we encounter. */
1294 if (!subnet
-> interface
) {
1295 interface_reference (&subnet
-> interface
, ip
, MDL
);
1296 subnet
-> interface_address
= *ia
;
1297 } else if (subnet
-> interface
!= ip
) {
1298 log_error ("Multiple interfaces match the %s: %s %s",
1300 subnet
-> interface
-> name
, ip
-> name
);
1302 share
= subnet
-> shared_network
;
1303 if (ip
-> shared_network
&&
1304 ip
-> shared_network
!= share
) {
1305 log_fatal ("Interface %s matches multiple shared %s",
1306 ip
-> name
, "networks");
1308 if (!ip
-> shared_network
)
1309 shared_network_reference
1310 (&ip
-> shared_network
, share
, MDL
);
1313 if (!share
-> interface
) {
1314 interface_reference (&share
-> interface
, ip
, MDL
);
1315 } else if (share
-> interface
!= ip
) {
1316 log_error ("Multiple interfaces match the %s: %s %s",
1317 "same shared network",
1318 share
-> interface
-> name
, ip
-> name
);
1320 subnet_dereference (&subnet
, MDL
);
1325 static TIME shutdown_time
;
1326 static int omapi_connection_count
;
1327 enum dhcp_shutdown_state shutdown_state
;
1329 isc_result_t
dhcp_io_shutdown (omapi_object_t
*obj
, void *foo
)
1331 /* Shut down all listeners. */
1332 if (shutdown_state
== shutdown_listeners
&&
1333 obj
-> type
== omapi_type_listener
&&
1335 obj
-> inner
-> type
== omapi_type_protocol_listener
) {
1336 omapi_listener_destroy (obj
, MDL
);
1337 return ISC_R_SUCCESS
;
1340 /* Shut down all existing omapi connections. */
1341 if (obj
-> type
== omapi_type_connection
&&
1343 obj
-> inner
-> type
== omapi_type_protocol
) {
1344 if (shutdown_state
== shutdown_drop_omapi_connections
) {
1345 omapi_disconnect (obj
, 1);
1347 omapi_connection_count
++;
1348 if (shutdown_state
== shutdown_omapi_connections
) {
1349 omapi_disconnect (obj
, 0);
1350 return ISC_R_SUCCESS
;
1354 /* Shutdown all DHCP interfaces. */
1355 if (obj
-> type
== dhcp_type_interface
&&
1356 shutdown_state
== shutdown_dhcp
) {
1357 dhcp_interface_remove (obj
, (omapi_object_t
*)0);
1358 return ISC_R_SUCCESS
;
1360 return ISC_R_SUCCESS
;
1363 static isc_result_t
dhcp_io_shutdown_countdown (void *vlp
)
1365 #if defined (FAILOVER_PROTOCOL)
1366 dhcp_failover_state_t
*state
;
1367 int failover_connection_count
= 0;
1372 if (shutdown_state
== shutdown_listeners
||
1373 shutdown_state
== shutdown_omapi_connections
||
1374 shutdown_state
== shutdown_drop_omapi_connections
||
1375 shutdown_state
== shutdown_dhcp
) {
1376 omapi_connection_count
= 0;
1377 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
1380 if ((shutdown_state
== shutdown_listeners
||
1381 shutdown_state
== shutdown_omapi_connections
||
1382 shutdown_state
== shutdown_drop_omapi_connections
) &&
1383 omapi_connection_count
== 0) {
1384 shutdown_state
= shutdown_dhcp
;
1385 shutdown_time
= cur_time
;
1387 } else if (shutdown_state
== shutdown_listeners
&&
1388 cur_time
- shutdown_time
> 4) {
1389 shutdown_state
= shutdown_omapi_connections
;
1390 shutdown_time
= cur_time
;
1391 } else if (shutdown_state
== shutdown_omapi_connections
&&
1392 cur_time
- shutdown_time
> 4) {
1393 shutdown_state
= shutdown_drop_omapi_connections
;
1394 shutdown_time
= cur_time
;
1395 } else if (shutdown_state
== shutdown_drop_omapi_connections
&&
1396 cur_time
- shutdown_time
> 4) {
1397 shutdown_state
= shutdown_dhcp
;
1398 shutdown_time
= cur_time
;
1400 } else if (shutdown_state
== shutdown_dhcp
&&
1401 cur_time
- shutdown_time
> 4) {
1402 shutdown_state
= shutdown_done
;
1403 shutdown_time
= cur_time
;
1406 #if defined (FAILOVER_PROTOCOL)
1407 /* Set all failover peers into the shutdown state. */
1408 if (shutdown_state
== shutdown_dhcp
) {
1409 for (state
= failover_states
; state
; state
= state
-> next
) {
1410 if (state
-> me
.state
== normal
) {
1411 dhcp_failover_set_state (state
, shut_down
);
1412 failover_connection_count
++;
1414 if (state
-> me
.state
== shut_down
&&
1415 state
-> partner
.state
!= partner_down
)
1416 failover_connection_count
++;
1420 if (shutdown_state
== shutdown_done
) {
1421 for (state
= failover_states
; state
; state
= state
-> next
) {
1422 if (state
-> me
.state
== shut_down
) {
1423 if (state
-> link_to_peer
)
1424 dhcp_failover_link_dereference (&state
-> link_to_peer
,
1426 dhcp_failover_set_state (state
, recover
);
1429 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1430 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1432 omapi_print_dmalloc_usage_by_caller ();
1434 if (no_pid_file
== ISC_FALSE
)
1435 (void) unlink(path_dhcpd_pid
);
1439 if (shutdown_state
== shutdown_done
) {
1440 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1441 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1443 omapi_print_dmalloc_usage_by_caller ();
1445 if (no_pid_file
== ISC_FALSE
)
1446 (void) unlink(path_dhcpd_pid
);
1450 if (shutdown_state
== shutdown_dhcp
&&
1451 #if defined(FAILOVER_PROTOCOL)
1452 !failover_connection_count
&&
1455 shutdown_state
= shutdown_done
;
1456 shutdown_time
= cur_time
;
1459 tv
.tv_sec
= cur_tv
.tv_sec
+ 1;
1460 tv
.tv_usec
= cur_tv
.tv_usec
;
1462 (void (*)(void *))dhcp_io_shutdown_countdown
, 0, 0, 0);
1463 return ISC_R_SUCCESS
;
1466 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
1467 control_object_state_t newstate
)
1471 if (newstate
!= server_shutdown
)
1472 return DHCP_R_INVALIDARG
;
1474 if (shutdown_signal
== SIGUSR1
)
1475 return ISC_R_SUCCESS
;
1476 shutdown_time
= cur_time
;
1477 shutdown_state
= shutdown_listeners
;
1478 /* Called by user. */
1479 if (shutdown_signal
== 0) {
1480 shutdown_signal
= SIGUSR1
;
1481 dhcp_io_shutdown_countdown (0);
1482 return ISC_R_SUCCESS
;
1484 /* Called on signal. */
1485 log_info("Received signal %d, initiating shutdown.", shutdown_signal
);
1486 shutdown_signal
= SIGUSR1
;
1489 * Prompt the shutdown event onto the timer queue
1490 * and return to the dispatch loop.
1492 tv
.tv_sec
= cur_tv
.tv_sec
;
1493 tv
.tv_usec
= cur_tv
.tv_usec
+ 1;
1495 (void (*)(void *))dhcp_io_shutdown_countdown
, 0, 0, 0);
1496 return ISC_R_SUCCESS
;