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