]> git.ipfire.org Git - thirdparty/dhcp.git/blame - client/dhclient.c
Support for asynchronous ddns per ticket 19216 - convert to using isclib and
[thirdparty/dhcp.git] / client / dhclient.c
CommitLineData
469cf3a4 1/* dhclient.c
95821729 2
9bdb9271 3 DHCP Client. */
95821729
TL
4
5/*
ae566556 6 * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 7 * Copyright (c) 1995-2003 by Internet Software Consortium
95821729 8 *
98311e4b
DH
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
95821729 12 *
98311e4b
DH
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
95821729 20 *
98311e4b
DH
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
2c85ac9b 25 * https://www.isc.org/
31730f17 26 *
3b106356
TL
27 * This code is based on the original client state machine that was
28 * written by Elliot Poger. The code has been extensively hacked on
29 * by Ted Lemon since then, so any mistakes you find are probably his
30 * fault and not Elliot's.
95821729
TL
31 */
32
c1503c57 33#include "dhcpd.h"
fe5b0fdd
DH
34#include <syslog.h>
35#include <signal.h>
36#include <errno.h>
be62cf06 37#include <sys/time.h>
fe5b0fdd 38#include <sys/wait.h>
e847f983 39#include <limits.h>
98bf1607 40#include <dns/result.h>
e581d615 41
4a0d788a
TL
42TIME default_lease_time = 43200; /* 12 hours... */
43TIME max_lease_time = 86400; /* 24 hours... */
44
b1b7b521 45const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
98bd7ca0
DH
46const char *path_dhclient_db = NULL;
47const char *path_dhclient_pid = NULL;
420d8b3f 48static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
c08637bb 49char *path_dhclient_script = path_dhclient_script_array;
cc26de46 50
36f5cb7c
TL
51int dhcp_max_agent_option_packet_length = 0;
52
b8cf055d
TL
53int interfaces_requested = 0;
54
cc26de46
TL
55struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
56struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
48d68880 57struct in_addr inaddr_any;
cc26de46 58struct sockaddr_in sockaddr_broadcast;
11373fb6 59struct in_addr giaddr;
98bd7ca0 60struct data_string default_duid;
a41d7a25 61int duid_type = 0;
469cf3a4 62
cc26de46
TL
63/* ASSERT_STATE() does nothing now; it used to be
64 assert (state_is == state_shouldbe). */
65#define ASSERT_STATE(state_is, state_shouldbe) {}
469cf3a4 66
ae566556
SR
67static const char copyright[] = "Copyright 2004-2009 Internet Systems Consortium.";
68static const char arr [] = "All rights reserved.";
69static const char message [] = "Internet Systems Consortium DHCP Client";
2c85ac9b 70static const char url [] = "For info, please visit https://www.isc.org/software/dhcp/";
c1503c57 71
420d8b3f
FD
72u_int16_t local_port = 0;
73u_int16_t remote_port = 0;
74int no_daemon = 0;
75struct string_list *client_env = NULL;
76int client_env_count = 0;
77int onetry = 0;
78int quiet = 1;
79int nowait = 0;
80int stateless = 0;
81int wanted_ia_na = -1; /* the absolute value is the real one. */
82int wanted_ia_ta = 0;
83int wanted_ia_pd = 0;
98bd7ca0 84char *mockup_relay = NULL;
c1503c57 85
3dbe2246
FD
86void run_stateless(int exit_mode);
87
420d8b3f 88static void usage(void);
95821729 89
98bd7ca0
DH
90static isc_result_t write_duid(struct data_string *duid);
91
3dbe2246 92int
98bd7ca0 93main(int argc, char **argv) {
185d16f9 94 int fd;
c1503c57 95 int i;
cc26de46 96 struct interface_info *ip;
02d9e453 97 struct client_state *client;
b1b7b521 98 unsigned seed;
420d8b3f 99 char *server = NULL;
628beb0e 100 isc_result_t status;
3dbe2246
FD
101 int exit_mode = 0;
102 int release_mode = 0;
be62cf06 103 struct timeval tv;
347de8bd
TL
104 omapi_object_t *listener;
105 isc_result_t result;
134ceef8 106 int persist = 0;
cfa7212d
TL
107 int no_dhclient_conf = 0;
108 int no_dhclient_db = 0;
109 int no_dhclient_pid = 0;
c08637bb 110 int no_dhclient_script = 0;
c998be87 111#ifdef DHCPv6
98bd7ca0 112 int local_family_set = 0;
c998be87 113#endif /* DHCPv6 */
cfa7212d 114 char *s;
6c6d5928 115
98bd7ca0
DH
116 /* Initialize client globals. */
117 memset(&default_duid, 0, sizeof(default_duid));
118
3dbe2246
FD
119 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
120 2 (stderr) are open. To do this, we assume that when we
121 open a file the lowest available file descriptor is used. */
122 fd = open("/dev/null", O_RDWR);
123 if (fd == 0)
124 fd = open("/dev/null", O_RDWR);
125 if (fd == 1)
126 fd = open("/dev/null", O_RDWR);
127 if (fd == 2)
128 log_perror = 0; /* No sense logging to /dev/null. */
129 else if (fd != -1)
130 close(fd);
ee8a3653 131
420d8b3f 132 openlog("dhclient", LOG_NDELAY, LOG_DAEMON);
95821729 133
420d8b3f
FD
134#if !(defined(DEBUG) || defined(__CYGWIN32__))
135 setlogmask(LOG_UPTO(LOG_INFO));
3dbe2246 136#endif
c1503c57 137
98bf1607
SR
138 /* Set up the isc and dns library managers */
139 status = dhcp_context_create();
140 if (status != ISC_R_SUCCESS)
141 log_fatal("Can't initialize context: %s",
142 isc_result_totext(status));
143
67569fa6 144 /* Set up the OMAPI. */
420d8b3f 145 status = omapi_init();
67569fa6 146 if (status != ISC_R_SUCCESS)
420d8b3f
FD
147 log_fatal("Can't initialize OMAPI: %s",
148 isc_result_totext(status));
67569fa6
TL
149
150 /* Set up the OMAPI wrappers for various server database internal
151 objects. */
420d8b3f 152 dhcp_common_objects_setup();
67569fa6
TL
153
154 dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
155 dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
57710b89 156 dhcp_interface_startup_hook = dhclient_interface_startup_hook;
67569fa6 157
c1503c57 158 for (i = 1; i < argc; i++) {
3dbe2246 159 if (!strcmp(argv[i], "-r")) {
182b187e
EH
160 release_mode = 1;
161 no_daemon = 1;
162#ifdef DHCPv6
163 } else if (!strcmp(argv[i], "-4")) {
98bd7ca0
DH
164 if (local_family_set && local_family != AF_INET)
165 log_fatal("Client can only do v4 or v6, not "
166 "both.");
167 local_family_set = 1;
168 local_family = AF_INET;
169 } else if (!strcmp(argv[i], "-6")) {
170 if (local_family_set && local_family != AF_INET6)
171 log_fatal("Client can only do v4 or v6, not "
172 "both.");
173 local_family_set = 1;
174 local_family = AF_INET6;
182b187e 175#endif /* DHCPv6 */
420d8b3f 176 } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
3dbe2246
FD
177 release_mode = 0;
178 no_daemon = 0;
179 exit_mode = 1;
420d8b3f 180 } else if (!strcmp(argv[i], "-p")) {
c1503c57 181 if (++i == argc)
420d8b3f 182 usage();
59112e84 183 local_port = validate_port(argv[i]);
420d8b3f
FD
184 log_debug("binding to user-specified port %d",
185 ntohs(local_port));
186 } else if (!strcmp(argv[i], "-d")) {
b00d3884 187 no_daemon = 1;
8ea19a71 188 quiet = 0;
420d8b3f 189 } else if (!strcmp(argv[i], "-pf")) {
3dbe2246 190 if (++i == argc)
420d8b3f
FD
191 usage();
192 path_dhclient_pid = argv[i];
cfa7212d 193 no_dhclient_pid = 1;
420d8b3f 194 } else if (!strcmp(argv[i], "-cf")) {
3dbe2246 195 if (++i == argc)
420d8b3f
FD
196 usage();
197 path_dhclient_conf = argv[i];
cfa7212d 198 no_dhclient_conf = 1;
420d8b3f 199 } else if (!strcmp(argv[i], "-lf")) {
3dbe2246 200 if (++i == argc)
420d8b3f
FD
201 usage();
202 path_dhclient_db = argv[i];
cfa7212d 203 no_dhclient_db = 1;
420d8b3f 204 } else if (!strcmp(argv[i], "-sf")) {
c08637bb 205 if (++i == argc)
420d8b3f
FD
206 usage();
207 path_dhclient_script = argv[i];
c08637bb 208 no_dhclient_script = 1;
420d8b3f 209 } else if (!strcmp(argv[i], "-1")) {
c08637bb 210 onetry = 1;
420d8b3f 211 } else if (!strcmp(argv[i], "-q")) {
62d0cb47 212 quiet = 1;
420d8b3f 213 } else if (!strcmp(argv[i], "-s")) {
3020a2c1 214 if (++i == argc)
420d8b3f
FD
215 usage();
216 server = argv[i];
217 } else if (!strcmp(argv[i], "-g")) {
11373fb6 218 if (++i == argc)
420d8b3f
FD
219 usage();
220 mockup_relay = argv[i];
221 } else if (!strcmp(argv[i], "-nw")) {
98311e4b 222 nowait = 1;
420d8b3f 223 } else if (!strcmp(argv[i], "-n")) {
347de8bd 224 /* do not start up any interfaces */
3dbe2246 225 interfaces_requested = -1;
420d8b3f 226 } else if (!strcmp(argv[i], "-w")) {
134ceef8
TL
227 /* do not exit if there are no broadcast interfaces. */
228 persist = 1;
420d8b3f 229 } else if (!strcmp(argv[i], "-e")) {
b1423aed
TL
230 struct string_list *tmp;
231 if (++i == argc)
420d8b3f
FD
232 usage();
233 tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
b1423aed 234 if (!tmp)
420d8b3f
FD
235 log_fatal("No memory for %s", argv[i]);
236 strcpy(tmp->string, argv[i]);
237 tmp->next = client_env;
b1423aed
TL
238 client_env = tmp;
239 client_env_count++;
420d8b3f 240#ifdef DHCPv6
3dbe2246
FD
241 } else if (!strcmp(argv[i], "-S")) {
242 if (local_family_set && (local_family == AF_INET)) {
420d8b3f 243 usage();
3dbe2246
FD
244 }
245 local_family_set = 1;
246 local_family = AF_INET6;
420d8b3f 247 wanted_ia_na = 0;
3dbe2246 248 stateless = 1;
420d8b3f
FD
249 } else if (!strcmp(argv[i], "-N")) {
250 if (local_family_set && (local_family == AF_INET)) {
251 usage();
252 }
253 local_family_set = 1;
254 local_family = AF_INET6;
255 if (wanted_ia_na < 0) {
256 wanted_ia_na = 0;
257 }
258 wanted_ia_na++;
259 } else if (!strcmp(argv[i], "-T")) {
260 if (local_family_set && (local_family == AF_INET)) {
261 usage();
262 }
263 local_family_set = 1;
264 local_family = AF_INET6;
265 if (wanted_ia_na < 0) {
266 wanted_ia_na = 0;
267 }
268 wanted_ia_ta++;
269 } else if (!strcmp(argv[i], "-P")) {
270 if (local_family_set && (local_family == AF_INET)) {
271 usage();
272 }
273 local_family_set = 1;
274 local_family = AF_INET6;
275 if (wanted_ia_na < 0) {
276 wanted_ia_na = 0;
277 }
278 wanted_ia_pd++;
a41d7a25
PS
279 } else if (!strcmp(argv[i], "-D")) {
280 if (local_family_set && (local_family == AF_INET)) {
281 usage();
282 }
283 local_family_set = 1;
284 local_family = AF_INET6;
285 if (++i == argc)
286 usage();
287 if (!strcasecmp(argv[i], "LL")) {
288 duid_type = DUID_LL;
289 } else if (!strcasecmp(argv[i], "LLT")) {
290 duid_type = DUID_LLT;
291 } else {
292 usage();
293 }
420d8b3f 294#endif /* DHCPv6 */
8ea19a71
DH
295 } else if (!strcmp(argv[i], "-v")) {
296 quiet = 0;
420d8b3f
FD
297 } else if (!strcmp(argv[i], "--version")) {
298 log_info("isc-dhclient-%s", PACKAGE_VERSION);
299 exit(0);
300 } else if (argv[i][0] == '-') {
301 usage();
3dbe2246 302 } else if (interfaces_requested < 0) {
420d8b3f 303 usage();
98311e4b 304 } else {
420d8b3f
FD
305 struct interface_info *tmp = NULL;
306
307 status = interface_allocate(&tmp, MDL);
3dbe2246 308 if (status != ISC_R_SUCCESS)
420d8b3f
FD
309 log_fatal("Can't record interface %s:%s",
310 argv[i], isc_result_totext(status));
88cd8aca
DH
311 if (strlen(argv[i]) >= sizeof(tmp->name))
312 log_fatal("%s: interface name too long (is %ld)",
420d8b3f 313 argv[i], (long)strlen(argv[i]));
88cd8aca 314 strcpy(tmp->name, argv[i]);
20916cae 315 if (interfaces) {
420d8b3f
FD
316 interface_reference(&tmp->next,
317 interfaces, MDL);
318 interface_dereference(&interfaces, MDL);
20916cae 319 }
420d8b3f
FD
320 interface_reference(&interfaces, tmp, MDL);
321 tmp->flags = INTERFACE_REQUESTED;
3dbe2246
FD
322 interfaces_requested++;
323 }
c1503c57 324 }
62d0cb47 325
420d8b3f
FD
326 if (wanted_ia_na < 0) {
327 wanted_ia_na = 1;
328 }
329
330 /* Support only one (requested) interface for Prefix Delegation. */
331 if (wanted_ia_pd && (interfaces_requested != 1)) {
332 usage();
333 }
334
335 if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
cfa7212d
TL
336 path_dhclient_conf = s;
337 }
420d8b3f 338 if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
cfa7212d
TL
339 path_dhclient_db = s;
340 }
420d8b3f 341 if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
cfa7212d
TL
342 path_dhclient_pid = s;
343 }
420d8b3f 344 if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
c08637bb
TL
345 path_dhclient_script = s;
346 }
cfa7212d 347
98bd7ca0
DH
348 /* Set up the initial dhcp option universe. */
349 initialize_common_option_spaces();
350
351 /* Assign v4 or v6 specific running parameters. */
352 if (local_family == AF_INET)
353 dhcpv4_client_assignments();
fe5b0fdd 354#ifdef DHCPv6
98bd7ca0
DH
355 else if (local_family == AF_INET6)
356 dhcpv6_client_assignments();
fe5b0fdd 357#endif /* DHCPv6 */
98bd7ca0
DH
358 else
359 log_fatal("Impossible condition at %s:%d.", MDL);
360
a546f2a7
EH
361 /*
362 * convert relative path names to absolute, for files that need
363 * to be reopened after chdir() has been called
364 */
365 if (path_dhclient_db[0] != '/') {
366 char *path = dmalloc(PATH_MAX, MDL);
367 if (path == NULL)
368 log_fatal("No memory for filename\n");
420d8b3f 369 path_dhclient_db = realpath(path_dhclient_db, path);
a546f2a7
EH
370 if (path_dhclient_db == NULL)
371 log_fatal("%s: %s", path, strerror(errno));
372 }
3dbe2246 373
a546f2a7
EH
374 if (path_dhclient_script[0] != '/') {
375 char *path = dmalloc(PATH_MAX, MDL);
376 if (path == NULL)
377 log_fatal("No memory for filename\n");
420d8b3f 378 path_dhclient_script = realpath(path_dhclient_script, path);
a546f2a7
EH
379 if (path_dhclient_script == NULL)
380 log_fatal("%s: %s", path, strerror(errno));
381 }
3dbe2246 382
a546f2a7 383 /* first kill off any currently running client */
af5fa176 384 if (release_mode || exit_mode) {
98311e4b
DH
385 FILE *pidfd;
386 pid_t oldpid;
387 long temp;
388 int e;
389
390 oldpid = 0;
391 if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
392 e = fscanf(pidfd, "%ld\n", &temp);
393 oldpid = (pid_t)temp;
394
395 if (e != 0 && e != EOF) {
182b187e
EH
396 if (oldpid)
397 kill(oldpid, SIGTERM);
98311e4b
DH
398 }
399 fclose(pidfd);
400 }
347de8bd
TL
401 }
402
62d0cb47 403 if (!quiet) {
420d8b3f
FD
404 log_info("%s %s", message, PACKAGE_VERSION);
405 log_info(copyright);
406 log_info(arr);
407 log_info(url);
408 log_info("%s", "");
8ea19a71 409 } else {
78a33b82 410 log_perror = 0;
8ea19a71
DH
411 quiet_interface_discovery = 1;
412 }
62d0cb47 413
11373fb6
TL
414 /* If we're given a relay agent address to insert, for testing
415 purposes, figure out what it is. */
98bd7ca0 416 if (mockup_relay) {
420d8b3f 417 if (!inet_aton(mockup_relay, &giaddr)) {
11373fb6 418 struct hostent *he;
420d8b3f 419 he = gethostbyname(mockup_relay);
11373fb6 420 if (he) {
420d8b3f
FD
421 memcpy(&giaddr, he->h_addr_list[0],
422 sizeof giaddr);
11373fb6 423 } else {
420d8b3f 424 log_fatal("%s: no such host", mockup_relay);
11373fb6
TL
425 }
426 }
427 }
428
95821729 429 /* Get the current time... */
be62cf06 430 gettimeofday(&cur_tv, NULL);
95821729 431
b00d3884 432 sockaddr_broadcast.sin_family = AF_INET;
cc26de46 433 sockaddr_broadcast.sin_port = remote_port;
3020a2c1 434 if (server) {
420d8b3f 435 if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
3020a2c1 436 struct hostent *he;
420d8b3f 437 he = gethostbyname(server);
3020a2c1 438 if (he) {
420d8b3f
FD
439 memcpy(&sockaddr_broadcast.sin_addr,
440 he->h_addr_list[0],
441 sizeof sockaddr_broadcast.sin_addr);
3020a2c1
TL
442 } else
443 sockaddr_broadcast.sin_addr.s_addr =
444 INADDR_BROADCAST;
445 }
446 } else {
447 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
448 }
11373fb6 449
48d68880 450 inaddr_any.s_addr = INADDR_ANY;
469cf3a4 451
3dbe2246
FD
452 /* Stateless special case. */
453 if (stateless) {
420d8b3f
FD
454 if (release_mode || (wanted_ia_na > 0) ||
455 wanted_ia_ta || wanted_ia_pd ||
456 (interfaces_requested != 1)) {
457 usage();
3dbe2246 458 }
420d8b3f 459 run_stateless(exit_mode);
3dbe2246
FD
460 return 0;
461 }
462
cc26de46 463 /* Discover all the network interfaces. */
420d8b3f 464 discover_interfaces(DISCOVER_UNCONFIGURED);
469cf3a4 465
cc26de46 466 /* Parse the dhclient.conf file. */
420d8b3f 467 read_client_conf();
469cf3a4 468
cc26de46 469 /* Parse the lease database. */
420d8b3f 470 read_client_leases();
469cf3a4 471
cc26de46 472 /* Rewrite the lease database... */
420d8b3f 473 rewrite_client_leases();
469cf3a4 474
ce0ec46d
TL
475 /* XXX */
476/* config_counter(&snd_counter, &rcv_counter); */
477
420d8b3f
FD
478 /*
479 * If no broadcast interfaces were discovered, call the script
480 * and tell it so.
481 */
cc26de46 482 if (!interfaces) {
420d8b3f
FD
483 /*
484 * Call dhclient-script with the NBI flag,
485 * in case somebody cares.
486 */
487 script_init(NULL, "NBI", NULL);
488 script_go(NULL);
489
490 /*
491 * If we haven't been asked to persist, waiting for new
492 * interfaces, then just exit.
493 */
134ceef8
TL
494 if (!persist) {
495 /* Nothing more to do. */
420d8b3f
FD
496 log_info("No broadcast interfaces found - exiting.");
497 exit(0);
134ceef8 498 }
af5fa176 499 } else if (!release_mode && !exit_mode) {
cc26de46 500 /* Call the script with the list of interfaces. */
420d8b3f
FD
501 for (ip = interfaces; ip; ip = ip->next) {
502 /*
503 * If interfaces were specified, don't configure
504 * interfaces that weren't specified!
505 */
3dbe2246 506 if ((interfaces_requested > 0) &&
420d8b3f
FD
507 ((ip->flags & (INTERFACE_REQUESTED |
508 INTERFACE_AUTOMATIC)) !=
62d0cb47 509 INTERFACE_REQUESTED))
5c2f78b4 510 continue;
98bd7ca0
DH
511
512 if (local_family == AF_INET6) {
513 script_init(ip->client, "PREINIT6", NULL);
514 } else {
515 script_init(ip->client, "PREINIT", NULL);
516 if (ip->client->alias != NULL)
517 script_write_params(ip->client,
518 "alias_",
519 ip->client->alias);
520 }
420d8b3f 521 script_go(ip->client);
cc26de46
TL
522 }
523 }
469cf3a4 524
cc26de46
TL
525 /* At this point, all the interfaces that the script thinks
526 are relevant should be running, so now we once again call
527 discover_interfaces(), and this time ask it to actually set
528 up the interfaces. */
420d8b3f
FD
529 discover_interfaces(interfaces_requested != 0
530 ? DISCOVER_REQUESTED
531 : DISCOVER_RUNNING);
cc26de46 532
66f973e4
TL
533 /* Make up a seed for the random number generator from current
534 time plus the sum of the last four bytes of each
535 interface's hardware address interpreted as an integer.
536 Not much entropy, but we're booting, so we're not likely to
537 find anything better. */
02d9e453 538 seed = 0;
420d8b3f 539 for (ip = interfaces; ip; ip = ip->next) {
66f973e4 540 int junk;
420d8b3f
FD
541 memcpy(&junk,
542 &ip->hw_address.hbuf[ip->hw_address.hlen -
543 sizeof seed], sizeof seed);
66f973e4
TL
544 seed += junk;
545 }
420d8b3f 546 srandom(seed + cur_time);
66f973e4 547
cc26de46 548 /* Start a configuration state machine for each interface. */
fe5b0fdd 549#ifdef DHCPv6
98bd7ca0 550 if (local_family == AF_INET6) {
98bd7ca0
DH
551 /* Establish a default DUID. This may be moved to the
552 * DHCPv4 area later.
553 */
554 if (default_duid.len == 0) {
555 if (default_duid.buffer != NULL)
556 data_string_forget(&default_duid, MDL);
557
558 form_duid(&default_duid, MDL);
559 write_duid(&default_duid);
560 }
561
562 for (ip = interfaces ; ip != NULL ; ip = ip->next) {
563 for (client = ip->client ; client != NULL ;
564 client = client->next) {
3dbe2246
FD
565 if (release_mode) {
566 start_release6(client);
567 continue;
568 } else if (exit_mode) {
569 unconfigure6(client, "STOP6");
570 continue;
571 }
af5fa176 572
98bd7ca0
DH
573 /* If we have a previous binding, Confirm
574 * that we can (or can't) still use it.
575 */
cabdb9b1
FD
576 if ((client->active_lease != NULL) &&
577 !client->active_lease->released)
98bd7ca0
DH
578 start_confirm6(client);
579 else
580 start_init6(client);
581 }
582 }
3dbe2246 583 } else
fe5b0fdd
DH
584#endif /* DHCPv6 */
585 {
98bd7ca0
DH
586 for (ip = interfaces ; ip ; ip = ip->next) {
587 ip->flags |= INTERFACE_RUNNING;
588 for (client = ip->client ; client ;
589 client = client->next) {
3dbe2246
FD
590 if (exit_mode)
591 state_stop(client);
592 else if (release_mode)
98bd7ca0
DH
593 do_release(client);
594 else {
595 client->state = S_INIT;
596 /* Set up a timeout to start the
597 * initialization process.
598 */
be62cf06
FD
599 tv.tv_sec = cur_time + random() % 5;
600 tv.tv_usec = 0;
601 add_timeout(&tv, state_reboot,
602 client, 0, 0);
98bd7ca0 603 }
347de8bd 604 }
02d9e453 605 }
cc26de46 606 }
469cf3a4 607
87202683 608 if (exit_mode)
347de8bd 609 return 0;
87202683
FD
610 if (release_mode) {
611#ifndef DHCPv6
612 return 0;
613#else
614 if (local_family == AF_INET6) {
615 if (onetry)
616 return 0;
617 } else
618 return 0;
619#endif /* DHCPv6 */
620 }
347de8bd
TL
621
622 /* Start up a listener for the object management API protocol. */
40a59753 623 if (top_level_config.omapi_port != -1) {
420d8b3f
FD
624 listener = NULL;
625 result = omapi_generic_new(&listener, MDL);
40a59753 626 if (result != ISC_R_SUCCESS)
420d8b3f
FD
627 log_fatal("Can't allocate new generic object: %s\n",
628 isc_result_totext(result));
629 result = omapi_protocol_listen(listener,
630 (unsigned)
631 top_level_config.omapi_port,
632 1);
40a59753 633 if (result != ISC_R_SUCCESS)
420d8b3f
FD
634 log_fatal("Can't start OMAPI protocol: %s",
635 isc_result_totext (result));
40a59753 636 }
347de8bd 637
84c4adde
TL
638 /* Set up the bootp packet handler... */
639 bootp_packet_handler = do_packet;
fe5b0fdd 640#ifdef DHCPv6
98bd7ca0 641 dhcpv6_packet_handler = do_packet6;
fe5b0fdd 642#endif /* DHCPv6 */
84c4adde 643
420d8b3f
FD
644#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
645 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1c44f6bd
TL
646 dmalloc_cutoff_generation = dmalloc_generation;
647 dmalloc_longterm = dmalloc_outstanding;
648 dmalloc_outstanding = 0;
649#endif
650
37c1f13f
TL
651 /* If we're not supposed to wait before getting the address,
652 don't. */
653 if (nowait)
420d8b3f 654 go_daemon();
37c1f13f 655
b1423aed
TL
656 /* If we're not going to daemonize, write the pid file
657 now. */
37c1f13f 658 if (no_daemon || nowait)
420d8b3f 659 write_client_pid_file();
b1423aed 660
cc26de46 661 /* Start dispatching packets and timeouts... */
420d8b3f 662 dispatch();
84c4adde 663
cc26de46
TL
664 /*NOTREACHED*/
665 return 0;
469cf3a4
TL
666}
667
420d8b3f 668static void usage()
c1503c57 669{
420d8b3f
FD
670 log_info("%s %s", message, PACKAGE_VERSION);
671 log_info(copyright);
672 log_info(arr);
673 log_info(url);
89c425dd 674
420d8b3f 675 log_error("Usage: dhclient %s %s",
182b187e 676#ifdef DHCPv6
a41d7a25 677 "[-4|-6] [-SNTP1dvrx] [-nw] [-p <port>] [-D LL|LLT]",
182b187e 678#else /* DHCPv6 */
420d8b3f 679 "[-1dvrx] [-nw] [-p <port>]",
182b187e 680#endif /* DHCPv6 */
420d8b3f
FD
681 "[-s server]");
682 log_error(" [-cf config-file] [-lf lease-file]%s",
683 "[-pf pid-file] [-e VAR=val]");
684 log_fatal(" [-sf script-file] [interface]");
c1503c57
TL
685}
686
3dbe2246
FD
687void run_stateless(int exit_mode)
688{
420d8b3f 689#ifdef DHCPv6
3dbe2246
FD
690 struct client_state *client;
691 omapi_object_t *listener;
692 isc_result_t result;
693
694 /* Discover the network interface. */
695 discover_interfaces(DISCOVER_REQUESTED);
696
697 if (!interfaces)
698 usage();
699
700 /* Parse the dhclient.conf file. */
701 read_client_conf();
702
703 /* Parse the lease database. */
704 read_client_leases();
705
706 /* Establish a default DUID. */
707 if (default_duid.len == 0) {
708 if (default_duid.buffer != NULL)
709 data_string_forget(&default_duid, MDL);
710
711 form_duid(&default_duid, MDL);
712 }
713
714 /* Start a configuration state machine. */
715 for (client = interfaces->client ;
716 client != NULL ;
717 client = client->next) {
718 if (exit_mode) {
719 unconfigure6(client, "STOP6");
720 continue;
721 }
722 start_info_request6(client);
723 }
724 if (exit_mode)
725 return;
726
727 /* Start up a listener for the object management API protocol. */
728 if (top_level_config.omapi_port != -1) {
420d8b3f 729 listener = NULL;
3dbe2246
FD
730 result = omapi_generic_new(&listener, MDL);
731 if (result != ISC_R_SUCCESS)
732 log_fatal("Can't allocate new generic object: %s\n",
733 isc_result_totext(result));
734 result = omapi_protocol_listen(listener,
735 (unsigned)
736 top_level_config.omapi_port,
737 1);
738 if (result != ISC_R_SUCCESS)
739 log_fatal("Can't start OMAPI protocol: %s",
740 isc_result_totext(result));
741 }
742
743 /* Set up the packet handler... */
744 dhcpv6_packet_handler = do_packet6;
745
420d8b3f
FD
746#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
747 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
3dbe2246
FD
748 dmalloc_cutoff_generation = dmalloc_generation;
749 dmalloc_longterm = dmalloc_outstanding;
750 dmalloc_outstanding = 0;
751#endif
752
753 /* If we're not supposed to wait before getting the address,
754 don't. */
755 if (nowait)
756 go_daemon();
757
758 /* If we're not going to daemonize, write the pid file
759 now. */
760 if (no_daemon || nowait)
761 write_client_pid_file();
762
763 /* Start dispatching packets and timeouts... */
764 dispatch();
765
766 /*NOTREACHED*/
420d8b3f 767#endif /* DHCPv6 */
3dbe2246
FD
768 return;
769}
770
20916cae
TL
771isc_result_t find_class (struct class **c,
772 const char *s, const char *file, int line)
02a015fb 773{
20916cae 774 return 0;
02a015fb
TL
775}
776
da38df14 777int check_collection (packet, lease, collection)
02a015fb 778 struct packet *packet;
da38df14 779 struct lease *lease;
02a015fb
TL
780 struct collection *collection;
781{
782 return 0;
783}
784
785void classify (packet, class)
786 struct packet *packet;
787 struct class *class;
788{
789}
790
73530742
TL
791int unbill_class (lease, class)
792 struct lease *lease;
793 struct class *class;
794{
795 return 0;
796}
797
20916cae
TL
798int find_subnet (struct subnet **sp,
799 struct iaddr addr, const char *file, int line)
bfdb842e 800{
20916cae 801 return 0;
bfdb842e
TL
802}
803
469cf3a4 804/* Individual States:
3dbe2246 805 *
469cf3a4
TL
806 * Each routine is called from the dhclient_state_machine() in one of
807 * these conditions:
808 * -> entering INIT state
809 * -> recvpacket_flag == 0: timeout in this state
810 * -> otherwise: received a packet in this state
811 *
812 * Return conditions as handled by dhclient_state_machine():
813 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
814 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
815 * Returns 0: finish the nap which was interrupted for no good reason.
816 *
cc26de46
TL
817 * Several per-interface variables are used to keep track of the process:
818 * active_lease: the lease that is being used on the interface
819 * (null pointer if not configured yet).
820 * offered_leases: leases corresponding to DHCPOFFER messages that have
821 * been sent to us by DHCP servers.
822 * acked_leases: leases corresponding to DHCPACK messages that have been
823 * sent to us by DHCP servers.
824 * sendpacket: DHCP packet we're trying to send.
469cf3a4 825 * destination: IP address to send sendpacket to
cc26de46 826 * In addition, there are several relevant per-lease variables.
469cf3a4 827 * T1_expiry, T2_expiry, lease_expiry: lease milestones
cc26de46
TL
828 * In the active lease, these control the process of renewing the lease;
829 * In leases on the acked_leases list, this simply determines when we
830 * can no longer legitimately use the lease.
469cf3a4
TL
831 */
832
02d9e453
TL
833void state_reboot (cpp)
834 void *cpp;
deff2d59 835{
02d9e453 836 struct client_state *client = cpp;
84c4adde 837
deff2d59 838 /* If we don't remember an active lease, go straight to INIT. */
02d9e453 839 if (!client -> active ||
d758ad8c
TL
840 client -> active -> is_bootp ||
841 client -> active -> expiry <= cur_time) {
02d9e453 842 state_init (client);
deff2d59
TL
843 return;
844 }
845
846 /* We are in the rebooting state. */
02d9e453 847 client -> state = S_REBOOTING;
deff2d59 848
420d8b3f
FD
849 /*
850 * make_request doesn't initialize xid because it normally comes
851 * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
852 * so pick an xid now.
853 */
02d9e453 854 client -> xid = random ();
5c2f78b4 855
420d8b3f
FD
856 /*
857 * Make a DHCPREQUEST packet, and set
858 * appropriate per-interface flags.
859 */
02d9e453
TL
860 make_request (client, client -> active);
861 client -> destination = iaddr_broadcast;
862 client -> first_sending = cur_time;
863 client -> interval = client -> config -> initial_interval;
deff2d59 864
b8cf055d 865 /* Zap the medium list... */
420d8b3f 866 client -> medium = NULL;
b8cf055d
TL
867
868 /* Send out the first DHCPREQUEST packet. */
02d9e453 869 send_request (client);
deff2d59
TL
870}
871
872/* Called when a lease has completely expired and we've been unable to
873 renew it. */
cc26de46 874
02d9e453
TL
875void state_init (cpp)
876 void *cpp;
469cf3a4 877{
02d9e453 878 struct client_state *client = cpp;
84c4adde 879
469cf3a4
TL
880 ASSERT_STATE(state, S_INIT);
881
cc26de46
TL
882 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
883 flags. */
02d9e453
TL
884 make_discover (client, client -> active);
885 client -> xid = client -> packet.xid;
886 client -> destination = iaddr_broadcast;
887 client -> state = S_SELECTING;
888 client -> first_sending = cur_time;
889 client -> interval = client -> config -> initial_interval;
cc26de46
TL
890
891 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
892 to go out. */
02d9e453 893 send_discover (client);
469cf3a4
TL
894}
895
420d8b3f
FD
896/*
897 * state_selecting is called when one or more DHCPOFFER packets have been
898 * received and a configurable period of time has passed.
899 */
cc26de46 900
02d9e453
TL
901void state_selecting (cpp)
902 void *cpp;
469cf3a4 903{
02d9e453 904 struct client_state *client = cpp;
b00d3884
TL
905 struct client_lease *lp, *next, *picked;
906
02d9e453 907
469cf3a4
TL
908 ASSERT_STATE(state, S_SELECTING);
909
420d8b3f
FD
910 /*
911 * Cancel state_selecting and send_discover timeouts, since either
912 * one could have got us here.
913 */
02d9e453
TL
914 cancel_timeout (state_selecting, client);
915 cancel_timeout (send_discover, client);
cc26de46 916
420d8b3f
FD
917 /*
918 * We have received one or more DHCPOFFER packets. Currently,
919 * the only criterion by which we judge leases is whether or
920 * not we get a response when we arp for them.
921 */
922 picked = NULL;
02d9e453 923 for (lp = client -> offered_leases; lp; lp = next) {
b00d3884
TL
924 next = lp -> next;
925
420d8b3f
FD
926 /*
927 * Check to see if we got an ARPREPLY for the address
928 * in this particular lease.
929 */
b00d3884 930 if (!picked) {
b00d3884 931 picked = lp;
420d8b3f 932 picked -> next = NULL;
b00d3884 933 } else {
02a015fb 934 destroy_client_lease (lp);
b00d3884
TL
935 }
936 }
420d8b3f 937 client -> offered_leases = NULL;
b00d3884 938
420d8b3f
FD
939 /*
940 * If we just tossed all the leases we were offered, go back
941 * to square one.
942 */
b00d3884 943 if (!picked) {
02d9e453
TL
944 client -> state = S_INIT;
945 state_init (client);
b00d3884
TL
946 return;
947 }
948
66f973e4 949 /* If it was a BOOTREPLY, we can just take the address right now. */
2455808f 950 if (picked -> is_bootp) {
02d9e453 951 client -> new = picked;
66f973e4
TL
952
953 /* Make up some lease expiry times
954 XXX these should be configurable. */
02d9e453
TL
955 client -> new -> expiry = cur_time + 12000;
956 client -> new -> renewal += cur_time + 8000;
957 client -> new -> rebind += cur_time + 10000;
66f973e4 958
02d9e453 959 client -> state = S_REQUESTING;
66f973e4
TL
960
961 /* Bind to the address we received. */
02d9e453 962 bind_lease (client);
66f973e4
TL
963 return;
964 }
965
b00d3884 966 /* Go to the REQUESTING state. */
02d9e453
TL
967 client -> destination = iaddr_broadcast;
968 client -> state = S_REQUESTING;
969 client -> first_sending = cur_time;
970 client -> interval = client -> config -> initial_interval;
cc26de46 971
b00d3884 972 /* Make a DHCPREQUEST packet from the lease we picked. */
02d9e453
TL
973 make_request (client, picked);
974 client -> xid = client -> packet.xid;
469cf3a4 975
b00d3884 976 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
02a015fb 977 destroy_client_lease (picked);
b00d3884 978
cc26de46 979 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
02d9e453 980 send_request (client);
3dbe2246 981}
469cf3a4 982
cc26de46
TL
983/* state_requesting is called when we receive a DHCPACK message after
984 having sent out one or more DHCPREQUEST packets. */
469cf3a4 985
cc26de46
TL
986void dhcpack (packet)
987 struct packet *packet;
469cf3a4 988{
cc26de46 989 struct interface_info *ip = packet -> interface;
02d9e453 990 struct client_state *client;
cc26de46 991 struct client_lease *lease;
02a015fb
TL
992 struct option_cache *oc;
993 struct data_string ds;
3dbe2246 994
cc26de46
TL
995 /* If we're not receptive to an offer right now, or if the offer
996 has an unrecognizable transaction id, then just drop it. */
02d9e453
TL
997 for (client = ip -> client; client; client = client -> next) {
998 if (client -> xid == packet -> raw -> xid)
999 break;
1000 }
1001 if (!client ||
31730f17 1002 (packet -> interface -> hw_address.hlen - 1 !=
5c2f78b4 1003 packet -> raw -> hlen) ||
31730f17 1004 (memcmp (&packet -> interface -> hw_address.hbuf [1],
fcaec4ef 1005 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2d1b06e0 1006#if defined (DEBUG)
8ae2d595 1007 log_debug ("DHCPACK in wrong transaction.");
2d1b06e0 1008#endif
cc26de46 1009 return;
469cf3a4 1010 }
469cf3a4 1011
02d9e453
TL
1012 if (client -> state != S_REBOOTING &&
1013 client -> state != S_REQUESTING &&
1014 client -> state != S_RENEWING &&
1015 client -> state != S_REBINDING) {
2d1b06e0 1016#if defined (DEBUG)
8ae2d595 1017 log_debug ("DHCPACK in wrong state.");
2d1b06e0 1018#endif
cc26de46 1019 return;
469cf3a4
TL
1020 }
1021
8ae2d595 1022 log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
34fdad6c 1023
6ceb9118 1024 lease = packet_to_lease (packet, client);
cc26de46 1025 if (!lease) {
8ae2d595 1026 log_info ("packet_to_lease failed.");
cc26de46 1027 return;
469cf3a4
TL
1028 }
1029
02d9e453 1030 client -> new = lease;
cc26de46
TL
1031
1032 /* Stop resending DHCPREQUEST. */
02d9e453 1033 cancel_timeout (send_request, client);
cc26de46
TL
1034
1035 /* Figure out the lease time. */
230e73e4 1036 oc = lookup_option (&dhcp_universe, client -> new -> options,
02a015fb
TL
1037 DHO_DHCP_LEASE_TIME);
1038 memset (&ds, 0, sizeof ds);
1039 if (oc &&
66e9cecf 1040 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
0852a27f 1041 packet -> options, client -> new -> options,
cf78bf20 1042 &global_scope, oc, MDL)) {
02a015fb 1043 if (ds.len > 3)
02d9e453 1044 client -> new -> expiry = getULong (ds.data);
02a015fb 1045 else
02d9e453 1046 client -> new -> expiry = 0;
cf78bf20 1047 data_string_forget (&ds, MDL);
02a015fb 1048 } else
02d9e453 1049 client -> new -> expiry = 0;
02a015fb 1050
02d9e453 1051 if (!client -> new -> expiry) {
8ae2d595 1052 log_error ("no expiry time on offered lease.");
02a015fb 1053 /* XXX this is going to be bad - if this _does_
3dbe2246 1054 XXX happen, we should probably dynamically
02a015fb
TL
1055 XXX disqualify the DHCP server that gave us the
1056 XXX bad packet from future selections and
1057 XXX then go back into the init state. */
02d9e453 1058 state_init (client);
02a015fb
TL
1059 return;
1060 }
cc26de46 1061
62d0cb47
TL
1062 /* A number that looks negative here is really just very large,
1063 because the lease expiry offset is unsigned. */
1064 if (client -> new -> expiry < 0)
1065 client -> new -> expiry = TIME_MAX;
02a015fb 1066 /* Take the server-provided renewal time if there is one. */
230e73e4 1067 oc = lookup_option (&dhcp_universe, client -> new -> options,
02a015fb
TL
1068 DHO_DHCP_RENEWAL_TIME);
1069 if (oc &&
66e9cecf 1070 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
0852a27f 1071 packet -> options, client -> new -> options,
cf78bf20 1072 &global_scope, oc, MDL)) {
02a015fb 1073 if (ds.len > 3)
02d9e453 1074 client -> new -> renewal = getULong (ds.data);
02a015fb 1075 else
02d9e453 1076 client -> new -> renewal = 0;
cf78bf20 1077 data_string_forget (&ds, MDL);
02a015fb 1078 } else
02d9e453 1079 client -> new -> renewal = 0;
02a015fb
TL
1080
1081 /* If it wasn't specified by the server, calculate it. */
02d9e453 1082 if (!client -> new -> renewal)
98311e4b
DH
1083 client -> new -> renewal = client -> new -> expiry / 2 + 1;
1084
1085 if (client -> new -> renewal <= 0)
1086 client -> new -> renewal = TIME_MAX;
cc26de46 1087
11373fb6 1088 /* Now introduce some randomness to the renewal time: */
88cd8aca
DH
1089 if (client->new->renewal <= ((TIME_MAX / 3) - 3))
1090 client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
1091 (((random() % client->new->renewal) + 3) / 4);
11373fb6 1092
cc26de46 1093 /* Same deal with the rebind time. */
230e73e4 1094 oc = lookup_option (&dhcp_universe, client -> new -> options,
02a015fb
TL
1095 DHO_DHCP_REBINDING_TIME);
1096 if (oc &&
66e9cecf 1097 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
0852a27f 1098 packet -> options, client -> new -> options,
cf78bf20 1099 &global_scope, oc, MDL)) {
02a015fb 1100 if (ds.len > 3)
02d9e453 1101 client -> new -> rebind = getULong (ds.data);
02a015fb 1102 else
02d9e453 1103 client -> new -> rebind = 0;
cf78bf20 1104 data_string_forget (&ds, MDL);
02a015fb 1105 } else
02d9e453 1106 client -> new -> rebind = 0;
02a015fb 1107
98311e4b
DH
1108 if (client -> new -> rebind <= 0) {
1109 if (client -> new -> expiry <= TIME_MAX / 7)
1110 client -> new -> rebind =
1111 client -> new -> expiry * 7 / 8;
1112 else
1113 client -> new -> rebind =
1114 client -> new -> expiry / 8 * 7;
1115 }
11373fb6
TL
1116
1117 /* Make sure our randomness didn't run the renewal time past the
1118 rebind time. */
98311e4b
DH
1119 if (client -> new -> renewal > client -> new -> rebind) {
1120 if (client -> new -> rebind <= TIME_MAX / 3)
1121 client -> new -> renewal =
1122 client -> new -> rebind * 3 / 4;
1123 else
1124 client -> new -> renewal =
1125 client -> new -> rebind / 4 * 3;
1126 }
cc26de46 1127
02d9e453 1128 client -> new -> expiry += cur_time;
62d0cb47
TL
1129 /* Lease lengths can never be negative. */
1130 if (client -> new -> expiry < cur_time)
1131 client -> new -> expiry = TIME_MAX;
02d9e453 1132 client -> new -> renewal += cur_time;
62d0cb47
TL
1133 if (client -> new -> renewal < cur_time)
1134 client -> new -> renewal = TIME_MAX;
02d9e453 1135 client -> new -> rebind += cur_time;
62d0cb47
TL
1136 if (client -> new -> rebind < cur_time)
1137 client -> new -> rebind = TIME_MAX;
cc26de46 1138
02d9e453 1139 bind_lease (client);
66f973e4
TL
1140}
1141
02d9e453
TL
1142void bind_lease (client)
1143 struct client_state *client;
66f973e4 1144{
be62cf06
FD
1145 struct timeval tv;
1146
9bdb9271 1147 /* Remember the medium. */
02d9e453 1148 client -> new -> medium = client -> medium;
9bdb9271 1149
cc26de46 1150 /* Run the client script with the new parameters. */
02d9e453 1151 script_init (client, (client -> state == S_REQUESTING
cc26de46 1152 ? "BOUND"
02d9e453 1153 : (client -> state == S_RENEWING
cc26de46 1154 ? "RENEW"
02d9e453 1155 : (client -> state == S_REBOOTING
77967680 1156 ? "REBOOT" : "REBIND"))),
02d9e453
TL
1157 client -> new -> medium);
1158 if (client -> active && client -> state != S_REBOOTING)
1159 script_write_params (client, "old_", client -> active);
1160 script_write_params (client, "new_", client -> new);
1161 if (client -> alias)
1162 script_write_params (client, "alias_", client -> alias);
e16f4c3e
TL
1163
1164 /* If the BOUND/RENEW code detects another machine using the
1165 offered address, it exits nonzero. We need to send a
1166 DHCPDECLINE and toss the lease. */
1167 if (script_go (client)) {
1168 make_decline (client, client -> new);
1169 send_decline (client);
1170 destroy_client_lease (client -> new);
7d3bc735 1171 client -> new = (struct client_lease *)0;
e16f4c3e
TL
1172 state_init (client);
1173 return;
1174 }
1175
1176 /* Write out the new lease. */
007e3ee4 1177 write_client_lease (client, client -> new, 0, 0);
cc26de46
TL
1178
1179 /* Replace the old active lease with the new one. */
02d9e453
TL
1180 if (client -> active)
1181 destroy_client_lease (client -> active);
1182 client -> active = client -> new;
1183 client -> new = (struct client_lease *)0;
cc26de46
TL
1184
1185 /* Set up a timeout to start the renewal process. */
be62cf06
FD
1186 tv . tv_sec = client -> active -> renewal;
1187 tv . tv_usec = 0;
1188 add_timeout (&tv, state_bound, client, 0, 0);
cc26de46 1189
ab58ff49 1190 log_info ("bound to %s -- renewal in %ld seconds.",
02d9e453 1191 piaddr (client -> active -> address),
ab58ff49 1192 (long)(client -> active -> renewal - cur_time));
02d9e453 1193 client -> state = S_BOUND;
b00d3884
TL
1194 reinitialize_interfaces ();
1195 go_daemon ();
98bf1607 1196#if defined (NSUPDATE)
98bd7ca0 1197 if (client->config->do_forward_update)
98bf1607
SR
1198 dhclient_schedule_updates(client, &client->active->address, 1);
1199#endif
3dbe2246 1200}
469cf3a4 1201
cc26de46
TL
1202/* state_bound is called when we've successfully bound to a particular
1203 lease, but the renewal time on that lease has expired. We are
1204 expected to unicast a DHCPREQUEST to the server that gave us our
1205 original lease. */
469cf3a4 1206
02d9e453
TL
1207void state_bound (cpp)
1208 void *cpp;
469cf3a4 1209{
02d9e453 1210 struct client_state *client = cpp;
02a015fb
TL
1211 struct option_cache *oc;
1212 struct data_string ds;
84c4adde 1213
cc26de46 1214 ASSERT_STATE(state, S_BOUND);
469cf3a4 1215
cc26de46 1216 /* T1 has expired. */
02d9e453
TL
1217 make_request (client, client -> active);
1218 client -> xid = client -> packet.xid;
469cf3a4 1219
02a015fb 1220 memset (&ds, 0, sizeof ds);
230e73e4 1221 oc = lookup_option (&dhcp_universe, client -> active -> options,
02a015fb
TL
1222 DHO_DHCP_SERVER_IDENTIFIER);
1223 if (oc &&
0852a27f 1224 evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
66e9cecf 1225 client, (struct option_state *)0,
da38df14 1226 client -> active -> options,
cf78bf20 1227 &global_scope, oc, MDL)) {
02a015fb 1228 if (ds.len > 3) {
02d9e453
TL
1229 memcpy (client -> destination.iabuf, ds.data, 4);
1230 client -> destination.len = 4;
02a015fb 1231 } else
02d9e453 1232 client -> destination = iaddr_broadcast;
98311e4b
DH
1233
1234 data_string_forget (&ds, MDL);
cc26de46 1235 } else
02d9e453 1236 client -> destination = iaddr_broadcast;
469cf3a4 1237
02d9e453
TL
1238 client -> first_sending = cur_time;
1239 client -> interval = client -> config -> initial_interval;
1240 client -> state = S_RENEWING;
cc26de46
TL
1241
1242 /* Send the first packet immediately. */
02d9e453 1243 send_request (client);
3dbe2246 1244}
469cf3a4 1245
d758ad8c
TL
1246/* state_stop is called when we've been told to shut down. We unconfigure
1247 the interfaces, and then stop operating until told otherwise. */
1248
1249void state_stop (cpp)
1250 void *cpp;
1251{
1252 struct client_state *client = cpp;
d758ad8c
TL
1253
1254 /* Cancel all timeouts. */
af5fa176
EH
1255 cancel_timeout(state_selecting, client);
1256 cancel_timeout(send_discover, client);
1257 cancel_timeout(send_request, client);
1258 cancel_timeout(state_bound, client);
d758ad8c
TL
1259
1260 /* If we have an address, unconfigure it. */
af5fa176
EH
1261 if (client->active) {
1262 script_init(client, "STOP", client->active->medium);
1263 script_write_params(client, "old_", client->active);
1264 if (client->alias)
1265 script_write_params(client, "alias_", client->alias);
1266 script_go(client);
d758ad8c 1267 }
3dbe2246 1268}
d758ad8c 1269
c1503c57
TL
1270int commit_leases ()
1271{
1272 return 0;
1273}
1274
1275int write_lease (lease)
1276 struct lease *lease;
1277{
1278 return 0;
95821729
TL
1279}
1280
628beb0e
TL
1281int write_host (host)
1282 struct host_decl *host;
1283{
1284 return 0;
1285}
1286
7d7a35fa
TL
1287void db_startup (testp)
1288 int testp;
c1503c57
TL
1289{
1290}
1291
1292void bootp (packet)
1293 struct packet *packet;
1294{
febbd402
DH
1295 struct iaddrmatchlist *ap;
1296 char addrbuf[4*16];
1297 char maskbuf[4*16];
fa2b3e59
TL
1298
1299 if (packet -> raw -> op != BOOTREPLY)
1300 return;
1301
1302 /* If there's a reject list, make sure this packet's sender isn't
1303 on it. */
1304 for (ap = packet -> interface -> client -> config -> reject_list;
1305 ap; ap = ap -> next) {
febbd402
DH
1306 if (addr_match(&packet->client_addr, &ap->match)) {
1307
1308 /* piaddr() returns its result in a static
1309 buffer sized 4*16 (see common/inet.c). */
1310
1311 strcpy(addrbuf, piaddr(ap->match.addr));
1312 strcpy(maskbuf, piaddr(ap->match.mask));
1313
1314 log_info("BOOTREPLY from %s rejected by rule %s "
1315 "mask %s.", piaddr(packet->client_addr),
1316 addrbuf, maskbuf);
fa2b3e59
TL
1317 return;
1318 }
1319 }
3dbe2246 1320
fa2b3e59 1321 dhcpoffer (packet);
66f973e4 1322
c1503c57 1323}
95821729 1324
c1503c57
TL
1325void dhcp (packet)
1326 struct packet *packet;
95821729 1327{
febbd402 1328 struct iaddrmatchlist *ap;
ea65d407 1329 void (*handler) PROTO ((struct packet *));
b1b7b521 1330 const char *type;
febbd402
DH
1331 char addrbuf[4*16];
1332 char maskbuf[4*16];
fa2b3e59 1333
c1503c57
TL
1334 switch (packet -> packet_type) {
1335 case DHCPOFFER:
fa2b3e59
TL
1336 handler = dhcpoffer;
1337 type = "DHCPOFFER";
95821729 1338 break;
c1503c57
TL
1339
1340 case DHCPNAK:
fa2b3e59
TL
1341 handler = dhcpnak;
1342 type = "DHCPNACK";
c1503c57
TL
1343 break;
1344
1345 case DHCPACK:
fa2b3e59
TL
1346 handler = dhcpack;
1347 type = "DHCPACK";
c1503c57
TL
1348 break;
1349
95821729 1350 default:
fa2b3e59
TL
1351 return;
1352 }
1353
1354 /* If there's a reject list, make sure this packet's sender isn't
1355 on it. */
1356 for (ap = packet -> interface -> client -> config -> reject_list;
1357 ap; ap = ap -> next) {
febbd402
DH
1358 if (addr_match(&packet->client_addr, &ap->match)) {
1359
1360 /* piaddr() returns its result in a static
1361 buffer sized 4*16 (see common/inet.c). */
1362
1363 strcpy(addrbuf, piaddr(ap->match.addr));
1364 strcpy(maskbuf, piaddr(ap->match.mask));
1365
1366 log_info("%s from %s rejected by rule %s mask %s.",
1367 type, piaddr(packet->client_addr),
1368 addrbuf, maskbuf);
fa2b3e59
TL
1369 return;
1370 }
95821729 1371 }
fa2b3e59 1372 (*handler) (packet);
95821729
TL
1373}
1374
fe5b0fdd 1375#ifdef DHCPv6
3dbe2246 1376void
98bd7ca0
DH
1377dhcpv6(struct packet *packet) {
1378 struct iaddrmatchlist *ap;
1379 struct client_state *client;
1380 char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
1381
1382 /* Silently drop bogus messages. */
1383 if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
1384 return;
1385
1386 /* Discard, with log, packets from quenched sources. */
1387 for (ap = packet->interface->client->config->reject_list ;
1388 ap ; ap = ap->next) {
1389 if (addr_match(&packet->client_addr, &ap->match)) {
1390 strcpy(addrbuf, piaddr(packet->client_addr));
1391 log_info("%s from %s rejected by rule %s",
1392 dhcpv6_type_names[packet->dhcpv6_msg_type],
1393 addrbuf,
1394 piaddrmask(&ap->match.addr, &ap->match.mask));
1395 return;
1396 }
1397 }
1398
1399 /* Screen out nonsensical messages. */
1400 switch(packet->dhcpv6_msg_type) {
1401 case DHCPV6_ADVERTISE:
98bd7ca0 1402 case DHCPV6_RECONFIGURE:
3dbe2246
FD
1403 if (stateless)
1404 return;
1405 /* Falls through */
1406 case DHCPV6_REPLY:
98bd7ca0
DH
1407 log_info("RCV: %s message on %s from %s.",
1408 dhcpv6_type_names[packet->dhcpv6_msg_type],
1409 packet->interface->name, piaddr(packet->client_addr));
1410 break;
1411
1412 default:
1413 return;
1414 }
1415
1416 /* Find a client state that matches the incoming XID. */
1417 for (client = packet->interface->client ; client ;
1418 client = client->next) {
1419 if (memcmp(&client->dhcpv6_transaction_id,
1420 packet->dhcpv6_transaction_id, 3) == 0) {
1421 client->v6_handler(packet, client);
1422 return;
1423 }
1424 }
1425
20ae1aff 1426 /* XXX: temporary log for debugging */
98bd7ca0
DH
1427 log_info("Packet received, but nothing done with it.");
1428}
fe5b0fdd 1429#endif /* DHCPv6 */
98bd7ca0 1430
c1503c57
TL
1431void dhcpoffer (packet)
1432 struct packet *packet;
95821729 1433{
cc26de46 1434 struct interface_info *ip = packet -> interface;
02d9e453 1435 struct client_state *client;
b00d3884 1436 struct client_lease *lease, *lp;
0c20eab3 1437 struct option **req;
cc26de46 1438 int i;
e16f4c3e 1439 int stop_selecting;
b1b7b521 1440 const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
d758ad8c 1441 char obuf [1024];
be62cf06 1442 struct timeval tv;
3dbe2246 1443
cc26de46 1444#ifdef DEBUG_PACKET
c1503c57 1445 dump_packet (packet);
3dbe2246 1446#endif
cc26de46 1447
02d9e453
TL
1448 /* Find a client state that matches the xid... */
1449 for (client = ip -> client; client; client = client -> next)
1450 if (client -> xid == packet -> raw -> xid)
1451 break;
1452
cc26de46
TL
1453 /* If we're not receptive to an offer right now, or if the offer
1454 has an unrecognizable transaction id, then just drop it. */
02d9e453 1455 if (!client ||
73530742 1456 client -> state != S_SELECTING ||
31730f17 1457 (packet -> interface -> hw_address.hlen - 1 !=
fcaec4ef 1458 packet -> raw -> hlen) ||
31730f17 1459 (memcmp (&packet -> interface -> hw_address.hbuf [1],
fcaec4ef 1460 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2d1b06e0 1461#if defined (DEBUG)
8ae2d595 1462 log_debug ("%s in wrong transaction.", name);
2d1b06e0 1463#endif
cc26de46
TL
1464 return;
1465 }
1466
d758ad8c 1467 sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
34fdad6c 1468
b8cf055d 1469
0c20eab3
DH
1470 /* If this lease doesn't supply the minimum required DHCPv4 parameters,
1471 * ignore it.
1472 */
1473 req = client->config->required_options;
1474 if (req != NULL) {
1475 for (i = 0 ; req[i] != NULL ; i++) {
1476 if ((req[i]->universe == &dhcp_universe) &&
1477 !lookup_option(&dhcp_universe, packet->options,
1478 req[i]->code)) {
1479 struct option *option = NULL;
1480 unsigned code = req[i]->code;
1481
1482 option_code_hash_lookup(&option,
1483 dhcp_universe.code_hash,
1484 &code, 0, MDL);
1485
1486 if (option)
1487 log_info("%s: no %s option.", obuf,
1488 option->name);
1489 else
1490 log_info("%s: no unknown-%u option.",
1491 obuf, code);
f7fdb216 1492
0c20eab3 1493 option_dereference(&option, MDL);
f7fdb216 1494
0c20eab3
DH
1495 return;
1496 }
cc26de46
TL
1497 }
1498 }
1499
1500 /* If we've already seen this lease, don't record it again. */
02d9e453 1501 for (lease = client -> offered_leases; lease; lease = lease -> next) {
cc26de46
TL
1502 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
1503 !memcmp (lease -> address.iabuf,
1504 &packet -> raw -> yiaddr, lease -> address.len)) {
d758ad8c 1505 log_debug ("%s: already seen.", obuf);
cc26de46
TL
1506 return;
1507 }
1508 }
1509
6ceb9118 1510 lease = packet_to_lease (packet, client);
cc26de46 1511 if (!lease) {
d758ad8c 1512 log_info ("%s: packet_to_lease failed.", obuf);
cc26de46
TL
1513 return;
1514 }
1515
66f973e4
TL
1516 /* If this lease was acquired through a BOOTREPLY, record that
1517 fact. */
02a015fb 1518 if (!packet -> options_valid || !packet -> packet_type)
66f973e4
TL
1519 lease -> is_bootp = 1;
1520
9bdb9271 1521 /* Record the medium under which this lease was offered. */
02d9e453 1522 lease -> medium = client -> medium;
9bdb9271 1523
b00d3884 1524 /* Figure out when we're supposed to stop selecting. */
02d9e453
TL
1525 stop_selecting = (client -> first_sending +
1526 client -> config -> select_interval);
b00d3884
TL
1527
1528 /* If this is the lease we asked for, put it at the head of the
1529 list, and don't mess with the arp request timeout. */
02d9e453 1530 if (lease -> address.len == client -> requested_address.len &&
b00d3884 1531 !memcmp (lease -> address.iabuf,
02d9e453
TL
1532 client -> requested_address.iabuf,
1533 client -> requested_address.len)) {
1534 lease -> next = client -> offered_leases;
1535 client -> offered_leases = lease;
b00d3884 1536 } else {
b00d3884
TL
1537 /* Put the lease at the end of the list. */
1538 lease -> next = (struct client_lease *)0;
02d9e453
TL
1539 if (!client -> offered_leases)
1540 client -> offered_leases = lease;
b00d3884 1541 else {
02d9e453 1542 for (lp = client -> offered_leases; lp -> next;
b00d3884
TL
1543 lp = lp -> next)
1544 ;
1545 lp -> next = lease;
1546 }
1547 }
1548
cc26de46
TL
1549 /* If the selecting interval has expired, go immediately to
1550 state_selecting(). Otherwise, time out into
1551 state_selecting at the select interval. */
b00d3884 1552 if (stop_selecting <= 0)
d758ad8c 1553 state_selecting (client);
84c4adde 1554 else {
be62cf06
FD
1555 tv . tv_sec = stop_selecting;
1556 tv . tv_usec = 0;
1557 add_timeout (&tv, state_selecting, client, 0, 0);
02d9e453 1558 cancel_timeout (send_discover, client);
84c4adde 1559 }
d758ad8c 1560 log_info ("%s", obuf);
95821729 1561}
e581d615 1562
cc26de46
TL
1563/* Allocate a client_lease structure and initialize it from the parameters
1564 in the specified packet. */
1565
6ceb9118 1566struct client_lease *packet_to_lease (packet, client)
c1503c57 1567 struct packet *packet;
6ceb9118 1568 struct client_state *client;
e581d615 1569{
cc26de46 1570 struct client_lease *lease;
b5f904a9 1571 unsigned i;
02a015fb 1572 struct option_cache *oc;
f7fdb216 1573 struct option *option = NULL;
02a015fb 1574 struct data_string data;
cc26de46 1575
cf78bf20 1576 lease = (struct client_lease *)new_client_lease (MDL);
cc26de46
TL
1577
1578 if (!lease) {
89c425dd 1579 log_error ("packet_to_lease: no memory to record lease.\n");
cc26de46
TL
1580 return (struct client_lease *)0;
1581 }
1582
1583 memset (lease, 0, sizeof *lease);
1584
1585 /* Copy the lease options. */
cf78bf20 1586 option_state_reference (&lease -> options, packet -> options, MDL);
cc26de46
TL
1587
1588 lease -> address.len = sizeof (packet -> raw -> yiaddr);
1589 memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
1590 lease -> address.len);
1591
98311e4b
DH
1592 memset (&data, 0, sizeof data);
1593
b5f904a9
TL
1594 if (client -> config -> vendor_space_name) {
1595 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
1596
1597 /* See if there was a vendor encapsulation option. */
1598 oc = lookup_option (&dhcp_universe, lease -> options, i);
b5f904a9
TL
1599 if (oc &&
1600 client -> config -> vendor_space_name &&
66e9cecf
TL
1601 evaluate_option_cache (&data, packet,
1602 (struct lease *)0, client,
b5f904a9
TL
1603 packet -> options, lease -> options,
1604 &global_scope, oc, MDL)) {
1605 if (data.len) {
f7fdb216
DH
1606 if (!option_code_hash_lookup(&option,
1607 dhcp_universe.code_hash,
1608 &i, 0, MDL))
1609 log_fatal("Unable to find VENDOR "
1610 "option (%s:%d).", MDL);
b5f904a9 1611 parse_encapsulated_suboptions
f7fdb216 1612 (packet -> options, option,
b5f904a9
TL
1613 data.data, data.len, &dhcp_universe,
1614 client -> config -> vendor_space_name
1615 );
f7fdb216
DH
1616
1617 option_dereference(&option, MDL);
b5f904a9
TL
1618 }
1619 data_string_forget (&data, MDL);
1620 }
1621 } else
1622 i = 0;
1623
02a015fb 1624 /* Figure out the overload flag. */
230e73e4 1625 oc = lookup_option (&dhcp_universe, lease -> options,
02a015fb 1626 DHO_DHCP_OPTION_OVERLOAD);
02a015fb 1627 if (oc &&
66e9cecf 1628 evaluate_option_cache (&data, packet, (struct lease *)0, client,
0852a27f 1629 packet -> options, lease -> options,
cf78bf20 1630 &global_scope, oc, MDL)) {
02a015fb
TL
1631 if (data.len > 0)
1632 i = data.data [0];
1633 else
1634 i = 0;
cf78bf20 1635 data_string_forget (&data, MDL);
02a015fb
TL
1636 } else
1637 i = 0;
1638
cc26de46 1639 /* If the server name was filled out, copy it. */
02a015fb 1640 if (!(i & 2) && packet -> raw -> sname [0]) {
b1b7b521 1641 unsigned len;
cc26de46 1642 /* Don't count on the NUL terminator. */
e2624b82 1643 for (len = 0; len < DHCP_SNAME_LEN; len++)
cc26de46
TL
1644 if (!packet -> raw -> sname [len])
1645 break;
cf78bf20 1646 lease -> server_name = dmalloc (len + 1, MDL);
cc26de46 1647 if (!lease -> server_name) {
98311e4b 1648 log_error ("dhcpoffer: no memory for server name.\n");
02a015fb 1649 destroy_client_lease (lease);
cc26de46
TL
1650 return (struct client_lease *)0;
1651 } else {
1652 memcpy (lease -> server_name,
1653 packet -> raw -> sname, len);
1654 lease -> server_name [len] = 0;
1655 }
1656 }
1657
1658 /* Ditto for the filename. */
0852a27f 1659 if (!(i & 1) && packet -> raw -> file [0]) {
b1b7b521 1660 unsigned len;
cc26de46 1661 /* Don't count on the NUL terminator. */
e2624b82 1662 for (len = 0; len < DHCP_FILE_LEN; len++)
cc26de46
TL
1663 if (!packet -> raw -> file [len])
1664 break;
cf78bf20 1665 lease -> filename = dmalloc (len + 1, MDL);
cc26de46 1666 if (!lease -> filename) {
8ae2d595 1667 log_error ("dhcpoffer: no memory for filename.\n");
02a015fb 1668 destroy_client_lease (lease);
cc26de46
TL
1669 return (struct client_lease *)0;
1670 } else {
1671 memcpy (lease -> filename,
1672 packet -> raw -> file, len);
1673 lease -> filename [len] = 0;
1674 }
1675 }
89c425dd
TL
1676
1677 execute_statements_in_scope ((struct binding_value **)0,
1678 (struct packet *)packet,
66e9cecf
TL
1679 (struct lease *)0, client,
1680 lease -> options, lease -> options,
1681 &global_scope,
89c425dd
TL
1682 client -> config -> on_receipt,
1683 (struct group *)0);
1684
cc26de46 1685 return lease;
3dbe2246 1686}
e581d615 1687
c1503c57
TL
1688void dhcpnak (packet)
1689 struct packet *packet;
1690{
deff2d59 1691 struct interface_info *ip = packet -> interface;
02d9e453
TL
1692 struct client_state *client;
1693
1694 /* Find a client state that matches the xid... */
1695 for (client = ip -> client; client; client = client -> next)
1696 if (client -> xid == packet -> raw -> xid)
1697 break;
deff2d59 1698
deff2d59
TL
1699 /* If we're not receptive to an offer right now, or if the offer
1700 has an unrecognizable transaction id, then just drop it. */
02d9e453 1701 if (!client ||
31730f17 1702 (packet -> interface -> hw_address.hlen - 1 !=
fcaec4ef 1703 packet -> raw -> hlen) ||
31730f17 1704 (memcmp (&packet -> interface -> hw_address.hbuf [1],
fcaec4ef 1705 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2d1b06e0 1706#if defined (DEBUG)
8ae2d595 1707 log_debug ("DHCPNAK in wrong transaction.");
2d1b06e0 1708#endif
deff2d59
TL
1709 return;
1710 }
1711
02d9e453
TL
1712 if (client -> state != S_REBOOTING &&
1713 client -> state != S_REQUESTING &&
1714 client -> state != S_RENEWING &&
1715 client -> state != S_REBINDING) {
2d1b06e0 1716#if defined (DEBUG)
8ae2d595 1717 log_debug ("DHCPNAK in wrong state.");
2d1b06e0 1718#endif
deff2d59
TL
1719 return;
1720 }
1721
8ae2d595 1722 log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
34fdad6c 1723
02d9e453 1724 if (!client -> active) {
2d1b06e0 1725#if defined (DEBUG)
8ae2d595 1726 log_info ("DHCPNAK with no active lease.\n");
2d1b06e0 1727#endif
deff2d59
TL
1728 return;
1729 }
1730
6cbc6629
DH
1731 /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
1732 * to indicate that we want all old bindings to be removed. (It
1733 * is possible that we may get a NAK while in the RENEW state,
1734 * so we might have bindings active at that time)
1735 */
1736 script_init(client, "EXPIRE", NULL);
1737 script_write_params(client, "old_", client->active);
1738 if (client->alias)
1739 script_write_params(client, "alias_", client->alias);
1740 script_go(client);
1741
02d9e453
TL
1742 destroy_client_lease (client -> active);
1743 client -> active = (struct client_lease *)0;
deff2d59
TL
1744
1745 /* Stop sending DHCPREQUEST packets... */
02d9e453 1746 cancel_timeout (send_request, client);
deff2d59 1747
0a73b7b6
SK
1748 /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
1749 * down (this expunges any routes and arp cache). This makes the
1750 * interface unusable by state_init(), which we call next. So, we
1751 * need to 'PREINIT' the interface to bring it back up.
1752 */
1753 script_init(client, "PREINIT", NULL);
1754 if (client->alias)
1755 script_write_params(client, "alias_", client->alias);
1756 script_go(client);
1757
02d9e453
TL
1758 client -> state = S_INIT;
1759 state_init (client);
e581d615
TL
1760}
1761
cc26de46 1762/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
66f973e4
TL
1763 one after the right interval has expired. If we don't get an offer by
1764 the time we reach the panic interval, call the panic function. */
469cf3a4 1765
02d9e453
TL
1766void send_discover (cpp)
1767 void *cpp;
469cf3a4 1768{
02d9e453 1769 struct client_state *client = cpp;
84c4adde 1770
cc26de46
TL
1771 int result;
1772 int interval;
9bdb9271 1773 int increase = 1;
be62cf06 1774 struct timeval tv;
cc26de46
TL
1775
1776 /* Figure out how long it's been since we started transmitting. */
02d9e453 1777 interval = cur_time - client -> first_sending;
cc26de46
TL
1778
1779 /* If we're past the panic timeout, call the script and tell it
1780 we haven't found anything for this interface yet. */
02d9e453
TL
1781 if (interval > client -> config -> timeout) {
1782 state_panic (client);
b00d3884 1783 return;
cc26de46 1784 }
469cf3a4 1785
9bdb9271
TL
1786 /* If we're selecting media, try the whole list before doing
1787 the exponential backoff, but if we've already received an
1788 offer, stop looping, because we obviously have it right. */
02d9e453
TL
1789 if (!client -> offered_leases &&
1790 client -> config -> media) {
9bdb9271
TL
1791 int fail = 0;
1792 again:
02d9e453
TL
1793 if (client -> medium) {
1794 client -> medium = client -> medium -> next;
9bdb9271 1795 increase = 0;
3dbe2246 1796 }
02d9e453 1797 if (!client -> medium) {
9bdb9271 1798 if (fail)
8ae2d595 1799 log_fatal ("No valid media types for %s!",
02d9e453
TL
1800 client -> interface -> name);
1801 client -> medium =
1802 client -> config -> media;
9bdb9271
TL
1803 increase = 1;
1804 }
3dbe2246 1805
8ae2d595 1806 log_info ("Trying medium \"%s\" %d",
b1423aed 1807 client -> medium -> string, increase);
02d9e453
TL
1808 script_init (client, "MEDIUM", client -> medium);
1809 if (script_go (client)) {
b1423aed 1810 fail = 1;
9bdb9271
TL
1811 goto again;
1812 }
1813 }
cc26de46 1814
9bdb9271
TL
1815 /* If we're supposed to increase the interval, do so. If it's
1816 currently zero (i.e., we haven't sent any packets yet), set
98311e4b
DH
1817 it to initial_interval; otherwise, add to it a random number
1818 between zero and two times itself. On average, this means
1819 that it will double with every transmission. */
9bdb9271 1820 if (increase) {
88cd8aca
DH
1821 if (!client->interval)
1822 client->interval = client->config->initial_interval;
b1423aed 1823 else
88cd8aca 1824 client->interval += random() % (2 * client->interval);
cc26de46 1825
34fdad6c 1826 /* Don't backoff past cutoff. */
88cd8aca
DH
1827 if (client->interval > client->config->backoff_cutoff)
1828 client->interval = (client->config->backoff_cutoff / 2)
1829 + (random() % client->config->backoff_cutoff);
1830 } else if (!client->interval)
1831 client->interval = client->config->initial_interval;
3dbe2246 1832
cc26de46
TL
1833 /* If the backoff would take us to the panic timeout, just use that
1834 as the interval. */
02d9e453
TL
1835 if (cur_time + client -> interval >
1836 client -> first_sending + client -> config -> timeout)
1837 client -> interval =
1838 (client -> first_sending +
1839 client -> config -> timeout) - cur_time + 1;
cc26de46 1840
34fdad6c 1841 /* Record the number of seconds since we started sending. */
af6df788
TL
1842 if (interval < 65536)
1843 client -> packet.secs = htons (interval);
34fdad6c 1844 else
af6df788
TL
1845 client -> packet.secs = htons (65535);
1846 client -> secs = client -> packet.secs;
34fdad6c 1847
8ae2d595 1848 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
02d9e453 1849 client -> name ? client -> name : client -> interface -> name,
66f973e4 1850 inet_ntoa (sockaddr_broadcast.sin_addr),
c4661845 1851 ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
66f973e4 1852
cc26de46 1853 /* Send out a packet. */
02d9e453
TL
1854 result = send_packet (client -> interface, (struct packet *)0,
1855 &client -> packet,
1856 client -> packet_length,
cc26de46
TL
1857 inaddr_any, &sockaddr_broadcast,
1858 (struct hardware *)0);
469cf3a4 1859
be62cf06
FD
1860 tv . tv_sec = cur_time + client -> interval;
1861 tv . tv_usec = 0;
1862 add_timeout (&tv, send_discover, client, 0, 0);
469cf3a4
TL
1863}
1864
b00d3884
TL
1865/* state_panic gets called if we haven't received any offers in a preset
1866 amount of time. When this happens, we try to use existing leases that
1867 haven't yet expired, and failing that, we call the client script and
1868 hope it can do something. */
1869
02d9e453
TL
1870void state_panic (cpp)
1871 void *cpp;
b00d3884 1872{
02d9e453
TL
1873 struct client_state *client = cpp;
1874 struct client_lease *loop;
b00d3884 1875 struct client_lease *lp;
be62cf06 1876 struct timeval tv;
b00d3884 1877
02d9e453
TL
1878 loop = lp = client -> active;
1879
8ae2d595 1880 log_info ("No DHCPOFFERS received.");
b00d3884 1881
deff2d59
TL
1882 /* We may not have an active lease, but we may have some
1883 predefined leases that we can try. */
02d9e453 1884 if (!client -> active && client -> leases)
deff2d59 1885 goto activate_next;
deff2d59 1886
b00d3884 1887 /* Run through the list of leases and see if one can be used. */
02d9e453
TL
1888 while (client -> active) {
1889 if (client -> active -> expiry > cur_time) {
8ae2d595 1890 log_info ("Trying recorded lease %s",
02d9e453 1891 piaddr (client -> active -> address));
b00d3884
TL
1892 /* Run the client script with the existing
1893 parameters. */
02d9e453
TL
1894 script_init (client, "TIMEOUT",
1895 client -> active -> medium);
1896 script_write_params (client, "new_", client -> active);
1897 if (client -> alias)
1898 script_write_params (client, "alias_",
1899 client -> alias);
b00d3884
TL
1900
1901 /* If the old lease is still good and doesn't
1902 yet need renewal, go into BOUND state and
1903 timeout at the renewal time. */
02d9e453 1904 if (!script_go (client)) {
1c016679
TL
1905 if (cur_time < client -> active -> renewal) {
1906 client -> state = S_BOUND;
1907 log_info ("bound: renewal in %ld %s.",
1908 (long)(client -> active -> renewal -
1909 cur_time), "seconds");
be62cf06
FD
1910 tv . tv_sec = client -> active -> renewal;
1911 tv . tv_usec = 0;
1912 add_timeout (&tv, state_bound, client, 0, 0);
1c016679
TL
1913 } else {
1914 client -> state = S_BOUND;
1915 log_info ("bound: immediate renewal.");
1916 state_bound (client);
1917 }
1918 reinitialize_interfaces ();
1919 go_daemon ();
1920 return;
b00d3884
TL
1921 }
1922 }
1923
1924 /* If there are no other leases, give up. */
02d9e453
TL
1925 if (!client -> leases) {
1926 client -> leases = client -> active;
1927 client -> active = (struct client_lease *)0;
b00d3884
TL
1928 break;
1929 }
1930
deff2d59 1931 activate_next:
b00d3884
TL
1932 /* Otherwise, put the active lease at the end of the
1933 lease list, and try another lease.. */
02d9e453 1934 for (lp = client -> leases; lp -> next; lp = lp -> next)
b00d3884 1935 ;
02d9e453 1936 lp -> next = client -> active;
34fdad6c
TL
1937 if (lp -> next) {
1938 lp -> next -> next = (struct client_lease *)0;
1939 }
02d9e453
TL
1940 client -> active = client -> leases;
1941 client -> leases = client -> leases -> next;
b00d3884
TL
1942
1943 /* If we already tried this lease, we've exhausted the
1944 set of leases, so we might as well give up for
1945 now. */
02d9e453 1946 if (client -> active == loop)
b00d3884 1947 break;
66f973e4 1948 else if (!loop)
02d9e453 1949 loop = client -> active;
b00d3884
TL
1950 }
1951
1952 /* No leases were available, or what was available didn't work, so
1953 tell the shell script that we failed to allocate an address,
1954 and try again later. */
c08637bb
TL
1955 if (onetry) {
1956 if (!quiet)
1957 log_info ("Unable to obtain a lease on first try.%s",
1958 " Exiting.");
1959 exit (2);
1960 }
1961
11373fb6 1962 log_info ("No working leases in persistent database - sleeping.");
02d9e453
TL
1963 script_init (client, "FAIL", (struct string_list *)0);
1964 if (client -> alias)
1965 script_write_params (client, "alias_", client -> alias);
1966 script_go (client);
1967 client -> state = S_INIT;
be62cf06 1968 tv . tv_sec = cur_time +
11373fb6 1969 ((client -> config -> retry_interval + 1) / 2 +
be62cf06
FD
1970 (random () % client -> config -> retry_interval));
1971 tv . tv_usec = 0;
1972 add_timeout (&tv, state_init, client, 0, 0);
ae04fa03 1973 go_daemon ();
b00d3884
TL
1974}
1975
02d9e453
TL
1976void send_request (cpp)
1977 void *cpp;
e581d615 1978{
02d9e453 1979 struct client_state *client = cpp;
84c4adde 1980
c1503c57 1981 int result;
cc26de46
TL
1982 int interval;
1983 struct sockaddr_in destination;
1984 struct in_addr from;
be62cf06 1985 struct timeval tv;
cc26de46
TL
1986
1987 /* Figure out how long it's been since we started transmitting. */
02d9e453 1988 interval = cur_time - client -> first_sending;
cc26de46 1989
34fdad6c
TL
1990 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1991 past the reboot timeout, go to INIT and see if we can
1992 DISCOVER an address... */
1993 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1994 means either that we're on a network with no DHCP server,
1995 or that our server is down. In the latter case, assuming
1996 that there is a backup DHCP server, DHCPDISCOVER will get
1997 us a new address, but we could also have successfully
1998 reused our old address. In the former case, we're hosed
1999 anyway. This is not a win-prone situation. */
02d9e453
TL
2000 if ((client -> state == S_REBOOTING ||
2001 client -> state == S_REQUESTING) &&
2002 interval > client -> config -> reboot_timeout) {
b8cf055d 2003 cancel:
02d9e453
TL
2004 client -> state = S_INIT;
2005 cancel_timeout (send_request, client);
2006 state_init (client);
deff2d59
TL
2007 return;
2008 }
2009
b8cf055d
TL
2010 /* If we're in the reboot state, make sure the media is set up
2011 correctly. */
02d9e453
TL
2012 if (client -> state == S_REBOOTING &&
2013 !client -> medium &&
2014 client -> active -> medium ) {
2015 script_init (client, "MEDIUM", client -> active -> medium);
b8cf055d
TL
2016
2017 /* If the medium we chose won't fly, go to INIT state. */
02d9e453 2018 if (script_go (client))
b8cf055d
TL
2019 goto cancel;
2020
2021 /* Record the medium. */
02d9e453 2022 client -> medium = client -> active -> medium;
b8cf055d
TL
2023 }
2024
cc26de46
TL
2025 /* If the lease has expired, relinquish the address and go back
2026 to the INIT state. */
02d9e453
TL
2027 if (client -> state != S_REQUESTING &&
2028 cur_time > client -> active -> expiry) {
cc26de46 2029 /* Run the client script with the new parameters. */
02d9e453
TL
2030 script_init (client, "EXPIRE", (struct string_list *)0);
2031 script_write_params (client, "old_", client -> active);
2032 if (client -> alias)
2033 script_write_params (client, "alias_",
2034 client -> alias);
2035 script_go (client);
2036
62d0cb47
TL
2037 /* Now do a preinit on the interface so that we can
2038 discover a new address. */
2039 script_init (client, "PREINIT", (struct string_list *)0);
2040 if (client -> alias)
2041 script_write_params (client, "alias_",
2042 client -> alias);
2043 script_go (client);
2044
02d9e453
TL
2045 client -> state = S_INIT;
2046 state_init (client);
cc26de46
TL
2047 return;
2048 }
2049
2050 /* Do the exponential backoff... */
02d9e453
TL
2051 if (!client -> interval)
2052 client -> interval = client -> config -> initial_interval;
34fdad6c 2053 else {
02d9e453
TL
2054 client -> interval += ((random () >> 2) %
2055 (2 * client -> interval));
34fdad6c 2056 }
3dbe2246 2057
34fdad6c 2058 /* Don't backoff past cutoff. */
02d9e453
TL
2059 if (client -> interval >
2060 client -> config -> backoff_cutoff)
2061 client -> interval =
2062 ((client -> config -> backoff_cutoff / 2)
98311e4b
DH
2063 + ((random () >> 2) %
2064 client -> config -> backoff_cutoff));
cc26de46
TL
2065
2066 /* If the backoff would take us to the expiry time, just set the
2067 timeout to the expiry time. */
02d9e453
TL
2068 if (client -> state != S_REQUESTING &&
2069 cur_time + client -> interval > client -> active -> expiry)
2070 client -> interval =
2071 client -> active -> expiry - cur_time + 1;
cc26de46
TL
2072
2073 /* If the lease T2 time has elapsed, or if we're not yet bound,
2074 broadcast the DHCPREQUEST rather than unicasting. */
02d9e453 2075 if (client -> state == S_REQUESTING ||
62d0cb47 2076 client -> state == S_REBOOTING ||
02d9e453 2077 cur_time > client -> active -> rebind)
3020a2c1 2078 destination.sin_addr = sockaddr_broadcast.sin_addr;
cc26de46
TL
2079 else
2080 memcpy (&destination.sin_addr.s_addr,
02d9e453 2081 client -> destination.iabuf,
cc26de46
TL
2082 sizeof destination.sin_addr.s_addr);
2083 destination.sin_port = remote_port;
b00d3884
TL
2084 destination.sin_family = AF_INET;
2085#ifdef HAVE_SA_LEN
2086 destination.sin_len = sizeof destination;
2087#endif
cc26de46 2088
7d3bc735
TL
2089 if (client -> state == S_RENEWING ||
2090 client -> state == S_REBINDING)
02d9e453 2091 memcpy (&from, client -> active -> address.iabuf,
cc26de46
TL
2092 sizeof from);
2093 else
2094 from.s_addr = INADDR_ANY;
2095
34fdad6c 2096 /* Record the number of seconds since we started sending. */
af6df788
TL
2097 if (client -> state == S_REQUESTING)
2098 client -> packet.secs = client -> secs;
2099 else {
2100 if (interval < 65536)
2101 client -> packet.secs = htons (interval);
2102 else
2103 client -> packet.secs = htons (65535);
2104 }
34fdad6c 2105
8ae2d595 2106 log_info ("DHCPREQUEST on %s to %s port %d",
02d9e453 2107 client -> name ? client -> name : client -> interface -> name,
cc26de46
TL
2108 inet_ntoa (destination.sin_addr),
2109 ntohs (destination.sin_port));
2110
62d0cb47
TL
2111 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
2112 fallback_interface)
2113 result = send_packet (fallback_interface,
2114 (struct packet *)0,
2115 &client -> packet,
2116 client -> packet_length,
2117 from, &destination,
2118 (struct hardware *)0);
cc26de46 2119 else
cc26de46 2120 /* Send out a packet. */
02d9e453
TL
2121 result = send_packet (client -> interface, (struct packet *)0,
2122 &client -> packet,
2123 client -> packet_length,
cc26de46
TL
2124 from, &destination,
2125 (struct hardware *)0);
469cf3a4 2126
be62cf06
FD
2127 tv . tv_sec = cur_time + client -> interval;
2128 tv . tv_usec = 0;
2129 add_timeout (&tv, send_request, client, 0, 0);
469cf3a4
TL
2130}
2131
02d9e453
TL
2132void send_decline (cpp)
2133 void *cpp;
b00d3884 2134{
02d9e453 2135 struct client_state *client = cpp;
84c4adde 2136
b00d3884
TL
2137 int result;
2138
8ae2d595 2139 log_info ("DHCPDECLINE on %s to %s port %d",
02d9e453 2140 client -> name ? client -> name : client -> interface -> name,
b00d3884
TL
2141 inet_ntoa (sockaddr_broadcast.sin_addr),
2142 ntohs (sockaddr_broadcast.sin_port));
2143
2144 /* Send out a packet. */
02d9e453
TL
2145 result = send_packet (client -> interface, (struct packet *)0,
2146 &client -> packet,
2147 client -> packet_length,
b00d3884
TL
2148 inaddr_any, &sockaddr_broadcast,
2149 (struct hardware *)0);
b00d3884
TL
2150}
2151
02d9e453
TL
2152void send_release (cpp)
2153 void *cpp;
b00d3884 2154{
02d9e453 2155 struct client_state *client = cpp;
84c4adde 2156
b00d3884 2157 int result;
007e3ee4
TL
2158 struct sockaddr_in destination;
2159 struct in_addr from;
2160
2161 memcpy (&from, client -> active -> address.iabuf,
2162 sizeof from);
2163 memcpy (&destination.sin_addr.s_addr,
2164 client -> destination.iabuf,
2165 sizeof destination.sin_addr.s_addr);
2166 destination.sin_port = remote_port;
2167 destination.sin_family = AF_INET;
2168#ifdef HAVE_SA_LEN
2169 destination.sin_len = sizeof destination;
2170#endif
2171
007e3ee4
TL
2172 /* Set the lease to end now, so that we don't accidentally
2173 reuse it if we restart before the old expiry time. */
2174 client -> active -> expiry =
2175 client -> active -> renewal =
2176 client -> active -> rebind = cur_time;
2177 if (!write_client_lease (client, client -> active, 1, 1)) {
2178 log_error ("Can't release lease: lease write failed.");
2179 return;
2180 }
b00d3884 2181
8ae2d595 2182 log_info ("DHCPRELEASE on %s to %s port %d",
02d9e453 2183 client -> name ? client -> name : client -> interface -> name,
007e3ee4
TL
2184 inet_ntoa (destination.sin_addr),
2185 ntohs (destination.sin_port));
b00d3884 2186
007e3ee4
TL
2187 if (fallback_interface)
2188 result = send_packet (fallback_interface,
2189 (struct packet *)0,
2190 &client -> packet,
2191 client -> packet_length,
2192 from, &destination,
2193 (struct hardware *)0);
2194 else
2195 /* Send out a packet. */
2196 result = send_packet (client -> interface, (struct packet *)0,
2197 &client -> packet,
2198 client -> packet_length,
2199 from, &destination,
2200 (struct hardware *)0);
b00d3884
TL
2201}
2202
0c20eab3
DH
2203void
2204make_client_options(struct client_state *client, struct client_lease *lease,
2205 u_int8_t *type, struct option_cache *sid,
2206 struct iaddr *rip, struct option **prl,
2207 struct option_state **op)
469cf3a4 2208{
b1b7b521 2209 unsigned i;
02a015fb 2210 struct option_cache *oc;
f7fdb216 2211 struct option *option = NULL;
02a015fb
TL
2212 struct buffer *bp = (struct buffer *)0;
2213
d758ad8c
TL
2214 /* If there are any leftover options, get rid of them. */
2215 if (*op)
2216 option_state_dereference (op, MDL);
2217
230e73e4 2218 /* Allocate space for options. */
cf78bf20 2219 option_state_allocate (op, MDL);
02a015fb
TL
2220
2221 /* Send the server identifier if provided. */
2222 if (sid)
230e73e4 2223 save_option (&dhcp_universe, *op, sid);
02a015fb 2224
2455808f
TL
2225 oc = (struct option_cache *)0;
2226
02a015fb
TL
2227 /* Send the requested address if provided. */
2228 if (rip) {
02d9e453 2229 client -> requested_address = *rip;
f7fdb216
DH
2230 i = DHO_DHCP_REQUESTED_ADDRESS;
2231 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
2232 &i, 0, MDL) &&
2233 make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
2234 option, MDL)))
230e73e4 2235 log_error ("can't make requested address cache.");
02a015fb 2236 else {
230e73e4 2237 save_option (&dhcp_universe, *op, oc);
cf78bf20 2238 option_cache_dereference (&oc, MDL);
02a015fb 2239 }
f7fdb216 2240 option_dereference(&option, MDL);
b00d3884 2241 } else {
02d9e453 2242 client -> requested_address.len = 0;
cc26de46 2243 }
c1503c57 2244
f7fdb216
DH
2245 i = DHO_DHCP_MESSAGE_TYPE;
2246 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
2247 MDL) &&
2248 make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
8ae2d595 2249 log_error ("can't make message type.");
02a015fb 2250 else {
230e73e4 2251 save_option (&dhcp_universe, *op, oc);
cf78bf20 2252 option_cache_dereference (&oc, MDL);
02a015fb 2253 }
f7fdb216 2254 option_dereference(&option, MDL);
02a015fb
TL
2255
2256 if (prl) {
0c20eab3
DH
2257 int len;
2258
2259 /* Probe the length of the list. */
2260 len = 0;
2261 for (i = 0 ; prl[i] != NULL ; i++)
2262 if (prl[i]->universe == &dhcp_universe)
2263 len++;
2264
2265 if (!buffer_allocate (&bp, len, MDL))
230e73e4 2266 log_error ("can't make parameter list buffer.");
02a015fb 2267 else {
d6614ea2
DH
2268 unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
2269
0c20eab3
DH
2270 len = 0;
2271 for (i = 0 ; prl[i] != NULL ; i++)
2272 if (prl[i]->universe == &dhcp_universe)
2273 bp->data[len++] = prl[i]->code;
2274
f7fdb216
DH
2275 if (!(option_code_hash_lookup(&option,
2276 dhcp_universe.code_hash,
d6614ea2 2277 &code, 0, MDL) &&
0c20eab3 2278 make_const_option_cache(&oc, &bp, NULL, len,
f7fdb216 2279 option, MDL)))
8ae2d595 2280 log_error ("can't make option cache");
02a015fb 2281 else {
230e73e4 2282 save_option (&dhcp_universe, *op, oc);
cf78bf20 2283 option_cache_dereference (&oc, MDL);
02a015fb 2284 }
f7fdb216 2285 option_dereference(&option, MDL);
deff2d59
TL
2286 }
2287 }
2288
02a015fb 2289 /* Run statements that need to be run on transmission. */
73530742
TL
2290 if (client -> config -> on_transmission)
2291 execute_statements_in_scope
1b234d44 2292 ((struct binding_value **)0,
66e9cecf 2293 (struct packet *)0, (struct lease *)0, client,
da38df14 2294 (lease ? lease -> options : (struct option_state *)0),
cf78bf20
TL
2295 *op, &global_scope,
2296 client -> config -> on_transmission,
73530742 2297 (struct group *)0);
02a015fb
TL
2298}
2299
02d9e453
TL
2300void make_discover (client, lease)
2301 struct client_state *client;
02a015fb
TL
2302 struct client_lease *lease;
2303{
02a015fb 2304 unsigned char discover = DHCPDISCOVER;
230e73e4 2305 struct option_state *options = (struct option_state *)0;
02a015fb 2306
02d9e453 2307 memset (&client -> packet, 0, sizeof (client -> packet));
02a015fb 2308
02d9e453
TL
2309 make_client_options (client,
2310 lease, &discover, (struct option_cache *)0,
02a015fb 2311 lease ? &lease -> address : (struct iaddr *)0,
02d9e453 2312 client -> config -> requested_options,
02a015fb
TL
2313 &options);
2314
c1503c57 2315 /* Set up the option buffer... */
02d9e453 2316 client -> packet_length =
da38df14 2317 cons_options ((struct packet *)0, &client -> packet,
98311e4b
DH
2318 (struct lease *)0, client,
2319 /* maximum packet size */1500,
2320 (struct option_state *)0,
2321 options,
2322 /* scope */ &global_scope,
2323 /* overload */ 0,
2324 /* terminate */0,
2325 /* bootpp */0,
2326 (struct data_string *)0,
ce75142f 2327 client -> config -> vendor_space_name);
98311e4b
DH
2328
2329 option_state_dereference (&options, MDL);
02d9e453
TL
2330 if (client -> packet_length < BOOTP_MIN_LEN)
2331 client -> packet_length = BOOTP_MIN_LEN;
2332
2333 client -> packet.op = BOOTREQUEST;
31730f17
TL
2334 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2335 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02d9e453
TL
2336 client -> packet.hops = 0;
2337 client -> packet.xid = random ();
2338 client -> packet.secs = 0; /* filled in by send_discover. */
f345b36d
TL
2339
2340 if (can_receive_unicast_unconfigured (client -> interface))
2341 client -> packet.flags = 0;
2342 else
2343 client -> packet.flags = htons (BOOTP_BROADCAST);
2344
02d9e453
TL
2345 memset (&(client -> packet.ciaddr),
2346 0, sizeof client -> packet.ciaddr);
2347 memset (&(client -> packet.yiaddr),
2348 0, sizeof client -> packet.yiaddr);
2349 memset (&(client -> packet.siaddr),
2350 0, sizeof client -> packet.siaddr);
11373fb6 2351 client -> packet.giaddr = giaddr;
31730f17
TL
2352 if (client -> interface -> hw_address.hlen > 0)
2353 memcpy (client -> packet.chaddr,
2354 &client -> interface -> hw_address.hbuf [1],
2355 (unsigned)(client -> interface -> hw_address.hlen - 1));
c1503c57
TL
2356
2357#ifdef DEBUG_PACKET
01aeb18a 2358 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
c1503c57 2359#endif
c1503c57
TL
2360}
2361
469cf3a4 2362
02d9e453
TL
2363void make_request (client, lease)
2364 struct client_state *client;
cc26de46 2365 struct client_lease *lease;
c1503c57 2366{
c1503c57 2367 unsigned char request = DHCPREQUEST;
02a015fb 2368 struct option_cache *oc;
c1503c57 2369
02d9e453 2370 memset (&client -> packet, 0, sizeof (client -> packet));
469cf3a4 2371
02d9e453 2372 if (client -> state == S_REQUESTING)
230e73e4 2373 oc = lookup_option (&dhcp_universe, lease -> options,
02a015fb
TL
2374 DHO_DHCP_SERVER_IDENTIFIER);
2375 else
2376 oc = (struct option_cache *)0;
8dba80a6 2377
98311e4b
DH
2378 if (client -> sent_options)
2379 option_state_dereference (&client -> sent_options, MDL);
2380
02d9e453
TL
2381 make_client_options (client, lease, &request, oc,
2382 ((client -> state == S_REQUESTING ||
2383 client -> state == S_REBOOTING)
02a015fb
TL
2384 ? &lease -> address
2385 : (struct iaddr *)0),
02d9e453 2386 client -> config -> requested_options,
d758ad8c 2387 &client -> sent_options);
deff2d59 2388
c1503c57 2389 /* Set up the option buffer... */
02d9e453 2390 client -> packet_length =
da38df14 2391 cons_options ((struct packet *)0, &client -> packet,
98311e4b
DH
2392 (struct lease *)0, client,
2393 /* maximum packet size */1500,
2394 (struct option_state *)0,
3dbe2246 2395 client -> sent_options,
98311e4b
DH
2396 /* scope */ &global_scope,
2397 /* overload */ 0,
2398 /* terminate */0,
2399 /* bootpp */0,
2400 (struct data_string *)0,
ce75142f 2401 client -> config -> vendor_space_name);
98311e4b 2402
02d9e453
TL
2403 if (client -> packet_length < BOOTP_MIN_LEN)
2404 client -> packet_length = BOOTP_MIN_LEN;
cc26de46 2405
02d9e453 2406 client -> packet.op = BOOTREQUEST;
31730f17
TL
2407 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2408 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02d9e453
TL
2409 client -> packet.hops = 0;
2410 client -> packet.xid = client -> xid;
2411 client -> packet.secs = 0; /* Filled in by send_request. */
cc26de46
TL
2412
2413 /* If we own the address we're requesting, put it in ciaddr;
2414 otherwise set ciaddr to zero. */
02d9e453
TL
2415 if (client -> state == S_BOUND ||
2416 client -> state == S_RENEWING ||
62d0cb47 2417 client -> state == S_REBINDING) {
02d9e453 2418 memcpy (&client -> packet.ciaddr,
cc26de46 2419 lease -> address.iabuf, lease -> address.len);
339b0231 2420 client -> packet.flags = 0;
62d0cb47 2421 } else {
02d9e453
TL
2422 memset (&client -> packet.ciaddr, 0,
2423 sizeof client -> packet.ciaddr);
f345b36d
TL
2424 if (can_receive_unicast_unconfigured (client -> interface))
2425 client -> packet.flags = 0;
2426 else
2427 client -> packet.flags = htons (BOOTP_BROADCAST);
62d0cb47 2428 }
02d9e453
TL
2429
2430 memset (&client -> packet.yiaddr, 0,
2431 sizeof client -> packet.yiaddr);
2432 memset (&client -> packet.siaddr, 0,
2433 sizeof client -> packet.siaddr);
1c44f6bd
TL
2434 if (client -> state != S_BOUND &&
2435 client -> state != S_RENEWING)
2436 client -> packet.giaddr = giaddr;
2437 else
2438 memset (&client -> packet.giaddr, 0,
2439 sizeof client -> packet.giaddr);
31730f17
TL
2440 if (client -> interface -> hw_address.hlen > 0)
2441 memcpy (client -> packet.chaddr,
2442 &client -> interface -> hw_address.hbuf [1],
2443 (unsigned)(client -> interface -> hw_address.hlen - 1));
c1503c57
TL
2444
2445#ifdef DEBUG_PACKET
01aeb18a 2446 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
c1503c57 2447#endif
469cf3a4 2448}
c1503c57 2449
02d9e453
TL
2450void make_decline (client, lease)
2451 struct client_state *client;
cc26de46 2452 struct client_lease *lease;
469cf3a4 2453{
cc26de46 2454 unsigned char decline = DHCPDECLINE;
02a015fb 2455 struct option_cache *oc;
c1503c57 2456
230e73e4 2457 struct option_state *options = (struct option_state *)0;
c1503c57 2458
40ec5f38 2459 /* Create the options cache. */
230e73e4 2460 oc = lookup_option (&dhcp_universe, lease -> options,
02a015fb 2461 DHO_DHCP_SERVER_IDENTIFIER);
0c20eab3
DH
2462 make_client_options(client, lease, &decline, oc, &lease->address,
2463 NULL, &options);
ca25f4ab 2464
40ec5f38 2465 /* Consume the options cache into the option buffer. */
230e73e4 2466 memset (&client -> packet, 0, sizeof (client -> packet));
02d9e453 2467 client -> packet_length =
da38df14 2468 cons_options ((struct packet *)0, &client -> packet,
66e9cecf 2469 (struct lease *)0, client, 0,
0852a27f 2470 (struct option_state *)0, options,
ce75142f
TL
2471 &global_scope, 0, 0, 0, (struct data_string *)0,
2472 client -> config -> vendor_space_name);
40ec5f38
DH
2473
2474 /* Destroy the options cache. */
98311e4b 2475 option_state_dereference (&options, MDL);
40ec5f38 2476
02d9e453
TL
2477 if (client -> packet_length < BOOTP_MIN_LEN)
2478 client -> packet_length = BOOTP_MIN_LEN;
cc26de46 2479
02d9e453 2480 client -> packet.op = BOOTREQUEST;
31730f17
TL
2481 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2482 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02d9e453
TL
2483 client -> packet.hops = 0;
2484 client -> packet.xid = client -> xid;
2485 client -> packet.secs = 0; /* Filled in by send_request. */
7d3bc735
TL
2486 if (can_receive_unicast_unconfigured (client -> interface))
2487 client -> packet.flags = 0;
2488 else
2489 client -> packet.flags = htons (BOOTP_BROADCAST);
cc26de46
TL
2490
2491 /* ciaddr must always be zero. */
02d9e453
TL
2492 memset (&client -> packet.ciaddr, 0,
2493 sizeof client -> packet.ciaddr);
2494 memset (&client -> packet.yiaddr, 0,
2495 sizeof client -> packet.yiaddr);
2496 memset (&client -> packet.siaddr, 0,
2497 sizeof client -> packet.siaddr);
11373fb6 2498 client -> packet.giaddr = giaddr;
02d9e453 2499 memcpy (client -> packet.chaddr,
31730f17 2500 &client -> interface -> hw_address.hbuf [1],
02d9e453 2501 client -> interface -> hw_address.hlen);
cc26de46
TL
2502
2503#ifdef DEBUG_PACKET
01aeb18a 2504 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
cc26de46
TL
2505#endif
2506}
2507
02d9e453
TL
2508void make_release (client, lease)
2509 struct client_state *client;
cc26de46
TL
2510 struct client_lease *lease;
2511{
2512 unsigned char request = DHCPRELEASE;
02a015fb 2513 struct option_cache *oc;
cc26de46 2514
230e73e4 2515 struct option_state *options = (struct option_state *)0;
cc26de46 2516
02d9e453 2517 memset (&client -> packet, 0, sizeof (client -> packet));
469cf3a4 2518
230e73e4 2519 oc = lookup_option (&dhcp_universe, lease -> options,
02a015fb 2520 DHO_DHCP_SERVER_IDENTIFIER);
0c20eab3 2521 make_client_options(client, lease, &request, oc, NULL, NULL, &options);
469cf3a4
TL
2522
2523 /* Set up the option buffer... */
02d9e453 2524 client -> packet_length =
da38df14 2525 cons_options ((struct packet *)0, &client -> packet,
98311e4b
DH
2526 (struct lease *)0, client,
2527 /* maximum packet size */1500,
2528 (struct option_state *)0,
2529 options,
2530 /* scope */ &global_scope,
2531 /* overload */ 0,
2532 /* terminate */0,
2533 /* bootpp */0,
2534 (struct data_string *)0,
ce75142f 2535 client -> config -> vendor_space_name);
98311e4b 2536
02d9e453
TL
2537 if (client -> packet_length < BOOTP_MIN_LEN)
2538 client -> packet_length = BOOTP_MIN_LEN;
cf78bf20 2539 option_state_dereference (&options, MDL);
02d9e453
TL
2540
2541 client -> packet.op = BOOTREQUEST;
31730f17
TL
2542 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
2543 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02d9e453 2544 client -> packet.hops = 0;
74f45f96 2545 client -> packet.xid = random ();
02d9e453
TL
2546 client -> packet.secs = 0;
2547 client -> packet.flags = 0;
2548 memcpy (&client -> packet.ciaddr,
cc26de46 2549 lease -> address.iabuf, lease -> address.len);
02d9e453
TL
2550 memset (&client -> packet.yiaddr, 0,
2551 sizeof client -> packet.yiaddr);
2552 memset (&client -> packet.siaddr, 0,
2553 sizeof client -> packet.siaddr);
11373fb6 2554 client -> packet.giaddr = giaddr;
02d9e453 2555 memcpy (client -> packet.chaddr,
bdcaf7b9 2556 &client -> interface -> hw_address.hbuf [1],
02d9e453 2557 client -> interface -> hw_address.hlen);
469cf3a4
TL
2558
2559#ifdef DEBUG_PACKET
01aeb18a 2560 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
469cf3a4 2561#endif
e581d615 2562}
cc26de46 2563
02a015fb 2564void destroy_client_lease (lease)
cc26de46
TL
2565 struct client_lease *lease;
2566{
cc26de46 2567 if (lease -> server_name)
cf78bf20 2568 dfree (lease -> server_name, MDL);
cc26de46 2569 if (lease -> filename)
cf78bf20
TL
2570 dfree (lease -> filename, MDL);
2571 option_state_dereference (&lease -> options, MDL);
2572 free_client_lease (lease, MDL);
cc26de46
TL
2573}
2574
98bd7ca0
DH
2575FILE *leaseFile = NULL;
2576int leases_written = 0;
cc26de46
TL
2577
2578void rewrite_client_leases ()
2579{
2580 struct interface_info *ip;
02d9e453 2581 struct client_state *client;
cc26de46
TL
2582 struct client_lease *lp;
2583
98bd7ca0 2584 if (leaseFile != NULL)
cc26de46
TL
2585 fclose (leaseFile);
2586 leaseFile = fopen (path_dhclient_db, "w");
98bd7ca0 2587 if (leaseFile == NULL) {
ee8a3653
TL
2588 log_error ("can't create %s: %m", path_dhclient_db);
2589 return;
2590 }
b00d3884 2591
98bd7ca0
DH
2592 /* If there is a default duid, write it out. */
2593 if (default_duid.len != 0)
2594 write_duid(&default_duid);
2595
b00d3884
TL
2596 /* Write out all the leases attached to configured interfaces that
2597 we know about. */
cc26de46 2598 for (ip = interfaces; ip; ip = ip -> next) {
02d9e453
TL
2599 for (client = ip -> client; client; client = client -> next) {
2600 for (lp = client -> leases; lp; lp = lp -> next) {
007e3ee4 2601 write_client_lease (client, lp, 1, 0);
02d9e453
TL
2602 }
2603 if (client -> active)
2604 write_client_lease (client,
007e3ee4 2605 client -> active, 1, 0);
98bd7ca0
DH
2606
2607 if (client->active_lease != NULL)
2608 write_client6_lease(client,
2609 client->active_lease,
2610 1, 0);
cc26de46 2611 }
cc26de46 2612 }
b00d3884
TL
2613
2614 /* Write out any leases that are attached to interfaces that aren't
2615 currently configured. */
2616 for (ip = dummy_interfaces; ip; ip = ip -> next) {
02d9e453
TL
2617 for (client = ip -> client; client; client = client -> next) {
2618 for (lp = client -> leases; lp; lp = lp -> next) {
007e3ee4 2619 write_client_lease (client, lp, 1, 0);
02d9e453
TL
2620 }
2621 if (client -> active)
2622 write_client_lease (client,
007e3ee4 2623 client -> active, 1, 0);
98bd7ca0
DH
2624
2625 if (client->active_lease != NULL)
2626 write_client6_lease(client,
2627 client->active_lease,
2628 1, 0);
b00d3884 2629 }
b00d3884 2630 }
cc26de46
TL
2631 fflush (leaseFile);
2632}
2633
c0504523
TL
2634void write_lease_option (struct option_cache *oc,
2635 struct packet *packet, struct lease *lease,
66e9cecf 2636 struct client_state *client_state,
c0504523
TL
2637 struct option_state *in_options,
2638 struct option_state *cfg_options,
2639 struct binding_scope **scope,
2640 struct universe *u, void *stuff)
2641{
2642 const char *name, *dot;
2643 struct data_string ds;
98bd7ca0 2644 char *preamble = stuff;
b5f904a9 2645
c0504523
TL
2646 memset (&ds, 0, sizeof ds);
2647
2648 if (u != &dhcp_universe) {
2649 name = u -> name;
2650 dot = ".";
2651 } else {
2652 name = "";
2653 dot = "";
2654 }
66e9cecf 2655 if (evaluate_option_cache (&ds, packet, lease, client_state,
c0504523 2656 in_options, cfg_options, scope, oc, MDL)) {
98bd7ca0
DH
2657 fprintf(leaseFile, "%soption %s%s%s %s;\n", preamble,
2658 name, dot, oc->option->name,
2659 pretty_print_option(oc->option, ds.data, ds.len,
2660 1, 1));
c0504523
TL
2661 data_string_forget (&ds, MDL);
2662 }
2663}
2664
98bd7ca0
DH
2665/* Write an option cache to the lease store. */
2666static void
2667write_options(struct client_state *client, struct option_state *options,
06eb8bab 2668 const char *preamble)
98bd7ca0
DH
2669{
2670 int i;
2671
2672 for (i = 0; i < options->universe_count; i++) {
2673 option_space_foreach(NULL, NULL, client, NULL, options,
3dbe2246 2674 &global_scope, universes[i],
06eb8bab 2675 (char *)preamble, write_lease_option);
98bd7ca0
DH
2676 }
2677}
2678
2679/* Write the default DUID to the lease store. */
2680static isc_result_t
2681write_duid(struct data_string *duid)
2682{
2683 char *str;
2684 int stat;
2685
2686 if ((duid == NULL) || (duid->len <= 2))
98bf1607 2687 return DHCP_R_INVALIDARG;
98bd7ca0
DH
2688
2689 if (leaseFile == NULL) { /* XXX? */
2690 leaseFile = fopen(path_dhclient_db, "w");
2691 if (leaseFile == NULL) {
2692 log_error("can't create %s: %m", path_dhclient_db);
2693 return ISC_R_IOERROR;
2694 }
2695 }
2696
2697 /* It would make more sense to write this as a hex string,
2698 * but our function to do that (print_hex_n) uses a fixed
2699 * length buffer...and we can't guarantee a duid would be
2700 * less than the fixed length.
2701 */
2702 str = quotify_buf(duid->data, duid->len, MDL);
2703 if (str == NULL)
2704 return ISC_R_NOMEMORY;
2705
2706 stat = fprintf(leaseFile, "default-duid \"%s\";\n", str);
2707 dfree(str, MDL);
2708 if (stat <= 0)
2709 return ISC_R_IOERROR;
2710
2711 if (fflush(leaseFile) != 0)
2712 return ISC_R_IOERROR;
6705543f
DH
2713
2714 return ISC_R_SUCCESS;
98bd7ca0
DH
2715}
2716
2717/* Write a DHCPv6 lease to the store. */
2718isc_result_t
2719write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
2720 int rewrite, int sync)
2721{
2722 struct dhc6_ia *ia;
2723 struct dhc6_addr *addr;
2724 int stat;
1d9774ab 2725 const char *ianame;
98bd7ca0
DH
2726
2727 /* This should include the current lease. */
2728 if (!rewrite && (leases_written++ > 20)) {
2729 rewrite_client_leases();
2730 leases_written = 0;
2731 return ISC_R_SUCCESS;
2732 }
2733
2734 if (client == NULL || lease == NULL)
98bf1607 2735 return DHCP_R_INVALIDARG;
98bd7ca0
DH
2736
2737 if (leaseFile == NULL) { /* XXX? */
2738 leaseFile = fopen(path_dhclient_db, "w");
2739 if (leaseFile == NULL) {
2740 log_error("can't create %s: %m", path_dhclient_db);
2741 return ISC_R_IOERROR;
2742 }
2743 }
2744
2745 stat = fprintf(leaseFile, "lease6 {\n");
2746 if (stat <= 0)
2747 return ISC_R_IOERROR;
2748
2749 stat = fprintf(leaseFile, " interface \"%s\";\n",
2750 client->interface->name);
2751 if (stat <= 0)
2752 return ISC_R_IOERROR;
2753
2754 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
1d9774ab
FD
2755 switch (ia->ia_type) {
2756 case D6O_IA_NA:
2757 default:
2758 ianame = "ia-na";
2759 break;
2760 case D6O_IA_TA:
2761 ianame = "ia-ta";
2762 break;
2763 case D6O_IA_PD:
2764 ianame = "ia-pd";
2765 break;
2766 }
2767 stat = fprintf(leaseFile, " %s %s {\n",
2768 ianame, print_hex_1(4, ia->iaid, 12));
98bd7ca0
DH
2769 if (stat <= 0)
2770 return ISC_R_IOERROR;
2771
1d9774ab
FD
2772 if (ia->ia_type != D6O_IA_TA)
2773 stat = fprintf(leaseFile, " starts %d;\n"
2774 " renew %u;\n"
2775 " rebind %u;\n",
2776 (int)ia->starts, ia->renew, ia->rebind);
2777 else
2778 stat = fprintf(leaseFile, " starts %d;\n",
2779 (int)ia->starts);
98bd7ca0
DH
2780 if (stat <= 0)
2781 return ISC_R_IOERROR;
2782
2783 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
1d9774ab
FD
2784 if (ia->ia_type != D6O_IA_PD)
2785 stat = fprintf(leaseFile,
2786 " iaaddr %s {\n",
2787 piaddr(addr->address));
2788 else
2789 stat = fprintf(leaseFile,
2790 " iaprefix %s/%d {\n",
2791 piaddr(addr->address),
2792 (int)addr->plen);
98bd7ca0
DH
2793 if (stat <= 0)
2794 return ISC_R_IOERROR;
2795
2796 stat = fprintf(leaseFile, " starts %d;\n"
2797 " preferred-life %u;\n"
2798 " max-life %u;\n",
6705543f 2799 (int)addr->starts, addr->preferred_life,
98bd7ca0
DH
2800 addr->max_life);
2801 if (stat <= 0)
2802 return ISC_R_IOERROR;
2803
2804 if (addr->options != NULL)
2805 write_options(client, addr->options, " ");
2806
2807 stat = fprintf(leaseFile, " }\n");
2808 if (stat <= 0)
2809 return ISC_R_IOERROR;
2810 }
2811
2812 if (ia->options != NULL)
2813 write_options(client, ia->options, " ");
2814
2815 stat = fprintf(leaseFile, " }\n");
2816 if (stat <= 0)
2817 return ISC_R_IOERROR;
2818 }
2819
cabdb9b1
FD
2820 if (lease->released) {
2821 stat = fprintf(leaseFile, " released;\n");
2822 if (stat <= 0)
2823 return ISC_R_IOERROR;
2824 }
2825
98bd7ca0
DH
2826 if (lease->options != NULL)
2827 write_options(client, lease->options, " ");
2828
2829 stat = fprintf(leaseFile, "}\n");
2830 if (stat <= 0)
2831 return ISC_R_IOERROR;
2832
2833 if (fflush(leaseFile) != 0)
2834 return ISC_R_IOERROR;
2835
2836 if (sync) {
2837 if (fsync(fileno(leaseFile)) < 0) {
2838 log_error("write_client_lease: fsync(): %m");
2839 return ISC_R_IOERROR;
2840 }
2841 }
6705543f
DH
2842
2843 return ISC_R_SUCCESS;
98bd7ca0
DH
2844}
2845
007e3ee4 2846int write_client_lease (client, lease, rewrite, makesure)
02d9e453 2847 struct client_state *client;
cc26de46 2848 struct client_lease *lease;
5c2f78b4 2849 int rewrite;
007e3ee4 2850 int makesure;
cc26de46 2851{
02a015fb 2852 struct data_string ds;
007e3ee4 2853 int errors = 0;
dd215f30 2854 char *s;
5e864416 2855 const char *tval;
5c2f78b4
TL
2856
2857 if (!rewrite) {
2858 if (leases_written++ > 20) {
2859 rewrite_client_leases ();
2860 leases_written = 0;
2861 }
2862 }
cc26de46 2863
b00d3884
TL
2864 /* If the lease came from the config file, we don't need to stash
2865 a copy in the lease database. */
2866 if (lease -> is_static)
007e3ee4 2867 return 1;
b00d3884 2868
98bd7ca0 2869 if (leaseFile == NULL) { /* XXX */
cc26de46 2870 leaseFile = fopen (path_dhclient_db, "w");
98bd7ca0 2871 if (leaseFile == NULL) {
ee8a3653
TL
2872 log_error ("can't create %s: %m", path_dhclient_db);
2873 return 0;
2874 }
cc26de46
TL
2875 }
2876
007e3ee4 2877 errno = 0;
cc26de46 2878 fprintf (leaseFile, "lease {\n");
dd215f30 2879 if (lease -> is_bootp) {
66f973e4 2880 fprintf (leaseFile, " bootp;\n");
dd215f30
TL
2881 if (errno) {
2882 ++errors;
2883 errno = 0;
2884 }
2885 }
02d9e453
TL
2886 fprintf (leaseFile, " interface \"%s\";\n",
2887 client -> interface -> name);
dd215f30
TL
2888 if (errno) {
2889 ++errors;
2890 errno = 0;
2891 }
2892 if (client -> name) {
02d9e453 2893 fprintf (leaseFile, " name \"%s\";\n", client -> name);
dd215f30
TL
2894 if (errno) {
2895 ++errors;
2896 errno = 0;
2897 }
2898 }
cc26de46
TL
2899 fprintf (leaseFile, " fixed-address %s;\n",
2900 piaddr (lease -> address));
dd215f30
TL
2901 if (errno) {
2902 ++errors;
2903 errno = 0;
2904 }
2905 if (lease -> filename) {
2906 s = quotify_string (lease -> filename, MDL);
2907 if (s) {
2908 fprintf (leaseFile, " filename \"%s\";\n", s);
2909 if (errno) {
2910 ++errors;
2911 errno = 0;
2912 }
2913 dfree (s, MDL);
2914 } else
2915 errors++;
2916
2917 }
23e10d37
DH
2918 if (lease->server_name != NULL) {
2919 s = quotify_string(lease->server_name, MDL);
2920 if (s != NULL) {
2921 fprintf(leaseFile, " server-name \"%s\";\n", s);
dd215f30
TL
2922 if (errno) {
2923 ++errors;
2924 errno = 0;
2925 }
23e10d37 2926 dfree(s, MDL);
dd215f30
TL
2927 } else
2928 ++errors;
2929 }
2930 if (lease -> medium) {
2931 s = quotify_string (lease -> medium -> string, MDL);
2932 if (s) {
2933 fprintf (leaseFile, " medium \"%s\";\n", s);
2934 if (errno) {
2935 ++errors;
2936 errno = 0;
2937 }
2938 dfree (s, MDL);
2939 } else
2940 errors++;
2941 }
007e3ee4
TL
2942 if (errno != 0) {
2943 errors++;
2944 errno = 0;
2945 }
2455808f
TL
2946
2947 memset (&ds, 0, sizeof ds);
230e73e4 2948
98bd7ca0 2949 write_options(client, lease->options, " ");
5c2f78b4 2950
5e864416
DH
2951 tval = print_time(lease->renewal);
2952 if (tval == NULL ||
2953 fprintf(leaseFile, " renew %s\n", tval) < 0)
dd215f30 2954 errors++;
5e864416
DH
2955
2956 tval = print_time(lease->rebind);
2957 if (tval == NULL ||
2958 fprintf(leaseFile, " rebind %s\n", tval) < 0)
dd215f30 2959 errors++;
5e864416
DH
2960
2961 tval = print_time(lease->expiry);
2962 if (tval == NULL ||
2963 fprintf(leaseFile, " expire %s\n", tval) < 0)
dd215f30 2964 errors++;
5e864416
DH
2965
2966 if (fprintf(leaseFile, "}\n") < 0)
dd215f30 2967 errors++;
5e864416
DH
2968
2969 if (fflush(leaseFile) != 0)
007e3ee4 2970 errors++;
5e864416 2971
007e3ee4
TL
2972 if (!errors && makesure) {
2973 if (fsync (fileno (leaseFile)) < 0) {
2974 log_info ("write_client_lease: %m");
2975 return 0;
2976 }
2977 }
2978 return errors ? 0 : 1;
cc26de46
TL
2979}
2980
2981/* Variables holding name of script and file pointer for writing to
2982 script. Needless to say, this is not reentrant - only one script
2983 can be invoked at a time. */
2984char scriptName [256];
2985FILE *scriptFile;
2986
02d9e453
TL
2987void script_init (client, reason, medium)
2988 struct client_state *client;
b1b7b521 2989 const char *reason;
9bdb9271 2990 struct string_list *medium;
cc26de46 2991{
32a47563 2992 struct string_list *sl, *next;
cc26de46 2993
02d9e453 2994 if (client) {
32a47563
TL
2995 for (sl = client -> env; sl; sl = next) {
2996 next = sl -> next;
2997 dfree (sl, MDL);
2998 }
2999 client -> env = (struct string_list *)0;
3000 client -> envc = 0;
3dbe2246 3001
02d9e453 3002 if (client -> interface) {
32a47563
TL
3003 client_envadd (client, "", "interface", "%s",
3004 client -> interface -> name);
02d9e453
TL
3005 }
3006 if (client -> name)
32a47563
TL
3007 client_envadd (client,
3008 "", "client", "%s", client -> name);
3009 if (medium)
3010 client_envadd (client,
3011 "", "medium", "%s", medium -> string);
3012
3013 client_envadd (client, "", "reason", "%s", reason);
6f7081bd 3014 client_envadd (client, "", "pid", "%ld", (long int)getpid ());
9bdb9271 3015 }
cc26de46
TL
3016}
3017
c0504523
TL
3018void client_option_envadd (struct option_cache *oc,
3019 struct packet *packet, struct lease *lease,
66e9cecf 3020 struct client_state *client_state,
c0504523
TL
3021 struct option_state *in_options,
3022 struct option_state *cfg_options,
3023 struct binding_scope **scope,
3024 struct universe *u, void *stuff)
3025{
3026 struct envadd_state *es = stuff;
3027 struct data_string data;
3028 memset (&data, 0, sizeof data);
3029
66e9cecf 3030 if (evaluate_option_cache (&data, packet, lease, client_state,
c0504523
TL
3031 in_options, cfg_options, scope, oc, MDL)) {
3032 if (data.len) {
3033 char name [256];
3034 if (dhcp_option_ev_name (name, sizeof name,
3035 oc -> option)) {
3036 client_envadd (es -> client, es -> prefix,
3037 name, "%s",
3038 (pretty_print_option
b5f904a9 3039 (oc -> option,
c0504523
TL
3040 data.data, data.len,
3041 0, 0)));
3042 data_string_forget (&data, MDL);
3043 }
3044 }
3045 }
3046}
3047
02d9e453
TL
3048void script_write_params (client, prefix, lease)
3049 struct client_state *client;
b1b7b521 3050 const char *prefix;
cc26de46
TL
3051 struct client_lease *lease;
3052{
3053 int i;
02a015fb
TL
3054 struct data_string data;
3055 struct option_cache *oc;
c0504523
TL
3056 struct envadd_state es;
3057
3058 es.client = client;
3059 es.prefix = prefix;
cc26de46 3060
32a47563
TL
3061 client_envadd (client,
3062 prefix, "ip_address", "%s", piaddr (lease -> address));
c6abd205
TL
3063
3064 /* For the benefit of Linux (and operating systems which may
3065 have similar needs), compute the network address based on
3066 the supplied ip address and netmask, if provided. Also
3067 compute the broadcast address (the host address all ones
3068 broadcast address, not the host address all zeroes
3069 broadcast address). */
3070
02a015fb 3071 memset (&data, 0, sizeof data);
230e73e4 3072 oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
66e9cecf
TL
3073 if (oc && evaluate_option_cache (&data, (struct packet *)0,
3074 (struct lease *)0, client,
0852a27f 3075 (struct option_state *)0,
da38df14 3076 lease -> options,
cf78bf20 3077 &global_scope, oc, MDL)) {
02a015fb
TL
3078 if (data.len > 3) {
3079 struct iaddr netmask, subnet, broadcast;
3080
8a4e543b
DH
3081 /*
3082 * No matter the length of the subnet-mask option,
3083 * use only the first four octets. Note that
3084 * subnet-mask options longer than 4 octets are not
3085 * in conformance with RFC 2132, but servers with this
3086 * flaw do exist.
3087 */
3088 memcpy(netmask.iabuf, data.data, 4);
3089 netmask.len = 4;
cf78bf20 3090 data_string_forget (&data, MDL);
02a015fb
TL
3091
3092 subnet = subnet_number (lease -> address, netmask);
3093 if (subnet.len) {
32a47563
TL
3094 client_envadd (client, prefix, "network_number",
3095 "%s", piaddr (subnet));
3096
3097 oc = lookup_option (&dhcp_universe,
3098 lease -> options,
3099 DHO_BROADCAST_ADDRESS);
3100 if (!oc ||
3101 !(evaluate_option_cache
3102 (&data, (struct packet *)0,
66e9cecf 3103 (struct lease *)0, client,
32a47563
TL
3104 (struct option_state *)0,
3105 lease -> options,
3106 &global_scope, oc, MDL))) {
3107 broadcast = broadcast_addr (subnet, netmask);
3108 if (broadcast.len) {
3109 client_envadd (client,
3110 prefix, "broadcast_address",
a8c190df 3111 "%s", piaddr (broadcast));
c6abd205 3112 }
32a47563 3113 }
c6abd205
TL
3114 }
3115 }
cf78bf20 3116 data_string_forget (&data, MDL);
c6abd205
TL
3117 }
3118
32a47563
TL
3119 if (lease -> filename)
3120 client_envadd (client,
3121 prefix, "filename", "%s", lease -> filename);
3122 if (lease -> server_name)
3123 client_envadd (client, prefix, "server_name",
3124 "%s", lease -> server_name);
02a015fb 3125
c0504523
TL
3126 for (i = 0; i < lease -> options -> universe_count; i++) {
3127 option_space_foreach ((struct packet *)0, (struct lease *)0,
66e9cecf 3128 client, (struct option_state *)0,
c0504523
TL
3129 lease -> options, &global_scope,
3130 universes [i],
3131 &es, client_option_envadd);
cc26de46 3132 }
32a47563 3133 client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
cc26de46
TL
3134}
3135
02d9e453
TL
3136int script_go (client)
3137 struct client_state *client;
cc26de46 3138{
32a47563
TL
3139 char *scriptName;
3140 char *argv [2];
3141 char **envp;
32a47563
TL
3142 char reason [] = "REASON=NBI";
3143 static char client_path [] = CLIENT_PATH;
3144 int i;
3145 struct string_list *sp, *next;
3146 int pid, wpid, wstatus;
cc26de46 3147
b1423aed 3148 if (client)
32a47563 3149 scriptName = client -> config -> script_name;
b1423aed
TL
3150 else
3151 scriptName = top_level_config.script_name;
3152
3153 envp = dmalloc (((client ? client -> envc : 2) +
3154 client_env_count + 2) * sizeof (char *), MDL);
3155 if (!envp) {
3156 log_error ("No memory for client script environment.");
3157 return 0;
3158 }
3159 i = 0;
3160 /* Copy out the environment specified on the command line,
3161 if any. */
3162 for (sp = client_env; sp; sp = sp -> next) {
3163 envp [i++] = sp -> string;
3164 }
3165 /* Copy out the environment specified by dhclient. */
3166 if (client) {
32a47563
TL
3167 for (sp = client -> env; sp; sp = sp -> next) {
3168 envp [i++] = sp -> string;
3169 }
32a47563 3170 } else {
b1423aed 3171 envp [i++] = reason;
32a47563 3172 }
b1423aed
TL
3173 /* Set $PATH. */
3174 envp [i++] = client_path;
3175 envp [i] = (char *)0;
32a47563
TL
3176
3177 argv [0] = scriptName;
3178 argv [1] = (char *)0;
3179
3180 pid = fork ();
3181 if (pid < 0) {
3182 log_error ("fork: %m");
3183 wstatus = 0;
3184 } else if (pid) {
3185 do {
3186 wpid = wait (&wstatus);
3187 } while (wpid != pid && wpid > 0);
3188 if (wpid < 0) {
3189 log_error ("wait: %m");
3190 wstatus = 0;
3191 }
3192 } else {
4d97a043
DH
3193 /* We don't want to pass an open file descriptor for
3194 * dhclient.leases when executing dhclient-script.
3195 */
3196 if (leaseFile != NULL)
3197 fclose(leaseFile);
32a47563
TL
3198 execve (scriptName, argv, envp);
3199 log_error ("execve (%s, ...): %m", scriptName);
3200 exit (0);
3201 }
3202
3203 if (client) {
3204 for (sp = client -> env; sp; sp = next) {
3205 next = sp -> next;
3206 dfree (sp, MDL);
3207 }
3208 client -> env = (struct string_list *)0;
3209 client -> envc = 0;
32a47563 3210 }
b1423aed 3211 dfree (envp, MDL);
be62cf06 3212 gettimeofday(&cur_tv, NULL);
ed0f73ab
TL
3213 return (WIFEXITED (wstatus) ?
3214 WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
32a47563
TL
3215}
3216
3217void client_envadd (struct client_state *client,
3218 const char *prefix, const char *name, const char *fmt, ...)
3219{
3220 char spbuf [1024];
3221 char *s;
28868515 3222 unsigned len;
32a47563
TL
3223 struct string_list *val;
3224 va_list list;
3225
3226 va_start (list, fmt);
3227 len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
3228 va_end (list);
3229
3230 val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
3231 len + sizeof *val, MDL);
3232 if (!val)
3233 return;
3234 s = val -> string;
3235 strcpy (s, prefix);
3236 strcat (s, name);
3237 s += strlen (s);
3238 *s++ = '=';
3239 if (len >= sizeof spbuf) {
3240 va_start (list, fmt);
3241 vsnprintf (s, len + 1, fmt, list);
3242 va_end (list);
3243 } else
3244 strcpy (s, spbuf);
3245 val -> next = client -> env;
3246 client -> env = val;
3247 client -> envc++;
cc26de46
TL
3248}
3249
32a47563
TL
3250int dhcp_option_ev_name (buf, buflen, option)
3251 char *buf;
6ceb9118 3252 size_t buflen;
cc26de46
TL
3253 struct option *option;
3254{
c0504523
TL
3255 int i, j;
3256 const char *s;
cc26de46 3257
c0504523
TL
3258 j = 0;
3259 if (option -> universe != &dhcp_universe) {
3260 s = option -> universe -> name;
3261 i = 0;
3dbe2246 3262 } else {
c0504523
TL
3263 s = option -> name;
3264 i = 1;
cc26de46
TL
3265 }
3266
c0504523
TL
3267 do {
3268 while (*s) {
3269 if (j + 1 == buflen)
3270 return 0;
3271 if (*s == '-')
3272 buf [j++] = '_';
3273 else
3274 buf [j++] = *s;
3275 ++s;
3276 }
3277 if (!i) {
3278 s = option -> name;
3279 if (j + 1 == buflen)
3280 return 0;
3281 buf [j++] = '_';
3282 }
3283 ++i;
3284 } while (i != 2);
3285
3286 buf [j] = 0;
32a47563 3287 return 1;
cc26de46 3288}
b00d3884
TL
3289
3290void go_daemon ()
3291{
3292 static int state = 0;
3293 int pid;
3294
3295 /* Don't become a daemon if the user requested otherwise. */
b8cf055d
TL
3296 if (no_daemon) {
3297 write_client_pid_file ();
b00d3884 3298 return;
b8cf055d 3299 }
b00d3884
TL
3300
3301 /* Only do it once. */
3302 if (state)
3303 return;
3304 state = 1;
3305
3306 /* Stop logging to stderr... */
3307 log_perror = 0;
3308
3309 /* Become a daemon... */
3310 if ((pid = fork ()) < 0)
8ae2d595 3311 log_fatal ("Can't fork daemon: %m");
b00d3884
TL
3312 else if (pid)
3313 exit (0);
3314 /* Become session leader and get pid... */
3315 pid = setsid ();
b8cf055d 3316
62d0cb47 3317 /* Close standard I/O descriptors. */
3dbe2246
FD
3318 close(0);
3319 close(1);
3320 close(2);
62d0cb47 3321
a609e69b 3322 /* Reopen them on /dev/null. */
509df655
SK
3323 open("/dev/null", O_RDWR);
3324 open("/dev/null", O_RDWR);
3325 open("/dev/null", O_RDWR);
a609e69b 3326
b8cf055d 3327 write_client_pid_file ();
a546f2a7 3328
ae566556 3329 IGNORE_RET (chdir("/"));
b8cf055d
TL
3330}
3331
3332void write_client_pid_file ()
3333{
3334 FILE *pf;
3335 int pfdesc;
3336
3337 pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
3338
3339 if (pfdesc < 0) {
8ae2d595 3340 log_error ("Can't create %s: %m", path_dhclient_pid);
b8cf055d
TL
3341 return;
3342 }
3343
3344 pf = fdopen (pfdesc, "w");
3345 if (!pf)
8ae2d595 3346 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
b8cf055d 3347 else {
19ea90f7 3348 fprintf (pf, "%ld\n", (long)getpid ());
b8cf055d
TL
3349 fclose (pf);
3350 }
3351}
3352
b8cf055d
TL
3353void client_location_changed ()
3354{
3355 struct interface_info *ip;
02d9e453 3356 struct client_state *client;
b8cf055d
TL
3357
3358 for (ip = interfaces; ip; ip = ip -> next) {
02d9e453
TL
3359 for (client = ip -> client; client; client = client -> next) {
3360 switch (client -> state) {
3361 case S_SELECTING:
3362 cancel_timeout (send_discover, client);
3363 break;
b8cf055d 3364
02d9e453
TL
3365 case S_BOUND:
3366 cancel_timeout (state_bound, client);
3367 break;
b8cf055d 3368
02d9e453
TL
3369 case S_REBOOTING:
3370 case S_REQUESTING:
3371 case S_RENEWING:
3372 cancel_timeout (send_request, client);
3373 break;
b8cf055d 3374
02d9e453
TL
3375 case S_INIT:
3376 case S_REBINDING:
57710b89 3377 case S_STOPPED:
02d9e453
TL
3378 break;
3379 }
3380 client -> state = S_INIT;
3381 state_reboot (client);
b8cf055d 3382 }
b8cf055d
TL
3383 }
3384}
6767b592 3385
3dbe2246 3386void do_release(client)
347de8bd
TL
3387 struct client_state *client;
3388{
007e3ee4
TL
3389 struct data_string ds;
3390 struct option_cache *oc;
3391
57710b89 3392 /* Pick a random xid. */
347de8bd
TL
3393 client -> xid = random ();
3394
bdcaf7b9
TL
3395 /* is there even a lease to release? */
3396 if (client -> active) {
3397 /* Make a DHCPRELEASE packet, and set appropriate per-interface
3398 flags. */
3399 make_release (client, client -> active);
007e3ee4
TL
3400
3401 memset (&ds, 0, sizeof ds);
3402 oc = lookup_option (&dhcp_universe,
3403 client -> active -> options,
3404 DHO_DHCP_SERVER_IDENTIFIER);
3405 if (oc &&
3406 evaluate_option_cache (&ds, (struct packet *)0,
66e9cecf 3407 (struct lease *)0, client,
007e3ee4
TL
3408 (struct option_state *)0,
3409 client -> active -> options,
3410 &global_scope, oc, MDL)) {
3411 if (ds.len > 3) {
3412 memcpy (client -> destination.iabuf,
3413 ds.data, 4);
3414 client -> destination.len = 4;
3415 } else
3416 client -> destination = iaddr_broadcast;
98311e4b
DH
3417
3418 data_string_forget (&ds, MDL);
007e3ee4
TL
3419 } else
3420 client -> destination = iaddr_broadcast;
bdcaf7b9
TL
3421 client -> first_sending = cur_time;
3422 client -> interval = client -> config -> initial_interval;
3dbe2246 3423
bdcaf7b9
TL
3424 /* Zap the medium list... */
3425 client -> medium = (struct string_list *)0;
3dbe2246 3426
bdcaf7b9
TL
3427 /* Send out the first and only DHCPRELEASE packet. */
3428 send_release (client);
347de8bd 3429
007e3ee4 3430 /* Do the client script RELEASE operation. */
bdcaf7b9
TL
3431 script_init (client,
3432 "RELEASE", (struct string_list *)0);
3433 if (client -> alias)
3434 script_write_params (client, "alias_",
3435 client -> alias);
d758ad8c 3436 script_write_params (client, "old_", client -> active);
bdcaf7b9
TL
3437 script_go (client);
3438 }
007e3ee4 3439
57710b89
TL
3440 /* Cancel any timeouts. */
3441 cancel_timeout (state_bound, client);
3442 cancel_timeout (send_discover, client);
3443 cancel_timeout (state_init, client);
3444 cancel_timeout (send_request, client);
3445 cancel_timeout (state_reboot, client);
3446 client -> state = S_STOPPED;
347de8bd
TL
3447}
3448
20916cae
TL
3449int dhclient_interface_shutdown_hook (struct interface_info *interface)
3450{
3451 do_release (interface -> client);
57710b89 3452
20916cae
TL
3453 return 1;
3454}
347de8bd 3455
20916cae
TL
3456int dhclient_interface_discovery_hook (struct interface_info *tmp)
3457{
3458 struct interface_info *last, *ip;
3459 /* See if we can find the client from dummy_interfaces */
3460 last = 0;
3461 for (ip = dummy_interfaces; ip; ip = ip -> next) {
3462 if (!strcmp (ip -> name, tmp -> name)) {
3463 /* Remove from dummy_interfaces */
3464 if (last) {
3465 ip = (struct interface_info *)0;
3466 interface_reference (&ip, last -> next, MDL);
3467 interface_dereference (&last -> next, MDL);
3468 if (ip -> next) {
3469 interface_reference (&last -> next,
3470 ip -> next, MDL);
3471 interface_dereference (&ip -> next,
3472 MDL);
3473 }
3474 } else {
3475 ip = (struct interface_info *)0;
3476 interface_reference (&ip,
3477 dummy_interfaces, MDL);
3478 interface_dereference (&dummy_interfaces, MDL);
3479 if (ip -> next) {
3480 interface_reference (&dummy_interfaces,
3481 ip -> next, MDL);
3482 interface_dereference (&ip -> next,
3483 MDL);
3484 }
3485 }
3486 /* Copy "client" to tmp */
3487 if (ip -> client) {
3488 tmp -> client = ip -> client;
3489 tmp -> client -> interface = tmp;
3490 }
3491 interface_dereference (&ip, MDL);
3492 break;
3493 }
3494 last = ip;
3495 }
3496 return 1;
3497}
347de8bd 3498
57710b89
TL
3499isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
3500{
3501 struct interface_info *ip;
3502 struct client_state *client;
be62cf06 3503 struct timeval tv;
57710b89
TL
3504
3505 /* This code needs some rethinking. It doesn't test against
3506 a signal name, and it just kind of bulls into doing something
3507 that may or may not be appropriate. */
3508
3509 if (interfaces) {
3510 interface_reference (&interface -> next, interfaces, MDL);
3511 interface_dereference (&interfaces, MDL);
3512 }
3513 interface_reference (&interfaces, interface, MDL);
3514
3515 discover_interfaces (DISCOVER_UNCONFIGURED);
3516
3517 for (ip = interfaces; ip; ip = ip -> next) {
3518 /* If interfaces were specified, don't configure
3519 interfaces that weren't specified! */
3520 if (ip -> flags & INTERFACE_RUNNING ||
3521 (ip -> flags & (INTERFACE_REQUESTED |
3522 INTERFACE_AUTOMATIC)) !=
3523 INTERFACE_REQUESTED)
3524 continue;
3525 script_init (ip -> client,
3526 "PREINIT", (struct string_list *)0);
3527 if (ip -> client -> alias)
3528 script_write_params (ip -> client, "alias_",
3529 ip -> client -> alias);
3530 script_go (ip -> client);
3531 }
3dbe2246
FD
3532
3533 discover_interfaces (interfaces_requested != 0
57710b89
TL
3534 ? DISCOVER_REQUESTED
3535 : DISCOVER_RUNNING);
3536
3537 for (ip = interfaces; ip; ip = ip -> next) {
3538 if (ip -> flags & INTERFACE_RUNNING)
3539 continue;
3540 ip -> flags |= INTERFACE_RUNNING;
3541 for (client = ip -> client; client; client = client -> next) {
3542 client -> state = S_INIT;
3543 /* Set up a timeout to start the initialization
3544 process. */
be62cf06
FD
3545 tv . tv_sec = cur_time + random () % 5;
3546 tv . tv_usec = 0;
3547 add_timeout (&tv, state_reboot, client, 0, 0);
57710b89
TL
3548 }
3549 }
3550 return ISC_R_SUCCESS;
3551}
3552
6767b592
TL
3553/* The client should never receive a relay agent information option,
3554 so if it does, log it and discard it. */
3555
3556int parse_agent_information_option (packet, len, data)
3557 struct packet *packet;
3558 int len;
3559 u_int8_t *data;
3560{
6767b592
TL
3561 return 1;
3562}
3563
3564/* The client never sends relay agent information options. */
3565
3566unsigned cons_agent_information_options (cfg_options, outpacket,
3567 agentix, length)
3568 struct option_state *cfg_options;
3569 struct dhcp_packet *outpacket;
3570 unsigned agentix;
3571 unsigned length;
3572{
3573 return length;
3574}
d758ad8c
TL
3575
3576static void shutdown_exit (void *foo)
3577{
3578 exit (0);
3579}
3580
98bf1607
SR
3581#if defined (NSUPDATE)
3582/*
3583 * If the first query fails, the updater MUST NOT delete the DNS name. It
3584 * may be that the host whose lease on the server has expired has moved
3585 * to another network and obtained a lease from a different server,
3586 * which has caused the client's A RR to be replaced. It may also be
3587 * that some other client has been configured with a name that matches
3588 * the name of the DHCP client, and the policy was that the last client
3589 * to specify the name would get the name. In this case, the DHCID RR
3590 * will no longer match the updater's notion of the client-identity of
3591 * the host pointed to by the DNS name.
3592 * -- "Interaction between DHCP and DNS"
3593 */
3594
3595/* The first and second stages are pretty similar so we combine them */
3596void
3597client_dns_remove_action(dhcp_ddns_cb_t *ddns_cb,
3598 isc_result_t eresult)
3599{
3600
3601 isc_result_t result;
3602
3603 if ((eresult == ISC_R_SUCCESS) &&
3604 (ddns_cb->state == DDNS_STATE_REM_FW_YXDHCID)) {
3605 /* Do the second stage of the FWD removal */
3606 ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
3607
3608 result = ddns_modify_fwd(ddns_cb);
3609 if (result == ISC_R_SUCCESS) {
3610 return;
3611 }
3612 }
3613
3614 /* If we are done or have an error clean up */
3615 ddns_cb_free(ddns_cb, MDL);
3616 return;
3617}
3618
3619void
3620client_dns_remove(struct client_state *client,
3621 struct iaddr *addr)
3622{
3623 dhcp_ddns_cb_t *ddns_cb;
3624 isc_result_t result;
3625
3626 /* if we have an old ddns request for this client, cancel it */
3627 if (client->ddns_cb != NULL) {
3628 ddns_cancel(client->ddns_cb);
3629 client->ddns_cb = NULL;
3630 }
3631
3632 ddns_cb = ddns_cb_alloc(MDL);
3633 if (ddns_cb != NULL) {
3634 ddns_cb->address = *addr;
3635 ddns_cb->timeout = 0;
3636
3637 ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
3638 ddns_cb->flags = DDNS_UPDATE_ADDR;
3639 ddns_cb->cur_func = client_dns_remove_action;
3640
3641 result = client_dns_update(client, ddns_cb);
3642
3643 if (result != ISC_R_TIMEDOUT) {
3644 ddns_cb_free(ddns_cb, MDL);
3645 }
3646 }
3647}
3648#endif
3649
d758ad8c
TL
3650isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
3651 control_object_state_t newstate)
3652{
3653 struct interface_info *ip;
3654 struct client_state *client;
be62cf06 3655 struct timeval tv;
d758ad8c
TL
3656
3657 /* Do the right thing for each interface. */
3658 for (ip = interfaces; ip; ip = ip -> next) {
3659 for (client = ip -> client; client; client = client -> next) {
3660 switch (newstate) {
3661 case server_startup:
3662 return ISC_R_SUCCESS;
3663
3664 case server_running:
3665 return ISC_R_SUCCESS;
3666
3667 case server_shutdown:
3668 if (client -> active &&
3669 client -> active -> expiry > cur_time) {
98bf1607
SR
3670#if defined (NSUPDATE)
3671 if (client->config->do_forward_update) {
3672 client_dns_remove(client,
3673 &client->active->address);
3674 }
3675#endif
d758ad8c
TL
3676 do_release (client);
3677 }
3678 break;
3679
3680 case server_hibernate:
3681 state_stop (client);
3682 break;
3683
3684 case server_awaken:
3685 state_reboot (client);
3686 break;
3687 }
3688 }
3689 }
af5fa176 3690
be62cf06
FD
3691 if (newstate == server_shutdown) {
3692 tv . tv_sec = cur_tv . tv_sec + 1;
3693 tv . tv_usec = cur_tv . tv_usec;
3694 add_timeout (&tv, shutdown_exit, 0, 0, 0);
3695 }
d758ad8c
TL
3696 return ISC_R_SUCCESS;
3697}
3698
98bf1607
SR
3699#if defined (NSUPDATE)
3700/*
3701 * Called after a timeout if the DNS update failed on the previous try.
3702 * Starts the retry process. If the retry times out it will schedule
3703 * this routine to run again after a 10x wait.
98bd7ca0
DH
3704 */
3705void
98bf1607 3706client_dns_update_timeout (void *cp)
98bd7ca0 3707{
98bf1607
SR
3708 dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)cp;
3709 struct client_state *client = (struct client_state *)ddns_cb->lease;
3710 isc_result_t status = ISC_R_FAILURE;
98bd7ca0 3711
98bf1607
SR
3712 if ((client != NULL) &&
3713 ((client->active != NULL) ||
3714 (client->active_lease != NULL)))
3715 status = client_dns_update(client, ddns_cb);
98bd7ca0 3716
98bf1607
SR
3717 /*
3718 * A status of timedout indicates that we started the update and
3719 * have released control of the control block. Any other status
3720 * indicates that we should clean up the control block. We either
3721 * got a success which indicates that we didn't really need to
3722 * send an update or some other error in which case we weren't able
3723 * to start the update process. In both cases we still own
3724 * the control block and should free it.
3725 */
3726 if (status != ISC_R_TIMEDOUT) {
3727 if (client != NULL) {
3728 client->ddns_cb = NULL;
3729 }
3730 ddns_cb_free(ddns_cb, MDL);
98bd7ca0
DH
3731 }
3732}
3733
98bf1607
SR
3734/*
3735 * If the first query succeeds, the updater can conclude that it
3736 * has added a new name whose only RRs are the A and DHCID RR records.
3737 * The A RR update is now complete (and a client updater is finished,
3738 * while a server might proceed to perform a PTR RR update).
3739 * -- "Interaction between DHCP and DNS"
3740 *
3741 * If the second query succeeds, the updater can conclude that the current
3742 * client was the last client associated with the domain name, and that
3743 * the name now contains the updated A RR. The A RR update is now
3744 * complete (and a client updater is finished, while a server would
3745 * then proceed to perform a PTR RR update).
3746 * -- "Interaction between DHCP and DNS"
3747 *
3748 * If the second query fails with NXRRSET, the updater must conclude
3749 * that the client's desired name is in use by another host. At this
3750 * juncture, the updater can decide (based on some administrative
3751 * configuration outside of the scope of this document) whether to let
3752 * the existing owner of the name keep that name, and to (possibly)
3753 * perform some name disambiguation operation on behalf of the current
3754 * client, or to replace the RRs on the name with RRs that represent
3755 * the current client. If the configured policy allows replacement of
3756 * existing records, the updater submits a query that deletes the
3757 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
3758 * represent the IP address and client-identity of the new client.
3759 * -- "Interaction between DHCP and DNS"
3760 */
98311e4b 3761
98bf1607
SR
3762/* The first and second stages are pretty similar so we combine them */
3763void
3764client_dns_update_action(dhcp_ddns_cb_t *ddns_cb,
3765 isc_result_t eresult)
98311e4b 3766{
98bf1607 3767 isc_result_t result;
be62cf06 3768 struct timeval tv;
98311e4b 3769
98bf1607
SR
3770 switch(eresult) {
3771 case ISC_R_SUCCESS:
3772 default:
3773 /* Either we succeeded or broke in a bad way, clean up */
3774 break;
3775
3776 case DNS_R_YXRRSET:
3777 /*
3778 * This is the only difference between the two stages,
3779 * check to see if it is the first stage, in which case
3780 * start the second stage
3781 */
3782 if (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) {
3783 ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
3784 ddns_cb->cur_func = client_dns_update_action;
3785
3786 result = ddns_modify_fwd(ddns_cb);
3787 if (result == ISC_R_SUCCESS) {
3788 return;
3789 }
3790 }
3791 break;
3792
3793 case ISC_R_TIMEDOUT:
3794 /*
3795 * We got a timeout response from the DNS module. Schedule
3796 * another attempt for later. We forget the name, dhcid and
3797 * zone so if it gets changed we will get the new information.
3798 */
3799 data_string_forget(&ddns_cb->fwd_name, MDL);
3800 data_string_forget(&ddns_cb->dhcid, MDL);
3801 if (ddns_cb->zone != NULL) {
3802 forget_zone((struct dns_zone **)&ddns_cb->zone);
3803 }
3804
3805 /* Reset to doing the first stage */
3806 ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
3807 ddns_cb->cur_func = client_dns_update_action;
3808
3809 /* and update our timer */
3810 if (ddns_cb->timeout < 3600)
3811 ddns_cb->timeout *= 10;
3812 tv.tv_sec = cur_time + ddns_cb->timeout;
be62cf06
FD
3813 tv.tv_usec = 0;
3814 add_timeout(&tv, client_dns_update_timeout,
98bf1607
SR
3815 ddns_cb, NULL, NULL);
3816 return;
3817 }
3818
3819 ddns_cb_free(ddns_cb, MDL);
3820 return;
98311e4b
DH
3821}
3822
d758ad8c
TL
3823/* See if we should do a DNS update, and if so, do it. */
3824
98bf1607
SR
3825isc_result_t
3826client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
d758ad8c 3827{
98bf1607 3828 struct data_string client_identifier;
d758ad8c
TL
3829 struct option_cache *oc;
3830 int ignorep;
3831 int result;
3832 isc_result_t rcode;
3833
3834 /* If we didn't send an FQDN option, we certainly aren't going to
3835 be doing an update. */
3836 if (!client -> sent_options)
98311e4b 3837 return ISC_R_SUCCESS;
d758ad8c
TL
3838
3839 /* If we don't have a lease, we can't do an update. */
98bd7ca0 3840 if ((client->active == NULL) && (client->active_lease == NULL))
98311e4b 3841 return ISC_R_SUCCESS;
d758ad8c
TL
3842
3843 /* If we set the no client update flag, don't do the update. */
3844 if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
3845 FQDN_NO_CLIENT_UPDATE)) &&
3846 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3847 (struct lease *)0, client,
3848 client -> sent_options,
3849 (struct option_state *)0,
3850 &global_scope, oc, MDL))
98311e4b 3851 return ISC_R_SUCCESS;
3dbe2246 3852
d758ad8c
TL
3853 /* If we set the "server, please update" flag, or didn't set it
3854 to false, don't do the update. */
3855 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3856 FQDN_SERVER_UPDATE)) ||
3857 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
3858 (struct lease *)0, client,
3859 client -> sent_options,
3860 (struct option_state *)0,
3861 &global_scope, oc, MDL))
98311e4b 3862 return ISC_R_SUCCESS;
3dbe2246 3863
d758ad8c 3864 /* If no FQDN option was supplied, don't do the update. */
d758ad8c
TL
3865 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
3866 FQDN_FQDN)) ||
98bf1607 3867 !evaluate_option_cache (&ddns_cb->fwd_name, (struct packet *)0,
d758ad8c
TL
3868 (struct lease *)0, client,
3869 client -> sent_options,
3870 (struct option_state *)0,
3871 &global_scope, oc, MDL))
98311e4b 3872 return ISC_R_SUCCESS;
d758ad8c 3873
98bd7ca0
DH
3874 /* If this is a DHCPv6 client update, make a dhcid string out of
3875 * the DUID. If this is a DHCPv4 client update, choose either
3876 * the client identifier, if there is one, or the interface's
3877 * MAC address.
3878 */
6705543f 3879 result = 0;
98bd7ca0
DH
3880 memset(&client_identifier, 0, sizeof(client_identifier));
3881 if (client->active_lease != NULL) {
3882 if (((oc =
3883 lookup_option(&dhcpv6_universe, client->sent_options,
3884 D6O_CLIENTID)) != NULL) &&
3885 evaluate_option_cache(&client_identifier, NULL, NULL,
3886 client, client->sent_options, NULL,
3887 &global_scope, oc, MDL)) {
3888 /* RFC4701 defines type '2' as being for the DUID
3889 * field. We aren't using RFC4701 DHCID RR's yet,
3890 * but this is as good a value as any.
3891 */
98bf1607 3892 result = get_dhcid(&ddns_cb->dhcid, 2,
98bd7ca0
DH
3893 client_identifier.data,
3894 client_identifier.len);
3895 data_string_forget(&client_identifier, MDL);
3896 } else
3897 log_fatal("Impossible condition at %s:%d.", MDL);
3898 } else {
3899 if (((oc =
3900 lookup_option(&dhcp_universe, client->sent_options,
3901 DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
3902 evaluate_option_cache(&client_identifier, NULL, NULL,
3903 client, client->sent_options, NULL,
3904 &global_scope, oc, MDL)) {
98bf1607 3905 result = get_dhcid(&ddns_cb->dhcid,
98bd7ca0
DH
3906 DHO_DHCP_CLIENT_IDENTIFIER,
3907 client_identifier.data,
3908 client_identifier.len);
3909 data_string_forget(&client_identifier, MDL);
3910 } else
98bf1607 3911 result = get_dhcid(&ddns_cb->dhcid, 0,
98bd7ca0
DH
3912 client->interface->hw_address.hbuf,
3913 client->interface->hw_address.hlen);
3914 }
d758ad8c 3915 if (!result) {
98311e4b 3916 return ISC_R_SUCCESS;
d758ad8c
TL
3917 }
3918
d758ad8c
TL
3919 /*
3920 * Perform updates.
3921 */
98bf1607
SR
3922 if (ddns_cb->fwd_name.len && ddns_cb->dhcid.len) {
3923 rcode = ddns_modify_fwd(ddns_cb);
98311e4b
DH
3924 } else
3925 rcode = ISC_R_FAILURE;
3dbe2246 3926
98bf1607
SR
3927 /*
3928 * A success from the modify routine means we are performing
3929 * async processing, for which we use the timedout error message.
3930 */
3931 if (rcode == ISC_R_SUCCESS) {
3932 rcode = ISC_R_TIMEDOUT;
3933 }
3934
98311e4b 3935 return rcode;
d758ad8c 3936}
98bd7ca0 3937
98bf1607
SR
3938
3939/*
3940 * Schedule the first update. They will continue to retry occasionally
3941 * until they no longer time out (or fail).
3942 */
3943void
3944dhclient_schedule_updates(struct client_state *client,
3945 struct iaddr *addr,
3946 int offset)
3947{
3948 dhcp_ddns_cb_t *ddns_cb;
3949 struct timeval tv;
3950
3951 if (!client->config->do_forward_update)
3952 return;
3953
3954 /* cancel any outstanding ddns requests */
3955 if (client->ddns_cb != NULL) {
3956 ddns_cancel(client->ddns_cb);
3957 client->ddns_cb = NULL;
3958 }
3959
3960 ddns_cb = ddns_cb_alloc(MDL);
3961
3962 if (ddns_cb != NULL) {
3963 ddns_cb->lease = (void *)client;
3964 ddns_cb->address = *addr;
3965 ddns_cb->timeout = 1;
3966
3967 /*
3968 * XXX: DNS TTL is a problem we need to solve properly.
3969 * Until that time, 300 is a placeholder default for
3970 * something that is less insane than a value scaled
3971 * by lease timeout.
3972 */
3973 ddns_cb->ttl = 300;
3974
3975 ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
3976 ddns_cb->cur_func = client_dns_update_action;
3977 ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_INCLUDE_RRSET;
3978
3979 client->ddns_cb = ddns_cb;
3980
3981 tv.tv_sec = cur_time + offset;
3982 tv.tv_usec = 0;
3983 add_timeout(&tv, client_dns_update_timeout,
3984 ddns_cb, NULL, NULL);
3985 } else {
3986 log_error("Unable to allocate dns update state for %s",
3987 piaddr(*addr));
3988 }
3989}
3990#endif
3991
98bd7ca0
DH
3992void
3993dhcpv4_client_assignments(void)
3994{
3995 struct servent *ent;
3996
3997 if (path_dhclient_pid == NULL)
3998 path_dhclient_pid = _PATH_DHCLIENT_PID;
3999 if (path_dhclient_db == NULL)
4000 path_dhclient_db = _PATH_DHCLIENT_DB;
4001
4002 /* Default to the DHCP/BOOTP port. */
4003 if (!local_port) {
4004 /* If we're faking a relay agent, and we're not using loopback,
4005 use the server port, not the client port. */
4006 if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
4007 local_port = htons(67);
4008 } else {
4009 ent = getservbyname ("dhcpc", "udp");
4010 if (!ent)
4011 local_port = htons (68);
4012 else
4013 local_port = ent -> s_port;
4014#ifndef __CYGWIN32__
4015 endservent ();
4016#endif
4017 }
4018 }
4019
4020 /* If we're faking a relay agent, and we're not using loopback,
4021 we're using the server port, not the client port. */
4022 if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
4023 remote_port = local_port;
4024 } else
4025 remote_port = htons (ntohs (local_port) - 1); /* XXX */
4026}