6 * Copyright (c) 2004-2008 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
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 static char copyright
[] =
36 "Copyright 2004-2008 Internet Systems Consortium.";
37 static char arr
[] = "All rights reserved.";
38 static char message
[] = "Internet Systems Consortium DHCP Server";
39 static char url
[] = "For info, please visit http://www.isc.org/sw/dhcp/";
42 #include <omapip/omapip_p.h>
46 #include <sys/types.h>
50 #if defined (PARANOIA)
51 # include <sys/types.h>
54 /* get around the ISC declaration of group */
55 # define group real_group
60 static void usage(void);
62 struct iaddr server_identifier
;
63 int server_identifier_matched
;
65 #if defined (NSUPDATE)
67 /* This stuff is always executed to figure the default values for certain
70 char std_nsupdate
[] = " \n\
71 option server.ddns-hostname = \n\
72 pick (option fqdn.hostname, option host-name); \n\
73 option server.ddns-domainname = config-option domain-name; \n\
74 option server.ddns-ttl = encode-int(lease-time / 2, 32); \n\
75 option server.ddns-rev-domainname = \"in-addr.arpa.\";";
77 /* This is the old-style name service updater that is executed
78 whenever a lease is committed. It does not follow the DHCP-DNS
81 char old_nsupdate
[] = " \n\
83 if (not static and \n\
84 ((config-option server.ddns-updates = null) or \n\
85 (config-option server.ddns-updates != 0))) { \n\
86 set new-ddns-fwd-name = \n\
87 concat (pick (config-option server.ddns-hostname, \n\
88 option host-name), \".\", \n\
89 pick (config-option server.ddns-domainname, \n\
90 config-option domain-name)); \n\
91 if (defined (ddns-fwd-name) and ddns-fwd-name != new-ddns-fwd-name) { \n\
92 switch (ns-update (delete (IN, A, ddns-fwd-name, leased-address))) { \n\
94 unset ddns-fwd-name; \n\
95 on expiry or release { \n\
100 if (not defined (ddns-fwd-name)) { \n\
101 set ddns-fwd-name = new-ddns-fwd-name; \n\
102 if defined (ddns-fwd-name) { \n\
103 switch (ns-update (not exists (IN, A, ddns-fwd-name, null), \n\
104 add (IN, A, ddns-fwd-name, leased-address, \n\
105 lease-time / 2))) { \n\
107 unset ddns-fwd-name; \n\
111 set ddns-rev-name = \n\
112 concat (binary-to-ascii (10, 8, \".\", \n\
114 leased-address)), \".\", \n\
115 pick (config-option server.ddns-rev-domainname, \n\
116 \"in-addr.arpa.\")); \n\
117 switch (ns-update (delete (IN, PTR, ddns-rev-name, null), \n\
118 add (IN, PTR, ddns-rev-name, ddns-fwd-name, \n\
119 lease-time / 2))) \n\
122 unset ddns-rev-name; \n\
123 on release or expiry { \n\
124 switch (ns-update (delete (IN, A, ddns-fwd-name, \n\
125 leased-address))) { \n\
127 unset ddns-fwd-name; \n\
130 on release or expiry; \n\
135 on release or expiry { \n\
136 switch (ns-update (delete (IN, PTR, ddns-rev-name, null))) {\n\
138 unset ddns-rev-name; \n\
141 switch (ns-update (delete (IN, A, ddns-fwd-name, \n\
142 leased-address))) { \n\
144 unset ddns-fwd-name; \n\
147 on release or expiry; \n\
153 unset new-ddns-fwd-name; \n\
157 int ddns_update_style
;
158 #endif /* NSUPDATE */
160 const char *path_dhcpd_conf
= _PATH_DHCPD_CONF
;
161 const char *path_dhcpd_db
= _PATH_DHCPD_DB
;
162 const char *path_dhcpd_pid
= _PATH_DHCPD_PID
;
164 int dhcp_max_agent_option_packet_length
= DHCP_MTU_MAX
;
166 static omapi_auth_key_t
*omapi_key
= (omapi_auth_key_t
*)0;
169 #if defined (TRACING)
170 trace_type_t
*trace_srandom
;
173 static isc_result_t
verify_addr (omapi_object_t
*l
, omapi_addr_t
*addr
) {
174 return ISC_R_SUCCESS
;
177 static isc_result_t
verify_auth (omapi_object_t
*p
, omapi_auth_key_t
*a
) {
179 return ISC_R_INVALIDKEY
;
180 return ISC_R_SUCCESS
;
183 static void omapi_listener_start (void *foo
)
185 omapi_object_t
*listener
;
189 listener
= (omapi_object_t
*)0;
190 result
= omapi_generic_new (&listener
, MDL
);
191 if (result
!= ISC_R_SUCCESS
)
192 log_fatal ("Can't allocate new generic object: %s",
193 isc_result_totext (result
));
194 result
= omapi_protocol_listen (listener
,
195 (unsigned)omapi_port
, 1);
196 if (result
== ISC_R_SUCCESS
&& omapi_key
)
197 result
= omapi_protocol_configure_security
198 (listener
, verify_addr
, verify_auth
);
199 if (result
!= ISC_R_SUCCESS
) {
200 log_error ("Can't start OMAPI protocol: %s",
201 isc_result_totext (result
));
202 tv
.tv_sec
= cur_time
+ 5;
204 add_timeout (&tv
, omapi_listener_start
, 0, 0, 0);
206 omapi_object_dereference (&listener
, MDL
);
209 #if defined (PARANOIA)
210 /* to be used in one of two possible scenarios */
211 static void setup_chroot (char *chroot_dir
) {
213 log_fatal ("you must be root to use chroot");
215 if (chroot(chroot_dir
)) {
216 log_fatal ("chroot(\"%s\"): %m", chroot_dir
);
219 /* probably permission denied */
220 log_fatal ("chdir(\"/\"): %m");
223 #endif /* PARANOIA */
227 main(int argc
, char **argv
) {
240 char *server
= (char *)0;
243 struct interface_info
*ip
;
246 int no_dhcpd_conf
= 0;
248 int no_dhcpd_pid
= 0;
250 int local_family_set
= 0;
252 #if defined (TRACING)
253 char *traceinfile
= (char *)0;
254 char *traceoutfile
= (char *)0;
257 #if defined (PARANOIA)
260 char *set_chroot
= 0;
264 #endif /* PARANOIA */
266 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
267 2 (stderr) are open. To do this, we assume that when we
268 open a file the lowest available file descriptor is used. */
269 fd
= open("/dev/null", O_RDWR
);
271 fd
= open("/dev/null", O_RDWR
);
273 fd
= open("/dev/null", O_RDWR
);
275 log_perror
= 0; /* No sense logging to /dev/null. */
279 /* Set up the client classification system. */
280 classification_setup ();
282 /* Initialize the omapi system. */
283 result
= omapi_init ();
284 if (result
!= ISC_R_SUCCESS
)
285 log_fatal ("Can't initialize OMAPI: %s",
286 isc_result_totext (result
));
288 /* Set up the OMAPI wrappers for common objects. */
289 dhcp_db_objects_setup ();
290 /* Set up the OMAPI wrappers for various server database internal
292 dhcp_common_objects_setup ();
294 /* Initially, log errors to stderr as well as to syslogd. */
295 openlog ("dhcpd", LOG_NDELAY
, DHCPD_LOG_FACILITY
);
297 for (i
= 1; i
< argc
; i
++) {
298 if (!strcmp (argv
[i
], "-p")) {
301 for (s
= argv
[i
]; *s
; s
++)
302 if (!isdigit ((unsigned char)*s
))
303 log_fatal ("%s: not a valid UDP port",
305 status
= atoi (argv
[i
]);
306 if (status
< 1 || status
> 65535)
307 log_fatal ("%s: not a valid UDP port",
309 local_port
= htons (status
);
310 log_debug ("binding to user-specified port %d",
312 } else if (!strcmp (argv
[i
], "-f")) {
316 } else if (!strcmp (argv
[i
], "-d")) {
321 } else if (!strcmp (argv
[i
], "-s")) {
325 #if defined (PARANOIA)
326 } else if (!strcmp (argv
[i
], "-user")) {
330 } else if (!strcmp (argv
[i
], "-group")) {
333 set_group
= argv
[i
];
334 } else if (!strcmp (argv
[i
], "-chroot")) {
337 set_chroot
= argv
[i
];
338 #endif /* PARANOIA */
339 } else if (!strcmp (argv
[i
], "-cf")) {
342 path_dhcpd_conf
= argv
[i
];
344 } else if (!strcmp (argv
[i
], "-lf")) {
347 path_dhcpd_db
= argv
[i
];
349 } else if (!strcmp (argv
[i
], "-pf")) {
352 path_dhcpd_pid
= argv
[i
];
354 } else if (!strcmp (argv
[i
], "-t")) {
355 /* test configurations only */
361 } else if (!strcmp (argv
[i
], "-T")) {
362 /* test configurations and lease file only */
369 } else if (!strcmp (argv
[i
], "-q")) {
371 quiet_interface_discovery
= 1;
373 } else if (!strcmp(argv
[i
], "-4")) {
374 if (local_family_set
&& (local_family
!= AF_INET
)) {
375 log_fatal("Server cannot run in both IPv4 and "
376 "IPv6 mode at the same time.");
378 local_family
= AF_INET
;
379 local_family_set
= 1;
380 } else if (!strcmp(argv
[i
], "-6")) {
381 if (local_family_set
&& (local_family
!= AF_INET6
)) {
382 log_fatal("Server cannot run in both IPv4 and "
383 "IPv6 mode at the same time.");
385 local_family
= AF_INET6
;
386 local_family_set
= 1;
388 } else if (!strcmp (argv
[i
], "--version")) {
389 log_info("isc-dhcpd-%s", PACKAGE_VERSION
);
391 #if defined (TRACING)
392 } else if (!strcmp (argv
[i
], "-tf")) {
395 traceoutfile
= argv
[i
];
396 } else if (!strcmp (argv
[i
], "-play")) {
399 traceinfile
= argv
[i
];
400 trace_replay_init ();
402 } else if (argv
[i
][0] == '-') {
405 struct interface_info
*tmp
=
406 (struct interface_info
*)0;
407 result
= interface_allocate (&tmp
, MDL
);
408 if (result
!= ISC_R_SUCCESS
)
409 log_fatal ("Insufficient memory to %s %s: %s",
410 "record interface", argv
[i
],
411 isc_result_totext (result
));
412 strcpy (tmp
-> name
, argv
[i
]);
414 interface_reference (&tmp
-> next
,
416 interface_dereference (&interfaces
, MDL
);
418 interface_reference (&interfaces
, tmp
, MDL
);
419 tmp
-> flags
= INTERFACE_REQUESTED
;
423 if (!no_dhcpd_conf
&& (s
= getenv ("PATH_DHCPD_CONF"))) {
428 if (local_family
== AF_INET6
) {
429 /* DHCPv6: override DHCPv4 lease and pid filenames */
431 if ((s
= getenv ("PATH_DHCPD6_DB")))
434 path_dhcpd_db
= _PATH_DHCPD6_DB
;
437 if ((s
= getenv ("PATH_DHCPD6_PID")))
440 path_dhcpd_pid
= _PATH_DHCPD6_PID
;
445 if (!no_dhcpd_db
&& (s
= getenv ("PATH_DHCPD_DB"))) {
448 if (!no_dhcpd_pid
&& (s
= getenv ("PATH_DHCPD_PID"))) {
455 * convert relative path names to absolute, for files that need
456 * to be reopened after chdir() has been called
458 if (path_dhcpd_db
[0] != '/') {
459 char *path
= dmalloc(PATH_MAX
, MDL
);
461 log_fatal("No memory for filename\n");
462 path_dhcpd_db
= realpath(path_dhcpd_db
, path
);
463 if (path_dhcpd_db
== NULL
)
464 log_fatal("%s: %s", path
, strerror(errno
));
468 log_info("%s %s", message
, PACKAGE_VERSION
);
469 log_info (copyright
);
477 #if defined (TRACING)
478 trace_init (set_time
, MDL
);
480 result
= trace_begin (traceoutfile
, MDL
);
481 if (result
!= ISC_R_SUCCESS
)
482 log_fatal ("Unable to begin trace: %s",
483 isc_result_totext (result
));
485 interface_trace_setup ();
486 parse_trace_setup ();
487 trace_srandom
= trace_type_register ("random-seed", (void *)0,
489 trace_seed_stop
, MDL
);
492 #if defined (PARANOIA)
493 /* get user and group info if those options were given */
495 struct passwd
*tmp_pwd
;
498 log_fatal ("you must be root to set user");
500 if (!(tmp_pwd
= getpwnam(set_user
)))
501 log_fatal ("no such user: %s", set_user
);
503 set_uid
= tmp_pwd
->pw_uid
;
505 /* use the user's group as the default gid */
507 set_gid
= tmp_pwd
->pw_gid
;
511 /* get around the ISC declaration of group */
512 #define group real_group
513 struct group
*tmp_grp
;
516 log_fatal ("you must be root to set group");
518 if (!(tmp_grp
= getgrnam(set_group
)))
519 log_fatal ("no such group: %s", set_group
);
521 set_gid
= tmp_grp
->gr_gid
;
525 # if defined (EARLY_CHROOT)
526 if (set_chroot
) setup_chroot (set_chroot
);
527 # endif /* EARLY_CHROOT */
528 #endif /* PARANOIA */
530 /* Default to the DHCP/BOOTP port. */
533 if ((s
= getenv ("DHCPD_PORT"))) {
534 local_port
= htons (atoi (s
));
535 log_debug ("binding to environment-specified port %d",
538 if (local_family
== AF_INET
) {
539 ent
= getservbyname("dhcp", "udp");
541 local_port
= htons(67);
543 local_port
= ent
->s_port
;
546 /* INSIST(local_family == AF_INET6); */
547 ent
= getservbyname("dhcpv6-server", "udp");
549 local_port
= htons(547);
551 local_port
= ent
->s_port
;
554 #ifndef __CYGWIN32__ /* XXX */
560 if (local_family
== AF_INET
) {
561 remote_port
= htons(ntohs(local_port
) + 1);
563 /* INSIST(local_family == AF_INET6); */
564 ent
= getservbyname("dhcpv6-client", "udp");
566 remote_port
= htons(546);
568 remote_port
= ent
->s_port
;
573 if (local_family
!= AF_INET
) {
574 log_fatal("You can only specify address to send "
575 "replies to when running an IPv4 server.");
577 if (!inet_aton (server
, &limited_broadcast
)) {
579 he
= gethostbyname (server
);
581 memcpy (&limited_broadcast
,
582 he
-> h_addr_list
[0],
583 sizeof limited_broadcast
);
585 limited_broadcast
.s_addr
= INADDR_BROADCAST
;
588 limited_broadcast
.s_addr
= INADDR_BROADCAST
;
591 /* Get the current time... */
592 gettimeofday(&cur_tv
, NULL
);
594 /* Set up the initial dhcp option universe. */
595 initialize_common_option_spaces ();
596 initialize_server_option_spaces ();
598 /* Add the ddns update style enumeration prior to parsing. */
599 add_enumeration (&ddns_styles
);
600 add_enumeration (&syslog_enum
);
602 if (!group_allocate (&root_group
, MDL
))
603 log_fatal ("Can't allocate root group!");
604 root_group
-> authoritative
= 0;
606 /* Set up various hooks. */
607 dhcp_interface_setup_hook
= dhcpd_interface_setup_hook
;
608 bootp_packet_handler
= do_packet
;
610 dhcpv6_packet_handler
= do_packet6
;
613 #if defined (NSUPDATE)
614 /* Set up the standard name service updater routine. */
615 parse
= (struct parse
*)0;
616 status
= new_parse (&parse
, -1,
617 std_nsupdate
, (sizeof std_nsupdate
) - 1,
618 "standard name service update routine", 0);
619 if (status
!= ISC_R_SUCCESS
)
620 log_fatal ("can't begin parsing name service updater!");
623 if (!(parse_executable_statements
624 (&root_group
-> statements
, parse
, &lose
, context_any
))) {
626 log_fatal ("can't parse standard name service updater!");
631 /* Initialize icmp support... */
632 if (!cftest
&& !lftest
)
633 icmp_startup (1, lease_pinged
);
635 #if defined (TRACING)
638 log_error ("%s", "");
639 log_error ("** You must specify a lease file with -lf.");
640 log_error (" Dhcpd will not overwrite your default");
641 log_fatal (" lease file when playing back a trace. **");
643 trace_file_replay (traceinfile
);
645 #if defined (DEBUG_MEMORY_LEAKAGE) && \
646 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
648 omapi_print_dmalloc_usage_by_caller ();
656 /* set up DHCPv6 hashes */
657 if (!ia_na_new_hash(&ia_na_active
, DEFAULT_HASH_SIZE
, MDL
)) {
658 log_fatal("Out of memory creating hash for active IA_NA.");
660 if (!ia_na_new_hash(&ia_ta_active
, DEFAULT_HASH_SIZE
, MDL
)) {
661 log_fatal("Out of memory creating hash for active IA_TA.");
663 if (!ia_pd_new_hash(&ia_pd_active
, DEFAULT_HASH_SIZE
, MDL
)) {
664 log_fatal("Out of memory creating hash for active IA_PD.");
668 /* Read the dhcpd.conf file... */
669 if (readconf () != ISC_R_SUCCESS
)
670 log_fatal ("Configuration file errors encountered -- exiting");
672 postconf_initialization (quiet
);
674 #if defined (PARANOIA) && !defined (EARLY_CHROOT)
675 if (set_chroot
) setup_chroot (set_chroot
);
676 #endif /* PARANOIA && !EARLY_CHROOT */
678 /* test option should cause an early exit */
679 if (cftest
&& !lftest
)
682 group_write_hook
= group_writer
;
684 /* Start up the database... */
690 /* Discover all the network interfaces and initialize them. */
691 discover_interfaces(DISCOVER_SERVER
);
695 * Remove addresses from our pools that we should not issue
698 * We currently have no support for this in IPv4. It is not
699 * as important in IPv4, as making pools with ranges that
700 * leave out interfaces and hosts is fairly straightforward
701 * using range notation, but not so handy with CIDR notation.
703 if (local_family
== AF_INET6
) {
704 mark_hosts_unavailable();
705 mark_phosts_unavailable();
706 mark_interfaces_unavailable();
711 /* Make up a seed for the random number generator from current
712 time plus the sum of the last four bytes of each
713 interface's hardware address interpreted as an integer.
714 Not much entropy, but we're booting, so we're not likely to
715 find anything better. */
717 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
720 &ip
-> hw_address
.hbuf
[ip
-> hw_address
.hlen
-
721 sizeof seed
], sizeof seed
);
724 srandom (seed
+ cur_time
);
725 #if defined (TRACING)
726 trace_seed_stash (trace_srandom
, seed
+ cur_time
);
732 * Set server DHCPv6 identifier.
733 * See dhcpv6.c for discussion of setting DUID.
735 if (set_server_duid_from_option() == ISC_R_SUCCESS
) {
738 if (!server_duid_isset()) {
739 if (generate_new_server_duid() != ISC_R_SUCCESS
) {
740 log_fatal("Unable to set server identifier.");
749 /* First part of becoming a daemon... */
750 if ((pid
= fork ()) < 0)
751 log_fatal ("Can't fork daemon: %m");
756 #if defined (PARANOIA)
757 /* change uid to the specified one */
760 if (setgroups (0, (void *)0))
761 log_fatal ("setgroups: %m");
762 if (setgid (set_gid
))
763 log_fatal ("setgid(%d): %m", (int) set_gid
);
767 if (setuid (set_uid
))
768 log_fatal ("setuid(%d): %m", (int) set_uid
);
770 #endif /* PARANOIA */
772 /* Read previous pid file. */
773 if ((i
= open (path_dhcpd_pid
, O_RDONLY
)) >= 0) {
774 status
= read(i
, pbuf
, (sizeof pbuf
) - 1);
781 * If there was a previous server process and it's
782 * is still running, abort
784 if (!pid
|| (pid
!= getpid() && kill(pid
, 0) == 0))
785 log_fatal("There's already a "
786 "DHCP server running.");
790 /* Write new pid file. */
791 if ((i
= open(path_dhcpd_pid
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644)) >= 0) {
792 sprintf(pbuf
, "%d\n", (int) getpid());
793 write(i
, pbuf
, strlen(pbuf
));
796 log_error("Can't create PID file %s: %m.", path_dhcpd_pid
);
800 /* If we were requested to log to stdout on the command line,
801 keep doing so; otherwise, stop. */
802 if (log_perror
== -1)
808 /* Become session leader and get pid... */
811 /* Close standard I/O descriptors. */
816 /* Reopen them on /dev/null. */
817 open("/dev/null", O_RDWR
);
818 open("/dev/null", O_RDWR
);
819 open("/dev/null", O_RDWR
);
820 log_perror
= 0; /* No sense logging to /dev/null. */
826 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
827 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
828 dmalloc_cutoff_generation
= dmalloc_generation
;
829 dmalloc_longterm
= dmalloc_outstanding
;
830 dmalloc_outstanding
= 0;
833 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
837 omapi_set_int_value ((omapi_object_t
*)dhcp_control_object
,
838 (omapi_object_t
*)0, "state", server_running
);
840 register_eventhandler(&rw_queue_empty
,commit_leases_readerdry
);
842 /* Receive packets and dispatch them... */
848 #endif /* !UNIT_TEST */
850 void postconf_initialization (int quiet
)
852 struct option_state
*options
= (struct option_state
*)0;
853 struct data_string db
;
854 struct option_cache
*oc
;
860 /* Now try to get the lease file name. */
861 option_state_allocate (&options
, MDL
);
863 execute_statements_in_scope ((struct binding_value
**)0,
866 (struct client_state
*)0,
867 (struct option_state
*)0,
868 options
, &global_scope
,
871 memset (&db
, 0, sizeof db
);
872 oc
= lookup_option (&server_universe
, options
, SV_LEASE_FILE_NAME
);
874 evaluate_option_cache (&db
, (struct packet
*)0,
875 (struct lease
*)0, (struct client_state
*)0,
876 options
, (struct option_state
*)0,
877 &global_scope
, oc
, MDL
)) {
878 s
= dmalloc (db
.len
+ 1, MDL
);
880 log_fatal ("no memory for lease db filename.");
881 memcpy (s
, db
.data
, db
.len
);
883 data_string_forget (&db
, MDL
);
887 oc
= lookup_option (&server_universe
, options
, SV_PID_FILE_NAME
);
889 evaluate_option_cache (&db
, (struct packet
*)0,
890 (struct lease
*)0, (struct client_state
*)0,
891 options
, (struct option_state
*)0,
892 &global_scope
, oc
, MDL
)) {
893 s
= dmalloc (db
.len
+ 1, MDL
);
895 log_fatal ("no memory for lease db filename.");
896 memcpy (s
, db
.data
, db
.len
);
898 data_string_forget (&db
, MDL
);
903 if (local_family
== AF_INET6
) {
905 * Override lease file name with dhcpv6 lease file name,
906 * if it was set; then, do the same with the pid file name
908 oc
= lookup_option(&server_universe
, options
,
909 SV_DHCPV6_LEASE_FILE_NAME
);
911 evaluate_option_cache(&db
, NULL
, NULL
, NULL
,
912 options
, NULL
, &global_scope
,
914 s
= dmalloc (db
.len
+ 1, MDL
);
916 log_fatal ("no memory for lease db filename.");
917 memcpy (s
, db
.data
, db
.len
);
919 data_string_forget (&db
, MDL
);
923 oc
= lookup_option(&server_universe
, options
,
924 SV_DHCPV6_PID_FILE_NAME
);
926 evaluate_option_cache(&db
, NULL
, NULL
, NULL
,
927 options
, NULL
, &global_scope
,
929 s
= dmalloc (db
.len
+ 1, MDL
);
931 log_fatal ("no memory for lease db filename.");
932 memcpy (s
, db
.data
, db
.len
);
934 data_string_forget (&db
, MDL
);
941 oc
= lookup_option (&server_universe
, options
, SV_OMAPI_PORT
);
943 evaluate_option_cache (&db
, (struct packet
*)0,
944 (struct lease
*)0, (struct client_state
*)0,
945 options
, (struct option_state
*)0,
946 &global_scope
, oc
, MDL
)) {
948 omapi_port
= getUShort (db
.data
);
950 log_fatal ("invalid omapi port data length");
951 data_string_forget (&db
, MDL
);
954 oc
= lookup_option (&server_universe
, options
, SV_OMAPI_KEY
);
956 evaluate_option_cache (&db
, (struct packet
*)0,
957 (struct lease
*)0, (struct client_state
*)0,
959 (struct option_state
*)0,
960 &global_scope
, oc
, MDL
)) {
961 s
= dmalloc (db
.len
+ 1, MDL
);
963 log_fatal ("no memory for OMAPI key filename.");
964 memcpy (s
, db
.data
, db
.len
);
966 data_string_forget (&db
, MDL
);
967 result
= omapi_auth_key_lookup_name (&omapi_key
, s
);
969 if (result
!= ISC_R_SUCCESS
)
970 log_fatal ("OMAPI key %s: %s",
971 s
, isc_result_totext (result
));
974 oc
= lookup_option (&server_universe
, options
, SV_LOCAL_PORT
);
976 evaluate_option_cache (&db
, (struct packet
*)0,
977 (struct lease
*)0, (struct client_state
*)0,
979 (struct option_state
*)0,
980 &global_scope
, oc
, MDL
)) {
982 local_port
= htons (getUShort (db
.data
));
984 log_fatal ("invalid local port data length");
985 data_string_forget (&db
, MDL
);
988 oc
= lookup_option (&server_universe
, options
, SV_REMOTE_PORT
);
990 evaluate_option_cache (&db
, (struct packet
*)0,
991 (struct lease
*)0, (struct client_state
*)0,
992 options
, (struct option_state
*)0,
993 &global_scope
, oc
, MDL
)) {
995 remote_port
= htons (getUShort (db
.data
));
997 log_fatal ("invalid remote port data length");
998 data_string_forget (&db
, MDL
);
1001 oc
= lookup_option (&server_universe
, options
,
1002 SV_LIMITED_BROADCAST_ADDRESS
);
1004 evaluate_option_cache (&db
, (struct packet
*)0,
1005 (struct lease
*)0, (struct client_state
*)0,
1006 options
, (struct option_state
*)0,
1007 &global_scope
, oc
, MDL
)) {
1009 memcpy (&limited_broadcast
, db
.data
, 4);
1011 log_fatal ("invalid remote port data length");
1012 data_string_forget (&db
, MDL
);
1015 oc
= lookup_option (&server_universe
, options
,
1018 evaluate_option_cache (&db
, (struct packet
*)0,
1019 (struct lease
*)0, (struct client_state
*)0,
1020 options
, (struct option_state
*)0,
1021 &global_scope
, oc
, MDL
)) {
1023 memcpy (&local_address
, db
.data
, 4);
1025 log_fatal ("invalid remote port data length");
1026 data_string_forget (&db
, MDL
);
1029 oc
= lookup_option (&server_universe
, options
, SV_DDNS_UPDATE_STYLE
);
1031 if (evaluate_option_cache (&db
, (struct packet
*)0,
1033 (struct client_state
*)0,
1035 (struct option_state
*)0,
1036 &global_scope
, oc
, MDL
)) {
1038 ddns_update_style
= db
.data
[0];
1040 log_fatal ("invalid dns update type");
1041 data_string_forget (&db
, MDL
);
1044 ddns_update_style
= DDNS_UPDATE_STYLE_NONE
;
1047 oc
= lookup_option (&server_universe
, options
, SV_LOG_FACILITY
);
1049 if (evaluate_option_cache (&db
, (struct packet
*)0,
1051 (struct client_state
*)0,
1053 (struct option_state
*)0,
1054 &global_scope
, oc
, MDL
)) {
1057 openlog ("dhcpd", LOG_NDELAY
, db
.data
[0]);
1058 /* Log the startup banner into the new
1061 /* Don't log to stderr twice. */
1065 message
, PACKAGE_VERSION
);
1066 log_info (copyright
);
1072 log_fatal ("invalid log facility");
1073 data_string_forget (&db
, MDL
);
1077 oc
= lookup_option(&server_universe
, options
, SV_DELAYED_ACK
);
1079 evaluate_option_cache(&db
, NULL
, NULL
, NULL
, options
, NULL
,
1080 &global_scope
, oc
, MDL
)) {
1082 max_outstanding_acks
= htons(getUShort(db
.data
));
1084 log_fatal("invalid max delayed ACK count ");
1086 data_string_forget(&db
, MDL
);
1089 /* Don't need the options anymore. */
1090 option_state_dereference (&options
, MDL
);
1092 #if defined (NSUPDATE)
1093 /* If old-style ddns updates have been requested, parse the
1094 old-style ddns updater. */
1095 if (ddns_update_style
== 1) {
1096 struct executable_statement
**e
, *s
;
1098 if (root_group
-> statements
) {
1099 s
= (struct executable_statement
*)0;
1100 if (!executable_statement_allocate (&s
, MDL
))
1101 log_fatal ("no memory for ddns updater");
1102 executable_statement_reference
1103 (&s
-> next
, root_group
-> statements
, MDL
);
1104 executable_statement_dereference
1105 (&root_group
-> statements
, MDL
);
1106 executable_statement_reference
1107 (&root_group
-> statements
, s
, MDL
);
1108 s
-> op
= statements_statement
;
1109 e
= &s
-> data
.statements
;
1110 executable_statement_dereference (&s
, MDL
);
1112 e
= &root_group
-> statements
;
1115 /* Set up the standard name service updater routine. */
1116 parse
= (struct parse
*)0;
1117 result
= new_parse (&parse
, -1,
1118 old_nsupdate
, (sizeof old_nsupdate
) - 1,
1119 "old name service update routine", 0);
1120 if (result
!= ISC_R_SUCCESS
)
1121 log_fatal ("can't begin parsing old ddns updater!");
1124 if (!(parse_executable_statements (e
, parse
,
1125 &tmp
, context_any
))) {
1127 log_fatal ("can't parse standard ddns updater!");
1134 void postdb_startup (void)
1136 /* Initialize the omapi listener state. */
1137 if (omapi_port
!= -1) {
1138 omapi_listener_start (0);
1141 #if defined (FAILOVER_PROTOCOL)
1142 /* Initialize the failover listener state. */
1143 dhcp_failover_startup ();
1147 * Begin our lease timeout background task.
1149 schedule_all_ipv6_lease_timeouts();
1152 /* Print usage message. */
1156 log_info("%s %s", message
, PACKAGE_VERSION
);
1157 log_info(copyright
);
1160 log_fatal("Usage: dhcpd [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
1162 " [-4|-6] [-cf config-file] [-lf lease-file]\n"
1164 " [-cf config-file] [-lf lease-file]\n"
1166 #if defined (PARANOIA)
1167 /* meld into the following string */
1168 " [-user user] [-group group] [-chroot dir]\n"
1169 #endif /* PARANOIA */
1170 #if defined (TRACING)
1171 " [-tf trace-output-file]\n"
1172 " [-play trace-input-file]\n"
1173 #endif /* TRACING */
1174 " [-pf pid-file] [-s server] [if0 [...ifN]]");
1177 void lease_pinged (from
, packet
, length
)
1184 /* Don't try to look up a pinged lease if we aren't trying to
1185 ping one - otherwise somebody could easily make us churn by
1186 just forging repeated ICMP EchoReply packets for us to look
1188 if (!outstanding_pings
)
1191 lp
= (struct lease
*)0;
1192 if (!find_lease_by_ip_addr (&lp
, from
, MDL
)) {
1193 log_debug ("unexpected ICMP Echo Reply from %s",
1199 #if defined (FAILOVER_PROTOCOL)
1201 !lp
-> pool
-> failover_peer
)
1203 log_debug ("ICMP Echo Reply for %s late or spurious.",
1208 if (lp
-> ends
> cur_time
) {
1209 log_debug ("ICMP Echo reply while lease %s valid.",
1213 /* At this point it looks like we pinged a lease and got a
1214 response, which shouldn't have happened. */
1215 data_string_forget (&lp
-> state
-> parameter_request_list
, MDL
);
1216 free_lease_state (lp
-> state
, MDL
);
1217 lp
-> state
= (struct lease_state
*)0;
1219 abandon_lease (lp
, "pinged before offer");
1220 cancel_timeout (lease_ping_timeout
, lp
);
1221 --outstanding_pings
;
1223 lease_dereference (&lp
, MDL
);
1226 void lease_ping_timeout (vlp
)
1229 struct lease
*lp
= vlp
;
1231 #if defined (DEBUG_MEMORY_LEAKAGE)
1232 unsigned long previous_outstanding
= dmalloc_outstanding
;
1235 --outstanding_pings
;
1238 #if defined (DEBUG_MEMORY_LEAKAGE)
1239 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
1241 dmalloc_outstanding
- previous_outstanding
,
1242 dmalloc_outstanding
, dmalloc_longterm
);
1244 #if defined (DEBUG_MEMORY_LEAKAGE)
1245 dmalloc_dump_outstanding ();
1249 int dhcpd_interface_setup_hook (struct interface_info
*ip
, struct iaddr
*ia
)
1251 struct subnet
*subnet
;
1252 struct shared_network
*share
;
1253 isc_result_t status
;
1255 /* Special case for fallback network - not sure why this is
1258 const char *fnn
= "fallback-net";
1259 status
= shared_network_allocate (&ip
-> shared_network
, MDL
);
1260 if (status
!= ISC_R_SUCCESS
)
1261 log_fatal ("No memory for shared subnet: %s",
1262 isc_result_totext (status
));
1263 ip
-> shared_network
-> name
= dmalloc (strlen (fnn
) + 1, MDL
);
1264 strcpy (ip
-> shared_network
-> name
, fnn
);
1268 /* If there's a registered subnet for this address,
1269 connect it together... */
1270 subnet
= (struct subnet
*)0;
1271 if (find_subnet (&subnet
, *ia
, MDL
)) {
1272 /* If this interface has multiple aliases on the same
1273 subnet, ignore all but the first we encounter. */
1274 if (!subnet
-> interface
) {
1275 interface_reference (&subnet
-> interface
, ip
, MDL
);
1276 subnet
-> interface_address
= *ia
;
1277 } else if (subnet
-> interface
!= ip
) {
1278 log_error ("Multiple interfaces match the %s: %s %s",
1280 subnet
-> interface
-> name
, ip
-> name
);
1282 share
= subnet
-> shared_network
;
1283 if (ip
-> shared_network
&&
1284 ip
-> shared_network
!= share
) {
1285 log_fatal ("Interface %s matches multiple shared %s",
1286 ip
-> name
, "networks");
1288 if (!ip
-> shared_network
)
1289 shared_network_reference
1290 (&ip
-> shared_network
, share
, MDL
);
1293 if (!share
-> interface
) {
1294 interface_reference (&share
-> interface
, ip
, MDL
);
1295 } else if (share
-> interface
!= ip
) {
1296 log_error ("Multiple interfaces match the %s: %s %s",
1297 "same shared network",
1298 share
-> interface
-> name
, ip
-> name
);
1300 subnet_dereference (&subnet
, MDL
);
1305 static TIME shutdown_time
;
1306 static int omapi_connection_count
;
1307 enum dhcp_shutdown_state shutdown_state
;
1309 isc_result_t
dhcp_io_shutdown (omapi_object_t
*obj
, void *foo
)
1311 /* Shut down all listeners. */
1312 if (shutdown_state
== shutdown_listeners
&&
1313 obj
-> type
== omapi_type_listener
&&
1315 obj
-> inner
-> type
== omapi_type_protocol_listener
) {
1316 omapi_listener_destroy (obj
, MDL
);
1317 return ISC_R_SUCCESS
;
1320 /* Shut down all existing omapi connections. */
1321 if (obj
-> type
== omapi_type_connection
&&
1323 obj
-> inner
-> type
== omapi_type_protocol
) {
1324 if (shutdown_state
== shutdown_drop_omapi_connections
) {
1325 omapi_disconnect (obj
, 1);
1327 omapi_connection_count
++;
1328 if (shutdown_state
== shutdown_omapi_connections
) {
1329 omapi_disconnect (obj
, 0);
1330 return ISC_R_SUCCESS
;
1334 /* Shutdown all DHCP interfaces. */
1335 if (obj
-> type
== dhcp_type_interface
&&
1336 shutdown_state
== shutdown_dhcp
) {
1337 dhcp_interface_remove (obj
, (omapi_object_t
*)0);
1338 return ISC_R_SUCCESS
;
1340 return ISC_R_SUCCESS
;
1343 static isc_result_t
dhcp_io_shutdown_countdown (void *vlp
)
1345 #if defined (FAILOVER_PROTOCOL)
1346 dhcp_failover_state_t
*state
;
1347 int failover_connection_count
= 0;
1352 if (shutdown_state
== shutdown_listeners
||
1353 shutdown_state
== shutdown_omapi_connections
||
1354 shutdown_state
== shutdown_drop_omapi_connections
||
1355 shutdown_state
== shutdown_dhcp
) {
1356 omapi_connection_count
= 0;
1357 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
1360 if ((shutdown_state
== shutdown_listeners
||
1361 shutdown_state
== shutdown_omapi_connections
||
1362 shutdown_state
== shutdown_drop_omapi_connections
) &&
1363 omapi_connection_count
== 0) {
1364 shutdown_state
= shutdown_dhcp
;
1365 shutdown_time
= cur_time
;
1367 } else if (shutdown_state
== shutdown_listeners
&&
1368 cur_time
- shutdown_time
> 4) {
1369 shutdown_state
= shutdown_omapi_connections
;
1370 shutdown_time
= cur_time
;
1371 } else if (shutdown_state
== shutdown_omapi_connections
&&
1372 cur_time
- shutdown_time
> 4) {
1373 shutdown_state
= shutdown_drop_omapi_connections
;
1374 shutdown_time
= cur_time
;
1375 } else if (shutdown_state
== shutdown_drop_omapi_connections
&&
1376 cur_time
- shutdown_time
> 4) {
1377 shutdown_state
= shutdown_dhcp
;
1378 shutdown_time
= cur_time
;
1380 } else if (shutdown_state
== shutdown_dhcp
&&
1381 cur_time
- shutdown_time
> 4) {
1382 shutdown_state
= shutdown_done
;
1383 shutdown_time
= cur_time
;
1386 #if defined (FAILOVER_PROTOCOL)
1387 /* Set all failover peers into the shutdown state. */
1388 if (shutdown_state
== shutdown_dhcp
) {
1389 for (state
= failover_states
; state
; state
= state
-> next
) {
1390 if (state
-> me
.state
== normal
) {
1391 dhcp_failover_set_state (state
, shut_down
);
1392 failover_connection_count
++;
1394 if (state
-> me
.state
== shut_down
&&
1395 state
-> partner
.state
!= partner_down
)
1396 failover_connection_count
++;
1400 if (shutdown_state
== shutdown_done
) {
1401 for (state
= failover_states
; state
; state
= state
-> next
) {
1402 if (state
-> me
.state
== shut_down
) {
1403 if (state
-> link_to_peer
)
1404 dhcp_failover_link_dereference (&state
-> link_to_peer
,
1406 dhcp_failover_set_state (state
, recover
);
1409 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1410 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1412 omapi_print_dmalloc_usage_by_caller ();
1417 if (shutdown_state
== shutdown_done
) {
1418 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1419 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1421 omapi_print_dmalloc_usage_by_caller ();
1426 if (shutdown_state
== shutdown_dhcp
&&
1427 #if defined(FAILOVER_PROTOCOL)
1428 !failover_connection_count
&&
1431 shutdown_state
= shutdown_done
;
1432 shutdown_time
= cur_time
;
1435 tv
.tv_sec
= cur_tv
.tv_sec
+ 1;
1436 tv
.tv_usec
= cur_tv
.tv_usec
;
1438 (void (*)(void *))dhcp_io_shutdown_countdown
, 0, 0, 0);
1439 return ISC_R_SUCCESS
;
1442 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
1443 control_object_state_t newstate
)
1445 if (newstate
== server_shutdown
) {
1446 shutdown_time
= cur_time
;
1447 shutdown_state
= shutdown_listeners
;
1448 dhcp_io_shutdown_countdown (0);
1449 return ISC_R_SUCCESS
;
1451 return ISC_R_INVALIDARG
;