1 /* $NetBSD: dhcpd.c,v 1.4 2014/07/12 12:09:38 spz Exp $ */
7 * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1996-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Redwood City, CA 94063
26 * https://www.isc.org/
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: dhcpd.c,v 1.4 2014/07/12 12:09:38 spz Exp $");
33 static const char copyright
[] =
34 "Copyright 2004-2014 Internet Systems Consortium.";
35 static const char arr
[] = "All rights reserved.";
36 static const char message
[] = "Internet Systems Consortium DHCP Server";
37 static const char url
[] =
38 "For info, please visit https://www.isc.org/software/dhcp/";
41 #include <omapip/omapip_p.h>
46 #include <sys/types.h>
49 #if defined (PARANOIA)
50 # include <sys/types.h>
53 /* get around the ISC declaration of group */
54 # define group real_group
60 static void usage(void);
63 struct iaddr server_identifier
;
64 int server_identifier_matched
;
66 #if defined (NSUPDATE)
68 /* 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); \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 */
81 const char *path_dhcpd_conf
= _PATH_DHCPD_CONF
;
82 const char *path_dhcpd_db
= _PATH_DHCPD_DB
;
83 const char *path_dhcpd_pid
= _PATH_DHCPD_PID
;
84 /* False (default) => we write and use a pid file */
85 isc_boolean_t no_pid_file
= ISC_FALSE
;
87 int dhcp_max_agent_option_packet_length
= DHCP_MTU_MAX
;
89 static omapi_auth_key_t
*omapi_key
= (omapi_auth_key_t
*)0;
93 trace_type_t
*trace_srandom
;
96 static isc_result_t
verify_addr (omapi_object_t
*l
, omapi_addr_t
*addr
) {
100 static isc_result_t
verify_auth (omapi_object_t
*p
, omapi_auth_key_t
*a
) {
102 return DHCP_R_INVALIDKEY
;
103 return ISC_R_SUCCESS
;
106 static void omapi_listener_start (void *foo
)
108 omapi_object_t
*listener
;
112 listener
= (omapi_object_t
*)0;
113 result
= omapi_generic_new (&listener
, MDL
);
114 if (result
!= ISC_R_SUCCESS
)
115 log_fatal ("Can't allocate new generic object: %s",
116 isc_result_totext (result
));
117 result
= omapi_protocol_listen (listener
,
118 (unsigned)omapi_port
, 1);
119 if (result
== ISC_R_SUCCESS
&& omapi_key
)
120 result
= omapi_protocol_configure_security
121 (listener
, verify_addr
, verify_auth
);
122 if (result
!= ISC_R_SUCCESS
) {
123 log_error ("Can't start OMAPI protocol: %s",
124 isc_result_totext (result
));
125 tv
.tv_sec
= cur_tv
.tv_sec
+ 5;
126 tv
.tv_usec
= cur_tv
.tv_usec
;
127 add_timeout (&tv
, omapi_listener_start
, 0, 0, 0);
129 omapi_object_dereference (&listener
, MDL
);
132 #if defined (PARANOIA)
133 /* to be used in one of two possible scenarios */
134 static void setup_chroot (char *chroot_dir
) {
136 log_fatal ("you must be root to use chroot");
138 if (chroot(chroot_dir
)) {
139 log_fatal ("chroot(\"%s\"): %m", chroot_dir
);
142 /* probably permission denied */
143 log_fatal ("chdir(\"/\"): %m");
146 #endif /* PARANOIA */
150 main(int argc
, char **argv
) {
163 char *server
= (char *)0;
166 struct interface_info
*ip
;
167 #if defined (NSUPDATE)
171 int no_dhcpd_conf
= 0;
173 int no_dhcpd_pid
= 0;
175 int local_family_set
= 0;
177 #if defined (TRACING)
178 char *traceinfile
= (char *)0;
179 char *traceoutfile
= (char *)0;
182 #if defined (PARANOIA)
185 char *set_chroot
= 0;
189 #endif /* PARANOIA */
191 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
192 2 (stderr) are open. To do this, we assume that when we
193 open a file the lowest available file descriptor is used. */
194 fd
= open("/dev/null", O_RDWR
);
196 fd
= open("/dev/null", O_RDWR
);
198 fd
= open("/dev/null", O_RDWR
);
200 log_perror
= 0; /* No sense logging to /dev/null. */
204 /* Initialize the omapi system. */
205 result
= omapi_init ();
206 if (result
!= ISC_R_SUCCESS
)
207 log_fatal ("Can't initialize OMAPI: %s",
208 isc_result_totext (result
));
210 /* Set up the OMAPI wrappers for common objects. */
211 dhcp_db_objects_setup ();
212 /* Set up the OMAPI wrappers for various server database internal
214 dhcp_common_objects_setup ();
216 /* Initially, log errors to stderr as well as to syslogd. */
217 openlog ("dhcpd", LOG_NDELAY
, DHCPD_LOG_FACILITY
);
219 for (i
= 1; i
< argc
; i
++) {
220 if (!strcmp (argv
[i
], "-p")) {
223 local_port
= validate_port (argv
[i
]);
224 log_debug ("binding to user-specified port %d",
226 } else if (!strcmp (argv
[i
], "-f")) {
230 } else if (!strcmp (argv
[i
], "-d")) {
235 } else if (!strcmp (argv
[i
], "-s")) {
239 #if defined (PARANOIA)
240 } else if (!strcmp (argv
[i
], "-user")) {
244 } else if (!strcmp (argv
[i
], "-group")) {
247 set_group
= argv
[i
];
248 } else if (!strcmp (argv
[i
], "-chroot")) {
251 set_chroot
= argv
[i
];
252 #endif /* PARANOIA */
253 } else if (!strcmp (argv
[i
], "-cf")) {
256 path_dhcpd_conf
= argv
[i
];
258 } else if (!strcmp (argv
[i
], "-lf")) {
261 path_dhcpd_db
= argv
[i
];
263 } else if (!strcmp (argv
[i
], "-pf")) {
266 path_dhcpd_pid
= argv
[i
];
268 } else if (!strcmp(argv
[i
], "--no-pid")) {
269 no_pid_file
= ISC_TRUE
;
270 } else if (!strcmp (argv
[i
], "-t")) {
271 /* test configurations only */
277 } else if (!strcmp (argv
[i
], "-T")) {
278 /* test configurations and lease file only */
285 } else if (!strcmp (argv
[i
], "-q")) {
287 quiet_interface_discovery
= 1;
289 } else if (!strcmp(argv
[i
], "-4")) {
290 if (local_family_set
&& (local_family
!= AF_INET
)) {
291 log_fatal("Server cannot run in both IPv4 and "
292 "IPv6 mode at the same time.");
294 local_family
= AF_INET
;
295 local_family_set
= 1;
296 } else if (!strcmp(argv
[i
], "-6")) {
297 if (local_family_set
&& (local_family
!= AF_INET6
)) {
298 log_fatal("Server cannot run in both IPv4 and "
299 "IPv6 mode at the same time.");
301 local_family
= AF_INET6
;
302 local_family_set
= 1;
304 } else if (!strcmp (argv
[i
], "--version")) {
305 log_info("isc-dhcpd-%s", PACKAGE_VERSION
);
307 #if defined (TRACING)
308 } else if (!strcmp (argv
[i
], "-tf")) {
311 traceoutfile
= argv
[i
];
312 } else if (!strcmp (argv
[i
], "-play")) {
315 traceinfile
= argv
[i
];
316 trace_replay_init ();
318 } else if (argv
[i
][0] == '-') {
321 struct interface_info
*tmp
=
322 (struct interface_info
*)0;
323 if (strlen(argv
[i
]) >= sizeof(tmp
->name
))
324 log_fatal("%s: interface name too long "
326 argv
[i
], (long)strlen(argv
[i
]));
327 result
= interface_allocate (&tmp
, MDL
);
328 if (result
!= ISC_R_SUCCESS
)
329 log_fatal ("Insufficient memory to %s %s: %s",
330 "record interface", argv
[i
],
331 isc_result_totext (result
));
332 strcpy (tmp
-> name
, argv
[i
]);
334 interface_reference (&tmp
-> next
,
336 interface_dereference (&interfaces
, MDL
);
338 interface_reference (&interfaces
, tmp
, MDL
);
339 tmp
-> flags
= INTERFACE_REQUESTED
;
343 if (!no_dhcpd_conf
&& (s
= getenv ("PATH_DHCPD_CONF"))) {
348 if (local_family
== AF_INET6
) {
349 /* DHCPv6: override DHCPv4 lease and pid filenames */
351 if ((s
= getenv ("PATH_DHCPD6_DB")))
354 path_dhcpd_db
= _PATH_DHCPD6_DB
;
357 if ((s
= getenv ("PATH_DHCPD6_PID")))
360 path_dhcpd_pid
= _PATH_DHCPD6_PID
;
365 if (!no_dhcpd_db
&& (s
= getenv ("PATH_DHCPD_DB"))) {
368 if (!no_dhcpd_pid
&& (s
= getenv ("PATH_DHCPD_PID"))) {
375 * convert relative path names to absolute, for files that need
376 * to be reopened after chdir() has been called
378 if (path_dhcpd_db
[0] != '/') {
379 const char *path
= path_dhcpd_db
;
380 path_dhcpd_db
= realpath(path_dhcpd_db
, NULL
);
381 if (path_dhcpd_db
== NULL
)
382 log_fatal("Failed to get realpath for %s: %s", path
,
387 log_info("%s %s", message
, PACKAGE_VERSION
);
388 log_info (copyright
);
398 * We need to fork before we call the context create
399 * call that creates the worker threads!
402 /* First part of becoming a daemon... */
403 if ((pid
= fork ()) < 0)
404 log_fatal ("Can't fork daemon: %m");
410 /* Set up the isc and dns library managers */
411 status
= dhcp_context_create(DHCP_CONTEXT_PRE_DB
, NULL
, NULL
);
412 if (status
!= ISC_R_SUCCESS
)
413 log_fatal("Can't initialize context: %s",
414 isc_result_totext(status
));
416 /* Set up the client classification system. */
417 classification_setup ();
419 #if defined (TRACING)
420 trace_init (set_time
, MDL
);
422 result
= trace_begin (traceoutfile
, MDL
);
423 if (result
!= ISC_R_SUCCESS
)
424 log_fatal ("Unable to begin trace: %s",
425 isc_result_totext (result
));
427 interface_trace_setup ();
428 parse_trace_setup ();
429 trace_srandom
= trace_type_register ("random-seed", (void *)0,
431 trace_seed_stop
, MDL
);
435 #if defined (PARANOIA)
436 /* get user and group info if those options were given */
438 struct passwd
*tmp_pwd
;
441 log_fatal ("you must be root to set user");
443 if (!(tmp_pwd
= getpwnam(set_user
)))
444 log_fatal ("no such user: %s", set_user
);
446 set_uid
= tmp_pwd
->pw_uid
;
448 /* use the user's group as the default gid */
450 set_gid
= tmp_pwd
->pw_gid
;
454 /* get around the ISC declaration of group */
455 #define group real_group
456 struct group
*tmp_grp
;
459 log_fatal ("you must be root to set group");
461 if (!(tmp_grp
= getgrnam(set_group
)))
462 log_fatal ("no such group: %s", set_group
);
464 set_gid
= tmp_grp
->gr_gid
;
468 # if defined (EARLY_CHROOT)
469 if (set_chroot
) setup_chroot (set_chroot
);
470 # endif /* EARLY_CHROOT */
471 #endif /* PARANOIA */
473 /* Default to the DHCP/BOOTP port. */
476 if ((s
= getenv ("DHCPD_PORT"))) {
477 local_port
= validate_port (s
);
478 log_debug ("binding to environment-specified port %d",
481 if (local_family
== AF_INET
) {
482 ent
= getservbyname("dhcp", "udp");
484 local_port
= htons(67);
486 local_port
= ent
->s_port
;
489 /* INSIST(local_family == AF_INET6); */
490 ent
= getservbyname("dhcpv6-server", "udp");
492 local_port
= htons(547);
494 local_port
= ent
->s_port
;
497 #ifndef __CYGWIN32__ /* XXX */
503 if (local_family
== AF_INET
) {
504 remote_port
= htons(ntohs(local_port
) + 1);
506 /* INSIST(local_family == AF_INET6); */
507 ent
= getservbyname("dhcpv6-client", "udp");
509 remote_port
= htons(546);
511 remote_port
= ent
->s_port
;
516 if (local_family
!= AF_INET
) {
517 log_fatal("You can only specify address to send "
518 "replies to when running an IPv4 server.");
520 if (!inet_aton (server
, &limited_broadcast
)) {
522 he
= gethostbyname (server
);
524 memcpy (&limited_broadcast
,
525 he
-> h_addr_list
[0],
526 sizeof limited_broadcast
);
528 limited_broadcast
.s_addr
= INADDR_BROADCAST
;
531 limited_broadcast
.s_addr
= INADDR_BROADCAST
;
534 /* Get the current time... */
535 gettimeofday(&cur_tv
, NULL
);
537 /* Set up the initial dhcp option universe. */
538 initialize_common_option_spaces ();
539 initialize_server_option_spaces ();
541 /* Add the ddns update style enumeration prior to parsing. */
542 add_enumeration (&ddns_styles
);
543 add_enumeration (&syslog_enum
);
544 #if defined (LDAP_CONFIGURATION)
545 add_enumeration (&ldap_methods
);
546 #if defined (LDAP_USE_SSL)
547 add_enumeration (&ldap_ssl_usage_enum
);
548 add_enumeration (&ldap_tls_reqcert_enum
);
549 add_enumeration (&ldap_tls_crlcheck_enum
);
553 if (!group_allocate (&root_group
, MDL
))
554 log_fatal ("Can't allocate root group!");
555 root_group
-> authoritative
= 0;
557 /* Set up various hooks. */
558 dhcp_interface_setup_hook
= dhcpd_interface_setup_hook
;
559 bootp_packet_handler
= do_packet
;
561 dhcpv6_packet_handler
= do_packet6
;
564 #if defined (NSUPDATE)
565 /* Set up the standard name service updater routine. */
567 status
= new_parse(&parse
, -1, std_nsupdate
, sizeof(std_nsupdate
) - 1,
568 "standard name service update routine", 0);
569 if (status
!= ISC_R_SUCCESS
)
570 log_fatal ("can't begin parsing name service updater!");
574 if (!(parse_executable_statements(&root_group
->statements
,
575 parse
, &lose
, context_any
))) {
577 log_fatal("can't parse standard name service updater!");
583 /* Initialize icmp support... */
584 if (!cftest
&& !lftest
)
585 icmp_startup (1, lease_pinged
);
587 #if defined (TRACING)
590 log_error ("%s", "");
591 log_error ("** You must specify a lease file with -lf.");
592 log_error (" Dhcpd will not overwrite your default");
593 log_fatal (" lease file when playing back a trace. **");
595 trace_file_replay (traceinfile
);
597 #if defined (DEBUG_MEMORY_LEAKAGE) && \
598 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
600 omapi_print_dmalloc_usage_by_caller ();
608 /* set up DHCPv6 hashes */
609 if (!ia_new_hash(&ia_na_active
, DEFAULT_HASH_SIZE
, MDL
)) {
610 log_fatal("Out of memory creating hash for active IA_NA.");
612 if (!ia_new_hash(&ia_ta_active
, DEFAULT_HASH_SIZE
, MDL
)) {
613 log_fatal("Out of memory creating hash for active IA_TA.");
615 if (!ia_new_hash(&ia_pd_active
, DEFAULT_HASH_SIZE
, MDL
)) {
616 log_fatal("Out of memory creating hash for active IA_PD.");
620 /* Read the dhcpd.conf file... */
621 if (readconf () != ISC_R_SUCCESS
)
622 log_fatal ("Configuration file errors encountered -- exiting");
624 postconf_initialization (quiet
);
626 #if defined (PARANOIA) && !defined (EARLY_CHROOT)
627 if (set_chroot
) setup_chroot (set_chroot
);
628 #endif /* PARANOIA && !EARLY_CHROOT */
630 /* test option should cause an early exit */
631 if (cftest
&& !lftest
)
634 group_write_hook
= group_writer
;
636 /* Start up the database... */
642 /* Discover all the network interfaces and initialize them. */
643 discover_interfaces(DISCOVER_SERVER
);
647 * Remove addresses from our pools that we should not issue
650 * We currently have no support for this in IPv4. It is not
651 * as important in IPv4, as making pools with ranges that
652 * leave out interfaces and hosts is fairly straightforward
653 * using range notation, but not so handy with CIDR notation.
655 if (local_family
== AF_INET6
) {
656 mark_hosts_unavailable();
657 mark_phosts_unavailable();
658 mark_interfaces_unavailable();
663 /* Make up a seed for the random number generator from current
664 time plus the sum of the last four bytes of each
665 interface's hardware address interpreted as an integer.
666 Not much entropy, but we're booting, so we're not likely to
667 find anything better. */
669 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
672 &ip
-> hw_address
.hbuf
[ip
-> hw_address
.hlen
-
673 sizeof seed
], sizeof seed
);
676 srandom (seed
+ cur_time
);
677 #if defined (TRACING)
678 trace_seed_stash (trace_srandom
, seed
+ cur_time
);
684 * Set server DHCPv6 identifier.
685 * See dhcpv6.c for discussion of setting DUID.
687 if (set_server_duid_from_option() == ISC_R_SUCCESS
) {
690 if (!server_duid_isset()) {
691 if (generate_new_server_duid() != ISC_R_SUCCESS
) {
692 log_fatal("Unable to set server identifier.");
701 #if defined (PARANOIA)
702 /* change uid to the specified one */
705 if (setgroups (0, (void *)0))
706 log_fatal ("setgroups: %m");
707 if (setgid (set_gid
))
708 log_fatal ("setgid(%d): %m", (int) set_gid
);
712 if (setuid (set_uid
))
713 log_fatal ("setuid(%d): %m", (int) set_uid
);
715 #endif /* PARANOIA */
718 * Deal with pid files. If the user told us
719 * not to write a file we don't read one either
721 if (no_pid_file
== ISC_FALSE
) {
722 /*Read previous pid file. */
723 if ((i
= open (path_dhcpd_pid
, O_RDONLY
)) >= 0) {
724 status
= read(i
, pbuf
, (sizeof pbuf
) - 1);
731 * If there was a previous server process and
732 * it is still running, abort
735 (pid
!= getpid() && kill(pid
, 0) == 0))
736 log_fatal("There's already a "
737 "DHCP server running.");
741 /* Write new pid file. */
742 i
= open(path_dhcpd_pid
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
744 sprintf(pbuf
, "%d\n", (int) getpid());
745 IGNORE_RET (write(i
, pbuf
, strlen(pbuf
)));
748 log_error("Can't create PID file %s: %m.",
753 /* If we were requested to log to stdout on the command line,
754 keep doing so; otherwise, stop. */
755 if (log_perror
== -1)
761 /* Become session leader and get pid... */
764 /* Close standard I/O descriptors. */
769 /* Reopen them on /dev/null. */
770 (void) open("/dev/null", O_RDWR
);
771 (void) open("/dev/null", O_RDWR
);
772 (void) open("/dev/null", O_RDWR
);
773 log_perror
= 0; /* No sense logging to /dev/null. */
775 IGNORE_RET (chdir("/"));
779 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
780 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
781 dmalloc_cutoff_generation
= dmalloc_generation
;
782 dmalloc_longterm
= dmalloc_outstanding
;
783 dmalloc_outstanding
= 0;
786 omapi_set_int_value ((omapi_object_t
*)dhcp_control_object
,
787 (omapi_object_t
*)0, "state", server_running
);
789 /* install signal handlers */
790 signal(SIGINT
, dhcp_signal_handler
); /* control-c */
791 signal(SIGTERM
, dhcp_signal_handler
); /* kill */
793 /* Log that we are about to start working */
794 log_info("Server starting service.");
797 * Receive packets and dispatch them...
798 * dispatch() will never return.
802 /* Let's return status code */
805 #endif /* !UNIT_TEST */
807 void postconf_initialization (int quiet
)
809 struct option_state
*options
= NULL
;
810 struct data_string db
;
811 struct option_cache
*oc
;
815 #if defined (NSUPDATE)
816 struct in_addr local4
, *local4_ptr
= NULL
;
817 struct in6_addr local6
, *local6_ptr
= NULL
;
820 /* Now try to get the lease file name. */
821 option_state_allocate(&options
, MDL
);
823 execute_statements_in_scope(NULL
, NULL
, NULL
, NULL
, NULL
,
824 options
, &global_scope
, root_group
,
826 memset(&db
, 0, sizeof db
);
827 oc
= lookup_option(&server_universe
, options
, SV_LEASE_FILE_NAME
);
829 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
830 &global_scope
, oc
, MDL
)) {
831 s
= dmalloc(db
.len
+ 1, MDL
);
833 log_fatal("no memory for lease db filename.");
834 memcpy(s
, db
.data
, db
.len
);
836 data_string_forget(&db
, MDL
);
840 oc
= lookup_option(&server_universe
, options
, SV_PID_FILE_NAME
);
842 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
843 &global_scope
, oc
, MDL
)) {
844 s
= dmalloc(db
.len
+ 1, MDL
);
846 log_fatal("no memory for pid filename.");
847 memcpy(s
, db
.data
, db
.len
);
849 data_string_forget(&db
, MDL
);
854 if (local_family
== AF_INET6
) {
856 * Override lease file name with dhcpv6 lease file name,
857 * if it was set; then, do the same with the pid file name
859 oc
= lookup_option(&server_universe
, options
,
860 SV_DHCPV6_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
,
874 SV_DHCPV6_PID_FILE_NAME
);
876 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
877 &global_scope
, oc
, MDL
)) {
878 s
= dmalloc(db
.len
+ 1, MDL
);
880 log_fatal("no memory for pid filename.");
881 memcpy(s
, db
.data
, db
.len
);
883 data_string_forget(&db
, MDL
);
890 oc
= lookup_option(&server_universe
, options
, SV_OMAPI_PORT
);
892 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
893 &global_scope
, oc
, MDL
)) {
895 omapi_port
= getUShort(db
.data
);
897 log_fatal("invalid omapi port data length");
898 data_string_forget(&db
, MDL
);
901 oc
= lookup_option(&server_universe
, options
, SV_OMAPI_KEY
);
903 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
904 &global_scope
, oc
, MDL
)) {
905 s
= dmalloc(db
.len
+ 1, MDL
);
907 log_fatal("no memory for OMAPI key filename.");
908 memcpy(s
, db
.data
, db
.len
);
910 data_string_forget(&db
, MDL
);
911 result
= omapi_auth_key_lookup_name(&omapi_key
, s
);
913 if (result
!= ISC_R_SUCCESS
)
914 log_fatal("OMAPI key %s: %s",
915 s
, isc_result_totext (result
));
918 oc
= lookup_option(&server_universe
, options
, SV_LOCAL_PORT
);
920 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
921 &global_scope
, oc
, MDL
)) {
923 local_port
= htons(getUShort (db
.data
));
925 log_fatal("invalid local port data length");
926 data_string_forget(&db
, MDL
);
929 oc
= lookup_option(&server_universe
, options
, SV_REMOTE_PORT
);
931 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
932 &global_scope
, oc
, MDL
)) {
934 remote_port
= htons(getUShort (db
.data
));
936 log_fatal("invalid remote port data length");
937 data_string_forget(&db
, MDL
);
940 oc
= lookup_option(&server_universe
, options
,
941 SV_LIMITED_BROADCAST_ADDRESS
);
943 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
944 &global_scope
, oc
, MDL
)) {
946 memcpy(&limited_broadcast
, db
.data
, 4);
948 log_fatal("invalid broadcast address data length");
949 data_string_forget(&db
, MDL
);
952 oc
= lookup_option(&server_universe
, options
, SV_LOCAL_ADDRESS
);
954 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
955 &global_scope
, oc
, MDL
)) {
957 memcpy(&local_address
, db
.data
, 4);
959 log_fatal("invalid local address data length");
960 data_string_forget(&db
, MDL
);
963 oc
= lookup_option(&server_universe
, options
, SV_DDNS_UPDATE_STYLE
);
965 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
966 &global_scope
, oc
, MDL
)) {
968 ddns_update_style
= db
.data
[0];
970 log_fatal("invalid dns update type");
971 data_string_forget(&db
, MDL
);
974 ddns_update_style
= DDNS_UPDATE_STYLE_NONE
;
976 #if defined (NSUPDATE)
977 /* We no longer support ad_hoc, tell the user */
978 if (ddns_update_style
== DDNS_UPDATE_STYLE_AD_HOC
) {
979 log_fatal("ddns-update-style ad_hoc no longer supported");
982 oc
= lookup_option(&server_universe
, options
, SV_DDNS_LOCAL_ADDRESS4
);
984 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
985 &global_scope
, oc
, MDL
)) {
987 memcpy(&local4
, db
.data
, 4);
988 local4_ptr
= &local4
;
990 data_string_forget(&db
, MDL
);
994 oc
= lookup_option(&server_universe
, options
, SV_DDNS_LOCAL_ADDRESS6
);
996 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
997 &global_scope
, oc
, MDL
)) {
999 memcpy(&local6
, db
.data
, 16);
1000 local6_ptr
= &local6
;
1002 data_string_forget(&db
, MDL
);
1006 if (dhcp_context_create(DHCP_CONTEXT_POST_DB
, local4_ptr
, local6_ptr
)
1008 log_fatal("Unable to complete ddns initialization");
1011 /* If we don't have support for updates compiled in tell the user */
1012 if (ddns_update_style
!= DDNS_UPDATE_STYLE_NONE
) {
1013 log_fatal("Support for ddns-update-style not compiled in");
1017 oc
= lookup_option(&server_universe
, options
, SV_LOG_FACILITY
);
1019 if (evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1020 &global_scope
, oc
, MDL
)) {
1023 openlog("dhcpd", LOG_NDELAY
, db
.data
[0]);
1024 /* Log the startup banner into the new
1027 /* Don't log to stderr twice. */
1031 message
, PACKAGE_VERSION
);
1032 log_info(copyright
);
1038 log_fatal("invalid log facility");
1039 data_string_forget(&db
, MDL
);
1043 oc
= lookup_option(&server_universe
, options
, SV_DELAYED_ACK
);
1045 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1046 &global_scope
, oc
, MDL
)) {
1048 max_outstanding_acks
= htons(getUShort(db
.data
));
1050 log_fatal("invalid max delayed ACK count ");
1052 data_string_forget(&db
, MDL
);
1055 oc
= lookup_option(&server_universe
, options
, SV_MAX_ACK_DELAY
);
1057 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1058 &global_scope
, oc
, MDL
)) {
1062 log_fatal("invalid max ack delay configuration");
1064 timeval
= getULong(db
.data
);
1065 max_ack_delay_secs
= timeval
/ 1000000;
1066 max_ack_delay_usecs
= timeval
% 1000000;
1068 data_string_forget(&db
, MDL
);
1071 oc
= lookup_option(&server_universe
, options
, SV_DONT_USE_FSYNC
);
1073 evaluate_boolean_option_cache(NULL
, NULL
, NULL
, NULL
, options
, NULL
,
1074 &global_scope
, oc
, MDL
)) {
1076 log_error("Not using fsync() to flush lease writes");
1079 /* Don't need the options anymore. */
1080 option_state_dereference(&options
, MDL
);
1083 void postdb_startup (void)
1085 /* Initialize the omapi listener state. */
1086 if (omapi_port
!= -1) {
1087 omapi_listener_start (0);
1090 #if defined (FAILOVER_PROTOCOL)
1091 /* Initialize the failover listener state. */
1092 dhcp_failover_startup ();
1096 * Begin our lease timeout background task.
1098 schedule_all_ipv6_lease_timeouts();
1101 /* Print usage message. */
1105 log_info("%s %s", message
, PACKAGE_VERSION
);
1106 log_info(copyright
);
1109 log_fatal("Usage: dhcpd [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
1111 " [-4|-6] [-cf config-file] [-lf lease-file]\n"
1113 " [-cf config-file] [-lf lease-file]\n"
1115 #if defined (PARANOIA)
1116 /* meld into the following string */
1117 " [-user user] [-group group] [-chroot dir]\n"
1118 #endif /* PARANOIA */
1119 #if defined (TRACING)
1120 " [-tf trace-output-file]\n"
1121 " [-play trace-input-file]\n"
1122 #endif /* TRACING */
1123 " [-pf pid-file] [--no-pid] [-s server]\n"
1128 void lease_pinged (from
, packet
, length
)
1135 /* Don't try to look up a pinged lease if we aren't trying to
1136 ping one - otherwise somebody could easily make us churn by
1137 just forging repeated ICMP EchoReply packets for us to look
1139 if (!outstanding_pings
)
1142 lp
= (struct lease
*)0;
1143 if (!find_lease_by_ip_addr (&lp
, from
, MDL
)) {
1144 log_debug ("unexpected ICMP Echo Reply from %s",
1150 #if defined (FAILOVER_PROTOCOL)
1152 !lp
-> pool
-> failover_peer
)
1154 log_debug ("ICMP Echo Reply for %s late or spurious.",
1159 if (lp
-> ends
> cur_time
) {
1160 log_debug ("ICMP Echo reply while lease %s valid.",
1164 /* At this point it looks like we pinged a lease and got a
1165 response, which shouldn't have happened. */
1166 data_string_forget (&lp
-> state
-> parameter_request_list
, MDL
);
1167 free_lease_state (lp
-> state
, MDL
);
1168 lp
-> state
= (struct lease_state
*)0;
1170 abandon_lease (lp
, "pinged before offer");
1171 cancel_timeout (lease_ping_timeout
, lp
);
1172 --outstanding_pings
;
1174 lease_dereference (&lp
, MDL
);
1177 void lease_ping_timeout (vlp
)
1180 struct lease
*lp
= vlp
;
1182 #if defined (DEBUG_MEMORY_LEAKAGE)
1183 unsigned long previous_outstanding
= dmalloc_outstanding
;
1186 --outstanding_pings
;
1189 #if defined (DEBUG_MEMORY_LEAKAGE)
1190 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
1192 dmalloc_outstanding
- previous_outstanding
,
1193 dmalloc_outstanding
, dmalloc_longterm
);
1195 #if defined (DEBUG_MEMORY_LEAKAGE)
1196 dmalloc_dump_outstanding ();
1200 int dhcpd_interface_setup_hook (struct interface_info
*ip
, struct iaddr
*ia
)
1202 struct subnet
*subnet
;
1203 struct shared_network
*share
;
1204 isc_result_t status
;
1206 /* Special case for fallback network - not sure why this is
1209 const char *fnn
= "fallback-net";
1210 status
= shared_network_allocate (&ip
-> shared_network
, MDL
);
1211 if (status
!= ISC_R_SUCCESS
)
1212 log_fatal ("No memory for shared subnet: %s",
1213 isc_result_totext (status
));
1214 ip
-> shared_network
-> name
= dmalloc (strlen (fnn
) + 1, MDL
);
1215 strcpy (ip
-> shared_network
-> name
, fnn
);
1219 /* If there's a registered subnet for this address,
1220 connect it together... */
1221 subnet
= (struct subnet
*)0;
1222 if (find_subnet (&subnet
, *ia
, MDL
)) {
1223 /* If this interface has multiple aliases on the same
1224 subnet, ignore all but the first we encounter. */
1225 if (!subnet
-> interface
) {
1226 interface_reference (&subnet
-> interface
, ip
, MDL
);
1227 subnet
-> interface_address
= *ia
;
1228 } else if (subnet
-> interface
!= ip
) {
1229 log_error ("Multiple interfaces match the %s: %s %s",
1231 subnet
-> interface
-> name
, ip
-> name
);
1233 share
= subnet
-> shared_network
;
1234 if (ip
-> shared_network
&&
1235 ip
-> shared_network
!= share
) {
1236 log_fatal ("Interface %s matches multiple shared %s",
1237 ip
-> name
, "networks");
1239 if (!ip
-> shared_network
)
1240 shared_network_reference
1241 (&ip
-> shared_network
, share
, MDL
);
1244 if (!share
-> interface
) {
1245 interface_reference (&share
-> interface
, ip
, MDL
);
1246 } else if (share
-> interface
!= ip
) {
1247 log_error ("Multiple interfaces match the %s: %s %s",
1248 "same shared network",
1249 share
-> interface
-> name
, ip
-> name
);
1251 subnet_dereference (&subnet
, MDL
);
1256 static TIME shutdown_time
;
1257 static int omapi_connection_count
;
1258 enum dhcp_shutdown_state shutdown_state
;
1260 isc_result_t
dhcp_io_shutdown (omapi_object_t
*obj
, void *foo
)
1262 /* Shut down all listeners. */
1263 if (shutdown_state
== shutdown_listeners
&&
1264 obj
-> type
== omapi_type_listener
&&
1266 obj
-> inner
-> type
== omapi_type_protocol_listener
) {
1267 omapi_listener_destroy (obj
, MDL
);
1268 return ISC_R_SUCCESS
;
1271 /* Shut down all existing omapi connections. */
1272 if (obj
-> type
== omapi_type_connection
&&
1274 obj
-> inner
-> type
== omapi_type_protocol
) {
1275 if (shutdown_state
== shutdown_drop_omapi_connections
) {
1276 omapi_disconnect (obj
, 1);
1278 omapi_connection_count
++;
1279 if (shutdown_state
== shutdown_omapi_connections
) {
1280 omapi_disconnect (obj
, 0);
1281 return ISC_R_SUCCESS
;
1285 /* Shutdown all DHCP interfaces. */
1286 if (obj
-> type
== dhcp_type_interface
&&
1287 shutdown_state
== shutdown_dhcp
) {
1288 dhcp_interface_remove (obj
, (omapi_object_t
*)0);
1289 return ISC_R_SUCCESS
;
1291 return ISC_R_SUCCESS
;
1294 static isc_result_t
dhcp_io_shutdown_countdown (void *vlp
)
1296 #if defined (FAILOVER_PROTOCOL)
1297 dhcp_failover_state_t
*state
;
1298 int failover_connection_count
= 0;
1303 if (shutdown_state
== shutdown_listeners
||
1304 shutdown_state
== shutdown_omapi_connections
||
1305 shutdown_state
== shutdown_drop_omapi_connections
||
1306 shutdown_state
== shutdown_dhcp
) {
1307 omapi_connection_count
= 0;
1308 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
1311 if ((shutdown_state
== shutdown_listeners
||
1312 shutdown_state
== shutdown_omapi_connections
||
1313 shutdown_state
== shutdown_drop_omapi_connections
) &&
1314 omapi_connection_count
== 0) {
1315 shutdown_state
= shutdown_dhcp
;
1316 shutdown_time
= cur_time
;
1318 } else if (shutdown_state
== shutdown_listeners
&&
1319 cur_time
- shutdown_time
> 4) {
1320 shutdown_state
= shutdown_omapi_connections
;
1321 shutdown_time
= cur_time
;
1322 } else if (shutdown_state
== shutdown_omapi_connections
&&
1323 cur_time
- shutdown_time
> 4) {
1324 shutdown_state
= shutdown_drop_omapi_connections
;
1325 shutdown_time
= cur_time
;
1326 } else if (shutdown_state
== shutdown_drop_omapi_connections
&&
1327 cur_time
- shutdown_time
> 4) {
1328 shutdown_state
= shutdown_dhcp
;
1329 shutdown_time
= cur_time
;
1331 } else if (shutdown_state
== shutdown_dhcp
&&
1332 cur_time
- shutdown_time
> 4) {
1333 shutdown_state
= shutdown_done
;
1334 shutdown_time
= cur_time
;
1337 #if defined (FAILOVER_PROTOCOL)
1338 /* Set all failover peers into the shutdown state. */
1339 if (shutdown_state
== shutdown_dhcp
) {
1340 for (state
= failover_states
; state
; state
= state
-> next
) {
1341 if (state
-> me
.state
== normal
) {
1342 dhcp_failover_set_state (state
, shut_down
);
1343 failover_connection_count
++;
1345 if (state
-> me
.state
== shut_down
&&
1346 state
-> partner
.state
!= partner_down
)
1347 failover_connection_count
++;
1351 if (shutdown_state
== shutdown_done
) {
1352 for (state
= failover_states
; state
; state
= state
-> next
) {
1353 if (state
-> me
.state
== shut_down
) {
1354 if (state
-> link_to_peer
)
1355 dhcp_failover_link_dereference (&state
-> link_to_peer
,
1357 dhcp_failover_set_state (state
, recover
);
1360 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1361 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1363 omapi_print_dmalloc_usage_by_caller ();
1368 if (shutdown_state
== shutdown_done
) {
1369 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1370 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1372 omapi_print_dmalloc_usage_by_caller ();
1377 if (shutdown_state
== shutdown_dhcp
&&
1378 #if defined(FAILOVER_PROTOCOL)
1379 !failover_connection_count
&&
1382 shutdown_state
= shutdown_done
;
1383 shutdown_time
= cur_time
;
1386 tv
.tv_sec
= cur_tv
.tv_sec
+ 1;
1387 tv
.tv_usec
= cur_tv
.tv_usec
;
1389 (void (*)(void *))dhcp_io_shutdown_countdown
, 0, 0, 0);
1390 return ISC_R_SUCCESS
;
1393 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
1394 control_object_state_t newstate
)
1398 if (newstate
!= server_shutdown
)
1399 return DHCP_R_INVALIDARG
;
1401 if (shutdown_signal
== SIGUSR1
)
1402 return ISC_R_SUCCESS
;
1403 shutdown_time
= cur_time
;
1404 shutdown_state
= shutdown_listeners
;
1405 /* Called by user. */
1406 if (shutdown_signal
== 0) {
1407 shutdown_signal
= SIGUSR1
;
1408 dhcp_io_shutdown_countdown (0);
1409 return ISC_R_SUCCESS
;
1411 /* Called on signal. */
1412 log_info("Received signal %d, initiating shutdown.", shutdown_signal
);
1413 shutdown_signal
= SIGUSR1
;
1416 * Prompt the shutdown event onto the timer queue
1417 * and return to the dispatch loop.
1419 tv
.tv_sec
= cur_tv
.tv_sec
;
1420 tv
.tv_usec
= cur_tv
.tv_usec
+ 1;
1422 (void (*)(void *))dhcp_io_shutdown_countdown
, 0, 0, 0);
1423 return ISC_R_SUCCESS
;