6 * Copyright (c) 2004-2014 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-2014 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>
45 #if defined (PARANOIA)
46 # include <sys/types.h>
49 /* get around the ISC declaration of group */
50 # define group real_group
56 static void usage(void);
59 struct iaddr server_identifier
;
60 int server_identifier_matched
;
62 #if defined (NSUPDATE)
64 /* This stuff is always executed to figure the default values for certain
66 char std_nsupdate
[] = " \n\
67 option server.ddns-hostname = \n\
68 pick (option fqdn.hostname, option host-name, config-option host-name); \n\
69 option server.ddns-domainname = config-option domain-name; \n\
70 option server.ddns-rev-domainname = \"in-addr.arpa.\";";
73 int ddns_update_style
;
74 int dont_use_fsync
= 0; /* 0 = default, use fsync, 1 = don't use fsync */
75 int server_id_check
= 0; /* 0 = default, don't check server id, 1 = do check */
77 const char *path_dhcpd_conf
= _PATH_DHCPD_CONF
;
78 const char *path_dhcpd_db
= _PATH_DHCPD_DB
;
79 const char *path_dhcpd_pid
= _PATH_DHCPD_PID
;
80 /* False (default) => we write and use a pid file */
81 isc_boolean_t no_pid_file
= ISC_FALSE
;
83 int dhcp_max_agent_option_packet_length
= DHCP_MTU_MAX
;
85 static omapi_auth_key_t
*omapi_key
= (omapi_auth_key_t
*)0;
89 trace_type_t
*trace_srandom
;
92 static isc_result_t
verify_addr (omapi_object_t
*l
, omapi_addr_t
*addr
) {
96 static isc_result_t
verify_auth (omapi_object_t
*p
, omapi_auth_key_t
*a
) {
98 return DHCP_R_INVALIDKEY
;
102 static void omapi_listener_start (void *foo
)
104 omapi_object_t
*listener
;
108 listener
= (omapi_object_t
*)0;
109 result
= omapi_generic_new (&listener
, MDL
);
110 if (result
!= ISC_R_SUCCESS
)
111 log_fatal ("Can't allocate new generic object: %s",
112 isc_result_totext (result
));
113 result
= omapi_protocol_listen (listener
,
114 (unsigned)omapi_port
, 1);
115 if (result
== ISC_R_SUCCESS
&& omapi_key
)
116 result
= omapi_protocol_configure_security
117 (listener
, verify_addr
, verify_auth
);
118 if (result
!= ISC_R_SUCCESS
) {
119 log_error ("Can't start OMAPI protocol: %s",
120 isc_result_totext (result
));
121 tv
.tv_sec
= cur_tv
.tv_sec
+ 5;
122 tv
.tv_usec
= cur_tv
.tv_usec
;
123 add_timeout (&tv
, omapi_listener_start
, 0, 0, 0);
125 omapi_object_dereference (&listener
, MDL
);
128 #if defined (PARANOIA)
129 /* to be used in one of two possible scenarios */
130 static void setup_chroot (char *chroot_dir
) {
132 log_fatal ("you must be root to use chroot");
134 if (chroot(chroot_dir
)) {
135 log_fatal ("chroot(\"%s\"): %m", chroot_dir
);
138 /* probably permission denied */
139 log_fatal ("chdir(\"/\"): %m");
142 #endif /* PARANOIA */
146 main(int argc
, char **argv
) {
159 char *server
= (char *)0;
162 struct interface_info
*ip
;
163 #if defined (NSUPDATE)
167 int no_dhcpd_conf
= 0;
169 int no_dhcpd_pid
= 0;
171 int local_family_set
= 0;
173 #if defined (TRACING)
174 char *traceinfile
= (char *)0;
175 char *traceoutfile
= (char *)0;
178 #if defined (PARANOIA)
181 char *set_chroot
= 0;
185 #endif /* PARANOIA */
187 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
188 2 (stderr) are open. To do this, we assume that when we
189 open a file the lowest available file descriptor is used. */
190 fd
= open("/dev/null", O_RDWR
);
192 fd
= open("/dev/null", O_RDWR
);
194 fd
= open("/dev/null", O_RDWR
);
196 log_perror
= 0; /* No sense logging to /dev/null. */
200 /* Set up the isc and dns library managers */
201 status
= dhcp_context_create(DHCP_CONTEXT_PRE_DB
,
203 if (status
!= ISC_R_SUCCESS
)
204 log_fatal("Can't initialize context: %s",
205 isc_result_totext(status
));
207 /* Set up the client classification system. */
208 classification_setup ();
210 /* Initialize the omapi system. */
211 result
= omapi_init ();
212 if (result
!= ISC_R_SUCCESS
)
213 log_fatal ("Can't initialize OMAPI: %s",
214 isc_result_totext (result
));
216 /* Set up the OMAPI wrappers for common objects. */
217 dhcp_db_objects_setup ();
218 /* Set up the OMAPI wrappers for various server database internal
220 dhcp_common_objects_setup ();
222 /* Initially, log errors to stderr as well as to syslogd. */
223 openlog ("dhcpd", DHCP_LOG_OPTIONS
, DHCPD_LOG_FACILITY
);
225 for (i
= 1; i
< argc
; i
++) {
226 if (!strcmp (argv
[i
], "-p")) {
229 local_port
= validate_port (argv
[i
]);
230 log_debug ("binding to user-specified port %d",
232 } else if (!strcmp (argv
[i
], "-f")) {
236 } else if (!strcmp (argv
[i
], "-d")) {
241 } else if (!strcmp (argv
[i
], "-s")) {
245 #if defined (PARANOIA)
246 } else if (!strcmp (argv
[i
], "-user")) {
250 } else if (!strcmp (argv
[i
], "-group")) {
253 set_group
= argv
[i
];
254 } else if (!strcmp (argv
[i
], "-chroot")) {
257 set_chroot
= argv
[i
];
258 #endif /* PARANOIA */
259 } else if (!strcmp (argv
[i
], "-cf")) {
262 path_dhcpd_conf
= argv
[i
];
264 } else if (!strcmp (argv
[i
], "-lf")) {
267 path_dhcpd_db
= argv
[i
];
269 } else if (!strcmp (argv
[i
], "-pf")) {
272 path_dhcpd_pid
= argv
[i
];
274 } else if (!strcmp(argv
[i
], "--no-pid")) {
275 no_pid_file
= ISC_TRUE
;
276 } else if (!strcmp (argv
[i
], "-t")) {
277 /* test configurations only */
283 } else if (!strcmp (argv
[i
], "-T")) {
284 /* test configurations and lease file only */
291 } else if (!strcmp (argv
[i
], "-q")) {
293 quiet_interface_discovery
= 1;
295 } else if (!strcmp(argv
[i
], "-4")) {
296 if (local_family_set
&& (local_family
!= AF_INET
)) {
297 log_fatal("Server cannot run in both IPv4 and "
298 "IPv6 mode at the same time.");
300 local_family
= AF_INET
;
301 local_family_set
= 1;
302 } else if (!strcmp(argv
[i
], "-6")) {
303 if (local_family_set
&& (local_family
!= AF_INET6
)) {
304 log_fatal("Server cannot run in both IPv4 and "
305 "IPv6 mode at the same time.");
307 local_family
= AF_INET6
;
308 local_family_set
= 1;
310 } else if (!strcmp (argv
[i
], "--version")) {
311 const char vstring
[] = "isc-dhcpd-";
312 IGNORE_RET(write(STDERR_FILENO
, vstring
,
314 IGNORE_RET(write(STDERR_FILENO
,
316 strlen(PACKAGE_VERSION
)));
317 IGNORE_RET(write(STDERR_FILENO
, "\n", 1));
319 #if defined (TRACING)
320 } else if (!strcmp (argv
[i
], "-tf")) {
323 traceoutfile
= argv
[i
];
324 } else if (!strcmp (argv
[i
], "-play")) {
327 traceinfile
= argv
[i
];
328 trace_replay_init ();
330 } else if (argv
[i
][0] == '-') {
333 struct interface_info
*tmp
=
334 (struct interface_info
*)0;
335 if (strlen(argv
[i
]) >= sizeof(tmp
->name
))
336 log_fatal("%s: interface name too long "
338 argv
[i
], (long)strlen(argv
[i
]));
339 result
= interface_allocate (&tmp
, MDL
);
340 if (result
!= ISC_R_SUCCESS
)
341 log_fatal ("Insufficient memory to %s %s: %s",
342 "record interface", argv
[i
],
343 isc_result_totext (result
));
344 strcpy (tmp
-> name
, argv
[i
]);
346 interface_reference (&tmp
-> next
,
348 interface_dereference (&interfaces
, MDL
);
350 interface_reference (&interfaces
, tmp
, MDL
);
351 tmp
-> flags
= INTERFACE_REQUESTED
;
355 if (!no_dhcpd_conf
&& (s
= getenv ("PATH_DHCPD_CONF"))) {
360 if (local_family
== AF_INET6
) {
361 /* DHCPv6: override DHCPv4 lease and pid filenames */
363 if ((s
= getenv ("PATH_DHCPD6_DB")))
366 path_dhcpd_db
= _PATH_DHCPD6_DB
;
369 if ((s
= getenv ("PATH_DHCPD6_PID")))
372 path_dhcpd_pid
= _PATH_DHCPD6_PID
;
377 if (!no_dhcpd_db
&& (s
= getenv ("PATH_DHCPD_DB"))) {
380 if (!no_dhcpd_pid
&& (s
= getenv ("PATH_DHCPD_PID"))) {
387 * convert relative path names to absolute, for files that need
388 * to be reopened after chdir() has been called
390 if (path_dhcpd_db
[0] != '/') {
391 const char *path
= path_dhcpd_db
;
392 path_dhcpd_db
= realpath(path_dhcpd_db
, NULL
);
393 if (path_dhcpd_db
== NULL
)
394 log_fatal("Failed to get realpath for %s: %s", path
,
399 log_info("%s %s", message
, PACKAGE_VERSION
);
400 log_info (copyright
);
407 #if defined (TRACING)
408 trace_init (set_time
, MDL
);
410 result
= trace_begin (traceoutfile
, MDL
);
411 if (result
!= ISC_R_SUCCESS
)
412 log_fatal ("Unable to begin trace: %s",
413 isc_result_totext (result
));
415 interface_trace_setup ();
416 parse_trace_setup ();
417 trace_srandom
= trace_type_register ("random-seed", (void *)0,
419 trace_seed_stop
, MDL
);
420 #if defined (NSUPDATE)
422 #endif /* NSUPDATE */
425 #if defined (PARANOIA)
426 /* get user and group info if those options were given */
428 struct passwd
*tmp_pwd
;
431 log_fatal ("you must be root to set user");
433 if (!(tmp_pwd
= getpwnam(set_user
)))
434 log_fatal ("no such user: %s", set_user
);
436 set_uid
= tmp_pwd
->pw_uid
;
438 /* use the user's group as the default gid */
440 set_gid
= tmp_pwd
->pw_gid
;
444 /* get around the ISC declaration of group */
445 #define group real_group
446 struct group
*tmp_grp
;
449 log_fatal ("you must be root to set group");
451 if (!(tmp_grp
= getgrnam(set_group
)))
452 log_fatal ("no such group: %s", set_group
);
454 set_gid
= tmp_grp
->gr_gid
;
458 # if defined (EARLY_CHROOT)
459 if (set_chroot
) setup_chroot (set_chroot
);
460 # endif /* EARLY_CHROOT */
461 #endif /* PARANOIA */
463 /* Default to the DHCP/BOOTP port. */
466 if ((s
= getenv ("DHCPD_PORT"))) {
467 local_port
= validate_port (s
);
468 log_debug ("binding to environment-specified port %d",
471 if (local_family
== AF_INET
) {
472 ent
= getservbyname("dhcp", "udp");
474 local_port
= htons(67);
476 local_port
= ent
->s_port
;
479 /* INSIST(local_family == AF_INET6); */
480 ent
= getservbyname("dhcpv6-server", "udp");
482 local_port
= htons(547);
484 local_port
= ent
->s_port
;
487 #ifndef __CYGWIN32__ /* XXX */
493 if (local_family
== AF_INET
) {
494 remote_port
= htons(ntohs(local_port
) + 1);
496 /* INSIST(local_family == AF_INET6); */
497 ent
= getservbyname("dhcpv6-client", "udp");
499 remote_port
= htons(546);
501 remote_port
= ent
->s_port
;
506 if (local_family
!= AF_INET
) {
507 log_fatal("You can only specify address to send "
508 "replies to when running an IPv4 server.");
510 if (!inet_aton (server
, &limited_broadcast
)) {
512 he
= gethostbyname (server
);
514 memcpy (&limited_broadcast
,
515 he
-> h_addr_list
[0],
516 sizeof limited_broadcast
);
518 limited_broadcast
.s_addr
= INADDR_BROADCAST
;
521 limited_broadcast
.s_addr
= INADDR_BROADCAST
;
524 /* Get the current time... */
525 gettimeofday(&cur_tv
, NULL
);
527 /* Set up the initial dhcp option universe. */
528 initialize_common_option_spaces ();
529 initialize_server_option_spaces ();
531 /* Add the ddns update style enumeration prior to parsing. */
532 add_enumeration (&ddns_styles
);
533 add_enumeration (&syslog_enum
);
534 #if defined (LDAP_CONFIGURATION)
535 add_enumeration (&ldap_methods
);
536 #if defined (LDAP_USE_SSL)
537 add_enumeration (&ldap_ssl_usage_enum
);
538 add_enumeration (&ldap_tls_reqcert_enum
);
539 add_enumeration (&ldap_tls_crlcheck_enum
);
543 if (!group_allocate (&root_group
, MDL
))
544 log_fatal ("Can't allocate root group!");
545 root_group
-> authoritative
= 0;
547 /* Set up various hooks. */
548 dhcp_interface_setup_hook
= dhcpd_interface_setup_hook
;
549 bootp_packet_handler
= do_packet
;
551 dhcpv6_packet_handler
= do_packet6
;
554 #if defined (NSUPDATE)
555 /* Set up the standard name service updater routine. */
557 status
= new_parse(&parse
, -1, std_nsupdate
, sizeof(std_nsupdate
) - 1,
558 "standard name service update routine", 0);
559 if (status
!= ISC_R_SUCCESS
)
560 log_fatal ("can't begin parsing name service updater!");
564 if (!(parse_executable_statements(&root_group
->statements
,
565 parse
, &lose
, context_any
))) {
567 log_fatal("can't parse standard name service updater!");
573 /* Initialize icmp support... */
574 if (!cftest
&& !lftest
)
575 icmp_startup (1, lease_pinged
);
577 #if defined (TRACING)
580 log_error ("%s", "");
581 log_error ("** You must specify a lease file with -lf.");
582 log_error (" Dhcpd will not overwrite your default");
583 log_fatal (" lease file when playing back a trace. **");
585 trace_file_replay (traceinfile
);
587 #if defined (DEBUG_MEMORY_LEAKAGE) && \
588 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
590 omapi_print_dmalloc_usage_by_caller ();
598 /* set up DHCPv6 hashes */
599 if (!ia_new_hash(&ia_na_active
, DEFAULT_HASH_SIZE
, MDL
)) {
600 log_fatal("Out of memory creating hash for active IA_NA.");
602 if (!ia_new_hash(&ia_ta_active
, DEFAULT_HASH_SIZE
, MDL
)) {
603 log_fatal("Out of memory creating hash for active IA_TA.");
605 if (!ia_new_hash(&ia_pd_active
, DEFAULT_HASH_SIZE
, MDL
)) {
606 log_fatal("Out of memory creating hash for active IA_PD.");
610 /* Read the dhcpd.conf file... */
611 if (readconf () != ISC_R_SUCCESS
)
612 log_fatal ("Configuration file errors encountered -- exiting");
614 postconf_initialization (quiet
);
616 #if defined (PARANOIA) && !defined (EARLY_CHROOT)
617 if (set_chroot
) setup_chroot (set_chroot
);
618 #endif /* PARANOIA && !EARLY_CHROOT */
620 /* test option should cause an early exit */
621 if (cftest
&& !lftest
)
625 * First part of dealing with pid files. Check to see if
626 * we should continue running or not. We run if:
627 * - we are testing the lease file out
628 * - we don't have a pid file to check
629 * - there is no other process running
631 if ((lftest
== 0) && (no_pid_file
== ISC_FALSE
)) {
632 /*Read previous pid file. */
633 if ((i
= open(path_dhcpd_pid
, O_RDONLY
)) >= 0) {
634 status
= read(i
, pbuf
, (sizeof pbuf
) - 1);
641 * If there was a previous server process and
642 * it is still running, abort
645 (pid
!= getpid() && kill(pid
, 0) == 0))
646 log_fatal("There's already a "
647 "DHCP server running.");
652 group_write_hook
= group_writer
;
654 /* Start up the database... */
660 /* Discover all the network interfaces and initialize them. */
661 discover_interfaces(DISCOVER_SERVER
);
665 * Remove addresses from our pools that we should not issue
668 * We currently have no support for this in IPv4. It is not
669 * as important in IPv4, as making pools with ranges that
670 * leave out interfaces and hosts is fairly straightforward
671 * using range notation, but not so handy with CIDR notation.
673 if (local_family
== AF_INET6
) {
674 mark_hosts_unavailable();
675 mark_phosts_unavailable();
676 mark_interfaces_unavailable();
681 /* Make up a seed for the random number generator from current
682 time plus the sum of the last four bytes of each
683 interface's hardware address interpreted as an integer.
684 Not much entropy, but we're booting, so we're not likely to
685 find anything better. */
687 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
690 &ip
-> hw_address
.hbuf
[ip
-> hw_address
.hlen
-
691 sizeof seed
], sizeof seed
);
694 srandom (seed
+ cur_time
);
695 #if defined (TRACING)
696 trace_seed_stash (trace_srandom
, seed
+ cur_time
);
702 * Set server DHCPv6 identifier.
703 * See dhcpv6.c for discussion of setting DUID.
705 if (set_server_duid_from_option() == ISC_R_SUCCESS
) {
708 if (!server_duid_isset()) {
709 if (generate_new_server_duid() != ISC_R_SUCCESS
) {
710 log_fatal("Unable to set server identifier.");
719 /* First part of becoming a daemon... */
720 if ((pid
= fork ()) < 0)
721 log_fatal ("Can't fork daemon: %m");
727 * Second part of dealing with pid files. Now
728 * that we have forked we can write our pid if
731 if (no_pid_file
== ISC_FALSE
) {
732 i
= open(path_dhcpd_pid
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
734 sprintf(pbuf
, "%d\n", (int) getpid());
735 IGNORE_RET(write(i
, pbuf
, strlen(pbuf
)));
738 log_error("Can't create PID file %s: %m.",
743 #if defined (PARANOIA)
744 /* change uid to the specified one */
747 if (setgroups (0, (void *)0))
748 log_fatal ("setgroups: %m");
749 if (setgid (set_gid
))
750 log_fatal ("setgid(%d): %m", (int) set_gid
);
754 if (setuid (set_uid
))
755 log_fatal ("setuid(%d): %m", (int) set_uid
);
757 #endif /* PARANOIA */
759 /* If we were requested to log to stdout on the command line,
760 keep doing so; otherwise, stop. */
761 if (log_perror
== -1)
767 /* Become session leader and get pid... */
770 /* Close standard I/O descriptors. */
775 /* Reopen them on /dev/null. */
776 (void) open("/dev/null", O_RDWR
);
777 (void) open("/dev/null", O_RDWR
);
778 (void) open("/dev/null", O_RDWR
);
779 log_perror
= 0; /* No sense logging to /dev/null. */
781 IGNORE_RET (chdir("/"));
785 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
786 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
787 dmalloc_cutoff_generation
= dmalloc_generation
;
788 dmalloc_longterm
= dmalloc_outstanding
;
789 dmalloc_outstanding
= 0;
792 omapi_set_int_value ((omapi_object_t
*)dhcp_control_object
,
793 (omapi_object_t
*)0, "state", server_running
);
795 #if defined(ENABLE_GENTLE_SHUTDOWN)
796 /* no signal handlers until we deal with the side effects */
797 /* install signal handlers */
798 signal(SIGINT
, dhcp_signal_handler
); /* control-c */
799 signal(SIGTERM
, dhcp_signal_handler
); /* kill */
802 /* Log that we are about to start working */
803 log_info("Server starting service.");
806 * Receive packets and dispatch them...
807 * dispatch() will never return.
811 /* Let's return status code */
814 #endif /* !UNIT_TEST */
816 void postconf_initialization (int quiet
)
818 struct option_state
*options
= NULL
;
819 struct data_string db
;
820 struct option_cache
*oc
;
824 #if defined (NSUPDATE)
825 struct in_addr local4
, *local4_ptr
= NULL
;
826 struct in6_addr local6
, *local6_ptr
= NULL
;
829 /* Now try to get the lease file name. */
830 option_state_allocate(&options
, MDL
);
832 execute_statements_in_scope(NULL
, NULL
, NULL
, NULL
, NULL
,
833 options
, &global_scope
, root_group
,
835 memset(&db
, 0, sizeof db
);
836 oc
= lookup_option(&server_universe
, options
, SV_LEASE_FILE_NAME
);
838 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
839 &global_scope
, oc
, MDL
)) {
840 s
= dmalloc(db
.len
+ 1, MDL
);
842 log_fatal("no memory for lease db filename.");
843 memcpy(s
, db
.data
, db
.len
);
845 data_string_forget(&db
, MDL
);
849 oc
= lookup_option(&server_universe
, options
, SV_PID_FILE_NAME
);
851 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
852 &global_scope
, oc
, MDL
)) {
853 s
= dmalloc(db
.len
+ 1, MDL
);
855 log_fatal("no memory for pid filename.");
856 memcpy(s
, db
.data
, db
.len
);
858 data_string_forget(&db
, MDL
);
863 if (local_family
== AF_INET6
) {
865 * Override lease file name with dhcpv6 lease file name,
866 * if it was set; then, do the same with the pid file name
868 oc
= lookup_option(&server_universe
, options
,
869 SV_DHCPV6_LEASE_FILE_NAME
);
871 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
872 &global_scope
, oc
, MDL
)) {
873 s
= dmalloc(db
.len
+ 1, MDL
);
875 log_fatal("no memory for lease db filename.");
876 memcpy(s
, db
.data
, db
.len
);
878 data_string_forget(&db
, MDL
);
882 oc
= lookup_option(&server_universe
, options
,
883 SV_DHCPV6_PID_FILE_NAME
);
885 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
886 &global_scope
, oc
, MDL
)) {
887 s
= dmalloc(db
.len
+ 1, MDL
);
889 log_fatal("no memory for pid filename.");
890 memcpy(s
, db
.data
, db
.len
);
892 data_string_forget(&db
, MDL
);
899 oc
= lookup_option(&server_universe
, options
, SV_OMAPI_PORT
);
901 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
902 &global_scope
, oc
, MDL
)) {
904 omapi_port
= getUShort(db
.data
);
906 log_fatal("invalid omapi port data length");
907 data_string_forget(&db
, MDL
);
910 oc
= lookup_option(&server_universe
, options
, SV_OMAPI_KEY
);
912 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
913 &global_scope
, oc
, MDL
)) {
914 s
= dmalloc(db
.len
+ 1, MDL
);
916 log_fatal("no memory for OMAPI key filename.");
917 memcpy(s
, db
.data
, db
.len
);
919 data_string_forget(&db
, MDL
);
920 result
= omapi_auth_key_lookup_name(&omapi_key
, s
);
922 if (result
!= ISC_R_SUCCESS
)
923 log_fatal("OMAPI key %s: %s",
924 s
, isc_result_totext (result
));
927 oc
= lookup_option(&server_universe
, options
, SV_LOCAL_PORT
);
929 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
930 &global_scope
, oc
, MDL
)) {
932 local_port
= htons(getUShort (db
.data
));
934 log_fatal("invalid local port data length");
935 data_string_forget(&db
, MDL
);
938 oc
= lookup_option(&server_universe
, options
, SV_REMOTE_PORT
);
940 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
941 &global_scope
, oc
, MDL
)) {
943 remote_port
= htons(getUShort (db
.data
));
945 log_fatal("invalid remote port data length");
946 data_string_forget(&db
, MDL
);
949 oc
= lookup_option(&server_universe
, options
,
950 SV_LIMITED_BROADCAST_ADDRESS
);
952 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
953 &global_scope
, oc
, MDL
)) {
955 memcpy(&limited_broadcast
, db
.data
, 4);
957 log_fatal("invalid broadcast address data length");
958 data_string_forget(&db
, MDL
);
961 oc
= lookup_option(&server_universe
, options
, SV_LOCAL_ADDRESS
);
963 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
964 &global_scope
, oc
, MDL
)) {
966 memcpy(&local_address
, db
.data
, 4);
968 log_fatal("invalid local address data length");
969 data_string_forget(&db
, MDL
);
972 oc
= lookup_option(&server_universe
, options
, SV_DDNS_UPDATE_STYLE
);
974 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
975 &global_scope
, oc
, MDL
)) {
977 ddns_update_style
= db
.data
[0];
979 log_fatal("invalid dns update type");
980 data_string_forget(&db
, MDL
);
983 ddns_update_style
= DDNS_UPDATE_STYLE_NONE
;
985 #if defined (NSUPDATE)
986 /* We no longer support ad_hoc, tell the user */
987 if (ddns_update_style
== DDNS_UPDATE_STYLE_AD_HOC
) {
988 log_fatal("ddns-update-style ad_hoc no longer supported");
991 oc
= lookup_option(&server_universe
, options
, SV_DDNS_LOCAL_ADDRESS4
);
993 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
994 &global_scope
, oc
, MDL
)) {
996 memcpy(&local4
, db
.data
, 4);
997 local4_ptr
= &local4
;
999 data_string_forget(&db
, MDL
);
1003 oc
= lookup_option(&server_universe
, options
, SV_DDNS_LOCAL_ADDRESS6
);
1005 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1006 &global_scope
, oc
, MDL
)) {
1008 memcpy(&local6
, db
.data
, 16);
1009 local6_ptr
= &local6
;
1011 data_string_forget(&db
, MDL
);
1015 if (dhcp_context_create(DHCP_CONTEXT_POST_DB
, local4_ptr
, local6_ptr
)
1017 log_fatal("Unable to complete ddns initialization");
1020 /* If we don't have support for updates compiled in tell the user */
1021 if (ddns_update_style
!= DDNS_UPDATE_STYLE_NONE
) {
1022 log_fatal("Support for ddns-update-style not compiled in");
1027 log_info ("Config file: %s", path_dhcpd_conf
);
1028 log_info ("Database file: %s", path_dhcpd_db
);
1029 log_info ("PID file: %s", path_dhcpd_pid
);
1032 oc
= lookup_option(&server_universe
, options
, SV_LOG_FACILITY
);
1034 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1035 &global_scope
, oc
, MDL
)) {
1038 openlog("dhcpd", DHCP_LOG_OPTIONS
, db
.data
[0]);
1039 /* Log the startup banner into the new
1041 /* Don't log to stderr twice. */
1044 log_info("%s %s", message
, PACKAGE_VERSION
);
1045 log_info(copyright
);
1050 log_fatal("invalid log facility");
1051 data_string_forget(&db
, MDL
);
1055 oc
= lookup_option(&server_universe
, options
, SV_DELAYED_ACK
);
1057 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1058 &global_scope
, oc
, MDL
)) {
1060 max_outstanding_acks
= htons(getUShort(db
.data
));
1062 log_fatal("invalid max delayed ACK count ");
1064 data_string_forget(&db
, MDL
);
1067 oc
= lookup_option(&server_universe
, options
, SV_MAX_ACK_DELAY
);
1069 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1070 &global_scope
, oc
, MDL
)) {
1074 log_fatal("invalid max ack delay configuration");
1076 timeval
= getULong(db
.data
);
1077 max_ack_delay_secs
= timeval
/ 1000000;
1078 max_ack_delay_usecs
= timeval
% 1000000;
1080 data_string_forget(&db
, MDL
);
1083 oc
= lookup_option(&server_universe
, options
, SV_DONT_USE_FSYNC
);
1085 evaluate_boolean_option_cache(NULL
, NULL
, NULL
, NULL
, options
, NULL
,
1086 &global_scope
, oc
, MDL
)) {
1088 log_error("Not using fsync() to flush lease writes");
1091 oc
= lookup_option(&server_universe
, options
, SV_SERVER_ID_CHECK
);
1093 evaluate_boolean_option_cache(NULL
, NULL
, NULL
, NULL
, options
, NULL
,
1094 &global_scope
, oc
, MDL
)) {
1095 log_info("Setting server-id-check true");
1096 server_id_check
= 1;
1099 /* Don't need the options anymore. */
1100 option_state_dereference(&options
, MDL
);
1103 void postdb_startup (void)
1105 /* Initialize the omapi listener state. */
1106 if (omapi_port
!= -1) {
1107 omapi_listener_start (0);
1110 #if defined (FAILOVER_PROTOCOL)
1111 /* Initialize the failover listener state. */
1112 dhcp_failover_startup ();
1116 * Begin our lease timeout background task.
1118 schedule_all_ipv6_lease_timeouts();
1121 /* Print usage message. */
1125 log_info("%s %s", message
, PACKAGE_VERSION
);
1126 log_info(copyright
);
1129 log_fatal("Usage: dhcpd [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
1131 " [-4|-6] [-cf config-file] [-lf lease-file]\n"
1133 " [-cf config-file] [-lf lease-file]\n"
1135 #if defined (PARANOIA)
1136 /* meld into the following string */
1137 " [-user user] [-group group] [-chroot dir]\n"
1138 #endif /* PARANOIA */
1139 #if defined (TRACING)
1140 " [-tf trace-output-file]\n"
1141 " [-play trace-input-file]\n"
1142 #endif /* TRACING */
1143 " [-pf pid-file] [--no-pid] [-s server]\n"
1148 void lease_pinged (from
, packet
, length
)
1155 /* Don't try to look up a pinged lease if we aren't trying to
1156 ping one - otherwise somebody could easily make us churn by
1157 just forging repeated ICMP EchoReply packets for us to look
1159 if (!outstanding_pings
)
1162 lp
= (struct lease
*)0;
1163 if (!find_lease_by_ip_addr (&lp
, from
, MDL
)) {
1164 log_debug ("unexpected ICMP Echo Reply from %s",
1170 #if defined (FAILOVER_PROTOCOL)
1172 !lp
-> pool
-> failover_peer
)
1174 log_debug ("ICMP Echo Reply for %s late or spurious.",
1179 if (lp
-> ends
> cur_time
) {
1180 log_debug ("ICMP Echo reply while lease %s valid.",
1184 /* At this point it looks like we pinged a lease and got a
1185 response, which shouldn't have happened. */
1186 data_string_forget (&lp
-> state
-> parameter_request_list
, MDL
);
1187 free_lease_state (lp
-> state
, MDL
);
1188 lp
-> state
= (struct lease_state
*)0;
1190 abandon_lease (lp
, "pinged before offer");
1191 cancel_timeout (lease_ping_timeout
, lp
);
1192 --outstanding_pings
;
1194 lease_dereference (&lp
, MDL
);
1197 void lease_ping_timeout (vlp
)
1200 struct lease
*lp
= vlp
;
1202 #if defined (DEBUG_MEMORY_LEAKAGE)
1203 unsigned long previous_outstanding
= dmalloc_outstanding
;
1206 --outstanding_pings
;
1209 #if defined (DEBUG_MEMORY_LEAKAGE)
1210 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
1212 dmalloc_outstanding
- previous_outstanding
,
1213 dmalloc_outstanding
, dmalloc_longterm
);
1215 #if defined (DEBUG_MEMORY_LEAKAGE)
1216 dmalloc_dump_outstanding ();
1220 int dhcpd_interface_setup_hook (struct interface_info
*ip
, struct iaddr
*ia
)
1222 struct subnet
*subnet
;
1223 struct shared_network
*share
;
1224 isc_result_t status
;
1226 /* Special case for fallback network - not sure why this is
1229 const char *fnn
= "fallback-net";
1230 status
= shared_network_allocate (&ip
-> shared_network
, MDL
);
1231 if (status
!= ISC_R_SUCCESS
)
1232 log_fatal ("No memory for shared subnet: %s",
1233 isc_result_totext (status
));
1234 ip
-> shared_network
-> name
= dmalloc (strlen (fnn
) + 1, MDL
);
1235 strcpy (ip
-> shared_network
-> name
, fnn
);
1239 /* If there's a registered subnet for this address,
1240 connect it together... */
1241 subnet
= (struct subnet
*)0;
1242 if (find_subnet (&subnet
, *ia
, MDL
)) {
1243 /* If this interface has multiple aliases on the same
1244 subnet, ignore all but the first we encounter. */
1245 if (!subnet
-> interface
) {
1246 interface_reference (&subnet
-> interface
, ip
, MDL
);
1247 subnet
-> interface_address
= *ia
;
1248 } else if (subnet
-> interface
!= ip
) {
1249 log_error ("Multiple interfaces match the %s: %s %s",
1251 subnet
-> interface
-> name
, ip
-> name
);
1253 share
= subnet
-> shared_network
;
1254 if (ip
-> shared_network
&&
1255 ip
-> shared_network
!= share
) {
1256 log_fatal ("Interface %s matches multiple shared %s",
1257 ip
-> name
, "networks");
1259 if (!ip
-> shared_network
)
1260 shared_network_reference
1261 (&ip
-> shared_network
, share
, MDL
);
1264 if (!share
-> interface
) {
1265 interface_reference (&share
-> interface
, ip
, MDL
);
1266 } else if (share
-> interface
!= ip
) {
1267 log_error ("Multiple interfaces match the %s: %s %s",
1268 "same shared network",
1269 share
-> interface
-> name
, ip
-> name
);
1271 subnet_dereference (&subnet
, MDL
);
1276 static TIME shutdown_time
;
1277 static int omapi_connection_count
;
1278 enum dhcp_shutdown_state shutdown_state
;
1280 isc_result_t
dhcp_io_shutdown (omapi_object_t
*obj
, void *foo
)
1282 /* Shut down all listeners. */
1283 if (shutdown_state
== shutdown_listeners
&&
1284 obj
-> type
== omapi_type_listener
&&
1286 obj
-> inner
-> type
== omapi_type_protocol_listener
) {
1287 omapi_listener_destroy (obj
, MDL
);
1288 return ISC_R_SUCCESS
;
1291 /* Shut down all existing omapi connections. */
1292 if (obj
-> type
== omapi_type_connection
&&
1294 obj
-> inner
-> type
== omapi_type_protocol
) {
1295 if (shutdown_state
== shutdown_drop_omapi_connections
) {
1296 omapi_disconnect (obj
, 1);
1298 omapi_connection_count
++;
1299 if (shutdown_state
== shutdown_omapi_connections
) {
1300 omapi_disconnect (obj
, 0);
1301 return ISC_R_SUCCESS
;
1305 /* Shutdown all DHCP interfaces. */
1306 if (obj
-> type
== dhcp_type_interface
&&
1307 shutdown_state
== shutdown_dhcp
) {
1308 dhcp_interface_remove (obj
, (omapi_object_t
*)0);
1309 return ISC_R_SUCCESS
;
1311 return ISC_R_SUCCESS
;
1314 static isc_result_t
dhcp_io_shutdown_countdown (void *vlp
)
1316 #if defined (FAILOVER_PROTOCOL)
1317 dhcp_failover_state_t
*state
;
1318 int failover_connection_count
= 0;
1323 if (shutdown_state
== shutdown_listeners
||
1324 shutdown_state
== shutdown_omapi_connections
||
1325 shutdown_state
== shutdown_drop_omapi_connections
||
1326 shutdown_state
== shutdown_dhcp
) {
1327 omapi_connection_count
= 0;
1328 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
1331 if ((shutdown_state
== shutdown_listeners
||
1332 shutdown_state
== shutdown_omapi_connections
||
1333 shutdown_state
== shutdown_drop_omapi_connections
) &&
1334 omapi_connection_count
== 0) {
1335 shutdown_state
= shutdown_dhcp
;
1336 shutdown_time
= cur_time
;
1338 } else if (shutdown_state
== shutdown_listeners
&&
1339 cur_time
- shutdown_time
> 4) {
1340 shutdown_state
= shutdown_omapi_connections
;
1341 shutdown_time
= cur_time
;
1342 } else if (shutdown_state
== shutdown_omapi_connections
&&
1343 cur_time
- shutdown_time
> 4) {
1344 shutdown_state
= shutdown_drop_omapi_connections
;
1345 shutdown_time
= cur_time
;
1346 } else if (shutdown_state
== shutdown_drop_omapi_connections
&&
1347 cur_time
- shutdown_time
> 4) {
1348 shutdown_state
= shutdown_dhcp
;
1349 shutdown_time
= cur_time
;
1351 } else if (shutdown_state
== shutdown_dhcp
&&
1352 cur_time
- shutdown_time
> 4) {
1353 shutdown_state
= shutdown_done
;
1354 shutdown_time
= cur_time
;
1357 #if defined (FAILOVER_PROTOCOL)
1358 /* Set all failover peers into the shutdown state. */
1359 if (shutdown_state
== shutdown_dhcp
) {
1360 for (state
= failover_states
; state
; state
= state
-> next
) {
1361 if (state
-> me
.state
== normal
) {
1362 dhcp_failover_set_state (state
, shut_down
);
1363 failover_connection_count
++;
1365 if (state
-> me
.state
== shut_down
&&
1366 state
-> partner
.state
!= partner_down
)
1367 failover_connection_count
++;
1371 if (shutdown_state
== shutdown_done
) {
1372 for (state
= failover_states
; state
; state
= state
-> next
) {
1373 if (state
-> me
.state
== shut_down
) {
1374 if (state
-> link_to_peer
)
1375 dhcp_failover_link_dereference (&state
-> link_to_peer
,
1377 dhcp_failover_set_state (state
, recover
);
1380 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1381 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1383 omapi_print_dmalloc_usage_by_caller ();
1385 if (no_pid_file
== ISC_FALSE
)
1386 (void) unlink(path_dhcpd_pid
);
1390 if (shutdown_state
== shutdown_done
) {
1391 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1392 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1394 omapi_print_dmalloc_usage_by_caller ();
1396 if (no_pid_file
== ISC_FALSE
)
1397 (void) unlink(path_dhcpd_pid
);
1401 if (shutdown_state
== shutdown_dhcp
&&
1402 #if defined(FAILOVER_PROTOCOL)
1403 !failover_connection_count
&&
1406 shutdown_state
= shutdown_done
;
1407 shutdown_time
= cur_time
;
1410 tv
.tv_sec
= cur_tv
.tv_sec
+ 1;
1411 tv
.tv_usec
= cur_tv
.tv_usec
;
1413 (void (*)(void *))dhcp_io_shutdown_countdown
, 0, 0, 0);
1414 return ISC_R_SUCCESS
;
1417 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
1418 control_object_state_t newstate
)
1422 if (newstate
!= server_shutdown
)
1423 return DHCP_R_INVALIDARG
;
1425 if (shutdown_signal
== SIGUSR1
)
1426 return ISC_R_SUCCESS
;
1427 shutdown_time
= cur_time
;
1428 shutdown_state
= shutdown_listeners
;
1429 /* Called by user. */
1430 if (shutdown_signal
== 0) {
1431 shutdown_signal
= SIGUSR1
;
1432 dhcp_io_shutdown_countdown (0);
1433 return ISC_R_SUCCESS
;
1435 /* Called on signal. */
1436 log_info("Received signal %d, initiating shutdown.", shutdown_signal
);
1437 shutdown_signal
= SIGUSR1
;
1440 * Prompt the shutdown event onto the timer queue
1441 * and return to the dispatch loop.
1443 tv
.tv_sec
= cur_tv
.tv_sec
;
1444 tv
.tv_usec
= cur_tv
.tv_usec
+ 1;
1446 (void (*)(void *))dhcp_io_shutdown_countdown
, 0, 0, 0);
1447 return ISC_R_SUCCESS
;