]> git.ipfire.org Git - thirdparty/dhcp.git/blame - client/dhclient.c
Added cancel timeouts
[thirdparty/dhcp.git] / client / dhclient.c
CommitLineData
469cf3a4 1/* dhclient.c
95821729 2
9bdb9271 3 DHCP Client. */
95821729
TL
4
5/*
109fa1d0 6 * Copyright (c) 2004-2020 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 7 * Copyright (c) 1995-2003 by Internet Software Consortium
95821729 8 *
7512d88b
TM
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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"
e39b4193
TM
34#include <isc/util.h>
35#include <isc/file.h>
36#include <dns/result.h>
fe5b0fdd
DH
37#include <syslog.h>
38#include <signal.h>
39#include <errno.h>
be62cf06 40#include <sys/time.h>
fe5b0fdd 41#include <sys/wait.h>
e847f983 42#include <limits.h>
e581d615 43
4a0d788a
TL
44TIME default_lease_time = 43200; /* 12 hours... */
45TIME max_lease_time = 86400; /* 24 hours... */
46
b1b7b521 47const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
98bd7ca0
DH
48const char *path_dhclient_db = NULL;
49const char *path_dhclient_pid = NULL;
420d8b3f 50static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
c08637bb 51char *path_dhclient_script = path_dhclient_script_array;
79818c93 52const char *path_dhclient_duid = NULL;
cc26de46 53
0cd94b5e
TM
54static void add_to_tail(struct client_lease** lease_list, struct client_lease* lease);
55
4a5bfeac
SR
56/* False (default) => we write and use a pid file */
57isc_boolean_t no_pid_file = ISC_FALSE;
58
36f5cb7c
TL
59int dhcp_max_agent_option_packet_length = 0;
60
b8cf055d
TL
61int interfaces_requested = 0;
62
cc26de46
TL
63struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
64struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
48d68880 65struct in_addr inaddr_any;
cc26de46 66struct sockaddr_in sockaddr_broadcast;
11373fb6 67struct in_addr giaddr;
98bd7ca0 68struct data_string default_duid;
a41d7a25 69int duid_type = 0;
d7d9c0c7
SR
70int duid_v4 = 0;
71int std_dhcid = 0;
469cf3a4 72
3e88222f
TM
73int decline_wait_time = 10; /* Default to 10 secs per, RFC 2131, 3.1.5 */
74
cc26de46
TL
75/* ASSERT_STATE() does nothing now; it used to be
76 assert (state_is == state_shouldbe). */
77#define ASSERT_STATE(state_is, state_shouldbe) {}
469cf3a4 78
eda1d0aa 79#ifndef UNIT_TEST
109fa1d0 80static const char copyright[] = "Copyright 2004-2020 Internet Systems Consortium.";
ae566556
SR
81static const char arr [] = "All rights reserved.";
82static const char message [] = "Internet Systems Consortium DHCP Client";
2c85ac9b 83static const char url [] = "For info, please visit https://www.isc.org/software/dhcp/";
eda1d0aa 84#endif /* UNIT_TEST */
c1503c57 85
6c7e6157
TM
86extern u_int16_t local_port;
87extern u_int16_t remote_port;
88
785c1a51
FD
89#if defined(DHCPv6) && defined(DHCP4o6)
90int dhcp4o6_state = -1; /* -1 = stopped, 0 = polling, 1 = started */
91#endif
420d8b3f 92int no_daemon = 0;
29b23207 93int dfd[2] = { -1, -1 };
420d8b3f
FD
94struct string_list *client_env = NULL;
95int client_env_count = 0;
96int onetry = 0;
97int quiet = 1;
98int nowait = 0;
99int stateless = 0;
100int wanted_ia_na = -1; /* the absolute value is the real one. */
101int wanted_ia_ta = 0;
102int wanted_ia_pd = 0;
c88dfebd
SR
103int require_all_ias = 0; /* If the user requires all of the IAs to
104 be available before accepting a lease
105 0 = no, 1 = requries */
c0e9661e 106#if defined(DHCPv6)
a68ec967 107int dad_wait_time = 0;
c0e9661e
TM
108int prefix_len_hint = 0;
109#endif
110
140612c8 111int address_prefix_len = DHCLIENT_DEFAULT_PREFIX_LEN;
98bd7ca0 112char *mockup_relay = NULL;
c1503c57 113
7acd8753
FD
114char *progname = NULL;
115
785c1a51 116void run_stateless(int exit_mode, u_int16_t port);
3dbe2246 117
98bd7ca0 118static isc_result_t write_duid(struct data_string *duid);
5d082abd 119static void add_reject(struct packet *packet);
98bd7ca0 120
bea17697
SR
121static int check_domain_name(const char *ptr, size_t len, int dots);
122static int check_domain_name_list(const char *ptr, size_t len, int dots);
123static int check_option_values(struct universe *universe, unsigned int opt,
124 const char *ptr, size_t len);
125
1c779d3b 126#if defined(NSUPDATE)
cca6a648 127static void dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb,
128 char* file, int line);
5df5813d
TM
129#endif /* defined NSUPDATE */
130
cca6a648 131
b2cb745b
SR
132/*!
133 *
134 * \brief Print the generic usage message
135 *
136 * If the user has provided an incorrect command line print out
137 * the description of the command line. The arguments provide
138 * a way for the caller to request more specific information about
139 * the error be printed as well. Mostly this will be that some
140 * comamnd doesn't include its argument.
141 *
142 * \param sfmt - The basic string and format for the specific error
143 * \param sarg - Generally the offending argument from the comamnd line.
144 *
145 * \return Nothing
146 */
147
785c1a51
FD
148#if defined(DHCPv6) && defined(DHCP4o6)
149static void dhcp4o6_poll(void *dummy);
150static void dhcp4o6_resume(void);
151static void recv_dhcpv4_response(struct data_string *raw);
152static int send_dhcpv4_query(struct client_state *client, int broadcast);
153
154static void dhcp4o6_stop(void);
155static void forw_dhcpv4_response(struct packet *packet);
156static void forw_dhcpv4_query(struct data_string *raw);
157#endif
158
b2cb745b
SR
159#ifndef UNIT_TEST
160/* These are only used when we call usage() from the main routine
161 * which isn't compiled when building for unit tests
162 */
163static const char use_noarg[] = "No argument for command: %s";
eda1d0aa 164#ifdef DHCPv6
b2cb745b 165static const char use_v6command[] = "Command not used for DHCPv4: %s";
eda1d0aa 166#endif
b2cb745b 167
68dfa910
FD
168#ifdef DHCPv6
169#ifdef DHCP4o6
170#define DHCLIENT_USAGE0 \
3e88222f
TM
171"[-4|-6] [-SNTPRI1dvrxi] [-nw] -4o6 <port>] [-p <port>] [-D LL|LLT]\n" \
172" [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
140612c8 173" [--decline-wait-time <seconds>]\n" \
a804fcc0 174" [--address-prefix-len <length>]\n"
68dfa910
FD
175#else /* DHCP4o6 */
176#define DHCLIENT_USAGE0 \
a68ec967 177"[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT]\n" \
3e88222f 178" [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
140612c8 179" [--decline-wait-time <seconds>]\n" \
a804fcc0 180" [--address-prefix-len <length>]\n"
68dfa910
FD
181#endif
182#else /* DHCPv6 */
183#define DHCLIENT_USAGE0 \
3e88222f
TM
184"[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" \
185" [--decline-wait-time <seconds>]\n"
68dfa910
FD
186#endif
187
188#define DHCLIENT_USAGEC \
189" [-s server-addr] [-cf config-file]\n" \
190" [-df duid-file] [-lf lease-file]\n" \
191" [-pf pid-file] [--no-pid] [-e VAR=val]\n" \
192" [-sf script-file] [interface]*"
193
194#define DHCLIENT_USAGEH "{--version|--help|-h}"
195
b2cb745b
SR
196static void
197usage(const char *sfmt, const char *sarg)
198{
199 log_info("%s %s", message, PACKAGE_VERSION);
200 log_info(copyright);
201 log_info(arr);
202 log_info(url);
203
204 /* If desired print out the specific error message */
205#ifdef PRINT_SPECIFIC_CL_ERRORS
206 if (sfmt != NULL)
207 log_error(sfmt, sarg);
208#endif
209
86bda88b 210 log_fatal("Usage: %s %s%s\n %s %s",
68dfa910
FD
211 isc_file_basename(progname),
212 DHCLIENT_USAGE0,
213 DHCLIENT_USAGEC,
214 isc_file_basename(progname),
215 DHCLIENT_USAGEH);
b2cb745b
SR
216}
217
c0a64ef0
TM
218extern void initialize_client_option_spaces();
219
3dbe2246 220int
98bd7ca0 221main(int argc, char **argv) {
185d16f9 222 int fd;
c1503c57 223 int i;
cc26de46 224 struct interface_info *ip;
02d9e453 225 struct client_state *client;
b1b7b521 226 unsigned seed;
420d8b3f 227 char *server = NULL;
628beb0e 228 isc_result_t status;
3dbe2246
FD
229 int exit_mode = 0;
230 int release_mode = 0;
be62cf06 231 struct timeval tv;
347de8bd
TL
232 omapi_object_t *listener;
233 isc_result_t result;
134ceef8 234 int persist = 0;
cfa7212d
TL
235 int no_dhclient_conf = 0;
236 int no_dhclient_db = 0;
237 int no_dhclient_pid = 0;
c08637bb 238 int no_dhclient_script = 0;
c998be87 239#ifdef DHCPv6
98bd7ca0 240 int local_family_set = 0;
785c1a51
FD
241#ifdef DHCP4o6
242 u_int16_t dhcp4o6_port = 0;
243#endif /* DHCP4o6 */
c998be87 244#endif /* DHCPv6 */
cfa7212d 245 char *s;
6c6d5928 246
7acd8753
FD
247#ifdef OLD_LOG_NAME
248 progname = "dhclient";
249#else
250 progname = argv[0];
251#endif
98bd7ca0
DH
252 /* Initialize client globals. */
253 memset(&default_duid, 0, sizeof(default_duid));
254
3dbe2246
FD
255 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
256 2 (stderr) are open. To do this, we assume that when we
257 open a file the lowest available file descriptor is used. */
258 fd = open("/dev/null", O_RDWR);
259 if (fd == 0)
260 fd = open("/dev/null", O_RDWR);
261 if (fd == 1)
262 fd = open("/dev/null", O_RDWR);
263 if (fd == 2)
264 log_perror = 0; /* No sense logging to /dev/null. */
265 else if (fd != -1)
266 close(fd);
ee8a3653 267
7acd8753 268 openlog(isc_file_basename(progname), DHCP_LOG_OPTIONS, LOG_DAEMON);
95821729 269
420d8b3f
FD
270#if !(defined(DEBUG) || defined(__CYGWIN32__))
271 setlogmask(LOG_UPTO(LOG_INFO));
3dbe2246 272#endif
c1503c57 273
29b23207
FD
274 /* Parse arguments changing no_daemon */
275 for (i = 1; i < argc; i++) {
276 if (!strcmp(argv[i], "-r")) {
277 no_daemon = 1;
278 } else if (!strcmp(argv[i], "-x")) {
279 no_daemon = 0;
280 } else if (!strcmp(argv[i], "-d")) {
281 no_daemon = 1;
282 } else if (!strcmp(argv[i], "--version")) {
283 const char vstring[] = "isc-dhclient-";
284 IGNORE_RET(write(STDERR_FILENO, vstring,
285 strlen(vstring)));
286 IGNORE_RET(write(STDERR_FILENO,
287 PACKAGE_VERSION,
288 strlen(PACKAGE_VERSION)));
289 IGNORE_RET(write(STDERR_FILENO, "\n", 1));
290 exit(0);
68dfa910
FD
291 } else if (!strcmp(argv[i], "--help") ||
292 !strcmp(argv[i], "-h")) {
293 const char *pname = isc_file_basename(progname);
294 IGNORE_RET(write(STDERR_FILENO, "Usage: ", 7));
295 IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
296 IGNORE_RET(write(STDERR_FILENO, " ", 1));
297 IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGE0,
298 strlen(DHCLIENT_USAGE0)));
299 IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGEC,
300 strlen(DHCLIENT_USAGEC)));
301 IGNORE_RET(write(STDERR_FILENO, "\n", 1));
302 IGNORE_RET(write(STDERR_FILENO, " ", 7));
303 IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
304 IGNORE_RET(write(STDERR_FILENO, " ", 1));
305 IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGEH,
306 strlen(DHCLIENT_USAGEH)));
307 IGNORE_RET(write(STDERR_FILENO, "\n", 1));
308 exit(0);
29b23207
FD
309 }
310 }
311 /* When not forbidden prepare to become a daemon */
312 if (!no_daemon) {
313 int pid;
314
315 if (pipe(dfd) == -1)
316 log_fatal("Can't get pipe: %m");
317 if ((pid = fork ()) < 0)
318 log_fatal("Can't fork daemon: %m");
319 if (pid != 0) {
320 /* Parent: wait for the child to start */
321 int n;
322
323 (void) close(dfd[1]);
324 do {
325 char buf;
326
327 n = read(dfd[0], &buf, 1);
328 if (n == 1)
329 _exit((int)buf);
330 } while (n == -1 && errno == EINTR);
331 _exit(1);
332 }
333 /* Child */
334 (void) close(dfd[0]);
335 }
336
98bf1607 337 /* Set up the isc and dns library managers */
ca22af89
TM
338 status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB
339 | DHCP_DNS_CLIENT_LAZY_INIT, NULL, NULL);
98bf1607
SR
340 if (status != ISC_R_SUCCESS)
341 log_fatal("Can't initialize context: %s",
342 isc_result_totext(status));
343
67569fa6 344 /* Set up the OMAPI. */
420d8b3f 345 status = omapi_init();
67569fa6 346 if (status != ISC_R_SUCCESS)
420d8b3f
FD
347 log_fatal("Can't initialize OMAPI: %s",
348 isc_result_totext(status));
67569fa6
TL
349
350 /* Set up the OMAPI wrappers for various server database internal
351 objects. */
420d8b3f 352 dhcp_common_objects_setup();
67569fa6
TL
353
354 dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
355 dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
57710b89 356 dhcp_interface_startup_hook = dhclient_interface_startup_hook;
67569fa6 357
c1503c57 358 for (i = 1; i < argc; i++) {
3dbe2246 359 if (!strcmp(argv[i], "-r")) {
182b187e 360 release_mode = 1;
29b23207 361 /* no_daemon = 1; */
182b187e
EH
362#ifdef DHCPv6
363 } else if (!strcmp(argv[i], "-4")) {
98bd7ca0
DH
364 if (local_family_set && local_family != AF_INET)
365 log_fatal("Client can only do v4 or v6, not "
366 "both.");
367 local_family_set = 1;
368 local_family = AF_INET;
369 } else if (!strcmp(argv[i], "-6")) {
370 if (local_family_set && local_family != AF_INET6)
371 log_fatal("Client can only do v4 or v6, not "
372 "both.");
373 local_family_set = 1;
374 local_family = AF_INET6;
785c1a51
FD
375#ifdef DHCP4o6
376 } else if (!strcmp(argv[i], "-4o6")) {
377 if (++i == argc)
378 usage(use_noarg, argv[i-1]);
379 dhcp4o6_port = validate_port_pair(argv[i]);
380
381 log_debug("DHCPv4 over DHCPv6 over ::1 port %d and %d",
382 ntohs(dhcp4o6_port),
383 ntohs(dhcp4o6_port) + 1);
384 dhcpv4_over_dhcpv6 = 1;
385#endif /* DHCP4o6 */
182b187e 386#endif /* DHCPv6 */
420d8b3f 387 } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
3dbe2246 388 release_mode = 0;
29b23207 389 /* no_daemon = 0; */
3dbe2246 390 exit_mode = 1;
420d8b3f 391 } else if (!strcmp(argv[i], "-p")) {
c1503c57 392 if (++i == argc)
b2cb745b 393 usage(use_noarg, argv[i-1]);
59112e84 394 local_port = validate_port(argv[i]);
420d8b3f
FD
395 log_debug("binding to user-specified port %d",
396 ntohs(local_port));
397 } else if (!strcmp(argv[i], "-d")) {
29b23207 398 /* no_daemon = 1; */
8ea19a71 399 quiet = 0;
420d8b3f 400 } else if (!strcmp(argv[i], "-pf")) {
3dbe2246 401 if (++i == argc)
b2cb745b 402 usage(use_noarg, argv[i-1]);
420d8b3f 403 path_dhclient_pid = argv[i];
cfa7212d 404 no_dhclient_pid = 1;
4a5bfeac
SR
405 } else if (!strcmp(argv[i], "--no-pid")) {
406 no_pid_file = ISC_TRUE;
420d8b3f 407 } else if (!strcmp(argv[i], "-cf")) {
3dbe2246 408 if (++i == argc)
b2cb745b 409 usage(use_noarg, argv[i-1]);
420d8b3f 410 path_dhclient_conf = argv[i];
cfa7212d 411 no_dhclient_conf = 1;
79818c93
SR
412 } else if (!strcmp(argv[i], "-df")) {
413 if (++i == argc)
b2cb745b 414 usage(use_noarg, argv[i-1]);
79818c93 415 path_dhclient_duid = argv[i];
420d8b3f 416 } else if (!strcmp(argv[i], "-lf")) {
3dbe2246 417 if (++i == argc)
b2cb745b 418 usage(use_noarg, argv[i-1]);
420d8b3f 419 path_dhclient_db = argv[i];
cfa7212d 420 no_dhclient_db = 1;
420d8b3f 421 } else if (!strcmp(argv[i], "-sf")) {
c08637bb 422 if (++i == argc)
b2cb745b 423 usage(use_noarg, argv[i-1]);
420d8b3f 424 path_dhclient_script = argv[i];
c08637bb 425 no_dhclient_script = 1;
420d8b3f 426 } else if (!strcmp(argv[i], "-1")) {
c08637bb 427 onetry = 1;
420d8b3f 428 } else if (!strcmp(argv[i], "-q")) {
62d0cb47 429 quiet = 1;
420d8b3f 430 } else if (!strcmp(argv[i], "-s")) {
3020a2c1 431 if (++i == argc)
b2cb745b 432 usage(use_noarg, argv[i-1]);
420d8b3f
FD
433 server = argv[i];
434 } else if (!strcmp(argv[i], "-g")) {
11373fb6 435 if (++i == argc)
b2cb745b 436 usage(use_noarg, argv[i-1]);
420d8b3f
FD
437 mockup_relay = argv[i];
438 } else if (!strcmp(argv[i], "-nw")) {
98311e4b 439 nowait = 1;
420d8b3f 440 } else if (!strcmp(argv[i], "-n")) {
347de8bd 441 /* do not start up any interfaces */
3dbe2246 442 interfaces_requested = -1;
420d8b3f 443 } else if (!strcmp(argv[i], "-w")) {
134ceef8
TL
444 /* do not exit if there are no broadcast interfaces. */
445 persist = 1;
420d8b3f 446 } else if (!strcmp(argv[i], "-e")) {
b1423aed
TL
447 struct string_list *tmp;
448 if (++i == argc)
b2cb745b 449 usage(use_noarg, argv[i-1]);
420d8b3f 450 tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
b1423aed 451 if (!tmp)
420d8b3f
FD
452 log_fatal("No memory for %s", argv[i]);
453 strcpy(tmp->string, argv[i]);
454 tmp->next = client_env;
b1423aed
TL
455 client_env = tmp;
456 client_env_count++;
420d8b3f 457#ifdef DHCPv6
3dbe2246
FD
458 } else if (!strcmp(argv[i], "-S")) {
459 if (local_family_set && (local_family == AF_INET)) {
b2cb745b 460 usage(use_v6command, argv[i]);
3dbe2246
FD
461 }
462 local_family_set = 1;
463 local_family = AF_INET6;
420d8b3f 464 wanted_ia_na = 0;
3dbe2246 465 stateless = 1;
420d8b3f
FD
466 } else if (!strcmp(argv[i], "-N")) {
467 if (local_family_set && (local_family == AF_INET)) {
b2cb745b 468 usage(use_v6command, argv[i]);
420d8b3f
FD
469 }
470 local_family_set = 1;
471 local_family = AF_INET6;
472 if (wanted_ia_na < 0) {
473 wanted_ia_na = 0;
474 }
475 wanted_ia_na++;
476 } else if (!strcmp(argv[i], "-T")) {
477 if (local_family_set && (local_family == AF_INET)) {
b2cb745b 478 usage(use_v6command, argv[i]);
420d8b3f
FD
479 }
480 local_family_set = 1;
481 local_family = AF_INET6;
482 if (wanted_ia_na < 0) {
483 wanted_ia_na = 0;
484 }
485 wanted_ia_ta++;
486 } else if (!strcmp(argv[i], "-P")) {
487 if (local_family_set && (local_family == AF_INET)) {
b2cb745b 488 usage(use_v6command, argv[i]);
420d8b3f
FD
489 }
490 local_family_set = 1;
491 local_family = AF_INET6;
492 if (wanted_ia_na < 0) {
493 wanted_ia_na = 0;
494 }
495 wanted_ia_pd++;
c88dfebd
SR
496 } else if (!strcmp(argv[i], "-R")) {
497 if (local_family_set && (local_family == AF_INET)) {
b2cb745b 498 usage(use_v6command, argv[i]);
c88dfebd
SR
499 }
500 local_family_set = 1;
501 local_family = AF_INET6;
502 require_all_ias = 1;
a68ec967
MS
503 } else if (!strcmp(argv[i], "--dad-wait-time")) {
504 if (++i == argc) {
505 usage(use_noarg, argv[i-1]);
506 }
83f1dd95 507 errno = 0;
a68ec967
MS
508 dad_wait_time = (int)strtol(argv[i], &s, 10);
509 if (errno || (*s != '\0') || (dad_wait_time < 0)) {
83f1dd95
TM
510 usage("Invalid value for --dad-wait-time: %s",
511 argv[i]);
a68ec967 512 }
c0e9661e
TM
513 } else if (!strcmp(argv[i], "--prefix-len-hint")) {
514 if (++i == argc) {
515 usage(use_noarg, argv[i-1]);
516 }
a68ec967 517
c0e9661e
TM
518 errno = 0;
519 prefix_len_hint = (int)strtol(argv[i], &s, 10);
520 if (errno || (*s != '\0') || (prefix_len_hint < 0)) {
521 usage("Invalid value for --prefix-len-hint: %s",
522 argv[i]);
523 }
140612c8
TM
524 } else if (!strcmp(argv[i], "--address-prefix-len")) {
525 if (++i == argc) {
526 usage(use_noarg, argv[i-1]);
527 }
528 errno = 0;
529 address_prefix_len = (int)strtol(argv[i], &s, 10);
530 if (errno || (*s != '\0') ||
531 (address_prefix_len < 0)) {
532 usage("Invalid value for"
533 " --address-prefix-len: %s", argv[i]);
534 }
d7d9c0c7 535#endif /* DHCPv6 */
3e88222f
TM
536 } else if (!strcmp(argv[i], "--decline-wait-time")) {
537 if (++i == argc) {
538 usage(use_noarg, argv[i-1]);
539 }
540
541 errno = 0;
542 decline_wait_time = (int)strtol(argv[i], &s, 10);
543 if (errno || (*s != '\0') ||
544 (decline_wait_time < 0)) {
545 usage("Invalid value for "
546 "--decline-wait-time: %s", argv[i]);
547 }
a41d7a25 548 } else if (!strcmp(argv[i], "-D")) {
d7d9c0c7 549 duid_v4 = 1;
a41d7a25 550 if (++i == argc)
b2cb745b 551 usage(use_noarg, argv[i-1]);
a41d7a25
PS
552 if (!strcasecmp(argv[i], "LL")) {
553 duid_type = DUID_LL;
554 } else if (!strcasecmp(argv[i], "LLT")) {
555 duid_type = DUID_LLT;
556 } else {
b2cb745b 557 usage("Unknown argument to -D: %s", argv[i]);
a41d7a25 558 }
d7d9c0c7
SR
559 } else if (!strcmp(argv[i], "-i")) {
560 /* enable DUID support for DHCPv4 clients */
561 duid_v4 = 1;
562 } else if (!strcmp(argv[i], "-I")) {
563 /* enable standard DHCID support for DDNS updates */
564 std_dhcid = 1;
8ea19a71
DH
565 } else if (!strcmp(argv[i], "-v")) {
566 quiet = 0;
420d8b3f 567 } else if (argv[i][0] == '-') {
b2cb745b 568 usage("Unknown command: %s", argv[i]);
3dbe2246 569 } else if (interfaces_requested < 0) {
b2cb745b
SR
570 usage("No interfaces comamnd -n and "
571 " requested interface %s", argv[i]);
98311e4b 572 } else {
420d8b3f
FD
573 struct interface_info *tmp = NULL;
574
575 status = interface_allocate(&tmp, MDL);
3dbe2246 576 if (status != ISC_R_SUCCESS)
420d8b3f
FD
577 log_fatal("Can't record interface %s:%s",
578 argv[i], isc_result_totext(status));
88cd8aca
DH
579 if (strlen(argv[i]) >= sizeof(tmp->name))
580 log_fatal("%s: interface name too long (is %ld)",
420d8b3f 581 argv[i], (long)strlen(argv[i]));
88cd8aca 582 strcpy(tmp->name, argv[i]);
20916cae 583 if (interfaces) {
420d8b3f
FD
584 interface_reference(&tmp->next,
585 interfaces, MDL);
586 interface_dereference(&interfaces, MDL);
20916cae 587 }
420d8b3f
FD
588 interface_reference(&interfaces, tmp, MDL);
589 tmp->flags = INTERFACE_REQUESTED;
3dbe2246
FD
590 interfaces_requested++;
591 }
c1503c57 592 }
62d0cb47 593
420d8b3f
FD
594 if (wanted_ia_na < 0) {
595 wanted_ia_na = 1;
596 }
597
598 /* Support only one (requested) interface for Prefix Delegation. */
599 if (wanted_ia_pd && (interfaces_requested != 1)) {
b2cb745b 600 usage("PD %s only supports one requested interface", "-P");
420d8b3f
FD
601 }
602
785c1a51
FD
603#if defined(DHCPv6) && defined(DHCP4o6)
604 if ((local_family == AF_INET6) && dhcpv4_over_dhcpv6 &&
605 (exit_mode || release_mode))
606 log_error("Can't relay DHCPv4-over-DHCPv6 "
607 "without a persistent DHCPv6 client");
608 if ((local_family == AF_INET) && dhcpv4_over_dhcpv6 &&
609 (interfaces_requested != 1))
610 log_fatal("DHCPv4-over-DHCPv6 requires an explicit "
611 "interface on which to be applied");
612#endif
613
420d8b3f 614 if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
cfa7212d
TL
615 path_dhclient_conf = s;
616 }
420d8b3f 617 if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
cfa7212d
TL
618 path_dhclient_db = s;
619 }
420d8b3f 620 if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
cfa7212d
TL
621 path_dhclient_pid = s;
622 }
420d8b3f 623 if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
c08637bb
TL
624 path_dhclient_script = s;
625 }
cfa7212d 626
98bd7ca0
DH
627 /* Set up the initial dhcp option universe. */
628 initialize_common_option_spaces();
629
c0a64ef0
TM
630 /* Set up the initial client option universe. */
631 initialize_client_option_spaces();
632
98bd7ca0
DH
633 /* Assign v4 or v6 specific running parameters. */
634 if (local_family == AF_INET)
635 dhcpv4_client_assignments();
fe5b0fdd 636#ifdef DHCPv6
98bd7ca0
DH
637 else if (local_family == AF_INET6)
638 dhcpv6_client_assignments();
fe5b0fdd 639#endif /* DHCPv6 */
98bd7ca0
DH
640 else
641 log_fatal("Impossible condition at %s:%d.", MDL);
642
a546f2a7
EH
643 /*
644 * convert relative path names to absolute, for files that need
645 * to be reopened after chdir() has been called
646 */
647 if (path_dhclient_db[0] != '/') {
db4e4aa2 648 path_dhclient_db = absolute_path(path_dhclient_db);
a546f2a7 649 }
3dbe2246 650
a546f2a7 651 if (path_dhclient_script[0] != '/') {
db4e4aa2 652 path_dhclient_script = absolute_path(path_dhclient_script);
a546f2a7 653 }
3dbe2246 654
4a5bfeac
SR
655 /*
656 * See if we should kill off any currently running client
657 * we don't try to kill it off if the user told us not
658 * to write a pid file - we assume they are controlling
659 * the process in some other fashion.
660 */
661 if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
98311e4b
DH
662 FILE *pidfd;
663 pid_t oldpid;
664 long temp;
665 int e;
666
98311e4b
DH
667 if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
668 e = fscanf(pidfd, "%ld\n", &temp);
669 oldpid = (pid_t)temp;
670
f950de77
SR
671 if (e != 0 && e != EOF && oldpid) {
672 if (kill(oldpid, SIGTERM) == 0) {
673 log_info("Killed old client process");
674 (void) unlink(path_dhclient_pid);
ad4001ce
SR
675 /*
676 * wait for the old process to
677 * cleanly terminate.
678 * Note kill() with sig=0 could
679 * detect termination but only
680 * the parent can be signaled...
681 */
682 sleep(1);
f950de77
SR
683 } else if (errno == ESRCH) {
684 log_info("Removed stale PID file");
685 (void) unlink(path_dhclient_pid);
ad4001ce 686 }
98311e4b
DH
687 }
688 fclose(pidfd);
689 }
347de8bd
TL
690 }
691
62d0cb47 692 if (!quiet) {
420d8b3f
FD
693 log_info("%s %s", message, PACKAGE_VERSION);
694 log_info(copyright);
695 log_info(arr);
696 log_info(url);
697 log_info("%s", "");
8ea19a71 698 } else {
78a33b82 699 log_perror = 0;
8ea19a71
DH
700 quiet_interface_discovery = 1;
701 }
62d0cb47 702
11373fb6
TL
703 /* If we're given a relay agent address to insert, for testing
704 purposes, figure out what it is. */
98bd7ca0 705 if (mockup_relay) {
420d8b3f 706 if (!inet_aton(mockup_relay, &giaddr)) {
11373fb6 707 struct hostent *he;
420d8b3f 708 he = gethostbyname(mockup_relay);
11373fb6 709 if (he) {
420d8b3f
FD
710 memcpy(&giaddr, he->h_addr_list[0],
711 sizeof giaddr);
11373fb6 712 } else {
420d8b3f 713 log_fatal("%s: no such host", mockup_relay);
11373fb6
TL
714 }
715 }
716 }
717
95821729 718 /* Get the current time... */
be62cf06 719 gettimeofday(&cur_tv, NULL);
95821729 720
b00d3884 721 sockaddr_broadcast.sin_family = AF_INET;
cc26de46 722 sockaddr_broadcast.sin_port = remote_port;
3020a2c1 723 if (server) {
420d8b3f 724 if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
3020a2c1 725 struct hostent *he;
420d8b3f 726 he = gethostbyname(server);
3020a2c1 727 if (he) {
420d8b3f
FD
728 memcpy(&sockaddr_broadcast.sin_addr,
729 he->h_addr_list[0],
730 sizeof sockaddr_broadcast.sin_addr);
3020a2c1
TL
731 } else
732 sockaddr_broadcast.sin_addr.s_addr =
733 INADDR_BROADCAST;
734 }
735 } else {
736 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
737 }
11373fb6 738
48d68880 739 inaddr_any.s_addr = INADDR_ANY;
469cf3a4 740
3dbe2246
FD
741 /* Stateless special case. */
742 if (stateless) {
420d8b3f
FD
743 if (release_mode || (wanted_ia_na > 0) ||
744 wanted_ia_ta || wanted_ia_pd ||
745 (interfaces_requested != 1)) {
29b23207 746 usage("Stateless command: %s incompatibile with "
b2cb745b 747 "other commands", "-S");
3dbe2246 748 }
785c1a51
FD
749#if defined(DHCPv6) && defined(DHCP4o6)
750 run_stateless(exit_mode, dhcp4o6_port);
751#else
752 run_stateless(exit_mode, 0);
753#endif
29b23207 754 finish(0);
3dbe2246
FD
755 }
756
cc26de46 757 /* Discover all the network interfaces. */
420d8b3f 758 discover_interfaces(DISCOVER_UNCONFIGURED);
469cf3a4 759
cc26de46 760 /* Parse the dhclient.conf file. */
420d8b3f 761 read_client_conf();
469cf3a4 762
cc26de46 763 /* Parse the lease database. */
420d8b3f 764 read_client_leases();
469cf3a4 765
79818c93
SR
766 /* If desired parse the secondary lease database for a DUID */
767 if ((default_duid.len == 0) && (path_dhclient_duid != NULL)) {
768 read_client_duid();
769 }
770
cc26de46 771 /* Rewrite the lease database... */
420d8b3f 772 rewrite_client_leases();
469cf3a4 773
ce0ec46d
TL
774 /* XXX */
775/* config_counter(&snd_counter, &rcv_counter); */
776
420d8b3f
FD
777 /*
778 * If no broadcast interfaces were discovered, call the script
779 * and tell it so.
780 */
cc26de46 781 if (!interfaces) {
420d8b3f
FD
782 /*
783 * Call dhclient-script with the NBI flag,
784 * in case somebody cares.
785 */
786 script_init(NULL, "NBI", NULL);
787 script_go(NULL);
788
789 /*
790 * If we haven't been asked to persist, waiting for new
791 * interfaces, then just exit.
792 */
134ceef8
TL
793 if (!persist) {
794 /* Nothing more to do. */
420d8b3f 795 log_info("No broadcast interfaces found - exiting.");
29b23207 796 finish(0);
134ceef8 797 }
af5fa176 798 } else if (!release_mode && !exit_mode) {
cc26de46 799 /* Call the script with the list of interfaces. */
420d8b3f
FD
800 for (ip = interfaces; ip; ip = ip->next) {
801 /*
802 * If interfaces were specified, don't configure
803 * interfaces that weren't specified!
804 */
3dbe2246 805 if ((interfaces_requested > 0) &&
420d8b3f
FD
806 ((ip->flags & (INTERFACE_REQUESTED |
807 INTERFACE_AUTOMATIC)) !=
62d0cb47 808 INTERFACE_REQUESTED))
5c2f78b4 809 continue;
98bd7ca0
DH
810
811 if (local_family == AF_INET6) {
812 script_init(ip->client, "PREINIT6", NULL);
813 } else {
814 script_init(ip->client, "PREINIT", NULL);
815 if (ip->client->alias != NULL)
816 script_write_params(ip->client,
817 "alias_",
818 ip->client->alias);
819 }
420d8b3f 820 script_go(ip->client);
cc26de46
TL
821 }
822 }
469cf3a4 823
cc26de46
TL
824 /* At this point, all the interfaces that the script thinks
825 are relevant should be running, so now we once again call
826 discover_interfaces(), and this time ask it to actually set
827 up the interfaces. */
420d8b3f
FD
828 discover_interfaces(interfaces_requested != 0
829 ? DISCOVER_REQUESTED
830 : DISCOVER_RUNNING);
cc26de46 831
66f973e4
TL
832 /* Make up a seed for the random number generator from current
833 time plus the sum of the last four bytes of each
834 interface's hardware address interpreted as an integer.
835 Not much entropy, but we're booting, so we're not likely to
836 find anything better. */
02d9e453 837 seed = 0;
420d8b3f 838 for (ip = interfaces; ip; ip = ip->next) {
66f973e4 839 int junk;
420d8b3f
FD
840 memcpy(&junk,
841 &ip->hw_address.hbuf[ip->hw_address.hlen -
842 sizeof seed], sizeof seed);
66f973e4
TL
843 seed += junk;
844 }
66be0ad1 845 srandom(seed + cur_time + (unsigned)getpid());
66f973e4 846
d7d9c0c7
SR
847
848 /*
849 * Establish a default DUID. We always do so for v6 and
850 * do so if desired for v4 via the -D or -i options
851 */
852 if ((local_family == AF_INET6) ||
853 ((local_family == AF_INET) && (duid_v4 == 1))) {
98bd7ca0
DH
854 if (default_duid.len == 0) {
855 if (default_duid.buffer != NULL)
856 data_string_forget(&default_duid, MDL);
857
858 form_duid(&default_duid, MDL);
859 write_duid(&default_duid);
860 }
d7d9c0c7 861 }
98bd7ca0 862
785c1a51
FD
863#if defined(DHCPv6) && defined(DHCP4o6)
864 if (dhcpv4_over_dhcpv6 && !exit_mode)
865 dhcp4o6_setup(dhcp4o6_port);
866#endif
867
d7d9c0c7
SR
868 /* Start a configuration state machine for each interface. */
869#ifdef DHCPv6
870 if (local_family == AF_INET6) {
98bd7ca0
DH
871 for (ip = interfaces ; ip != NULL ; ip = ip->next) {
872 for (client = ip->client ; client != NULL ;
873 client = client->next) {
3dbe2246
FD
874 if (release_mode) {
875 start_release6(client);
876 continue;
877 } else if (exit_mode) {
878 unconfigure6(client, "STOP6");
879 continue;
880 }
af5fa176 881
98bd7ca0
DH
882 /* If we have a previous binding, Confirm
883 * that we can (or can't) still use it.
884 */
cabdb9b1
FD
885 if ((client->active_lease != NULL) &&
886 !client->active_lease->released)
98bd7ca0
DH
887 start_confirm6(client);
888 else
889 start_init6(client);
890 }
891 }
3dbe2246 892 } else
fe5b0fdd
DH
893#endif /* DHCPv6 */
894 {
98bd7ca0
DH
895 for (ip = interfaces ; ip ; ip = ip->next) {
896 ip->flags |= INTERFACE_RUNNING;
897 for (client = ip->client ; client ;
898 client = client->next) {
3dbe2246
FD
899 if (exit_mode)
900 state_stop(client);
785c1a51 901 if (release_mode)
98bd7ca0
DH
902 do_release(client);
903 else {
904 client->state = S_INIT;
5d082abd
TM
905
906 if (top_level_config.initial_delay>0)
907 {
908 tv.tv_sec = 0;
909 if (top_level_config.
910 initial_delay>1)
911 tv.tv_sec = cur_time
912 + random()
913 % (top_level_config.
914 initial_delay-1);
915 tv.tv_usec = random()
916 % 1000000;
917 /*
918 * this gives better
919 * distribution than just
920 *whole seconds
921 */
922 add_timeout(&tv, state_reboot,
923 client, 0, 0);
924 } else {
925 state_reboot(client);
926 }
98bd7ca0 927 }
347de8bd 928 }
02d9e453 929 }
cc26de46 930 }
469cf3a4 931
87202683 932 if (exit_mode)
29b23207 933 finish(0);
87202683
FD
934 if (release_mode) {
935#ifndef DHCPv6
29b23207 936 finish(0);
87202683 937#else
785c1a51 938 if ((local_family == AF_INET6) || dhcpv4_over_dhcpv6) {
87202683 939 if (onetry)
29b23207 940 finish(0);
87202683 941 } else
29b23207 942 finish(0);
87202683
FD
943#endif /* DHCPv6 */
944 }
347de8bd
TL
945
946 /* Start up a listener for the object management API protocol. */
40a59753 947 if (top_level_config.omapi_port != -1) {
420d8b3f
FD
948 listener = NULL;
949 result = omapi_generic_new(&listener, MDL);
40a59753 950 if (result != ISC_R_SUCCESS)
420d8b3f
FD
951 log_fatal("Can't allocate new generic object: %s\n",
952 isc_result_totext(result));
953 result = omapi_protocol_listen(listener,
954 (unsigned)
955 top_level_config.omapi_port,
956 1);
40a59753 957 if (result != ISC_R_SUCCESS)
420d8b3f
FD
958 log_fatal("Can't start OMAPI protocol: %s",
959 isc_result_totext (result));
40a59753 960 }
347de8bd 961
84c4adde
TL
962 /* Set up the bootp packet handler... */
963 bootp_packet_handler = do_packet;
fe5b0fdd 964#ifdef DHCPv6
98bd7ca0 965 dhcpv6_packet_handler = do_packet6;
fe5b0fdd 966#endif /* DHCPv6 */
84c4adde 967
420d8b3f
FD
968#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
969 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1c44f6bd
TL
970 dmalloc_cutoff_generation = dmalloc_generation;
971 dmalloc_longterm = dmalloc_outstanding;
972 dmalloc_outstanding = 0;
973#endif
974
e9326fd0
SR
975#if defined(ENABLE_GENTLE_SHUTDOWN)
976 /* no signal handlers until we deal with the side effects */
47e8308d
SR
977 /* install signal handlers */
978 signal(SIGINT, dhcp_signal_handler); /* control-c */
979 signal(SIGTERM, dhcp_signal_handler); /* kill */
e9326fd0 980#endif
47e8308d 981
37c1f13f
TL
982 /* If we're not supposed to wait before getting the address,
983 don't. */
984 if (nowait)
29b23207 985 detach();
37c1f13f 986
b1423aed
TL
987 /* If we're not going to daemonize, write the pid file
988 now. */
37c1f13f 989 if (no_daemon || nowait)
420d8b3f 990 write_client_pid_file();
b1423aed 991
cc26de46 992 /* Start dispatching packets and timeouts... */
420d8b3f 993 dispatch();
84c4adde 994
0895c955 995 /* In fact dispatch() never returns. */
cc26de46 996 return 0;
469cf3a4
TL
997}
998
785c1a51
FD
999/*
1000 * \brief Run the DHCPv6 stateless client (dhclient -6 -S)
1001 *
1002 * \param exist_mode set to 1 when dhclient was called with -x
1003 * \param port DHCPv4-over-DHCPv6 client inter-process communication
1004 * UDP port pair (port,port+1 with port in network byte order)
1005 */
1006
1007void run_stateless(int exit_mode, u_int16_t port)
3dbe2246 1008{
420d8b3f 1009#ifdef DHCPv6
3dbe2246
FD
1010 struct client_state *client;
1011 omapi_object_t *listener;
1012 isc_result_t result;
1013
785c1a51
FD
1014#ifndef DHCP4o6
1015 IGNORE_UNUSED(port);
1016#endif
1017
3dbe2246
FD
1018 /* Discover the network interface. */
1019 discover_interfaces(DISCOVER_REQUESTED);
1020
1021 if (!interfaces)
b2cb745b 1022 usage("No interfaces available for stateless command: %s", "-S");
3dbe2246
FD
1023
1024 /* Parse the dhclient.conf file. */
785c1a51
FD
1025#ifdef DHCP4o6
1026 if (dhcpv4_over_dhcpv6) {
1027 /* Mark we want to request IRT too! */
1028 dhcpv4_over_dhcpv6++;
1029 }
1030#endif
3dbe2246
FD
1031 read_client_conf();
1032
1033 /* Parse the lease database. */
1034 read_client_leases();
1035
79818c93
SR
1036 /* If desired parse the secondary lease database for a DUID */
1037 if ((default_duid.len == 0) && (path_dhclient_duid != NULL)) {
1038 read_client_duid();
1039 }
1040
3dbe2246
FD
1041 /* Establish a default DUID. */
1042 if (default_duid.len == 0) {
1043 if (default_duid.buffer != NULL)
1044 data_string_forget(&default_duid, MDL);
1045
1046 form_duid(&default_duid, MDL);
1047 }
1048
785c1a51
FD
1049#ifdef DHCP4o6
1050 if (dhcpv4_over_dhcpv6 && !exit_mode)
1051 dhcp4o6_setup(port);
1052#endif
1053
3dbe2246
FD
1054 /* Start a configuration state machine. */
1055 for (client = interfaces->client ;
1056 client != NULL ;
1057 client = client->next) {
1058 if (exit_mode) {
1059 unconfigure6(client, "STOP6");
1060 continue;
1061 }
1062 start_info_request6(client);
1063 }
1064 if (exit_mode)
1065 return;
1066
1067 /* Start up a listener for the object management API protocol. */
1068 if (top_level_config.omapi_port != -1) {
420d8b3f 1069 listener = NULL;
3dbe2246
FD
1070 result = omapi_generic_new(&listener, MDL);
1071 if (result != ISC_R_SUCCESS)
1072 log_fatal("Can't allocate new generic object: %s\n",
1073 isc_result_totext(result));
1074 result = omapi_protocol_listen(listener,
1075 (unsigned)
1076 top_level_config.omapi_port,
1077 1);
1078 if (result != ISC_R_SUCCESS)
1079 log_fatal("Can't start OMAPI protocol: %s",
1080 isc_result_totext(result));
1081 }
1082
1083 /* Set up the packet handler... */
1084 dhcpv6_packet_handler = do_packet6;
1085
420d8b3f
FD
1086#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
1087 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
3dbe2246
FD
1088 dmalloc_cutoff_generation = dmalloc_generation;
1089 dmalloc_longterm = dmalloc_outstanding;
1090 dmalloc_outstanding = 0;
1091#endif
1092
1093 /* If we're not supposed to wait before getting the address,
1094 don't. */
1095 if (nowait)
29b23207 1096 detach();
3dbe2246
FD
1097
1098 /* If we're not going to daemonize, write the pid file
1099 now. */
1100 if (no_daemon || nowait)
1101 write_client_pid_file();
1102
1103 /* Start dispatching packets and timeouts... */
1104 dispatch();
1105
420d8b3f 1106#endif /* DHCPv6 */
3dbe2246
FD
1107 return;
1108}
eda1d0aa 1109#endif /* !UNIT_TEST */
3dbe2246 1110
20916cae
TL
1111isc_result_t find_class (struct class **c,
1112 const char *s, const char *file, int line)
02a015fb 1113{
20916cae 1114 return 0;
02a015fb
TL
1115}
1116
da38df14 1117int check_collection (packet, lease, collection)
02a015fb 1118 struct packet *packet;
da38df14 1119 struct lease *lease;
02a015fb
TL
1120 struct collection *collection;
1121{
1122 return 0;
1123}
1124
1125void classify (packet, class)
1126 struct packet *packet;
1127 struct class *class;
1128{
1129}
1130
6a39bcf0 1131void unbill_class (lease)
73530742 1132 struct lease *lease;
73530742 1133{
73530742
TL
1134}
1135
20916cae
TL
1136int find_subnet (struct subnet **sp,
1137 struct iaddr addr, const char *file, int line)
bfdb842e 1138{
20916cae 1139 return 0;
bfdb842e
TL
1140}
1141
469cf3a4 1142/* Individual States:
3dbe2246 1143 *
469cf3a4
TL
1144 * Each routine is called from the dhclient_state_machine() in one of
1145 * these conditions:
1146 * -> entering INIT state
1147 * -> recvpacket_flag == 0: timeout in this state
1148 * -> otherwise: received a packet in this state
1149 *
1150 * Return conditions as handled by dhclient_state_machine():
1151 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
1152 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
1153 * Returns 0: finish the nap which was interrupted for no good reason.
1154 *
cc26de46
TL
1155 * Several per-interface variables are used to keep track of the process:
1156 * active_lease: the lease that is being used on the interface
1157 * (null pointer if not configured yet).
1158 * offered_leases: leases corresponding to DHCPOFFER messages that have
1159 * been sent to us by DHCP servers.
1160 * acked_leases: leases corresponding to DHCPACK messages that have been
1161 * sent to us by DHCP servers.
1162 * sendpacket: DHCP packet we're trying to send.
469cf3a4 1163 * destination: IP address to send sendpacket to
cc26de46 1164 * In addition, there are several relevant per-lease variables.
469cf3a4 1165 * T1_expiry, T2_expiry, lease_expiry: lease milestones
cc26de46
TL
1166 * In the active lease, these control the process of renewing the lease;
1167 * In leases on the acked_leases list, this simply determines when we
1168 * can no longer legitimately use the lease.
469cf3a4
TL
1169 */
1170
02d9e453
TL
1171void state_reboot (cpp)
1172 void *cpp;
deff2d59 1173{
02d9e453 1174 struct client_state *client = cpp;
84c4adde 1175
785c1a51
FD
1176#if defined(DHCPv6) && defined(DHCP4o6)
1177 if (dhcpv4_over_dhcpv6 && (dhcp4o6_state <= 0)) {
1178 if (dhcp4o6_state < 0)
1179 dhcp4o6_poll(NULL);
1180 client->pending = P_REBOOT;
1181 return;
1182 }
1183#endif
1184
1185 client->pending= P_NONE;
1186
deff2d59 1187 /* If we don't remember an active lease, go straight to INIT. */
02d9e453 1188 if (!client -> active ||
d758ad8c
TL
1189 client -> active -> is_bootp ||
1190 client -> active -> expiry <= cur_time) {
02d9e453 1191 state_init (client);
deff2d59
TL
1192 return;
1193 }
1194
1195 /* We are in the rebooting state. */
02d9e453 1196 client -> state = S_REBOOTING;
deff2d59 1197
420d8b3f
FD
1198 /*
1199 * make_request doesn't initialize xid because it normally comes
1200 * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
1201 * so pick an xid now.
1202 */
02d9e453 1203 client -> xid = random ();
5c2f78b4 1204
420d8b3f
FD
1205 /*
1206 * Make a DHCPREQUEST packet, and set
1207 * appropriate per-interface flags.
1208 */
02d9e453
TL
1209 make_request (client, client -> active);
1210 client -> destination = iaddr_broadcast;
1211 client -> first_sending = cur_time;
1212 client -> interval = client -> config -> initial_interval;
deff2d59 1213
b8cf055d 1214 /* Zap the medium list... */
420d8b3f 1215 client -> medium = NULL;
b8cf055d
TL
1216
1217 /* Send out the first DHCPREQUEST packet. */
02d9e453 1218 send_request (client);
deff2d59
TL
1219}
1220
1221/* Called when a lease has completely expired and we've been unable to
1222 renew it. */
cc26de46 1223
02d9e453
TL
1224void state_init (cpp)
1225 void *cpp;
469cf3a4 1226{
02d9e453 1227 struct client_state *client = cpp;
84c4adde 1228
469cf3a4
TL
1229 ASSERT_STATE(state, S_INIT);
1230
cc26de46
TL
1231 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
1232 flags. */
02d9e453
TL
1233 make_discover (client, client -> active);
1234 client -> xid = client -> packet.xid;
1235 client -> destination = iaddr_broadcast;
1236 client -> state = S_SELECTING;
1237 client -> first_sending = cur_time;
1238 client -> interval = client -> config -> initial_interval;
cc26de46
TL
1239
1240 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
1241 to go out. */
02d9e453 1242 send_discover (client);
469cf3a4
TL
1243}
1244
3354013a
FD
1245/* check_v6only is called by dhcpoffer and dhcpack. It checks if a
1246 * requested v6-only-preferred option is present and returned the
1247 * V6ONLY_WAIT delay to suspend DHCPv4. */
933b80fa 1248
3354013a 1249uint32_t check_v6only(packet, client)
933b80fa
FD
1250 struct packet *packet;
1251 struct client_state *client;
1252{
3354013a
FD
1253 int i;
1254 struct option **req;
1255 isc_boolean_t found = ISC_FALSE;
933b80fa
FD
1256 struct option_cache *oc;
1257 struct data_string data;
1258 uint32_t v6only_wait = 0;
933b80fa 1259
3354013a
FD
1260 /* Check if the v6-only-preferred was requested. */
1261 req = client->config->requested_options;
1262
1263 if (req == NULL)
1264 return 0;
1265
1266 for (i = 0 ; req[i] != NULL ; i++) {
1267 if ((req[i]->universe == &dhcp_universe) &&
1268 (req[i]->code == DHO_V6_ONLY_PREFERRED)) {
1269 found = ISC_TRUE;
1270 break;
1271 }
1272 }
1273
1274 if (found == ISC_FALSE)
1275 return 0;
1276
933b80fa
FD
1277 /* Get the V6ONLY_WAIT timer. */
1278 oc = lookup_option(&dhcp_universe, packet->options,
1279 DHO_V6_ONLY_PREFERRED);
3354013a
FD
1280 if (!oc)
1281 return 0;
933b80fa
FD
1282
1283 memset(&data, 0, sizeof(data));
1284
1285 if (evaluate_option_cache(&data, packet, (struct lease *)0, client,
1286 packet->options, (struct option_state *)0,
1287 &global_scope, oc, MDL)) {
3354013a 1288 if (data.len > 3) {
933b80fa 1289 v6only_wait = getULong(data.data);
3354013a
FD
1290 if (v6only_wait < MIN_V6ONLY_WAIT)
1291 v6only_wait = MIN_V6ONLY_WAIT;
1292 }
933b80fa
FD
1293 data_string_forget(&data, MDL);
1294 }
1295
3354013a
FD
1296 return (v6only_wait);
1297}
1298
1299/* finish_v6only is called when the V6ONLY_WAIT timer expired. */
1300
1301void finish_v6only(cpp)
1302 void *cpp;
1303{
1304 struct client_state *client = cpp;
4b705d0d
FD
1305
1306 cancel_timeout(finish_v6only, client);
3354013a
FD
1307 client->state = S_INIT;
1308 state_init(cpp);
1309}
1310
1311/*
1312 * start_v6only is called when a requested v6-only-preferred option was
1313 * returned by the server. */
1314
1315void start_v6only(client, v6only_wait)
1316 struct client_state *client;
1317 uint32_t v6only_wait;
1318{
1319 struct timeval tv;
933b80fa
FD
1320
1321 /* Enter V6ONLY state. */
1322
1323 client->state = S_V6ONLY;
1324
1325 /* Run the client script. */
1326 script_init(client, "V6ONLY", NULL);
1327 if (client->active) {
1328 script_write_params(client, "old_", client->active);
1329 destroy_client_lease(client->active);
1330 client->active = NULL;
1331 }
1332 script_write_requested(client);
1333 client_envadd(client, "", "v6-only-preferred", "%lu",
1334 (long unsigned)v6only_wait);
1335 script_go(client);
1336
1337 /* Trigger finish_v6only after V6ONLY_WAIT seconds. */
1338 tv.tv_sec = cur_tv.tv_sec + v6only_wait;
1339 tv.tv_usec = cur_tv.tv_usec;
1340
1341 add_timeout(&tv, finish_v6only, client, 0, 0);
1342}
1343
420d8b3f
FD
1344/*
1345 * state_selecting is called when one or more DHCPOFFER packets have been
1346 * received and a configurable period of time has passed.
1347 */
cc26de46 1348
02d9e453
TL
1349void state_selecting (cpp)
1350 void *cpp;
469cf3a4 1351{
02d9e453 1352 struct client_state *client = cpp;
b00d3884
TL
1353 struct client_lease *lp, *next, *picked;
1354
02d9e453 1355
469cf3a4
TL
1356 ASSERT_STATE(state, S_SELECTING);
1357
420d8b3f
FD
1358 /*
1359 * Cancel state_selecting and send_discover timeouts, since either
1360 * one could have got us here.
1361 */
02d9e453
TL
1362 cancel_timeout (state_selecting, client);
1363 cancel_timeout (send_discover, client);
cc26de46 1364
420d8b3f
FD
1365 /*
1366 * We have received one or more DHCPOFFER packets. Currently,
1367 * the only criterion by which we judge leases is whether or
1368 * not we get a response when we arp for them.
1369 */
1370 picked = NULL;
02d9e453 1371 for (lp = client -> offered_leases; lp; lp = next) {
b00d3884
TL
1372 next = lp -> next;
1373
420d8b3f
FD
1374 /*
1375 * Check to see if we got an ARPREPLY for the address
1376 * in this particular lease.
1377 */
b00d3884 1378 if (!picked) {
b00d3884 1379 picked = lp;
420d8b3f 1380 picked -> next = NULL;
b00d3884 1381 } else {
02a015fb 1382 destroy_client_lease (lp);
b00d3884
TL
1383 }
1384 }
420d8b3f 1385 client -> offered_leases = NULL;
b00d3884 1386
420d8b3f
FD
1387 /*
1388 * If we just tossed all the leases we were offered, go back
1389 * to square one.
1390 */
b00d3884 1391 if (!picked) {
02d9e453
TL
1392 client -> state = S_INIT;
1393 state_init (client);
b00d3884
TL
1394 return;
1395 }
1396
66f973e4 1397 /* If it was a BOOTREPLY, we can just take the address right now. */
2455808f 1398 if (picked -> is_bootp) {
02d9e453 1399 client -> new = picked;
66f973e4
TL
1400
1401 /* Make up some lease expiry times
1402 XXX these should be configurable. */
02d9e453
TL
1403 client -> new -> expiry = cur_time + 12000;
1404 client -> new -> renewal += cur_time + 8000;
1405 client -> new -> rebind += cur_time + 10000;
66f973e4 1406
02d9e453 1407 client -> state = S_REQUESTING;
66f973e4
TL
1408
1409 /* Bind to the address we received. */
02d9e453 1410 bind_lease (client);
66f973e4
TL
1411 return;
1412 }
1413
b00d3884 1414 /* Go to the REQUESTING state. */
02d9e453
TL
1415 client -> destination = iaddr_broadcast;
1416 client -> state = S_REQUESTING;
1417 client -> first_sending = cur_time;
1418 client -> interval = client -> config -> initial_interval;
cc26de46 1419
b00d3884 1420 /* Make a DHCPREQUEST packet from the lease we picked. */
02d9e453
TL
1421 make_request (client, picked);
1422 client -> xid = client -> packet.xid;
469cf3a4 1423
b00d3884 1424 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
02a015fb 1425 destroy_client_lease (picked);
b00d3884 1426
cc26de46 1427 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
02d9e453 1428 send_request (client);
3dbe2246 1429}
469cf3a4 1430
cc26de46
TL
1431/* state_requesting is called when we receive a DHCPACK message after
1432 having sent out one or more DHCPREQUEST packets. */
469cf3a4 1433
cc26de46
TL
1434void dhcpack (packet)
1435 struct packet *packet;
469cf3a4 1436{
cc26de46 1437 struct interface_info *ip = packet -> interface;
02d9e453 1438 struct client_state *client;
3354013a 1439 uint32_t v6only_wait;
cc26de46 1440 struct client_lease *lease;
02a015fb
TL
1441 struct option_cache *oc;
1442 struct data_string ds;
3dbe2246 1443
cc26de46
TL
1444 /* If we're not receptive to an offer right now, or if the offer
1445 has an unrecognizable transaction id, then just drop it. */
02d9e453
TL
1446 for (client = ip -> client; client; client = client -> next) {
1447 if (client -> xid == packet -> raw -> xid)
1448 break;
1449 }
1450 if (!client ||
31730f17 1451 (packet -> interface -> hw_address.hlen - 1 !=
5c2f78b4 1452 packet -> raw -> hlen) ||
31730f17 1453 (memcmp (&packet -> interface -> hw_address.hbuf [1],
fcaec4ef 1454 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2d1b06e0 1455#if defined (DEBUG)
8ae2d595 1456 log_debug ("DHCPACK in wrong transaction.");
2d1b06e0 1457#endif
cc26de46 1458 return;
469cf3a4 1459 }
469cf3a4 1460
02d9e453
TL
1461 if (client -> state != S_REBOOTING &&
1462 client -> state != S_REQUESTING &&
1463 client -> state != S_RENEWING &&
1464 client -> state != S_REBINDING) {
2d1b06e0 1465#if defined (DEBUG)
8ae2d595 1466 log_debug ("DHCPACK in wrong state.");
2d1b06e0 1467#endif
cc26de46 1468 return;
469cf3a4
TL
1469 }
1470
35e86889
TM
1471 log_info ("DHCPACK of %s from %s",
1472 inet_ntoa(packet->raw->yiaddr),
1473 piaddr (packet->client_addr));
34fdad6c 1474
3354013a
FD
1475 /* Check v6only first. */
1476 v6only_wait = check_v6only(packet, client);
1477 if (v6only_wait > 0) {
1478 log_info("v6 only preferred for %lu.",
1479 (long unsigned)v6only_wait);
4b705d0d 1480 cancel_timeout(send_request, client);
3354013a
FD
1481 start_v6only(client, v6only_wait);
1482 return;
1483 }
1484
6ceb9118 1485 lease = packet_to_lease (packet, client);
cc26de46 1486 if (!lease) {
8ae2d595 1487 log_info ("packet_to_lease failed.");
cc26de46 1488 return;
469cf3a4
TL
1489 }
1490
02d9e453 1491 client -> new = lease;
cc26de46
TL
1492
1493 /* Stop resending DHCPREQUEST. */
02d9e453 1494 cancel_timeout (send_request, client);
cc26de46
TL
1495
1496 /* Figure out the lease time. */
230e73e4 1497 oc = lookup_option (&dhcp_universe, client -> new -> options,
02a015fb
TL
1498 DHO_DHCP_LEASE_TIME);
1499 memset (&ds, 0, sizeof ds);
1500 if (oc &&
66e9cecf 1501 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
0852a27f 1502 packet -> options, client -> new -> options,
cf78bf20 1503 &global_scope, oc, MDL)) {
02a015fb 1504 if (ds.len > 3)
02d9e453 1505 client -> new -> expiry = getULong (ds.data);
02a015fb 1506 else
02d9e453 1507 client -> new -> expiry = 0;
cf78bf20 1508 data_string_forget (&ds, MDL);
02a015fb 1509 } else
02d9e453 1510 client -> new -> expiry = 0;
02a015fb 1511
5d082abd
TM
1512 if (client->new->expiry == 0) {
1513 struct timeval tv;
1514
8ae2d595 1515 log_error ("no expiry time on offered lease.");
5d082abd
TM
1516
1517 /* Quench this (broken) server. Return to INIT to reselect. */
1518 add_reject(packet);
1519
1520 /* 1/2 second delay to restart at INIT. */
1521 tv.tv_sec = cur_tv.tv_sec;
1522 tv.tv_usec = cur_tv.tv_usec + 500000;
1523
1524 if (tv.tv_usec >= 1000000) {
1525 tv.tv_sec++;
1526 tv.tv_usec -= 1000000;
1527 }
1528
1529 add_timeout(&tv, state_init, client, 0, 0);
02a015fb
TL
1530 return;
1531 }
cc26de46 1532
5d082abd
TM
1533 /*
1534 * A number that looks negative here is really just very large,
1535 * because the lease expiry offset is unsigned.
1536 */
1537 if (client->new->expiry < 0)
1538 client->new->expiry = TIME_MAX;
1539
02a015fb 1540 /* Take the server-provided renewal time if there is one. */
230e73e4 1541 oc = lookup_option (&dhcp_universe, client -> new -> options,
02a015fb
TL
1542 DHO_DHCP_RENEWAL_TIME);
1543 if (oc &&
66e9cecf 1544 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
0852a27f 1545 packet -> options, client -> new -> options,
cf78bf20 1546 &global_scope, oc, MDL)) {
02a015fb 1547 if (ds.len > 3)
02d9e453 1548 client -> new -> renewal = getULong (ds.data);
02a015fb 1549 else
02d9e453 1550 client -> new -> renewal = 0;
cf78bf20 1551 data_string_forget (&ds, MDL);
02a015fb 1552 } else
02d9e453 1553 client -> new -> renewal = 0;
02a015fb
TL
1554
1555 /* If it wasn't specified by the server, calculate it. */
02d9e453 1556 if (!client -> new -> renewal)
98311e4b
DH
1557 client -> new -> renewal = client -> new -> expiry / 2 + 1;
1558
1559 if (client -> new -> renewal <= 0)
1560 client -> new -> renewal = TIME_MAX;
cc26de46 1561
11373fb6 1562 /* Now introduce some randomness to the renewal time: */
88cd8aca
DH
1563 if (client->new->renewal <= ((TIME_MAX / 3) - 3))
1564 client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
1565 (((random() % client->new->renewal) + 3) / 4);
11373fb6 1566
cc26de46 1567 /* Same deal with the rebind time. */
230e73e4 1568 oc = lookup_option (&dhcp_universe, client -> new -> options,
02a015fb
TL
1569 DHO_DHCP_REBINDING_TIME);
1570 if (oc &&
66e9cecf 1571 evaluate_option_cache (&ds, packet, (struct lease *)0, client,
0852a27f 1572 packet -> options, client -> new -> options,
cf78bf20 1573 &global_scope, oc, MDL)) {
02a015fb 1574 if (ds.len > 3)
02d9e453 1575 client -> new -> rebind = getULong (ds.data);
02a015fb 1576 else
02d9e453 1577 client -> new -> rebind = 0;
cf78bf20 1578 data_string_forget (&ds, MDL);
02a015fb 1579 } else
02d9e453 1580 client -> new -> rebind = 0;
02a015fb 1581
98311e4b
DH
1582 if (client -> new -> rebind <= 0) {
1583 if (client -> new -> expiry <= TIME_MAX / 7)
1584 client -> new -> rebind =
1585 client -> new -> expiry * 7 / 8;
1586 else
1587 client -> new -> rebind =
1588 client -> new -> expiry / 8 * 7;
1589 }
11373fb6
TL
1590
1591 /* Make sure our randomness didn't run the renewal time past the
1592 rebind time. */
98311e4b
DH
1593 if (client -> new -> renewal > client -> new -> rebind) {
1594 if (client -> new -> rebind <= TIME_MAX / 3)
1595 client -> new -> renewal =
1596 client -> new -> rebind * 3 / 4;
1597 else
1598 client -> new -> renewal =
1599 client -> new -> rebind / 4 * 3;
1600 }
cc26de46 1601
02d9e453 1602 client -> new -> expiry += cur_time;
62d0cb47
TL
1603 /* Lease lengths can never be negative. */
1604 if (client -> new -> expiry < cur_time)
1605 client -> new -> expiry = TIME_MAX;
02d9e453 1606 client -> new -> renewal += cur_time;
62d0cb47
TL
1607 if (client -> new -> renewal < cur_time)
1608 client -> new -> renewal = TIME_MAX;
02d9e453 1609 client -> new -> rebind += cur_time;
62d0cb47
TL
1610 if (client -> new -> rebind < cur_time)
1611 client -> new -> rebind = TIME_MAX;
cc26de46 1612
02d9e453 1613 bind_lease (client);
66f973e4
TL
1614}
1615
02d9e453
TL
1616void bind_lease (client)
1617 struct client_state *client;
66f973e4 1618{
be62cf06
FD
1619 struct timeval tv;
1620
9bdb9271 1621 /* Remember the medium. */
02b0bdc3 1622 client->new->medium = client->medium;
9bdb9271 1623
cc26de46 1624 /* Run the client script with the new parameters. */
02b0bdc3 1625 script_init(client, (client->state == S_REQUESTING ? "BOUND" :
cca6a648 1626 (client->state == S_RENEWING ? "RENEW" :
02b0bdc3
SR
1627 (client->state == S_REBOOTING ? "REBOOT" :
1628 "REBIND"))),
1629 client->new->medium);
1630 if (client->active && client->state != S_REBOOTING)
1631 script_write_params(client, "old_", client->active);
27be804f 1632 script_write_params(client, "new_", client->new);
10613724 1633 script_write_requested(client);
02b0bdc3
SR
1634 if (client->alias)
1635 script_write_params(client, "alias_", client->alias);
e16f4c3e
TL
1636
1637 /* If the BOUND/RENEW code detects another machine using the
1638 offered address, it exits nonzero. We need to send a
1639 DHCPDECLINE and toss the lease. */
02b0bdc3
SR
1640 if (script_go(client)) {
1641 make_decline(client, client->new);
1642 send_decline(client);
1643 destroy_client_lease(client->new);
1644 client->new = NULL;
1645 if (onetry) {
5c03ed37 1646 if (!quiet) {
02b0bdc3
SR
1647 log_info("Unable to obtain a lease on first "
1648 "try (declined). Exiting.");
5c03ed37 1649 }
c788d4f8 1650
5c03ed37 1651#if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
c788d4f8
TM
1652 /* Let's call a script and we're done */
1653 script_init(client, "FAIL", (struct string_list *)0);
1654 script_go(client);
5c03ed37 1655#endif
29b23207 1656 finish(2);
02b0bdc3 1657 } else {
3e88222f
TM
1658 struct timeval tv;
1659 tv.tv_sec = cur_tv.tv_sec + decline_wait_time;
1660 tv.tv_usec = cur_tv.tv_usec;
1661 add_timeout(&tv, state_init, client, 0, 0);
02b0bdc3
SR
1662 return;
1663 }
e16f4c3e
TL
1664 }
1665
5d082abd
TM
1666 /* Write out the new lease if it has been long enough. */
1667 if (!client->last_write ||
1668 (cur_time - client->last_write) >= MIN_LEASE_WRITE)
8a2e40cf 1669 write_client_lease(client, client->new, 0, 1);
cc26de46
TL
1670
1671 /* Replace the old active lease with the new one. */
0cd94b5e
TM
1672 if (client->active) {
1673 if (client->active->is_static) {
1674 // We need to preserve the fallback lease in case
1675 // we lose DHCP service again.
1676 add_to_tail(&client->leases, client->active);
1677 } else {
1678 destroy_client_lease(client->active);
1679 }
1680 }
1681
02b0bdc3
SR
1682 client->active = client->new;
1683 client->new = NULL;
cc26de46
TL
1684
1685 /* Set up a timeout to start the renewal process. */
5d082abd
TM
1686 tv.tv_sec = client->active->renewal;
1687 tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
1688 random() % 1000000 : cur_tv.tv_usec;
1689 add_timeout(&tv, state_bound, client, 0, 0);
cc26de46 1690
02b0bdc3
SR
1691 log_info("bound to %s -- renewal in %ld seconds.",
1692 piaddr(client->active->address),
1693 (long)(client->active->renewal - cur_time));
1694 client->state = S_BOUND;
1695 reinitialize_interfaces();
29b23207 1696 detach();
98bf1607 1697#if defined (NSUPDATE)
98bd7ca0 1698 if (client->config->do_forward_update)
98bf1607 1699 dhclient_schedule_updates(client, &client->active->address, 1);
5df5813d
TM
1700#endif /* defined NSUPDATE */
1701
3dbe2246 1702}
469cf3a4 1703
cc26de46
TL
1704/* state_bound is called when we've successfully bound to a particular
1705 lease, but the renewal time on that lease has expired. We are
1706 expected to unicast a DHCPREQUEST to the server that gave us our
1707 original lease. */
469cf3a4 1708
02d9e453
TL
1709void state_bound (cpp)
1710 void *cpp;
469cf3a4 1711{
02d9e453 1712 struct client_state *client = cpp;
02a015fb
TL
1713 struct option_cache *oc;
1714 struct data_string ds;
84c4adde 1715
cc26de46 1716 ASSERT_STATE(state, S_BOUND);
469cf3a4 1717
cc26de46 1718 /* T1 has expired. */
02d9e453
TL
1719 make_request (client, client -> active);
1720 client -> xid = client -> packet.xid;
469cf3a4 1721
02a015fb 1722 memset (&ds, 0, sizeof ds);
230e73e4 1723 oc = lookup_option (&dhcp_universe, client -> active -> options,
02a015fb
TL
1724 DHO_DHCP_SERVER_IDENTIFIER);
1725 if (oc &&
0852a27f 1726 evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
66e9cecf 1727 client, (struct option_state *)0,
da38df14 1728 client -> active -> options,
cf78bf20 1729 &global_scope, oc, MDL)) {
02a015fb 1730 if (ds.len > 3) {
02d9e453
TL
1731 memcpy (client -> destination.iabuf, ds.data, 4);
1732 client -> destination.len = 4;
02a015fb 1733 } else
02d9e453 1734 client -> destination = iaddr_broadcast;
98311e4b
DH
1735
1736 data_string_forget (&ds, MDL);
cc26de46 1737 } else
02d9e453 1738 client -> destination = iaddr_broadcast;
469cf3a4 1739
02d9e453
TL
1740 client -> first_sending = cur_time;
1741 client -> interval = client -> config -> initial_interval;
1742 client -> state = S_RENEWING;
cc26de46
TL
1743
1744 /* Send the first packet immediately. */
02d9e453 1745 send_request (client);
3dbe2246 1746}
469cf3a4 1747
d758ad8c
TL
1748/* state_stop is called when we've been told to shut down. We unconfigure
1749 the interfaces, and then stop operating until told otherwise. */
1750
1751void state_stop (cpp)
1752 void *cpp;
1753{
1754 struct client_state *client = cpp;
d758ad8c 1755
785c1a51
FD
1756 client->pending = P_NONE;
1757
d758ad8c 1758 /* Cancel all timeouts. */
af5fa176
EH
1759 cancel_timeout(state_selecting, client);
1760 cancel_timeout(send_discover, client);
1761 cancel_timeout(send_request, client);
1762 cancel_timeout(state_bound, client);
933b80fa 1763 cancel_timeout(finish_v6only, client);
d758ad8c
TL
1764
1765 /* If we have an address, unconfigure it. */
af5fa176
EH
1766 if (client->active) {
1767 script_init(client, "STOP", client->active->medium);
1768 script_write_params(client, "old_", client->active);
10613724 1769 script_write_requested(client);
af5fa176
EH
1770 if (client->alias)
1771 script_write_params(client, "alias_", client->alias);
1772 script_go(client);
d758ad8c 1773 }
3dbe2246 1774}
d758ad8c 1775
c1503c57
TL
1776int commit_leases ()
1777{
1778 return 0;
1779}
1780
1781int write_lease (lease)
1782 struct lease *lease;
1783{
1784 return 0;
95821729
TL
1785}
1786
628beb0e
TL
1787int write_host (host)
1788 struct host_decl *host;
1789{
1790 return 0;
1791}
1792
7d7a35fa
TL
1793void db_startup (testp)
1794 int testp;
c1503c57
TL
1795{
1796}
1797
1798void bootp (packet)
1799 struct packet *packet;
1800{
febbd402
DH
1801 struct iaddrmatchlist *ap;
1802 char addrbuf[4*16];
1803 char maskbuf[4*16];
fa2b3e59
TL
1804
1805 if (packet -> raw -> op != BOOTREPLY)
1806 return;
1807
1808 /* If there's a reject list, make sure this packet's sender isn't
1809 on it. */
1810 for (ap = packet -> interface -> client -> config -> reject_list;
1811 ap; ap = ap -> next) {
febbd402
DH
1812 if (addr_match(&packet->client_addr, &ap->match)) {
1813
1814 /* piaddr() returns its result in a static
1815 buffer sized 4*16 (see common/inet.c). */
1816
1817 strcpy(addrbuf, piaddr(ap->match.addr));
1818 strcpy(maskbuf, piaddr(ap->match.mask));
1819
1820 log_info("BOOTREPLY from %s rejected by rule %s "
1821 "mask %s.", piaddr(packet->client_addr),
1822 addrbuf, maskbuf);
fa2b3e59
TL
1823 return;
1824 }
1825 }
3dbe2246 1826
fa2b3e59 1827 dhcpoffer (packet);
66f973e4 1828
c1503c57 1829}
95821729 1830
c1503c57
TL
1831void dhcp (packet)
1832 struct packet *packet;
95821729 1833{
febbd402 1834 struct iaddrmatchlist *ap;
a34feb7d 1835 void (*handler) (struct packet *);
b1b7b521 1836 const char *type;
febbd402
DH
1837 char addrbuf[4*16];
1838 char maskbuf[4*16];
fa2b3e59 1839
c1503c57
TL
1840 switch (packet -> packet_type) {
1841 case DHCPOFFER:
fa2b3e59
TL
1842 handler = dhcpoffer;
1843 type = "DHCPOFFER";
95821729 1844 break;
c1503c57
TL
1845
1846 case DHCPNAK:
fa2b3e59
TL
1847 handler = dhcpnak;
1848 type = "DHCPNACK";
c1503c57
TL
1849 break;
1850
1851 case DHCPACK:
fa2b3e59
TL
1852 handler = dhcpack;
1853 type = "DHCPACK";
c1503c57
TL
1854 break;
1855
95821729 1856 default:
fa2b3e59
TL
1857 return;
1858 }
1859
1860 /* If there's a reject list, make sure this packet's sender isn't
1861 on it. */
1862 for (ap = packet -> interface -> client -> config -> reject_list;
1863 ap; ap = ap -> next) {
febbd402
DH
1864 if (addr_match(&packet->client_addr, &ap->match)) {
1865
1866 /* piaddr() returns its result in a static
1867 buffer sized 4*16 (see common/inet.c). */
1868
1869 strcpy(addrbuf, piaddr(ap->match.addr));
1870 strcpy(maskbuf, piaddr(ap->match.mask));
1871
1872 log_info("%s from %s rejected by rule %s mask %s.",
1873 type, piaddr(packet->client_addr),
1874 addrbuf, maskbuf);
fa2b3e59
TL
1875 return;
1876 }
95821729 1877 }
fa2b3e59 1878 (*handler) (packet);
95821729
TL
1879}
1880
fe5b0fdd 1881#ifdef DHCPv6
3dbe2246 1882void
98bd7ca0
DH
1883dhcpv6(struct packet *packet) {
1884 struct iaddrmatchlist *ap;
1885 struct client_state *client;
1886 char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
1887
1888 /* Silently drop bogus messages. */
1889 if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
1890 return;
1891
1892 /* Discard, with log, packets from quenched sources. */
1893 for (ap = packet->interface->client->config->reject_list ;
1894 ap ; ap = ap->next) {
1895 if (addr_match(&packet->client_addr, &ap->match)) {
1896 strcpy(addrbuf, piaddr(packet->client_addr));
1897 log_info("%s from %s rejected by rule %s",
1898 dhcpv6_type_names[packet->dhcpv6_msg_type],
1899 addrbuf,
1900 piaddrmask(&ap->match.addr, &ap->match.mask));
1901 return;
1902 }
1903 }
1904
1905 /* Screen out nonsensical messages. */
1906 switch(packet->dhcpv6_msg_type) {
785c1a51
FD
1907#ifdef DHCP4o6
1908 case DHCPV6_DHCPV4_RESPONSE:
1909 if (dhcpv4_over_dhcpv6) {
1910 log_info("RCV: %s message on %s from %s.",
1911 dhcpv6_type_names[packet->dhcpv6_msg_type],
1912 packet->interface->name,
1913 piaddr(packet->client_addr));
1914 forw_dhcpv4_response(packet);
1915 }
1916 return;
1917#endif
98bd7ca0 1918 case DHCPV6_ADVERTISE:
98bd7ca0 1919 case DHCPV6_RECONFIGURE:
3dbe2246
FD
1920 if (stateless)
1921 return;
1922 /* Falls through */
1923 case DHCPV6_REPLY:
98bd7ca0
DH
1924 log_info("RCV: %s message on %s from %s.",
1925 dhcpv6_type_names[packet->dhcpv6_msg_type],
1926 packet->interface->name, piaddr(packet->client_addr));
1927 break;
1928
1929 default:
1930 return;
1931 }
1932
1933 /* Find a client state that matches the incoming XID. */
1934 for (client = packet->interface->client ; client ;
1935 client = client->next) {
1936 if (memcmp(&client->dhcpv6_transaction_id,
1937 packet->dhcpv6_transaction_id, 3) == 0) {
1938 client->v6_handler(packet, client);
1939 return;
1940 }
1941 }
1942
20ae1aff 1943 /* XXX: temporary log for debugging */
98bd7ca0
DH
1944 log_info("Packet received, but nothing done with it.");
1945}
785c1a51
FD
1946
1947#ifdef DHCP4o6
1948/*
1949 * \brief Forward a DHCPv4-response to the DHCPv4 client.
1950 * (DHCPv6 client function)
1951 *
1952 * The DHCPv6 client receives a DHCPv4-response which is forwarded
1953 * to the DHCPv4 client.
1954 * Format: address:16 + DHCPv4 message content
1955 * (we have no state to keep the address so it is transported in
1956 * DHCPv6 <-> DHCPv6 inter-process messages)
1957 *
1958 * \param packet the DHCPv4-response packet
1959 */
1960static void forw_dhcpv4_response(struct packet *packet)
1961{
1962 struct option_cache *oc;
1963 struct data_string enc_opt_data;
1964 struct data_string ds;
1965 int cc;
1966
1967 /*
1968 * Discard if relay is not ready.
1969 */
1970 if (dhcp4o6_state == -1) {
1971 log_info("forw_dhcpv4_response: not ready.");
1972 return;
1973 }
1974
1975 if (packet->client_addr.len != 16) {
1976 log_error("forw_dhcpv4_response: bad address");
1977 return;
1978 }
1979
1980 /*
1981 * Get our encapsulated DHCPv4 message.
1982 */
1983 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_DHCPV4_MSG);
1984 if (oc == NULL) {
1985 log_info("DHCPv4-response from %s missing "
1986 "DHCPv4 Message option.",
1987 piaddr(packet->client_addr));
1988 return;
1989 }
1990
1991 memset(&enc_opt_data, 0, sizeof(enc_opt_data));
1992 if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL,
1993 NULL, NULL, &global_scope, oc, MDL)) {
1994 log_error("forw_dhcpv4_response: error evaluating "
1995 "DHCPv4 message.");
1996 data_string_forget(&enc_opt_data, MDL);
1997 return;
1998 }
1999
2000 if (enc_opt_data.len < DHCP_FIXED_NON_UDP) {
2001 log_error("forw_dhcpv4_response: "
2002 "no memory for encapsulated packet.");
2003 data_string_forget(&enc_opt_data, MDL);
2004 return;
2005 }
2006
2007 /*
2008 * Append address.
2009 */
2010 memset(&ds, 0, sizeof(ds));
2011 if (!buffer_allocate(&ds.buffer, enc_opt_data.len + 16, MDL)) {
2012 log_error("forw_dhcpv4_response: no memory buffer.");
2013 data_string_forget(&enc_opt_data, MDL);
2014 return;
2015 }
2016 ds.data = ds.buffer->data;
2017 ds.len = enc_opt_data.len + 16;
2018 memcpy(ds.buffer->data, enc_opt_data.data, enc_opt_data.len);
2019 memcpy(ds.buffer->data + enc_opt_data.len,
2020 packet->client_addr.iabuf, 16);
2021 data_string_forget(&enc_opt_data, MDL);
2022
2023 /*
2024 * Forward them.
2025 */
2026 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
2027 if (cc < 0)
2028 log_error("forw_dhcpv4_response: send(): %m");
2029
2030 data_string_forget(&ds, MDL);
2031}
2032
2033/*
2034 * \brief Receive a DHCPv4-response from the DHCPv6 client.
2035 * (DHCPv4 client function)
2036 *
2037 * The DHCPv4 client receives a DHCPv4-response forwarded
2038 * by the DHCPv6 client (using \ref forw_dhcpv4_response())
2039 *
2040 * \param raw the DHCPv4-response raw packet
2041 */
2042static void recv_dhcpv4_response(struct data_string *raw)
2043{
2044 struct packet *packet;
2045 struct iaddr from;
2046
2047 if (interfaces == NULL) {
2048 log_error("recv_dhcpv4_response: no interfaces.");
2049 return;
2050 }
2051
2052 from.len = 16;
2053 memcpy(from.iabuf, raw->data + (raw->len - 16), 16);
2054
2055 /*
2056 * Build a packet structure.
2057 */
2058 packet = NULL;
2059 if (!packet_allocate(&packet, MDL)) {
2060 log_error("recv_dhcpv4_response: no memory for packet.");
2061 return;
2062 }
2063
2064 packet->raw = (struct dhcp_packet *) raw->data;
2065 packet->packet_length = raw->len - 16;
2066 packet->client_port = remote_port;
2067 packet->client_addr = from;
2068 interface_reference(&packet->interface, interfaces, MDL);
2069
2070 /* Allocate packet->options now so it is non-null for all packets */
2071 if (!option_state_allocate (&packet->options, MDL)) {
2072 log_error("recv_dhcpv4_response: no memory for options.");
2073 packet_dereference (&packet, MDL);
2074 return;
2075 }
2076
2077 /* If there's an option buffer, try to parse it. */
2078 if (packet->packet_length >= DHCP_FIXED_NON_UDP + 4) {
2079 struct option_cache *op;
2080 if (!parse_options(packet)) {
2081 if (packet->options)
2082 option_state_dereference
2083 (&packet->options, MDL);
2084 packet_dereference (&packet, MDL);
2085 return;
2086 }
2087
2088 if (packet->options_valid &&
2089 (op = lookup_option(&dhcp_universe,
2090 packet->options,
2091 DHO_DHCP_MESSAGE_TYPE))) {
2092 struct data_string dp;
2093 memset(&dp, 0, sizeof dp);
2094 evaluate_option_cache(&dp, packet, NULL, NULL,
2095 packet->options, NULL,
2096 NULL, op, MDL);
2097 if (dp.len > 0)
2098 packet->packet_type = dp.data[0];
2099 else
2100 packet->packet_type = 0;
2101 data_string_forget(&dp, MDL);
2102 }
2103 }
2104
2105 if (validate_packet(packet) != 0) {
2106 if (packet->packet_type)
2107 dhcp(packet);
2108 else
2109 bootp(packet);
2110 }
2111
2112 /* If the caller kept the packet, they'll have upped the refcnt. */
2113 packet_dereference(&packet, MDL);
2114}
2115#endif /* DHCP4o6 */
fe5b0fdd 2116#endif /* DHCPv6 */
98bd7ca0 2117
c1503c57
TL
2118void dhcpoffer (packet)
2119 struct packet *packet;
95821729 2120{
cc26de46 2121 struct interface_info *ip = packet -> interface;
02d9e453 2122 struct client_state *client;
3354013a 2123 uint32_t v6only_wait;
b00d3884 2124 struct client_lease *lease, *lp;
0c20eab3 2125 struct option **req;
cc26de46 2126 int i;
e16f4c3e 2127 int stop_selecting;
b1b7b521 2128 const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
d758ad8c 2129 char obuf [1024];
be62cf06 2130 struct timeval tv;
3dbe2246 2131
cc26de46 2132#ifdef DEBUG_PACKET
c1503c57 2133 dump_packet (packet);
3dbe2246 2134#endif
cc26de46 2135
02d9e453
TL
2136 /* Find a client state that matches the xid... */
2137 for (client = ip -> client; client; client = client -> next)
2138 if (client -> xid == packet -> raw -> xid)
2139 break;
2140
cc26de46
TL
2141 /* If we're not receptive to an offer right now, or if the offer
2142 has an unrecognizable transaction id, then just drop it. */
02d9e453 2143 if (!client ||
73530742 2144 client -> state != S_SELECTING ||
31730f17 2145 (packet -> interface -> hw_address.hlen - 1 !=
fcaec4ef 2146 packet -> raw -> hlen) ||
31730f17 2147 (memcmp (&packet -> interface -> hw_address.hbuf [1],
fcaec4ef 2148 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2d1b06e0 2149#if defined (DEBUG)
8ae2d595 2150 log_debug ("%s in wrong transaction.", name);
2d1b06e0 2151#endif
cc26de46
TL
2152 return;
2153 }
2154
35e86889
TM
2155 sprintf (obuf, "%s of %s from %s", name,
2156 inet_ntoa(packet->raw->yiaddr),
2157 piaddr(packet->client_addr));
b8cf055d 2158
3354013a
FD
2159 /* Check v6only first. */
2160 v6only_wait = check_v6only(packet, client);
2161 if (v6only_wait > 0) {
2162 log_info("%s: v6 only preferred for %lu.", obuf,
2163 (long unsigned)v6only_wait);
4b705d0d 2164 cancel_timeout(send_discover, client);
3354013a
FD
2165 start_v6only(client, v6only_wait);
2166 return;
2167 }
2168
0c20eab3
DH
2169 /* If this lease doesn't supply the minimum required DHCPv4 parameters,
2170 * ignore it.
2171 */
2172 req = client->config->required_options;
2173 if (req != NULL) {
2174 for (i = 0 ; req[i] != NULL ; i++) {
2175 if ((req[i]->universe == &dhcp_universe) &&
2176 !lookup_option(&dhcp_universe, packet->options,
2177 req[i]->code)) {
2178 struct option *option = NULL;
2179 unsigned code = req[i]->code;
2180
2181 option_code_hash_lookup(&option,
2182 dhcp_universe.code_hash,
2183 &code, 0, MDL);
2184
2185 if (option)
2186 log_info("%s: no %s option.", obuf,
2187 option->name);
2188 else
2189 log_info("%s: no unknown-%u option.",
2190 obuf, code);
f7fdb216 2191
0c20eab3 2192 option_dereference(&option, MDL);
f7fdb216 2193
0c20eab3
DH
2194 return;
2195 }
cc26de46
TL
2196 }
2197 }
2198
2199 /* If we've already seen this lease, don't record it again. */
02d9e453 2200 for (lease = client -> offered_leases; lease; lease = lease -> next) {
cc26de46
TL
2201 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
2202 !memcmp (lease -> address.iabuf,
2203 &packet -> raw -> yiaddr, lease -> address.len)) {
d758ad8c 2204 log_debug ("%s: already seen.", obuf);
cc26de46
TL
2205 return;
2206 }
2207 }
2208
6ceb9118 2209 lease = packet_to_lease (packet, client);
cc26de46 2210 if (!lease) {
d758ad8c 2211 log_info ("%s: packet_to_lease failed.", obuf);
cc26de46
TL
2212 return;
2213 }
2214
35e86889
TM
2215 /* log it now, so it emits before the request goes out */
2216 log_info("%s", obuf);
2217
66f973e4
TL
2218 /* If this lease was acquired through a BOOTREPLY, record that
2219 fact. */
02a015fb 2220 if (!packet -> options_valid || !packet -> packet_type)
66f973e4
TL
2221 lease -> is_bootp = 1;
2222
9bdb9271 2223 /* Record the medium under which this lease was offered. */
02d9e453 2224 lease -> medium = client -> medium;
9bdb9271 2225
b00d3884 2226 /* Figure out when we're supposed to stop selecting. */
02d9e453
TL
2227 stop_selecting = (client -> first_sending +
2228 client -> config -> select_interval);
b00d3884
TL
2229
2230 /* If this is the lease we asked for, put it at the head of the
2231 list, and don't mess with the arp request timeout. */
02d9e453 2232 if (lease -> address.len == client -> requested_address.len &&
b00d3884 2233 !memcmp (lease -> address.iabuf,
02d9e453
TL
2234 client -> requested_address.iabuf,
2235 client -> requested_address.len)) {
2236 lease -> next = client -> offered_leases;
2237 client -> offered_leases = lease;
b00d3884 2238 } else {
b00d3884
TL
2239 /* Put the lease at the end of the list. */
2240 lease -> next = (struct client_lease *)0;
02d9e453
TL
2241 if (!client -> offered_leases)
2242 client -> offered_leases = lease;
b00d3884 2243 else {
02d9e453 2244 for (lp = client -> offered_leases; lp -> next;
b00d3884
TL
2245 lp = lp -> next)
2246 ;
2247 lp -> next = lease;
2248 }
2249 }
2250
cc26de46
TL
2251 /* If the selecting interval has expired, go immediately to
2252 state_selecting(). Otherwise, time out into
2253 state_selecting at the select interval. */
5d082abd 2254 if (stop_selecting <= cur_tv.tv_sec)
d758ad8c 2255 state_selecting (client);
84c4adde 2256 else {
5d082abd
TM
2257 tv.tv_sec = stop_selecting;
2258 tv.tv_usec = cur_tv.tv_usec;
2259 add_timeout(&tv, state_selecting, client, 0, 0);
2260 cancel_timeout(send_discover, client);
84c4adde 2261 }
95821729 2262}
e581d615 2263
cc26de46
TL
2264/* Allocate a client_lease structure and initialize it from the parameters
2265 in the specified packet. */
2266
6ceb9118 2267struct client_lease *packet_to_lease (packet, client)
c1503c57 2268 struct packet *packet;
6ceb9118 2269 struct client_state *client;
e581d615 2270{
cc26de46 2271 struct client_lease *lease;
b5f904a9 2272 unsigned i;
02a015fb 2273 struct option_cache *oc;
f7fdb216 2274 struct option *option = NULL;
02a015fb 2275 struct data_string data;
cc26de46 2276
cf78bf20 2277 lease = (struct client_lease *)new_client_lease (MDL);
cc26de46
TL
2278
2279 if (!lease) {
02b0bdc3
SR
2280 log_error("packet_to_lease: no memory to record lease.\n");
2281 return NULL;
cc26de46
TL
2282 }
2283
02b0bdc3 2284 memset(lease, 0, sizeof(*lease));
cc26de46
TL
2285
2286 /* Copy the lease options. */
02b0bdc3 2287 option_state_reference(&lease->options, packet->options, MDL);
cc26de46 2288
02b0bdc3
SR
2289 lease->address.len = sizeof(packet->raw->yiaddr);
2290 memcpy(lease->address.iabuf, &packet->raw->yiaddr,
2291 lease->address.len);
cc26de46 2292
02b0bdc3
SR
2293 lease->next_srv_addr.len = sizeof(packet->raw->siaddr);
2294 memcpy(lease->next_srv_addr.iabuf, &packet->raw->siaddr,
2295 lease->next_srv_addr.len);
cca6a648 2296
02b0bdc3 2297 memset(&data, 0, sizeof(data));
98311e4b 2298
b5f904a9
TL
2299 if (client -> config -> vendor_space_name) {
2300 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
2301
2302 /* See if there was a vendor encapsulation option. */
2303 oc = lookup_option (&dhcp_universe, lease -> options, i);
b5f904a9
TL
2304 if (oc &&
2305 client -> config -> vendor_space_name &&
66e9cecf
TL
2306 evaluate_option_cache (&data, packet,
2307 (struct lease *)0, client,
b5f904a9
TL
2308 packet -> options, lease -> options,
2309 &global_scope, oc, MDL)) {
2310 if (data.len) {
f7fdb216
DH
2311 if (!option_code_hash_lookup(&option,
2312 dhcp_universe.code_hash,
2313 &i, 0, MDL))
2314 log_fatal("Unable to find VENDOR "
2315 "option (%s:%d).", MDL);
b5f904a9 2316 parse_encapsulated_suboptions
f7fdb216 2317 (packet -> options, option,
b5f904a9
TL
2318 data.data, data.len, &dhcp_universe,
2319 client -> config -> vendor_space_name
2320 );
f7fdb216
DH
2321
2322 option_dereference(&option, MDL);
b5f904a9
TL
2323 }
2324 data_string_forget (&data, MDL);
2325 }
2326 } else
2327 i = 0;
2328
02a015fb 2329 /* Figure out the overload flag. */
230e73e4 2330 oc = lookup_option (&dhcp_universe, lease -> options,
02a015fb 2331 DHO_DHCP_OPTION_OVERLOAD);
02a015fb 2332 if (oc &&
66e9cecf 2333 evaluate_option_cache (&data, packet, (struct lease *)0, client,
0852a27f 2334 packet -> options, lease -> options,
cf78bf20 2335 &global_scope, oc, MDL)) {
02a015fb
TL
2336 if (data.len > 0)
2337 i = data.data [0];
2338 else
2339 i = 0;
cf78bf20 2340 data_string_forget (&data, MDL);
02a015fb
TL
2341 } else
2342 i = 0;
2343
cc26de46 2344 /* If the server name was filled out, copy it. */
02a015fb 2345 if (!(i & 2) && packet -> raw -> sname [0]) {
b1b7b521 2346 unsigned len;
cc26de46 2347 /* Don't count on the NUL terminator. */
e2624b82 2348 for (len = 0; len < DHCP_SNAME_LEN; len++)
cc26de46
TL
2349 if (!packet -> raw -> sname [len])
2350 break;
cf78bf20 2351 lease -> server_name = dmalloc (len + 1, MDL);
cc26de46 2352 if (!lease -> server_name) {
98311e4b 2353 log_error ("dhcpoffer: no memory for server name.\n");
02a015fb 2354 destroy_client_lease (lease);
cc26de46
TL
2355 return (struct client_lease *)0;
2356 } else {
2357 memcpy (lease -> server_name,
2358 packet -> raw -> sname, len);
2359 lease -> server_name [len] = 0;
2360 }
2361 }
2362
2363 /* Ditto for the filename. */
0852a27f 2364 if (!(i & 1) && packet -> raw -> file [0]) {
b1b7b521 2365 unsigned len;
cc26de46 2366 /* Don't count on the NUL terminator. */
e2624b82 2367 for (len = 0; len < DHCP_FILE_LEN; len++)
cc26de46
TL
2368 if (!packet -> raw -> file [len])
2369 break;
cf78bf20 2370 lease -> filename = dmalloc (len + 1, MDL);
cc26de46 2371 if (!lease -> filename) {
8ae2d595 2372 log_error ("dhcpoffer: no memory for filename.\n");
02a015fb 2373 destroy_client_lease (lease);
cc26de46
TL
2374 return (struct client_lease *)0;
2375 } else {
2376 memcpy (lease -> filename,
2377 packet -> raw -> file, len);
2378 lease -> filename [len] = 0;
2379 }
2380 }
89c425dd 2381
a7341359
SR
2382 execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
2383 client, lease->options, lease->options,
2384 &global_scope, client->config->on_receipt,
2385 NULL, NULL);
89c425dd 2386
cc26de46 2387 return lease;
3dbe2246 2388}
e581d615 2389
c1503c57
TL
2390void dhcpnak (packet)
2391 struct packet *packet;
2392{
deff2d59 2393 struct interface_info *ip = packet -> interface;
02d9e453
TL
2394 struct client_state *client;
2395
2396 /* Find a client state that matches the xid... */
2397 for (client = ip -> client; client; client = client -> next)
2398 if (client -> xid == packet -> raw -> xid)
2399 break;
deff2d59 2400
deff2d59
TL
2401 /* If we're not receptive to an offer right now, or if the offer
2402 has an unrecognizable transaction id, then just drop it. */
02d9e453 2403 if (!client ||
31730f17 2404 (packet -> interface -> hw_address.hlen - 1 !=
fcaec4ef 2405 packet -> raw -> hlen) ||
31730f17 2406 (memcmp (&packet -> interface -> hw_address.hbuf [1],
fcaec4ef 2407 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2d1b06e0 2408#if defined (DEBUG)
8ae2d595 2409 log_debug ("DHCPNAK in wrong transaction.");
2d1b06e0 2410#endif
deff2d59
TL
2411 return;
2412 }
2413
02d9e453
TL
2414 if (client -> state != S_REBOOTING &&
2415 client -> state != S_REQUESTING &&
2416 client -> state != S_RENEWING &&
2417 client -> state != S_REBINDING) {
2d1b06e0 2418#if defined (DEBUG)
8ae2d595 2419 log_debug ("DHCPNAK in wrong state.");
2d1b06e0 2420#endif
deff2d59
TL
2421 return;
2422 }
2423
8ae2d595 2424 log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
34fdad6c 2425
02d9e453 2426 if (!client -> active) {
2d1b06e0 2427#if defined (DEBUG)
8ae2d595 2428 log_info ("DHCPNAK with no active lease.\n");
2d1b06e0 2429#endif
deff2d59
TL
2430 return;
2431 }
2432
6cbc6629
DH
2433 /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
2434 * to indicate that we want all old bindings to be removed. (It
2435 * is possible that we may get a NAK while in the RENEW state,
2436 * so we might have bindings active at that time)
2437 */
2438 script_init(client, "EXPIRE", NULL);
2439 script_write_params(client, "old_", client->active);
10613724 2440 script_write_requested(client);
6cbc6629
DH
2441 if (client->alias)
2442 script_write_params(client, "alias_", client->alias);
2443 script_go(client);
2444
02d9e453
TL
2445 destroy_client_lease (client -> active);
2446 client -> active = (struct client_lease *)0;
deff2d59
TL
2447
2448 /* Stop sending DHCPREQUEST packets... */
02d9e453 2449 cancel_timeout (send_request, client);
deff2d59 2450
0a73b7b6
SK
2451 /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
2452 * down (this expunges any routes and arp cache). This makes the
2453 * interface unusable by state_init(), which we call next. So, we
2454 * need to 'PREINIT' the interface to bring it back up.
2455 */
2456 script_init(client, "PREINIT", NULL);
2457 if (client->alias)
2458 script_write_params(client, "alias_", client->alias);
2459 script_go(client);
2460
02d9e453
TL
2461 client -> state = S_INIT;
2462 state_init (client);
e581d615
TL
2463}
2464
cc26de46 2465/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
66f973e4
TL
2466 one after the right interval has expired. If we don't get an offer by
2467 the time we reach the panic interval, call the panic function. */
469cf3a4 2468
02d9e453
TL
2469void send_discover (cpp)
2470 void *cpp;
469cf3a4 2471{
02d9e453 2472 struct client_state *client = cpp;
84c4adde 2473
cc26de46
TL
2474 int result;
2475 int interval;
9bdb9271 2476 int increase = 1;
be62cf06 2477 struct timeval tv;
cc26de46
TL
2478
2479 /* Figure out how long it's been since we started transmitting. */
02d9e453 2480 interval = cur_time - client -> first_sending;
cc26de46
TL
2481
2482 /* If we're past the panic timeout, call the script and tell it
2483 we haven't found anything for this interface yet. */
02d9e453
TL
2484 if (interval > client -> config -> timeout) {
2485 state_panic (client);
b00d3884 2486 return;
cc26de46 2487 }
469cf3a4 2488
9bdb9271
TL
2489 /* If we're selecting media, try the whole list before doing
2490 the exponential backoff, but if we've already received an
2491 offer, stop looping, because we obviously have it right. */
02d9e453
TL
2492 if (!client -> offered_leases &&
2493 client -> config -> media) {
9bdb9271
TL
2494 int fail = 0;
2495 again:
02d9e453
TL
2496 if (client -> medium) {
2497 client -> medium = client -> medium -> next;
9bdb9271 2498 increase = 0;
3dbe2246 2499 }
02d9e453 2500 if (!client -> medium) {
9bdb9271 2501 if (fail)
8ae2d595 2502 log_fatal ("No valid media types for %s!",
02d9e453
TL
2503 client -> interface -> name);
2504 client -> medium =
2505 client -> config -> media;
9bdb9271
TL
2506 increase = 1;
2507 }
3dbe2246 2508
8ae2d595 2509 log_info ("Trying medium \"%s\" %d",
b1423aed 2510 client -> medium -> string, increase);
27be804f
TM
2511 script_init(client, "MEDIUM", client -> medium);
2512 if (script_go(client)) {
b1423aed 2513 fail = 1;
9bdb9271
TL
2514 goto again;
2515 }
2516 }
cc26de46 2517
9bdb9271
TL
2518 /* If we're supposed to increase the interval, do so. If it's
2519 currently zero (i.e., we haven't sent any packets yet), set
98311e4b
DH
2520 it to initial_interval; otherwise, add to it a random number
2521 between zero and two times itself. On average, this means
2522 that it will double with every transmission. */
9bdb9271 2523 if (increase) {
88cd8aca
DH
2524 if (!client->interval)
2525 client->interval = client->config->initial_interval;
b1423aed 2526 else
88cd8aca 2527 client->interval += random() % (2 * client->interval);
cc26de46 2528
34fdad6c 2529 /* Don't backoff past cutoff. */
88cd8aca
DH
2530 if (client->interval > client->config->backoff_cutoff)
2531 client->interval = (client->config->backoff_cutoff / 2)
2532 + (random() % client->config->backoff_cutoff);
2533 } else if (!client->interval)
2534 client->interval = client->config->initial_interval;
3dbe2246 2535
cc26de46
TL
2536 /* If the backoff would take us to the panic timeout, just use that
2537 as the interval. */
02d9e453
TL
2538 if (cur_time + client -> interval >
2539 client -> first_sending + client -> config -> timeout)
2540 client -> interval =
2541 (client -> first_sending +
2542 client -> config -> timeout) - cur_time + 1;
cc26de46 2543
34fdad6c 2544 /* Record the number of seconds since we started sending. */
af6df788
TL
2545 if (interval < 65536)
2546 client -> packet.secs = htons (interval);
34fdad6c 2547 else
af6df788
TL
2548 client -> packet.secs = htons (65535);
2549 client -> secs = client -> packet.secs;
34fdad6c 2550
785c1a51
FD
2551#if defined(DHCPv6) && defined(DHCP4o6)
2552 if (dhcpv4_over_dhcpv6) {
2553 log_info ("DHCPDISCOVER interval %ld",
2554 (long)(client -> interval));
2555 } else
2556#endif
8ae2d595 2557 log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
02d9e453 2558 client -> name ? client -> name : client -> interface -> name,
66f973e4 2559 inet_ntoa (sockaddr_broadcast.sin_addr),
c4661845 2560 ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
66f973e4 2561
cc26de46 2562 /* Send out a packet. */
785c1a51
FD
2563#if defined(DHCPv6) && defined(DHCP4o6)
2564 if (dhcpv4_over_dhcpv6) {
2565 result = send_dhcpv4_query(client, 1);
2566 } else
2567#endif
dd9237c3
TM
2568 result = send_packet(client->interface, NULL, &client->packet,
2569 client->packet_length, inaddr_any,
2570 &sockaddr_broadcast, NULL);
2571 if (result < 0) {
785c1a51
FD
2572#if defined(DHCPv6) && defined(DHCP4o6)
2573 if (dhcpv4_over_dhcpv6) {
2574 log_error("%s:%d: Failed to send %d byte long packet.",
2575 MDL, client->packet_length);
2576 } else
2577#endif
dd9237c3
TM
2578 log_error("%s:%d: Failed to send %d byte long packet over %s "
2579 "interface.", MDL, client->packet_length,
2580 client->interface->name);
2581 }
469cf3a4 2582
5d082abd
TM
2583 /*
2584 * If we used 0 microseconds here, and there were other clients on the
2585 * same network with a synchronized local clock (ntp), and a similar
2586 * zero-microsecond-scheduler behavior, then we could be participating
2587 * in a sub-second DOS ttck.
2588 */
2589 tv.tv_sec = cur_tv.tv_sec + client->interval;
2590 tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
2591 add_timeout(&tv, send_discover, client, 0, 0);
469cf3a4
TL
2592}
2593
0cd94b5e
TM
2594
2595/*
2596 * \brief Remove leases from a list of leases which duplicate a given lease
2597 *
2598 * Searches through a linked-list of leases, remove the first one matches the
2599 * given lease's address and value of is_static. The latter test is done
2600 * so we only remove leases that are from the same source (i.e server/lease file
2601 * vs config file). This ensures we do not discard "fallback" config file leases
2602 * that happen to match non-config file leases.
2603 *
2604 * \param lease_list list of leases to clean
2605 * \param lease lease for which duplicates should be removed
2606 */
2607void discard_duplicate (struct client_lease** lease_list, struct client_lease* lease) {
2608 struct client_lease *cur, *prev, *next;
2609
2610 if (!lease_list || !lease) {
2611 return;
2612 }
2613
2614 prev = (struct client_lease *)0;
2615 for (cur = *lease_list; cur; cur = next) {
2616 next = cur->next;
2617 if ((cur->is_static == lease->is_static) &&
2618 (cur->address.len == lease->address.len &&
2619 !memcmp (cur->address.iabuf, lease->address.iabuf,
2620 lease->address.len))) {
2621 if (prev)
2622 prev->next = next;
2623 else
2624 *lease_list = next;
2625
2626 destroy_client_lease (cur);
2627 break;
2628 } else {
2629 prev = cur;
2630 }
2631 }
2632}
2633
2634/*
2635 * \brief Add a given lease to the end of list of leases
2636 *
2637 * Searches through a linked-list of leases, removing any that match the
2638 * given lease's address and value of is_static. The latter test is done
2639 * so we only remove leases that are from the same source (i.e server/lease file
2640 * vs config file). This ensures we do not discard "fallback" config file leases
2641 * that happen to match non-config file leases.
2642 *
2643 * \param lease_list list of leases to clean
2644 * \param lease lease for which duplicates should be removed
2645 */
2646void add_to_tail(struct client_lease** lease_list,
2647 struct client_lease* lease)
2648{
2649 if (!lease_list || !lease) {
2650 return;
2651 }
2652
2653 /* If there is already a lease for this address and
2654 * is_static value, toss discard it. This ensures
2655 * we only keep one dynamic and/or one static lease
2656 * for a given address. */
2657 discard_duplicate(lease_list, lease);
2658
2659 /* Find the tail */
2660 struct client_lease* tail;
2661 for (tail = *lease_list; tail && tail->next; tail = tail->next){};
2662
2663 /* Ensure the tail points nowhere. */
2664 lease->next = NULL;
2665
2666 /* Add to the tail. */
2667 if (!tail) {
2668 *lease_list = lease;
2669 } else {
2670 tail->next = lease;
2671 }
2672}
2673
2674#if 0
2675void dbg_print_lease(char *text, struct client_lease* lease) {
2676 if (!lease) {
2677 log_debug("%s, lease is null", text);
2678 } else {
2679 log_debug ("%s: %p addr:%s expires:%ld :is_static? %d",
2680 text, lease, piaddr (lease->address),
2681 (lease->expiry - cur_time),
2682 lease->is_static);
2683 }
2684}
2685#endif
2686
b00d3884
TL
2687/* state_panic gets called if we haven't received any offers in a preset
2688 amount of time. When this happens, we try to use existing leases that
2689 haven't yet expired, and failing that, we call the client script and
2690 hope it can do something. */
2691
02d9e453
TL
2692void state_panic (cpp)
2693 void *cpp;
b00d3884 2694{
02d9e453
TL
2695 struct client_state *client = cpp;
2696 struct client_lease *loop;
b00d3884 2697 struct client_lease *lp;
be62cf06 2698 struct timeval tv;
b00d3884 2699
02d9e453
TL
2700 loop = lp = client -> active;
2701
8ae2d595 2702 log_info ("No DHCPOFFERS received.");
b00d3884 2703
deff2d59
TL
2704 /* We may not have an active lease, but we may have some
2705 predefined leases that we can try. */
02d9e453 2706 if (!client -> active && client -> leases)
deff2d59 2707 goto activate_next;
deff2d59 2708
b00d3884 2709 /* Run through the list of leases and see if one can be used. */
02d9e453
TL
2710 while (client -> active) {
2711 if (client -> active -> expiry > cur_time) {
0cd94b5e
TM
2712 log_info ("Trying %s lease %s",
2713 (client -> active -> is_static
2714 ? "fallback" : "recorded"),
2715 piaddr (client -> active -> address));
b00d3884
TL
2716 /* Run the client script with the existing
2717 parameters. */
27be804f 2718 script_init(client, "TIMEOUT",
02d9e453 2719 client -> active -> medium);
27be804f 2720 script_write_params(client, "new_", client -> active);
10613724 2721 script_write_requested(client);
02d9e453 2722 if (client -> alias)
27be804f
TM
2723 script_write_params(client, "alias_",
2724 client -> alias);
b00d3884
TL
2725
2726 /* If the old lease is still good and doesn't
2727 yet need renewal, go into BOUND state and
2728 timeout at the renewal time. */
27be804f 2729 if (!script_go(client)) {
1c016679
TL
2730 if (cur_time < client -> active -> renewal) {
2731 client -> state = S_BOUND;
2732 log_info ("bound: renewal in %ld %s.",
2733 (long)(client -> active -> renewal -
2734 cur_time), "seconds");
5d082abd
TM
2735 tv.tv_sec = client->active->renewal;
2736 tv.tv_usec = ((client->active->renewal -
2737 cur_time) > 1) ?
2738 random() % 1000000 :
2739 cur_tv.tv_usec;
2740 add_timeout(&tv, state_bound, client, 0, 0);
1c016679
TL
2741 } else {
2742 client -> state = S_BOUND;
2743 log_info ("bound: immediate renewal.");
2744 state_bound (client);
2745 }
2746 reinitialize_interfaces ();
29b23207 2747 detach ();
1c016679 2748 return;
b00d3884
TL
2749 }
2750 }
2751
2752 /* If there are no other leases, give up. */
02d9e453
TL
2753 if (!client -> leases) {
2754 client -> leases = client -> active;
2755 client -> active = (struct client_lease *)0;
b00d3884
TL
2756 break;
2757 }
2758
deff2d59 2759 activate_next:
b00d3884
TL
2760 /* Otherwise, put the active lease at the end of the
2761 lease list, and try another lease.. */
0cd94b5e
TM
2762 add_to_tail(&client->leases, client->active);
2763
02d9e453
TL
2764 client -> active = client -> leases;
2765 client -> leases = client -> leases -> next;
b00d3884
TL
2766
2767 /* If we already tried this lease, we've exhausted the
2768 set of leases, so we might as well give up for
2769 now. */
02d9e453 2770 if (client -> active == loop)
b00d3884 2771 break;
66f973e4 2772 else if (!loop)
02d9e453 2773 loop = client -> active;
b00d3884
TL
2774 }
2775
2776 /* No leases were available, or what was available didn't work, so
2777 tell the shell script that we failed to allocate an address,
2778 and try again later. */
c08637bb 2779 if (onetry) {
5c03ed37 2780 if (!quiet) {
c08637bb
TL
2781 log_info ("Unable to obtain a lease on first try.%s",
2782 " Exiting.");
5c03ed37 2783 }
c788d4f8 2784
5c03ed37 2785#if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
c788d4f8
TM
2786 /* Let's call a script and we're done */
2787 script_init(client, "FAIL", (struct string_list *)0);
2788 script_go(client);
5c03ed37 2789#endif
29b23207 2790 finish(2);
c08637bb
TL
2791 }
2792
11373fb6 2793 log_info ("No working leases in persistent database - sleeping.");
27be804f 2794 script_init(client, "FAIL", (struct string_list *)0);
02d9e453 2795 if (client -> alias)
27be804f
TM
2796 script_write_params(client, "alias_", client -> alias);
2797 script_go(client);
02d9e453 2798 client -> state = S_INIT;
5d082abd
TM
2799 tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
2800 (random() % client->config->retry_interval));
2801 tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
2802 random() % 1000000 : cur_tv.tv_usec;
2803 add_timeout(&tv, state_init, client, 0, 0);
29b23207 2804 detach ();
b00d3884
TL
2805}
2806
02d9e453
TL
2807void send_request (cpp)
2808 void *cpp;
e581d615 2809{
02d9e453 2810 struct client_state *client = cpp;
84c4adde 2811
c1503c57 2812 int result;
cc26de46
TL
2813 int interval;
2814 struct sockaddr_in destination;
2815 struct in_addr from;
be62cf06 2816 struct timeval tv;
35e86889
TM
2817 char rip_buf[128];
2818 const char* rip_str = "";
cc26de46
TL
2819
2820 /* Figure out how long it's been since we started transmitting. */
02d9e453 2821 interval = cur_time - client -> first_sending;
cc26de46 2822
34fdad6c
TL
2823 /* If we're in the INIT-REBOOT or REQUESTING state and we're
2824 past the reboot timeout, go to INIT and see if we can
2825 DISCOVER an address... */
2826 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
2827 means either that we're on a network with no DHCP server,
2828 or that our server is down. In the latter case, assuming
2829 that there is a backup DHCP server, DHCPDISCOVER will get
2830 us a new address, but we could also have successfully
2831 reused our old address. In the former case, we're hosed
2832 anyway. This is not a win-prone situation. */
02d9e453
TL
2833 if ((client -> state == S_REBOOTING ||
2834 client -> state == S_REQUESTING) &&
2835 interval > client -> config -> reboot_timeout) {
b8cf055d 2836 cancel:
02d9e453
TL
2837 client -> state = S_INIT;
2838 cancel_timeout (send_request, client);
2839 state_init (client);
deff2d59
TL
2840 return;
2841 }
2842
b8cf055d
TL
2843 /* If we're in the reboot state, make sure the media is set up
2844 correctly. */
02d9e453
TL
2845 if (client -> state == S_REBOOTING &&
2846 !client -> medium &&
2847 client -> active -> medium ) {
27be804f 2848 script_init(client, "MEDIUM", client -> active -> medium);
b8cf055d
TL
2849
2850 /* If the medium we chose won't fly, go to INIT state. */
27be804f 2851 if (script_go(client))
b8cf055d
TL
2852 goto cancel;
2853
2854 /* Record the medium. */
02d9e453 2855 client -> medium = client -> active -> medium;
b8cf055d
TL
2856 }
2857
cc26de46
TL
2858 /* If the lease has expired, relinquish the address and go back
2859 to the INIT state. */
02d9e453
TL
2860 if (client -> state != S_REQUESTING &&
2861 cur_time > client -> active -> expiry) {
cc26de46 2862 /* Run the client script with the new parameters. */
27be804f
TM
2863 script_init(client, "EXPIRE", (struct string_list *)0);
2864 script_write_params(client, "old_", client -> active);
10613724 2865 script_write_requested(client);
02d9e453 2866 if (client -> alias)
27be804f
TM
2867 script_write_params(client, "alias_",
2868 client -> alias);
2869 script_go(client);
02d9e453 2870
62d0cb47
TL
2871 /* Now do a preinit on the interface so that we can
2872 discover a new address. */
27be804f 2873 script_init(client, "PREINIT", (struct string_list *)0);
62d0cb47 2874 if (client -> alias)
27be804f
TM
2875 script_write_params(client, "alias_",
2876 client -> alias);
2877 script_go(client);
62d0cb47 2878
02d9e453
TL
2879 client -> state = S_INIT;
2880 state_init (client);
cc26de46
TL
2881 return;
2882 }
2883
2884 /* Do the exponential backoff... */
02d9e453
TL
2885 if (!client -> interval)
2886 client -> interval = client -> config -> initial_interval;
34fdad6c 2887 else {
02d9e453
TL
2888 client -> interval += ((random () >> 2) %
2889 (2 * client -> interval));
34fdad6c 2890 }
3dbe2246 2891
34fdad6c 2892 /* Don't backoff past cutoff. */
02d9e453
TL
2893 if (client -> interval >
2894 client -> config -> backoff_cutoff)
2895 client -> interval =
2896 ((client -> config -> backoff_cutoff / 2)
98311e4b
DH
2897 + ((random () >> 2) %
2898 client -> config -> backoff_cutoff));
cc26de46
TL
2899
2900 /* If the backoff would take us to the expiry time, just set the
2901 timeout to the expiry time. */
02d9e453
TL
2902 if (client -> state != S_REQUESTING &&
2903 cur_time + client -> interval > client -> active -> expiry)
2904 client -> interval =
2905 client -> active -> expiry - cur_time + 1;
cc26de46
TL
2906
2907 /* If the lease T2 time has elapsed, or if we're not yet bound,
2908 broadcast the DHCPREQUEST rather than unicasting. */
02d9e453 2909 if (client -> state == S_REQUESTING ||
62d0cb47 2910 client -> state == S_REBOOTING ||
02d9e453 2911 cur_time > client -> active -> rebind)
3020a2c1 2912 destination.sin_addr = sockaddr_broadcast.sin_addr;
cc26de46
TL
2913 else
2914 memcpy (&destination.sin_addr.s_addr,
02d9e453 2915 client -> destination.iabuf,
cc26de46
TL
2916 sizeof destination.sin_addr.s_addr);
2917 destination.sin_port = remote_port;
b00d3884
TL
2918 destination.sin_family = AF_INET;
2919#ifdef HAVE_SA_LEN
2920 destination.sin_len = sizeof destination;
2921#endif
cc26de46 2922
7d3bc735
TL
2923 if (client -> state == S_RENEWING ||
2924 client -> state == S_REBINDING)
02d9e453 2925 memcpy (&from, client -> active -> address.iabuf,
cc26de46
TL
2926 sizeof from);
2927 else
2928 from.s_addr = INADDR_ANY;
2929
34fdad6c 2930 /* Record the number of seconds since we started sending. */
af6df788
TL
2931 if (client -> state == S_REQUESTING)
2932 client -> packet.secs = client -> secs;
2933 else {
2934 if (interval < 65536)
2935 client -> packet.secs = htons (interval);
2936 else
2937 client -> packet.secs = htons (65535);
2938 }
34fdad6c 2939
785c1a51
FD
2940#if defined(DHCPv6) && defined(DHCP4o6)
2941 if (dhcpv4_over_dhcpv6) {
2942 log_info ("DHCPREQUEST");
2943 } else
2944#endif
35e86889
TM
2945 memset(rip_buf, 0x0, sizeof(rip_buf));
2946 if (client->state == S_BOUND || client->state == S_RENEWING ||
2947 client->state == S_REBINDING) {
2948 rip_str = inet_ntoa(client->packet.ciaddr);
2949 } else {
2950 rip_str = piaddr(client->requested_address);
2951 }
2952
2953 strncpy(rip_buf, rip_str, sizeof(rip_buf)-1);
2954 log_info ("DHCPREQUEST for %s on %s to %s port %d", rip_buf,
2955 client->name ? client->name : client->interface->name,
2956 inet_ntoa(destination.sin_addr),
2957 ntohs (destination.sin_port));
cc26de46 2958
785c1a51
FD
2959#if defined(DHCPv6) && defined(DHCP4o6)
2960 if (dhcpv4_over_dhcpv6) {
2961 int broadcast = 0;
2962 if (destination.sin_addr.s_addr == INADDR_BROADCAST)
2963 broadcast = 1;
2964 result = send_dhcpv4_query(client, broadcast);
2965 if (result < 0) {
2966 log_error("%s:%d: Failed to send %d byte long packet.",
2967 MDL, client->packet_length);
2968 }
2969 } else
2970#endif
62d0cb47 2971 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
dd9237c3
TM
2972 fallback_interface) {
2973 result = send_packet(fallback_interface, NULL, &client->packet,
2974 client->packet_length, from, &destination,
2975 NULL);
2976 if (result < 0) {
2977 log_error("%s:%d: Failed to send %d byte long packet "
2978 "over %s interface.", MDL,
2979 client->packet_length,
2980 fallback_interface->name);
2981 }
2982 }
2983 else {
cc26de46 2984 /* Send out a packet. */
dd9237c3
TM
2985 result = send_packet(client->interface, NULL, &client->packet,
2986 client->packet_length, from, &destination,
2987 NULL);
2988 if (result < 0) {
2989 log_error("%s:%d: Failed to send %d byte long packet"
2990 " over %s interface.", MDL,
2991 client->packet_length,
2992 client->interface->name);
2993 }
2994 }
469cf3a4 2995
5d082abd
TM
2996 tv.tv_sec = cur_tv.tv_sec + client->interval;
2997 tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
2998 random() % 1000000 : cur_tv.tv_usec;
2999 add_timeout(&tv, send_request, client, 0, 0);
469cf3a4
TL
3000}
3001
02d9e453
TL
3002void send_decline (cpp)
3003 void *cpp;
b00d3884 3004{
02d9e453 3005 struct client_state *client = cpp;
84c4adde 3006
b00d3884
TL
3007 int result;
3008
785c1a51
FD
3009#if defined(DHCPv6) && defined(DHCP4o6)
3010 if (dhcpv4_over_dhcpv6) {
3011 log_info ("DHCPDECLINE");
3012 } else
3013#endif
35e86889
TM
3014 log_info ("DHCPDECLINE of %s on %s to %s port %d",
3015 piaddr(client->requested_address),
3016 (client->name ? client->name : client->interface->name),
3017 inet_ntoa(sockaddr_broadcast.sin_addr),
3018 ntohs(sockaddr_broadcast.sin_port));
b00d3884
TL
3019
3020 /* Send out a packet. */
785c1a51
FD
3021#if defined(DHCPv6) && defined(DHCP4o6)
3022 if (dhcpv4_over_dhcpv6) {
3023 result = send_dhcpv4_query(client, 1);
3024 } else
3025#endif
dd9237c3
TM
3026 result = send_packet(client->interface, NULL, &client->packet,
3027 client->packet_length, inaddr_any,
3028 &sockaddr_broadcast, NULL);
3029 if (result < 0) {
785c1a51
FD
3030#if defined(DHCPv6) && defined(DHCP4o6)
3031 if (dhcpv4_over_dhcpv6) {
3032 log_error("%s:%d: Failed to send %d byte long packet.",
3033 MDL, client->packet_length);
3034 } else
3035#endif
dd9237c3
TM
3036 log_error("%s:%d: Failed to send %d byte long packet over %s"
3037 " interface.", MDL, client->packet_length,
3038 client->interface->name);
3039 }
b00d3884
TL
3040}
3041
02d9e453
TL
3042void send_release (cpp)
3043 void *cpp;
b00d3884 3044{
02d9e453 3045 struct client_state *client = cpp;
84c4adde 3046
b00d3884 3047 int result;
007e3ee4
TL
3048 struct sockaddr_in destination;
3049 struct in_addr from;
3050
3051 memcpy (&from, client -> active -> address.iabuf,
3052 sizeof from);
3053 memcpy (&destination.sin_addr.s_addr,
3054 client -> destination.iabuf,
3055 sizeof destination.sin_addr.s_addr);
3056 destination.sin_port = remote_port;
3057 destination.sin_family = AF_INET;
3058#ifdef HAVE_SA_LEN
3059 destination.sin_len = sizeof destination;
3060#endif
3061
007e3ee4
TL
3062 /* Set the lease to end now, so that we don't accidentally
3063 reuse it if we restart before the old expiry time. */
3064 client -> active -> expiry =
3065 client -> active -> renewal =
3066 client -> active -> rebind = cur_time;
3067 if (!write_client_lease (client, client -> active, 1, 1)) {
3068 log_error ("Can't release lease: lease write failed.");
3069 return;
3070 }
b00d3884 3071
785c1a51
FD
3072#if defined(DHCPv6) && defined(DHCP4o6)
3073 if (dhcpv4_over_dhcpv6) {
3074 log_info ("DHCPRELEASE");
3075 } else
3076#endif
35e86889
TM
3077 log_info ("DHCPRELEASE of %s on %s to %s port %d",
3078 piaddr(client->active->address),
3079 client->name ? client->name : client->interface->name,
3080 inet_ntoa (destination.sin_addr),
3081 ntohs (destination.sin_port));
b00d3884 3082
785c1a51
FD
3083#if defined(DHCPv6) && defined(DHCP4o6)
3084 if (dhcpv4_over_dhcpv6) {
3085 int broadcast = 0;
3086 if (destination.sin_addr.s_addr == INADDR_BROADCAST)
3087 broadcast = 1;
3088 result = send_dhcpv4_query(client, broadcast);
3089 if (result < 0) {
3090 log_error("%s:%d: Failed to send %d byte long packet.",
3091 MDL, client->packet_length);
3092 }
3093 } else
3094#endif
dd9237c3
TM
3095 if (fallback_interface) {
3096 result = send_packet(fallback_interface, NULL, &client->packet,
3097 client->packet_length, from, &destination,
3098 NULL);
3099 if (result < 0) {
3100 log_error("%s:%d: Failed to send %d byte long packet"
3101 " over %s interface.", MDL,
3102 client->packet_length,
3103 fallback_interface->name);
3104 }
3105 } else {
007e3ee4 3106 /* Send out a packet. */
dd9237c3
TM
3107 result = send_packet(client->interface, NULL, &client->packet,
3108 client->packet_length, from, &destination,
3109 NULL);
3110 if (result < 0) {
3111 log_error ("%s:%d: Failed to send %d byte long packet"
3112 " over %s interface.", MDL,
3113 client->packet_length,
3114 client->interface->name);
3115 }
3116
3117 }
b00d3884
TL
3118}
3119
785c1a51
FD
3120#if defined(DHCPv6) && defined(DHCP4o6)
3121/*
3122 * \brief Send a DHCPv4-query to the DHCPv6 client
3123 * (DHCPv4 client function)
3124 *
3125 * The DHCPv4 client sends a DHCPv4-query to the DHCPv6 client over
3126 * the inter-process communication socket.
3127 *
3128 * \param client the DHCPv4 client state
3129 * \param broadcast the broadcast flag
3130 * \return the sent byte count (-1 on error)
3131 */
3132static int send_dhcpv4_query(struct client_state *client, int broadcast) {
3133 struct data_string ds;
3134 struct dhcpv4_over_dhcpv6_packet *query;
3135 int ofs, len, cc;
3136
3137 if (dhcp4o6_state <= 0) {
3138 log_info("send_dhcpv4_query: not ready.");
3139 return -1;
3140 }
3141
3142 /*
3143 * Compute buffer length and allocate it.
3144 */
3145 len = ofs = (int)(offsetof(struct dhcpv4_over_dhcpv6_packet, options));
3146 len += dhcpv6_universe.tag_size + dhcpv6_universe.length_size;
3147 len += client->packet_length;
3148 memset(&ds, 0, sizeof(ds));
3149 if (!buffer_allocate(&ds.buffer, len, MDL)) {
3150 log_error("Unable to allocate memory for DHCPv4-query.");
3151 return -1;
3152 }
3153 ds.data = ds.buffer->data;
3154 ds.len = len;
3155
3156 /*
3157 * Fill header.
3158 */
3159 query = (struct dhcpv4_over_dhcpv6_packet *)ds.data;
3160 query->msg_type = DHCPV6_DHCPV4_QUERY;
3161 query->flags[0] = query->flags[1] = query->flags[2] = 0;
3162 if (!broadcast)
3163 query->flags[0] |= DHCP4O6_QUERY_UNICAST;
3164
3165 /*
3166 * Append DHCPv4 message.
3167 */
3168 dhcpv6_universe.store_tag(ds.buffer->data + ofs, D6O_DHCPV4_MSG);
3169 ofs += dhcpv6_universe.tag_size;
3170 dhcpv6_universe.store_length(ds.buffer->data + ofs,
3171 client->packet_length);
3172 ofs += dhcpv6_universe.length_size;
3173 memcpy(ds.buffer->data + ofs, &client->packet, client->packet_length);
3174
3175 /*
3176 * Send DHCPv6 message.
3177 */
3178 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
3179 if (cc < 0)
3180 log_error("send_dhcpv4_query: send(): %m");
3181
3182 data_string_forget(&ds, MDL);
3183
3184 return cc;
3185}
3186
3187/*
3188 * \brief Forward a DHCPv4-query to all DHCPv4 over DHCPv6 server addresses.
3189 * (DHCPv6 client function)
3190 *
3191 * \param raw the DHCPv6 DHCPv4-query message raw content
3192 */
3193static void forw_dhcpv4_query(struct data_string *raw) {
3194 struct interface_info *ip;
3195 struct client_state *client;
3196 struct dhc6_lease *lease;
3197 struct option_cache *oc;
3198 struct data_string addrs;
3199 struct sockaddr_in6 sin6;
3200 int i, send_ret, attempt, success;
3201
3202 attempt = success = 0;
3203 memset(&sin6, 0, sizeof(sin6));
3204 sin6.sin6_family = AF_INET6;
3205 sin6.sin6_port = remote_port;
3206#ifdef HAVE_SA_LEN
3207 sin6.sin6_len = sizeof(sin6);
3208#endif
3209 memset(&addrs, 0, sizeof(addrs));
3210 for (ip = interfaces; ip != NULL; ip = ip->next) {
3211 for (client = ip->client; client != NULL;
3212 client = client->next) {
3213 if ((client->state != S_BOUND) &&
3214 (client->state != S_RENEWING) &&
3215 (client->state != S_REBINDING))
3216 continue;
3217 lease = client->active_lease;
3218 if ((lease == NULL) || lease->released)
3219 continue;
3220 oc = lookup_option(&dhcpv6_universe,
3221 lease->options,
3222 D6O_DHCP4_O_DHCP6_SERVER);
3223 if ((oc == NULL) ||
3224 !evaluate_option_cache(&addrs, NULL, NULL, NULL,
3225 lease->options, NULL,
3226 &global_scope, oc, MDL) ||
3227 ((addrs.len % sizeof(sin6.sin6_addr)) != 0)) {
3228 data_string_forget(&addrs, MDL);
3229 continue;
3230 }
3231 if (addrs.len == 0) {
3232 /* note there is nothing to forget */
3233 inet_pton(AF_INET6,
3234 All_DHCP_Relay_Agents_and_Servers,
3235 &sin6.sin6_addr);
3236 attempt++;
3237 send_ret = send_packet6(ip, raw->data,
3238 raw->len, &sin6);
3239 if (send_ret == raw->len)
3240 success++;
3241 continue;
3242 }
3243 for (i = 0; i < addrs.len;
3244 i += sizeof(sin6.sin6_addr)) {
3245 memcpy(&sin6.sin6_addr, addrs.data + i,
3246 sizeof(sin6.sin6_addr));
3247 attempt++;
3248 send_ret = send_packet6(ip, raw->data,
3249 raw->len, &sin6);
3250 if (send_ret == raw->len)
3251 success++;
3252 }
3253 data_string_forget(&addrs, MDL);
3254 }
3255 }
3256
3257 log_info("forw_dhcpv4_query: sent(%d): %d/%d",
3258 raw->len, success, attempt);
3259
3260 if (attempt == 0)
3261 dhcp4o6_stop();
3262}
3263#endif
3264
0c20eab3
DH
3265void
3266make_client_options(struct client_state *client, struct client_lease *lease,
3267 u_int8_t *type, struct option_cache *sid,
3268 struct iaddr *rip, struct option **prl,
3269 struct option_state **op)
469cf3a4 3270{
b1b7b521 3271 unsigned i;
02a015fb 3272 struct option_cache *oc;
f7fdb216 3273 struct option *option = NULL;
d7d9c0c7 3274 struct buffer *bp = NULL;
02a015fb 3275
d758ad8c
TL
3276 /* If there are any leftover options, get rid of them. */
3277 if (*op)
d7d9c0c7 3278 option_state_dereference(op, MDL);
d758ad8c 3279
230e73e4 3280 /* Allocate space for options. */
d7d9c0c7 3281 option_state_allocate(op, MDL);
02a015fb
TL
3282
3283 /* Send the server identifier if provided. */
3284 if (sid)
d7d9c0c7 3285 save_option(&dhcp_universe, *op, sid);
02a015fb 3286
d7d9c0c7 3287 oc = NULL;
2455808f 3288
02a015fb
TL
3289 /* Send the requested address if provided. */
3290 if (rip) {
d7d9c0c7 3291 client->requested_address = *rip;
f7fdb216
DH
3292 i = DHO_DHCP_REQUESTED_ADDRESS;
3293 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
3294 &i, 0, MDL) &&
3295 make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
3296 option, MDL)))
230e73e4 3297 log_error ("can't make requested address cache.");
02a015fb 3298 else {
d7d9c0c7
SR
3299 save_option(&dhcp_universe, *op, oc);
3300 option_cache_dereference(&oc, MDL);
02a015fb 3301 }
f7fdb216 3302 option_dereference(&option, MDL);
b00d3884 3303 } else {
d7d9c0c7 3304 client->requested_address.len = 0;
cc26de46 3305 }
c1503c57 3306
f7fdb216
DH
3307 i = DHO_DHCP_MESSAGE_TYPE;
3308 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
3309 MDL) &&
3310 make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
d7d9c0c7 3311 log_error("can't make message type.");
02a015fb 3312 else {
d7d9c0c7
SR
3313 save_option(&dhcp_universe, *op, oc);
3314 option_cache_dereference(&oc, MDL);
02a015fb 3315 }
f7fdb216 3316 option_dereference(&option, MDL);
02a015fb
TL
3317
3318 if (prl) {
0c20eab3
DH
3319 int len;
3320
3321 /* Probe the length of the list. */
3322 len = 0;
3323 for (i = 0 ; prl[i] != NULL ; i++)
3324 if (prl[i]->universe == &dhcp_universe)
3325 len++;
3326
d7d9c0c7
SR
3327 if (!buffer_allocate(&bp, len, MDL))
3328 log_error("can't make parameter list buffer.");
02a015fb 3329 else {
d6614ea2
DH
3330 unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
3331
0c20eab3
DH
3332 len = 0;
3333 for (i = 0 ; prl[i] != NULL ; i++)
3334 if (prl[i]->universe == &dhcp_universe)
3335 bp->data[len++] = prl[i]->code;
3336
f7fdb216
DH
3337 if (!(option_code_hash_lookup(&option,
3338 dhcp_universe.code_hash,
d6614ea2 3339 &code, 0, MDL) &&
0c20eab3 3340 make_const_option_cache(&oc, &bp, NULL, len,
b05e05b7
SR
3341 option, MDL))) {
3342 if (bp != NULL)
3343 buffer_dereference(&bp, MDL);
3344 log_error ("can't make option cache");
3345 } else {
d7d9c0c7
SR
3346 save_option(&dhcp_universe, *op, oc);
3347 option_cache_dereference(&oc, MDL);
02a015fb 3348 }
f7fdb216 3349 option_dereference(&option, MDL);
deff2d59
TL
3350 }
3351 }
3352
d7d9c0c7
SR
3353 /*
3354 * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
3355 * This can be overridden by including a client id in the configuration
3356 * file.
3357 */
3358 if (duid_v4 == 1) {
3359 struct data_string client_identifier;
3360 int hw_idx, hw_len;
3361
3362 memset(&client_identifier, 0, sizeof(client_identifier));
3363 client_identifier.len = 1 + 4 + default_duid.len;
3364 if (!buffer_allocate(&client_identifier.buffer,
3365 client_identifier.len, MDL))
3366 log_fatal("no memory for default DUID!");
3367 client_identifier.data = client_identifier.buffer->data;
3368
3369 i = DHO_DHCP_CLIENT_IDENTIFIER;
3370
3371 /* Client-identifier type : 1 byte */
3372 *client_identifier.buffer->data = 255;
cca6a648 3373
d7d9c0c7
SR
3374 /* IAID : 4 bytes
3375 * we use the low 4 bytes from the interface address
3376 */
3377 if (client->interface->hw_address.hlen > 4) {
3378 hw_idx = client->interface->hw_address.hlen - 4;
3379 hw_len = 4;
3380 } else {
3381 hw_idx = 0;
3382 hw_len = client->interface->hw_address.hlen;
3383 }
3384 memcpy(&client_identifier.buffer->data + 5 - hw_len,
3385 client->interface->hw_address.hbuf + hw_idx,
3386 hw_len);
cca6a648 3387
d7d9c0c7
SR
3388 /* Add the default duid */
3389 memcpy(&client_identifier.buffer->data+(1+4),
3390 default_duid.data, default_duid.len);
3391
3392 /* And save the option */
3393 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
3394 &i, 0, MDL) &&
3395 make_const_option_cache(&oc, NULL,
3396 (u_int8_t *)client_identifier.data,
3397 client_identifier.len,
3398 option, MDL)))
3399 log_error ("can't make requested client id cache..");
3400 else {
3401 save_option (&dhcp_universe, *op, oc);
3402 option_cache_dereference (&oc, MDL);
3403 }
3404 option_dereference(&option, MDL);
3405 }
3406
02a015fb 3407 /* Run statements that need to be run on transmission. */
a7341359
SR
3408 if (client->config->on_transmission)
3409 execute_statements_in_scope(NULL, NULL, NULL, client,
3410 (lease ? lease->options : NULL),
3411 *op, &global_scope,
3412 client->config->on_transmission,
3413 NULL, NULL);
02a015fb
TL
3414}
3415
02d9e453
TL
3416void make_discover (client, lease)
3417 struct client_state *client;
02a015fb
TL
3418 struct client_lease *lease;
3419{
02a015fb 3420 unsigned char discover = DHCPDISCOVER;
230e73e4 3421 struct option_state *options = (struct option_state *)0;
02a015fb 3422
02d9e453 3423 memset (&client -> packet, 0, sizeof (client -> packet));
02a015fb 3424
02d9e453
TL
3425 make_client_options (client,
3426 lease, &discover, (struct option_cache *)0,
02a015fb 3427 lease ? &lease -> address : (struct iaddr *)0,
02d9e453 3428 client -> config -> requested_options,
02a015fb
TL
3429 &options);
3430
c1503c57 3431 /* Set up the option buffer... */
02d9e453 3432 client -> packet_length =
da38df14 3433 cons_options ((struct packet *)0, &client -> packet,
98311e4b
DH
3434 (struct lease *)0, client,
3435 /* maximum packet size */1500,
3436 (struct option_state *)0,
3437 options,
3438 /* scope */ &global_scope,
3439 /* overload */ 0,
3440 /* terminate */0,
3441 /* bootpp */0,
3442 (struct data_string *)0,
ce75142f 3443 client -> config -> vendor_space_name);
98311e4b
DH
3444
3445 option_state_dereference (&options, MDL);
02d9e453
TL
3446 if (client -> packet_length < BOOTP_MIN_LEN)
3447 client -> packet_length = BOOTP_MIN_LEN;
3448
3449 client -> packet.op = BOOTREQUEST;
31730f17 3450 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
785c1a51 3451 /* Assumes hw_address is known, otherwise a random value may result */
31730f17 3452 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02d9e453
TL
3453 client -> packet.hops = 0;
3454 client -> packet.xid = random ();
3455 client -> packet.secs = 0; /* filled in by send_discover. */
f345b36d
TL
3456
3457 if (can_receive_unicast_unconfigured (client -> interface))
3458 client -> packet.flags = 0;
3459 else
3460 client -> packet.flags = htons (BOOTP_BROADCAST);
3461
02d9e453
TL
3462 memset (&(client -> packet.ciaddr),
3463 0, sizeof client -> packet.ciaddr);
3464 memset (&(client -> packet.yiaddr),
3465 0, sizeof client -> packet.yiaddr);
3466 memset (&(client -> packet.siaddr),
3467 0, sizeof client -> packet.siaddr);
11373fb6 3468 client -> packet.giaddr = giaddr;
31730f17
TL
3469 if (client -> interface -> hw_address.hlen > 0)
3470 memcpy (client -> packet.chaddr,
3471 &client -> interface -> hw_address.hbuf [1],
3472 (unsigned)(client -> interface -> hw_address.hlen - 1));
c1503c57
TL
3473
3474#ifdef DEBUG_PACKET
01aeb18a 3475 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
c1503c57 3476#endif
c1503c57
TL
3477}
3478
469cf3a4 3479
02d9e453
TL
3480void make_request (client, lease)
3481 struct client_state *client;
cc26de46 3482 struct client_lease *lease;
c1503c57 3483{
c1503c57 3484 unsigned char request = DHCPREQUEST;
02a015fb 3485 struct option_cache *oc;
c1503c57 3486
02d9e453 3487 memset (&client -> packet, 0, sizeof (client -> packet));
469cf3a4 3488
02d9e453 3489 if (client -> state == S_REQUESTING)
230e73e4 3490 oc = lookup_option (&dhcp_universe, lease -> options,
02a015fb
TL
3491 DHO_DHCP_SERVER_IDENTIFIER);
3492 else
3493 oc = (struct option_cache *)0;
8dba80a6 3494
98311e4b
DH
3495 if (client -> sent_options)
3496 option_state_dereference (&client -> sent_options, MDL);
3497
02d9e453
TL
3498 make_client_options (client, lease, &request, oc,
3499 ((client -> state == S_REQUESTING ||
3500 client -> state == S_REBOOTING)
02a015fb
TL
3501 ? &lease -> address
3502 : (struct iaddr *)0),
02d9e453 3503 client -> config -> requested_options,
d758ad8c 3504 &client -> sent_options);
deff2d59 3505
c1503c57 3506 /* Set up the option buffer... */
02d9e453 3507 client -> packet_length =
da38df14 3508 cons_options ((struct packet *)0, &client -> packet,
98311e4b
DH
3509 (struct lease *)0, client,
3510 /* maximum packet size */1500,
3511 (struct option_state *)0,
3dbe2246 3512 client -> sent_options,
98311e4b
DH
3513 /* scope */ &global_scope,
3514 /* overload */ 0,
3515 /* terminate */0,
3516 /* bootpp */0,
3517 (struct data_string *)0,
ce75142f 3518 client -> config -> vendor_space_name);
98311e4b 3519
02d9e453
TL
3520 if (client -> packet_length < BOOTP_MIN_LEN)
3521 client -> packet_length = BOOTP_MIN_LEN;
cc26de46 3522
02d9e453 3523 client -> packet.op = BOOTREQUEST;
31730f17 3524 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
785c1a51 3525 /* Assumes hw_address is known, otherwise a random value may result */
31730f17 3526 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02d9e453
TL
3527 client -> packet.hops = 0;
3528 client -> packet.xid = client -> xid;
3529 client -> packet.secs = 0; /* Filled in by send_request. */
cc26de46
TL
3530
3531 /* If we own the address we're requesting, put it in ciaddr;
3532 otherwise set ciaddr to zero. */
02d9e453
TL
3533 if (client -> state == S_BOUND ||
3534 client -> state == S_RENEWING ||
62d0cb47 3535 client -> state == S_REBINDING) {
02d9e453 3536 memcpy (&client -> packet.ciaddr,
cc26de46 3537 lease -> address.iabuf, lease -> address.len);
339b0231 3538 client -> packet.flags = 0;
62d0cb47 3539 } else {
02d9e453
TL
3540 memset (&client -> packet.ciaddr, 0,
3541 sizeof client -> packet.ciaddr);
f345b36d
TL
3542 if (can_receive_unicast_unconfigured (client -> interface))
3543 client -> packet.flags = 0;
3544 else
3545 client -> packet.flags = htons (BOOTP_BROADCAST);
62d0cb47 3546 }
02d9e453
TL
3547
3548 memset (&client -> packet.yiaddr, 0,
3549 sizeof client -> packet.yiaddr);
3550 memset (&client -> packet.siaddr, 0,
3551 sizeof client -> packet.siaddr);
1c44f6bd
TL
3552 if (client -> state != S_BOUND &&
3553 client -> state != S_RENEWING)
3554 client -> packet.giaddr = giaddr;
3555 else
3556 memset (&client -> packet.giaddr, 0,
3557 sizeof client -> packet.giaddr);
31730f17
TL
3558 if (client -> interface -> hw_address.hlen > 0)
3559 memcpy (client -> packet.chaddr,
3560 &client -> interface -> hw_address.hbuf [1],
3561 (unsigned)(client -> interface -> hw_address.hlen - 1));
c1503c57
TL
3562
3563#ifdef DEBUG_PACKET
01aeb18a 3564 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
c1503c57 3565#endif
469cf3a4 3566}
c1503c57 3567
02d9e453
TL
3568void make_decline (client, lease)
3569 struct client_state *client;
cc26de46 3570 struct client_lease *lease;
469cf3a4 3571{
cc26de46 3572 unsigned char decline = DHCPDECLINE;
02a015fb 3573 struct option_cache *oc;
c1503c57 3574
230e73e4 3575 struct option_state *options = (struct option_state *)0;
c1503c57 3576
40ec5f38 3577 /* Create the options cache. */
230e73e4 3578 oc = lookup_option (&dhcp_universe, lease -> options,
02a015fb 3579 DHO_DHCP_SERVER_IDENTIFIER);
0c20eab3
DH
3580 make_client_options(client, lease, &decline, oc, &lease->address,
3581 NULL, &options);
ca25f4ab 3582
40ec5f38 3583 /* Consume the options cache into the option buffer. */
230e73e4 3584 memset (&client -> packet, 0, sizeof (client -> packet));
02d9e453 3585 client -> packet_length =
da38df14 3586 cons_options ((struct packet *)0, &client -> packet,
66e9cecf 3587 (struct lease *)0, client, 0,
0852a27f 3588 (struct option_state *)0, options,
ce75142f
TL
3589 &global_scope, 0, 0, 0, (struct data_string *)0,
3590 client -> config -> vendor_space_name);
40ec5f38
DH
3591
3592 /* Destroy the options cache. */
98311e4b 3593 option_state_dereference (&options, MDL);
40ec5f38 3594
02d9e453
TL
3595 if (client -> packet_length < BOOTP_MIN_LEN)
3596 client -> packet_length = BOOTP_MIN_LEN;
cc26de46 3597
02d9e453 3598 client -> packet.op = BOOTREQUEST;
31730f17 3599 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
785c1a51 3600 /* Assumes hw_address is known, otherwise a random value may result */
31730f17 3601 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02d9e453
TL
3602 client -> packet.hops = 0;
3603 client -> packet.xid = client -> xid;
3604 client -> packet.secs = 0; /* Filled in by send_request. */
7d3bc735
TL
3605 if (can_receive_unicast_unconfigured (client -> interface))
3606 client -> packet.flags = 0;
3607 else
3608 client -> packet.flags = htons (BOOTP_BROADCAST);
cc26de46
TL
3609
3610 /* ciaddr must always be zero. */
02d9e453
TL
3611 memset (&client -> packet.ciaddr, 0,
3612 sizeof client -> packet.ciaddr);
3613 memset (&client -> packet.yiaddr, 0,
3614 sizeof client -> packet.yiaddr);
3615 memset (&client -> packet.siaddr, 0,
3616 sizeof client -> packet.siaddr);
11373fb6 3617 client -> packet.giaddr = giaddr;
02d9e453 3618 memcpy (client -> packet.chaddr,
31730f17 3619 &client -> interface -> hw_address.hbuf [1],
02d9e453 3620 client -> interface -> hw_address.hlen);
cc26de46
TL
3621
3622#ifdef DEBUG_PACKET
01aeb18a 3623 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
cc26de46
TL
3624#endif
3625}
3626
02d9e453
TL
3627void make_release (client, lease)
3628 struct client_state *client;
cc26de46
TL
3629 struct client_lease *lease;
3630{
3631 unsigned char request = DHCPRELEASE;
02a015fb 3632 struct option_cache *oc;
cc26de46 3633
230e73e4 3634 struct option_state *options = (struct option_state *)0;
cc26de46 3635
02d9e453 3636 memset (&client -> packet, 0, sizeof (client -> packet));
469cf3a4 3637
230e73e4 3638 oc = lookup_option (&dhcp_universe, lease -> options,
02a015fb 3639 DHO_DHCP_SERVER_IDENTIFIER);
0c20eab3 3640 make_client_options(client, lease, &request, oc, NULL, NULL, &options);
469cf3a4
TL
3641
3642 /* Set up the option buffer... */
02d9e453 3643 client -> packet_length =
da38df14 3644 cons_options ((struct packet *)0, &client -> packet,
98311e4b
DH
3645 (struct lease *)0, client,
3646 /* maximum packet size */1500,
3647 (struct option_state *)0,
3648 options,
3649 /* scope */ &global_scope,
3650 /* overload */ 0,
3651 /* terminate */0,
3652 /* bootpp */0,
3653 (struct data_string *)0,
ce75142f 3654 client -> config -> vendor_space_name);
98311e4b 3655
02d9e453
TL
3656 if (client -> packet_length < BOOTP_MIN_LEN)
3657 client -> packet_length = BOOTP_MIN_LEN;
cf78bf20 3658 option_state_dereference (&options, MDL);
02d9e453
TL
3659
3660 client -> packet.op = BOOTREQUEST;
31730f17 3661 client -> packet.htype = client -> interface -> hw_address.hbuf [0];
785c1a51 3662 /* Assumes hw_address is known, otherwise a random value may result */
31730f17 3663 client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02d9e453 3664 client -> packet.hops = 0;
74f45f96 3665 client -> packet.xid = random ();
02d9e453
TL
3666 client -> packet.secs = 0;
3667 client -> packet.flags = 0;
3668 memcpy (&client -> packet.ciaddr,
cc26de46 3669 lease -> address.iabuf, lease -> address.len);
02d9e453
TL
3670 memset (&client -> packet.yiaddr, 0,
3671 sizeof client -> packet.yiaddr);
3672 memset (&client -> packet.siaddr, 0,
3673 sizeof client -> packet.siaddr);
11373fb6 3674 client -> packet.giaddr = giaddr;
02d9e453 3675 memcpy (client -> packet.chaddr,
bdcaf7b9 3676 &client -> interface -> hw_address.hbuf [1],
02d9e453 3677 client -> interface -> hw_address.hlen);
469cf3a4
TL
3678
3679#ifdef DEBUG_PACKET
01aeb18a 3680 dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
469cf3a4 3681#endif
e581d615 3682}
cc26de46 3683
02a015fb 3684void destroy_client_lease (lease)
cc26de46
TL
3685 struct client_lease *lease;
3686{
cc26de46 3687 if (lease -> server_name)
cf78bf20 3688 dfree (lease -> server_name, MDL);
cc26de46 3689 if (lease -> filename)
cf78bf20
TL
3690 dfree (lease -> filename, MDL);
3691 option_state_dereference (&lease -> options, MDL);
3692 free_client_lease (lease, MDL);
cc26de46
TL
3693}
3694
98bd7ca0
DH
3695FILE *leaseFile = NULL;
3696int leases_written = 0;
cc26de46
TL
3697
3698void rewrite_client_leases ()
3699{
3700 struct interface_info *ip;
02d9e453 3701 struct client_state *client;
cc26de46
TL
3702 struct client_lease *lp;
3703
98bd7ca0 3704 if (leaseFile != NULL)
cc26de46
TL
3705 fclose (leaseFile);
3706 leaseFile = fopen (path_dhclient_db, "w");
98bd7ca0 3707 if (leaseFile == NULL) {
ee8a3653
TL
3708 log_error ("can't create %s: %m", path_dhclient_db);
3709 return;
3710 }
b00d3884 3711
98bd7ca0
DH
3712 /* If there is a default duid, write it out. */
3713 if (default_duid.len != 0)
3714 write_duid(&default_duid);
3715
b00d3884
TL
3716 /* Write out all the leases attached to configured interfaces that
3717 we know about. */
cc26de46 3718 for (ip = interfaces; ip; ip = ip -> next) {
02d9e453
TL
3719 for (client = ip -> client; client; client = client -> next) {
3720 for (lp = client -> leases; lp; lp = lp -> next) {
007e3ee4 3721 write_client_lease (client, lp, 1, 0);
02d9e453
TL
3722 }
3723 if (client -> active)
3724 write_client_lease (client,
007e3ee4 3725 client -> active, 1, 0);
98bd7ca0
DH
3726
3727 if (client->active_lease != NULL)
3728 write_client6_lease(client,
3729 client->active_lease,
3730 1, 0);
5d082abd
TM
3731
3732 /* Reset last_write after rewrites. */
3733 client->last_write = 0;
cc26de46 3734 }
cc26de46 3735 }
b00d3884
TL
3736
3737 /* Write out any leases that are attached to interfaces that aren't
3738 currently configured. */
3739 for (ip = dummy_interfaces; ip; ip = ip -> next) {
02d9e453
TL
3740 for (client = ip -> client; client; client = client -> next) {
3741 for (lp = client -> leases; lp; lp = lp -> next) {
007e3ee4 3742 write_client_lease (client, lp, 1, 0);
02d9e453
TL
3743 }
3744 if (client -> active)
3745 write_client_lease (client,
007e3ee4 3746 client -> active, 1, 0);
98bd7ca0
DH
3747
3748 if (client->active_lease != NULL)
3749 write_client6_lease(client,
3750 client->active_lease,
3751 1, 0);
5d082abd
TM
3752
3753 /* Reset last_write after rewrites. */
3754 client->last_write = 0;
b00d3884 3755 }
b00d3884 3756 }
cc26de46
TL
3757 fflush (leaseFile);
3758}
3759
c0504523
TL
3760void write_lease_option (struct option_cache *oc,
3761 struct packet *packet, struct lease *lease,
66e9cecf 3762 struct client_state *client_state,
c0504523
TL
3763 struct option_state *in_options,
3764 struct option_state *cfg_options,
3765 struct binding_scope **scope,
3766 struct universe *u, void *stuff)
3767{
3768 const char *name, *dot;
3769 struct data_string ds;
98bd7ca0 3770 char *preamble = stuff;
b5f904a9 3771
c0504523
TL
3772 memset (&ds, 0, sizeof ds);
3773
3774 if (u != &dhcp_universe) {
3775 name = u -> name;
3776 dot = ".";
3777 } else {
3778 name = "";
3779 dot = "";
3780 }
66e9cecf 3781 if (evaluate_option_cache (&ds, packet, lease, client_state,
c0504523 3782 in_options, cfg_options, scope, oc, MDL)) {
35de6c8c
SR
3783 /* The option name */
3784 fprintf(leaseFile, "%soption %s%s%s", preamble,
3785 name, dot, oc->option->name);
3786
3787 /* The option value if there is one */
3788 if ((oc->option->format == NULL) ||
3789 (oc->option->format[0] != 'Z')) {
3790 fprintf(leaseFile, " %s",
3791 pretty_print_option(oc->option, ds.data,
3792 ds.len, 1, 1));
3793 }
3794
3795 /* The closing semi-colon and newline */
3796 fprintf(leaseFile, ";\n");
3797
c0504523
TL
3798 data_string_forget (&ds, MDL);
3799 }
3800}
3801
98bd7ca0
DH
3802/* Write an option cache to the lease store. */
3803static void
3804write_options(struct client_state *client, struct option_state *options,
06eb8bab 3805 const char *preamble)
98bd7ca0
DH
3806{
3807 int i;
3808
3809 for (i = 0; i < options->universe_count; i++) {
3810 option_space_foreach(NULL, NULL, client, NULL, options,
3dbe2246 3811 &global_scope, universes[i],
06eb8bab 3812 (char *)preamble, write_lease_option);
98bd7ca0
DH
3813 }
3814}
3815
d7d9c0c7
SR
3816/*
3817 * The "best" default DUID, since we cannot predict any information
3818 * about the system (such as whether or not the hardware addresses are
3819 * integrated into the motherboard or similar), is the "LLT", link local
3820 * plus time, DUID. For real stateless "LL" is better.
3821 *
3822 * Once generated, this duid is stored into the state database, and
3823 * retained across restarts.
3824 *
3825 * For the time being, there is probably a different state database for
3826 * every daemon, so this winds up being a per-interface identifier...which
3827 * is not how it is intended. Upcoming rearchitecting the client should
3828 * address this "one daemon model."
3829 */
3830void
3831form_duid(struct data_string *duid, const char *file, int line)
3832{
3833 struct interface_info *ip;
3834 int len;
79818c93 3835 char *str;
d7d9c0c7
SR
3836
3837 /* For now, just use the first interface on the list. */
3838 ip = interfaces;
3839
3840 if (ip == NULL)
3841 log_fatal("Impossible condition at %s:%d.", MDL);
3842
3843 if ((ip->hw_address.hlen == 0) ||
3844 (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
3845 log_fatal("Impossible hardware address length at %s:%d.", MDL);
3846
3847 if (duid_type == 0)
3848 duid_type = stateless ? DUID_LL : DUID_LLT;
3849
3850 /*
3851 * 2 bytes for the 'duid type' field.
3852 * 2 bytes for the 'htype' field.
3853 * (DUID_LLT) 4 bytes for the 'current time'.
3854 * enough bytes for the hardware address (note that hw_address has
3855 * the 'htype' on byte zero).
3856 */
3857 len = 4 + (ip->hw_address.hlen - 1);
3858 if (duid_type == DUID_LLT)
3859 len += 4;
3860 if (!buffer_allocate(&duid->buffer, len, MDL))
3861 log_fatal("no memory for default DUID!");
3862 duid->data = duid->buffer->data;
3863 duid->len = len;
3864
3865 /* Basic Link Local Address type of DUID. */
3866 if (duid_type == DUID_LLT) {
3867 putUShort(duid->buffer->data, DUID_LLT);
3868 putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
3869 putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
3870 memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
3871 ip->hw_address.hlen - 1);
3872 } else {
3873 putUShort(duid->buffer->data, DUID_LL);
3874 putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
3875 memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
3876 ip->hw_address.hlen - 1);
3877 }
79818c93 3878
cc1bd34e
TM
3879 /* Now format the output based on lease-id-format */
3880 str = format_lease_id(duid->data, duid->len,
3881 top_level_config.lease_id_format, MDL);
3882 if (str == NULL) {
3883 log_info("form_duid: Couldn't allocate memory to log duid!");
3884 } else {
79818c93
SR
3885 log_info("Created duid %s.", str);
3886 dfree(str, MDL);
3887 }
d7d9c0c7
SR
3888}
3889
98bd7ca0
DH
3890/* Write the default DUID to the lease store. */
3891static isc_result_t
3892write_duid(struct data_string *duid)
3893{
3894 char *str;
3895 int stat;
3896
3897 if ((duid == NULL) || (duid->len <= 2))
98bf1607 3898 return DHCP_R_INVALIDARG;
98bd7ca0
DH
3899
3900 if (leaseFile == NULL) { /* XXX? */
3901 leaseFile = fopen(path_dhclient_db, "w");
3902 if (leaseFile == NULL) {
3903 log_error("can't create %s: %m", path_dhclient_db);
3904 return ISC_R_IOERROR;
3905 }
3906 }
3907
cc1bd34e
TM
3908 /* Generate a formatted duid string per lease-id-format */
3909 str = format_lease_id(duid->data, duid->len,
3910 top_level_config.lease_id_format, MDL);
98bd7ca0
DH
3911 if (str == NULL)
3912 return ISC_R_NOMEMORY;
3913
cc1bd34e 3914 stat = fprintf(leaseFile, "default-duid %s;\n", str);
98bd7ca0
DH
3915 dfree(str, MDL);
3916 if (stat <= 0)
3917 return ISC_R_IOERROR;
3918
3919 if (fflush(leaseFile) != 0)
3920 return ISC_R_IOERROR;
6705543f
DH
3921
3922 return ISC_R_SUCCESS;
98bd7ca0
DH
3923}
3924
3925/* Write a DHCPv6 lease to the store. */
3926isc_result_t
3927write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
3928 int rewrite, int sync)
3929{
3930 struct dhc6_ia *ia;
3931 struct dhc6_addr *addr;
3932 int stat;
1d9774ab 3933 const char *ianame;
98bd7ca0
DH
3934
3935 /* This should include the current lease. */
3936 if (!rewrite && (leases_written++ > 20)) {
3937 rewrite_client_leases();
3938 leases_written = 0;
3939 return ISC_R_SUCCESS;
3940 }
3941
3942 if (client == NULL || lease == NULL)
98bf1607 3943 return DHCP_R_INVALIDARG;
98bd7ca0
DH
3944
3945 if (leaseFile == NULL) { /* XXX? */
3946 leaseFile = fopen(path_dhclient_db, "w");
3947 if (leaseFile == NULL) {
3948 log_error("can't create %s: %m", path_dhclient_db);
3949 return ISC_R_IOERROR;
3950 }
3951 }
3952
3953 stat = fprintf(leaseFile, "lease6 {\n");
3954 if (stat <= 0)
3955 return ISC_R_IOERROR;
3956
3957 stat = fprintf(leaseFile, " interface \"%s\";\n",
3958 client->interface->name);
3959 if (stat <= 0)
3960 return ISC_R_IOERROR;
3961
3962 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
1d9774ab
FD
3963 switch (ia->ia_type) {
3964 case D6O_IA_NA:
3965 default:
3966 ianame = "ia-na";
3967 break;
3968 case D6O_IA_TA:
3969 ianame = "ia-ta";
3970 break;
3971 case D6O_IA_PD:
3972 ianame = "ia-pd";
3973 break;
3974 }
cc1bd34e
TM
3975
3976 /* For some reason IAID was never octal or hex, but string or
3977 * hex. Go figure. So for compatibilty's sake we will either
3978 * do hex or "legacy" i.e string rather than octal. What a
3979 * cluster. */
3980 switch(top_level_config.lease_id_format) {
3981 case TOKEN_HEX: {
3982 char* iaid_str = format_lease_id(
3983 (const unsigned char *) &ia->iaid, 4,
3984 top_level_config.lease_id_format, MDL);
3985
3986 if (!iaid_str) {
3987 log_error("Can't format iaid");
3988 return ISC_R_IOERROR;
3989 }
3990
3991 stat = fprintf(leaseFile, " %s %s {\n",
3992 ianame, iaid_str);
3993 dfree(iaid_str, MDL);
3994 break;
3995 }
3996
3997 case TOKEN_OCTAL:
3998 default:
3999 stat = fprintf(leaseFile, " %s %s {\n", ianame,
4000 print_hex_1(4, ia->iaid, 12));
4001 break;
4002 }
4003
98bd7ca0
DH
4004 if (stat <= 0)
4005 return ISC_R_IOERROR;
4006
1d9774ab
FD
4007 if (ia->ia_type != D6O_IA_TA)
4008 stat = fprintf(leaseFile, " starts %d;\n"
4009 " renew %u;\n"
4010 " rebind %u;\n",
4011 (int)ia->starts, ia->renew, ia->rebind);
4012 else
4013 stat = fprintf(leaseFile, " starts %d;\n",
4014 (int)ia->starts);
98bd7ca0
DH
4015 if (stat <= 0)
4016 return ISC_R_IOERROR;
4017
4018 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
1d9774ab
FD
4019 if (ia->ia_type != D6O_IA_PD)
4020 stat = fprintf(leaseFile,
4021 " iaaddr %s {\n",
4022 piaddr(addr->address));
4023 else
4024 stat = fprintf(leaseFile,
4025 " iaprefix %s/%d {\n",
4026 piaddr(addr->address),
4027 (int)addr->plen);
98bd7ca0
DH
4028 if (stat <= 0)
4029 return ISC_R_IOERROR;
4030
4031 stat = fprintf(leaseFile, " starts %d;\n"
4032 " preferred-life %u;\n"
4033 " max-life %u;\n",
6705543f 4034 (int)addr->starts, addr->preferred_life,
98bd7ca0
DH
4035 addr->max_life);
4036 if (stat <= 0)
4037 return ISC_R_IOERROR;
4038
4039 if (addr->options != NULL)
4040 write_options(client, addr->options, " ");
4041
4042 stat = fprintf(leaseFile, " }\n");
4043 if (stat <= 0)
4044 return ISC_R_IOERROR;
4045 }
4046
4047 if (ia->options != NULL)
4048 write_options(client, ia->options, " ");
4049
4050 stat = fprintf(leaseFile, " }\n");
4051 if (stat <= 0)
4052 return ISC_R_IOERROR;
4053 }
4054
cabdb9b1
FD
4055 if (lease->released) {
4056 stat = fprintf(leaseFile, " released;\n");
4057 if (stat <= 0)
4058 return ISC_R_IOERROR;
4059 }
4060
98bd7ca0
DH
4061 if (lease->options != NULL)
4062 write_options(client, lease->options, " ");
4063
4064 stat = fprintf(leaseFile, "}\n");
4065 if (stat <= 0)
4066 return ISC_R_IOERROR;
4067
4068 if (fflush(leaseFile) != 0)
4069 return ISC_R_IOERROR;
4070
4071 if (sync) {
4072 if (fsync(fileno(leaseFile)) < 0) {
4073 log_error("write_client_lease: fsync(): %m");
4074 return ISC_R_IOERROR;
4075 }
4076 }
6705543f
DH
4077
4078 return ISC_R_SUCCESS;
98bd7ca0
DH
4079}
4080
007e3ee4 4081int write_client_lease (client, lease, rewrite, makesure)
02d9e453 4082 struct client_state *client;
cc26de46 4083 struct client_lease *lease;
5c2f78b4 4084 int rewrite;
007e3ee4 4085 int makesure;
cc26de46 4086{
02a015fb 4087 struct data_string ds;
007e3ee4 4088 int errors = 0;
dd215f30 4089 char *s;
5e864416 4090 const char *tval;
5c2f78b4
TL
4091
4092 if (!rewrite) {
4093 if (leases_written++ > 20) {
4094 rewrite_client_leases ();
4095 leases_written = 0;
4096 }
4097 }
cc26de46 4098
b00d3884
TL
4099 /* If the lease came from the config file, we don't need to stash
4100 a copy in the lease database. */
4101 if (lease -> is_static)
007e3ee4 4102 return 1;
b00d3884 4103
98bd7ca0 4104 if (leaseFile == NULL) { /* XXX */
cc26de46 4105 leaseFile = fopen (path_dhclient_db, "w");
98bd7ca0 4106 if (leaseFile == NULL) {
ee8a3653
TL
4107 log_error ("can't create %s: %m", path_dhclient_db);
4108 return 0;
4109 }
cc26de46
TL
4110 }
4111
007e3ee4 4112 errno = 0;
cc26de46 4113 fprintf (leaseFile, "lease {\n");
dd215f30 4114 if (lease -> is_bootp) {
66f973e4 4115 fprintf (leaseFile, " bootp;\n");
dd215f30
TL
4116 if (errno) {
4117 ++errors;
4118 errno = 0;
4119 }
4120 }
02d9e453
TL
4121 fprintf (leaseFile, " interface \"%s\";\n",
4122 client -> interface -> name);
dd215f30
TL
4123 if (errno) {
4124 ++errors;
4125 errno = 0;
4126 }
4127 if (client -> name) {
02d9e453 4128 fprintf (leaseFile, " name \"%s\";\n", client -> name);
dd215f30
TL
4129 if (errno) {
4130 ++errors;
4131 errno = 0;
4132 }
4133 }
cc26de46
TL
4134 fprintf (leaseFile, " fixed-address %s;\n",
4135 piaddr (lease -> address));
dd215f30
TL
4136 if (errno) {
4137 ++errors;
4138 errno = 0;
4139 }
4140 if (lease -> filename) {
4141 s = quotify_string (lease -> filename, MDL);
4142 if (s) {
4143 fprintf (leaseFile, " filename \"%s\";\n", s);
4144 if (errno) {
4145 ++errors;
4146 errno = 0;
4147 }
4148 dfree (s, MDL);
4149 } else
4150 errors++;
4151
4152 }
23e10d37
DH
4153 if (lease->server_name != NULL) {
4154 s = quotify_string(lease->server_name, MDL);
4155 if (s != NULL) {
4156 fprintf(leaseFile, " server-name \"%s\";\n", s);
dd215f30
TL
4157 if (errno) {
4158 ++errors;
4159 errno = 0;
4160 }
23e10d37 4161 dfree(s, MDL);
dd215f30
TL
4162 } else
4163 ++errors;
4164 }
4165 if (lease -> medium) {
4166 s = quotify_string (lease -> medium -> string, MDL);
4167 if (s) {
4168 fprintf (leaseFile, " medium \"%s\";\n", s);
4169 if (errno) {
4170 ++errors;
4171 errno = 0;
4172 }
4173 dfree (s, MDL);
4174 } else
4175 errors++;
4176 }
007e3ee4
TL
4177 if (errno != 0) {
4178 errors++;
4179 errno = 0;
4180 }
2455808f
TL
4181
4182 memset (&ds, 0, sizeof ds);
230e73e4 4183
98bd7ca0 4184 write_options(client, lease->options, " ");
5c2f78b4 4185
5e864416
DH
4186 tval = print_time(lease->renewal);
4187 if (tval == NULL ||
4188 fprintf(leaseFile, " renew %s\n", tval) < 0)
dd215f30 4189 errors++;
5e864416
DH
4190
4191 tval = print_time(lease->rebind);
4192 if (tval == NULL ||
4193 fprintf(leaseFile, " rebind %s\n", tval) < 0)
dd215f30 4194 errors++;
5e864416
DH
4195
4196 tval = print_time(lease->expiry);
4197 if (tval == NULL ||
4198 fprintf(leaseFile, " expire %s\n", tval) < 0)
dd215f30 4199 errors++;
5e864416
DH
4200
4201 if (fprintf(leaseFile, "}\n") < 0)
dd215f30 4202 errors++;
5e864416
DH
4203
4204 if (fflush(leaseFile) != 0)
007e3ee4 4205 errors++;
5e864416 4206
5d082abd
TM
4207 client->last_write = cur_time;
4208
007e3ee4
TL
4209 if (!errors && makesure) {
4210 if (fsync (fileno (leaseFile)) < 0) {
4211 log_info ("write_client_lease: %m");
4212 return 0;
4213 }
4214 }
5d082abd 4215
007e3ee4 4216 return errors ? 0 : 1;
cc26de46
TL
4217}
4218
4219/* Variables holding name of script and file pointer for writing to
4220 script. Needless to say, this is not reentrant - only one script
4221 can be invoked at a time. */
4222char scriptName [256];
4223FILE *scriptFile;
4224
27be804f
TM
4225/**
4226 * @brief Initializes basic variables for a script
4227 *
4228 * This function is called as an initial preparation for calling a script.
4229 * It sets up a number of common env. variables that will be passed to
4230 * the script. For actual script calling, see @ref script_go .
4231 *
4232 * @param client variables will be stored here (if null, the whole function
4233 * is no-op)
4234 * @param reason specified the reason for calling a script (must be non-null)
4235 * @param medium if specified, defines medium type (may be null)
4236 */
4237void script_init(struct client_state *client, const char *reason,
4238 struct string_list *medium)
cc26de46 4239{
32a47563 4240 struct string_list *sl, *next;
cc26de46 4241
02d9e453 4242 if (client) {
32a47563
TL
4243 for (sl = client -> env; sl; sl = next) {
4244 next = sl -> next;
4245 dfree (sl, MDL);
4246 }
4247 client -> env = (struct string_list *)0;
4248 client -> envc = 0;
3dbe2246 4249
02d9e453 4250 if (client -> interface) {
32a47563
TL
4251 client_envadd (client, "", "interface", "%s",
4252 client -> interface -> name);
02d9e453
TL
4253 }
4254 if (client -> name)
32a47563
TL
4255 client_envadd (client,
4256 "", "client", "%s", client -> name);
4257 if (medium)
4258 client_envadd (client,
4259 "", "medium", "%s", medium -> string);
4260
4261 client_envadd (client, "", "reason", "%s", reason);
6f7081bd 4262 client_envadd (client, "", "pid", "%ld", (long int)getpid ());
3e88222f 4263#if defined(DHCPv6)
a68ec967
MS
4264 client_envadd (client, "", "dad_wait_time", "%ld",
4265 (long int)dad_wait_time);
3e88222f 4266#endif
9bdb9271 4267 }
cc26de46
TL
4268}
4269
c0504523
TL
4270void client_option_envadd (struct option_cache *oc,
4271 struct packet *packet, struct lease *lease,
66e9cecf 4272 struct client_state *client_state,
c0504523
TL
4273 struct option_state *in_options,
4274 struct option_state *cfg_options,
4275 struct binding_scope **scope,
4276 struct universe *u, void *stuff)
4277{
4278 struct envadd_state *es = stuff;
4279 struct data_string data;
4280 memset (&data, 0, sizeof data);
4281
66e9cecf 4282 if (evaluate_option_cache (&data, packet, lease, client_state,
c0504523
TL
4283 in_options, cfg_options, scope, oc, MDL)) {
4284 if (data.len) {
4285 char name [256];
4286 if (dhcp_option_ev_name (name, sizeof name,
bea17697
SR
4287 oc->option)) {
4288 const char *value;
1405aa2d 4289 size_t length;
bea17697
SR
4290 value = pretty_print_option(oc->option,
4291 data.data,
4292 data.len, 0, 0);
1405aa2d 4293 length = strlen(value);
bea17697
SR
4294
4295 if (check_option_values(oc->option->universe,
4296 oc->option->code,
4297 value, length) == 0) {
4298 client_envadd(es->client, es->prefix,
4299 name, "%s", value);
4300 } else {
4301 log_error("suspect value in %s "
4302 "option - discarded",
4303 name);
4304 }
c0504523
TL
4305 }
4306 }
0cd94b5e
TM
4307
4308 data_string_forget (&data, MDL);
c0504523
TL
4309 }
4310}
4311
27be804f
TM
4312/**
4313 * @brief Adds parameters to environment variables for a script
4314 *
4315 * This function add details of specified lease to a list of env. variables
4316 * to be passed to a script. The lease details will be prepended with
4317 * specified prefix (e.g. "old_") and added to the list stored in client.
4318 * Following variables may be set:
4319 * - ip_address
4320 * - next_server
4321 * - network_number
4322 * - broadcast_address
4323 * - filename
4324 * - server_name
4325 * - expiry
4326 *
4327 * @param client env. variables will be stored here
4328 * @param prefix textual prefix to be added to each variable (e.g. "old_")
4329 * @param lease lease details will be extracted from here
4330 */
4331void script_write_params(struct client_state *client, const char *prefix,
4332 struct client_lease *lease)
cc26de46
TL
4333{
4334 int i;
02a015fb
TL
4335 struct data_string data;
4336 struct option_cache *oc;
c0504523
TL
4337 struct envadd_state es;
4338
4339 es.client = client;
4340 es.prefix = prefix;
cc26de46 4341
32a47563
TL
4342 client_envadd (client,
4343 prefix, "ip_address", "%s", piaddr (lease -> address));
c6abd205 4344
02b0bdc3
SR
4345 /* If we've set the next server address in the lease structure
4346 put it into an environment variable for the script */
4347 if (lease->next_srv_addr.len != 0) {
4348 client_envadd(client, prefix, "next_server", "%s",
4349 piaddr(lease->next_srv_addr));
4350 }
4351
c6abd205
TL
4352 /* For the benefit of Linux (and operating systems which may
4353 have similar needs), compute the network address based on
4354 the supplied ip address and netmask, if provided. Also
4355 compute the broadcast address (the host address all ones
4356 broadcast address, not the host address all zeroes
4357 broadcast address). */
4358
02a015fb 4359 memset (&data, 0, sizeof data);
230e73e4 4360 oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
66e9cecf
TL
4361 if (oc && evaluate_option_cache (&data, (struct packet *)0,
4362 (struct lease *)0, client,
0852a27f 4363 (struct option_state *)0,
da38df14 4364 lease -> options,
cf78bf20 4365 &global_scope, oc, MDL)) {
02a015fb
TL
4366 if (data.len > 3) {
4367 struct iaddr netmask, subnet, broadcast;
4368
8a4e543b
DH
4369 /*
4370 * No matter the length of the subnet-mask option,
4371 * use only the first four octets. Note that
4372 * subnet-mask options longer than 4 octets are not
4373 * in conformance with RFC 2132, but servers with this
4374 * flaw do exist.
4375 */
4376 memcpy(netmask.iabuf, data.data, 4);
4377 netmask.len = 4;
cf78bf20 4378 data_string_forget (&data, MDL);
02a015fb
TL
4379
4380 subnet = subnet_number (lease -> address, netmask);
4381 if (subnet.len) {
32a47563
TL
4382 client_envadd (client, prefix, "network_number",
4383 "%s", piaddr (subnet));
4384
4385 oc = lookup_option (&dhcp_universe,
4386 lease -> options,
4387 DHO_BROADCAST_ADDRESS);
4388 if (!oc ||
4389 !(evaluate_option_cache
4390 (&data, (struct packet *)0,
66e9cecf 4391 (struct lease *)0, client,
32a47563
TL
4392 (struct option_state *)0,
4393 lease -> options,
4394 &global_scope, oc, MDL))) {
4395 broadcast = broadcast_addr (subnet, netmask);
4396 if (broadcast.len) {
4397 client_envadd (client,
4398 prefix, "broadcast_address",
a8c190df 4399 "%s", piaddr (broadcast));
c6abd205 4400 }
32a47563 4401 }
c6abd205
TL
4402 }
4403 }
cf78bf20 4404 data_string_forget (&data, MDL);
c6abd205
TL
4405 }
4406
bea17697
SR
4407 if (lease->filename) {
4408 if (check_option_values(NULL, DHO_ROOT_PATH,
4409 lease->filename,
4410 strlen(lease->filename)) == 0) {
4411 client_envadd(client, prefix, "filename",
4412 "%s", lease->filename);
4413 } else {
4414 log_error("suspect value in %s "
4415 "option - discarded",
4416 lease->filename);
4417 }
4418 }
4419
4420 if (lease->server_name) {
4421 if (check_option_values(NULL, DHO_HOST_NAME,
4422 lease->server_name,
4423 strlen(lease->server_name)) == 0 ) {
4424 client_envadd (client, prefix, "server_name",
4425 "%s", lease->server_name);
4426 } else {
4427 log_error("suspect value in %s "
4428 "option - discarded",
4429 lease->server_name);
4430 }
4431 }
02a015fb 4432
c0504523
TL
4433 for (i = 0; i < lease -> options -> universe_count; i++) {
4434 option_space_foreach ((struct packet *)0, (struct lease *)0,
66e9cecf 4435 client, (struct option_state *)0,
c0504523
TL
4436 lease -> options, &global_scope,
4437 universes [i],
4438 &es, client_option_envadd);
cc26de46 4439 }
86bda88b
TM
4440
4441 client_envadd (client, prefix, "expiry", "%lu",
4442 (unsigned long)(lease -> expiry));
cc26de46
TL
4443}
4444
27be804f
TM
4445/**
4446 * @brief Write out the environent variable the client requested.
10613724
SR
4447 * Write out the environment variables for the objects that the
4448 * client requested. If the object was requested the variable will be:
4449 * requested_<option_name>=1
4450 * If it wasn't requested there won't be a variable.
27be804f
TM
4451 *
4452 * @param client client structure
10613724 4453 */
27be804f 4454void script_write_requested(struct client_state *client)
10613724
SR
4455{
4456 int i;
4457 struct option **req;
4458 char name[256];
4459 req = client->config->requested_options;
4460
4461 if (req == NULL)
4462 return;
4463
4464 for (i = 0 ; req[i] != NULL ; i++) {
4465 if ((req[i]->universe == &dhcp_universe) &&
4466 dhcp_option_ev_name(name, sizeof(name), req[i])) {
4467 client_envadd(client, "requested_", name, "%d", 1);
4468 }
4469 }
4470}
4471
27be804f
TM
4472/**
4473 * @brief Calls external script.
4474 *
4475 * External script is specified either using -sf command line or
4476 * script parameter in the configuration file.
4477 *
4478 * @param client specifies client information (environment variables,
4479 * and other parameters will be extracted and passed to the script.
4480 * @return If positive, it contains exit code of the process running script.
4481 * If negative, returns the signal number that cause the script process
4482 * to terminate.
4483 */
4484int script_go(struct client_state *client)
cc26de46 4485{
32a47563
TL
4486 char *scriptName;
4487 char *argv [2];
4488 char **envp;
32a47563
TL
4489 char reason [] = "REASON=NBI";
4490 static char client_path [] = CLIENT_PATH;
4491 int i;
4492 struct string_list *sp, *next;
4493 int pid, wpid, wstatus;
cc26de46 4494
b1423aed 4495 if (client)
32a47563 4496 scriptName = client -> config -> script_name;
b1423aed
TL
4497 else
4498 scriptName = top_level_config.script_name;
4499
4500 envp = dmalloc (((client ? client -> envc : 2) +
4501 client_env_count + 2) * sizeof (char *), MDL);
4502 if (!envp) {
4503 log_error ("No memory for client script environment.");
4504 return 0;
4505 }
4506 i = 0;
4507 /* Copy out the environment specified on the command line,
4508 if any. */
4509 for (sp = client_env; sp; sp = sp -> next) {
4510 envp [i++] = sp -> string;
4511 }
4512 /* Copy out the environment specified by dhclient. */
4513 if (client) {
32a47563
TL
4514 for (sp = client -> env; sp; sp = sp -> next) {
4515 envp [i++] = sp -> string;
4516 }
32a47563 4517 } else {
b1423aed 4518 envp [i++] = reason;
32a47563 4519 }
b1423aed
TL
4520 /* Set $PATH. */
4521 envp [i++] = client_path;
4522 envp [i] = (char *)0;
32a47563
TL
4523
4524 argv [0] = scriptName;
4525 argv [1] = (char *)0;
4526
4527 pid = fork ();
4528 if (pid < 0) {
4529 log_error ("fork: %m");
4530 wstatus = 0;
4531 } else if (pid) {
4532 do {
4533 wpid = wait (&wstatus);
4534 } while (wpid != pid && wpid > 0);
4535 if (wpid < 0) {
4536 log_error ("wait: %m");
4537 wstatus = 0;
4538 }
4539 } else {
4d97a043
DH
4540 /* We don't want to pass an open file descriptor for
4541 * dhclient.leases when executing dhclient-script.
4542 */
4543 if (leaseFile != NULL)
4544 fclose(leaseFile);
32a47563
TL
4545 execve (scriptName, argv, envp);
4546 log_error ("execve (%s, ...): %m", scriptName);
4547 exit (0);
4548 }
4549
4550 if (client) {
4551 for (sp = client -> env; sp; sp = next) {
4552 next = sp -> next;
4553 dfree (sp, MDL);
4554 }
4555 client -> env = (struct string_list *)0;
4556 client -> envc = 0;
32a47563 4557 }
b1423aed 4558 dfree (envp, MDL);
be62cf06 4559 gettimeofday(&cur_tv, NULL);
ed0f73ab
TL
4560 return (WIFEXITED (wstatus) ?
4561 WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
32a47563
TL
4562}
4563
4564void client_envadd (struct client_state *client,
4565 const char *prefix, const char *name, const char *fmt, ...)
4566{
4567 char spbuf [1024];
4568 char *s;
28868515 4569 unsigned len;
32a47563
TL
4570 struct string_list *val;
4571 va_list list;
4572
4573 va_start (list, fmt);
4574 len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
4575 va_end (list);
4576
4577 val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
4578 len + sizeof *val, MDL);
8c785e79
TM
4579 if (!val) {
4580 log_error ("client_envadd: cannot allocate space for variable");
32a47563 4581 return;
8c785e79
TM
4582 }
4583
32a47563
TL
4584 s = val -> string;
4585 strcpy (s, prefix);
4586 strcat (s, name);
4587 s += strlen (s);
4588 *s++ = '=';
4589 if (len >= sizeof spbuf) {
4590 va_start (list, fmt);
4591 vsnprintf (s, len + 1, fmt, list);
4592 va_end (list);
8c785e79 4593 } else {
32a47563 4594 strcpy (s, spbuf);
8c785e79
TM
4595 }
4596
32a47563
TL
4597 val -> next = client -> env;
4598 client -> env = val;
4599 client -> envc++;
cc26de46
TL
4600}
4601
32a47563
TL
4602int dhcp_option_ev_name (buf, buflen, option)
4603 char *buf;
6ceb9118 4604 size_t buflen;
cc26de46
TL
4605 struct option *option;
4606{
c0504523
TL
4607 int i, j;
4608 const char *s;
cc26de46 4609
c0504523
TL
4610 j = 0;
4611 if (option -> universe != &dhcp_universe) {
4612 s = option -> universe -> name;
4613 i = 0;
3dbe2246 4614 } else {
c0504523
TL
4615 s = option -> name;
4616 i = 1;
cc26de46
TL
4617 }
4618
c0504523
TL
4619 do {
4620 while (*s) {
4621 if (j + 1 == buflen)
4622 return 0;
4623 if (*s == '-')
4624 buf [j++] = '_';
4625 else
4626 buf [j++] = *s;
4627 ++s;
4628 }
4629 if (!i) {
4630 s = option -> name;
4631 if (j + 1 == buflen)
4632 return 0;
4633 buf [j++] = '_';
4634 }
4635 ++i;
4636 } while (i != 2);
4637
4638 buf [j] = 0;
32a47563 4639 return 1;
cc26de46 4640}
b00d3884 4641
29b23207 4642void finish (char ret)
b00d3884 4643{
29b23207
FD
4644 if (no_daemon || dfd[0] == -1 || dfd[1] == -1)
4645 exit((int)ret);
4646 if (write(dfd[1], &ret, 1) != 1)
4647 log_fatal("write to parent: %m");
4648 (void) close(dfd[1]);
4649 dfd[0] = dfd[1] = -1;
4650 exit((int)ret);
4651}
4652
4653void detach ()
4654{
4655 char buf = 0;
b00d3884
TL
4656
4657 /* Don't become a daemon if the user requested otherwise. */
b8cf055d
TL
4658 if (no_daemon) {
4659 write_client_pid_file ();
b00d3884 4660 return;
b8cf055d 4661 }
b00d3884
TL
4662
4663 /* Only do it once. */
29b23207 4664 if (dfd[0] == -1 || dfd[1] == -1)
b00d3884 4665 return;
29b23207
FD
4666
4667 /* Signal parent we started successfully. */
4668 if (write(dfd[1], &buf, 1) != 1)
4669 log_fatal("write to parent: %m");
4670 (void) close(dfd[1]);
4671 dfd[0] = dfd[1] = -1;
b00d3884
TL
4672
4673 /* Stop logging to stderr... */
4674 log_perror = 0;
4675
b00d3884 4676 /* Become session leader and get pid... */
dc9d7b08 4677 (void) setsid ();
b8cf055d 4678
62d0cb47 4679 /* Close standard I/O descriptors. */
dc9d7b08
MA
4680 (void) close(0);
4681 (void) close(1);
4682 (void) close(2);
62d0cb47 4683
a609e69b 4684 /* Reopen them on /dev/null. */
dc9d7b08
MA
4685 (void) open("/dev/null", O_RDWR);
4686 (void) open("/dev/null", O_RDWR);
4687 (void) open("/dev/null", O_RDWR);
a609e69b 4688
b8cf055d 4689 write_client_pid_file ();
a546f2a7 4690
ae566556 4691 IGNORE_RET (chdir("/"));
29b23207 4692
b8cf055d
TL
4693}
4694
4695void write_client_pid_file ()
4696{
4697 FILE *pf;
4698 int pfdesc;
4699
4a5bfeac
SR
4700 /* nothing to do if the user doesn't want a pid file */
4701 if (no_pid_file == ISC_TRUE) {
4702 return;
4703 }
4704
b8cf055d
TL
4705 pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
4706
4707 if (pfdesc < 0) {
8ae2d595 4708 log_error ("Can't create %s: %m", path_dhclient_pid);
b8cf055d
TL
4709 return;
4710 }
4711
4712 pf = fdopen (pfdesc, "w");
fb30f3fc
SR
4713 if (!pf) {
4714 close(pfdesc);
8ae2d595 4715 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
fb30f3fc 4716 } else {
19ea90f7 4717 fprintf (pf, "%ld\n", (long)getpid ());
b8cf055d
TL
4718 fclose (pf);
4719 }
4720}
4721
b8cf055d
TL
4722void client_location_changed ()
4723{
4724 struct interface_info *ip;
02d9e453 4725 struct client_state *client;
b8cf055d
TL
4726
4727 for (ip = interfaces; ip; ip = ip -> next) {
02d9e453
TL
4728 for (client = ip -> client; client; client = client -> next) {
4729 switch (client -> state) {
4730 case S_SELECTING:
4731 cancel_timeout (send_discover, client);
4732 break;
b8cf055d 4733
02d9e453
TL
4734 case S_BOUND:
4735 cancel_timeout (state_bound, client);
4736 break;
b8cf055d 4737
02d9e453
TL
4738 case S_REBOOTING:
4739 case S_REQUESTING:
4740 case S_RENEWING:
4741 cancel_timeout (send_request, client);
4742 break;
b8cf055d 4743
02d9e453
TL
4744 case S_INIT:
4745 case S_REBINDING:
57710b89 4746 case S_STOPPED:
0f69ff73 4747 case S_DECLINING:
933b80fa 4748 case S_V6ONLY:
02d9e453
TL
4749 break;
4750 }
4751 client -> state = S_INIT;
4752 state_reboot (client);
b8cf055d 4753 }
b8cf055d
TL
4754 }
4755}
6767b592 4756
3dbe2246 4757void do_release(client)
347de8bd
TL
4758 struct client_state *client;
4759{
007e3ee4
TL
4760 struct data_string ds;
4761 struct option_cache *oc;
4762
785c1a51
FD
4763#if defined(DHCPv6) && defined(DHCP4o6)
4764 if (dhcpv4_over_dhcpv6 && (dhcp4o6_state <= 0)) {
4765 if (dhcp4o6_state < 0)
4766 dhcp4o6_poll(NULL);
4767 client->pending = P_RELEASE;
4768 return;
4769 }
4770#endif
4771
57710b89 4772 /* Pick a random xid. */
347de8bd
TL
4773 client -> xid = random ();
4774
bdcaf7b9
TL
4775 /* is there even a lease to release? */
4776 if (client -> active) {
4777 /* Make a DHCPRELEASE packet, and set appropriate per-interface
4778 flags. */
4779 make_release (client, client -> active);
007e3ee4
TL
4780
4781 memset (&ds, 0, sizeof ds);
4782 oc = lookup_option (&dhcp_universe,
4783 client -> active -> options,
4784 DHO_DHCP_SERVER_IDENTIFIER);
4785 if (oc &&
4786 evaluate_option_cache (&ds, (struct packet *)0,
66e9cecf 4787 (struct lease *)0, client,
007e3ee4
TL
4788 (struct option_state *)0,
4789 client -> active -> options,
4790 &global_scope, oc, MDL)) {
4791 if (ds.len > 3) {
4792 memcpy (client -> destination.iabuf,
4793 ds.data, 4);
4794 client -> destination.len = 4;
4795 } else
4796 client -> destination = iaddr_broadcast;
98311e4b
DH
4797
4798 data_string_forget (&ds, MDL);
007e3ee4
TL
4799 } else
4800 client -> destination = iaddr_broadcast;
bdcaf7b9
TL
4801 client -> first_sending = cur_time;
4802 client -> interval = client -> config -> initial_interval;
3dbe2246 4803
bdcaf7b9
TL
4804 /* Zap the medium list... */
4805 client -> medium = (struct string_list *)0;
3dbe2246 4806
bdcaf7b9
TL
4807 /* Send out the first and only DHCPRELEASE packet. */
4808 send_release (client);
347de8bd 4809
007e3ee4 4810 /* Do the client script RELEASE operation. */
bdcaf7b9
TL
4811 script_init (client,
4812 "RELEASE", (struct string_list *)0);
4813 if (client -> alias)
27be804f
TM
4814 script_write_params(client, "alias_",
4815 client -> alias);
4816 script_write_params(client, "old_", client -> active);
10613724 4817 script_write_requested(client);
27be804f 4818 script_go(client);
bdcaf7b9 4819 }
007e3ee4 4820
57710b89
TL
4821 /* Cancel any timeouts. */
4822 cancel_timeout (state_bound, client);
4823 cancel_timeout (send_discover, client);
4824 cancel_timeout (state_init, client);
4825 cancel_timeout (send_request, client);
4826 cancel_timeout (state_reboot, client);
933b80fa 4827 cancel_timeout (finish_v6only, client);
57710b89 4828 client -> state = S_STOPPED;
785c1a51
FD
4829
4830#if defined(DHCPv6) && defined(DHCP4o6)
4831 if (dhcpv4_over_dhcpv6)
29b23207 4832 finish(0);
785c1a51 4833#endif
347de8bd
TL
4834}
4835
20916cae
TL
4836int dhclient_interface_shutdown_hook (struct interface_info *interface)
4837{
4838 do_release (interface -> client);
57710b89 4839
20916cae
TL
4840 return 1;
4841}
347de8bd 4842
20916cae
TL
4843int dhclient_interface_discovery_hook (struct interface_info *tmp)
4844{
4845 struct interface_info *last, *ip;
4846 /* See if we can find the client from dummy_interfaces */
4847 last = 0;
4848 for (ip = dummy_interfaces; ip; ip = ip -> next) {
4849 if (!strcmp (ip -> name, tmp -> name)) {
4850 /* Remove from dummy_interfaces */
4851 if (last) {
4852 ip = (struct interface_info *)0;
4853 interface_reference (&ip, last -> next, MDL);
4854 interface_dereference (&last -> next, MDL);
4855 if (ip -> next) {
4856 interface_reference (&last -> next,
4857 ip -> next, MDL);
4858 interface_dereference (&ip -> next,
4859 MDL);
4860 }
4861 } else {
4862 ip = (struct interface_info *)0;
4863 interface_reference (&ip,
4864 dummy_interfaces, MDL);
4865 interface_dereference (&dummy_interfaces, MDL);
4866 if (ip -> next) {
4867 interface_reference (&dummy_interfaces,
4868 ip -> next, MDL);
4869 interface_dereference (&ip -> next,
4870 MDL);
4871 }
4872 }
4873 /* Copy "client" to tmp */
4874 if (ip -> client) {
4875 tmp -> client = ip -> client;
4876 tmp -> client -> interface = tmp;
4877 }
4878 interface_dereference (&ip, MDL);
4879 break;
4880 }
4881 last = ip;
4882 }
4883 return 1;
4884}
347de8bd 4885
57710b89
TL
4886isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
4887{
4888 struct interface_info *ip;
4889 struct client_state *client;
4890
4891 /* This code needs some rethinking. It doesn't test against
4892 a signal name, and it just kind of bulls into doing something
4893 that may or may not be appropriate. */
4894
4895 if (interfaces) {
4896 interface_reference (&interface -> next, interfaces, MDL);
4897 interface_dereference (&interfaces, MDL);
4898 }
4899 interface_reference (&interfaces, interface, MDL);
4900
4901 discover_interfaces (DISCOVER_UNCONFIGURED);
4902
4903 for (ip = interfaces; ip; ip = ip -> next) {
4904 /* If interfaces were specified, don't configure
4905 interfaces that weren't specified! */
4906 if (ip -> flags & INTERFACE_RUNNING ||
4907 (ip -> flags & (INTERFACE_REQUESTED |
4908 INTERFACE_AUTOMATIC)) !=
4909 INTERFACE_REQUESTED)
4910 continue;
4911 script_init (ip -> client,
4912 "PREINIT", (struct string_list *)0);
4913 if (ip -> client -> alias)
27be804f
TM
4914 script_write_params(ip -> client, "alias_",
4915 ip -> client -> alias);
4916 script_go(ip -> client);
57710b89 4917 }
3dbe2246
FD
4918
4919 discover_interfaces (interfaces_requested != 0
57710b89
TL
4920 ? DISCOVER_REQUESTED
4921 : DISCOVER_RUNNING);
4922
4923 for (ip = interfaces; ip; ip = ip -> next) {
4924 if (ip -> flags & INTERFACE_RUNNING)
4925 continue;
4926 ip -> flags |= INTERFACE_RUNNING;
5d082abd
TM
4927 for (client = ip->client ; client ; client = client->next) {
4928 client->state = S_INIT;
4929 state_reboot(client);
57710b89
TL
4930 }
4931 }
4932 return ISC_R_SUCCESS;
4933}
4934
6767b592
TL
4935/* The client should never receive a relay agent information option,
4936 so if it does, log it and discard it. */
4937
4938int parse_agent_information_option (packet, len, data)
4939 struct packet *packet;
4940 int len;
4941 u_int8_t *data;
4942{
6767b592
TL
4943 return 1;
4944}
4945
4946/* The client never sends relay agent information options. */
4947
4948unsigned cons_agent_information_options (cfg_options, outpacket,
4949 agentix, length)
4950 struct option_state *cfg_options;
4951 struct dhcp_packet *outpacket;
4952 unsigned agentix;
4953 unsigned length;
4954{
4955 return length;
4956}
d758ad8c
TL
4957
4958static void shutdown_exit (void *foo)
4959{
f950de77
SR
4960 /* get rid of the pid if we can */
4961 if (no_pid_file == ISC_FALSE)
4962 (void) unlink(path_dhclient_pid);
29b23207 4963 finish(0);
d758ad8c
TL
4964}
4965
98bf1607
SR
4966#if defined (NSUPDATE)
4967/*
4968 * If the first query fails, the updater MUST NOT delete the DNS name. It
4969 * may be that the host whose lease on the server has expired has moved
4970 * to another network and obtained a lease from a different server,
4971 * which has caused the client's A RR to be replaced. It may also be
4972 * that some other client has been configured with a name that matches
4973 * the name of the DHCP client, and the policy was that the last client
4974 * to specify the name would get the name. In this case, the DHCID RR
4975 * will no longer match the updater's notion of the client-identity of
4976 * the host pointed to by the DNS name.
4977 * -- "Interaction between DHCP and DNS"
4978 */
4979
4980/* The first and second stages are pretty similar so we combine them */
4981void
4982client_dns_remove_action(dhcp_ddns_cb_t *ddns_cb,
4983 isc_result_t eresult)
4984{
4985
4986 isc_result_t result;
4987
4988 if ((eresult == ISC_R_SUCCESS) &&
4989 (ddns_cb->state == DDNS_STATE_REM_FW_YXDHCID)) {
4990 /* Do the second stage of the FWD removal */
4991 ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
4992
87132514 4993 result = ddns_modify_fwd(ddns_cb, MDL);
98bf1607
SR
4994 if (result == ISC_R_SUCCESS) {
4995 return;
4996 }
4997 }
4998
4999 /* If we are done or have an error clean up */
cca6a648 5000 dhclient_ddns_cb_free(ddns_cb, MDL);
98bf1607
SR
5001 return;
5002}
5003
5004void
5005client_dns_remove(struct client_state *client,
5006 struct iaddr *addr)
5007{
5008 dhcp_ddns_cb_t *ddns_cb;
5009 isc_result_t result;
5010
5011 /* if we have an old ddns request for this client, cancel it */
5012 if (client->ddns_cb != NULL) {
87132514 5013 ddns_cancel(client->ddns_cb, MDL);
98bf1607
SR
5014 client->ddns_cb = NULL;
5015 }
cca6a648 5016
98bf1607
SR
5017 ddns_cb = ddns_cb_alloc(MDL);
5018 if (ddns_cb != NULL) {
5019 ddns_cb->address = *addr;
5020 ddns_cb->timeout = 0;
5021
5022 ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
5023 ddns_cb->flags = DDNS_UPDATE_ADDR;
5024 ddns_cb->cur_func = client_dns_remove_action;
5025
5026 result = client_dns_update(client, ddns_cb);
5027
5028 if (result != ISC_R_TIMEDOUT) {
cca6a648 5029 dhclient_ddns_cb_free(ddns_cb, MDL);
98bf1607
SR
5030 }
5031 }
5032}
5df5813d
TM
5033#endif /* defined NSUPDATE */
5034
98bf1607 5035
d758ad8c
TL
5036isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
5037 control_object_state_t newstate)
5038{
5039 struct interface_info *ip;
5040 struct client_state *client;
be62cf06 5041 struct timeval tv;
d758ad8c 5042
0895c955
SR
5043 if (newstate == server_shutdown) {
5044 /* Re-entry */
5045 if (shutdown_signal == SIGUSR1)
5046 return ISC_R_SUCCESS;
5047 /* Log shutdown on signal. */
5048 if ((shutdown_signal == SIGINT) ||
5049 (shutdown_signal == SIGTERM)) {
5050 log_info("Received signal %d, initiating shutdown.",
5051 shutdown_signal);
5052 }
5053 /* Mark it was called. */
5054 shutdown_signal = SIGUSR1;
5055 }
5056
d758ad8c
TL
5057 /* Do the right thing for each interface. */
5058 for (ip = interfaces; ip; ip = ip -> next) {
5059 for (client = ip -> client; client; client = client -> next) {
5060 switch (newstate) {
5061 case server_startup:
5062 return ISC_R_SUCCESS;
5063
5064 case server_running:
5065 return ISC_R_SUCCESS;
5066
5067 case server_shutdown:
5068 if (client -> active &&
5069 client -> active -> expiry > cur_time) {
98bf1607
SR
5070#if defined (NSUPDATE)
5071 if (client->config->do_forward_update) {
5072 client_dns_remove(client,
5073 &client->active->address);
5074 }
5df5813d
TM
5075#endif /* defined NSUPDATE */
5076
d758ad8c
TL
5077 do_release (client);
5078 }
5079 break;
5080
5081 case server_hibernate:
5082 state_stop (client);
5083 break;
5084
5085 case server_awaken:
5086 state_reboot (client);
5087 break;
5088 }
5089 }
5090 }
af5fa176 5091
be62cf06 5092 if (newstate == server_shutdown) {
5d082abd
TM
5093 tv.tv_sec = cur_tv.tv_sec;
5094 tv.tv_usec = cur_tv.tv_usec + 1;
5095 add_timeout(&tv, shutdown_exit, 0, 0, 0);
be62cf06 5096 }
d758ad8c
TL
5097 return ISC_R_SUCCESS;
5098}
5099
98bf1607
SR
5100#if defined (NSUPDATE)
5101/*
5102 * Called after a timeout if the DNS update failed on the previous try.
5103 * Starts the retry process. If the retry times out it will schedule
5104 * this routine to run again after a 10x wait.
98bd7ca0
DH
5105 */
5106void
98bf1607 5107client_dns_update_timeout (void *cp)
98bd7ca0 5108{
98bf1607
SR
5109 dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)cp;
5110 struct client_state *client = (struct client_state *)ddns_cb->lease;
5111 isc_result_t status = ISC_R_FAILURE;
98bd7ca0 5112
98bf1607
SR
5113 if ((client != NULL) &&
5114 ((client->active != NULL) ||
5115 (client->active_lease != NULL)))
5116 status = client_dns_update(client, ddns_cb);
98bd7ca0 5117
98bf1607
SR
5118 /*
5119 * A status of timedout indicates that we started the update and
5120 * have released control of the control block. Any other status
5121 * indicates that we should clean up the control block. We either
5122 * got a success which indicates that we didn't really need to
5123 * send an update or some other error in which case we weren't able
5124 * to start the update process. In both cases we still own
5125 * the control block and should free it.
5126 */
5127 if (status != ISC_R_TIMEDOUT) {
cca6a648 5128 dhclient_ddns_cb_free(ddns_cb, MDL);
98bd7ca0
DH
5129 }
5130}
5131
98bf1607
SR
5132/*
5133 * If the first query succeeds, the updater can conclude that it
5134 * has added a new name whose only RRs are the A and DHCID RR records.
5135 * The A RR update is now complete (and a client updater is finished,
5136 * while a server might proceed to perform a PTR RR update).
5137 * -- "Interaction between DHCP and DNS"
5138 *
5139 * If the second query succeeds, the updater can conclude that the current
5140 * client was the last client associated with the domain name, and that
5141 * the name now contains the updated A RR. The A RR update is now
5142 * complete (and a client updater is finished, while a server would
5143 * then proceed to perform a PTR RR update).
5144 * -- "Interaction between DHCP and DNS"
5145 *
5146 * If the second query fails with NXRRSET, the updater must conclude
5147 * that the client's desired name is in use by another host. At this
5148 * juncture, the updater can decide (based on some administrative
5149 * configuration outside of the scope of this document) whether to let
5150 * the existing owner of the name keep that name, and to (possibly)
5151 * perform some name disambiguation operation on behalf of the current
5152 * client, or to replace the RRs on the name with RRs that represent
5153 * the current client. If the configured policy allows replacement of
5154 * existing records, the updater submits a query that deletes the
5155 * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
5156 * represent the IP address and client-identity of the new client.
5157 * -- "Interaction between DHCP and DNS"
5158 */
98311e4b 5159
98bf1607
SR
5160/* The first and second stages are pretty similar so we combine them */
5161void
5162client_dns_update_action(dhcp_ddns_cb_t *ddns_cb,
5163 isc_result_t eresult)
98311e4b 5164{
98bf1607 5165 isc_result_t result;
be62cf06 5166 struct timeval tv;
98311e4b 5167
98bf1607
SR
5168 switch(eresult) {
5169 case ISC_R_SUCCESS:
5170 default:
5171 /* Either we succeeded or broke in a bad way, clean up */
5172 break;
5173
5174 case DNS_R_YXRRSET:
5175 /*
5176 * This is the only difference between the two stages,
5177 * check to see if it is the first stage, in which case
5178 * start the second stage
5179 */
5180 if (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) {
5181 ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
5182 ddns_cb->cur_func = client_dns_update_action;
5183
87132514 5184 result = ddns_modify_fwd(ddns_cb, MDL);
98bf1607
SR
5185 if (result == ISC_R_SUCCESS) {
5186 return;
5187 }
5188 }
5189 break;
5190
5191 case ISC_R_TIMEDOUT:
5192 /*
5193 * We got a timeout response from the DNS module. Schedule
5194 * another attempt for later. We forget the name, dhcid and
5195 * zone so if it gets changed we will get the new information.
5196 */
5197 data_string_forget(&ddns_cb->fwd_name, MDL);
5198 data_string_forget(&ddns_cb->dhcid, MDL);
5199 if (ddns_cb->zone != NULL) {
5200 forget_zone((struct dns_zone **)&ddns_cb->zone);
5201 }
5202
5203 /* Reset to doing the first stage */
5204 ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
5205 ddns_cb->cur_func = client_dns_update_action;
5206
5207 /* and update our timer */
5208 if (ddns_cb->timeout < 3600)
5209 ddns_cb->timeout *= 10;
5d082abd
TM
5210 tv.tv_sec = cur_tv.tv_sec + ddns_cb->timeout;
5211 tv.tv_usec = cur_tv.tv_usec;
be62cf06 5212 add_timeout(&tv, client_dns_update_timeout,
98bf1607
SR
5213 ddns_cb, NULL, NULL);
5214 return;
5215 }
5216
cca6a648 5217 dhclient_ddns_cb_free(ddns_cb, MDL);
98bf1607 5218 return;
98311e4b
DH
5219}
5220
d758ad8c
TL
5221/* See if we should do a DNS update, and if so, do it. */
5222
98bf1607
SR
5223isc_result_t
5224client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
d758ad8c 5225{
98bf1607 5226 struct data_string client_identifier;
d758ad8c
TL
5227 struct option_cache *oc;
5228 int ignorep;
5229 int result;
d7d9c0c7 5230 int ddns_v4_type;
d758ad8c
TL
5231 isc_result_t rcode;
5232
5233 /* If we didn't send an FQDN option, we certainly aren't going to
5234 be doing an update. */
5235 if (!client -> sent_options)
98311e4b 5236 return ISC_R_SUCCESS;
d758ad8c
TL
5237
5238 /* If we don't have a lease, we can't do an update. */
98bd7ca0 5239 if ((client->active == NULL) && (client->active_lease == NULL))
98311e4b 5240 return ISC_R_SUCCESS;
d758ad8c
TL
5241
5242 /* If we set the no client update flag, don't do the update. */
5243 if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
5244 FQDN_NO_CLIENT_UPDATE)) &&
5245 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
5246 (struct lease *)0, client,
5247 client -> sent_options,
5248 (struct option_state *)0,
5249 &global_scope, oc, MDL))
98311e4b 5250 return ISC_R_SUCCESS;
3dbe2246 5251
d758ad8c
TL
5252 /* If we set the "server, please update" flag, or didn't set it
5253 to false, don't do the update. */
5254 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
5255 FQDN_SERVER_UPDATE)) ||
5256 evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
5257 (struct lease *)0, client,
5258 client -> sent_options,
5259 (struct option_state *)0,
5260 &global_scope, oc, MDL))
98311e4b 5261 return ISC_R_SUCCESS;
3dbe2246 5262
d758ad8c 5263 /* If no FQDN option was supplied, don't do the update. */
d758ad8c
TL
5264 if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
5265 FQDN_FQDN)) ||
98bf1607 5266 !evaluate_option_cache (&ddns_cb->fwd_name, (struct packet *)0,
d758ad8c
TL
5267 (struct lease *)0, client,
5268 client -> sent_options,
5269 (struct option_state *)0,
5270 &global_scope, oc, MDL))
98311e4b 5271 return ISC_R_SUCCESS;
d758ad8c 5272
d7d9c0c7
SR
5273 /*
5274 * Construct the DHCID value for use in the DDNS update process
5275 * We have the newer standard version and the older interim version
5276 * chosen by the '-I' option. The interim version is left as is
5277 * for backwards compatibility. The standard version is based on
5278 * RFC 4701 section 3.3
98bd7ca0 5279 */
d7d9c0c7 5280
6705543f 5281 result = 0;
dc9d7b08 5282 POST(result);
98bd7ca0 5283 memset(&client_identifier, 0, sizeof(client_identifier));
d7d9c0c7
SR
5284
5285 if (std_dhcid == 1) {
5286 /* standard style */
5287 ddns_cb->dhcid_class = dns_rdatatype_dhcid;
5288 ddns_v4_type = 1;
5289 } else {
5290 /* interim style */
5291 ddns_cb->dhcid_class = dns_rdatatype_txt;
5292 /* for backwards compatibility */
5293 ddns_v4_type = DHO_DHCP_CLIENT_IDENTIFIER;
5294 }
98bd7ca0 5295 if (client->active_lease != NULL) {
d7d9c0c7 5296 /* V6 request, get the client identifier, then
cca6a648 5297 * construct the dhcid for either standard
d7d9c0c7
SR
5298 * or interim */
5299 if (((oc = lookup_option(&dhcpv6_universe,
5300 client->sent_options,
5301 D6O_CLIENTID)) != NULL) &&
5302 evaluate_option_cache(&client_identifier, NULL,
5303 NULL, client,
5304 client->sent_options, NULL,
98bd7ca0 5305 &global_scope, oc, MDL)) {
d7d9c0c7 5306 result = get_dhcid(ddns_cb, 2,
98bd7ca0
DH
5307 client_identifier.data,
5308 client_identifier.len);
5309 data_string_forget(&client_identifier, MDL);
5310 } else
5311 log_fatal("Impossible condition at %s:%d.", MDL);
5312 } else {
d7d9c0c7
SR
5313 /*
5314 * V4 request, use the client id if there is one or the
5315 * mac address if there isn't. If we have a client id
5316 * we check to see if it is an embedded DUID.
5317 */
5318 if (((oc = lookup_option(&dhcp_universe,
5319 client->sent_options,
5320 DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
5321 evaluate_option_cache(&client_identifier, NULL,
5322 NULL, client,
5323 client->sent_options, NULL,
98bd7ca0 5324 &global_scope, oc, MDL)) {
d7d9c0c7
SR
5325 if ((std_dhcid == 1) && (duid_v4 == 1) &&
5326 (client_identifier.data[0] == 255)) {
5327 /*
5328 * This appears to be an embedded DUID,
5329 * extract it and treat it as such
5330 */
5331 if (client_identifier.len <= 5)
5332 log_fatal("Impossible condition at %s:%d.",
5333 MDL);
5334 result = get_dhcid(ddns_cb, 2,
5335 client_identifier.data + 5,
5336 client_identifier.len - 5);
5337 } else {
5338 result = get_dhcid(ddns_cb, ddns_v4_type,
5339 client_identifier.data,
5340 client_identifier.len);
5341 }
98bd7ca0
DH
5342 data_string_forget(&client_identifier, MDL);
5343 } else
d7d9c0c7 5344 result = get_dhcid(ddns_cb, 0,
98bd7ca0
DH
5345 client->interface->hw_address.hbuf,
5346 client->interface->hw_address.hlen);
5347 }
d7d9c0c7 5348
d758ad8c 5349 if (!result) {
98311e4b 5350 return ISC_R_SUCCESS;
d758ad8c
TL
5351 }
5352
d758ad8c
TL
5353 /*
5354 * Perform updates.
5355 */
98bf1607 5356 if (ddns_cb->fwd_name.len && ddns_cb->dhcid.len) {
87132514 5357 rcode = ddns_modify_fwd(ddns_cb, MDL);
98311e4b
DH
5358 } else
5359 rcode = ISC_R_FAILURE;
3dbe2246 5360
98bf1607
SR
5361 /*
5362 * A success from the modify routine means we are performing
5363 * async processing, for which we use the timedout error message.
5364 */
5365 if (rcode == ISC_R_SUCCESS) {
5366 rcode = ISC_R_TIMEDOUT;
5367 }
5368
98311e4b 5369 return rcode;
d758ad8c 5370}
98bd7ca0 5371
98bf1607
SR
5372
5373/*
5374 * Schedule the first update. They will continue to retry occasionally
5375 * until they no longer time out (or fail).
5376 */
5377void
5378dhclient_schedule_updates(struct client_state *client,
5379 struct iaddr *addr,
5380 int offset)
5381{
5382 dhcp_ddns_cb_t *ddns_cb;
5383 struct timeval tv;
5384
5385 if (!client->config->do_forward_update)
5386 return;
5387
5388 /* cancel any outstanding ddns requests */
5389 if (client->ddns_cb != NULL) {
87132514 5390 ddns_cancel(client->ddns_cb, MDL);
98bf1607
SR
5391 client->ddns_cb = NULL;
5392 }
5393
5394 ddns_cb = ddns_cb_alloc(MDL);
5395
5396 if (ddns_cb != NULL) {
5397 ddns_cb->lease = (void *)client;
5398 ddns_cb->address = *addr;
5399 ddns_cb->timeout = 1;
5400
5401 /*
5402 * XXX: DNS TTL is a problem we need to solve properly.
5403 * Until that time, 300 is a placeholder default for
5404 * something that is less insane than a value scaled
5405 * by lease timeout.
5406 */
5407 ddns_cb->ttl = 300;
5408
5409 ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
5410 ddns_cb->cur_func = client_dns_update_action;
5411 ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_INCLUDE_RRSET;
5412
5413 client->ddns_cb = ddns_cb;
5d082abd
TM
5414 tv.tv_sec = cur_tv.tv_sec + offset;
5415 tv.tv_usec = cur_tv.tv_usec;
98bf1607
SR
5416 add_timeout(&tv, client_dns_update_timeout,
5417 ddns_cb, NULL, NULL);
5418 } else {
5419 log_error("Unable to allocate dns update state for %s",
5420 piaddr(*addr));
5421 }
5422}
5df5813d 5423#endif /* defined NSUPDATE */
98bf1607 5424
98bd7ca0
DH
5425void
5426dhcpv4_client_assignments(void)
5427{
5428 struct servent *ent;
5429
5430 if (path_dhclient_pid == NULL)
5431 path_dhclient_pid = _PATH_DHCLIENT_PID;
5432 if (path_dhclient_db == NULL)
5433 path_dhclient_db = _PATH_DHCLIENT_DB;
5434
5435 /* Default to the DHCP/BOOTP port. */
5436 if (!local_port) {
5437 /* If we're faking a relay agent, and we're not using loopback,
5438 use the server port, not the client port. */
02b0bdc3 5439 if (mockup_relay && giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
98bd7ca0
DH
5440 local_port = htons(67);
5441 } else {
02b0bdc3
SR
5442 ent = getservbyname("dhcpc", "udp");
5443 if (ent == NULL)
5444 ent = getservbyname("bootpc", "udp");
5445 if (ent == NULL)
5446 local_port = htons(68);
98bd7ca0 5447 else
02b0bdc3 5448 local_port = ent->s_port;
98bd7ca0
DH
5449#ifndef __CYGWIN32__
5450 endservent ();
5451#endif
5452 }
5453 }
5454
5455 /* If we're faking a relay agent, and we're not using loopback,
5456 we're using the server port, not the client port. */
02b0bdc3 5457 if (mockup_relay && giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
98bd7ca0
DH
5458 remote_port = local_port;
5459 } else
02b0bdc3 5460 remote_port = htons(ntohs(local_port) - 1); /* XXX */
98bd7ca0 5461}
bea17697
SR
5462
5463/*
5464 * The following routines are used to check that certain
5465 * strings are reasonable before we pass them to the scripts.
5466 * This avoids some problems with scripts treating the strings
5467 * as commands - see ticket 23722
5468 * The domain checking code should be done as part of assembling
5469 * the string but we are doing it here for now due to time
5470 * constraints.
5471 */
5472
5473static int check_domain_name(const char *ptr, size_t len, int dots)
5474{
5475 const char *p;
5476
5477 /* not empty or complete length not over 255 characters */
5478 if ((len == 0) || (len > 256))
5479 return(-1);
5480
5481 /* consists of [[:alnum:]-]+ labels separated by [.] */
5482 /* a [_] is against RFC but seems to be "widely used"... */
5483 for (p=ptr; (*p != 0) && (len-- > 0); p++) {
5484 if ((*p == '-') || (*p == '_')) {
5485 /* not allowed at begin or end of a label */
5486 if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
5487 return(-1);
5488 } else if (*p == '.') {
5489 /* each label has to be 1-63 characters;
5490 we allow [.] at the end ('foo.bar.') */
5491 size_t d = p - ptr;
5492 if ((d <= 0) || (d >= 64))
5493 return(-1);
5494 ptr = p + 1; /* jump to the next label */
5495 if ((dots > 0) && (len > 0))
5496 dots--;
5497 } else if (isalnum((unsigned char)*p) == 0) {
5498 /* also numbers at the begin are fine */
5499 return(-1);
5500 }
5501 }
5502 return(dots ? -1 : 0);
5503}
5504
5505static int check_domain_name_list(const char *ptr, size_t len, int dots)
5506{
5507 const char *p;
5508 int ret = -1; /* at least one needed */
5509
5510 if ((ptr == NULL) || (len == 0))
5511 return(-1);
5512
5513 for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
5514 if (*p != ' ')
5515 continue;
5516 if (p > ptr) {
5517 if (check_domain_name(ptr, p - ptr, dots) != 0)
5518 return(-1);
5519 ret = 0;
5520 }
5521 ptr = p + 1;
5522 }
5523 if (p > ptr)
5524 return(check_domain_name(ptr, p - ptr, dots));
5525 else
5526 return(ret);
5527}
5528
5529static int check_option_values(struct universe *universe,
5530 unsigned int opt,
5531 const char *ptr,
5532 size_t len)
5533{
5534 if (ptr == NULL)
5535 return(-1);
5536
5537 /* just reject options we want to protect, will be escaped anyway */
5538 if ((universe == NULL) || (universe == &dhcp_universe)) {
5539 switch(opt) {
bea17697 5540 case DHO_DOMAIN_NAME:
d15aa964
TM
5541#ifdef ACCEPT_LIST_IN_DOMAIN_NAME
5542 return check_domain_name_list(ptr, len, 0);
5543#else
5544 return check_domain_name(ptr, len, 0);
5545#endif
5546 case DHO_HOST_NAME:
bea17697
SR
5547 case DHO_NIS_DOMAIN:
5548 case DHO_NETBIOS_SCOPE:
5549 return check_domain_name(ptr, len, 0);
5550 break;
5551 case DHO_DOMAIN_SEARCH:
5552 return check_domain_name_list(ptr, len, 0);
5553 break;
5554 case DHO_ROOT_PATH:
5555 if (len == 0)
5556 return(-1);
5557 for (; (*ptr != 0) && (len-- > 0); ptr++) {
5558 if(!(isalnum((unsigned char)*ptr) ||
5559 *ptr == '#' || *ptr == '%' ||
5560 *ptr == '+' || *ptr == '-' ||
5561 *ptr == '_' || *ptr == ':' ||
5562 *ptr == '.' || *ptr == ',' ||
5563 *ptr == '@' || *ptr == '~' ||
5564 *ptr == '\\' || *ptr == '/' ||
5565 *ptr == '[' || *ptr == ']' ||
5566 *ptr == '=' || *ptr == ' '))
5567 return(-1);
5568 }
5569 return(0);
5570 break;
5571 }
5572 }
5573
5574#ifdef DHCPv6
5575 if (universe == &dhcpv6_universe) {
5576 switch(opt) {
5577 case D6O_SIP_SERVERS_DNS:
5578 case D6O_DOMAIN_SEARCH:
5579 case D6O_NIS_DOMAIN_NAME:
5580 case D6O_NISP_DOMAIN_NAME:
5581 return check_domain_name_list(ptr, len, 0);
5582 break;
5583 }
5584 }
5585#endif
5586
5587 return(0);
5588}
bea17697 5589
5d082abd
TM
5590static void
5591add_reject(struct packet *packet) {
5592 struct iaddrmatchlist *list;
cca6a648 5593
5d082abd
TM
5594 list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
5595 if (!list)
5596 log_fatal ("no memory for reject list!");
bea17697 5597
5d082abd
TM
5598 /*
5599 * client_addr is misleading - it is set to source address in common
5600 * code.
5601 */
5602 list->match.addr = packet->client_addr;
5603 /* Set mask to indicate host address. */
5604 list->match.mask.len = list->match.addr.len;
5605 memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
5606
5607 /* Append to reject list for the source interface. */
5608 list->next = packet->interface->client->config->reject_list;
5609 packet->interface->client->config->reject_list = list;
5610
5611 /*
5612 * We should inform user that we won't be accepting this server
5613 * anymore.
5614 */
5615 log_info("Server added to list of rejected servers.");
5616}
d7d9c0c7 5617
1c779d3b 5618#if defined(NSUPDATE)
cca6a648 5619/* Wrapper function around common ddns_cb_free function that ensures
5620 * we set the client_state pointer to the control block to NULL. */
5621static void
5622dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, char* file, int line) {
5623 if (ddns_cb) {
5624 struct client_state *client = (struct client_state *)ddns_cb->lease;
5625 if (client != NULL) {
5626 client->ddns_cb = NULL;
5627 }
5628
5629 ddns_cb_free(ddns_cb, file, line);
5630 }
5631}
5df5813d 5632#endif /* defined NSUPDATE */
785c1a51
FD
5633
5634#if defined(DHCPv6) && defined(DHCP4o6)
5635/*
5636 * \brief Omapi I/O handler
5637 *
5638 * The inter-process communication receive handler.
5639 *
5640 * On the DHCPv6 side, the message is either a POLL (which is answered
5641 * by a START or a STOP) or a DHCPv4-QUERY (which is forwarded to
5642 * DHCPv4 over DHCPv6 servers by forw_dhcpv4_query()).
5643 *
5644 * On the DHCPv4 side, the message is either a START, a STOP
5645 * (both for the DHCP4 over DHCPv6 state machine) or a DHCPv4-RESPONSE
5646 * (which is processed by recv_dhcpv4_response()).
5647 *
5648 * \param h the OMAPI object
5649 * \return a result for I/O success or error (used by the I/O subsystem)
5650 */
5651isc_result_t dhcpv4o6_handler(omapi_object_t *h) {
5652 char buf[65536];
5653 char start_msg[5] = { 'S', 'T', 'A', 'R', 'T' };
5654 char stop_msg[4] = { 'S', 'T', 'O', 'P' };
5655 char poll_msg[4] = { 'P', 'O', 'L', 'L' };
5656 struct data_string raw;
5657 int cc;
5658
5659 if (h->type != dhcp4o6_type)
5660 return DHCP_R_INVALIDARG;
5661
5662 cc = recv(dhcp4o6_fd, buf, sizeof(buf), 0);
5663 if (cc <= 0)
5664 return ISC_R_UNEXPECTED;
5665
5666 if (local_family == AF_INET6) {
5667 if ((cc == 4) &&
5668 (memcmp(buf, poll_msg, sizeof(poll_msg)) == 0)) {
5669 log_info("RCV: POLL");
5670 if (dhcp4o6_state < 0)
5671 cc = send(dhcp4o6_fd, stop_msg,
5672 sizeof(stop_msg), 0);
5673 else
5674 cc = send(dhcp4o6_fd, start_msg,
5675 sizeof(start_msg), 0);
5676 if (cc < 0) {
5677 log_error("dhcpv4o6_handler: send(): %m");
5678 return ISC_R_IOERROR;
5679 }
5680 } else {
5681 if (cc < DHCP_FIXED_NON_UDP + 8)
5682 return ISC_R_UNEXPECTED;
5683 memset(&raw, 0, sizeof(raw));
5684 if (!buffer_allocate(&raw.buffer, cc, MDL)) {
5685 log_error("dhcpv4o6_handler: "
5686 "no memory buffer.");
5687 return ISC_R_NOMEMORY;
5688 }
5689 raw.data = raw.buffer->data;
5690 raw.len = cc;
5691 memcpy(raw.buffer->data, buf, cc);
5692
5693 forw_dhcpv4_query(&raw);
5694
5695 data_string_forget(&raw, MDL);
5696 }
5697 } else {
5698 if ((cc == 4) &&
5699 (memcmp(buf, stop_msg, sizeof(stop_msg)) == 0)) {
5700 log_info("RCV: STOP");
5701 if (dhcp4o6_state > 0) {
5702 dhcp4o6_state = 0;
5703 dhcp4o6_poll(NULL);
5704 }
5705 } else if ((cc == 5) &&
5706 (memcmp(buf, start_msg, sizeof(start_msg)) == 0)) {
5707 log_info("RCV: START");
5708 if (dhcp4o6_state == 0)
5709 cancel_timeout(dhcp4o6_poll, NULL);
5710 dhcp4o6_state = 1;
5711 dhcp4o6_resume();
5712 } else {
5713 if (cc < DHCP_FIXED_NON_UDP + 16)
5714 return ISC_R_UNEXPECTED;
5715 memset(&raw, 0, sizeof(raw));
5716 if (!buffer_allocate(&raw.buffer, cc, MDL)) {
5717 log_error("dhcpv4o6_handler: "
5718 "no memory buffer.");
5719 return ISC_R_NOMEMORY;
5720 }
5721 raw.data = raw.buffer->data;
5722 raw.len = cc;
5723 memcpy(raw.buffer->data, buf, cc);
5724
5725 recv_dhcpv4_response(&raw);
5726
5727 data_string_forget(&raw, MDL);
5728 }
5729 }
5730
5731 return ISC_R_SUCCESS;
5732}
5733
5734/*
5735 * \brief Poll the DHCPv6 client
5736 * (DHCPv4 client function)
5737 *
5738 * A POLL message is sent to the DHCPv6 client periodically to check
5739 * if the DHCPv6 is ready (i.e., has a valid DHCPv4-over-DHCPv6 server
5740 * address option).
5741 */
5742static void dhcp4o6_poll(void *dummy) {
5743 char msg[4] = { 'P', 'O', 'L', 'L' };
5744 struct timeval tv;
5745 int cc;
5746
5747 IGNORE_UNUSED(dummy);
5748
5749 if (dhcp4o6_state < 0)
5750 dhcp4o6_state = 0;
5751
5752 log_info("POLL");
5753
5754 cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
5755 if (cc < 0)
5756 log_error("dhcp4o6_poll: send(): %m");
5757
5758 tv.tv_sec = cur_time + 60;
5759 tv.tv_usec = random() % 1000000;
5760
5761 add_timeout(&tv, dhcp4o6_poll, NULL, 0, 0);
5762}
5763
5764/*
5765 * \brief Resume pending operations
5766 * (DHCPv4 client function)
5767 *
5768 * A START message was received from the DHCPv6 client so pending
5769 * operations (RELEASE or REBOOT) must be resumed.
5770 */
5771static void dhcp4o6_resume() {
5772 struct interface_info *ip;
5773 struct client_state *client;
5774
5775 for (ip = interfaces; ip != NULL; ip = ip->next) {
5776 for (client = ip->client; client != NULL;
5777 client = client->next) {
5778 if (client->pending == P_RELEASE)
5779 do_release(client);
5780 else if (client->pending == P_REBOOT)
5781 state_reboot(client);
5782 }
5783 }
5784}
5785
5786/*
5787 * \brief Send a START to the DHCPv4 client
5788 * (DHCPv6 client function)
5789 *
5790 * First check if there is a valid DHCPv4-over-DHCPv6 server address option,
5791 * and when found go UP and on a transition from another state send
5792 * a START message to the DHCPv4 client.
5793 */
5794void dhcp4o6_start() {
5795 struct interface_info *ip;
5796 struct client_state *client;
5797 struct dhc6_lease *lease;
5798 struct option_cache *oc;
5799 struct data_string addrs;
5800 char msg[5] = { 'S', 'T', 'A', 'R', 'T' };
5801 int cc;
5802
5803 memset(&addrs, 0, sizeof(addrs));
5804 for (ip = interfaces; ip != NULL; ip = ip->next) {
5805 for (client = ip->client; client != NULL;
5806 client = client->next) {
5807 if ((client->state != S_BOUND) &&
5808 (client->state != S_RENEWING) &&
5809 (client->state != S_REBINDING))
5810 continue;
5811 lease = client->active_lease;
5812 if ((lease == NULL) || lease->released)
5813 continue;
5814 oc = lookup_option(&dhcpv6_universe,
5815 lease->options,
5816 D6O_DHCP4_O_DHCP6_SERVER);
5817 if ((oc == NULL) ||
5818 !evaluate_option_cache(&addrs, NULL, NULL, NULL,
5819 lease->options, NULL,
5820 &global_scope, oc, MDL))
5821 continue;
5822 if ((addrs.len % 16) != 0) {
5823 data_string_forget(&addrs, MDL);
5824 continue;
5825 }
5826 data_string_forget(&addrs, MDL);
5827 goto found;
5828 }
5829 }
5830 log_info("dhcp4o6_start: failed");
5831 dhcp4o6_stop();
5832 return;
5833
5834found:
5835 if (dhcp4o6_state == 1)
5836 return;
5837 log_info("dhcp4o6_start: go to UP");
5838 dhcp4o6_state = 1;
5839
5840 cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
5841 if (cc < 0)
5842 log_info("dhcp4o6_start: send(): %m");
5843}
5844
5845/*
5846 * Send a STOP to the DHCPv4 client
5847 * (DHCPv6 client function)
5848 *
5849 * Go DOWN and on a transition from another state send a STOP message
5850 * to the DHCPv4 client.
5851 */
5852static void dhcp4o6_stop() {
5853 char msg[4] = { 'S', 'T', 'O', 'P' };
5854 int cc;
5855
5856 if (dhcp4o6_state == -1)
5857 return;
5858
5859 log_info("dhcp4o6_stop: go to DOWN");
5860 dhcp4o6_state = -1;
5861
5862 cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
5863 if (cc < 0)
5864 log_error("dhcp4o6_stop: send(): %m");
5865}
5866#endif /* DHCPv6 && DHCP4o6 */