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
00030
00031
00032
00033 #include "dhcpd.h"
00034 #include <syslog.h>
00035 #include <signal.h>
00036 #include <errno.h>
00037 #include <sys/time.h>
00038 #include <sys/wait.h>
00039 #include <limits.h>
00040 #include <dns/result.h>
00041
00042 #ifdef HAVE_LIBCAP_NG
00043 #include <cap-ng.h>
00044 #endif
00045
00046
00047
00048
00049
00050 extern int asprintf(char **strp, const char *fmt, ...);
00051
00052 TIME default_lease_time = 43200;
00053 TIME max_lease_time = 86400;
00054
00055 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
00056 const char *path_dhclient_db = NULL;
00057 const char *path_dhclient_pid = NULL;
00058 static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
00059 char *path_dhclient_script = path_dhclient_script_array;
00060
00061
00062 isc_boolean_t no_pid_file = ISC_FALSE;
00063
00064 int dhcp_max_agent_option_packet_length = 0;
00065
00066 int interfaces_requested = 0;
00067
00068 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
00069 struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
00070 struct in_addr inaddr_any;
00071 struct sockaddr_in sockaddr_broadcast;
00072 struct in_addr giaddr;
00073 struct data_string default_duid;
00074 int duid_type = 0;
00075 int duid_v4 = 1;
00076 int std_dhcid = 0;
00077
00078
00079
00080 #define ASSERT_STATE(state_is, state_shouldbe) {}
00081
00082 static const char copyright[] = "Copyright 2004-2014 Internet Systems Consortium.";
00083 static const char arr [] = "All rights reserved.";
00084 static const char message [] = "Internet Systems Consortium DHCP Client";
00085 static const char url [] = "For info, please visit https://www.isc.org/software/dhcp/";
00086
00087 u_int16_t local_port = 0;
00088 u_int16_t remote_port = 0;
00089 int no_daemon = 0;
00090 struct string_list *client_env = NULL;
00091 int client_env_count = 0;
00092 int onetry = 0;
00093 int quiet = 1;
00094 int nowait = 0;
00095 int stateless = 0;
00096 int wanted_ia_na = -1;
00097 int wanted_ia_ta = 0;
00098 int wanted_ia_pd = 0;
00099 char *mockup_relay = NULL;
00100 int bootp_broadcast_always = 0;
00101
00102 extern u_int32_t default_requested_options[];
00103
00104 void run_stateless(int exit_mode);
00105
00106 static void usage(void);
00107
00108 static isc_result_t write_duid(struct data_string *duid);
00109 static void add_reject(struct packet *packet);
00110
00111 static int check_domain_name(const char *ptr, size_t len, int dots);
00112 static int check_domain_name_list(const char *ptr, size_t len, int dots);
00113 static int check_option_values(struct universe *universe, unsigned int opt,
00114 const char *ptr, size_t len);
00115
00116 static void setup_ib_interface(struct interface_info *ip);
00117
00118 int
00119 main(int argc, char **argv) {
00120 int fd;
00121 int i;
00122 struct interface_info *ip;
00123 struct client_state *client;
00124 unsigned seed;
00125 char *server = NULL;
00126 isc_result_t status;
00127 int exit_mode = 0;
00128 int release_mode = 0;
00129 struct timeval tv;
00130 omapi_object_t *listener;
00131 isc_result_t result;
00132 int persist = 0;
00133 int no_dhclient_conf = 0;
00134 int no_dhclient_db = 0;
00135 int no_dhclient_pid = 0;
00136 int no_dhclient_script = 0;
00137 #ifdef DHCPv6
00138 int local_family_set = 0;
00139 #endif
00140 char *s;
00141 char *dhcp_client_identifier_arg = NULL;
00142 char *dhcp_host_name_arg = NULL;
00143 char *dhcp_fqdn_arg = NULL;
00144 char *dhcp_vendor_class_identifier_arg = NULL;
00145 char *dhclient_request_options = NULL;
00146
00147 int timeout_arg = 0;
00148 char *arg_conf = NULL;
00149 int arg_conf_len = 0;
00150 #ifdef HAVE_LIBCAP_NG
00151 int keep_capabilities = 0;
00152 #endif
00153
00154
00155 memset(&default_duid, 0, sizeof(default_duid));
00156
00157
00158
00159
00160 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00161 if (fd == 0)
00162 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00163 if (fd == 1)
00164 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00165 if (fd == 2)
00166 log_perror = 0;
00167 else if (fd != -1)
00168 close(fd);
00169
00170 openlog("dhclient", LOG_NDELAY | LOG_PID, LOG_DAEMON);
00171
00172 #if !(defined(DEBUG) || defined(__CYGWIN32__))
00173 setlogmask(LOG_UPTO(LOG_INFO));
00174 #endif
00175
00176
00177 status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
00178 NULL, NULL);
00179 if (status != ISC_R_SUCCESS)
00180 log_fatal("Can't initialize context: %s",
00181 isc_result_totext(status));
00182
00183
00184 status = omapi_init();
00185 if (status != ISC_R_SUCCESS)
00186 log_fatal("Can't initialize OMAPI: %s",
00187 isc_result_totext(status));
00188
00189
00190
00191 dhcp_common_objects_setup();
00192
00193 dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
00194 dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
00195 dhcp_interface_startup_hook = dhclient_interface_startup_hook;
00196
00197 for (i = 1; i < argc; i++) {
00198 if (!strcmp(argv[i], "-r")) {
00199 release_mode = 1;
00200 no_daemon = 1;
00201 #ifdef DHCPv6
00202 } else if (!strcmp(argv[i], "-4")) {
00203 if (local_family_set && local_family != AF_INET)
00204 log_fatal("Client can only do v4 or v6, not "
00205 "both.");
00206 local_family_set = 1;
00207 local_family = AF_INET;
00208 } else if (!strcmp(argv[i], "-6")) {
00209 if (local_family_set && local_family != AF_INET6)
00210 log_fatal("Client can only do v4 or v6, not "
00211 "both.");
00212 local_family_set = 1;
00213 local_family = AF_INET6;
00214 #endif
00215 } else if (!strcmp(argv[i], "-x")) {
00216 release_mode = 0;
00217 no_daemon = 0;
00218 exit_mode = 1;
00219 } else if (!strcmp(argv[i], "-p")) {
00220 if (++i == argc)
00221 usage();
00222 local_port = validate_port(argv[i]);
00223 log_debug("binding to user-specified port %d",
00224 ntohs(local_port));
00225 } else if (!strcmp(argv[i], "-d")) {
00226 no_daemon = 1;
00227 quiet = 0;
00228 } else if (!strcmp(argv[i], "-pf")) {
00229 if (++i == argc)
00230 usage();
00231 path_dhclient_pid = argv[i];
00232 no_dhclient_pid = 1;
00233 } else if (!strcmp(argv[i], "--no-pid")) {
00234 no_pid_file = ISC_TRUE;
00235 } else if (!strcmp(argv[i], "-cf")) {
00236 if (++i == argc)
00237 usage();
00238 path_dhclient_conf = argv[i];
00239 no_dhclient_conf = 1;
00240 } else if (!strcmp(argv[i], "-lf")) {
00241 if (++i == argc)
00242 usage();
00243 path_dhclient_db = argv[i];
00244 no_dhclient_db = 1;
00245 } else if (!strcmp(argv[i], "-sf")) {
00246 if (++i == argc)
00247 usage();
00248 path_dhclient_script = argv[i];
00249 no_dhclient_script = 1;
00250 } else if (!strcmp(argv[i], "-1")) {
00251 onetry = 1;
00252 } else if (!strcmp(argv[i], "-q")) {
00253 quiet = 1;
00254 } else if (!strcmp(argv[i], "-s")) {
00255 if (++i == argc)
00256 usage();
00257 server = argv[i];
00258 } else if (!strcmp(argv[i], "-g")) {
00259 if (++i == argc)
00260 usage();
00261 mockup_relay = argv[i];
00262 } else if (!strcmp(argv[i], "-nw")) {
00263 nowait = 1;
00264 } else if (!strcmp(argv[i], "-n")) {
00265
00266 interfaces_requested = -1;
00267 } else if (!strcmp(argv[i], "-w")) {
00268
00269 persist = 1;
00270 } else if (!strcmp(argv[i], "-e")) {
00271 struct string_list *tmp;
00272 if (++i == argc)
00273 usage();
00274 tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
00275 if (!tmp)
00276 log_fatal("No memory for %s", argv[i]);
00277 strcpy(tmp->string, argv[i]);
00278 tmp->next = client_env;
00279 client_env = tmp;
00280 client_env_count++;
00281 #ifdef DHCPv6
00282 } else if (!strcmp(argv[i], "-S")) {
00283 if (local_family_set && (local_family == AF_INET)) {
00284 usage();
00285 }
00286 local_family_set = 1;
00287 local_family = AF_INET6;
00288 wanted_ia_na = 0;
00289 stateless = 1;
00290 } else if (!strcmp(argv[i], "-N")) {
00291 if (local_family_set && (local_family == AF_INET)) {
00292 usage();
00293 }
00294 local_family_set = 1;
00295 local_family = AF_INET6;
00296 if (wanted_ia_na < 0) {
00297 wanted_ia_na = 0;
00298 }
00299 wanted_ia_na++;
00300 } else if (!strcmp(argv[i], "-T")) {
00301 if (local_family_set && (local_family == AF_INET)) {
00302 usage();
00303 }
00304 local_family_set = 1;
00305 local_family = AF_INET6;
00306 if (wanted_ia_na < 0) {
00307 wanted_ia_na = 0;
00308 }
00309 wanted_ia_ta++;
00310 } else if (!strcmp(argv[i], "-P")) {
00311 if (local_family_set && (local_family == AF_INET)) {
00312 usage();
00313 }
00314 local_family_set = 1;
00315 local_family = AF_INET6;
00316 if (wanted_ia_na < 0) {
00317 wanted_ia_na = 0;
00318 }
00319 wanted_ia_pd++;
00320 #endif
00321 } else if (!strcmp(argv[i], "-D")) {
00322 duid_v4 = 1;
00323 if (++i == argc)
00324 usage();
00325 if (!strcasecmp(argv[i], "LL")) {
00326 duid_type = DUID_LL;
00327 } else if (!strcasecmp(argv[i], "LLT")) {
00328 duid_type = DUID_LLT;
00329 } else {
00330 usage();
00331 }
00332 } else if (!strcmp(argv[i], "-i")) {
00333
00334 duid_v4 = 1;
00335 } else if (!strcmp(argv[i], "-I")) {
00336
00337 std_dhcid = 1;
00338 } else if (!strcmp(argv[i], "-v")) {
00339 quiet = 0;
00340 } else if (!strcmp(argv[i], "--version")) {
00341 log_info("isc-dhclient-%s", PACKAGE_VERSION);
00342 exit(0);
00343 } else if (!strcmp(argv[i], "-C")) {
00344 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00345 usage();
00346 exit(1);
00347 }
00348
00349 if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
00350 log_error("-C option dhcp-client-identifier string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
00351 exit(1);
00352 }
00353
00354 dhcp_client_identifier_arg = argv[i];
00355 } else if (!strcmp(argv[i], "-B")) {
00356 bootp_broadcast_always = 1;
00357 } else if (!strcmp(argv[i], "-H")) {
00358 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00359 usage();
00360 exit(1);
00361 }
00362
00363 if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
00364 log_error("-H option host-name string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
00365 exit(1);
00366 }
00367
00368 if (dhcp_host_name_arg != NULL) {
00369 log_error("The -H <host-name> and -F <fqdn> arguments are mutually exclusive");
00370 exit(1);
00371 }
00372
00373 dhcp_host_name_arg = argv[i];
00374 } else if (!strcmp(argv[i], "-F")) {
00375 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00376 usage();
00377 exit(1);
00378 }
00379
00380 if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
00381 log_error("-F option fqdn.fqdn string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
00382 exit(1);
00383 }
00384
00385 if (dhcp_fqdn_arg != NULL) {
00386 log_error("Only one -F <fqdn> argument can be specified");
00387 exit(1);
00388 }
00389
00390 if (dhcp_host_name_arg != NULL) {
00391 log_error("The -F <fqdn> and -H <host-name> arguments are mutually exclusive");
00392 exit(1);
00393 }
00394
00395 dhcp_fqdn_arg = argv[i];
00396 } else if (!strcmp(argv[i], "-timeout")) {
00397 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00398 usage();
00399 exit(1);
00400 }
00401
00402 if ((timeout_arg = atoi(argv[i])) <= 0) {
00403 log_error("timeout option must be > 0 - bad value: %s",argv[i]);
00404 exit(1);
00405 }
00406 } else if (!strcmp(argv[i], "-V")) {
00407 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00408 usage();
00409 exit(1);
00410 }
00411
00412 if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
00413 log_error("-V option vendor-class-identifier string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
00414 exit(1);
00415 }
00416
00417 dhcp_vendor_class_identifier_arg = argv[i];
00418 } else if (!strcmp(argv[i], "-R")) {
00419 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00420 usage();
00421 exit(1);
00422 }
00423
00424 dhclient_request_options = argv[i];
00425 } else if (!strcmp(argv[i], "-nc")) {
00426 #ifdef HAVE_LIBCAP_NG
00427 keep_capabilities = 1;
00428 #endif
00429 } else if (argv[i][0] == '-') {
00430 usage();
00431 } else if (interfaces_requested < 0) {
00432 usage();
00433 } else {
00434 struct interface_info *tmp = NULL;
00435
00436 status = interface_allocate(&tmp, MDL);
00437 if (status != ISC_R_SUCCESS)
00438 log_fatal("Can't record interface %s:%s",
00439 argv[i], isc_result_totext(status));
00440 if (strlen(argv[i]) >= sizeof(tmp->name))
00441 log_fatal("%s: interface name too long (is %ld)",
00442 argv[i], (long)strlen(argv[i]));
00443 strcpy(tmp->name, argv[i]);
00444 if (interfaces) {
00445 interface_reference(&tmp->next,
00446 interfaces, MDL);
00447 interface_dereference(&interfaces, MDL);
00448 }
00449 interface_reference(&interfaces, tmp, MDL);
00450 tmp->flags = INTERFACE_REQUESTED;
00451 interfaces_requested++;
00452 }
00453 }
00454
00455 if (wanted_ia_na < 0) {
00456 wanted_ia_na = 1;
00457 }
00458
00459
00460 if (wanted_ia_pd && (interfaces_requested != 1)) {
00461 usage();
00462 }
00463
00464 if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
00465 path_dhclient_conf = s;
00466 }
00467 if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
00468 path_dhclient_db = s;
00469 }
00470 if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
00471 path_dhclient_pid = s;
00472 }
00473 if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
00474 path_dhclient_script = s;
00475 }
00476
00477 #ifdef HAVE_LIBCAP_NG
00478
00479 if (!keep_capabilities) {
00480 capng_clear(CAPNG_SELECT_CAPS);
00481 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
00482 CAP_DAC_OVERRIDE);
00483 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
00484 CAP_NET_ADMIN, CAP_NET_RAW,
00485 CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
00486 capng_apply(CAPNG_SELECT_CAPS);
00487 }
00488 #endif
00489
00490
00491 initialize_common_option_spaces();
00492
00493
00494 if (local_family == AF_INET)
00495 dhcpv4_client_assignments();
00496 #ifdef DHCPv6
00497 else if (local_family == AF_INET6)
00498 dhcpv6_client_assignments();
00499 #endif
00500 else
00501 log_fatal("Impossible condition at %s:%d.", MDL);
00502
00503
00504
00505
00506
00507 if (path_dhclient_db[0] != '/') {
00508 const char *old_path = path_dhclient_db;
00509 path_dhclient_db = realpath(path_dhclient_db, NULL);
00510 if (path_dhclient_db == NULL)
00511 log_fatal("Failed to get realpath for %s: %s", old_path, strerror(errno));
00512 }
00513
00514 if (path_dhclient_script[0] != '/') {
00515 const char *old_path = path_dhclient_script;
00516 path_dhclient_script = realpath(path_dhclient_script, NULL);
00517 if (path_dhclient_script == NULL)
00518 log_fatal("Failed to get realpath for %s: %s", old_path, strerror(errno));
00519 }
00520
00521
00522
00523
00524
00525
00526
00527 if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
00528 FILE *pidfd;
00529 pid_t oldpid;
00530 long temp;
00531 int e;
00532
00533 if ((pidfd = fopen(path_dhclient_pid, "re")) != NULL) {
00534 e = fscanf(pidfd, "%ld\n", &temp);
00535 oldpid = (pid_t)temp;
00536
00537 if (e != 0 && e != EOF) {
00538 if (oldpid && (kill(oldpid, SIGTERM) == 0)) {
00539
00540
00541
00542
00543
00544
00545
00546 sleep(1);
00547 }
00548 }
00549 fclose(pidfd);
00550 } else {
00551
00552
00553
00554
00555 if ((path_dhclient_pid == NULL) || (*path_dhclient_pid == '\0'))
00556 path_dhclient_pid = "/var/run/dhclient.pid";
00557
00558 char *new_path_dhclient_pid;
00559 struct interface_info *ip;
00560 int pdp_len = strlen(path_dhclient_pid), pfx, dpfx;
00561
00562
00563
00564 for (pfx=pdp_len; (pfx >= 0) && (path_dhclient_pid[pfx] != '.') && (path_dhclient_pid[pfx] != '/'); pfx--);
00565 if (pfx == -1)
00566 pfx = pdp_len;
00567
00568 if (path_dhclient_pid[pfx] == '/')
00569 pfx += 1;
00570
00571 for (dpfx=pfx; (dpfx >= 0) && (path_dhclient_pid[dpfx] != '-') && (path_dhclient_pid[dpfx] != '/'); dpfx--);
00572 if ((dpfx > -1) && (path_dhclient_pid[dpfx] != '/'))
00573 pfx = dpfx;
00574
00575 for (ip = interfaces; ip; ip = ip->next) {
00576 if (interfaces_requested && (ip->flags & (INTERFACE_REQUESTED))) {
00577 int n_len = strlen(ip->name);
00578
00579 new_path_dhclient_pid = (char*) malloc(pfx + n_len + 6);
00580 strncpy(new_path_dhclient_pid, path_dhclient_pid, pfx);
00581 sprintf(new_path_dhclient_pid + pfx, "-%s.pid", ip->name);
00582
00583 if ((pidfd = fopen(new_path_dhclient_pid, "re")) != NULL) {
00584 e = fscanf(pidfd, "%ld\n", &temp);
00585 oldpid = (pid_t)temp;
00586
00587 if (e != 0 && e != EOF) {
00588 if (oldpid) {
00589 if (kill(oldpid, SIGTERM) == 0)
00590 unlink(path_dhclient_pid);
00591 }
00592 }
00593
00594 fclose(pidfd);
00595 }
00596
00597 free(new_path_dhclient_pid);
00598 }
00599 }
00600 }
00601 } else {
00602 FILE *pidfp = NULL;
00603 long temp = 0;
00604 pid_t dhcpid = 0;
00605 int dhc_running = 0;
00606 char procfn[256] = "";
00607
00608 if ((pidfp = fopen(path_dhclient_pid, "re")) != NULL) {
00609 if ((fscanf(pidfp, "%ld", &temp)==1) && ((dhcpid=(pid_t)temp) > 0)) {
00610 snprintf(procfn,256,"/proc/%u",dhcpid);
00611 dhc_running = (access(procfn, F_OK) == 0);
00612 }
00613
00614 fclose(pidfp);
00615 }
00616
00617 if (dhc_running) {
00618 log_fatal("dhclient(%u) is already running - exiting. ", dhcpid);
00619 return(1);
00620 }
00621 }
00622
00623 write_client_pid_file();
00624
00625 if (!quiet) {
00626 log_info("%s %s", message, PACKAGE_VERSION);
00627 log_info(copyright);
00628 log_info(arr);
00629 log_info(url);
00630 log_info("%s", "");
00631 } else {
00632 log_perror = 0;
00633 quiet_interface_discovery = 1;
00634 }
00635
00636
00637
00638 if (mockup_relay) {
00639 if (!inet_aton(mockup_relay, &giaddr)) {
00640 struct hostent *he;
00641 he = gethostbyname(mockup_relay);
00642 if (he) {
00643 memcpy(&giaddr, he->h_addr_list[0],
00644 sizeof giaddr);
00645 } else {
00646 log_fatal("%s: no such host", mockup_relay);
00647 }
00648 }
00649 }
00650
00651
00652 gettimeofday(&cur_tv, NULL);
00653
00654 sockaddr_broadcast.sin_family = AF_INET;
00655 sockaddr_broadcast.sin_port = remote_port;
00656 if (server) {
00657 if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
00658 struct hostent *he;
00659 he = gethostbyname(server);
00660 if (he) {
00661 memcpy(&sockaddr_broadcast.sin_addr,
00662 he->h_addr_list[0],
00663 sizeof sockaddr_broadcast.sin_addr);
00664 } else
00665 sockaddr_broadcast.sin_addr.s_addr =
00666 INADDR_BROADCAST;
00667 }
00668 } else {
00669 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
00670 }
00671
00672 inaddr_any.s_addr = INADDR_ANY;
00673
00674
00675 if (stateless) {
00676 if (release_mode || (wanted_ia_na > 0) ||
00677 wanted_ia_ta || wanted_ia_pd ||
00678 (interfaces_requested != 1)) {
00679 usage();
00680 }
00681 run_stateless(exit_mode);
00682 return 0;
00683 }
00684
00685
00686 discover_interfaces(DISCOVER_UNCONFIGURED);
00687
00688
00689 read_client_conf();
00690
00691
00692 if ((dhcp_client_identifier_arg != NULL) && (*dhcp_client_identifier_arg != '\0')) {
00693 arg_conf_len = asprintf(&arg_conf, "send dhcp-client-identifier \"%s\";", dhcp_client_identifier_arg);
00694
00695 if ((arg_conf == 0) || (arg_conf_len <= 0))
00696 log_fatal("Unable to send -C option dhcp-client-identifier");
00697 }
00698
00699 if ((dhcp_host_name_arg != NULL) && (*dhcp_host_name_arg != '\0')) {
00700 if (arg_conf == 0) {
00701 arg_conf_len = asprintf(&arg_conf, "send host-name \"%s\";", dhcp_host_name_arg);
00702
00703 if ((arg_conf == 0) || (arg_conf_len <= 0))
00704 log_fatal("Unable to send -H option host-name");
00705 } else {
00706 char *last_arg_conf = arg_conf;
00707 arg_conf = NULL;
00708 arg_conf_len = asprintf(&arg_conf, "%s\nsend host-name \"%s\";", last_arg_conf, dhcp_host_name_arg);
00709
00710 if ((arg_conf == 0) || (arg_conf_len <= 0))
00711 log_fatal("Unable to send -H option host-name");
00712
00713 free(last_arg_conf);
00714 }
00715 }
00716
00717 if ((dhcp_fqdn_arg != NULL) && (*dhcp_fqdn_arg != '\0')) {
00718 if (arg_conf == 0) {
00719 arg_conf_len = asprintf(&arg_conf, "send fqdn.fqdn \"%s\";", dhcp_fqdn_arg);
00720
00721 if ((arg_conf == 0) || (arg_conf_len <= 0))
00722 log_fatal("Unable to send -F option fqdn.fqdn");
00723 } else {
00724 char *last_arg_conf = arg_conf;
00725 arg_conf = NULL;
00726 arg_conf_len = asprintf(&arg_conf, "%s\nsend fqdn.fqdn \"%s\";", last_arg_conf, dhcp_fqdn_arg);
00727
00728 if ((arg_conf == 0) || (arg_conf_len <= 0))
00729 log_fatal("Unable to send -F option fqdn.fqdn");
00730
00731 free(last_arg_conf);
00732 }
00733 }
00734
00735 if (timeout_arg) {
00736 if (arg_conf == 0) {
00737 arg_conf_len = asprintf(&arg_conf, "timeout %d;", timeout_arg);
00738
00739 if ((arg_conf == 0) || (arg_conf_len <= 0))
00740 log_fatal("Unable to process -timeout timeout argument");
00741 } else {
00742 char *last_arg_conf = arg_conf;
00743 arg_conf = NULL;
00744 arg_conf_len = asprintf(&arg_conf, "%s\ntimeout %d;", last_arg_conf, timeout_arg);
00745
00746 if ((arg_conf == 0) || (arg_conf_len == 0))
00747 log_fatal("Unable to process -timeout timeout argument");
00748
00749 free(last_arg_conf);
00750 }
00751 }
00752
00753 if ((dhcp_vendor_class_identifier_arg != NULL) && (*dhcp_vendor_class_identifier_arg != '\0')) {
00754 if (arg_conf == 0) {
00755 arg_conf_len = asprintf(&arg_conf, "send vendor-class-identifier \"%s\";", dhcp_vendor_class_identifier_arg);
00756
00757 if ((arg_conf == 0) || (arg_conf_len <= 0))
00758 log_fatal("Unable to send -V option vendor-class-identifier");
00759 } else {
00760 char *last_arg_conf = arg_conf;
00761 arg_conf = NULL;
00762 arg_conf_len = asprintf(&arg_conf, "%s\nsend vendor-class-identifier \"%s\";", last_arg_conf, dhcp_vendor_class_identifier_arg);
00763
00764 if ((arg_conf == 0) || (arg_conf_len <= 0))
00765 log_fatal("Unable to send -V option vendor-class-identifier");
00766
00767 free(last_arg_conf);
00768 }
00769 }
00770
00771 if (dhclient_request_options != NULL) {
00772 if (arg_conf == 0) {
00773 arg_conf_len = asprintf(&arg_conf, "request %s;", dhclient_request_options);
00774
00775 if ((arg_conf == 0) || (arg_conf_len <= 0))
00776 log_fatal("Unable to parse -R <request options list> argument");
00777 } else {
00778 char *last_arg_conf = arg_conf;
00779 arg_conf = NULL;
00780 arg_conf_len = asprintf(&arg_conf, "%s\nrequest %s;", last_arg_conf, dhclient_request_options);
00781
00782 if ((arg_conf == 0) || (arg_conf_len <= 0))
00783 log_fatal("Unable to parse -R <request options list> argument");
00784
00785 free(last_arg_conf);
00786 }
00787 }
00788
00789 if (arg_conf) {
00790 if (arg_conf_len == 0)
00791 if ((arg_conf_len = strlen(arg_conf)) == 0)
00792
00793 log_fatal("Unable to process -C/-H/-F/-timeout/-V/-R configuration arguments");
00794
00795
00796
00797 struct parse *cfile = (struct parse *)0;
00798 const char *val = NULL;
00799 int token;
00800
00801 status = new_parse(&cfile, -1, arg_conf, arg_conf_len, "extra dhclient -C/-H/-F/-timeout/-V/-R configuration arguments", 0);
00802
00803 if ((status != ISC_R_SUCCESS) || (cfile -> warnings_occurred))
00804 log_fatal("Cannot parse -C/-H/-F/-timeout/-V/-R configuration arguments !");
00805
00806
00807 do {
00808 token = peek_token(&val, (unsigned *)0, cfile);
00809 if (token == END_OF_FILE)
00810 break;
00811
00812 parse_client_statement(cfile, (struct interface_info *)0, &top_level_config);
00813 } while (1);
00814
00815 if (cfile -> warnings_occurred)
00816 log_fatal("Cannot parse -C/-H/-F/-timeout/-V/-R configuration arguments !");
00817 end_parse(&cfile);
00818
00819 if (timeout_arg) {
00820
00821
00822
00823 for (ip=interfaces; ip; ip = ip->next) {
00824 if (ip->client->config->timeout == 60)
00825 ip->client->config->timeout = timeout_arg;
00826 }
00827 }
00828
00829 if ((dhclient_request_options != 0) && (top_level_config.requested_options != default_requested_options)) {
00830 for (ip=interfaces; ip; ip = ip->next) {
00831 if (ip->client->config->requested_options == default_requested_options)
00832 ip->client->config->requested_options = top_level_config.requested_options;
00833 }
00834 }
00835
00836 free(arg_conf);
00837 arg_conf = NULL;
00838 arg_conf_len = 0;
00839 }
00840
00841
00842 read_client_leases();
00843
00844
00845 rewrite_client_leases();
00846
00847
00848
00849
00850
00851
00852
00853
00854 if (!interfaces) {
00855
00856
00857
00858
00859 script_init(NULL, "NBI", NULL);
00860 script_go(NULL);
00861
00862
00863
00864
00865
00866 if (!persist) {
00867
00868 log_info("No broadcast interfaces found - exiting.");
00869 exit(0);
00870 }
00871 } else if (!release_mode && !exit_mode) {
00872
00873 for (ip = interfaces; ip; ip = ip->next) {
00874
00875
00876
00877
00878 if ((interfaces_requested > 0) &&
00879 ((ip->flags & (INTERFACE_REQUESTED |
00880 INTERFACE_AUTOMATIC)) !=
00881 INTERFACE_REQUESTED))
00882 continue;
00883
00884 if (local_family == AF_INET6) {
00885 script_init(ip->client, "PREINIT6", NULL);
00886 } else {
00887 script_init(ip->client, "PREINIT", NULL);
00888 if (ip->client->alias != NULL)
00889 script_write_params(ip->client,
00890 "alias_",
00891 ip->client->alias);
00892 }
00893 script_go(ip->client);
00894 }
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 unsigned backup_seed = 0;
00906 for (ip = interfaces; ip; ip = ip -> next) {
00907 int junk;
00908 if ( ip -> hw_address.hlen <= sizeof seed )
00909 continue;
00910 memcpy (&junk,
00911 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
00912 sizeof seed], sizeof seed);
00913 backup_seed = junk;
00914 }
00915
00916
00917
00918
00919
00920
00921 discover_interfaces(interfaces_requested != 0
00922 ? DISCOVER_REQUESTED
00923 : DISCOVER_RUNNING);
00924
00925
00926
00927
00928
00929
00930 seed = 0;
00931 int seed_flag = 0;
00932 for (ip = interfaces; ip; ip = ip->next) {
00933 int junk;
00934 if ( ip -> hw_address.hlen <= sizeof seed )
00935 continue;
00936 memcpy(&junk,
00937 &ip->hw_address.hbuf[ip->hw_address.hlen -
00938 sizeof seed], sizeof seed);
00939 seed += junk;
00940 seed_flag = 1;
00941 }
00942 if ( seed_flag == 0 ) {
00943 if ( backup_seed != 0 ) {
00944 seed = backup_seed;
00945 log_info ("xid: rand init seed (0x%x) built using all"
00946 " available interfaces",seed);
00947 }
00948 else {
00949 seed = cur_time^((unsigned) gethostid()) ;
00950 log_info ("xid: warning: no netdev with useable HWADDR found"
00951 " for seed's uniqueness enforcement");
00952 log_info ("xid: rand init seed (0x%x) built using gethostid",
00953 seed);
00954 }
00955
00956
00957 srandom(seed);
00958 }
00959 else
00960 srandom(seed + cur_time + (unsigned)getpid());
00961
00962
00963 for (ip = interfaces; ip; ip = ip->next) {
00964 if (ip->client &&
00965 (ip->hw_address.hbuf[0] == HTYPE_INFINIBAND)) {
00966 setup_ib_interface(ip);
00967 }
00968 }
00969
00970
00971
00972
00973
00974 if ((local_family == AF_INET6) ||
00975 ((local_family == AF_INET) && (duid_v4 == 1))) {
00976 if (default_duid.len == 0) {
00977 if (default_duid.buffer != NULL)
00978 data_string_forget(&default_duid, MDL);
00979
00980 if (form_duid(&default_duid, MDL) == ISC_R_SUCCESS)
00981 write_duid(&default_duid);
00982 }
00983 }
00984
00985
00986 #ifdef DHCPv6
00987 if (local_family == AF_INET6) {
00988 for (ip = interfaces ; ip != NULL ; ip = ip->next) {
00989 for (client = ip->client ; client != NULL ;
00990 client = client->next) {
00991 if (release_mode) {
00992 start_release6(client);
00993 continue;
00994 } else if (exit_mode) {
00995 unconfigure6(client, "STOP6");
00996 continue;
00997 }
00998
00999
01000
01001
01002 if ((client->active_lease != NULL) &&
01003 !client->active_lease->released)
01004 start_confirm6(client);
01005 else
01006 start_init6(client);
01007 }
01008 }
01009 } else
01010 #endif
01011 {
01012 for (ip = interfaces ; ip ; ip = ip->next) {
01013 ip->flags |= INTERFACE_RUNNING;
01014 for (client = ip->client ; client ;
01015 client = client->next) {
01016 if (exit_mode)
01017 state_stop(client);
01018 else if (release_mode)
01019 do_release(client);
01020 else {
01021 client->state = S_INIT;
01022
01023 if (top_level_config.initial_delay>0)
01024 {
01025 tv.tv_sec = 0;
01026 if (top_level_config.
01027 initial_delay>1)
01028 tv.tv_sec = cur_time
01029 + random()
01030 % (top_level_config.
01031 initial_delay-1);
01032 tv.tv_usec = random()
01033 % 1000000;
01034
01035
01036
01037
01038
01039 add_timeout(&tv, state_reboot,
01040 client, 0, 0);
01041 } else {
01042 state_reboot(client);
01043 }
01044 }
01045 }
01046 }
01047 }
01048
01049 if (exit_mode)
01050 return 0;
01051 if (release_mode) {
01052 #ifndef DHCPv6
01053 return 0;
01054 #else
01055 if (local_family == AF_INET6) {
01056 if (onetry)
01057 return 0;
01058 } else
01059 return 0;
01060 #endif
01061 }
01062
01063
01064 if (top_level_config.omapi_port != -1) {
01065 listener = NULL;
01066 result = omapi_generic_new(&listener, MDL);
01067 if (result != ISC_R_SUCCESS)
01068 log_fatal("Can't allocate new generic object: %s\n",
01069 isc_result_totext(result));
01070 result = omapi_protocol_listen(listener,
01071 (unsigned)
01072 top_level_config.omapi_port,
01073 1);
01074 if (result != ISC_R_SUCCESS)
01075 log_fatal("Can't start OMAPI protocol: %s",
01076 isc_result_totext (result));
01077 }
01078
01079
01080 bootp_packet_handler = do_packet;
01081 #ifdef DHCPv6
01082 dhcpv6_packet_handler = do_packet6;
01083 #endif
01084
01085 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
01086 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
01087 dmalloc_cutoff_generation = dmalloc_generation;
01088 dmalloc_longterm = dmalloc_outstanding;
01089 dmalloc_outstanding = 0;
01090 #endif
01091
01092
01093 signal(SIGINT, dhcp_signal_handler);
01094 signal(SIGTERM, dhcp_signal_handler);
01095
01096
01097
01098 if (nowait)
01099 go_daemon();
01100
01101
01102
01103 if (no_daemon || nowait)
01104 write_client_pid_file();
01105
01106
01107 dispatch();
01108
01109
01110 return 0;
01111 }
01112
01113 static void usage()
01114 {
01115 log_info("%s %s", message, PACKAGE_VERSION);
01116 log_info(copyright);
01117 log_info(arr);
01118 log_info(url);
01119
01120
01121 log_fatal("Usage: dhclient "
01122 #ifdef DHCPv6
01123 "[-4|-6] [-SNTPI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
01124 #else
01125 "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
01126 #endif
01127 " [-s server-addr] [-cf config-file] "
01128 "[-lf lease-file]\n"
01129 " [-pf pid-file] [--no-pid] [-e VAR=val]\n"
01130 " [-C <dhcp-client-identifier>] [-B]\n"
01131 " [-H <host-name> | -F <fqdn.fqdn>] [-timeout <timeout>]\n"
01132 " [-V <vendor-class-identifier>]\n"
01133 " [-R <request option list>]\n"
01134 " [-sf script-file] [interface]");
01135 }
01136
01137 void run_stateless(int exit_mode)
01138 {
01139 #ifdef DHCPv6
01140 struct client_state *client;
01141 omapi_object_t *listener;
01142 isc_result_t result;
01143
01144
01145 discover_interfaces(DISCOVER_REQUESTED);
01146
01147 if (!interfaces)
01148 usage();
01149
01150
01151 read_client_conf();
01152
01153
01154 read_client_leases();
01155
01156
01157 if (default_duid.len == 0) {
01158 if (default_duid.buffer != NULL)
01159 data_string_forget(&default_duid, MDL);
01160
01161 form_duid(&default_duid, MDL);
01162 }
01163
01164
01165 for (client = interfaces->client ;
01166 client != NULL ;
01167 client = client->next) {
01168 if (exit_mode) {
01169 unconfigure6(client, "STOP6");
01170 continue;
01171 }
01172 start_info_request6(client);
01173 }
01174 if (exit_mode)
01175 return;
01176
01177
01178 if (top_level_config.omapi_port != -1) {
01179 listener = NULL;
01180 result = omapi_generic_new(&listener, MDL);
01181 if (result != ISC_R_SUCCESS)
01182 log_fatal("Can't allocate new generic object: %s\n",
01183 isc_result_totext(result));
01184 result = omapi_protocol_listen(listener,
01185 (unsigned)
01186 top_level_config.omapi_port,
01187 1);
01188 if (result != ISC_R_SUCCESS)
01189 log_fatal("Can't start OMAPI protocol: %s",
01190 isc_result_totext(result));
01191 }
01192
01193
01194 dhcpv6_packet_handler = do_packet6;
01195
01196 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
01197 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
01198 dmalloc_cutoff_generation = dmalloc_generation;
01199 dmalloc_longterm = dmalloc_outstanding;
01200 dmalloc_outstanding = 0;
01201 #endif
01202
01203
01204
01205 if (nowait)
01206 go_daemon();
01207
01208
01209
01210 if (no_daemon || nowait)
01211 write_client_pid_file();
01212
01213
01214 dispatch();
01215
01216 #endif
01217 return;
01218 }
01219
01220 isc_result_t find_class (struct class **c,
01221 const char *s, const char *file, int line)
01222 {
01223 return 0;
01224 }
01225
01226 int check_collection (packet, lease, collection)
01227 struct packet *packet;
01228 struct lease *lease;
01229 struct collection *collection;
01230 {
01231 return 0;
01232 }
01233
01234 void classify (packet, class)
01235 struct packet *packet;
01236 struct class *class;
01237 {
01238 }
01239
01240 int unbill_class (lease, class)
01241 struct lease *lease;
01242 struct class *class;
01243 {
01244 return 0;
01245 }
01246
01247 int find_subnet (struct subnet **sp,
01248 struct iaddr addr, const char *file, int line)
01249 {
01250 return 0;
01251 }
01252
01253 static void setup_ib_interface(struct interface_info *ip)
01254 {
01255 struct group *g;
01256
01257
01258 ip->client->config->bootp_broadcast_always = 1;
01259
01260
01261
01262
01263
01264 for (g = ip->client->config->on_transmission; g != NULL; g = g->next) {
01265 if ((g->statements != NULL) &&
01266 (strcmp(g->statements->data.option->option->name,
01267 "dhcp-client-identifier") == 0)) {
01268 return;
01269 }
01270 }
01271
01272
01273
01274 }
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305 void state_reboot (cpp)
01306 void *cpp;
01307 {
01308 struct client_state *client = cpp;
01309
01310
01311 if (!client -> active ||
01312 client -> active -> is_bootp ||
01313 client -> active -> expiry <= cur_time) {
01314 state_init (client);
01315 return;
01316 }
01317
01318
01319 client -> state = S_REBOOTING;
01320
01321
01322
01323
01324
01325
01326 client -> xid = random ();
01327
01328
01329
01330
01331
01332 make_request (client, client -> active);
01333 client -> destination = iaddr_broadcast;
01334 client -> first_sending = cur_time;
01335 client -> interval = client -> config -> initial_interval;
01336
01337
01338 client -> medium = NULL;
01339
01340
01341 send_request (client);
01342 }
01343
01344
01345
01346
01347 void state_init (cpp)
01348 void *cpp;
01349 {
01350 struct client_state *client = cpp;
01351 enum dhcp_state init_state = client->state;
01352 struct timeval tv;
01353
01354 ASSERT_STATE(state, S_INIT);
01355
01356
01357
01358 make_discover (client, client -> active);
01359 client -> xid = client -> packet.xid;
01360 client -> destination = iaddr_broadcast;
01361 client -> state = S_SELECTING;
01362 client -> first_sending = cur_time;
01363 client -> interval = client -> config -> initial_interval;
01364
01365 if (init_state != S_DECLINED) {
01366
01367
01368 send_discover(client);
01369 } else {
01370
01371
01372
01373 tv . tv_sec = cur_time + ((1 + (random() >> 2)) % client->config->backoff_cutoff);
01374 tv . tv_usec = 0;
01375 add_timeout(&tv, send_discover, client, 0, 0);
01376 }
01377 }
01378
01379
01380
01381
01382
01383
01384 void state_selecting (cpp)
01385 void *cpp;
01386 {
01387 struct client_state *client = cpp;
01388 struct client_lease *lp, *next, *picked;
01389
01390
01391 ASSERT_STATE(state, S_SELECTING);
01392
01393
01394
01395
01396
01397 cancel_timeout (state_selecting, client);
01398 cancel_timeout (send_discover, client);
01399
01400
01401
01402
01403
01404
01405 picked = NULL;
01406 for (lp = client -> offered_leases; lp; lp = next) {
01407 next = lp -> next;
01408
01409
01410
01411
01412
01413 if (!picked) {
01414 picked = lp;
01415 picked -> next = NULL;
01416 } else {
01417 destroy_client_lease (lp);
01418 }
01419 }
01420 client -> offered_leases = NULL;
01421
01422
01423
01424
01425
01426 if (!picked) {
01427 client -> state = S_INIT;
01428 state_init (client);
01429 return;
01430 }
01431
01432
01433 if (picked -> is_bootp) {
01434 client -> new = picked;
01435
01436
01437
01438 client -> new -> expiry = cur_time + 12000;
01439 client -> new -> renewal += cur_time + 8000;
01440 client -> new -> rebind += cur_time + 10000;
01441
01442 client -> state = S_REQUESTING;
01443
01444
01445 bind_lease (client, NULL);
01446 return;
01447 }
01448
01449
01450 client -> destination = iaddr_broadcast;
01451 client -> state = S_REQUESTING;
01452 client -> first_sending = cur_time;
01453 client -> interval = client -> config -> initial_interval;
01454
01455
01456 make_request (client, picked);
01457 client -> xid = client -> packet.xid;
01458
01459
01460 destroy_client_lease (picked);
01461
01462
01463 send_request (client);
01464 }
01465
01466
01467
01468
01469 void dhcpack (packet)
01470 struct packet *packet;
01471 {
01472 struct interface_info *ip = packet -> interface;
01473 struct client_state *client;
01474 struct client_lease *lease;
01475 struct option_cache *oc;
01476 struct data_string ds;
01477
01478
01479
01480 for (client = ip -> client; client; client = client -> next) {
01481 if (client -> xid == packet -> raw -> xid)
01482 break;
01483 }
01484 if (!client ||
01485 (packet -> interface -> hw_address.hlen - 1 !=
01486 packet -> raw -> hlen) ||
01487 (memcmp (&packet -> interface -> hw_address.hbuf [1],
01488 packet -> raw -> chaddr, packet -> raw -> hlen))) {
01489 #if defined (DEBUG)
01490 log_debug ("DHCPACK in wrong transaction.");
01491 #endif
01492 return;
01493 }
01494
01495 if (client -> state != S_REBOOTING &&
01496 client -> state != S_REQUESTING &&
01497 client -> state != S_RENEWING &&
01498 client -> state != S_REBINDING) {
01499 #if defined (DEBUG)
01500 log_debug ("DHCPACK in wrong state.");
01501 #endif
01502 return;
01503 }
01504
01505 log_info ("DHCPACK from %s (xid=0x%x)", piaddr (packet -> client_addr), client -> xid);
01506
01507 lease = packet_to_lease (packet, client);
01508 if (!lease) {
01509 log_info ("packet_to_lease failed.");
01510 return;
01511 }
01512
01513 client -> new = lease;
01514
01515
01516 cancel_timeout (send_request, client);
01517
01518
01519 oc = lookup_option (&dhcp_universe, client -> new -> options,
01520 DHO_DHCP_LEASE_TIME);
01521 memset (&ds, 0, sizeof ds);
01522 if (oc &&
01523 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
01524 packet -> options, client -> new -> options,
01525 &global_scope, oc, MDL)) {
01526 if (ds.len > 3)
01527 client -> new -> expiry = getULong (ds.data);
01528 else
01529 client -> new -> expiry = 0;
01530 data_string_forget (&ds, MDL);
01531 } else
01532 client -> new -> expiry = 0;
01533
01534 if (client->new->expiry == 0) {
01535 struct timeval tv;
01536
01537 log_error ("no expiry time on offered lease.");
01538
01539
01540 add_reject(packet);
01541
01542
01543 tv.tv_sec = cur_tv.tv_sec;
01544 tv.tv_usec = cur_tv.tv_usec + 500000;
01545
01546 if (tv.tv_usec >= 1000000) {
01547 tv.tv_sec++;
01548 tv.tv_usec -= 1000000;
01549 }
01550
01551 add_timeout(&tv, state_init, client, 0, 0);
01552 return;
01553 }
01554
01555
01556
01557
01558
01559 if (client->new->expiry < 0)
01560 client->new->expiry = TIME_MAX;
01561
01562
01563 oc = lookup_option (&dhcp_universe, client -> new -> options,
01564 DHO_DHCP_RENEWAL_TIME);
01565 if (oc &&
01566 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
01567 packet -> options, client -> new -> options,
01568 &global_scope, oc, MDL)) {
01569 if (ds.len > 3)
01570 client -> new -> renewal = getULong (ds.data);
01571 else
01572 client -> new -> renewal = 0;
01573 data_string_forget (&ds, MDL);
01574 } else
01575 client -> new -> renewal = 0;
01576
01577
01578 if (!client -> new -> renewal)
01579 client -> new -> renewal = client -> new -> expiry / 2 + 1;
01580
01581 if (client -> new -> renewal <= 0)
01582 client -> new -> renewal = TIME_MAX;
01583
01584
01585 if (client->new->renewal <= ((TIME_MAX / 3) - 3))
01586 client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
01587 (((random() % client->new->renewal) + 3) / 4);
01588
01589
01590 oc = lookup_option (&dhcp_universe, client -> new -> options,
01591 DHO_DHCP_REBINDING_TIME);
01592 if (oc &&
01593 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
01594 packet -> options, client -> new -> options,
01595 &global_scope, oc, MDL)) {
01596 if (ds.len > 3)
01597 client -> new -> rebind = getULong (ds.data);
01598 else
01599 client -> new -> rebind = 0;
01600 data_string_forget (&ds, MDL);
01601 } else
01602 client -> new -> rebind = 0;
01603
01604 if (client -> new -> rebind <= 0) {
01605 if (client -> new -> expiry <= TIME_MAX / 7)
01606 client -> new -> rebind =
01607 client -> new -> expiry * 7 / 8;
01608 else
01609 client -> new -> rebind =
01610 client -> new -> expiry / 8 * 7;
01611 }
01612
01613
01614
01615 if (client -> new -> renewal > client -> new -> rebind) {
01616 if (client -> new -> rebind <= TIME_MAX / 3)
01617 client -> new -> renewal =
01618 client -> new -> rebind * 3 / 4;
01619 else
01620 client -> new -> renewal =
01621 client -> new -> rebind / 4 * 3;
01622 }
01623
01624 client -> new -> expiry += cur_time;
01625
01626 if (client -> new -> expiry < cur_time)
01627 client -> new -> expiry = TIME_MAX;
01628 client -> new -> renewal += cur_time;
01629 if (client -> new -> renewal < cur_time)
01630 client -> new -> renewal = TIME_MAX;
01631 client -> new -> rebind += cur_time;
01632 if (client -> new -> rebind < cur_time)
01633 client -> new -> rebind = TIME_MAX;
01634
01635 bind_lease (client, &packet -> raw -> siaddr);
01636 }
01637
01638 void bind_lease (client, siaddr)
01639 struct client_state *client;
01640 struct in_addr *siaddr;
01641 {
01642 struct timeval tv;
01643
01644
01645 client -> new -> medium = client -> medium;
01646
01647
01648 script_init (client, (client -> state == S_REQUESTING
01649 ? "BOUND"
01650 : (client -> state == S_RENEWING
01651 ? "RENEW"
01652 : (client -> state == S_REBOOTING
01653 ? "REBOOT" : "REBIND"))),
01654 client -> new -> medium);
01655 if (client -> active && client -> state != S_REBOOTING)
01656 script_write_params (client, "old_", client -> active);
01657 script_write_params (client, "new_", client -> new);
01658 script_write_requested(client);
01659 if (client -> alias)
01660 script_write_params (client, "alias_", client -> alias);
01661
01662 if (siaddr) {
01663 char buf[INET_ADDRSTRLEN];
01664
01665 if (inet_ntop (AF_INET, (void *) siaddr, buf, sizeof (buf)))
01666 client_envadd (client, "new_", "next_server", "%s", buf);
01667 }
01668
01669
01670
01671
01672 if (script_go (client)) {
01673 make_decline (client, client -> new);
01674 send_decline (client);
01675 if (onetry) {
01676 if (!quiet)
01677 log_info ("Unable to obtain a lease on first try.%s",
01678 " Exiting.");
01679 exit (2);
01680 } else {
01681 destroy_client_lease (client -> new);
01682 client -> new = (struct client_lease *)0;
01683 client -> state = S_DECLINED;
01684 state_init (client);
01685 return;
01686 }
01687 }
01688
01689
01690 if (!client->last_write ||
01691 (cur_time - client->last_write) >= MIN_LEASE_WRITE)
01692 write_client_lease(client, client->new, 0, 0);
01693
01694
01695 if (client -> active)
01696 destroy_client_lease (client -> active);
01697 client -> active = client -> new;
01698 client -> new = (struct client_lease *)0;
01699
01700
01701 tv.tv_sec = client->active->renewal;
01702 tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
01703 random() % 1000000 : cur_tv.tv_usec;
01704 add_timeout(&tv, state_bound, client, 0, 0);
01705
01706 log_info ("bound to %s -- renewal in %ld seconds.",
01707 piaddr (client -> active -> address),
01708 (long)(client -> active -> renewal - cur_time));
01709 client -> state = S_BOUND;
01710 reinitialize_interfaces ();
01711 go_daemon ();
01712 #if defined (NSUPDATE)
01713 if (client->config->do_forward_update)
01714 dhclient_schedule_updates(client, &client->active->address, 1);
01715 #endif
01716 }
01717
01718
01719
01720
01721
01722
01723 void state_bound (cpp)
01724 void *cpp;
01725 {
01726 struct client_state *client = cpp;
01727 struct option_cache *oc;
01728 struct data_string ds;
01729
01730 ASSERT_STATE(state, S_BOUND);
01731
01732
01733 make_request (client, client -> active);
01734 client -> xid = client -> packet.xid;
01735
01736 memset (&ds, 0, sizeof ds);
01737 oc = lookup_option (&dhcp_universe, client -> active -> options,
01738 DHO_DHCP_SERVER_IDENTIFIER);
01739 if (oc &&
01740 evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
01741 client, (struct option_state *)0,
01742 client -> active -> options,
01743 &global_scope, oc, MDL)) {
01744 if (ds.len > 3) {
01745 memcpy (client -> destination.iabuf, ds.data, 4);
01746 client -> destination.len = 4;
01747 } else
01748 client -> destination = iaddr_broadcast;
01749
01750 data_string_forget (&ds, MDL);
01751 } else
01752 client -> destination = iaddr_broadcast;
01753
01754 client -> first_sending = cur_time;
01755 client -> interval = client -> config -> initial_interval;
01756 client -> state = S_RENEWING;
01757
01758
01759 send_request (client);
01760 }
01761
01762
01763
01764
01765 void state_stop (cpp)
01766 void *cpp;
01767 {
01768 struct client_state *client = cpp;
01769
01770
01771 cancel_timeout(state_selecting, client);
01772 cancel_timeout(send_discover, client);
01773 cancel_timeout(send_request, client);
01774 cancel_timeout(state_bound, client);
01775
01776
01777 if (client->active) {
01778 script_init(client, "STOP", client->active->medium);
01779 script_write_params(client, "old_", client->active);
01780 script_write_requested(client);
01781 if (client->alias)
01782 script_write_params(client, "alias_", client->alias);
01783 script_go(client);
01784 }
01785 }
01786
01787 int commit_leases ()
01788 {
01789 return 0;
01790 }
01791
01792 int write_lease (lease)
01793 struct lease *lease;
01794 {
01795 return 0;
01796 }
01797
01798 int write_host (host)
01799 struct host_decl *host;
01800 {
01801 return 0;
01802 }
01803
01804 void bootp (packet)
01805 struct packet *packet;
01806 {
01807 struct iaddrmatchlist *ap;
01808 char addrbuf[4*16];
01809 char maskbuf[4*16];
01810
01811 if (packet -> raw -> op != BOOTREPLY)
01812 return;
01813
01814
01815
01816 for (ap = packet -> interface -> client -> config -> reject_list;
01817 ap; ap = ap -> next) {
01818 if (addr_match(&packet->client_addr, &ap->match)) {
01819
01820
01821
01822
01823 strcpy(addrbuf, piaddr(ap->match.addr));
01824 strcpy(maskbuf, piaddr(ap->match.mask));
01825
01826 log_info("BOOTREPLY from %s rejected by rule %s "
01827 "mask %s.", piaddr(packet->client_addr),
01828 addrbuf, maskbuf);
01829 return;
01830 }
01831 }
01832
01833 dhcpoffer (packet);
01834
01835 }
01836
01837 void dhcp (packet)
01838 struct packet *packet;
01839 {
01840 struct iaddrmatchlist *ap;
01841 void (*handler) (struct packet *);
01842 const char *type;
01843 char addrbuf[4*16];
01844 char maskbuf[4*16];
01845
01846 switch (packet -> packet_type) {
01847 case DHCPOFFER:
01848 handler = dhcpoffer;
01849 type = "DHCPOFFER";
01850 break;
01851
01852 case DHCPNAK:
01853 handler = dhcpnak;
01854 type = "DHCPNACK";
01855 break;
01856
01857 case DHCPACK:
01858 handler = dhcpack;
01859 type = "DHCPACK";
01860 break;
01861
01862 default:
01863 return;
01864 }
01865
01866
01867
01868 for (ap = packet -> interface -> client -> config -> reject_list;
01869 ap; ap = ap -> next) {
01870 if (addr_match(&packet->client_addr, &ap->match)) {
01871
01872
01873
01874
01875 strcpy(addrbuf, piaddr(ap->match.addr));
01876 strcpy(maskbuf, piaddr(ap->match.mask));
01877
01878 log_info("%s from %s rejected by rule %s mask %s.",
01879 type, piaddr(packet->client_addr),
01880 addrbuf, maskbuf);
01881 return;
01882 }
01883 }
01884 (*handler) (packet);
01885 }
01886
01887 #ifdef DHCPv6
01888 void
01889 dhcpv6(struct packet *packet) {
01890 struct iaddrmatchlist *ap;
01891 struct client_state *client;
01892 char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
01893
01894
01895 if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
01896 return;
01897
01898
01899 for (ap = packet->interface->client->config->reject_list ;
01900 ap ; ap = ap->next) {
01901 if (addr_match(&packet->client_addr, &ap->match)) {
01902 strcpy(addrbuf, piaddr(packet->client_addr));
01903 log_info("%s from %s rejected by rule %s",
01904 dhcpv6_type_names[packet->dhcpv6_msg_type],
01905 addrbuf,
01906 piaddrmask(&ap->match.addr, &ap->match.mask));
01907 return;
01908 }
01909 }
01910
01911
01912 switch(packet->dhcpv6_msg_type) {
01913 case DHCPV6_ADVERTISE:
01914 case DHCPV6_RECONFIGURE:
01915 if (stateless)
01916 return;
01917
01918 case DHCPV6_REPLY:
01919 log_info("RCV: %s message on %s from %s.",
01920 dhcpv6_type_names[packet->dhcpv6_msg_type],
01921 packet->interface->name, piaddr(packet->client_addr));
01922 break;
01923
01924 default:
01925 return;
01926 }
01927
01928
01929 for (client = packet->interface->client ; client ;
01930 client = client->next) {
01931 if (memcmp(&client->dhcpv6_transaction_id,
01932 packet->dhcpv6_transaction_id, 3) == 0) {
01933 client->v6_handler(packet, client);
01934 return;
01935 }
01936 }
01937
01938
01939 log_info("Packet received, but nothing done with it.");
01940 }
01941 #endif
01942
01943 void dhcpoffer (packet)
01944 struct packet *packet;
01945 {
01946 struct interface_info *ip = packet -> interface;
01947 struct client_state *client;
01948 struct client_lease *lease, *lp;
01949 struct option **req;
01950 int i;
01951 int stop_selecting;
01952 const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
01953 char obuf [1024];
01954 struct timeval tv;
01955
01956 #ifdef DEBUG_PACKET
01957 dump_packet (packet);
01958 #endif
01959
01960
01961 for (client = ip -> client; client; client = client -> next)
01962 if (client -> xid == packet -> raw -> xid)
01963 break;
01964
01965
01966
01967 if (!client ||
01968 client -> state != S_SELECTING ||
01969 (packet -> interface -> hw_address.hlen - 1 !=
01970 packet -> raw -> hlen) ||
01971 (memcmp (&packet -> interface -> hw_address.hbuf [1],
01972 packet -> raw -> chaddr, packet -> raw -> hlen))) {
01973 #if defined (DEBUG)
01974 log_debug ("%s in wrong transaction.", name);
01975 #endif
01976 return;
01977 }
01978
01979 sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
01980
01981
01982
01983
01984
01985 req = client->config->required_options;
01986 if (req != NULL) {
01987 for (i = 0 ; req[i] != NULL ; i++) {
01988 if ((req[i]->universe == &dhcp_universe) &&
01989 !lookup_option(&dhcp_universe, packet->options,
01990 req[i]->code)) {
01991 struct option *option = NULL;
01992 unsigned code = req[i]->code;
01993
01994 option_code_hash_lookup(&option,
01995 dhcp_universe.code_hash,
01996 &code, 0, MDL);
01997
01998 if (option)
01999 log_info("%s: no %s option.", obuf,
02000 option->name);
02001 else
02002 log_info("%s: no unknown-%u option.",
02003 obuf, code);
02004
02005 option_dereference(&option, MDL);
02006
02007 return;
02008 }
02009 }
02010 }
02011
02012
02013 for (lease = client -> offered_leases; lease; lease = lease -> next) {
02014 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
02015 !memcmp (lease -> address.iabuf,
02016 &packet -> raw -> yiaddr, lease -> address.len)) {
02017 log_debug ("%s: already seen.", obuf);
02018 return;
02019 }
02020 }
02021
02022 lease = packet_to_lease (packet, client);
02023 if (!lease) {
02024 log_info ("%s: packet_to_lease failed.", obuf);
02025 return;
02026 }
02027
02028
02029
02030 if (!packet -> options_valid || !packet -> packet_type)
02031 lease -> is_bootp = 1;
02032
02033
02034 lease -> medium = client -> medium;
02035
02036
02037 stop_selecting = (client -> first_sending +
02038 client -> config -> select_interval);
02039
02040
02041
02042 if (lease -> address.len == client -> requested_address.len &&
02043 !memcmp (lease -> address.iabuf,
02044 client -> requested_address.iabuf,
02045 client -> requested_address.len)) {
02046 lease -> next = client -> offered_leases;
02047 client -> offered_leases = lease;
02048 } else {
02049
02050 lease -> next = (struct client_lease *)0;
02051 if (!client -> offered_leases)
02052 client -> offered_leases = lease;
02053 else {
02054 for (lp = client -> offered_leases; lp -> next;
02055 lp = lp -> next)
02056 ;
02057 lp -> next = lease;
02058 }
02059 }
02060
02061
02062
02063
02064 if (stop_selecting <= cur_tv.tv_sec)
02065 state_selecting (client);
02066 else {
02067 tv.tv_sec = stop_selecting;
02068 tv.tv_usec = cur_tv.tv_usec;
02069 add_timeout(&tv, state_selecting, client, 0, 0);
02070 cancel_timeout(send_discover, client);
02071 }
02072 log_info("%s", obuf);
02073 }
02074
02075
02076
02077
02078 struct client_lease *packet_to_lease (packet, client)
02079 struct packet *packet;
02080 struct client_state *client;
02081 {
02082 struct client_lease *lease;
02083 unsigned i;
02084 struct option_cache *oc;
02085 struct option *option = NULL;
02086 struct data_string data;
02087
02088 lease = (struct client_lease *)new_client_lease (MDL);
02089
02090 if (!lease) {
02091 log_error ("packet_to_lease: no memory to record lease.\n");
02092 return (struct client_lease *)0;
02093 }
02094
02095 memset (lease, 0, sizeof *lease);
02096
02097
02098 option_state_reference (&lease -> options, packet -> options, MDL);
02099
02100 lease -> address.len = sizeof (packet -> raw -> yiaddr);
02101 memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
02102 lease -> address.len);
02103
02104 memset (&data, 0, sizeof data);
02105
02106 if (client -> config -> vendor_space_name) {
02107 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
02108
02109
02110 oc = lookup_option (&dhcp_universe, lease -> options, i);
02111 if (oc &&
02112 client -> config -> vendor_space_name &&
02113 evaluate_option_cache (&data, packet,
02114 (struct lease *)0, client,
02115 packet -> options, lease -> options,
02116 &global_scope, oc, MDL)) {
02117 if (data.len) {
02118 if (!option_code_hash_lookup(&option,
02119 dhcp_universe.code_hash,
02120 &i, 0, MDL))
02121 log_fatal("Unable to find VENDOR "
02122 "option (%s:%d).", MDL);
02123 parse_encapsulated_suboptions
02124 (packet -> options, option,
02125 data.data, data.len, &dhcp_universe,
02126 client -> config -> vendor_space_name
02127 );
02128
02129 option_dereference(&option, MDL);
02130 }
02131 data_string_forget (&data, MDL);
02132 }
02133 } else
02134 i = 0;
02135
02136
02137 oc = lookup_option (&dhcp_universe, lease -> options,
02138 DHO_DHCP_OPTION_OVERLOAD);
02139 if (oc &&
02140 evaluate_option_cache (&data, packet, (struct lease *)0, client,
02141 packet -> options, lease -> options,
02142 &global_scope, oc, MDL)) {
02143 if (data.len > 0)
02144 i = data.data [0];
02145 else
02146 i = 0;
02147 data_string_forget (&data, MDL);
02148 } else
02149 i = 0;
02150
02151
02152 if (!(i & 2) && packet -> raw -> sname [0]) {
02153 unsigned len;
02154
02155 for (len = 0; len < DHCP_SNAME_LEN; len++)
02156 if (!packet -> raw -> sname [len])
02157 break;
02158 lease -> server_name = dmalloc (len + 1, MDL);
02159 if (!lease -> server_name) {
02160 log_error ("dhcpoffer: no memory for server name.\n");
02161 destroy_client_lease (lease);
02162 return (struct client_lease *)0;
02163 } else {
02164 memcpy (lease -> server_name,
02165 packet -> raw -> sname, len);
02166 lease -> server_name [len] = 0;
02167 }
02168 }
02169
02170
02171 if (!(i & 1) && packet -> raw -> file [0]) {
02172 unsigned len;
02173
02174 for (len = 0; len < DHCP_FILE_LEN; len++)
02175 if (!packet -> raw -> file [len])
02176 break;
02177 lease -> filename = dmalloc (len + 1, MDL);
02178 if (!lease -> filename) {
02179 log_error ("dhcpoffer: no memory for filename.\n");
02180 destroy_client_lease (lease);
02181 return (struct client_lease *)0;
02182 } else {
02183 memcpy (lease -> filename,
02184 packet -> raw -> file, len);
02185 lease -> filename [len] = 0;
02186 }
02187 }
02188
02189 execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
02190 client, lease->options, lease->options,
02191 &global_scope, client->config->on_receipt,
02192 NULL, NULL);
02193
02194 return lease;
02195 }
02196
02197 void dhcpnak (packet)
02198 struct packet *packet;
02199 {
02200 struct interface_info *ip = packet -> interface;
02201 struct client_state *client;
02202
02203
02204 for (client = ip -> client; client; client = client -> next)
02205 if (client -> xid == packet -> raw -> xid)
02206 break;
02207
02208
02209
02210 if (!client ||
02211 (packet -> interface -> hw_address.hlen - 1 !=
02212 packet -> raw -> hlen) ||
02213 (memcmp (&packet -> interface -> hw_address.hbuf [1],
02214 packet -> raw -> chaddr, packet -> raw -> hlen))) {
02215 #if defined (DEBUG)
02216 log_debug ("DHCPNAK in wrong transaction.");
02217 #endif
02218 return;
02219 }
02220
02221 if (client -> state != S_REBOOTING &&
02222 client -> state != S_REQUESTING &&
02223 client -> state != S_RENEWING &&
02224 client -> state != S_REBINDING) {
02225 #if defined (DEBUG)
02226 log_debug ("DHCPNAK in wrong state.");
02227 #endif
02228 return;
02229 }
02230
02231 log_info ("DHCPNAK from %s (xid=0x%x)", piaddr (packet -> client_addr), client -> xid);
02232
02233 if (!client -> active) {
02234 #if defined (DEBUG)
02235 log_info ("DHCPNAK with no active lease.\n");
02236 #endif
02237 return;
02238 }
02239
02240
02241
02242
02243
02244
02245 script_init(client, "EXPIRE", NULL);
02246 script_write_params(client, "old_", client->active);
02247 script_write_requested(client);
02248 if (client->alias)
02249 script_write_params(client, "alias_", client->alias);
02250 script_go(client);
02251
02252 destroy_client_lease (client -> active);
02253 client -> active = (struct client_lease *)0;
02254
02255
02256 cancel_timeout (send_request, client);
02257
02258
02259
02260
02261
02262
02263 script_init(client, "PREINIT", NULL);
02264 if (client->alias)
02265 script_write_params(client, "alias_", client->alias);
02266 script_go(client);
02267
02268 client -> state = S_INIT;
02269 state_init (client);
02270 }
02271
02272
02273
02274
02275
02276 void send_discover (cpp)
02277 void *cpp;
02278 {
02279 struct client_state *client = cpp;
02280
02281 int result;
02282 int interval;
02283 int increase = 1;
02284 struct timeval tv;
02285
02286
02287 interval = cur_time - client -> first_sending;
02288
02289
02290
02291 if (interval > client -> config -> timeout) {
02292 state_panic (client);
02293 return;
02294 }
02295
02296
02297
02298
02299 if (!client -> offered_leases &&
02300 client -> config -> media) {
02301 int fail = 0;
02302 again:
02303 if (client -> medium) {
02304 client -> medium = client -> medium -> next;
02305 increase = 0;
02306 }
02307 if (!client -> medium) {
02308 if (fail)
02309 log_fatal ("No valid media types for %s!",
02310 client -> interface -> name);
02311 client -> medium =
02312 client -> config -> media;
02313 increase = 1;
02314 }
02315
02316 log_info ("Trying medium \"%s\" %d",
02317 client -> medium -> string, increase);
02318 script_init (client, "MEDIUM", client -> medium);
02319 if (script_go (client)) {
02320 fail = 1;
02321 goto again;
02322 }
02323 }
02324
02325
02326
02327
02328
02329
02330 if (increase) {
02331 if (!client->interval)
02332 client->interval = client->config->initial_interval;
02333 else
02334 client->interval += random() % (2 * client->interval);
02335
02336
02337 if (client->interval > client->config->backoff_cutoff)
02338 client->interval = (client->config->backoff_cutoff / 2)
02339 + (random() % client->config->backoff_cutoff);
02340 } else if (!client->interval)
02341 client->interval = client->config->initial_interval;
02342
02343
02344
02345 if (cur_time + client -> interval >
02346 client -> first_sending + client -> config -> timeout)
02347 client -> interval =
02348 (client -> first_sending +
02349 client -> config -> timeout) - cur_time + 1;
02350
02351
02352 if (interval < 65536)
02353 client -> packet.secs = htons (interval);
02354 else
02355 client -> packet.secs = htons (65535);
02356 client -> secs = client -> packet.secs;
02357
02358 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld (xid=0x%x)",
02359 client -> name ? client -> name : client -> interface -> name,
02360 inet_ntoa (sockaddr_broadcast.sin_addr),
02361 ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval), client -> xid);
02362
02363
02364 result = send_packet(client->interface, NULL, &client->packet,
02365 client->packet_length, inaddr_any,
02366 &sockaddr_broadcast, NULL);
02367 if (result < 0) {
02368 log_error("%s:%d: Failed to send %d byte long packet over %s "
02369 "interface.", MDL, client->packet_length,
02370 client->interface->name);
02371 }
02372
02373
02374
02375
02376
02377
02378
02379 tv.tv_sec = cur_tv.tv_sec + client->interval;
02380 tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
02381 add_timeout(&tv, send_discover, client, 0, 0);
02382 }
02383
02384
02385
02386
02387
02388
02389 void state_panic (cpp)
02390 void *cpp;
02391 {
02392 struct client_state *client = cpp;
02393 struct client_lease *loop;
02394 struct client_lease *lp;
02395 struct timeval tv;
02396
02397 loop = lp = client -> active;
02398
02399 log_info ("No DHCPOFFERS received.");
02400
02401
02402
02403 if (!client -> active && client -> leases)
02404 goto activate_next;
02405
02406
02407 while (client -> active) {
02408 if (client -> active -> expiry > cur_time) {
02409 log_info ("Trying recorded lease %s",
02410 piaddr (client -> active -> address));
02411
02412
02413 script_init (client, "TIMEOUT",
02414 client -> active -> medium);
02415 script_write_params (client, "new_", client -> active);
02416 script_write_requested(client);
02417 if (client -> alias)
02418 script_write_params (client, "alias_",
02419 client -> alias);
02420
02421
02422
02423
02424 if (!script_go (client)) {
02425 if (cur_time < client -> active -> renewal) {
02426 client -> state = S_BOUND;
02427 log_info ("bound: renewal in %ld %s.",
02428 (long)(client -> active -> renewal -
02429 cur_time), "seconds");
02430 tv.tv_sec = client->active->renewal;
02431 tv.tv_usec = ((client->active->renewal -
02432 cur_time) > 1) ?
02433 random() % 1000000 :
02434 cur_tv.tv_usec;
02435 add_timeout(&tv, state_bound, client, 0, 0);
02436 } else {
02437 client -> state = S_BOUND;
02438 log_info ("bound: immediate renewal.");
02439 state_bound (client);
02440 }
02441 reinitialize_interfaces ();
02442 go_daemon ();
02443 return;
02444 }
02445 }
02446
02447
02448 if (!client -> leases) {
02449 client -> leases = client -> active;
02450 client -> active = (struct client_lease *)0;
02451 break;
02452 }
02453
02454 activate_next:
02455
02456
02457 for (lp = client -> leases; lp -> next; lp = lp -> next)
02458 ;
02459 lp -> next = client -> active;
02460 if (lp -> next) {
02461 lp -> next -> next = (struct client_lease *)0;
02462 }
02463 client -> active = client -> leases;
02464 client -> leases = client -> leases -> next;
02465
02466
02467
02468
02469 if (client -> active == loop)
02470 break;
02471 else if (!loop)
02472 loop = client -> active;
02473 }
02474
02475
02476
02477
02478 if (onetry) {
02479 if (!quiet)
02480 log_info ("Unable to obtain a lease on first try.%s",
02481 " Exiting.");
02482 exit (2);
02483 }
02484
02485 log_info ("No working leases in persistent database - sleeping.");
02486 script_init (client, "FAIL", (struct string_list *)0);
02487 if (client -> alias)
02488 script_write_params (client, "alias_", client -> alias);
02489 script_go (client);
02490 client -> state = S_INIT;
02491 tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
02492 (random() % client->config->retry_interval));
02493 tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
02494 random() % 1000000 : cur_tv.tv_usec;
02495 add_timeout(&tv, state_init, client, 0, 0);
02496 go_daemon ();
02497 }
02498
02499 void send_request (cpp)
02500 void *cpp;
02501 {
02502 struct client_state *client = cpp;
02503
02504 int result;
02505 int interval;
02506 struct sockaddr_in destination;
02507 struct in_addr from;
02508 struct timeval tv;
02509
02510
02511 interval = cur_time - client -> first_sending;
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523 if ((client -> state == S_REBOOTING ||
02524 client -> state == S_REQUESTING) &&
02525 interval > client -> config -> reboot_timeout) {
02526 cancel:
02527 client -> state = S_INIT;
02528 cancel_timeout (send_request, client);
02529 state_init (client);
02530 return;
02531 }
02532
02533
02534
02535 if (client -> state == S_REBOOTING &&
02536 !client -> medium &&
02537 client -> active -> medium ) {
02538 script_init (client, "MEDIUM", client -> active -> medium);
02539
02540
02541 if (script_go (client))
02542 goto cancel;
02543
02544
02545 client -> medium = client -> active -> medium;
02546 }
02547
02548
02549
02550 if (client -> state != S_REQUESTING &&
02551 cur_time > client -> active -> expiry) {
02552
02553 script_init (client, "EXPIRE", (struct string_list *)0);
02554 script_write_params (client, "old_", client -> active);
02555 script_write_requested(client);
02556 if (client -> alias)
02557 script_write_params (client, "alias_",
02558 client -> alias);
02559 script_go (client);
02560
02561
02562
02563 script_init (client, "PREINIT", (struct string_list *)0);
02564 if (client -> alias)
02565 script_write_params (client, "alias_",
02566 client -> alias);
02567 script_go (client);
02568
02569 client -> state = S_INIT;
02570 state_init (client);
02571 return;
02572 }
02573
02574
02575 if (!client -> interval)
02576 client -> interval = client -> config -> initial_interval;
02577 else {
02578 client -> interval += ((random () >> 2) %
02579 (2 * client -> interval));
02580 }
02581
02582
02583 if (client -> interval >
02584 client -> config -> backoff_cutoff)
02585 client -> interval =
02586 ((client -> config -> backoff_cutoff / 2)
02587 + ((random () >> 2) %
02588 client -> config -> backoff_cutoff));
02589
02590
02591
02592 if (client -> state != S_REQUESTING &&
02593 cur_time + client -> interval > client -> active -> expiry)
02594 client -> interval =
02595 client -> active -> expiry - cur_time + 1;
02596
02597
02598
02599 if (client -> state == S_REQUESTING ||
02600 client -> state == S_REBOOTING ||
02601 cur_time > client -> active -> rebind)
02602 destination.sin_addr = sockaddr_broadcast.sin_addr;
02603 else
02604 memcpy (&destination.sin_addr.s_addr,
02605 client -> destination.iabuf,
02606 sizeof destination.sin_addr.s_addr);
02607 destination.sin_port = remote_port;
02608 destination.sin_family = AF_INET;
02609 #ifdef HAVE_SA_LEN
02610 destination.sin_len = sizeof destination;
02611 #endif
02612
02613 if (client -> state == S_RENEWING ||
02614 client -> state == S_REBINDING)
02615 memcpy (&from, client -> active -> address.iabuf,
02616 sizeof from);
02617 else
02618 from.s_addr = INADDR_ANY;
02619
02620
02621 if (client -> state == S_REQUESTING)
02622 client -> packet.secs = client -> secs;
02623 else {
02624 if (interval < 65536)
02625 client -> packet.secs = htons (interval);
02626 else
02627 client -> packet.secs = htons (65535);
02628 }
02629
02630 log_info ("DHCPREQUEST on %s to %s port %d (xid=0x%x)",
02631 client -> name ? client -> name : client -> interface -> name,
02632 inet_ntoa (destination.sin_addr),
02633 ntohs (destination.sin_port), client -> xid);
02634
02635 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
02636 fallback_interface) {
02637 result = send_packet(fallback_interface, NULL, &client->packet,
02638 client->packet_length, from, &destination,
02639 NULL);
02640 if (result < 0) {
02641 log_error("%s:%d: Failed to send %d byte long packet "
02642 "over %s interface.", MDL,
02643 client->packet_length,
02644 fallback_interface->name);
02645 }
02646 }
02647 else {
02648
02649 result = send_packet(client->interface, NULL, &client->packet,
02650 client->packet_length, from, &destination,
02651 NULL);
02652 if (result < 0) {
02653 log_error("%s:%d: Failed to send %d byte long packet"
02654 " over %s interface.", MDL,
02655 client->packet_length,
02656 client->interface->name);
02657 }
02658 }
02659
02660 tv.tv_sec = cur_tv.tv_sec + client->interval;
02661 tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
02662 random() % 1000000 : cur_tv.tv_usec;
02663 add_timeout(&tv, send_request, client, 0, 0);
02664 }
02665
02666 void send_decline (cpp)
02667 void *cpp;
02668 {
02669 struct client_state *client = cpp;
02670
02671 int result;
02672
02673 log_info ("DHCPDECLINE on %s to %s port %d (xid=0x%x)",
02674 client->name ? client->name : client->interface->name,
02675 inet_ntoa(sockaddr_broadcast.sin_addr),
02676 ntohs(sockaddr_broadcast.sin_port), client -> xid);
02677
02678
02679 result = send_packet(client->interface, NULL, &client->packet,
02680 client->packet_length, inaddr_any,
02681 &sockaddr_broadcast, NULL);
02682 if (result < 0) {
02683 log_error("%s:%d: Failed to send %d byte long packet over %s"
02684 " interface.", MDL, client->packet_length,
02685 client->interface->name);
02686 }
02687 }
02688
02689 void send_release (cpp)
02690 void *cpp;
02691 {
02692 struct client_state *client = cpp;
02693
02694 int result;
02695 struct sockaddr_in destination;
02696 struct in_addr from;
02697
02698 memcpy (&from, client -> active -> address.iabuf,
02699 sizeof from);
02700 memcpy (&destination.sin_addr.s_addr,
02701 client -> destination.iabuf,
02702 sizeof destination.sin_addr.s_addr);
02703 destination.sin_port = remote_port;
02704 destination.sin_family = AF_INET;
02705 #ifdef HAVE_SA_LEN
02706 destination.sin_len = sizeof destination;
02707 #endif
02708
02709
02710
02711 client -> active -> expiry =
02712 client -> active -> renewal =
02713 client -> active -> rebind = cur_time;
02714 if (!write_client_lease (client, client -> active, 1, 1)) {
02715 log_error ("Can't release lease: lease write failed.");
02716 return;
02717 }
02718
02719 log_info ("DHCPRELEASE on %s to %s port %d (xid=0x%x)",
02720 client -> name ? client -> name : client -> interface -> name,
02721 inet_ntoa (destination.sin_addr),
02722 ntohs (destination.sin_port), client -> xid);
02723
02724 if (fallback_interface) {
02725 result = send_packet(fallback_interface, NULL, &client->packet,
02726 client->packet_length, from, &destination,
02727 NULL);
02728 if (result < 0) {
02729 log_error("%s:%d: Failed to send %d byte long packet"
02730 " over %s interface.", MDL,
02731 client->packet_length,
02732 fallback_interface->name);
02733 }
02734 } else {
02735
02736 result = send_packet(client->interface, NULL, &client->packet,
02737 client->packet_length, from, &destination,
02738 NULL);
02739 if (result < 0) {
02740 log_error ("%s:%d: Failed to send %d byte long packet"
02741 " over %s interface.", MDL,
02742 client->packet_length,
02743 client->interface->name);
02744 }
02745
02746 }
02747 }
02748
02749 void
02750 make_client_options(struct client_state *client, struct client_lease *lease,
02751 u_int8_t *type, struct option_cache *sid,
02752 struct iaddr *rip, struct option **prl,
02753 struct option_state **op)
02754 {
02755 unsigned i;
02756 struct option_cache *oc;
02757 struct option *option = NULL;
02758 struct buffer *bp = NULL;
02759
02760
02761 if (*op)
02762 option_state_dereference(op, MDL);
02763
02764
02765 option_state_allocate(op, MDL);
02766
02767
02768 if (sid)
02769 save_option(&dhcp_universe, *op, sid);
02770
02771 oc = NULL;
02772
02773
02774 if (rip) {
02775 client->requested_address = *rip;
02776 i = DHO_DHCP_REQUESTED_ADDRESS;
02777 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
02778 &i, 0, MDL) &&
02779 make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
02780 option, MDL)))
02781 log_error ("can't make requested address cache.");
02782 else {
02783 save_option(&dhcp_universe, *op, oc);
02784 option_cache_dereference(&oc, MDL);
02785 }
02786 option_dereference(&option, MDL);
02787 } else {
02788 client->requested_address.len = 0;
02789 }
02790
02791 i = DHO_DHCP_MESSAGE_TYPE;
02792 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
02793 MDL) &&
02794 make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
02795 log_error("can't make message type.");
02796 else {
02797 save_option(&dhcp_universe, *op, oc);
02798 option_cache_dereference(&oc, MDL);
02799 }
02800 option_dereference(&option, MDL);
02801
02802 if (prl) {
02803 int len;
02804
02805
02806 len = 0;
02807 for (i = 0 ; prl[i] != NULL ; i++)
02808 if (prl[i]->universe == &dhcp_universe)
02809 len++;
02810
02811 if (!buffer_allocate(&bp, len, MDL))
02812 log_error("can't make parameter list buffer.");
02813 else {
02814 unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
02815
02816 len = 0;
02817 for (i = 0 ; prl[i] != NULL ; i++)
02818 if (prl[i]->universe == &dhcp_universe)
02819 bp->data[len++] = prl[i]->code;
02820
02821 if (!(option_code_hash_lookup(&option,
02822 dhcp_universe.code_hash,
02823 &code, 0, MDL) &&
02824 make_const_option_cache(&oc, &bp, NULL, len,
02825 option, MDL)))
02826 log_error("can't make option cache");
02827 else {
02828 save_option(&dhcp_universe, *op, oc);
02829 option_cache_dereference(&oc, MDL);
02830 }
02831 option_dereference(&option, MDL);
02832 }
02833 }
02834
02835
02836
02837
02838
02839
02840 if (duid_v4 == 1) {
02841 struct data_string client_identifier;
02842 int hw_idx, hw_len;
02843
02844 memset(&client_identifier, 0, sizeof(client_identifier));
02845 client_identifier.len = 1 + 4 + default_duid.len;
02846 if (!buffer_allocate(&client_identifier.buffer,
02847 client_identifier.len, MDL))
02848 log_fatal("no memory for default DUID!");
02849 client_identifier.data = client_identifier.buffer->data;
02850
02851 i = DHO_DHCP_CLIENT_IDENTIFIER;
02852
02853
02854 *client_identifier.buffer->data = 255;
02855
02856
02857
02858
02859 if (client->interface->hw_address.hlen > 4) {
02860 hw_idx = client->interface->hw_address.hlen - 4;
02861 hw_len = 4;
02862 } else {
02863 hw_idx = 0;
02864 hw_len = client->interface->hw_address.hlen;
02865 }
02866 memcpy(&client_identifier.buffer->data + 5 - hw_len,
02867 client->interface->hw_address.hbuf + hw_idx,
02868 hw_len);
02869
02870
02871 memcpy(&client_identifier.buffer->data+(1+4),
02872 default_duid.data, default_duid.len);
02873
02874
02875 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
02876 &i, 0, MDL) &&
02877 make_const_option_cache(&oc, NULL,
02878 (u_int8_t *)client_identifier.data,
02879 client_identifier.len,
02880 option, MDL)))
02881 log_error ("can't make requested client id cache..");
02882 else {
02883 save_option (&dhcp_universe, *op, oc);
02884 option_cache_dereference (&oc, MDL);
02885 }
02886 option_dereference(&option, MDL);
02887 }
02888
02889
02890 if (client->config->on_transmission)
02891 execute_statements_in_scope(NULL, NULL, NULL, client,
02892 (lease ? lease->options : NULL),
02893 *op, &global_scope,
02894 client->config->on_transmission,
02895 NULL, NULL);
02896 }
02897
02898 void make_discover (client, lease)
02899 struct client_state *client;
02900 struct client_lease *lease;
02901 {
02902 unsigned char discover = DHCPDISCOVER;
02903 struct option_state *options = (struct option_state *)0;
02904
02905 memset (&client -> packet, 0, sizeof (client -> packet));
02906
02907 make_client_options (client,
02908 lease, &discover, (struct option_cache *)0,
02909 lease ? &lease -> address : (struct iaddr *)0,
02910 client -> config -> requested_options,
02911 &options);
02912
02913
02914 client -> packet_length =
02915 cons_options ((struct packet *)0, &client -> packet,
02916 (struct lease *)0, client,
02917 1500,
02918 (struct option_state *)0,
02919 options,
02920 &global_scope,
02921 0,
02922 0,
02923 0,
02924 (struct data_string *)0,
02925 client -> config -> vendor_space_name);
02926
02927 option_state_dereference (&options, MDL);
02928 if (client -> packet_length < BOOTP_MIN_LEN)
02929 client -> packet_length = BOOTP_MIN_LEN;
02930
02931 client -> packet.op = BOOTREQUEST;
02932 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
02933 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02934 client -> packet.hops = 0;
02935 client -> packet.xid = random ();
02936 client -> packet.secs = 0;
02937
02938 if ((!(bootp_broadcast_always || client->config->bootp_broadcast_always))
02939 && can_receive_unicast_unconfigured(client->interface))
02940 client -> packet.flags = 0;
02941 else
02942 client -> packet.flags = htons (BOOTP_BROADCAST);
02943
02944 memset (&(client -> packet.ciaddr),
02945 0, sizeof client -> packet.ciaddr);
02946 memset (&(client -> packet.yiaddr),
02947 0, sizeof client -> packet.yiaddr);
02948 memset (&(client -> packet.siaddr),
02949 0, sizeof client -> packet.siaddr);
02950 client -> packet.giaddr = giaddr;
02951 if (client -> interface -> hw_address.hlen > 0)
02952 memcpy (client -> packet.chaddr,
02953 &client -> interface -> hw_address.hbuf [1],
02954 (unsigned)(client -> interface -> hw_address.hlen - 1));
02955
02956 #ifdef DEBUG_PACKET
02957 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
02958 #endif
02959 }
02960
02961
02962 void make_request (client, lease)
02963 struct client_state *client;
02964 struct client_lease *lease;
02965 {
02966 unsigned char request = DHCPREQUEST;
02967 struct option_cache *oc;
02968
02969 memset (&client -> packet, 0, sizeof (client -> packet));
02970
02971 if (client -> state == S_REQUESTING)
02972 oc = lookup_option (&dhcp_universe, lease -> options,
02973 DHO_DHCP_SERVER_IDENTIFIER);
02974 else
02975 oc = (struct option_cache *)0;
02976
02977 if (client -> sent_options)
02978 option_state_dereference (&client -> sent_options, MDL);
02979
02980 make_client_options (client, lease, &request, oc,
02981 ((client -> state == S_REQUESTING ||
02982 client -> state == S_REBOOTING)
02983 ? &lease -> address
02984 : (struct iaddr *)0),
02985 client -> config -> requested_options,
02986 &client -> sent_options);
02987
02988
02989 client -> packet_length =
02990 cons_options ((struct packet *)0, &client -> packet,
02991 (struct lease *)0, client,
02992 1500,
02993 (struct option_state *)0,
02994 client -> sent_options,
02995 &global_scope,
02996 0,
02997 0,
02998 0,
02999 (struct data_string *)0,
03000 client -> config -> vendor_space_name);
03001
03002 if (client -> packet_length < BOOTP_MIN_LEN)
03003 client -> packet_length = BOOTP_MIN_LEN;
03004
03005 client -> packet.op = BOOTREQUEST;
03006 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
03007 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
03008 client -> packet.hops = 0;
03009 client -> packet.xid = client -> xid;
03010 client -> packet.secs = 0;
03011
03012
03013
03014 if (client -> state == S_BOUND ||
03015 client -> state == S_RENEWING ||
03016 client -> state == S_REBINDING) {
03017 memcpy (&client -> packet.ciaddr,
03018 lease -> address.iabuf, lease -> address.len);
03019 client -> packet.flags = 0;
03020 } else {
03021 memset (&client -> packet.ciaddr, 0,
03022 sizeof client -> packet.ciaddr);
03023 if ((!(bootp_broadcast_always ||
03024 client ->config->bootp_broadcast_always)) &&
03025 can_receive_unicast_unconfigured (client -> interface))
03026 client -> packet.flags = 0;
03027 else
03028 client -> packet.flags = htons (BOOTP_BROADCAST);
03029 }
03030
03031 memset (&client -> packet.yiaddr, 0,
03032 sizeof client -> packet.yiaddr);
03033 memset (&client -> packet.siaddr, 0,
03034 sizeof client -> packet.siaddr);
03035 if (client -> state != S_BOUND &&
03036 client -> state != S_RENEWING)
03037 client -> packet.giaddr = giaddr;
03038 else
03039 memset (&client -> packet.giaddr, 0,
03040 sizeof client -> packet.giaddr);
03041 if (client -> interface -> hw_address.hlen > 0)
03042 memcpy (client -> packet.chaddr,
03043 &client -> interface -> hw_address.hbuf [1],
03044 (unsigned)(client -> interface -> hw_address.hlen - 1));
03045
03046 #ifdef DEBUG_PACKET
03047 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
03048 #endif
03049 }
03050
03051 void make_decline (client, lease)
03052 struct client_state *client;
03053 struct client_lease *lease;
03054 {
03055 unsigned char decline = DHCPDECLINE;
03056 struct option_cache *oc;
03057
03058 struct option_state *options = (struct option_state *)0;
03059
03060
03061 oc = lookup_option (&dhcp_universe, lease -> options,
03062 DHO_DHCP_SERVER_IDENTIFIER);
03063 make_client_options(client, lease, &decline, oc, &lease->address,
03064 NULL, &options);
03065
03066
03067 memset (&client -> packet, 0, sizeof (client -> packet));
03068 client -> packet_length =
03069 cons_options ((struct packet *)0, &client -> packet,
03070 (struct lease *)0, client, 0,
03071 (struct option_state *)0, options,
03072 &global_scope, 0, 0, 0, (struct data_string *)0,
03073 client -> config -> vendor_space_name);
03074
03075
03076 option_state_dereference (&options, MDL);
03077
03078 if (client -> packet_length < BOOTP_MIN_LEN)
03079 client -> packet_length = BOOTP_MIN_LEN;
03080
03081 client -> packet.op = BOOTREQUEST;
03082 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
03083 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
03084 client -> packet.hops = 0;
03085 client -> packet.xid = client -> xid;
03086 client -> packet.secs = 0;
03087 if ((!(bootp_broadcast_always || client->config-> bootp_broadcast_always))
03088 && can_receive_unicast_unconfigured (client->interface))
03089 client -> packet.flags = 0;
03090 else
03091 client -> packet.flags = htons (BOOTP_BROADCAST);
03092
03093
03094 memset (&client -> packet.ciaddr, 0,
03095 sizeof client -> packet.ciaddr);
03096 memset (&client -> packet.yiaddr, 0,
03097 sizeof client -> packet.yiaddr);
03098 memset (&client -> packet.siaddr, 0,
03099 sizeof client -> packet.siaddr);
03100 client -> packet.giaddr = giaddr;
03101 memcpy (client -> packet.chaddr,
03102 &client -> interface -> hw_address.hbuf [1],
03103 client -> interface -> hw_address.hlen);
03104
03105 #ifdef DEBUG_PACKET
03106 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
03107 #endif
03108 }
03109
03110 void make_release (client, lease)
03111 struct client_state *client;
03112 struct client_lease *lease;
03113 {
03114 unsigned char request = DHCPRELEASE;
03115 struct option_cache *oc;
03116
03117 struct option_state *options = (struct option_state *)0;
03118
03119 memset (&client -> packet, 0, sizeof (client -> packet));
03120
03121 oc = lookup_option (&dhcp_universe, lease -> options,
03122 DHO_DHCP_SERVER_IDENTIFIER);
03123 make_client_options(client, lease, &request, oc, NULL, NULL, &options);
03124
03125
03126 client -> packet_length =
03127 cons_options ((struct packet *)0, &client -> packet,
03128 (struct lease *)0, client,
03129 1500,
03130 (struct option_state *)0,
03131 options,
03132 &global_scope,
03133 0,
03134 0,
03135 0,
03136 (struct data_string *)0,
03137 client -> config -> vendor_space_name);
03138
03139 if (client -> packet_length < BOOTP_MIN_LEN)
03140 client -> packet_length = BOOTP_MIN_LEN;
03141 option_state_dereference (&options, MDL);
03142
03143 client -> packet.op = BOOTREQUEST;
03144 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
03145 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
03146 client -> packet.hops = 0;
03147 client -> packet.xid = random ();
03148 client -> packet.secs = 0;
03149 client -> packet.flags = 0;
03150 memcpy (&client -> packet.ciaddr,
03151 lease -> address.iabuf, lease -> address.len);
03152 memset (&client -> packet.yiaddr, 0,
03153 sizeof client -> packet.yiaddr);
03154 memset (&client -> packet.siaddr, 0,
03155 sizeof client -> packet.siaddr);
03156 client -> packet.giaddr = giaddr;
03157 memcpy (client -> packet.chaddr,
03158 &client -> interface -> hw_address.hbuf [1],
03159 client -> interface -> hw_address.hlen);
03160
03161 #ifdef DEBUG_PACKET
03162 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
03163 #endif
03164 }
03165
03166 void destroy_client_lease (lease)
03167 struct client_lease *lease;
03168 {
03169 if (lease -> server_name)
03170 dfree (lease -> server_name, MDL);
03171 if (lease -> filename)
03172 dfree (lease -> filename, MDL);
03173 option_state_dereference (&lease -> options, MDL);
03174 free_client_lease (lease, MDL);
03175 }
03176
03177 FILE *leaseFile = NULL;
03178 int leases_written = 0;
03179
03180 void rewrite_client_leases ()
03181 {
03182 struct interface_info *ip;
03183 struct client_state *client;
03184 struct client_lease *lp;
03185
03186 if (leaseFile != NULL)
03187 fclose (leaseFile);
03188 leaseFile = fopen (path_dhclient_db, "we");
03189 if (leaseFile == NULL) {
03190 log_error ("can't create %s: %m", path_dhclient_db);
03191 return;
03192 }
03193
03194
03195 if (default_duid.len != 0)
03196 write_duid(&default_duid);
03197
03198
03199
03200 for (ip = interfaces; ip; ip = ip -> next) {
03201 for (client = ip -> client; client; client = client -> next) {
03202 for (lp = client -> leases; lp; lp = lp -> next) {
03203 write_client_lease (client, lp, 1, 0);
03204 }
03205 if (client -> active)
03206 write_client_lease (client,
03207 client -> active, 1, 0);
03208
03209 if (client->active_lease != NULL)
03210 write_client6_lease(client,
03211 client->active_lease,
03212 1, 0);
03213
03214
03215 client->last_write = 0;
03216 }
03217 }
03218
03219
03220
03221 for (ip = dummy_interfaces; ip; ip = ip -> next) {
03222 for (client = ip -> client; client; client = client -> next) {
03223 for (lp = client -> leases; lp; lp = lp -> next) {
03224 write_client_lease (client, lp, 1, 0);
03225 }
03226 if (client -> active)
03227 write_client_lease (client,
03228 client -> active, 1, 0);
03229
03230 if (client->active_lease != NULL)
03231 write_client6_lease(client,
03232 client->active_lease,
03233 1, 0);
03234
03235
03236 client->last_write = 0;
03237 }
03238 }
03239 fflush (leaseFile);
03240 }
03241
03242 void write_lease_option (struct option_cache *oc,
03243 struct packet *packet, struct lease *lease,
03244 struct client_state *client_state,
03245 struct option_state *in_options,
03246 struct option_state *cfg_options,
03247 struct binding_scope **scope,
03248 struct universe *u, void *stuff)
03249 {
03250 const char *name, *dot;
03251 struct data_string ds;
03252 char *preamble = stuff;
03253
03254 memset (&ds, 0, sizeof ds);
03255
03256 if (u != &dhcp_universe) {
03257 name = u -> name;
03258 dot = ".";
03259 } else {
03260 name = "";
03261 dot = "";
03262 }
03263 if (evaluate_option_cache (&ds, packet, lease, client_state,
03264 in_options, cfg_options, scope, oc, MDL)) {
03265
03266 fprintf(leaseFile, "%soption %s%s%s", preamble,
03267 name, dot, oc->option->name);
03268
03269
03270 if ((oc->option->format == NULL) ||
03271 (oc->option->format[0] != 'Z')) {
03272 fprintf(leaseFile, " %s",
03273 pretty_print_option(oc->option, ds.data,
03274 ds.len, 1, 1));
03275 }
03276
03277
03278 fprintf(leaseFile, ";\n");
03279
03280 data_string_forget (&ds, MDL);
03281 }
03282 }
03283
03284
03285 static void
03286 write_options(struct client_state *client, struct option_state *options,
03287 const char *preamble)
03288 {
03289 int i;
03290
03291 for (i = 0; i < options->universe_count; i++) {
03292 option_space_foreach(NULL, NULL, client, NULL, options,
03293 &global_scope, universes[i],
03294 (char *)preamble, write_lease_option);
03295 }
03296 }
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312 isc_result_t
03313 form_duid(struct data_string *duid, const char *file, int line)
03314 {
03315 struct interface_info *ip;
03316 int len;
03317 unsigned hlen;
03318
03319
03320 ip = interfaces;
03321
03322 if (ip == NULL)
03323 log_fatal("Impossible condition at %s:%d.", MDL);
03324
03325 while (ip && ip->hw_address.hbuf[0] == HTYPE_RESERVED) {
03326
03327 log_debug("Cannot form default DUID from interface %s.", ip->name);
03328 ip = ip->next;
03329 }
03330 if (ip == NULL) {
03331 return ISC_R_UNEXPECTED;
03332 }
03333
03334 if ((ip->hw_address.hlen == 0) ||
03335 (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
03336 log_fatal("Impossible hardware address length at %s:%d.", MDL);
03337
03338 if (duid_type == 0)
03339 duid_type = stateless ? DUID_LL : DUID_LLT;
03340
03341 if (ip->hw_address.hbuf[0] == HTYPE_INFINIBAND)
03342 hlen = 9;
03343 else
03344 hlen = ip->hw_address.hlen;
03345
03346
03347
03348
03349
03350
03351
03352
03353 len = 4 + (hlen - 1);
03354 if (duid_type == DUID_LLT)
03355 len += 4;
03356 if (!buffer_allocate(&duid->buffer, len, MDL))
03357 log_fatal("no memory for default DUID!");
03358 duid->data = duid->buffer->data;
03359 duid->len = len;
03360
03361
03362 if (duid_type == DUID_LLT) {
03363 putUShort(duid->buffer->data, DUID_LLT);
03364 putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
03365 putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
03366 memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
03367 hlen - 1);
03368 } else {
03369 putUShort(duid->buffer->data, DUID_LL);
03370 putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
03371 memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
03372 hlen - 1);
03373 }
03374
03375 return ISC_R_SUCCESS;
03376 }
03377
03378
03379 static isc_result_t
03380 write_duid(struct data_string *duid)
03381 {
03382 char *str;
03383 int stat;
03384
03385 if ((duid == NULL) || (duid->len <= 2))
03386 return DHCP_R_INVALIDARG;
03387
03388 if (leaseFile == NULL) {
03389 leaseFile = fopen(path_dhclient_db, "we");
03390 if (leaseFile == NULL) {
03391 log_error("can't create %s: %m", path_dhclient_db);
03392 return ISC_R_IOERROR;
03393 }
03394 }
03395
03396
03397
03398
03399
03400
03401 str = quotify_buf(duid->data, duid->len, MDL);
03402 if (str == NULL)
03403 return ISC_R_NOMEMORY;
03404
03405 stat = fprintf(leaseFile, "default-duid \"%s\";\n", str);
03406 dfree(str, MDL);
03407 if (stat <= 0)
03408 return ISC_R_IOERROR;
03409
03410 if (fflush(leaseFile) != 0)
03411 return ISC_R_IOERROR;
03412
03413 return ISC_R_SUCCESS;
03414 }
03415
03416
03417 isc_result_t
03418 write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
03419 int rewrite, int sync)
03420 {
03421 struct dhc6_ia *ia;
03422 struct dhc6_addr *addr;
03423 int stat;
03424 const char *ianame;
03425
03426
03427 if (!rewrite && (leases_written++ > 20)) {
03428 rewrite_client_leases();
03429 leases_written = 0;
03430 return ISC_R_SUCCESS;
03431 }
03432
03433 if (client == NULL || lease == NULL)
03434 return DHCP_R_INVALIDARG;
03435
03436 if (leaseFile == NULL) {
03437 leaseFile = fopen(path_dhclient_db, "w");
03438 if (leaseFile == NULL) {
03439 log_error("can't create %s: %m", path_dhclient_db);
03440 return ISC_R_IOERROR;
03441 }
03442 }
03443
03444 stat = fprintf(leaseFile, "lease6 {\n");
03445 if (stat <= 0)
03446 return ISC_R_IOERROR;
03447
03448 stat = fprintf(leaseFile, " interface \"%s\";\n",
03449 client->interface->name);
03450 if (stat <= 0)
03451 return ISC_R_IOERROR;
03452
03453 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
03454 switch (ia->ia_type) {
03455 case D6O_IA_NA:
03456 default:
03457 ianame = "ia-na";
03458 break;
03459 case D6O_IA_TA:
03460 ianame = "ia-ta";
03461 break;
03462 case D6O_IA_PD:
03463 ianame = "ia-pd";
03464 break;
03465 }
03466 stat = fprintf(leaseFile, " %s %s {\n",
03467 ianame, print_hex_1(4, ia->iaid, 12));
03468 if (stat <= 0)
03469 return ISC_R_IOERROR;
03470
03471 if (ia->ia_type != D6O_IA_TA)
03472 stat = fprintf(leaseFile, " starts %d;\n"
03473 " renew %u;\n"
03474 " rebind %u;\n",
03475 (int)ia->starts, ia->renew, ia->rebind);
03476 else
03477 stat = fprintf(leaseFile, " starts %d;\n",
03478 (int)ia->starts);
03479 if (stat <= 0)
03480 return ISC_R_IOERROR;
03481
03482 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
03483 if (ia->ia_type != D6O_IA_PD)
03484 stat = fprintf(leaseFile,
03485 " iaaddr %s {\n",
03486 piaddr(addr->address));
03487 else
03488 stat = fprintf(leaseFile,
03489 " iaprefix %s/%d {\n",
03490 piaddr(addr->address),
03491 (int)addr->plen);
03492 if (stat <= 0)
03493 return ISC_R_IOERROR;
03494
03495 stat = fprintf(leaseFile, " starts %d;\n"
03496 " preferred-life %u;\n"
03497 " max-life %u;\n",
03498 (int)addr->starts, addr->preferred_life,
03499 addr->max_life);
03500 if (stat <= 0)
03501 return ISC_R_IOERROR;
03502
03503 if (addr->options != NULL)
03504 write_options(client, addr->options, " ");
03505
03506 stat = fprintf(leaseFile, " }\n");
03507 if (stat <= 0)
03508 return ISC_R_IOERROR;
03509 }
03510
03511 if (ia->options != NULL)
03512 write_options(client, ia->options, " ");
03513
03514 stat = fprintf(leaseFile, " }\n");
03515 if (stat <= 0)
03516 return ISC_R_IOERROR;
03517 }
03518
03519 if (lease->released) {
03520 stat = fprintf(leaseFile, " released;\n");
03521 if (stat <= 0)
03522 return ISC_R_IOERROR;
03523 }
03524
03525 if (lease->options != NULL)
03526 write_options(client, lease->options, " ");
03527
03528 stat = fprintf(leaseFile, "}\n");
03529 if (stat <= 0)
03530 return ISC_R_IOERROR;
03531
03532 if (fflush(leaseFile) != 0)
03533 return ISC_R_IOERROR;
03534
03535 if (sync) {
03536 if (fsync(fileno(leaseFile)) < 0) {
03537 log_error("write_client_lease: fsync(): %m");
03538 return ISC_R_IOERROR;
03539 }
03540 }
03541
03542 return ISC_R_SUCCESS;
03543 }
03544
03545 int write_client_lease (client, lease, rewrite, makesure)
03546 struct client_state *client;
03547 struct client_lease *lease;
03548 int rewrite;
03549 int makesure;
03550 {
03551 struct data_string ds;
03552 int errors = 0;
03553 char *s;
03554 const char *tval;
03555
03556 if (!rewrite) {
03557 if (leases_written++ > 20) {
03558 rewrite_client_leases ();
03559 leases_written = 0;
03560 }
03561 }
03562
03563
03564
03565 if (lease -> is_static)
03566 return 1;
03567
03568 if (leaseFile == NULL) {
03569 leaseFile = fopen (path_dhclient_db, "we");
03570 if (leaseFile == NULL) {
03571 log_error ("can't create %s: %m", path_dhclient_db);
03572 return 0;
03573 }
03574 }
03575
03576 errno = 0;
03577 fprintf (leaseFile, "lease {\n");
03578 if (lease -> is_bootp) {
03579 fprintf (leaseFile, " bootp;\n");
03580 if (errno) {
03581 ++errors;
03582 errno = 0;
03583 }
03584 }
03585 fprintf (leaseFile, " interface \"%s\";\n",
03586 client -> interface -> name);
03587 if (errno) {
03588 ++errors;
03589 errno = 0;
03590 }
03591 if (client -> name) {
03592 fprintf (leaseFile, " name \"%s\";\n", client -> name);
03593 if (errno) {
03594 ++errors;
03595 errno = 0;
03596 }
03597 }
03598 fprintf (leaseFile, " fixed-address %s;\n",
03599 piaddr (lease -> address));
03600 if (errno) {
03601 ++errors;
03602 errno = 0;
03603 }
03604 if (lease -> filename) {
03605 s = quotify_string (lease -> filename, MDL);
03606 if (s) {
03607 fprintf (leaseFile, " filename \"%s\";\n", s);
03608 if (errno) {
03609 ++errors;
03610 errno = 0;
03611 }
03612 dfree (s, MDL);
03613 } else
03614 errors++;
03615
03616 }
03617 if (lease->server_name != NULL) {
03618 s = quotify_string(lease->server_name, MDL);
03619 if (s != NULL) {
03620 fprintf(leaseFile, " server-name \"%s\";\n", s);
03621 if (errno) {
03622 ++errors;
03623 errno = 0;
03624 }
03625 dfree(s, MDL);
03626 } else
03627 ++errors;
03628 }
03629 if (lease -> medium) {
03630 s = quotify_string (lease -> medium -> string, MDL);
03631 if (s) {
03632 fprintf (leaseFile, " medium \"%s\";\n", s);
03633 if (errno) {
03634 ++errors;
03635 errno = 0;
03636 }
03637 dfree (s, MDL);
03638 } else
03639 errors++;
03640 }
03641 if (errno != 0) {
03642 errors++;
03643 errno = 0;
03644 }
03645
03646 memset (&ds, 0, sizeof ds);
03647
03648 write_options(client, lease->options, " ");
03649
03650 tval = print_time(lease->renewal);
03651 if (tval == NULL ||
03652 fprintf(leaseFile, " renew %s\n", tval) < 0)
03653 errors++;
03654
03655 tval = print_time(lease->rebind);
03656 if (tval == NULL ||
03657 fprintf(leaseFile, " rebind %s\n", tval) < 0)
03658 errors++;
03659
03660 tval = print_time(lease->expiry);
03661 if (tval == NULL ||
03662 fprintf(leaseFile, " expire %s\n", tval) < 0)
03663 errors++;
03664
03665 if (fprintf(leaseFile, "}\n") < 0)
03666 errors++;
03667
03668 if (fflush(leaseFile) != 0)
03669 errors++;
03670
03671 client->last_write = cur_time;
03672
03673 if (!errors && makesure) {
03674 if (fsync (fileno (leaseFile)) < 0) {
03675 log_info ("write_client_lease: %m");
03676 return 0;
03677 }
03678 }
03679
03680 return errors ? 0 : 1;
03681 }
03682
03683
03684
03685
03686 char scriptName [256];
03687 FILE *scriptFile;
03688
03689 void script_init (client, reason, medium)
03690 struct client_state *client;
03691 const char *reason;
03692 struct string_list *medium;
03693 {
03694 struct string_list *sl, *next;
03695
03696 if (client) {
03697 for (sl = client -> env; sl; sl = next) {
03698 next = sl -> next;
03699 dfree (sl, MDL);
03700 }
03701 client -> env = (struct string_list *)0;
03702 client -> envc = 0;
03703
03704 if (client -> interface) {
03705 client_envadd (client, "", "interface", "%s",
03706 client -> interface -> name);
03707 }
03708 if (client -> name)
03709 client_envadd (client,
03710 "", "client", "%s", client -> name);
03711 if (medium)
03712 client_envadd (client,
03713 "", "medium", "%s", medium -> string);
03714
03715 client_envadd (client, "", "reason", "%s", reason);
03716 client_envadd (client, "", "pid", "%ld", (long int)getpid ());
03717 }
03718 }
03719
03720 void client_option_envadd (struct option_cache *oc,
03721 struct packet *packet, struct lease *lease,
03722 struct client_state *client_state,
03723 struct option_state *in_options,
03724 struct option_state *cfg_options,
03725 struct binding_scope **scope,
03726 struct universe *u, void *stuff)
03727 {
03728 struct envadd_state *es = stuff;
03729 struct data_string data;
03730 memset (&data, 0, sizeof data);
03731
03732 if (evaluate_option_cache (&data, packet, lease, client_state,
03733 in_options, cfg_options, scope, oc, MDL)) {
03734 if (data.len) {
03735 char name [256];
03736 if (dhcp_option_ev_name (name, sizeof name,
03737 oc->option)) {
03738 const char *value;
03739 size_t length;
03740 value = pretty_print_option(oc->option,
03741 data.data,
03742 data.len, 0, 0);
03743 length = strlen(value);
03744
03745 if (check_option_values(oc->option->universe,
03746 oc->option->code,
03747 value, length) == 0) {
03748 client_envadd(es->client, es->prefix,
03749 name, "%s", value);
03750 } else {
03751 log_error("suspect value in %s "
03752 "option - discarded",
03753 name);
03754 }
03755 data_string_forget (&data, MDL);
03756 }
03757 }
03758 }
03759 }
03760
03761 void script_write_params (client, prefix, lease)
03762 struct client_state *client;
03763 const char *prefix;
03764 struct client_lease *lease;
03765 {
03766 int i;
03767 struct data_string data;
03768 struct option_cache *oc;
03769 struct envadd_state es;
03770
03771 es.client = client;
03772 es.prefix = prefix;
03773
03774 client_envadd (client,
03775 prefix, "ip_address", "%s", piaddr (lease -> address));
03776
03777
03778
03779
03780
03781
03782
03783
03784 memset (&data, 0, sizeof data);
03785 oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
03786 if (oc && evaluate_option_cache (&data, (struct packet *)0,
03787 (struct lease *)0, client,
03788 (struct option_state *)0,
03789 lease -> options,
03790 &global_scope, oc, MDL)) {
03791 if (data.len > 3) {
03792 struct iaddr netmask, subnet, broadcast;
03793
03794
03795
03796
03797
03798
03799
03800
03801 memcpy(netmask.iabuf, data.data, 4);
03802 netmask.len = 4;
03803 data_string_forget (&data, MDL);
03804
03805 subnet = subnet_number (lease -> address, netmask);
03806 if (subnet.len) {
03807 client_envadd (client, prefix, "network_number",
03808 "%s", piaddr (subnet));
03809
03810 oc = lookup_option (&dhcp_universe,
03811 lease -> options,
03812 DHO_BROADCAST_ADDRESS);
03813 if (!oc ||
03814 !(evaluate_option_cache
03815 (&data, (struct packet *)0,
03816 (struct lease *)0, client,
03817 (struct option_state *)0,
03818 lease -> options,
03819 &global_scope, oc, MDL))) {
03820 broadcast = broadcast_addr (subnet, netmask);
03821 if (broadcast.len) {
03822 client_envadd (client,
03823 prefix, "broadcast_address",
03824 "%s", piaddr (broadcast));
03825 }
03826 }
03827 }
03828 }
03829 data_string_forget (&data, MDL);
03830 }
03831
03832 if (lease->filename) {
03833 if (check_option_values(NULL, DHO_ROOT_PATH,
03834 lease->filename,
03835 strlen(lease->filename)) == 0) {
03836 client_envadd(client, prefix, "filename",
03837 "%s", lease->filename);
03838 } else {
03839 log_error("suspect value in %s "
03840 "option - discarded",
03841 lease->filename);
03842 }
03843 }
03844
03845 if (lease->server_name) {
03846 if (check_option_values(NULL, DHO_HOST_NAME,
03847 lease->server_name,
03848 strlen(lease->server_name)) == 0 ) {
03849 client_envadd (client, prefix, "server_name",
03850 "%s", lease->server_name);
03851 } else {
03852 log_error("suspect value in %s "
03853 "option - discarded",
03854 lease->server_name);
03855 }
03856 }
03857
03858 for (i = 0; i < lease -> options -> universe_count; i++) {
03859 option_space_foreach ((struct packet *)0, (struct lease *)0,
03860 client, (struct option_state *)0,
03861 lease -> options, &global_scope,
03862 universes [i],
03863 &es, client_option_envadd);
03864 }
03865 client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
03866 }
03867
03868
03869
03870
03871
03872
03873
03874 void script_write_requested(client)
03875 struct client_state *client;
03876 {
03877 int i;
03878 struct option **req;
03879 char name[256];
03880 req = client->config->requested_options;
03881
03882 if (req == NULL)
03883 return;
03884
03885 for (i = 0 ; req[i] != NULL ; i++) {
03886 if ((req[i]->universe == &dhcp_universe) &&
03887 dhcp_option_ev_name(name, sizeof(name), req[i])) {
03888 client_envadd(client, "requested_", name, "%d", 1);
03889 }
03890 }
03891 }
03892
03893 int script_go (client)
03894 struct client_state *client;
03895 {
03896 char *scriptName;
03897 char *argv [2];
03898 char **envp;
03899 char reason [] = "REASON=NBI";
03900 static char client_path [] = CLIENT_PATH;
03901 int i;
03902 struct string_list *sp, *next;
03903 int pid, wpid, wstatus;
03904
03905 if (client)
03906 scriptName = client -> config -> script_name;
03907 else
03908 scriptName = top_level_config.script_name;
03909
03910 envp = dmalloc (((client ? client -> envc : 2) +
03911 client_env_count + 2) * sizeof (char *), MDL);
03912 if (!envp) {
03913 log_error ("No memory for client script environment.");
03914 return 0;
03915 }
03916 i = 0;
03917
03918
03919 for (sp = client_env; sp; sp = sp -> next) {
03920 envp [i++] = sp -> string;
03921 }
03922
03923 if (client) {
03924 for (sp = client -> env; sp; sp = sp -> next) {
03925 envp [i++] = sp -> string;
03926 }
03927 } else {
03928 envp [i++] = reason;
03929 }
03930
03931 envp [i++] = client_path;
03932 envp [i] = (char *)0;
03933
03934 argv [0] = scriptName;
03935 argv [1] = (char *)0;
03936
03937 pid = fork ();
03938 if (pid < 0) {
03939 log_error ("fork: %m");
03940 wstatus = 0;
03941 } else if (pid) {
03942 do {
03943 wpid = wait (&wstatus);
03944 } while (wpid != pid && wpid > 0);
03945 if (wpid < 0) {
03946 log_error ("wait: %m");
03947 wstatus = 0;
03948 }
03949 } else {
03950
03951
03952
03953 if (leaseFile != NULL)
03954 fclose(leaseFile);
03955 execve (scriptName, argv, envp);
03956 log_error ("execve (%s, ...): %m", scriptName);
03957 exit (0);
03958 }
03959
03960 if (client) {
03961 for (sp = client -> env; sp; sp = next) {
03962 next = sp -> next;
03963 dfree (sp, MDL);
03964 }
03965 client -> env = (struct string_list *)0;
03966 client -> envc = 0;
03967 }
03968 dfree (envp, MDL);
03969 gettimeofday(&cur_tv, NULL);
03970 return (WIFEXITED (wstatus) ?
03971 WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
03972 }
03973
03974 void client_envadd (struct client_state *client,
03975 const char *prefix, const char *name, const char *fmt, ...)
03976 {
03977 char spbuf [1024];
03978 char *s;
03979 unsigned len;
03980 struct string_list *val;
03981 va_list list;
03982
03983 va_start (list, fmt);
03984 len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
03985 va_end (list);
03986
03987 val = dmalloc (strlen (prefix) + strlen (name) + 1 +
03988 len + sizeof *val, MDL);
03989 if (!val)
03990 return;
03991 s = val -> string;
03992 strcpy (s, prefix);
03993 strcat (s, name);
03994 s += strlen (s);
03995 *s++ = '=';
03996 if (len >= sizeof spbuf) {
03997 va_start (list, fmt);
03998 vsnprintf (s, len + 1, fmt, list);
03999 va_end (list);
04000 } else
04001 strcpy (s, spbuf);
04002 val -> next = client -> env;
04003 client -> env = val;
04004 client -> envc++;
04005 }
04006
04007 int dhcp_option_ev_name (buf, buflen, option)
04008 char *buf;
04009 size_t buflen;
04010 struct option *option;
04011 {
04012 int i, j;
04013 const char *s;
04014
04015 j = 0;
04016 if (option -> universe != &dhcp_universe) {
04017 s = option -> universe -> name;
04018 i = 0;
04019 } else {
04020 s = option -> name;
04021 i = 1;
04022 }
04023
04024 do {
04025 while (*s) {
04026 if (j + 1 == buflen)
04027 return 0;
04028 if (*s == '-')
04029 buf [j++] = '_';
04030 else
04031 buf [j++] = *s;
04032 ++s;
04033 }
04034 if (!i) {
04035 s = option -> name;
04036 if (j + 1 == buflen)
04037 return 0;
04038 buf [j++] = '_';
04039 }
04040 ++i;
04041 } while (i != 2);
04042
04043 buf [j] = 0;
04044 return 1;
04045 }
04046
04047 void go_daemon ()
04048 {
04049 static int state = 0;
04050 int pid;
04051
04052
04053 if (no_daemon) {
04054 write_client_pid_file ();
04055 return;
04056 }
04057
04058
04059 if (state)
04060 return;
04061 state = 1;
04062
04063
04064 log_perror = 0;
04065
04066
04067 if ((pid = fork ()) < 0)
04068 log_fatal ("Can't fork daemon: %m");
04069 else if (pid)
04070 exit (0);
04071
04072 (void) setsid ();
04073
04074
04075 (void) close(0);
04076 (void) close(1);
04077 (void) close(2);
04078
04079
04080 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
04081 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
04082 (void) open("/dev/null", O_RDWR | O_CLOEXEC);
04083
04084 write_client_pid_file ();
04085
04086 IGNORE_RET (chdir("/"));
04087 }
04088
04089 void write_client_pid_file ()
04090 {
04091 FILE *pf;
04092 int pfdesc;
04093
04094
04095 if (no_pid_file == ISC_TRUE) {
04096 return;
04097 }
04098
04099 pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
04100
04101 if (pfdesc < 0) {
04102 log_error ("Can't create %s: %m", path_dhclient_pid);
04103 return;
04104 }
04105
04106 pf = fdopen (pfdesc, "we");
04107 if (!pf) {
04108 close(pfdesc);
04109 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
04110 } else {
04111 fprintf (pf, "%ld\n", (long)getpid ());
04112 fclose (pf);
04113 }
04114 }
04115
04116 void client_location_changed ()
04117 {
04118 struct interface_info *ip;
04119 struct client_state *client;
04120
04121 for (ip = interfaces; ip; ip = ip -> next) {
04122 for (client = ip -> client; client; client = client -> next) {
04123 switch (client -> state) {
04124 case S_SELECTING:
04125 cancel_timeout (send_discover, client);
04126 break;
04127
04128 case S_BOUND:
04129 cancel_timeout (state_bound, client);
04130 break;
04131
04132 case S_REBOOTING:
04133 case S_REQUESTING:
04134 case S_RENEWING:
04135 cancel_timeout (send_request, client);
04136 break;
04137
04138 case S_INIT:
04139 case S_REBINDING:
04140 case S_STOPPED:
04141 case S_DECLINED:
04142 break;
04143 }
04144 client -> state = S_INIT;
04145 state_reboot (client);
04146 }
04147 }
04148 }
04149
04150 void do_release(client)
04151 struct client_state *client;
04152 {
04153 struct data_string ds;
04154 struct option_cache *oc;
04155
04156
04157 client -> xid = random ();
04158
04159
04160 if (client -> active) {
04161
04162
04163 make_release (client, client -> active);
04164
04165 memset (&ds, 0, sizeof ds);
04166 oc = lookup_option (&dhcp_universe,
04167 client -> active -> options,
04168 DHO_DHCP_SERVER_IDENTIFIER);
04169 if (oc &&
04170 evaluate_option_cache (&ds, (struct packet *)0,
04171 (struct lease *)0, client,
04172 (struct option_state *)0,
04173 client -> active -> options,
04174 &global_scope, oc, MDL)) {
04175 if (ds.len > 3) {
04176 memcpy (client -> destination.iabuf,
04177 ds.data, 4);
04178 client -> destination.len = 4;
04179 } else
04180 client -> destination = iaddr_broadcast;
04181
04182 data_string_forget (&ds, MDL);
04183 } else
04184 client -> destination = iaddr_broadcast;
04185 client -> first_sending = cur_time;
04186 client -> interval = client -> config -> initial_interval;
04187
04188
04189 client -> medium = (struct string_list *)0;
04190
04191
04192 send_release (client);
04193
04194
04195 script_init (client,
04196 "RELEASE", (struct string_list *)0);
04197 if (client -> alias)
04198 script_write_params (client, "alias_",
04199 client -> alias);
04200 script_write_params (client, "old_", client -> active);
04201 script_write_requested(client);
04202 script_go (client);
04203 }
04204
04205
04206 cancel_timeout (state_bound, client);
04207 cancel_timeout (send_discover, client);
04208 cancel_timeout (state_init, client);
04209 cancel_timeout (send_request, client);
04210 cancel_timeout (state_reboot, client);
04211 client -> state = S_STOPPED;
04212 }
04213
04214 int dhclient_interface_shutdown_hook (struct interface_info *interface)
04215 {
04216 do_release (interface -> client);
04217
04218 return 1;
04219 }
04220
04221 int dhclient_interface_discovery_hook (struct interface_info *tmp)
04222 {
04223 struct interface_info *last, *ip;
04224
04225 last = 0;
04226 for (ip = dummy_interfaces; ip; ip = ip -> next) {
04227 if (!strcmp (ip -> name, tmp -> name)) {
04228
04229 if (last) {
04230 ip = (struct interface_info *)0;
04231 interface_reference (&ip, last -> next, MDL);
04232 interface_dereference (&last -> next, MDL);
04233 if (ip -> next) {
04234 interface_reference (&last -> next,
04235 ip -> next, MDL);
04236 interface_dereference (&ip -> next,
04237 MDL);
04238 }
04239 } else {
04240 ip = (struct interface_info *)0;
04241 interface_reference (&ip,
04242 dummy_interfaces, MDL);
04243 interface_dereference (&dummy_interfaces, MDL);
04244 if (ip -> next) {
04245 interface_reference (&dummy_interfaces,
04246 ip -> next, MDL);
04247 interface_dereference (&ip -> next,
04248 MDL);
04249 }
04250 }
04251
04252 if (ip -> client) {
04253 tmp -> client = ip -> client;
04254 tmp -> client -> interface = tmp;
04255 }
04256 interface_dereference (&ip, MDL);
04257 break;
04258 }
04259 last = ip;
04260 }
04261 return 1;
04262 }
04263
04264 isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
04265 {
04266 struct interface_info *ip;
04267 struct client_state *client;
04268
04269
04270
04271
04272
04273 if (interfaces) {
04274 interface_reference (&interface -> next, interfaces, MDL);
04275 interface_dereference (&interfaces, MDL);
04276 }
04277 interface_reference (&interfaces, interface, MDL);
04278
04279 discover_interfaces (DISCOVER_UNCONFIGURED);
04280
04281 for (ip = interfaces; ip; ip = ip -> next) {
04282
04283
04284 if (ip -> flags & INTERFACE_RUNNING ||
04285 (ip -> flags & (INTERFACE_REQUESTED |
04286 INTERFACE_AUTOMATIC)) !=
04287 INTERFACE_REQUESTED)
04288 continue;
04289 script_init (ip -> client,
04290 "PREINIT", (struct string_list *)0);
04291 if (ip -> client -> alias)
04292 script_write_params (ip -> client, "alias_",
04293 ip -> client -> alias);
04294 script_go (ip -> client);
04295 }
04296
04297 discover_interfaces (interfaces_requested != 0
04298 ? DISCOVER_REQUESTED
04299 : DISCOVER_RUNNING);
04300
04301 for (ip = interfaces; ip; ip = ip -> next) {
04302 if (ip -> flags & INTERFACE_RUNNING)
04303 continue;
04304 ip -> flags |= INTERFACE_RUNNING;
04305 for (client = ip->client ; client ; client = client->next) {
04306 client->state = S_INIT;
04307 state_reboot(client);
04308 }
04309 }
04310 return ISC_R_SUCCESS;
04311 }
04312
04313
04314
04315
04316 int parse_agent_information_option (packet, len, data)
04317 struct packet *packet;
04318 int len;
04319 u_int8_t *data;
04320 {
04321 return 1;
04322 }
04323
04324
04325
04326 unsigned cons_agent_information_options (cfg_options, outpacket,
04327 agentix, length)
04328 struct option_state *cfg_options;
04329 struct dhcp_packet *outpacket;
04330 unsigned agentix;
04331 unsigned length;
04332 {
04333 return length;
04334 }
04335
04336 static void shutdown_exit (void *foo)
04337 {
04338 exit (0);
04339 }
04340
04341 #if defined (NSUPDATE)
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356 void
04357 client_dns_remove_action(dhcp_ddns_cb_t *ddns_cb,
04358 isc_result_t eresult)
04359 {
04360
04361 isc_result_t result;
04362
04363 if ((eresult == ISC_R_SUCCESS) &&
04364 (ddns_cb->state == DDNS_STATE_REM_FW_YXDHCID)) {
04365
04366 ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
04367
04368 result = ddns_modify_fwd(ddns_cb, MDL);
04369 if (result == ISC_R_SUCCESS) {
04370 return;
04371 }
04372 }
04373
04374
04375 ddns_cb_free(ddns_cb, MDL);
04376 return;
04377 }
04378
04379 void
04380 client_dns_remove(struct client_state *client,
04381 struct iaddr *addr)
04382 {
04383 dhcp_ddns_cb_t *ddns_cb;
04384 isc_result_t result;
04385
04386
04387 if (client->ddns_cb != NULL) {
04388 ddns_cancel(client->ddns_cb, MDL);
04389 client->ddns_cb = NULL;
04390 }
04391
04392 ddns_cb = ddns_cb_alloc(MDL);
04393 if (ddns_cb != NULL) {
04394 ddns_cb->address = *addr;
04395 ddns_cb->timeout = 0;
04396
04397 ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
04398 ddns_cb->flags = DDNS_UPDATE_ADDR;
04399 ddns_cb->cur_func = client_dns_remove_action;
04400
04401 result = client_dns_update(client, ddns_cb);
04402
04403 if (result != ISC_R_TIMEDOUT) {
04404 ddns_cb_free(ddns_cb, MDL);
04405 }
04406 }
04407 }
04408 #endif
04409
04410 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
04411 control_object_state_t newstate)
04412 {
04413 struct interface_info *ip;
04414 struct client_state *client;
04415 struct timeval tv;
04416
04417 if (newstate == server_shutdown) {
04418
04419 if (shutdown_signal == SIGUSR1)
04420 return ISC_R_SUCCESS;
04421
04422 if ((shutdown_signal == SIGINT) ||
04423 (shutdown_signal == SIGTERM)) {
04424 log_info("Received signal %d, initiating shutdown.",
04425 shutdown_signal);
04426 }
04427
04428 shutdown_signal = SIGUSR1;
04429 }
04430
04431
04432 for (ip = interfaces; ip; ip = ip -> next) {
04433 for (client = ip -> client; client; client = client -> next) {
04434 switch (newstate) {
04435 case server_startup:
04436 return ISC_R_SUCCESS;
04437
04438 case server_running:
04439 return ISC_R_SUCCESS;
04440
04441 case server_shutdown:
04442 if (client -> active &&
04443 client -> active -> expiry > cur_time) {
04444 #if defined (NSUPDATE)
04445 if (client->config->do_forward_update) {
04446 client_dns_remove(client,
04447 &client->active->address);
04448 }
04449 #endif
04450 do_release (client);
04451 }
04452 break;
04453
04454 case server_hibernate:
04455 state_stop (client);
04456 break;
04457
04458 case server_awaken:
04459 state_reboot (client);
04460 break;
04461 }
04462 }
04463 }
04464
04465 if (newstate == server_shutdown) {
04466 tv.tv_sec = cur_tv.tv_sec;
04467 tv.tv_usec = cur_tv.tv_usec + 1;
04468 add_timeout(&tv, shutdown_exit, 0, 0, 0);
04469 }
04470 return ISC_R_SUCCESS;
04471 }
04472
04473 #if defined (NSUPDATE)
04474
04475
04476
04477
04478
04479 void
04480 client_dns_update_timeout (void *cp)
04481 {
04482 dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)cp;
04483 struct client_state *client = (struct client_state *)ddns_cb->lease;
04484 isc_result_t status = ISC_R_FAILURE;
04485
04486 if ((client != NULL) &&
04487 ((client->active != NULL) ||
04488 (client->active_lease != NULL)))
04489 status = client_dns_update(client, ddns_cb);
04490
04491
04492
04493
04494
04495
04496
04497
04498
04499
04500 if (status != ISC_R_TIMEDOUT) {
04501 if (client != NULL) {
04502 client->ddns_cb = NULL;
04503 }
04504 ddns_cb_free(ddns_cb, MDL);
04505 }
04506 }
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522
04523
04524
04525
04526
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537 void
04538 client_dns_update_action(dhcp_ddns_cb_t *ddns_cb,
04539 isc_result_t eresult)
04540 {
04541 isc_result_t result;
04542 struct timeval tv;
04543
04544 switch(eresult) {
04545 case ISC_R_SUCCESS:
04546 default:
04547
04548 break;
04549
04550 case DNS_R_YXRRSET:
04551
04552
04553
04554
04555
04556 if (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) {
04557 ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
04558 ddns_cb->cur_func = client_dns_update_action;
04559
04560 result = ddns_modify_fwd(ddns_cb, MDL);
04561 if (result == ISC_R_SUCCESS) {
04562 return;
04563 }
04564 }
04565 break;
04566
04567 case ISC_R_TIMEDOUT:
04568
04569
04570
04571
04572
04573 data_string_forget(&ddns_cb->fwd_name, MDL);
04574 data_string_forget(&ddns_cb->dhcid, MDL);
04575 if (ddns_cb->zone != NULL) {
04576 forget_zone((struct dns_zone **)&ddns_cb->zone);
04577 }
04578
04579
04580 ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
04581 ddns_cb->cur_func = client_dns_update_action;
04582
04583
04584 if (ddns_cb->timeout < 3600)
04585 ddns_cb->timeout *= 10;
04586 tv.tv_sec = cur_tv.tv_sec + ddns_cb->timeout;
04587 tv.tv_usec = cur_tv.tv_usec;
04588 add_timeout(&tv, client_dns_update_timeout,
04589 ddns_cb, NULL, NULL);
04590 return;
04591 }
04592
04593 ddns_cb_free(ddns_cb, MDL);
04594 return;
04595 }
04596
04597
04598
04599 isc_result_t
04600 client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
04601 {
04602 struct data_string client_identifier;
04603 struct option_cache *oc;
04604 int ignorep;
04605 int result;
04606 int ddns_v4_type;
04607 isc_result_t rcode;
04608
04609
04610
04611 if (!client -> sent_options)
04612 return ISC_R_SUCCESS;
04613
04614
04615 if ((client->active == NULL) && (client->active_lease == NULL))
04616 return ISC_R_SUCCESS;
04617
04618
04619 if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
04620 FQDN_NO_CLIENT_UPDATE)) &&
04621 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
04622 (struct lease *)0, client,
04623 client -> sent_options,
04624 (struct option_state *)0,
04625 &global_scope, oc, MDL))
04626 return ISC_R_SUCCESS;
04627
04628
04629
04630 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
04631 FQDN_SERVER_UPDATE)) ||
04632 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
04633 (struct lease *)0, client,
04634 client -> sent_options,
04635 (struct option_state *)0,
04636 &global_scope, oc, MDL))
04637 return ISC_R_SUCCESS;
04638
04639
04640 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
04641 FQDN_FQDN)) ||
04642 !evaluate_option_cache (&ddns_cb->fwd_name, (struct packet *)0,
04643 (struct lease *)0, client,
04644 client -> sent_options,
04645 (struct option_state *)0,
04646 &global_scope, oc, MDL))
04647 return ISC_R_SUCCESS;
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657 result = 0;
04658 POST(result);
04659 memset(&client_identifier, 0, sizeof(client_identifier));
04660
04661 if (std_dhcid == 1) {
04662
04663 ddns_cb->dhcid_class = dns_rdatatype_dhcid;
04664 ddns_v4_type = 1;
04665 } else {
04666
04667 ddns_cb->dhcid_class = dns_rdatatype_txt;
04668
04669 ddns_v4_type = DHO_DHCP_CLIENT_IDENTIFIER;
04670 }
04671 if (client->active_lease != NULL) {
04672
04673
04674
04675 if (((oc = lookup_option(&dhcpv6_universe,
04676 client->sent_options,
04677 D6O_CLIENTID)) != NULL) &&
04678 evaluate_option_cache(&client_identifier, NULL,
04679 NULL, client,
04680 client->sent_options, NULL,
04681 &global_scope, oc, MDL)) {
04682 result = get_dhcid(ddns_cb, 2,
04683 client_identifier.data,
04684 client_identifier.len);
04685 data_string_forget(&client_identifier, MDL);
04686 } else
04687 log_fatal("Impossible condition at %s:%d.", MDL);
04688 } else {
04689
04690
04691
04692
04693
04694 if (((oc = lookup_option(&dhcp_universe,
04695 client->sent_options,
04696 DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
04697 evaluate_option_cache(&client_identifier, NULL,
04698 NULL, client,
04699 client->sent_options, NULL,
04700 &global_scope, oc, MDL)) {
04701 if ((std_dhcid == 1) && (duid_v4 == 1) &&
04702 (client_identifier.data[0] == 255)) {
04703
04704
04705
04706
04707 if (client_identifier.len <= 5)
04708 log_fatal("Impossible condition at %s:%d.",
04709 MDL);
04710 result = get_dhcid(ddns_cb, 2,
04711 client_identifier.data + 5,
04712 client_identifier.len - 5);
04713 } else {
04714 result = get_dhcid(ddns_cb, ddns_v4_type,
04715 client_identifier.data,
04716 client_identifier.len);
04717 }
04718 data_string_forget(&client_identifier, MDL);
04719 } else
04720 result = get_dhcid(ddns_cb, 0,
04721 client->interface->hw_address.hbuf,
04722 client->interface->hw_address.hlen);
04723 }
04724
04725 if (!result) {
04726 return ISC_R_SUCCESS;
04727 }
04728
04729
04730
04731
04732 if (ddns_cb->fwd_name.len && ddns_cb->dhcid.len) {
04733 rcode = ddns_modify_fwd(ddns_cb, MDL);
04734 } else
04735 rcode = ISC_R_FAILURE;
04736
04737
04738
04739
04740
04741 if (rcode == ISC_R_SUCCESS) {
04742 rcode = ISC_R_TIMEDOUT;
04743 }
04744
04745 return rcode;
04746 }
04747
04748
04749
04750
04751
04752
04753 void
04754 dhclient_schedule_updates(struct client_state *client,
04755 struct iaddr *addr,
04756 int offset)
04757 {
04758 dhcp_ddns_cb_t *ddns_cb;
04759 struct timeval tv;
04760
04761 if (!client->config->do_forward_update)
04762 return;
04763
04764
04765 if (client->ddns_cb != NULL) {
04766 ddns_cancel(client->ddns_cb, MDL);
04767 client->ddns_cb = NULL;
04768 }
04769
04770 ddns_cb = ddns_cb_alloc(MDL);
04771
04772 if (ddns_cb != NULL) {
04773 ddns_cb->lease = (void *)client;
04774 ddns_cb->address = *addr;
04775 ddns_cb->timeout = 1;
04776
04777
04778
04779
04780
04781
04782
04783 ddns_cb->ttl = 300;
04784
04785 ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
04786 ddns_cb->cur_func = client_dns_update_action;
04787 ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_INCLUDE_RRSET;
04788
04789 client->ddns_cb = ddns_cb;
04790
04791 tv.tv_sec = cur_tv.tv_sec + offset;
04792 tv.tv_usec = cur_tv.tv_usec;
04793 add_timeout(&tv, client_dns_update_timeout,
04794 ddns_cb, NULL, NULL);
04795 } else {
04796 log_error("Unable to allocate dns update state for %s",
04797 piaddr(*addr));
04798 }
04799 }
04800 #endif
04801
04802 void
04803 dhcpv4_client_assignments(void)
04804 {
04805 struct servent *ent;
04806
04807 if (path_dhclient_pid == NULL)
04808 path_dhclient_pid = _PATH_DHCLIENT_PID;
04809 if (path_dhclient_db == NULL)
04810 path_dhclient_db = _PATH_DHCLIENT_DB;
04811
04812
04813 if (!local_port) {
04814
04815
04816 if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
04817 local_port = htons(67);
04818 } else {
04819 ent = getservbyname ("dhcpc", "udp");
04820 if (!ent)
04821 local_port = htons (68);
04822 else
04823 local_port = ent -> s_port;
04824 #ifndef __CYGWIN32__
04825 endservent ();
04826 #endif
04827 }
04828 }
04829
04830
04831
04832 if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
04833 remote_port = local_port;
04834 } else
04835 remote_port = htons (ntohs (local_port) - 1);
04836 }
04837
04838
04839
04840
04841
04842
04843
04844
04845
04846
04847
04848 static int check_domain_name(const char *ptr, size_t len, int dots)
04849 {
04850 const char *p;
04851
04852
04853 if ((len == 0) || (len > 256))
04854 return(-1);
04855
04856
04857
04858 for (p=ptr; (*p != 0) && (len-- > 0); p++) {
04859 if ((*p == '-') || (*p == '_')) {
04860
04861 if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
04862 return(-1);
04863 } else if (*p == '.') {
04864
04865
04866 size_t d = p - ptr;
04867 if ((d <= 0) || (d >= 64))
04868 return(-1);
04869 ptr = p + 1;
04870 if ((dots > 0) && (len > 0))
04871 dots--;
04872 } else if (isalnum((unsigned char)*p) == 0) {
04873
04874 return(-1);
04875 }
04876 }
04877 return(dots ? -1 : 0);
04878 }
04879
04880 static int check_domain_name_list(const char *ptr, size_t len, int dots)
04881 {
04882 const char *p;
04883 int ret = -1;
04884
04885 if ((ptr == NULL) || (len == 0))
04886 return(-1);
04887
04888 for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
04889 if (*p != ' ')
04890 continue;
04891 if (p > ptr) {
04892 if (check_domain_name(ptr, p - ptr, dots) != 0)
04893 return(-1);
04894 ret = 0;
04895 }
04896 ptr = p + 1;
04897 }
04898 if (p > ptr)
04899 return(check_domain_name(ptr, p - ptr, dots));
04900 else
04901 return(ret);
04902 }
04903
04904 static int check_option_values(struct universe *universe,
04905 unsigned int opt,
04906 const char *ptr,
04907 size_t len)
04908 {
04909 if (ptr == NULL)
04910 return(-1);
04911
04912
04913 if ((universe == NULL) || (universe == &dhcp_universe)) {
04914 switch(opt) {
04915 case DHO_DOMAIN_NAME:
04916 #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
04917 return check_domain_name_list(ptr, len, 0);
04918 #else
04919 return check_domain_name(ptr, len, 0);
04920 #endif
04921 case DHO_HOST_NAME:
04922 case DHO_NIS_DOMAIN:
04923 case DHO_NETBIOS_SCOPE:
04924 return check_domain_name(ptr, len, 0);
04925 break;
04926 case DHO_DOMAIN_SEARCH:
04927 return check_domain_name_list(ptr, len, 0);
04928 break;
04929 case DHO_ROOT_PATH:
04930 if (len == 0)
04931 return(-1);
04932 for (; (*ptr != 0) && (len-- > 0); ptr++) {
04933 if(!(isalnum((unsigned char)*ptr) ||
04934 *ptr == '#' || *ptr == '%' ||
04935 *ptr == '+' || *ptr == '-' ||
04936 *ptr == '_' || *ptr == ':' ||
04937 *ptr == '.' || *ptr == ',' ||
04938 *ptr == '@' || *ptr == '~' ||
04939 *ptr == '\\' || *ptr == '/' ||
04940 *ptr == '[' || *ptr == ']' ||
04941 *ptr == '=' || *ptr == ' '))
04942 return(-1);
04943 }
04944 return(0);
04945 break;
04946 }
04947 }
04948
04949 #ifdef DHCPv6
04950 if (universe == &dhcpv6_universe) {
04951 switch(opt) {
04952 case D6O_SIP_SERVERS_DNS:
04953 case D6O_DOMAIN_SEARCH:
04954 case D6O_NIS_DOMAIN_NAME:
04955 case D6O_NISP_DOMAIN_NAME:
04956 return check_domain_name_list(ptr, len, 0);
04957 break;
04958 }
04959 }
04960 #endif
04961
04962 return(0);
04963 }
04964
04965 static void
04966 add_reject(struct packet *packet) {
04967 struct iaddrmatchlist *list;
04968
04969 list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
04970 if (!list)
04971 log_fatal ("no memory for reject list!");
04972
04973
04974
04975
04976
04977 list->match.addr = packet->client_addr;
04978
04979 list->match.mask.len = list->match.addr.len;
04980 memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
04981
04982
04983 list->next = packet->interface->client->config->reject_list;
04984 packet->interface->client->config->reject_list = list;
04985
04986
04987
04988
04989
04990 log_info("Server added to list of rejected servers.");
04991 }
04992