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