00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 static const char copyright[] =
00030 "Copyright 2004-2014 Internet Systems Consortium.";
00031 static const char arr [] = "All rights reserved.";
00032 static const char message [] = "Internet Systems Consortium DHCP Server";
00033 static const char url [] =
00034 "For info, please visit https://www.isc.org/software/dhcp/";
00035
00036 #include "dhcpd.h"
00037 #include <omapip/omapip_p.h>
00038 #include <syslog.h>
00039 #include <signal.h>
00040 #include <errno.h>
00041 #include <limits.h>
00042 #include <sys/types.h>
00043 #include <sys/time.h>
00044
00045 #if defined (PARANOIA)
00046 # include <sys/types.h>
00047 # include <unistd.h>
00048 # include <pwd.h>
00049
00050 # define group real_group
00051 # include <grp.h>
00052 # undef group
00053 #endif
00054
00055 #include "trace.h"
00056
00057 #ifndef UNIT_TEST
00058 static void usage(void);
00059 #endif
00060
00061 struct iaddr server_identifier;
00062 int server_identifier_matched;
00063
00064 #if defined (NSUPDATE)
00065
00066
00067
00068
00069 char std_nsupdate [] = " \n\
00070 option server.ddns-hostname = \n\
00071 pick (option fqdn.hostname, option host-name); \n\
00072 option server.ddns-domainname = config-option domain-name; \n\
00073 option server.ddns-rev-domainname = \"in-addr.arpa.\";";
00074
00075 #endif
00076 int ddns_update_style;
00077 int dont_use_fsync = 0;
00078
00079 const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
00080 const char *path_dhcpd_db = _PATH_DHCPD_DB;
00081 const char *path_dhcpd_pid = _PATH_DHCPD_PID;
00082
00083 isc_boolean_t no_pid_file = ISC_FALSE;
00084
00085 int dhcp_max_agent_option_packet_length = DHCP_MTU_MAX;
00086
00087 static omapi_auth_key_t *omapi_key = (omapi_auth_key_t *)0;
00088 int omapi_port;
00089
00090 #if defined (TRACING)
00091 trace_type_t *trace_srandom;
00092 #endif
00093
00094 static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) {
00095 return ISC_R_SUCCESS;
00096 }
00097
00098 static isc_result_t verify_auth (omapi_object_t *p, omapi_auth_key_t *a) {
00099 if (a != omapi_key)
00100 return DHCP_R_INVALIDKEY;
00101 return ISC_R_SUCCESS;
00102 }
00103
00104 static void omapi_listener_start (void *foo)
00105 {
00106 omapi_object_t *listener;
00107 isc_result_t result;
00108 struct timeval tv;
00109
00110 listener = (omapi_object_t *)0;
00111 result = omapi_generic_new (&listener, MDL);
00112 if (result != ISC_R_SUCCESS)
00113 log_fatal ("Can't allocate new generic object: %s",
00114 isc_result_totext (result));
00115 result = omapi_protocol_listen (listener,
00116 (unsigned)omapi_port, 1);
00117 if (result == ISC_R_SUCCESS && omapi_key)
00118 result = omapi_protocol_configure_security
00119 (listener, verify_addr, verify_auth);
00120 if (result != ISC_R_SUCCESS) {
00121 log_error ("Can't start OMAPI protocol: %s",
00122 isc_result_totext (result));
00123 tv.tv_sec = cur_tv.tv_sec + 5;
00124 tv.tv_usec = cur_tv.tv_usec;
00125 add_timeout (&tv, omapi_listener_start, 0, 0, 0);
00126 }
00127 omapi_object_dereference (&listener, MDL);
00128 }
00129
00130 #if defined (PARANOIA)
00131
00132 static void setup_chroot (char *chroot_dir) {
00133 if (geteuid())
00134 log_fatal ("you must be root to use chroot");
00135
00136 if (chroot(chroot_dir)) {
00137 log_fatal ("chroot(\"%s\"): %m", chroot_dir);
00138 }
00139 if (chdir ("/")) {
00140
00141 log_fatal ("chdir(\"/\"): %m");
00142 }
00143 }
00144 #endif
00145
00146 #ifndef UNIT_TEST
00147 int
00148 main(int argc, char **argv) {
00149 int fd;
00150 int i, status;
00151 struct servent *ent;
00152 char *s;
00153 int cftest = 0;
00154 int lftest = 0;
00155 #ifndef DEBUG
00156 int pid;
00157 char pbuf [20];
00158 int daemon = 1;
00159 #endif
00160 int quiet = 0;
00161 char *server = (char *)0;
00162 isc_result_t result;
00163 unsigned seed;
00164 struct interface_info *ip;
00165 #if defined (NSUPDATE)
00166 struct parse *parse;
00167 int lose;
00168 #endif
00169 int no_dhcpd_conf = 0;
00170 int no_dhcpd_db = 0;
00171 int no_dhcpd_pid = 0;
00172 #ifdef DHCPv6
00173 int local_family_set = 0;
00174 #endif
00175 #if defined (TRACING)
00176 char *traceinfile = (char *)0;
00177 char *traceoutfile = (char *)0;
00178 #endif
00179
00180 #if defined (PARANOIA)
00181 char *set_user = 0;
00182 char *set_group = 0;
00183 char *set_chroot = 0;
00184
00185 uid_t set_uid = 0;
00186 gid_t set_gid = 0;
00187 #endif
00188
00189
00190
00191
00192 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00193 if (fd == 0)
00194 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00195 if (fd == 1)
00196 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00197 if (fd == 2)
00198 log_perror = 0;
00199 else if (fd != -1)
00200 close(fd);
00201
00202
00203 status = dhcp_context_create(DHCP_CONTEXT_PRE_DB,
00204 NULL, NULL);
00205 if (status != ISC_R_SUCCESS)
00206 log_fatal("Can't initialize context: %s",
00207 isc_result_totext(status));
00208
00209
00210 classification_setup ();
00211
00212
00213 result = omapi_init ();
00214 if (result != ISC_R_SUCCESS)
00215 log_fatal ("Can't initialize OMAPI: %s",
00216 isc_result_totext (result));
00217
00218
00219 dhcp_db_objects_setup ();
00220
00221
00222 dhcp_common_objects_setup ();
00223
00224
00225 openlog ("dhcpd", LOG_NDELAY, DHCPD_LOG_FACILITY);
00226
00227 for (i = 1; i < argc; i++) {
00228 if (!strcmp (argv [i], "-p")) {
00229 if (++i == argc)
00230 usage ();
00231 local_port = validate_port (argv [i]);
00232 log_debug ("binding to user-specified port %d",
00233 ntohs (local_port));
00234 } else if (!strcmp (argv [i], "-f")) {
00235 #ifndef DEBUG
00236 daemon = 0;
00237 #endif
00238 log_perror = 0;
00239 } else if (!strcmp (argv [i], "-d")) {
00240 #ifndef DEBUG
00241 daemon = 0;
00242 #endif
00243 log_perror = -1;
00244 } else if (!strcmp (argv [i], "-s")) {
00245 if (++i == argc)
00246 usage ();
00247 server = argv [i];
00248 #if defined (PARANOIA)
00249 } else if (!strcmp (argv [i], "-user")) {
00250 if (++i == argc)
00251 usage ();
00252 set_user = argv [i];
00253 } else if (!strcmp (argv [i], "-group")) {
00254 if (++i == argc)
00255 usage ();
00256 set_group = argv [i];
00257 } else if (!strcmp (argv [i], "-chroot")) {
00258 if (++i == argc)
00259 usage ();
00260 set_chroot = argv [i];
00261 #endif
00262 } else if (!strcmp (argv [i], "-cf")) {
00263 if (++i == argc)
00264 usage ();
00265 path_dhcpd_conf = argv [i];
00266 no_dhcpd_conf = 1;
00267 } else if (!strcmp (argv [i], "-lf")) {
00268 if (++i == argc)
00269 usage ();
00270 path_dhcpd_db = argv [i];
00271 no_dhcpd_db = 1;
00272 } else if (!strcmp (argv [i], "-pf")) {
00273 if (++i == argc)
00274 usage ();
00275 path_dhcpd_pid = argv [i];
00276 no_dhcpd_pid = 1;
00277 } else if (!strcmp(argv[i], "--no-pid")) {
00278 no_pid_file = ISC_TRUE;
00279 } else if (!strcmp (argv [i], "-t")) {
00280
00281 #ifndef DEBUG
00282 daemon = 0;
00283 #endif
00284 cftest = 1;
00285 log_perror = -1;
00286 } else if (!strcmp (argv [i], "-T")) {
00287
00288 #ifndef DEBUG
00289 daemon = 0;
00290 #endif
00291 cftest = 1;
00292 lftest = 1;
00293 log_perror = -1;
00294 } else if (!strcmp (argv [i], "-q")) {
00295 quiet = 1;
00296 quiet_interface_discovery = 1;
00297 #ifdef DHCPv6
00298 } else if (!strcmp(argv[i], "-4")) {
00299 if (local_family_set && (local_family != AF_INET)) {
00300 log_fatal("Server cannot run in both IPv4 and "
00301 "IPv6 mode at the same time.");
00302 }
00303 local_family = AF_INET;
00304 local_family_set = 1;
00305 } else if (!strcmp(argv[i], "-6")) {
00306 if (local_family_set && (local_family != AF_INET6)) {
00307 log_fatal("Server cannot run in both IPv4 and "
00308 "IPv6 mode at the same time.");
00309 }
00310 local_family = AF_INET6;
00311 local_family_set = 1;
00312 #endif
00313 } else if (!strcmp (argv [i], "--version")) {
00314 log_info("isc-dhcpd-%s", PACKAGE_VERSION);
00315 exit (0);
00316 #if defined (TRACING)
00317 } else if (!strcmp (argv [i], "-tf")) {
00318 if (++i == argc)
00319 usage ();
00320 traceoutfile = argv [i];
00321 } else if (!strcmp (argv [i], "-play")) {
00322 if (++i == argc)
00323 usage ();
00324 traceinfile = argv [i];
00325 trace_replay_init ();
00326 #endif
00327 } else if (argv [i][0] == '-') {
00328 usage ();
00329 } else {
00330 struct interface_info *tmp =
00331 (struct interface_info *)0;
00332 if (strlen(argv[i]) >= sizeof(tmp->name))
00333 log_fatal("%s: interface name too long "
00334 "(is %ld)",
00335 argv[i], (long)strlen(argv[i]));
00336 result = interface_allocate (&tmp, MDL);
00337 if (result != ISC_R_SUCCESS)
00338 log_fatal ("Insufficient memory to %s %s: %s",
00339 "record interface", argv [i],
00340 isc_result_totext (result));
00341 strcpy (tmp -> name, argv [i]);
00342 if (interfaces) {
00343 interface_reference (&tmp -> next,
00344 interfaces, MDL);
00345 interface_dereference (&interfaces, MDL);
00346 }
00347 interface_reference (&interfaces, tmp, MDL);
00348 tmp -> flags = INTERFACE_REQUESTED;
00349 }
00350 }
00351
00352 if (!no_dhcpd_conf && (s = getenv ("PATH_DHCPD_CONF"))) {
00353 path_dhcpd_conf = s;
00354 }
00355
00356 #ifdef DHCPv6
00357 if (local_family == AF_INET6) {
00358
00359 if (!no_dhcpd_db) {
00360 if ((s = getenv ("PATH_DHCPD6_DB")))
00361 path_dhcpd_db = s;
00362 else
00363 path_dhcpd_db = _PATH_DHCPD6_DB;
00364 }
00365 if (!no_dhcpd_pid) {
00366 if ((s = getenv ("PATH_DHCPD6_PID")))
00367 path_dhcpd_pid = s;
00368 else
00369 path_dhcpd_pid = _PATH_DHCPD6_PID;
00370 }
00371 } else
00372 #else
00373 {
00374 if (!no_dhcpd_db && (s = getenv ("PATH_DHCPD_DB"))) {
00375 path_dhcpd_db = s;
00376 }
00377 if (!no_dhcpd_pid && (s = getenv ("PATH_DHCPD_PID"))) {
00378 path_dhcpd_pid = s;
00379 }
00380 }
00381 #endif
00382
00383
00384
00385
00386
00387 if (path_dhcpd_db[0] != '/') {
00388 const char *path = path_dhcpd_db;
00389 path_dhcpd_db = realpath(path_dhcpd_db, NULL);
00390 if (path_dhcpd_db == NULL)
00391 log_fatal("Failed to get realpath for %s: %s", path,
00392 strerror(errno));
00393 }
00394
00395 if (!quiet) {
00396 log_info("%s %s", message, PACKAGE_VERSION);
00397 log_info (copyright);
00398 log_info (arr);
00399 log_info (url);
00400 } else {
00401 quiet = 0;
00402 log_perror = 0;
00403 }
00404
00405 #if defined (TRACING)
00406 trace_init (set_time, MDL);
00407 if (traceoutfile) {
00408 result = trace_begin (traceoutfile, MDL);
00409 if (result != ISC_R_SUCCESS)
00410 log_fatal ("Unable to begin trace: %s",
00411 isc_result_totext (result));
00412 }
00413 interface_trace_setup ();
00414 parse_trace_setup ();
00415 trace_srandom = trace_type_register ("random-seed", (void *)0,
00416 trace_seed_input,
00417 trace_seed_stop, MDL);
00418 trace_ddns_init();
00419 #endif
00420
00421 #if defined (PARANOIA)
00422
00423 if (set_user) {
00424 struct passwd *tmp_pwd;
00425
00426 if (geteuid())
00427 log_fatal ("you must be root to set user");
00428
00429 if (!(tmp_pwd = getpwnam(set_user)))
00430 log_fatal ("no such user: %s", set_user);
00431
00432 set_uid = tmp_pwd->pw_uid;
00433
00434
00435 if (!set_group)
00436 set_gid = tmp_pwd->pw_gid;
00437 }
00438
00439 if (set_group) {
00440
00441 #define group real_group
00442 struct group *tmp_grp;
00443
00444 if (geteuid())
00445 log_fatal ("you must be root to set group");
00446
00447 if (!(tmp_grp = getgrnam(set_group)))
00448 log_fatal ("no such group: %s", set_group);
00449
00450 set_gid = tmp_grp->gr_gid;
00451 #undef group
00452 }
00453
00454 # if defined (EARLY_CHROOT)
00455 if (set_chroot) setup_chroot (set_chroot);
00456 # endif
00457 #endif
00458
00459
00460 if (!local_port)
00461 {
00462 if ((s = getenv ("DHCPD_PORT"))) {
00463 local_port = validate_port (s);
00464 log_debug ("binding to environment-specified port %d",
00465 ntohs (local_port));
00466 } else {
00467 if (local_family == AF_INET) {
00468 ent = getservbyname("dhcp", "udp");
00469 if (ent == NULL) {
00470 local_port = htons(67);
00471 } else {
00472 local_port = ent->s_port;
00473 }
00474 } else {
00475
00476 ent = getservbyname("dhcpv6-server", "udp");
00477 if (ent == NULL) {
00478 local_port = htons(547);
00479 } else {
00480 local_port = ent->s_port;
00481 }
00482 }
00483 #ifndef __CYGWIN32__
00484 endservent ();
00485 #endif
00486 }
00487 }
00488
00489 if (local_family == AF_INET) {
00490 remote_port = htons(ntohs(local_port) + 1);
00491 } else {
00492
00493 ent = getservbyname("dhcpv6-client", "udp");
00494 if (ent == NULL) {
00495 remote_port = htons(546);
00496 } else {
00497 remote_port = ent->s_port;
00498 }
00499 }
00500
00501 if (server) {
00502 if (local_family != AF_INET) {
00503 log_fatal("You can only specify address to send "
00504 "replies to when running an IPv4 server.");
00505 }
00506 if (!inet_aton (server, &limited_broadcast)) {
00507 struct hostent *he;
00508 he = gethostbyname (server);
00509 if (he) {
00510 memcpy (&limited_broadcast,
00511 he -> h_addr_list [0],
00512 sizeof limited_broadcast);
00513 } else
00514 limited_broadcast.s_addr = INADDR_BROADCAST;
00515 }
00516 } else {
00517 limited_broadcast.s_addr = INADDR_BROADCAST;
00518 }
00519
00520
00521 gettimeofday(&cur_tv, NULL);
00522
00523
00524 initialize_common_option_spaces ();
00525 initialize_server_option_spaces ();
00526
00527
00528 add_enumeration (&ddns_styles);
00529 add_enumeration (&syslog_enum);
00530 #if defined (LDAP_CONFIGURATION)
00531 add_enumeration (&ldap_methods);
00532 #if defined (LDAP_USE_SSL)
00533 add_enumeration (&ldap_ssl_usage_enum);
00534 add_enumeration (&ldap_tls_reqcert_enum);
00535 add_enumeration (&ldap_tls_crlcheck_enum);
00536 #endif
00537 #endif
00538
00539 if (!group_allocate (&root_group, MDL))
00540 log_fatal ("Can't allocate root group!");
00541 root_group -> authoritative = 0;
00542
00543
00544 dhcp_interface_setup_hook = dhcpd_interface_setup_hook;
00545 bootp_packet_handler = do_packet;
00546 #ifdef DHCPv6
00547 dhcpv6_packet_handler = do_packet6;
00548 #endif
00549
00550 #if defined (NSUPDATE)
00551
00552 parse = NULL;
00553 status = new_parse(&parse, -1, std_nsupdate, sizeof(std_nsupdate) - 1,
00554 "standard name service update routine", 0);
00555 if (status != ISC_R_SUCCESS)
00556 log_fatal ("can't begin parsing name service updater!");
00557
00558 if (parse != NULL) {
00559 lose = 0;
00560 if (!(parse_executable_statements(&root_group->statements,
00561 parse, &lose, context_any))) {
00562 end_parse(&parse);
00563 log_fatal("can't parse standard name service updater!");
00564 }
00565 end_parse(&parse);
00566 }
00567 #endif
00568
00569
00570 if (!cftest && !lftest)
00571 icmp_startup (1, lease_pinged);
00572
00573 #if defined (TRACING)
00574 if (traceinfile) {
00575 if (!no_dhcpd_db) {
00576 log_error ("%s", "");
00577 log_error ("** You must specify a lease file with -lf.");
00578 log_error (" Dhcpd will not overwrite your default");
00579 log_fatal (" lease file when playing back a trace. **");
00580 }
00581 trace_file_replay (traceinfile);
00582
00583 #if defined (DEBUG_MEMORY_LEAKAGE) && \
00584 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00585 free_everything ();
00586 omapi_print_dmalloc_usage_by_caller ();
00587 #endif
00588
00589 exit (0);
00590 }
00591 #endif
00592
00593 #ifdef DHCPv6
00594
00595 if (!ia_new_hash(&ia_na_active, DEFAULT_HASH_SIZE, MDL)) {
00596 log_fatal("Out of memory creating hash for active IA_NA.");
00597 }
00598 if (!ia_new_hash(&ia_ta_active, DEFAULT_HASH_SIZE, MDL)) {
00599 log_fatal("Out of memory creating hash for active IA_TA.");
00600 }
00601 if (!ia_new_hash(&ia_pd_active, DEFAULT_HASH_SIZE, MDL)) {
00602 log_fatal("Out of memory creating hash for active IA_PD.");
00603 }
00604 #endif
00605
00606
00607 if (readconf () != ISC_R_SUCCESS)
00608 log_fatal ("Configuration file errors encountered -- exiting");
00609
00610 postconf_initialization (quiet);
00611
00612 #if defined (PARANOIA) && !defined (EARLY_CHROOT)
00613 if (set_chroot) setup_chroot (set_chroot);
00614 #endif
00615
00616
00617 if (cftest && !lftest)
00618 exit(0);
00619
00620 group_write_hook = group_writer;
00621
00622
00623 #if defined (PARANOIA)
00624 db_startup (lftest, set_uid, set_gid);
00625 #else
00626 db_startup (lftest);
00627 #endif
00628
00629 if (lftest)
00630 exit (0);
00631
00632
00633 discover_interfaces(DISCOVER_SERVER);
00634
00635 #ifdef DHCPv6
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 if (local_family == AF_INET6) {
00646 mark_hosts_unavailable();
00647 mark_phosts_unavailable();
00648 mark_interfaces_unavailable();
00649 }
00650 #endif
00651
00652
00653
00654
00655
00656
00657
00658 seed = 0;
00659 for (ip = interfaces; ip; ip = ip -> next) {
00660 int junk;
00661 memcpy (&junk,
00662 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
00663 sizeof seed], sizeof seed);
00664 seed += junk;
00665 }
00666 srandom (seed + cur_time);
00667 #if defined (TRACING)
00668 trace_seed_stash (trace_srandom, seed + cur_time);
00669 #endif
00670 postdb_startup ();
00671
00672 #ifdef DHCPv6
00673
00674
00675
00676
00677 if (set_server_duid_from_option() == ISC_R_SUCCESS) {
00678 write_server_duid();
00679 } else {
00680 if (!server_duid_isset()) {
00681 if (generate_new_server_duid() != ISC_R_SUCCESS) {
00682 log_fatal("Unable to set server identifier.");
00683 }
00684 write_server_duid();
00685 }
00686 }
00687 #endif
00688
00689 #ifndef DEBUG
00690 if (daemon) {
00691
00692 if ((pid = fork ()) < 0)
00693 log_fatal ("Can't fork daemon: %m");
00694 else if (pid)
00695 exit (0);
00696 }
00697
00698
00699
00700
00701
00702 if (no_pid_file == ISC_FALSE) {
00703
00704 if ((i = open (path_dhcpd_pid, O_RDONLY | O_CLOEXEC)) >= 0) {
00705 status = read(i, pbuf, (sizeof pbuf) - 1);
00706 close (i);
00707 if (status > 0) {
00708 pbuf[status] = 0;
00709 pid = atoi(pbuf);
00710
00711
00712
00713
00714
00715 if (!pid ||
00716 (pid != getpid() && kill(pid, 0) == 0))
00717 log_fatal("There's already a "
00718 "DHCP server running.");
00719 }
00720 }
00721
00722
00723 i = open(path_dhcpd_pid, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
00724 if (i >= 0) {
00725 sprintf(pbuf, "%d\n", (int) getpid());
00726 IGNORE_RET (write(i, pbuf, strlen(pbuf)));
00727 close(i);
00728 } else {
00729 log_error("Can't create PID file %s: %m.",
00730 path_dhcpd_pid);
00731 }
00732 }
00733
00734 #if defined (PARANOIA)
00735
00736
00737 if (set_gid) {
00738 if (setgroups (0, (void *)0))
00739 log_fatal ("setgroups: %m");
00740 if (setgid (set_gid))
00741 log_fatal ("setgid(%d): %m", (int) set_gid);
00742 }
00743
00744 if (set_uid) {
00745 if (setuid (set_uid))
00746 log_fatal ("setuid(%d): %m", (int) set_uid);
00747 }
00748 #endif
00749
00750
00751
00752 if (log_perror == -1)
00753 log_perror = 1;
00754 else
00755 log_perror = 0;
00756
00757 if (daemon) {
00758
00759 (void) setsid();
00760
00761
00762 (void) close(0);
00763 (void) close(1);
00764 (void) close(2);
00765
00766
00767 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
00768 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
00769 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
00770 log_perror = 0;
00771
00772 IGNORE_RET (chdir("/"));
00773 }
00774 #endif
00775
00776 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
00777 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00778 dmalloc_cutoff_generation = dmalloc_generation;
00779 dmalloc_longterm = dmalloc_outstanding;
00780 dmalloc_outstanding = 0;
00781 #endif
00782
00783 omapi_set_int_value ((omapi_object_t *)dhcp_control_object,
00784 (omapi_object_t *)0, "state", server_running);
00785
00786
00787 signal(SIGINT, dhcp_signal_handler);
00788 signal(SIGTERM, dhcp_signal_handler);
00789
00790
00791 log_info("Server starting service.");
00792
00793 TRACE(DHCPD_MAIN());
00794
00795
00796
00797
00798
00799 dispatch ();
00800
00801
00802 return 0;
00803 }
00804 #endif
00805
00806 void postconf_initialization (int quiet)
00807 {
00808 struct option_state *options = NULL;
00809 struct data_string db;
00810 struct option_cache *oc;
00811 char *s;
00812 isc_result_t result;
00813 int tmp;
00814 #if defined (NSUPDATE)
00815 struct in_addr local4, *local4_ptr = NULL;
00816 struct in6_addr local6, *local6_ptr = NULL;
00817 #endif
00818
00819
00820 option_state_allocate(&options, MDL);
00821
00822 execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
00823 options, &global_scope, root_group,
00824 NULL, NULL);
00825 memset(&db, 0, sizeof db);
00826 oc = lookup_option(&server_universe, options, SV_LEASE_FILE_NAME);
00827 if (oc &&
00828 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00829 &global_scope, oc, MDL)) {
00830 s = dmalloc(db.len + 1, MDL);
00831 if (!s)
00832 log_fatal("no memory for lease db filename.");
00833 memcpy(s, db.data, db.len);
00834 s[db.len] = 0;
00835 data_string_forget(&db, MDL);
00836 path_dhcpd_db = s;
00837 }
00838
00839 oc = lookup_option(&server_universe, options, SV_PID_FILE_NAME);
00840 if (oc &&
00841 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00842 &global_scope, oc, MDL)) {
00843 s = dmalloc(db.len + 1, MDL);
00844 if (!s)
00845 log_fatal("no memory for pid filename.");
00846 memcpy(s, db.data, db.len);
00847 s[db.len] = 0;
00848 data_string_forget(&db, MDL);
00849 path_dhcpd_pid = s;
00850 }
00851
00852 #ifdef DHCPv6
00853 if (local_family == AF_INET6) {
00854
00855
00856
00857
00858 oc = lookup_option(&server_universe, options,
00859 SV_DHCPV6_LEASE_FILE_NAME);
00860 if (oc &&
00861 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00862 &global_scope, oc, MDL)) {
00863 s = dmalloc(db.len + 1, MDL);
00864 if (!s)
00865 log_fatal("no memory for lease db filename.");
00866 memcpy(s, db.data, db.len);
00867 s[db.len] = 0;
00868 data_string_forget(&db, MDL);
00869 path_dhcpd_db = s;
00870 }
00871
00872 oc = lookup_option(&server_universe, options,
00873 SV_DHCPV6_PID_FILE_NAME);
00874 if (oc &&
00875 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00876 &global_scope, oc, MDL)) {
00877 s = dmalloc(db.len + 1, MDL);
00878 if (!s)
00879 log_fatal("no memory for pid filename.");
00880 memcpy(s, db.data, db.len);
00881 s[db.len] = 0;
00882 data_string_forget(&db, MDL);
00883 path_dhcpd_pid = s;
00884 }
00885 }
00886 #endif
00887
00888 omapi_port = -1;
00889 oc = lookup_option(&server_universe, options, SV_OMAPI_PORT);
00890 if (oc &&
00891 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00892 &global_scope, oc, MDL)) {
00893 if (db.len == 2) {
00894 omapi_port = getUShort(db.data);
00895 } else
00896 log_fatal("invalid omapi port data length");
00897 data_string_forget(&db, MDL);
00898 }
00899
00900 oc = lookup_option(&server_universe, options, SV_OMAPI_KEY);
00901 if (oc &&
00902 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00903 &global_scope, oc, MDL)) {
00904 s = dmalloc(db.len + 1, MDL);
00905 if (!s)
00906 log_fatal("no memory for OMAPI key filename.");
00907 memcpy(s, db.data, db.len);
00908 s[db.len] = 0;
00909 data_string_forget(&db, MDL);
00910 result = omapi_auth_key_lookup_name(&omapi_key, s);
00911 dfree(s, MDL);
00912 if (result != ISC_R_SUCCESS)
00913 log_fatal("OMAPI key %s: %s",
00914 s, isc_result_totext (result));
00915 }
00916
00917 oc = lookup_option(&server_universe, options, SV_LOCAL_PORT);
00918 if (oc &&
00919 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00920 &global_scope, oc, MDL)) {
00921 if (db.len == 2) {
00922 local_port = htons(getUShort (db.data));
00923 } else
00924 log_fatal("invalid local port data length");
00925 data_string_forget(&db, MDL);
00926 }
00927
00928 oc = lookup_option(&server_universe, options, SV_REMOTE_PORT);
00929 if (oc &&
00930 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00931 &global_scope, oc, MDL)) {
00932 if (db.len == 2) {
00933 remote_port = htons(getUShort (db.data));
00934 } else
00935 log_fatal("invalid remote port data length");
00936 data_string_forget(&db, MDL);
00937 }
00938
00939 oc = lookup_option(&server_universe, options,
00940 SV_LIMITED_BROADCAST_ADDRESS);
00941 if (oc &&
00942 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00943 &global_scope, oc, MDL)) {
00944 if (db.len == 4) {
00945 memcpy(&limited_broadcast, db.data, 4);
00946 } else
00947 log_fatal("invalid broadcast address data length");
00948 data_string_forget(&db, MDL);
00949 }
00950
00951 oc = lookup_option(&server_universe, options, SV_LOCAL_ADDRESS);
00952 if (oc &&
00953 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00954 &global_scope, oc, MDL)) {
00955 if (db.len == 4) {
00956 memcpy(&local_address, db.data, 4);
00957 } else
00958 log_fatal("invalid local address data length");
00959 data_string_forget(&db, MDL);
00960 }
00961
00962 oc = lookup_option(&server_universe, options, SV_DDNS_UPDATE_STYLE);
00963 if (oc) {
00964 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00965 &global_scope, oc, MDL)) {
00966 if (db.len == 1) {
00967 ddns_update_style = db.data[0];
00968 } else
00969 log_fatal("invalid dns update type");
00970 data_string_forget(&db, MDL);
00971 }
00972 } else {
00973 ddns_update_style = DDNS_UPDATE_STYLE_NONE;
00974 }
00975 #if defined (NSUPDATE)
00976
00977 if (ddns_update_style == DDNS_UPDATE_STYLE_AD_HOC) {
00978 log_fatal("ddns-update-style ad_hoc no longer supported");
00979 }
00980
00981 oc = lookup_option(&server_universe, options, SV_DDNS_LOCAL_ADDRESS4);
00982 if (oc) {
00983 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00984 &global_scope, oc, MDL)) {
00985 if (db.len == 4) {
00986 memcpy(&local4, db.data, 4);
00987 local4_ptr = &local4;
00988 }
00989 data_string_forget(&db, MDL);
00990 }
00991 }
00992
00993 oc = lookup_option(&server_universe, options, SV_DDNS_LOCAL_ADDRESS6);
00994 if (oc) {
00995 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
00996 &global_scope, oc, MDL)) {
00997 if (db.len == 16) {
00998 memcpy(&local6, db.data, 16);
00999 local6_ptr = &local6;
01000 }
01001 data_string_forget(&db, MDL);
01002 }
01003 }
01004
01005 if (dhcp_context_create(DHCP_CONTEXT_POST_DB, local4_ptr, local6_ptr)
01006 != ISC_R_SUCCESS)
01007 log_fatal("Unable to complete ddns initialization");
01008
01009 #else
01010
01011 if (ddns_update_style != DDNS_UPDATE_STYLE_NONE) {
01012 log_fatal("Support for ddns-update-style not compiled in");
01013 }
01014 #endif
01015
01016 oc = lookup_option(&server_universe, options, SV_LOG_FACILITY);
01017 if (oc) {
01018 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
01019 &global_scope, oc, MDL)) {
01020 if (db.len == 1) {
01021 closelog ();
01022 openlog("dhcpd", LOG_NDELAY, db.data[0]);
01023
01024
01025 if (!quiet) {
01026
01027 tmp = log_perror;
01028 log_perror = 0;
01029 log_info("%s %s",
01030 message, PACKAGE_VERSION);
01031 log_info(copyright);
01032 log_info(arr);
01033 log_info(url);
01034 log_perror = tmp;
01035 }
01036 } else
01037 log_fatal("invalid log facility");
01038 data_string_forget(&db, MDL);
01039 }
01040 }
01041
01042 oc = lookup_option(&server_universe, options, SV_DELAYED_ACK);
01043 if (oc &&
01044 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
01045 &global_scope, oc, MDL)) {
01046 if (db.len == 2) {
01047 max_outstanding_acks = htons(getUShort(db.data));
01048 } else {
01049 log_fatal("invalid max delayed ACK count ");
01050 }
01051 data_string_forget(&db, MDL);
01052 }
01053
01054 oc = lookup_option(&server_universe, options, SV_MAX_ACK_DELAY);
01055 if (oc &&
01056 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
01057 &global_scope, oc, MDL)) {
01058 u_int32_t timeval;
01059
01060 if (db.len != 4)
01061 log_fatal("invalid max ack delay configuration");
01062
01063 timeval = getULong(db.data);
01064 max_ack_delay_secs = timeval / 1000000;
01065 max_ack_delay_usecs = timeval % 1000000;
01066
01067 data_string_forget(&db, MDL);
01068 }
01069
01070 oc = lookup_option(&server_universe, options, SV_DONT_USE_FSYNC);
01071 if ((oc != NULL) &&
01072 evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
01073 &global_scope, oc, MDL)) {
01074 dont_use_fsync = 1;
01075 log_error("Not using fsync() to flush lease writes");
01076 }
01077
01078
01079 option_state_dereference(&options, MDL);
01080 }
01081
01082 void postdb_startup (void)
01083 {
01084
01085 if (omapi_port != -1) {
01086 omapi_listener_start (0);
01087 }
01088
01089 #if defined (FAILOVER_PROTOCOL)
01090
01091 dhcp_failover_startup ();
01092 #endif
01093
01094
01095
01096
01097 schedule_all_ipv6_lease_timeouts();
01098 }
01099
01100
01101 #ifndef UNIT_TEST
01102 static void
01103 usage(void) {
01104 log_info("%s %s", message, PACKAGE_VERSION);
01105 log_info(copyright);
01106 log_info(arr);
01107
01108 log_fatal("Usage: dhcpd [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
01109 #ifdef DHCPv6
01110 " [-4|-6] [-cf config-file] [-lf lease-file]\n"
01111 #else
01112 " [-cf config-file] [-lf lease-file]\n"
01113 #endif
01114 #if defined (PARANOIA)
01115
01116 " [-user user] [-group group] [-chroot dir]\n"
01117 #endif
01118 #if defined (TRACING)
01119 " [-tf trace-output-file]\n"
01120 " [-play trace-input-file]\n"
01121 #endif
01122 " [-pf pid-file] [--no-pid] [-s server]\n"
01123 " [if0 [...ifN]]");
01124 }
01125 #endif
01126
01127 void lease_pinged (from, packet, length)
01128 struct iaddr from;
01129 u_int8_t *packet;
01130 int length;
01131 {
01132 struct lease *lp;
01133
01134
01135
01136
01137
01138 if (!outstanding_pings)
01139 return;
01140
01141 lp = (struct lease *)0;
01142 if (!find_lease_by_ip_addr (&lp, from, MDL)) {
01143 log_debug ("unexpected ICMP Echo Reply from %s",
01144 piaddr (from));
01145 return;
01146 }
01147
01148 if (!lp -> state) {
01149 #if defined (FAILOVER_PROTOCOL)
01150 if (!lp -> pool ||
01151 !lp -> pool -> failover_peer)
01152 #endif
01153 log_debug ("ICMP Echo Reply for %s late or spurious.",
01154 piaddr (from));
01155 goto out;
01156 }
01157
01158 if (lp -> ends > cur_time) {
01159 log_debug ("ICMP Echo reply while lease %s valid.",
01160 piaddr (from));
01161 }
01162
01163
01164
01165 data_string_forget (&lp -> state -> parameter_request_list, MDL);
01166 free_lease_state (lp -> state, MDL);
01167 lp -> state = (struct lease_state *)0;
01168
01169 abandon_lease (lp, "pinged before offer");
01170 cancel_timeout (lease_ping_timeout, lp);
01171 --outstanding_pings;
01172 out:
01173 lease_dereference (&lp, MDL);
01174 }
01175
01176 void lease_ping_timeout (vlp)
01177 void *vlp;
01178 {
01179 struct lease *lp = vlp;
01180
01181 #if defined (DEBUG_MEMORY_LEAKAGE)
01182 unsigned long previous_outstanding = dmalloc_outstanding;
01183 #endif
01184
01185 --outstanding_pings;
01186 dhcp_reply (lp);
01187
01188 #if defined (DEBUG_MEMORY_LEAKAGE)
01189 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
01190 dmalloc_generation,
01191 dmalloc_outstanding - previous_outstanding,
01192 dmalloc_outstanding, dmalloc_longterm);
01193 #endif
01194 #if defined (DEBUG_MEMORY_LEAKAGE)
01195 dmalloc_dump_outstanding ();
01196 #endif
01197 }
01198
01199 int dhcpd_interface_setup_hook (struct interface_info *ip, struct iaddr *ia)
01200 {
01201 struct subnet *subnet;
01202 struct shared_network *share;
01203 isc_result_t status;
01204
01205
01206
01207 if (!ia) {
01208 const char *fnn = "fallback-net";
01209 status = shared_network_allocate (&ip -> shared_network, MDL);
01210 if (status != ISC_R_SUCCESS)
01211 log_fatal ("No memory for shared subnet: %s",
01212 isc_result_totext (status));
01213 ip -> shared_network -> name = dmalloc (strlen (fnn) + 1, MDL);
01214 strcpy (ip -> shared_network -> name, fnn);
01215 return 1;
01216 }
01217
01218
01219
01220 subnet = (struct subnet *)0;
01221 if (find_subnet (&subnet, *ia, MDL)) {
01222
01223
01224 if (!subnet -> interface) {
01225 interface_reference (&subnet -> interface, ip, MDL);
01226 subnet -> interface_address = *ia;
01227 } else if (subnet -> interface != ip) {
01228 log_error ("Multiple interfaces match the %s: %s %s",
01229 "same subnet",
01230 subnet -> interface -> name, ip -> name);
01231 }
01232 share = subnet -> shared_network;
01233 if (ip -> shared_network &&
01234 ip -> shared_network != share) {
01235 log_fatal ("Interface %s matches multiple shared %s",
01236 ip -> name, "networks");
01237 } else {
01238 if (!ip -> shared_network)
01239 shared_network_reference
01240 (&ip -> shared_network, share, MDL);
01241 }
01242
01243 if (!share -> interface) {
01244 interface_reference (&share -> interface, ip, MDL);
01245 } else if (share -> interface != ip) {
01246 log_error ("Multiple interfaces match the %s: %s %s",
01247 "same shared network",
01248 share -> interface -> name, ip -> name);
01249 }
01250 subnet_dereference (&subnet, MDL);
01251 }
01252 return 1;
01253 }
01254
01255 static TIME shutdown_time;
01256 static int omapi_connection_count;
01257 enum dhcp_shutdown_state shutdown_state;
01258
01259 isc_result_t dhcp_io_shutdown (omapi_object_t *obj, void *foo)
01260 {
01261
01262 if (shutdown_state == shutdown_listeners &&
01263 obj -> type == omapi_type_listener &&
01264 obj -> inner &&
01265 obj -> inner -> type == omapi_type_protocol_listener) {
01266 omapi_listener_destroy (obj, MDL);
01267 return ISC_R_SUCCESS;
01268 }
01269
01270
01271 if (obj -> type == omapi_type_connection &&
01272 obj -> inner &&
01273 obj -> inner -> type == omapi_type_protocol) {
01274 if (shutdown_state == shutdown_drop_omapi_connections) {
01275 omapi_disconnect (obj, 1);
01276 }
01277 omapi_connection_count++;
01278 if (shutdown_state == shutdown_omapi_connections) {
01279 omapi_disconnect (obj, 0);
01280 return ISC_R_SUCCESS;
01281 }
01282 }
01283
01284
01285 if (obj -> type == dhcp_type_interface &&
01286 shutdown_state == shutdown_dhcp) {
01287 dhcp_interface_remove (obj, (omapi_object_t *)0);
01288 return ISC_R_SUCCESS;
01289 }
01290 return ISC_R_SUCCESS;
01291 }
01292
01293 static isc_result_t dhcp_io_shutdown_countdown (void *vlp)
01294 {
01295 #if defined (FAILOVER_PROTOCOL)
01296 dhcp_failover_state_t *state;
01297 int failover_connection_count = 0;
01298 #endif
01299 struct timeval tv;
01300
01301 oncemore:
01302 if (shutdown_state == shutdown_listeners ||
01303 shutdown_state == shutdown_omapi_connections ||
01304 shutdown_state == shutdown_drop_omapi_connections ||
01305 shutdown_state == shutdown_dhcp) {
01306 omapi_connection_count = 0;
01307 omapi_io_state_foreach (dhcp_io_shutdown, 0);
01308 }
01309
01310 if ((shutdown_state == shutdown_listeners ||
01311 shutdown_state == shutdown_omapi_connections ||
01312 shutdown_state == shutdown_drop_omapi_connections) &&
01313 omapi_connection_count == 0) {
01314 shutdown_state = shutdown_dhcp;
01315 shutdown_time = cur_time;
01316 goto oncemore;
01317 } else if (shutdown_state == shutdown_listeners &&
01318 cur_time - shutdown_time > 4) {
01319 shutdown_state = shutdown_omapi_connections;
01320 shutdown_time = cur_time;
01321 } else if (shutdown_state == shutdown_omapi_connections &&
01322 cur_time - shutdown_time > 4) {
01323 shutdown_state = shutdown_drop_omapi_connections;
01324 shutdown_time = cur_time;
01325 } else if (shutdown_state == shutdown_drop_omapi_connections &&
01326 cur_time - shutdown_time > 4) {
01327 shutdown_state = shutdown_dhcp;
01328 shutdown_time = cur_time;
01329 goto oncemore;
01330 } else if (shutdown_state == shutdown_dhcp &&
01331 cur_time - shutdown_time > 4) {
01332 shutdown_state = shutdown_done;
01333 shutdown_time = cur_time;
01334 }
01335
01336 #if defined (FAILOVER_PROTOCOL)
01337
01338 if (shutdown_state == shutdown_dhcp) {
01339 for (state = failover_states; state; state = state -> next) {
01340 if (state -> me.state == normal) {
01341 dhcp_failover_set_state (state, shut_down);
01342 failover_connection_count++;
01343 }
01344 if (state -> me.state == shut_down &&
01345 state -> partner.state != partner_down)
01346 failover_connection_count++;
01347 }
01348 }
01349
01350 if (shutdown_state == shutdown_done) {
01351 for (state = failover_states; state; state = state -> next) {
01352 if (state -> me.state == shut_down) {
01353 if (state -> link_to_peer)
01354 dhcp_failover_link_dereference (&state -> link_to_peer,
01355 MDL);
01356 dhcp_failover_set_state (state, recover);
01357 }
01358 }
01359 #if defined (DEBUG_MEMORY_LEAKAGE) && \
01360 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
01361 free_everything ();
01362 omapi_print_dmalloc_usage_by_caller ();
01363 #endif
01364 exit (0);
01365 }
01366 #else
01367 if (shutdown_state == shutdown_done) {
01368 #if defined (DEBUG_MEMORY_LEAKAGE) && \
01369 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
01370 free_everything ();
01371 omapi_print_dmalloc_usage_by_caller ();
01372 #endif
01373 exit (0);
01374 }
01375 #endif
01376 if (shutdown_state == shutdown_dhcp &&
01377 #if defined(FAILOVER_PROTOCOL)
01378 !failover_connection_count &&
01379 #endif
01380 ISC_TRUE) {
01381 shutdown_state = shutdown_done;
01382 shutdown_time = cur_time;
01383 goto oncemore;
01384 }
01385 tv.tv_sec = cur_tv.tv_sec + 1;
01386 tv.tv_usec = cur_tv.tv_usec;
01387 add_timeout (&tv,
01388 (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
01389 return ISC_R_SUCCESS;
01390 }
01391
01392 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
01393 control_object_state_t newstate)
01394 {
01395 struct timeval tv;
01396
01397 if (newstate != server_shutdown)
01398 return DHCP_R_INVALIDARG;
01399
01400 if (shutdown_signal == SIGUSR1)
01401 return ISC_R_SUCCESS;
01402 shutdown_time = cur_time;
01403 shutdown_state = shutdown_listeners;
01404
01405 if (shutdown_signal == 0) {
01406 shutdown_signal = SIGUSR1;
01407 dhcp_io_shutdown_countdown (0);
01408 return ISC_R_SUCCESS;
01409 }
01410
01411 log_info("Received signal %d, initiating shutdown.", shutdown_signal);
01412 shutdown_signal = SIGUSR1;
01413
01414
01415
01416
01417
01418 tv.tv_sec = cur_tv.tv_sec;
01419 tv.tv_usec = cur_tv.tv_usec + 1;
01420 add_timeout(&tv,
01421 (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
01422 return ISC_R_SUCCESS;
01423 }