xref: /netbsd/external/mpl/dhcp/dist/client/dhclient.c (revision 13df4856)
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 
49 TIME default_lease_time = 43200; /* 12 hours... */
50 TIME max_lease_time = 86400; /* 24 hours... */
51 
52 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
53 const char *path_dhclient_db = NULL;
54 const char *path_dhclient_pid = NULL;
55 static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
56 char *path_dhclient_script = path_dhclient_script_array;
57 const char *path_dhclient_duid = NULL;
58 
59 static void add_to_tail(struct client_lease** lease_list, struct client_lease* lease);
60 
61 /* False (default) => we write and use a pid file */
62 isc_boolean_t no_pid_file = ISC_FALSE;
63 isc_boolean_t hw_mismatch_drop = ISC_TRUE;
64 
65 int dhcp_max_agent_option_packet_length = 0;
66 
67 int interfaces_requested = 0;
68 int interfaces_left = 0;
69 
70 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
71 struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
72 struct in_addr inaddr_any;
73 struct sockaddr_in sockaddr_broadcast;
74 struct in_addr giaddr;
75 struct data_string default_duid;
76 int duid_type = 0;
77 int duid_v4 = 0;
78 int std_dhcid = 0;
79 
80 int 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
87 static const char copyright[] = "Copyright 2004-2022 Internet Systems Consortium.";
88 static const char arr [] = "All rights reserved.";
89 static const char message [] = "Internet Systems Consortium DHCP Client";
90 static const char url [] = "For info, please visit https://www.isc.org/software/dhcp/";
91 #endif /* UNIT_TEST */
92 
93 extern u_int16_t local_port;
94 extern u_int16_t remote_port;
95 
96 #if defined(DHCPv6) && defined(DHCP4o6)
97 int dhcp4o6_state = -1; /* -1 = stopped, 0 = polling, 1 = started */
98 #endif
99 int no_daemon = 0;
100 int dfd[2] = { -1, -1 };
101 struct string_list *client_env = NULL;
102 int client_env_count = 0;
103 int onetry = 0;
104 int quiet = 1;
105 int nowait = 0;
106 int stateless = 0;
107 int wanted_ia_na = -1;		/* the absolute value is the real one. */
108 int wanted_ia_ta = 0;
109 int wanted_ia_pd = 0;
110 int 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)
114 int dad_wait_time = 0;
115 int prefix_len_hint = 0;
116 #endif
117 
118 int address_prefix_len = DHCLIENT_DEFAULT_PREFIX_LEN;
119 char *mockup_relay = NULL;
120 
121 libdhcp_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 
136 char *progname = NULL;
137 
138 void run_stateless(int exit_mode, u_int16_t port);
139 
140 static isc_result_t write_duid(struct data_string *duid);
141 static void add_reject(struct packet *packet);
142 
143 static int check_domain_name(const char *ptr, size_t len, int dots);
144 static int check_domain_name_list(const char *ptr, size_t len, int dots);
145 static int check_option_values(struct universe *universe, unsigned int opt,
146 			       const char *ptr, size_t len);
147 
148 #if defined(NSUPDATE)
149 static void dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb,
150                                    char* file, int line);
151 #endif /* defined NSUPDATE */
152 
153 static void
setup(void)154 setup(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 
177 static void
go_daemon(void)178 go_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 
204 static void
add_interfaces(char ** ifaces,int nifaces)205 add_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)
248 static void dhcp4o6_poll(void *dummy);
249 static void dhcp4o6_resume(void);
250 static void recv_dhcpv4_response(struct data_string *raw);
251 static int send_dhcpv4_query(struct client_state *client, int broadcast);
252 
253 static void dhcp4o6_stop(void);
254 static void forw_dhcpv4_response(struct packet *packet);
255 static 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  */
262 static const char use_noarg[] = "No argument for command: %s";
263 #ifdef DHCPv6
264 static 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 
295 static void
usage(const char * sfmt,const char * sarg)296 usage(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 
317 extern void initialize_client_option_spaces(void);
318 
319 int
main(int argc,char ** argv)320 main(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 
run_stateless(int exit_mode,u_int16_t port)1084 void 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 
find_class(struct class ** c,const char * s,const char * file,int line)1188 isc_result_t find_class (struct class **c,
1189 		const char *s, const char *file, int line)
1190 {
1191 	return 0;
1192 }
1193 
check_collection(packet,lease,collection)1194 int check_collection (packet, lease, collection)
1195 	struct packet *packet;
1196 	struct lease *lease;
1197 	struct collection *collection;
1198 {
1199 	return 0;
1200 }
1201 
classify(packet,class)1202 void classify (packet, class)
1203 	struct packet *packet;
1204 	struct class *class;
1205 {
1206 }
1207 
unbill_class(lease)1208 void unbill_class (lease)
1209 	struct lease *lease;
1210 {
1211 }
1212 
find_subnet(struct subnet ** sp,struct iaddr addr,const char * file,int line)1213 int 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 
state_reboot(cpp)1251 void 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 
state_init(cpp)1304 void 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 
check_v6only(packet,client)1329 uint32_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 
finish_v6only(cpp)1381 void 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 
start_v6only(client,v6only_wait)1395 void 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 
state_selecting(cpp)1429 void 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 
1511 static isc_boolean_t
compare_hw_address(const char * name,struct packet * packet)1512 compare_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 
dhcpack(packet)1534 void 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 
bind_lease(client)1708 void 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 
state_bound(cpp)1804 void 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 
state_stop(cpp)1846 void 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 
commit_leases()1871 int commit_leases ()
1872 {
1873 	return 0;
1874 }
1875 
write_lease(lease)1876 int write_lease (lease)
1877 	struct lease *lease;
1878 {
1879 	return 0;
1880 }
1881 
write_host(host)1882 int write_host (host)
1883 	struct host_decl *host;
1884 {
1885 	return 0;
1886 }
1887 
db_startup(testp)1888 void db_startup (testp)
1889 	int testp;
1890 {
1891 }
1892 
bootp(packet)1893 void 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 
dhcp(packet)1926 void 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
1977 void
dhcpv6(struct packet * packet)1978 dhcpv6(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  */
forw_dhcpv4_response(struct packet * packet)2055 static 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  */
recv_dhcpv4_response(struct data_string * raw)2137 static 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 
dhcpoffer(packet)2213 void 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 
packet_to_lease(packet,client)2354 struct 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 
dhcpnak(packet)2477 void 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 
send_discover(cpp)2548 void 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  */
2686 extern void discard_duplicate (struct client_lease** lease_list,
2687                                struct client_lease* lease);
discard_duplicate(struct client_lease ** lease_list,struct client_lease * lease)2688 void 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  */
add_to_tail(struct client_lease ** lease_list,struct client_lease * lease)2727 void 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
2756 void 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 
state_panic(cpp)2773 void 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 
send_request(cpp)2888 void 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 
send_decline(cpp)3083 void 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 
send_release(cpp)3123 void 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  */
send_dhcpv4_query(struct client_state * client,int broadcast)3213 static 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  */
forw_dhcpv4_query(struct data_string * raw)3274 static 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 
3346 void
make_client_options(struct client_state * client,struct client_lease * lease,u_int8_t * type,struct option_cache * sid,struct iaddr * rip,struct option ** prl,struct option_state ** op)3347 make_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 
make_discover(client,lease)3497 void 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 
make_request(client,lease)3561 void 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 
make_decline(client,lease)3649 void 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 
make_release(client,lease)3708 void 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 
destroy_client_lease(lease)3765 void 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 
3776 FILE *leaseFile = NULL;
3777 int leases_written = 0;
3778 
rewrite_client_leases()3779 void 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 
write_lease_option(struct option_cache * oc,struct packet * packet,struct lease * lease,struct client_state * client_state,struct option_state * in_options,struct option_state * cfg_options,struct binding_scope ** scope,struct universe * u,void * stuff)3841 void 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. */
3884 static void
write_options(struct client_state * client,struct option_state * options,const char * preamble)3885 write_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  */
3911 void
form_duid(struct data_string * duid,const char * file,int line)3912 form_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. */
3972 static isc_result_t
write_duid(struct data_string * duid)3973 write_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. */
4007 isc_result_t
write_client6_lease(struct client_state * client,struct dhc6_lease * lease,int rewrite,int sync)4008 write_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 
write_client_lease(client,lease,rewrite,makesure)4162 int 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. */
4303 char scriptName [256];
4304 FILE *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  */
script_init(struct client_state * client,const char * reason,struct string_list * medium)4318 void 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 
client_option_envadd(struct option_cache * oc,struct packet * packet,struct lease * lease,struct client_state * client_state,struct option_state * in_options,struct option_state * cfg_options,struct binding_scope ** scope,struct universe * u,void * stuff)4351 void 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  */
script_write_params(struct client_state * client,const char * prefix,struct client_lease * lease)4412 void 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  */
script_write_requested(struct client_state * client)4535 void 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  */
script_go(struct client_state * client)4565 int 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 
client_envadd(struct client_state * client,const char * prefix,const char * name,const char * fmt,...)4651 void 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 
dhcp_option_ev_name(buf,buflen,option)4689 int 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 
finish(char ret)4729 void 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 
detach()4740 void 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 
write_client_pid_file()4782 void 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 
client_location_changed()4809 void 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 
do_release(client)4844 void 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 
dhclient_interface_shutdown_hook(struct interface_info * interface)4923 int dhclient_interface_shutdown_hook (struct interface_info *interface)
4924 {
4925 	do_release (interface -> client);
4926 
4927 	return 1;
4928 }
4929 
dhclient_interface_discovery_hook(struct interface_info * tmp)4930 int 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 
dhclient_interface_startup_hook(struct interface_info * interface)4973 isc_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 
parse_agent_information_option(packet,len,data)5025 int 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 
cons_agent_information_options(cfg_options,outpacket,agentix,length)5035 unsigned 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 
shutdown_exit(void * foo)5045 static 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 */
5068 static void
client_dns_remove_action(dhcp_ddns_cb_t * ddns_cb,isc_result_t eresult)5069 client_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 
5091 void
client_dns_remove(struct client_state * client,struct iaddr * addr)5092 client_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 
dhcp_set_control_state(control_object_state_t oldstate,control_object_state_t newstate)5123 isc_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  */
5193 void
client_dns_update_timeout(void * cp)5194 client_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 */
5248 static void
client_dns_update_action(dhcp_ddns_cb_t * ddns_cb,isc_result_t eresult)5249 client_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 
5310 isc_result_t
client_dns_update(struct client_state * client,dhcp_ddns_cb_t * ddns_cb)5311 client_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  */
5464 void
dhclient_schedule_updates(struct client_state * client,struct iaddr * addr,int offset)5465 dhclient_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 
5512 void
dhcpv4_client_assignments(void)5513 dhcpv4_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 
check_domain_name(const char * ptr,size_t len,int dots)5560 static 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 
check_domain_name_list(const char * ptr,size_t len,int dots)5592 static 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 
check_option_values(struct universe * universe,unsigned int opt,const char * ptr,size_t len)5616 static 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 
5677 static void
add_reject(struct packet * packet)5678 add_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. */
5708 static void
dhclient_ddns_cb_free(dhcp_ddns_cb_t * ddns_cb,char * file,int line)5709 dhclient_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  */
dhcpv4o6_handler(omapi_object_t * h)5738 isc_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  */
dhcp4o6_poll(void * dummy)5829 static 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  */
dhcp4o6_resume()5858 static 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  */
dhcp4o6_start()5881 void 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 
5921 found:
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  */
dhcp4o6_stop()5939 static 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