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