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