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