xref: /freebsd/sbin/dhclient/dhclient.c (revision 086165ecb55d212e36dd3e8e7f42d463c590b121)
1 /*	$OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * Copyright 2004 Henning Brauer <henning@openbsd.org>
7  * Copyright (c) 1995, 1996, 1997, 1998, 1999
8  * The Internet Software Consortium.    All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of The Internet Software Consortium nor the names
20  *    of its contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
24  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
28  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
31  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  * This software has been written for the Internet Software Consortium
38  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
39  * Enterprises.  To learn more about the Internet Software Consortium,
40  * see ``http://www.vix.com/isc''.  To learn more about Vixie
41  * Enterprises, see ``http://www.vix.com''.
42  *
43  * This client was substantially modified and enhanced by Elliot Poger
44  * for use on Linux while he was working on the MosquitoNet project at
45  * Stanford.
46  *
47  * The current version owes much to Elliot's Linux enhancements, but
48  * was substantially reorganized and partially rewritten by Ted Lemon
49  * so as to use the same networking framework that the Internet Software
50  * Consortium DHCP server uses.   Much system-specific configuration code
51  * was moved into a shell script so that as support for more operating
52  * systems is added, it will not be necessary to port and maintain
53  * system-specific configuration code to these operating systems - instead,
54  * the shell script can invoke the native tools to accomplish the same
55  * purpose.
56  */
57 
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
60 
61 #include "dhcpd.h"
62 #include "privsep.h"
63 
64 #include <sys/capsicum.h>
65 #include <sys/endian.h>
66 
67 #include <capsicum_helpers.h>
68 #include <libgen.h>
69 
70 #include <net80211/ieee80211_freebsd.h>
71 
72 
73 #ifndef _PATH_VAREMPTY
74 #define	_PATH_VAREMPTY	"/var/empty"
75 #endif
76 
77 #define	PERIOD 0x2e
78 #define	hyphenchar(c) ((c) == 0x2d)
79 #define	bslashchar(c) ((c) == 0x5c)
80 #define	periodchar(c) ((c) == PERIOD)
81 #define	asterchar(c) ((c) == 0x2a)
82 #define	alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
83 	    ((c) >= 0x61 && (c) <= 0x7a))
84 #define	digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
85 #define	whitechar(c) ((c) == ' ' || (c) == '\t')
86 
87 #define	borderchar(c) (alphachar(c) || digitchar(c))
88 #define	middlechar(c) (borderchar(c) || hyphenchar(c))
89 #define	domainchar(c) ((c) > 0x20 && (c) < 0x7f)
90 
91 #define	CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
92 
93 cap_channel_t *capsyslog;
94 
95 time_t cur_time;
96 static time_t default_lease_time = 43200; /* 12 hours... */
97 
98 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
99 char *path_dhclient_db = NULL;
100 
101 int log_perror = 1;
102 static int privfd;
103 static int nullfd = -1;
104 
105 static char hostname[_POSIX_HOST_NAME_MAX + 1];
106 
107 static struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
108 static struct in_addr inaddr_any, inaddr_broadcast;
109 
110 static char *path_dhclient_pidfile;
111 struct pidfh *pidfile;
112 
113 /*
114  * ASSERT_STATE() does nothing now; it used to be
115  * assert (state_is == state_shouldbe).
116  */
117 #define ASSERT_STATE(state_is, state_shouldbe) {}
118 
119 /*
120  * We need to check that the expiry, renewal and rebind times are not beyond
121  * the end of time (~2038 when a 32-bit time_t is being used).
122  */
123 #define TIME_MAX        ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
124 
125 int		log_priority;
126 static int		no_daemon;
127 static int		unknown_ok = 1;
128 static int		routefd;
129 
130 struct interface_info	*ifi;
131 
132 int		 findproto(char *, int);
133 struct sockaddr	*get_ifa(char *, int);
134 void		 routehandler(struct protocol *);
135 void		 usage(void);
136 int		 check_option(struct client_lease *l, int option);
137 int		 check_classless_option(unsigned char *data, int len);
138 int		 ipv4addrs(const char * buf);
139 int		 res_hnok(const char *dn);
140 int		 check_search(const char *srch);
141 const char	*option_as_string(unsigned int code, unsigned char *data, int len);
142 int		 fork_privchld(int, int);
143 
144 #define	ROUNDUP(a) \
145 	    ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
146 #define	ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
147 
148 /* Minimum MTU is 68 as per RFC791, p. 24 */
149 #define MIN_MTU 68
150 
151 static time_t	scripttime;
152 
153 int
154 findproto(char *cp, int n)
155 {
156 	struct sockaddr *sa;
157 	unsigned i;
158 
159 	if (n == 0)
160 		return -1;
161 	for (i = 1; i; i <<= 1) {
162 		if (i & n) {
163 			sa = (struct sockaddr *)cp;
164 			switch (i) {
165 			case RTA_IFA:
166 			case RTA_DST:
167 			case RTA_GATEWAY:
168 			case RTA_NETMASK:
169 				if (sa->sa_family == AF_INET)
170 					return AF_INET;
171 				if (sa->sa_family == AF_INET6)
172 					return AF_INET6;
173 				break;
174 			case RTA_IFP:
175 				break;
176 			}
177 			ADVANCE(cp, sa);
178 		}
179 	}
180 	return (-1);
181 }
182 
183 struct sockaddr *
184 get_ifa(char *cp, int n)
185 {
186 	struct sockaddr *sa;
187 	unsigned i;
188 
189 	if (n == 0)
190 		return (NULL);
191 	for (i = 1; i; i <<= 1)
192 		if (i & n) {
193 			sa = (struct sockaddr *)cp;
194 			if (i == RTA_IFA)
195 				return (sa);
196 			ADVANCE(cp, sa);
197 		}
198 
199 	return (NULL);
200 }
201 
202 static struct iaddr defaddr = { .len = 4 };
203 static uint8_t curbssid[6];
204 
205 static void
206 disassoc(void *arg)
207 {
208 	struct interface_info *_ifi = arg;
209 
210 	/*
211 	 * Clear existing state.
212 	 */
213 	if (_ifi->client->active != NULL) {
214 		script_init("EXPIRE", NULL);
215 		script_write_params("old_",
216 		    _ifi->client->active);
217 		if (_ifi->client->alias)
218 			script_write_params("alias_",
219 				_ifi->client->alias);
220 		script_go();
221 	}
222 	_ifi->client->state = S_INIT;
223 }
224 
225 void
226 routehandler(struct protocol *p __unused)
227 {
228 	char msg[2048], *addr;
229 	struct rt_msghdr *rtm;
230 	struct if_msghdr *ifm;
231 	struct ifa_msghdr *ifam;
232 	struct if_announcemsghdr *ifan;
233 	struct ieee80211_join_event *jev;
234 	struct client_lease *l;
235 	time_t t = time(NULL);
236 	struct sockaddr_in *sa;
237 	struct iaddr a;
238 	ssize_t n;
239 	int linkstat;
240 
241 	n = read(routefd, &msg, sizeof(msg));
242 	rtm = (struct rt_msghdr *)msg;
243 	if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
244 	    n < (ssize_t)rtm->rtm_msglen ||
245 	    rtm->rtm_version != RTM_VERSION)
246 		return;
247 
248 	switch (rtm->rtm_type) {
249 	case RTM_NEWADDR:
250 	case RTM_DELADDR:
251 		ifam = (struct ifa_msghdr *)rtm;
252 
253 		if (ifam->ifam_index != ifi->index)
254 			break;
255 		if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
256 			break;
257 		if (scripttime == 0 || t < scripttime + 10)
258 			break;
259 
260 		sa = (struct sockaddr_in*)get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
261 		if (sa == NULL)
262 			break;
263 
264 		if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
265 			error("king bula sez: len mismatch");
266 		memcpy(a.iabuf, &sa->sin_addr, a.len);
267 		if (addr_eq(a, defaddr))
268 			break;
269 
270 		for (l = ifi->client->active; l != NULL; l = l->next)
271 			if (addr_eq(a, l->address))
272 				break;
273 
274 		if (l == NULL)	/* added/deleted addr is not the one we set */
275 			break;
276 
277 		addr = inet_ntoa(sa->sin_addr);
278 		if (rtm->rtm_type == RTM_NEWADDR)  {
279 			/*
280 			 * XXX: If someone other than us adds our address,
281 			 * should we assume they are taking over from us,
282 			 * delete the lease record, and exit without modifying
283 			 * the interface?
284 			 */
285 			warning("My address (%s) was re-added", addr);
286 		} else {
287 			warning("My address (%s) was deleted, dhclient exiting",
288 			    addr);
289 			goto die;
290 		}
291 		break;
292 	case RTM_IFINFO:
293 		ifm = (struct if_msghdr *)rtm;
294 		if (ifm->ifm_index != ifi->index)
295 			break;
296 		if ((rtm->rtm_flags & RTF_UP) == 0) {
297 			warning("Interface %s is down, dhclient exiting",
298 			    ifi->name);
299 			goto die;
300 		}
301 		linkstat = interface_link_status(ifi->name);
302 		if (linkstat != ifi->linkstat) {
303 			debug("%s link state %s -> %s", ifi->name,
304 			    ifi->linkstat ? "up" : "down",
305 			    linkstat ? "up" : "down");
306 			ifi->linkstat = linkstat;
307 			if (linkstat)
308 				state_reboot(ifi);
309 		}
310 		break;
311 	case RTM_IFANNOUNCE:
312 		ifan = (struct if_announcemsghdr *)rtm;
313 		if (ifan->ifan_what == IFAN_DEPARTURE &&
314 		    ifan->ifan_index == ifi->index) {
315 			warning("Interface %s is gone, dhclient exiting",
316 			    ifi->name);
317 			goto die;
318 		}
319 		break;
320 	case RTM_IEEE80211:
321 		ifan = (struct if_announcemsghdr *)rtm;
322 		if (ifan->ifan_index != ifi->index)
323 			break;
324 		switch (ifan->ifan_what) {
325 		case RTM_IEEE80211_ASSOC:
326 		case RTM_IEEE80211_REASSOC:
327 			/*
328 			 * Use assoc/reassoc event to kick state machine
329 			 * in case we roam.  Otherwise fall back to the
330 			 * normal state machine just like a wired network.
331 			 */
332 			jev = (struct ieee80211_join_event *) &ifan[1];
333 			if (memcmp(curbssid, jev->iev_addr, 6)) {
334 				disassoc(ifi);
335 				state_reboot(ifi);
336 			}
337 			memcpy(curbssid, jev->iev_addr, 6);
338 			break;
339 		}
340 		break;
341 	default:
342 		break;
343 	}
344 	return;
345 
346 die:
347 	script_init("FAIL", NULL);
348 	if (ifi->client->alias)
349 		script_write_params("alias_", ifi->client->alias);
350 	script_go();
351 	if (pidfile != NULL)
352 		pidfile_remove(pidfile);
353 	exit(1);
354 }
355 
356 static void
357 init_casper(void)
358 {
359 	cap_channel_t		*casper;
360 
361 	casper = cap_init();
362 	if (casper == NULL)
363 		error("unable to start casper");
364 
365 	capsyslog = cap_service_open(casper, "system.syslog");
366 	cap_close(casper);
367 	if (capsyslog == NULL)
368 		error("unable to open system.syslog service");
369 }
370 
371 int
372 main(int argc, char *argv[])
373 {
374 	u_int			 capmode;
375 	int			 ch, fd, quiet = 0, i = 0;
376 	int			 pipe_fd[2];
377 	int			 immediate_daemon = 0;
378 	struct passwd		*pw;
379 	pid_t			 otherpid;
380 	cap_rights_t		 rights;
381 
382 	init_casper();
383 
384 	/* Initially, log errors to stderr as well as to syslogd. */
385 	cap_openlog(capsyslog, getprogname(), LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
386 	cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
387 
388 	while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
389 		switch (ch) {
390 		case 'b':
391 			immediate_daemon = 1;
392 			break;
393 		case 'c':
394 			path_dhclient_conf = optarg;
395 			break;
396 		case 'd':
397 			no_daemon = 1;
398 			break;
399 		case 'l':
400 			path_dhclient_db = optarg;
401 			break;
402 		case 'p':
403 			path_dhclient_pidfile = optarg;
404 			break;
405 		case 'q':
406 			quiet = 1;
407 			break;
408 		case 'u':
409 			unknown_ok = 0;
410 			break;
411 		default:
412 			usage();
413 		}
414 
415 	argc -= optind;
416 	argv += optind;
417 
418 	if (argc != 1)
419 		usage();
420 
421 	if (path_dhclient_pidfile == NULL) {
422 		asprintf(&path_dhclient_pidfile,
423 		    "%s/dhclient/dhclient.%s.pid", _PATH_VARRUN, *argv);
424 		if (path_dhclient_pidfile == NULL)
425 			error("asprintf");
426 	}
427 	pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
428 	if (pidfile == NULL) {
429 		if (errno == EEXIST)
430 			error("dhclient already running, pid: %d.", otherpid);
431 		if (errno == EAGAIN)
432 			error("dhclient already running.");
433 		warning("Cannot open or create pidfile: %m");
434 	}
435 
436 	if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
437 		error("calloc");
438 	if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
439 		error("Interface name too long");
440 	if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
441 	    _PATH_DHCLIENT_DB, ifi->name) == -1)
442 		error("asprintf");
443 
444 	if (quiet)
445 		log_perror = 0;
446 
447 	tzset();
448 	time(&cur_time);
449 
450 	inaddr_broadcast.s_addr = INADDR_BROADCAST;
451 	inaddr_any.s_addr = INADDR_ANY;
452 
453 	read_client_conf();
454 
455 	/* The next bit is potentially very time-consuming, so write out
456 	   the pidfile right away.  We will write it out again with the
457 	   correct pid after daemonizing. */
458 	if (pidfile != NULL)
459 		pidfile_write(pidfile);
460 
461 	if (!interface_link_status(ifi->name)) {
462 		fprintf(stderr, "%s: no link ...", ifi->name);
463 		fflush(stderr);
464 		sleep(1);
465 		while (!interface_link_status(ifi->name)) {
466 			fprintf(stderr, ".");
467 			fflush(stderr);
468 			if (++i > 10) {
469 				fprintf(stderr, " giving up\n");
470 				exit(1);
471 			}
472 			sleep(1);
473 		}
474 		fprintf(stderr, " got link\n");
475 	}
476 	ifi->linkstat = 1;
477 
478 	if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
479 		error("cannot open %s: %m", _PATH_DEVNULL);
480 
481 	if ((pw = getpwnam("_dhcp")) == NULL) {
482 		warning("no such user: _dhcp, falling back to \"nobody\"");
483 		if ((pw = getpwnam("nobody")) == NULL)
484 			error("no such user: nobody");
485 	}
486 
487 	/*
488 	 * Obtain hostname before entering capability mode - it won't be
489 	 * possible then, as reading kern.hostname is not permitted.
490 	 */
491 	if (gethostname(hostname, sizeof(hostname)) < 0)
492 		hostname[0] = '\0';
493 
494 	priv_script_init("PREINIT", NULL);
495 	if (ifi->client->alias)
496 		priv_script_write_params("alias_", ifi->client->alias);
497 	priv_script_go();
498 
499 	/* set up the interface */
500 	discover_interfaces(ifi);
501 
502 	if (pipe(pipe_fd) == -1)
503 		error("pipe");
504 
505 	fork_privchld(pipe_fd[0], pipe_fd[1]);
506 
507 	close(ifi->ufdesc);
508 	ifi->ufdesc = -1;
509 	close(ifi->wfdesc);
510 	ifi->wfdesc = -1;
511 
512 	close(pipe_fd[0]);
513 	privfd = pipe_fd[1];
514 	cap_rights_init(&rights, CAP_READ, CAP_WRITE);
515 	if (caph_rights_limit(privfd, &rights) < 0)
516 		error("can't limit private descriptor: %m");
517 
518 	if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
519 		error("can't open and lock %s: %m", path_dhclient_db);
520 	read_client_leases();
521 	rewrite_client_leases();
522 	close(fd);
523 
524 	if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
525 		add_protocol("AF_ROUTE", routefd, routehandler, ifi);
526 	if (shutdown(routefd, SHUT_WR) < 0)
527 		error("can't shutdown route socket: %m");
528 	cap_rights_init(&rights, CAP_EVENT, CAP_READ);
529 	if (caph_rights_limit(routefd, &rights) < 0)
530 		error("can't limit route socket: %m");
531 
532 	endpwent();
533 
534 	setproctitle("%s", ifi->name);
535 
536 	/* setgroups(2) is not permitted in capability mode. */
537 	if (setgroups(1, &pw->pw_gid) != 0)
538 		error("can't restrict groups: %m");
539 
540 	if (caph_enter_casper() < 0)
541 		error("can't enter capability mode: %m");
542 
543 	/*
544 	 * If we are not in capability mode (i.e., Capsicum or libcasper is
545 	 * disabled), try to restrict filesystem access.  This will fail if
546 	 * kern.chroot_allow_open_directories is 0 or the process is jailed.
547 	 */
548 	if (cap_getmode(&capmode) < 0 || capmode == 0) {
549 		if (chroot(_PATH_VAREMPTY) == -1)
550 			error("chroot");
551 		if (chdir("/") == -1)
552 			error("chdir(\"/\")");
553 	}
554 
555 	if (setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
556 	    seteuid(pw->pw_uid) || setuid(pw->pw_uid))
557 		error("can't drop privileges: %m");
558 
559 	if (immediate_daemon)
560 		go_daemon();
561 
562 	ifi->client->state = S_INIT;
563 	state_reboot(ifi);
564 
565 	bootp_packet_handler = do_packet;
566 
567 	dispatch();
568 
569 	/* not reached */
570 	return (0);
571 }
572 
573 void
574 usage(void)
575 {
576 
577 	fprintf(stderr, "usage: %s [-bdqu] ", getprogname());
578 	fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
579 	exit(1);
580 }
581 
582 /*
583  * Individual States:
584  *
585  * Each routine is called from the dhclient_state_machine() in one of
586  * these conditions:
587  * -> entering INIT state
588  * -> recvpacket_flag == 0: timeout in this state
589  * -> otherwise: received a packet in this state
590  *
591  * Return conditions as handled by dhclient_state_machine():
592  * Returns 1, sendpacket_flag = 1: send packet, reset timer.
593  * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
594  * Returns 0: finish the nap which was interrupted for no good reason.
595  *
596  * Several per-interface variables are used to keep track of the process:
597  *   active_lease: the lease that is being used on the interface
598  *                 (null pointer if not configured yet).
599  *   offered_leases: leases corresponding to DHCPOFFER messages that have
600  *                   been sent to us by DHCP servers.
601  *   acked_leases: leases corresponding to DHCPACK messages that have been
602  *                 sent to us by DHCP servers.
603  *   sendpacket: DHCP packet we're trying to send.
604  *   destination: IP address to send sendpacket to
605  * In addition, there are several relevant per-lease variables.
606  *   T1_expiry, T2_expiry, lease_expiry: lease milestones
607  * In the active lease, these control the process of renewing the lease;
608  * In leases on the acked_leases list, this simply determines when we
609  * can no longer legitimately use the lease.
610  */
611 
612 void
613 state_reboot(void *ipp)
614 {
615 	struct interface_info *ip = ipp;
616 
617 	/* If we don't remember an active lease, go straight to INIT. */
618 	if (!ip->client->active || ip->client->active->is_bootp) {
619 		state_init(ip);
620 		return;
621 	}
622 
623 	/* We are in the rebooting state. */
624 	ip->client->state = S_REBOOTING;
625 
626 	/* make_request doesn't initialize xid because it normally comes
627 	   from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
628 	   so pick an xid now. */
629 	ip->client->xid = arc4random();
630 
631 	/* Make a DHCPREQUEST packet, and set appropriate per-interface
632 	   flags. */
633 	make_request(ip, ip->client->active);
634 	ip->client->destination = iaddr_broadcast;
635 	ip->client->first_sending = cur_time;
636 	ip->client->interval = ip->client->config->initial_interval;
637 
638 	/* Zap the medium list... */
639 	ip->client->medium = NULL;
640 
641 	/* Send out the first DHCPREQUEST packet. */
642 	send_request(ip);
643 }
644 
645 /*
646  * Called when a lease has completely expired and we've
647  * been unable to renew it.
648  */
649 void
650 state_init(void *ipp)
651 {
652 	struct interface_info *ip = ipp;
653 
654 	ASSERT_STATE(state, S_INIT);
655 
656 	/* Make a DHCPDISCOVER packet, and set appropriate per-interface
657 	   flags. */
658 	make_discover(ip, ip->client->active);
659 	ip->client->xid = ip->client->packet.xid;
660 	ip->client->destination = iaddr_broadcast;
661 	ip->client->state = S_SELECTING;
662 	ip->client->first_sending = cur_time;
663 	ip->client->interval = ip->client->config->initial_interval;
664 
665 	/* Add an immediate timeout to cause the first DHCPDISCOVER packet
666 	   to go out. */
667 	send_discover(ip);
668 }
669 
670 /*
671  * state_selecting is called when one or more DHCPOFFER packets
672  * have been received and a configurable period of time has passed.
673  */
674 void
675 state_selecting(void *ipp)
676 {
677 	struct interface_info *ip = ipp;
678 	struct client_lease *lp, *next, *picked;
679 
680 	ASSERT_STATE(state, S_SELECTING);
681 
682 	/* Cancel state_selecting and send_discover timeouts, since either
683 	   one could have got us here. */
684 	cancel_timeout(state_selecting, ip);
685 	cancel_timeout(send_discover, ip);
686 
687 	/* We have received one or more DHCPOFFER packets.   Currently,
688 	   the only criterion by which we judge leases is whether or
689 	   not we get a response when we arp for them. */
690 	picked = NULL;
691 	for (lp = ip->client->offered_leases; lp; lp = next) {
692 		next = lp->next;
693 
694 		/* Check to see if we got an ARPREPLY for the address
695 		   in this particular lease. */
696 		if (!picked) {
697 			script_init("ARPCHECK", lp->medium);
698 			script_write_params("check_", lp);
699 
700 			/* If the ARPCHECK code detects another
701 			   machine using the offered address, it exits
702 			   nonzero.  We need to send a DHCPDECLINE and
703 			   toss the lease. */
704 			if (script_go()) {
705 				make_decline(ip, lp);
706 				send_decline(ip);
707 				goto freeit;
708 			}
709 			picked = lp;
710 			picked->next = NULL;
711 		} else {
712 freeit:
713 			free_client_lease(lp);
714 		}
715 	}
716 	ip->client->offered_leases = NULL;
717 
718 	/* If we just tossed all the leases we were offered, go back
719 	   to square one. */
720 	if (!picked) {
721 		ip->client->state = S_INIT;
722 		state_init(ip);
723 		return;
724 	}
725 
726 	/* If it was a BOOTREPLY, we can just take the address right now. */
727 	if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
728 		ip->client->new = picked;
729 
730 		/* Make up some lease expiry times
731 		   XXX these should be configurable. */
732 		ip->client->new->expiry = cur_time + 12000;
733 		ip->client->new->renewal += cur_time + 8000;
734 		ip->client->new->rebind += cur_time + 10000;
735 
736 		ip->client->state = S_REQUESTING;
737 
738 		/* Bind to the address we received. */
739 		bind_lease(ip);
740 		return;
741 	}
742 
743 	/* Go to the REQUESTING state. */
744 	ip->client->destination = iaddr_broadcast;
745 	ip->client->state = S_REQUESTING;
746 	ip->client->first_sending = cur_time;
747 	ip->client->interval = ip->client->config->initial_interval;
748 
749 	/* Make a DHCPREQUEST packet from the lease we picked. */
750 	make_request(ip, picked);
751 	ip->client->xid = ip->client->packet.xid;
752 
753 	/* Toss the lease we picked - we'll get it back in a DHCPACK. */
754 	free_client_lease(picked);
755 
756 	/* Add an immediate timeout to send the first DHCPREQUEST packet. */
757 	send_request(ip);
758 }
759 
760 /* state_requesting is called when we receive a DHCPACK message after
761    having sent out one or more DHCPREQUEST packets. */
762 
763 void
764 dhcpack(struct packet *packet)
765 {
766 	struct interface_info *ip = packet->interface;
767 	struct client_lease *lease;
768 
769 	/* If we're not receptive to an offer right now, or if the offer
770 	   has an unrecognizable transaction id, then just drop it. */
771 	if (packet->interface->client->xid != packet->raw->xid ||
772 	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
773 	    (memcmp(packet->interface->hw_address.haddr,
774 	    packet->raw->chaddr, packet->raw->hlen)))
775 		return;
776 
777 	if (ip->client->state != S_REBOOTING &&
778 	    ip->client->state != S_REQUESTING &&
779 	    ip->client->state != S_RENEWING &&
780 	    ip->client->state != S_REBINDING)
781 		return;
782 
783 	note("DHCPACK from %s", piaddr(packet->client_addr));
784 
785 	lease = packet_to_lease(packet);
786 	if (!lease) {
787 		note("packet_to_lease failed.");
788 		return;
789 	}
790 
791 	ip->client->new = lease;
792 
793 	/* Stop resending DHCPREQUEST. */
794 	cancel_timeout(send_request, ip);
795 
796 	/* Figure out the lease time. */
797         if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
798             ACTION_SUPERSEDE)
799 		ip->client->new->expiry = getULong(
800 		    ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
801         else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
802 		ip->client->new->expiry = getULong(
803 		    ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
804 	else
805 		ip->client->new->expiry = default_lease_time;
806 	/* A number that looks negative here is really just very large,
807 	   because the lease expiry offset is unsigned. Also make sure that
808            the addition of cur_time below does not overflow (a 32 bit) time_t. */
809 	if (ip->client->new->expiry < 0 ||
810             ip->client->new->expiry > TIME_MAX - cur_time)
811 		ip->client->new->expiry = TIME_MAX - cur_time;
812 	/* XXX should be fixed by resetting the client state */
813 	if (ip->client->new->expiry < 60)
814 		ip->client->new->expiry = 60;
815 
816         /* Unless overridden in the config, take the server-provided renewal
817          * time if there is one. Otherwise figure it out according to the spec.
818          * Also make sure the renewal time does not exceed the expiry time.
819          */
820         if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
821             ACTION_SUPERSEDE)
822 		ip->client->new->renewal = getULong(
823 		    ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
824         else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
825 		ip->client->new->renewal = getULong(
826 		    ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
827 	else
828 		ip->client->new->renewal = ip->client->new->expiry / 2;
829         if (ip->client->new->renewal < 0 ||
830             ip->client->new->renewal > ip->client->new->expiry / 2)
831                 ip->client->new->renewal = ip->client->new->expiry / 2;
832 
833 	/* Same deal with the rebind time. */
834         if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
835             ACTION_SUPERSEDE)
836 		ip->client->new->rebind = getULong(
837 		    ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
838         else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
839 		ip->client->new->rebind = getULong(
840 		    ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
841 	else
842 		ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
843 	if (ip->client->new->rebind < 0 ||
844             ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
845                 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
846 
847         /* Convert the time offsets into seconds-since-the-epoch */
848         ip->client->new->expiry += cur_time;
849         ip->client->new->renewal += cur_time;
850         ip->client->new->rebind += cur_time;
851 
852 	bind_lease(ip);
853 }
854 
855 void
856 bind_lease(struct interface_info *ip)
857 {
858 	struct option_data *opt;
859 
860 	/* Remember the medium. */
861 	ip->client->new->medium = ip->client->medium;
862 
863 	opt = &ip->client->new->options[DHO_INTERFACE_MTU];
864 	if (opt->len == sizeof(u_int16_t)) {
865 		u_int16_t mtu = 0;
866 		bool supersede = (ip->client->config->default_actions[DHO_INTERFACE_MTU] ==
867 			ACTION_SUPERSEDE);
868 
869 		if (supersede)
870 			mtu = getUShort(ip->client->config->defaults[DHO_INTERFACE_MTU].data);
871 		else
872 			mtu = be16dec(opt->data);
873 
874 		if (mtu < MIN_MTU) {
875 			/* Treat 0 like a user intentionally doesn't want to change MTU and,
876 			 * therefore, warning is not needed */
877 			if (!supersede || mtu != 0)
878 				warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
879 		} else {
880 			interface_set_mtu_unpriv(privfd, mtu);
881 		}
882 	}
883 
884 	/* Write out the new lease. */
885 	write_client_lease(ip, ip->client->new, 0);
886 
887 	/* Run the client script with the new parameters. */
888 	script_init((ip->client->state == S_REQUESTING ? "BOUND" :
889 	    (ip->client->state == S_RENEWING ? "RENEW" :
890 	    (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
891 	    ip->client->new->medium);
892 	if (ip->client->active && ip->client->state != S_REBOOTING)
893 		script_write_params("old_", ip->client->active);
894 	script_write_params("new_", ip->client->new);
895 	if (ip->client->alias)
896 		script_write_params("alias_", ip->client->alias);
897 	script_go();
898 
899 	/* Replace the old active lease with the new one. */
900 	if (ip->client->active)
901 		free_client_lease(ip->client->active);
902 	ip->client->active = ip->client->new;
903 	ip->client->new = NULL;
904 
905 	/* Set up a timeout to start the renewal process. */
906 	add_timeout(ip->client->active->renewal, state_bound, ip);
907 
908 	note("bound to %s -- renewal in %d seconds.",
909 	    piaddr(ip->client->active->address),
910 	    (int)(ip->client->active->renewal - cur_time));
911 	ip->client->state = S_BOUND;
912 	reinitialize_interfaces();
913 	go_daemon();
914 }
915 
916 /*
917  * state_bound is called when we've successfully bound to a particular
918  * lease, but the renewal time on that lease has expired.   We are
919  * expected to unicast a DHCPREQUEST to the server that gave us our
920  * original lease.
921  */
922 void
923 state_bound(void *ipp)
924 {
925 	struct interface_info *ip = ipp;
926 
927 	ASSERT_STATE(state, S_BOUND);
928 
929 	/* T1 has expired. */
930 	make_request(ip, ip->client->active);
931 	ip->client->xid = ip->client->packet.xid;
932 
933 	if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
934 		memcpy(ip->client->destination.iabuf, ip->client->active->
935 		    options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
936 		ip->client->destination.len = 4;
937 	} else
938 		ip->client->destination = iaddr_broadcast;
939 
940 	ip->client->first_sending = cur_time;
941 	ip->client->interval = ip->client->config->initial_interval;
942 	ip->client->state = S_RENEWING;
943 
944 	/* Send the first packet immediately. */
945 	send_request(ip);
946 }
947 
948 void
949 bootp(struct packet *packet)
950 {
951 	struct iaddrlist *ap;
952 
953 	if (packet->raw->op != BOOTREPLY)
954 		return;
955 
956 	/* If there's a reject list, make sure this packet's sender isn't
957 	   on it. */
958 	for (ap = packet->interface->client->config->reject_list;
959 	    ap; ap = ap->next) {
960 		if (addr_eq(packet->client_addr, ap->addr)) {
961 			note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
962 			return;
963 		}
964 	}
965 	dhcpoffer(packet);
966 }
967 
968 void
969 dhcp(struct packet *packet)
970 {
971 	struct iaddrlist *ap;
972 	void (*handler)(struct packet *);
973 	const char *type;
974 
975 	switch (packet->packet_type) {
976 	case DHCPOFFER:
977 		handler = dhcpoffer;
978 		type = "DHCPOFFER";
979 		break;
980 	case DHCPNAK:
981 		handler = dhcpnak;
982 		type = "DHCPNACK";
983 		break;
984 	case DHCPACK:
985 		handler = dhcpack;
986 		type = "DHCPACK";
987 		break;
988 	default:
989 		return;
990 	}
991 
992 	/* If there's a reject list, make sure this packet's sender isn't
993 	   on it. */
994 	for (ap = packet->interface->client->config->reject_list;
995 	    ap; ap = ap->next) {
996 		if (addr_eq(packet->client_addr, ap->addr)) {
997 			note("%s from %s rejected.", type, piaddr(ap->addr));
998 			return;
999 		}
1000 	}
1001 	(*handler)(packet);
1002 }
1003 
1004 void
1005 dhcpoffer(struct packet *packet)
1006 {
1007 	struct interface_info *ip = packet->interface;
1008 	struct client_lease *lease, *lp;
1009 	int i;
1010 	int arp_timeout_needed, stop_selecting;
1011 	const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
1012 	    "DHCPOFFER" : "BOOTREPLY";
1013 
1014 	/* If we're not receptive to an offer right now, or if the offer
1015 	   has an unrecognizable transaction id, then just drop it. */
1016 	if (ip->client->state != S_SELECTING ||
1017 	    packet->interface->client->xid != packet->raw->xid ||
1018 	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1019 	    (memcmp(packet->interface->hw_address.haddr,
1020 	    packet->raw->chaddr, packet->raw->hlen)))
1021 		return;
1022 
1023 	note("%s from %s", name, piaddr(packet->client_addr));
1024 
1025 
1026 	/* If this lease doesn't supply the minimum required parameters,
1027 	   blow it off. */
1028 	for (i = 0; ip->client->config->required_options[i]; i++) {
1029 		if (!packet->options[ip->client->config->
1030 		    required_options[i]].len) {
1031 			note("%s isn't satisfactory.", name);
1032 			return;
1033 		}
1034 	}
1035 
1036 	/* If we've already seen this lease, don't record it again. */
1037 	for (lease = ip->client->offered_leases;
1038 	    lease; lease = lease->next) {
1039 		if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1040 		    !memcmp(lease->address.iabuf,
1041 		    &packet->raw->yiaddr, lease->address.len)) {
1042 			debug("%s already seen.", name);
1043 			return;
1044 		}
1045 	}
1046 
1047 	lease = packet_to_lease(packet);
1048 	if (!lease) {
1049 		note("packet_to_lease failed.");
1050 		return;
1051 	}
1052 
1053 	/* If this lease was acquired through a BOOTREPLY, record that
1054 	   fact. */
1055 	if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1056 		lease->is_bootp = 1;
1057 
1058 	/* Record the medium under which this lease was offered. */
1059 	lease->medium = ip->client->medium;
1060 
1061 	/* Send out an ARP Request for the offered IP address. */
1062 	script_init("ARPSEND", lease->medium);
1063 	script_write_params("check_", lease);
1064 	/* If the script can't send an ARP request without waiting,
1065 	   we'll be waiting when we do the ARPCHECK, so don't wait now. */
1066 	if (script_go())
1067 		arp_timeout_needed = 0;
1068 	else
1069 		arp_timeout_needed = 2;
1070 
1071 	/* Figure out when we're supposed to stop selecting. */
1072 	stop_selecting =
1073 	    ip->client->first_sending + ip->client->config->select_interval;
1074 
1075 	/* If this is the lease we asked for, put it at the head of the
1076 	   list, and don't mess with the arp request timeout. */
1077 	if (lease->address.len == ip->client->requested_address.len &&
1078 	    !memcmp(lease->address.iabuf,
1079 	    ip->client->requested_address.iabuf,
1080 	    ip->client->requested_address.len)) {
1081 		lease->next = ip->client->offered_leases;
1082 		ip->client->offered_leases = lease;
1083 	} else {
1084 		/* If we already have an offer, and arping for this
1085 		   offer would take us past the selection timeout,
1086 		   then don't extend the timeout - just hope for the
1087 		   best. */
1088 		if (ip->client->offered_leases &&
1089 		    (cur_time + arp_timeout_needed) > stop_selecting)
1090 			arp_timeout_needed = 0;
1091 
1092 		/* Put the lease at the end of the list. */
1093 		lease->next = NULL;
1094 		if (!ip->client->offered_leases)
1095 			ip->client->offered_leases = lease;
1096 		else {
1097 			for (lp = ip->client->offered_leases; lp->next;
1098 			    lp = lp->next)
1099 				;	/* nothing */
1100 			lp->next = lease;
1101 		}
1102 	}
1103 
1104 	/* If we're supposed to stop selecting before we've had time
1105 	   to wait for the ARPREPLY, add some delay to wait for
1106 	   the ARPREPLY. */
1107 	if (stop_selecting - cur_time < arp_timeout_needed)
1108 		stop_selecting = cur_time + arp_timeout_needed;
1109 
1110 	/* If the selecting interval has expired, go immediately to
1111 	   state_selecting().  Otherwise, time out into
1112 	   state_selecting at the select interval. */
1113 	if (stop_selecting <= 0)
1114 		state_selecting(ip);
1115 	else {
1116 		add_timeout(stop_selecting, state_selecting, ip);
1117 		cancel_timeout(send_discover, ip);
1118 	}
1119 }
1120 
1121 /* Allocate a client_lease structure and initialize it from the parameters
1122    in the specified packet. */
1123 
1124 struct client_lease *
1125 packet_to_lease(struct packet *packet)
1126 {
1127 	struct client_lease *lease;
1128 	int i;
1129 
1130 	lease = malloc(sizeof(struct client_lease));
1131 
1132 	if (!lease) {
1133 		warning("dhcpoffer: no memory to record lease.");
1134 		return (NULL);
1135 	}
1136 
1137 	memset(lease, 0, sizeof(*lease));
1138 
1139 	/* Copy the lease options. */
1140 	for (i = 0; i < 256; i++) {
1141 		if (packet->options[i].len) {
1142 			lease->options[i].data =
1143 			    malloc(packet->options[i].len + 1);
1144 			if (!lease->options[i].data) {
1145 				warning("dhcpoffer: no memory for option %d", i);
1146 				free_client_lease(lease);
1147 				return (NULL);
1148 			} else {
1149 				memcpy(lease->options[i].data,
1150 				    packet->options[i].data,
1151 				    packet->options[i].len);
1152 				lease->options[i].len =
1153 				    packet->options[i].len;
1154 				lease->options[i].data[lease->options[i].len] =
1155 				    0;
1156 			}
1157 			if (!check_option(lease,i)) {
1158 				/* ignore a bogus lease offer */
1159 				warning("Invalid lease option - ignoring offer");
1160 				free_client_lease(lease);
1161 				return (NULL);
1162 			}
1163 		}
1164 	}
1165 
1166 	lease->address.len = sizeof(packet->raw->yiaddr);
1167 	memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1168 
1169 	lease->nextserver.len = sizeof(packet->raw->siaddr);
1170 	memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1171 
1172 	/* If the server name was filled out, copy it.
1173 	   Do not attempt to validate the server name as a host name.
1174 	   RFC 2131 merely states that sname is NUL-terminated (which do
1175 	   do not assume) and that it is the server's host name.  Since
1176 	   the ISC client and server allow arbitrary characters, we do
1177 	   as well. */
1178 	if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1179 	    !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1180 	    packet->raw->sname[0]) {
1181 		lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1182 		if (!lease->server_name) {
1183 			warning("dhcpoffer: no memory for server name.");
1184 			free_client_lease(lease);
1185 			return (NULL);
1186 		}
1187 		memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1188 		lease->server_name[DHCP_SNAME_LEN]='\0';
1189 	}
1190 
1191 	/* Ditto for the filename. */
1192 	if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1193 	    !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1194 	    packet->raw->file[0]) {
1195 		/* Don't count on the NUL terminator. */
1196 		lease->filename = malloc(DHCP_FILE_LEN + 1);
1197 		if (!lease->filename) {
1198 			warning("dhcpoffer: no memory for filename.");
1199 			free_client_lease(lease);
1200 			return (NULL);
1201 		}
1202 		memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1203 		lease->filename[DHCP_FILE_LEN]='\0';
1204 	}
1205 	return lease;
1206 }
1207 
1208 void
1209 dhcpnak(struct packet *packet)
1210 {
1211 	struct interface_info *ip = packet->interface;
1212 
1213 	/* If we're not receptive to an offer right now, or if the offer
1214 	   has an unrecognizable transaction id, then just drop it. */
1215 	if (packet->interface->client->xid != packet->raw->xid ||
1216 	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1217 	    (memcmp(packet->interface->hw_address.haddr,
1218 	    packet->raw->chaddr, packet->raw->hlen)))
1219 		return;
1220 
1221 	if (ip->client->state != S_REBOOTING &&
1222 	    ip->client->state != S_REQUESTING &&
1223 	    ip->client->state != S_RENEWING &&
1224 	    ip->client->state != S_REBINDING)
1225 		return;
1226 
1227 	note("DHCPNAK from %s", piaddr(packet->client_addr));
1228 
1229 	if (!ip->client->active) {
1230 		note("DHCPNAK with no active lease.\n");
1231 		return;
1232 	}
1233 
1234 	free_client_lease(ip->client->active);
1235 	ip->client->active = NULL;
1236 
1237 	/* Stop sending DHCPREQUEST packets... */
1238 	cancel_timeout(send_request, ip);
1239 
1240 	ip->client->state = S_INIT;
1241 	state_init(ip);
1242 }
1243 
1244 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1245    one after the right interval has expired.  If we don't get an offer by
1246    the time we reach the panic interval, call the panic function. */
1247 
1248 void
1249 send_discover(void *ipp)
1250 {
1251 	struct interface_info *ip = ipp;
1252 	int interval, increase = 1;
1253 
1254 	/* Figure out how long it's been since we started transmitting. */
1255 	interval = cur_time - ip->client->first_sending;
1256 
1257 	/* If we're past the panic timeout, call the script and tell it
1258 	   we haven't found anything for this interface yet. */
1259 	if (interval > ip->client->config->timeout) {
1260 		state_panic(ip);
1261 		return;
1262 	}
1263 
1264 	/* If we're selecting media, try the whole list before doing
1265 	   the exponential backoff, but if we've already received an
1266 	   offer, stop looping, because we obviously have it right. */
1267 	if (!ip->client->offered_leases &&
1268 	    ip->client->config->media) {
1269 		int fail = 0;
1270 again:
1271 		if (ip->client->medium) {
1272 			ip->client->medium = ip->client->medium->next;
1273 			increase = 0;
1274 		}
1275 		if (!ip->client->medium) {
1276 			if (fail)
1277 				error("No valid media types for %s!", ip->name);
1278 			ip->client->medium = ip->client->config->media;
1279 			increase = 1;
1280 		}
1281 
1282 		note("Trying medium \"%s\" %d", ip->client->medium->string,
1283 		    increase);
1284 		script_init("MEDIUM", ip->client->medium);
1285 		if (script_go())
1286 			goto again;
1287 	}
1288 
1289 	/*
1290 	 * If we're supposed to increase the interval, do so.  If it's
1291 	 * currently zero (i.e., we haven't sent any packets yet), set
1292 	 * it to one; otherwise, add to it a random number between zero
1293 	 * and two times itself.  On average, this means that it will
1294 	 * double with every transmission.
1295 	 */
1296 	if (increase) {
1297 		if (!ip->client->interval)
1298 			ip->client->interval =
1299 			    ip->client->config->initial_interval;
1300 		else {
1301 			ip->client->interval += (arc4random() >> 2) %
1302 			    (2 * ip->client->interval);
1303 		}
1304 
1305 		/* Don't backoff past cutoff. */
1306 		if (ip->client->interval >
1307 		    ip->client->config->backoff_cutoff)
1308 			ip->client->interval =
1309 				((ip->client->config->backoff_cutoff / 2)
1310 				 + ((arc4random() >> 2) %
1311 				    ip->client->config->backoff_cutoff));
1312 	} else if (!ip->client->interval)
1313 		ip->client->interval =
1314 			ip->client->config->initial_interval;
1315 
1316 	/* If the backoff would take us to the panic timeout, just use that
1317 	   as the interval. */
1318 	if (cur_time + ip->client->interval >
1319 	    ip->client->first_sending + ip->client->config->timeout)
1320 		ip->client->interval =
1321 			(ip->client->first_sending +
1322 			 ip->client->config->timeout) - cur_time + 1;
1323 
1324 	/* Record the number of seconds since we started sending. */
1325 	if (interval < 65536)
1326 		ip->client->packet.secs = htons(interval);
1327 	else
1328 		ip->client->packet.secs = htons(65535);
1329 	ip->client->secs = ip->client->packet.secs;
1330 
1331 	note("DHCPDISCOVER on %s to %s port %d interval %d",
1332 	    ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1333 	    (int)ip->client->interval);
1334 
1335 	/* Send out a packet. */
1336 	send_packet_unpriv(privfd, &ip->client->packet,
1337 	    ip->client->packet_length, inaddr_any, inaddr_broadcast);
1338 
1339 	add_timeout(cur_time + ip->client->interval, send_discover, ip);
1340 }
1341 
1342 /*
1343  * state_panic gets called if we haven't received any offers in a preset
1344  * amount of time.   When this happens, we try to use existing leases
1345  * that haven't yet expired, and failing that, we call the client script
1346  * and hope it can do something.
1347  */
1348 void
1349 state_panic(void *ipp)
1350 {
1351 	struct interface_info *ip = ipp;
1352 	struct client_lease *loop = ip->client->active;
1353 	struct client_lease *lp;
1354 
1355 	note("No DHCPOFFERS received.");
1356 
1357 	/* We may not have an active lease, but we may have some
1358 	   predefined leases that we can try. */
1359 	if (!ip->client->active && ip->client->leases)
1360 		goto activate_next;
1361 
1362 	/* Run through the list of leases and see if one can be used. */
1363 	while (ip->client->active) {
1364 		if (ip->client->active->expiry > cur_time) {
1365 			note("Trying recorded lease %s",
1366 			    piaddr(ip->client->active->address));
1367 			/* Run the client script with the existing
1368 			   parameters. */
1369 			script_init("TIMEOUT",
1370 			    ip->client->active->medium);
1371 			script_write_params("new_", ip->client->active);
1372 			if (ip->client->alias)
1373 				script_write_params("alias_",
1374 				    ip->client->alias);
1375 
1376 			/* If the old lease is still good and doesn't
1377 			   yet need renewal, go into BOUND state and
1378 			   timeout at the renewal time. */
1379 			if (!script_go()) {
1380 				if (cur_time <
1381 				    ip->client->active->renewal) {
1382 					ip->client->state = S_BOUND;
1383 					note("bound: renewal in %d seconds.",
1384 					    (int)(ip->client->active->renewal -
1385 					    cur_time));
1386 					add_timeout(
1387 					    ip->client->active->renewal,
1388 					    state_bound, ip);
1389 				} else {
1390 					ip->client->state = S_BOUND;
1391 					note("bound: immediate renewal.");
1392 					state_bound(ip);
1393 				}
1394 				reinitialize_interfaces();
1395 				go_daemon();
1396 				return;
1397 			}
1398 		}
1399 
1400 		/* If there are no other leases, give up. */
1401 		if (!ip->client->leases) {
1402 			ip->client->leases = ip->client->active;
1403 			ip->client->active = NULL;
1404 			break;
1405 		}
1406 
1407 activate_next:
1408 		/* Otherwise, put the active lease at the end of the
1409 		   lease list, and try another lease.. */
1410 		for (lp = ip->client->leases; lp->next; lp = lp->next)
1411 			;
1412 		lp->next = ip->client->active;
1413 		if (lp->next)
1414 			lp->next->next = NULL;
1415 		ip->client->active = ip->client->leases;
1416 		ip->client->leases = ip->client->leases->next;
1417 
1418 		/* If we already tried this lease, we've exhausted the
1419 		   set of leases, so we might as well give up for
1420 		   now. */
1421 		if (ip->client->active == loop)
1422 			break;
1423 		else if (!loop)
1424 			loop = ip->client->active;
1425 	}
1426 
1427 	/* No leases were available, or what was available didn't work, so
1428 	   tell the shell script that we failed to allocate an address,
1429 	   and try again later. */
1430 	note("No working leases in persistent database - sleeping.\n");
1431 	script_init("FAIL", NULL);
1432 	if (ip->client->alias)
1433 		script_write_params("alias_", ip->client->alias);
1434 	script_go();
1435 	ip->client->state = S_INIT;
1436 	add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1437 	    ip);
1438 	go_daemon();
1439 }
1440 
1441 void
1442 send_request(void *ipp)
1443 {
1444 	struct interface_info *ip = ipp;
1445 	struct in_addr from, to;
1446 	int interval;
1447 
1448 	/* Figure out how long it's been since we started transmitting. */
1449 	interval = cur_time - ip->client->first_sending;
1450 
1451 	/* If we're in the INIT-REBOOT or REQUESTING state and we're
1452 	   past the reboot timeout, go to INIT and see if we can
1453 	   DISCOVER an address... */
1454 	/* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1455 	   means either that we're on a network with no DHCP server,
1456 	   or that our server is down.  In the latter case, assuming
1457 	   that there is a backup DHCP server, DHCPDISCOVER will get
1458 	   us a new address, but we could also have successfully
1459 	   reused our old address.  In the former case, we're hosed
1460 	   anyway.  This is not a win-prone situation. */
1461 	if ((ip->client->state == S_REBOOTING ||
1462 	    ip->client->state == S_REQUESTING) &&
1463 	    interval > ip->client->config->reboot_timeout) {
1464 cancel:
1465 		ip->client->state = S_INIT;
1466 		cancel_timeout(send_request, ip);
1467 		state_init(ip);
1468 		return;
1469 	}
1470 
1471 	/* If we're in the reboot state, make sure the media is set up
1472 	   correctly. */
1473 	if (ip->client->state == S_REBOOTING &&
1474 	    !ip->client->medium &&
1475 	    ip->client->active->medium ) {
1476 		script_init("MEDIUM", ip->client->active->medium);
1477 
1478 		/* If the medium we chose won't fly, go to INIT state. */
1479 		if (script_go())
1480 			goto cancel;
1481 
1482 		/* Record the medium. */
1483 		ip->client->medium = ip->client->active->medium;
1484 	}
1485 
1486 	/* If the lease has expired, relinquish the address and go back
1487 	   to the INIT state. */
1488 	if (ip->client->state != S_REQUESTING &&
1489 	    cur_time > ip->client->active->expiry) {
1490 		/* Run the client script with the new parameters. */
1491 		script_init("EXPIRE", NULL);
1492 		script_write_params("old_", ip->client->active);
1493 		if (ip->client->alias)
1494 			script_write_params("alias_", ip->client->alias);
1495 		script_go();
1496 
1497 		/* Now do a preinit on the interface so that we can
1498 		   discover a new address. */
1499 		script_init("PREINIT", NULL);
1500 		if (ip->client->alias)
1501 			script_write_params("alias_", ip->client->alias);
1502 		script_go();
1503 
1504 		ip->client->state = S_INIT;
1505 		state_init(ip);
1506 		return;
1507 	}
1508 
1509 	/* Do the exponential backoff... */
1510 	if (!ip->client->interval)
1511 		ip->client->interval = ip->client->config->initial_interval;
1512 	else
1513 		ip->client->interval += ((arc4random() >> 2) %
1514 		    (2 * ip->client->interval));
1515 
1516 	/* Don't backoff past cutoff. */
1517 	if (ip->client->interval >
1518 	    ip->client->config->backoff_cutoff)
1519 		ip->client->interval =
1520 		    ((ip->client->config->backoff_cutoff / 2) +
1521 		    ((arc4random() >> 2) % ip->client->interval));
1522 
1523 	/* If the backoff would take us to the expiry time, just set the
1524 	   timeout to the expiry time. */
1525 	if (ip->client->state != S_REQUESTING &&
1526 	    cur_time + ip->client->interval >
1527 	    ip->client->active->expiry)
1528 		ip->client->interval =
1529 		    ip->client->active->expiry - cur_time + 1;
1530 
1531 	/* If the lease T2 time has elapsed, or if we're not yet bound,
1532 	   broadcast the DHCPREQUEST rather than unicasting. */
1533 	if (ip->client->state == S_REQUESTING ||
1534 	    ip->client->state == S_REBOOTING ||
1535 	    cur_time > ip->client->active->rebind)
1536 		to.s_addr = INADDR_BROADCAST;
1537 	else
1538 		memcpy(&to.s_addr, ip->client->destination.iabuf,
1539 		    sizeof(to.s_addr));
1540 
1541 	if (ip->client->state != S_REQUESTING &&
1542 	    ip->client->state != S_REBOOTING)
1543 		memcpy(&from, ip->client->active->address.iabuf,
1544 		    sizeof(from));
1545 	else
1546 		from.s_addr = INADDR_ANY;
1547 
1548 	/* Record the number of seconds since we started sending. */
1549 	if (ip->client->state == S_REQUESTING)
1550 		ip->client->packet.secs = ip->client->secs;
1551 	else {
1552 		if (interval < 65536)
1553 			ip->client->packet.secs = htons(interval);
1554 		else
1555 			ip->client->packet.secs = htons(65535);
1556 	}
1557 
1558 	note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1559 	    REMOTE_PORT);
1560 
1561 	/* Send out a packet. */
1562 	send_packet_unpriv(privfd, &ip->client->packet,
1563 	    ip->client->packet_length, from, to);
1564 
1565 	add_timeout(cur_time + ip->client->interval, send_request, ip);
1566 }
1567 
1568 void
1569 send_decline(void *ipp)
1570 {
1571 	struct interface_info *ip = ipp;
1572 
1573 	note("DHCPDECLINE on %s to %s port %d", ip->name,
1574 	    inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1575 
1576 	/* Send out a packet. */
1577 	send_packet_unpriv(privfd, &ip->client->packet,
1578 	    ip->client->packet_length, inaddr_any, inaddr_broadcast);
1579 }
1580 
1581 void
1582 make_discover(struct interface_info *ip, struct client_lease *lease)
1583 {
1584 	unsigned char discover = DHCPDISCOVER;
1585 	struct tree_cache *options[256];
1586 	struct tree_cache option_elements[256];
1587 	int i;
1588 
1589 	memset(option_elements, 0, sizeof(option_elements));
1590 	memset(options, 0, sizeof(options));
1591 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1592 
1593 	/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1594 	i = DHO_DHCP_MESSAGE_TYPE;
1595 	options[i] = &option_elements[i];
1596 	options[i]->value = &discover;
1597 	options[i]->len = sizeof(discover);
1598 	options[i]->buf_size = sizeof(discover);
1599 	options[i]->timeout = 0xFFFFFFFF;
1600 
1601 	/* Request the options we want */
1602 	i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1603 	options[i] = &option_elements[i];
1604 	options[i]->value = ip->client->config->requested_options;
1605 	options[i]->len = ip->client->config->requested_option_count;
1606 	options[i]->buf_size =
1607 		ip->client->config->requested_option_count;
1608 	options[i]->timeout = 0xFFFFFFFF;
1609 
1610 	/* If we had an address, try to get it again. */
1611 	if (lease) {
1612 		ip->client->requested_address = lease->address;
1613 		i = DHO_DHCP_REQUESTED_ADDRESS;
1614 		options[i] = &option_elements[i];
1615 		options[i]->value = lease->address.iabuf;
1616 		options[i]->len = lease->address.len;
1617 		options[i]->buf_size = lease->address.len;
1618 		options[i]->timeout = 0xFFFFFFFF;
1619 	} else
1620 		ip->client->requested_address.len = 0;
1621 
1622 	/* Send any options requested in the config file. */
1623 	for (i = 0; i < 256; i++)
1624 		if (!options[i] &&
1625 		    ip->client->config->send_options[i].data) {
1626 			options[i] = &option_elements[i];
1627 			options[i]->value =
1628 			    ip->client->config->send_options[i].data;
1629 			options[i]->len =
1630 			    ip->client->config->send_options[i].len;
1631 			options[i]->buf_size =
1632 			    ip->client->config->send_options[i].len;
1633 			options[i]->timeout = 0xFFFFFFFF;
1634 		}
1635 
1636 	/* send host name if not set via config file. */
1637 	if (!options[DHO_HOST_NAME]) {
1638 		if (hostname[0] != '\0') {
1639 			size_t len;
1640 			char* posDot = strchr(hostname, '.');
1641 			if (posDot != NULL)
1642 				len = posDot - hostname;
1643 			else
1644 				len = strlen(hostname);
1645 			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1646 			options[DHO_HOST_NAME]->value = hostname;
1647 			options[DHO_HOST_NAME]->len = len;
1648 			options[DHO_HOST_NAME]->buf_size = len;
1649 			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1650 		}
1651 	}
1652 
1653 	/* set unique client identifier */
1654 	char client_ident[sizeof(ip->hw_address.haddr) + 1];
1655 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1656 		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1657 				ip->hw_address.hlen : sizeof(client_ident)-1;
1658 		client_ident[0] = ip->hw_address.htype;
1659 		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1660 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1661 		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1662 		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1663 		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1664 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1665 	}
1666 
1667 	/* Set up the option buffer... */
1668 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1669 	    options, 0, 0, 0, NULL, 0);
1670 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1671 		ip->client->packet_length = BOOTP_MIN_LEN;
1672 
1673 	ip->client->packet.op = BOOTREQUEST;
1674 	ip->client->packet.htype = ip->hw_address.htype;
1675 	ip->client->packet.hlen = ip->hw_address.hlen;
1676 	ip->client->packet.hops = 0;
1677 	ip->client->packet.xid = arc4random();
1678 	ip->client->packet.secs = 0; /* filled in by send_discover. */
1679 	ip->client->packet.flags = 0;
1680 
1681 	memset(&(ip->client->packet.ciaddr),
1682 	    0, sizeof(ip->client->packet.ciaddr));
1683 	memset(&(ip->client->packet.yiaddr),
1684 	    0, sizeof(ip->client->packet.yiaddr));
1685 	memset(&(ip->client->packet.siaddr),
1686 	    0, sizeof(ip->client->packet.siaddr));
1687 	memset(&(ip->client->packet.giaddr),
1688 	    0, sizeof(ip->client->packet.giaddr));
1689 	memcpy(ip->client->packet.chaddr,
1690 	    ip->hw_address.haddr, ip->hw_address.hlen);
1691 }
1692 
1693 
1694 void
1695 make_request(struct interface_info *ip, struct client_lease * lease)
1696 {
1697 	unsigned char request = DHCPREQUEST;
1698 	struct tree_cache *options[256];
1699 	struct tree_cache option_elements[256];
1700 	int i;
1701 
1702 	memset(options, 0, sizeof(options));
1703 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1704 
1705 	/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1706 	i = DHO_DHCP_MESSAGE_TYPE;
1707 	options[i] = &option_elements[i];
1708 	options[i]->value = &request;
1709 	options[i]->len = sizeof(request);
1710 	options[i]->buf_size = sizeof(request);
1711 	options[i]->timeout = 0xFFFFFFFF;
1712 
1713 	/* Request the options we want */
1714 	i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1715 	options[i] = &option_elements[i];
1716 	options[i]->value = ip->client->config->requested_options;
1717 	options[i]->len = ip->client->config->requested_option_count;
1718 	options[i]->buf_size =
1719 		ip->client->config->requested_option_count;
1720 	options[i]->timeout = 0xFFFFFFFF;
1721 
1722 	/* If we are requesting an address that hasn't yet been assigned
1723 	   to us, use the DHCP Requested Address option. */
1724 	if (ip->client->state == S_REQUESTING) {
1725 		/* Send back the server identifier... */
1726 		i = DHO_DHCP_SERVER_IDENTIFIER;
1727 		options[i] = &option_elements[i];
1728 		options[i]->value = lease->options[i].data;
1729 		options[i]->len = lease->options[i].len;
1730 		options[i]->buf_size = lease->options[i].len;
1731 		options[i]->timeout = 0xFFFFFFFF;
1732 	}
1733 	if (ip->client->state == S_REQUESTING ||
1734 	    ip->client->state == S_REBOOTING) {
1735 		ip->client->requested_address = lease->address;
1736 		i = DHO_DHCP_REQUESTED_ADDRESS;
1737 		options[i] = &option_elements[i];
1738 		options[i]->value = lease->address.iabuf;
1739 		options[i]->len = lease->address.len;
1740 		options[i]->buf_size = lease->address.len;
1741 		options[i]->timeout = 0xFFFFFFFF;
1742 	} else
1743 		ip->client->requested_address.len = 0;
1744 
1745 	/* Send any options requested in the config file. */
1746 	for (i = 0; i < 256; i++)
1747 		if (!options[i] &&
1748 		    ip->client->config->send_options[i].data) {
1749 			options[i] = &option_elements[i];
1750 			options[i]->value =
1751 			    ip->client->config->send_options[i].data;
1752 			options[i]->len =
1753 			    ip->client->config->send_options[i].len;
1754 			options[i]->buf_size =
1755 			    ip->client->config->send_options[i].len;
1756 			options[i]->timeout = 0xFFFFFFFF;
1757 		}
1758 
1759 	/* send host name if not set via config file. */
1760 	if (!options[DHO_HOST_NAME]) {
1761 		if (hostname[0] != '\0') {
1762 			size_t len;
1763 			char* posDot = strchr(hostname, '.');
1764 			if (posDot != NULL)
1765 				len = posDot - hostname;
1766 			else
1767 				len = strlen(hostname);
1768 			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1769 			options[DHO_HOST_NAME]->value = hostname;
1770 			options[DHO_HOST_NAME]->len = len;
1771 			options[DHO_HOST_NAME]->buf_size = len;
1772 			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1773 		}
1774 	}
1775 
1776 	/* set unique client identifier */
1777 	char client_ident[sizeof(struct hardware)];
1778 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1779 		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1780 				ip->hw_address.hlen : sizeof(client_ident)-1;
1781 		client_ident[0] = ip->hw_address.htype;
1782 		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1783 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1784 		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1785 		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1786 		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1787 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1788 	}
1789 
1790 	/* Set up the option buffer... */
1791 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1792 	    options, 0, 0, 0, NULL, 0);
1793 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1794 		ip->client->packet_length = BOOTP_MIN_LEN;
1795 
1796 	ip->client->packet.op = BOOTREQUEST;
1797 	ip->client->packet.htype = ip->hw_address.htype;
1798 	ip->client->packet.hlen = ip->hw_address.hlen;
1799 	ip->client->packet.hops = 0;
1800 	ip->client->packet.xid = ip->client->xid;
1801 	ip->client->packet.secs = 0; /* Filled in by send_request. */
1802 
1803 	/* If we own the address we're requesting, put it in ciaddr;
1804 	   otherwise set ciaddr to zero. */
1805 	if (ip->client->state == S_BOUND ||
1806 	    ip->client->state == S_RENEWING ||
1807 	    ip->client->state == S_REBINDING) {
1808 		memcpy(&ip->client->packet.ciaddr,
1809 		    lease->address.iabuf, lease->address.len);
1810 		ip->client->packet.flags = 0;
1811 	} else {
1812 		memset(&ip->client->packet.ciaddr, 0,
1813 		    sizeof(ip->client->packet.ciaddr));
1814 		ip->client->packet.flags = 0;
1815 	}
1816 
1817 	memset(&ip->client->packet.yiaddr, 0,
1818 	    sizeof(ip->client->packet.yiaddr));
1819 	memset(&ip->client->packet.siaddr, 0,
1820 	    sizeof(ip->client->packet.siaddr));
1821 	memset(&ip->client->packet.giaddr, 0,
1822 	    sizeof(ip->client->packet.giaddr));
1823 	memcpy(ip->client->packet.chaddr,
1824 	    ip->hw_address.haddr, ip->hw_address.hlen);
1825 }
1826 
1827 void
1828 make_decline(struct interface_info *ip, struct client_lease *lease)
1829 {
1830 	struct tree_cache *options[256], message_type_tree;
1831 	struct tree_cache requested_address_tree;
1832 	struct tree_cache server_id_tree, client_id_tree;
1833 	unsigned char decline = DHCPDECLINE;
1834 	int i;
1835 
1836 	memset(options, 0, sizeof(options));
1837 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1838 
1839 	/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1840 	i = DHO_DHCP_MESSAGE_TYPE;
1841 	options[i] = &message_type_tree;
1842 	options[i]->value = &decline;
1843 	options[i]->len = sizeof(decline);
1844 	options[i]->buf_size = sizeof(decline);
1845 	options[i]->timeout = 0xFFFFFFFF;
1846 
1847 	/* Send back the server identifier... */
1848 	i = DHO_DHCP_SERVER_IDENTIFIER;
1849 	options[i] = &server_id_tree;
1850 	options[i]->value = lease->options[i].data;
1851 	options[i]->len = lease->options[i].len;
1852 	options[i]->buf_size = lease->options[i].len;
1853 	options[i]->timeout = 0xFFFFFFFF;
1854 
1855 	/* Send back the address we're declining. */
1856 	i = DHO_DHCP_REQUESTED_ADDRESS;
1857 	options[i] = &requested_address_tree;
1858 	options[i]->value = lease->address.iabuf;
1859 	options[i]->len = lease->address.len;
1860 	options[i]->buf_size = lease->address.len;
1861 	options[i]->timeout = 0xFFFFFFFF;
1862 
1863 	/* Send the uid if the user supplied one. */
1864 	i = DHO_DHCP_CLIENT_IDENTIFIER;
1865 	if (ip->client->config->send_options[i].len) {
1866 		options[i] = &client_id_tree;
1867 		options[i]->value = ip->client->config->send_options[i].data;
1868 		options[i]->len = ip->client->config->send_options[i].len;
1869 		options[i]->buf_size = ip->client->config->send_options[i].len;
1870 		options[i]->timeout = 0xFFFFFFFF;
1871 	}
1872 
1873 
1874 	/* Set up the option buffer... */
1875 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1876 	    options, 0, 0, 0, NULL, 0);
1877 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1878 		ip->client->packet_length = BOOTP_MIN_LEN;
1879 
1880 	ip->client->packet.op = BOOTREQUEST;
1881 	ip->client->packet.htype = ip->hw_address.htype;
1882 	ip->client->packet.hlen = ip->hw_address.hlen;
1883 	ip->client->packet.hops = 0;
1884 	ip->client->packet.xid = ip->client->xid;
1885 	ip->client->packet.secs = 0; /* Filled in by send_request. */
1886 	ip->client->packet.flags = 0;
1887 
1888 	/* ciaddr must always be zero. */
1889 	memset(&ip->client->packet.ciaddr, 0,
1890 	    sizeof(ip->client->packet.ciaddr));
1891 	memset(&ip->client->packet.yiaddr, 0,
1892 	    sizeof(ip->client->packet.yiaddr));
1893 	memset(&ip->client->packet.siaddr, 0,
1894 	    sizeof(ip->client->packet.siaddr));
1895 	memset(&ip->client->packet.giaddr, 0,
1896 	    sizeof(ip->client->packet.giaddr));
1897 	memcpy(ip->client->packet.chaddr,
1898 	    ip->hw_address.haddr, ip->hw_address.hlen);
1899 }
1900 
1901 void
1902 free_client_lease(struct client_lease *lease)
1903 {
1904 	int i;
1905 
1906 	if (lease->server_name)
1907 		free(lease->server_name);
1908 	if (lease->filename)
1909 		free(lease->filename);
1910 	for (i = 0; i < 256; i++) {
1911 		if (lease->options[i].len)
1912 			free(lease->options[i].data);
1913 	}
1914 	free(lease);
1915 }
1916 
1917 static FILE *leaseFile;
1918 
1919 void
1920 rewrite_client_leases(void)
1921 {
1922 	struct client_lease *lp;
1923 	cap_rights_t rights;
1924 
1925 	if (!leaseFile) {
1926 		leaseFile = fopen(path_dhclient_db, "w");
1927 		if (!leaseFile)
1928 			error("can't create %s: %m", path_dhclient_db);
1929 		cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1930 		    CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1931 		if (caph_rights_limit(fileno(leaseFile), &rights) < 0) {
1932 			error("can't limit lease descriptor: %m");
1933 		}
1934 		if (caph_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0) {
1935 			error("can't limit lease descriptor fcntls: %m");
1936 		}
1937 	} else {
1938 		fflush(leaseFile);
1939 		rewind(leaseFile);
1940 	}
1941 
1942 	for (lp = ifi->client->leases; lp; lp = lp->next)
1943 		write_client_lease(ifi, lp, 1);
1944 	if (ifi->client->active)
1945 		write_client_lease(ifi, ifi->client->active, 1);
1946 
1947 	fflush(leaseFile);
1948 	ftruncate(fileno(leaseFile), ftello(leaseFile));
1949 	fsync(fileno(leaseFile));
1950 }
1951 
1952 void
1953 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1954     int rewrite)
1955 {
1956 	static int leases_written;
1957 	struct tm *t;
1958 	int i;
1959 
1960 	if (!rewrite) {
1961 		if (leases_written++ > 20) {
1962 			rewrite_client_leases();
1963 			leases_written = 0;
1964 		}
1965 	}
1966 
1967 	/* If the lease came from the config file, we don't need to stash
1968 	   a copy in the lease database. */
1969 	if (lease->is_static)
1970 		return;
1971 
1972 	if (!leaseFile) {	/* XXX */
1973 		leaseFile = fopen(path_dhclient_db, "w");
1974 		if (!leaseFile)
1975 			error("can't create %s: %m", path_dhclient_db);
1976 	}
1977 
1978 	fprintf(leaseFile, "lease {\n");
1979 	if (lease->is_bootp)
1980 		fprintf(leaseFile, "  bootp;\n");
1981 	fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1982 	fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1983 	if (lease->nextserver.len == sizeof(inaddr_any) &&
1984 	    0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1985 	    sizeof(inaddr_any)))
1986 		fprintf(leaseFile, "  next-server %s;\n",
1987 		    piaddr(lease->nextserver));
1988 	if (lease->filename)
1989 		fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1990 	if (lease->server_name)
1991 		fprintf(leaseFile, "  server-name \"%s\";\n",
1992 		    lease->server_name);
1993 	if (lease->medium)
1994 		fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1995 	for (i = 0; i < 256; i++)
1996 		if (lease->options[i].len)
1997 			fprintf(leaseFile, "  option %s %s;\n",
1998 			    dhcp_options[i].name,
1999 			    pretty_print_option(i, lease->options[i].data,
2000 			    lease->options[i].len, 1, 1));
2001 
2002 	t = gmtime(&lease->renewal);
2003 	fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
2004 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2005 	    t->tm_hour, t->tm_min, t->tm_sec);
2006 	t = gmtime(&lease->rebind);
2007 	fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2008 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2009 	    t->tm_hour, t->tm_min, t->tm_sec);
2010 	t = gmtime(&lease->expiry);
2011 	fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
2012 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2013 	    t->tm_hour, t->tm_min, t->tm_sec);
2014 	fprintf(leaseFile, "}\n");
2015 	fflush(leaseFile);
2016 }
2017 
2018 void
2019 script_init(const char *reason, struct string_list *medium)
2020 {
2021 	size_t		 len, mediumlen = 0;
2022 	struct imsg_hdr	 hdr;
2023 	struct buf	*buf;
2024 	int		 errs;
2025 
2026 	if (medium != NULL && medium->string != NULL)
2027 		mediumlen = strlen(medium->string);
2028 
2029 	hdr.code = IMSG_SCRIPT_INIT;
2030 	hdr.len = sizeof(struct imsg_hdr) +
2031 	    sizeof(size_t) + mediumlen +
2032 	    sizeof(size_t) + strlen(reason);
2033 
2034 	if ((buf = buf_open(hdr.len)) == NULL)
2035 		error("buf_open: %m");
2036 
2037 	errs = 0;
2038 	errs += buf_add(buf, &hdr, sizeof(hdr));
2039 	errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2040 	if (mediumlen > 0)
2041 		errs += buf_add(buf, medium->string, mediumlen);
2042 	len = strlen(reason);
2043 	errs += buf_add(buf, &len, sizeof(len));
2044 	errs += buf_add(buf, reason, len);
2045 
2046 	if (errs)
2047 		error("buf_add: %m");
2048 
2049 	if (buf_close(privfd, buf) == -1)
2050 		error("buf_close: %m");
2051 }
2052 
2053 void
2054 priv_script_init(const char *reason, char *medium)
2055 {
2056 	struct interface_info *ip = ifi;
2057 
2058 	if (ip) {
2059 		ip->client->scriptEnvsize = 100;
2060 		if (ip->client->scriptEnv == NULL)
2061 			ip->client->scriptEnv =
2062 			    malloc(ip->client->scriptEnvsize * sizeof(char *));
2063 		if (ip->client->scriptEnv == NULL)
2064 			error("script_init: no memory for environment");
2065 
2066 		ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2067 		if (ip->client->scriptEnv[0] == NULL)
2068 			error("script_init: no memory for environment");
2069 
2070 		ip->client->scriptEnv[1] = NULL;
2071 
2072 		script_set_env(ip->client, "", "interface", ip->name);
2073 
2074 		if (medium)
2075 			script_set_env(ip->client, "", "medium", medium);
2076 
2077 		script_set_env(ip->client, "", "reason", reason);
2078 	}
2079 }
2080 
2081 void
2082 priv_script_write_params(const char *prefix, struct client_lease *lease)
2083 {
2084 	struct interface_info *ip = ifi;
2085 	u_int8_t dbuf[1500], *dp = NULL;
2086 	int i;
2087 	size_t len;
2088 	char tbuf[128];
2089 
2090 	script_set_env(ip->client, prefix, "ip_address",
2091 	    piaddr(lease->address));
2092 
2093 	if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2094 	    ACTION_SUPERSEDE) {
2095 		dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2096 		len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2097 	} else {
2098 		dp = lease->options[DHO_SUBNET_MASK].data;
2099 		len = lease->options[DHO_SUBNET_MASK].len;
2100 	}
2101 	if (len && (len < sizeof(lease->address.iabuf))) {
2102 		struct iaddr netmask, subnet, broadcast;
2103 
2104 		memcpy(netmask.iabuf, dp, len);
2105 		netmask.len = len;
2106 		subnet = subnet_number(lease->address, netmask);
2107 		if (subnet.len) {
2108 			script_set_env(ip->client, prefix, "network_number",
2109 			    piaddr(subnet));
2110 			if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2111 				broadcast = broadcast_addr(subnet, netmask);
2112 				if (broadcast.len)
2113 					script_set_env(ip->client, prefix,
2114 					    "broadcast_address",
2115 					    piaddr(broadcast));
2116 			}
2117 		}
2118 	}
2119 
2120 	if (lease->filename)
2121 		script_set_env(ip->client, prefix, "filename", lease->filename);
2122 	if (lease->server_name)
2123 		script_set_env(ip->client, prefix, "server_name",
2124 		    lease->server_name);
2125 	for (i = 0; i < 256; i++) {
2126 		len = 0;
2127 
2128 		if (ip->client->config->defaults[i].len) {
2129 			if (lease->options[i].len) {
2130 				switch (
2131 				    ip->client->config->default_actions[i]) {
2132 				case ACTION_DEFAULT:
2133 					dp = lease->options[i].data;
2134 					len = lease->options[i].len;
2135 					break;
2136 				case ACTION_SUPERSEDE:
2137 supersede:
2138 					dp = ip->client->
2139 						config->defaults[i].data;
2140 					len = ip->client->
2141 						config->defaults[i].len;
2142 					break;
2143 				case ACTION_PREPEND:
2144 					len = ip->client->
2145 					    config->defaults[i].len +
2146 					    lease->options[i].len;
2147 					if (len >= sizeof(dbuf)) {
2148 						warning("no space to %s %s",
2149 						    "prepend option",
2150 						    dhcp_options[i].name);
2151 						goto supersede;
2152 					}
2153 					dp = dbuf;
2154 					memcpy(dp,
2155 						ip->client->
2156 						config->defaults[i].data,
2157 						ip->client->
2158 						config->defaults[i].len);
2159 					memcpy(dp + ip->client->
2160 						config->defaults[i].len,
2161 						lease->options[i].data,
2162 						lease->options[i].len);
2163 					dp[len] = '\0';
2164 					break;
2165 				case ACTION_APPEND:
2166 					/*
2167 					 * When we append, we assume that we're
2168 					 * appending to text.  Some MS servers
2169 					 * include a NUL byte at the end of
2170 					 * the search string provided.
2171 					 */
2172 					len = ip->client->
2173 					    config->defaults[i].len +
2174 					    lease->options[i].len;
2175 					if (len >= sizeof(dbuf)) {
2176 						warning("no space to %s %s",
2177 						    "append option",
2178 						    dhcp_options[i].name);
2179 						goto supersede;
2180 					}
2181 					memcpy(dbuf,
2182 						lease->options[i].data,
2183 						lease->options[i].len);
2184 					for (dp = dbuf + lease->options[i].len;
2185 					    dp > dbuf; dp--, len--)
2186 						if (dp[-1] != '\0')
2187 							break;
2188 					memcpy(dp,
2189 						ip->client->
2190 						config->defaults[i].data,
2191 						ip->client->
2192 						config->defaults[i].len);
2193 					dp = dbuf;
2194 					dp[len] = '\0';
2195 				}
2196 			} else {
2197 				dp = ip->client->
2198 					config->defaults[i].data;
2199 				len = ip->client->
2200 					config->defaults[i].len;
2201 			}
2202 		} else if (lease->options[i].len) {
2203 			len = lease->options[i].len;
2204 			dp = lease->options[i].data;
2205 		} else {
2206 			len = 0;
2207 		}
2208 		if (len) {
2209 			char name[256];
2210 
2211 			if (dhcp_option_ev_name(name, sizeof(name),
2212 			    &dhcp_options[i]))
2213 				script_set_env(ip->client, prefix, name,
2214 				    pretty_print_option(i, dp, len, 0, 0));
2215 		}
2216 	}
2217 	snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2218 	script_set_env(ip->client, prefix, "expiry", tbuf);
2219 }
2220 
2221 void
2222 script_write_params(const char *prefix, struct client_lease *lease)
2223 {
2224 	size_t		 fn_len = 0, sn_len = 0, pr_len = 0;
2225 	struct imsg_hdr	 hdr;
2226 	struct buf	*buf;
2227 	int		 errs, i;
2228 
2229 	if (lease->filename != NULL)
2230 		fn_len = strlen(lease->filename);
2231 	if (lease->server_name != NULL)
2232 		sn_len = strlen(lease->server_name);
2233 	if (prefix != NULL)
2234 		pr_len = strlen(prefix);
2235 
2236 	hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2237 	hdr.len = sizeof(hdr) + sizeof(*lease) +
2238 	    sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2239 	    sizeof(pr_len) + pr_len;
2240 
2241 	for (i = 0; i < 256; i++) {
2242 		hdr.len += sizeof(lease->options[i].len);
2243 		hdr.len += lease->options[i].len;
2244 	}
2245 
2246 	scripttime = time(NULL);
2247 
2248 	if ((buf = buf_open(hdr.len)) == NULL)
2249 		error("buf_open: %m");
2250 
2251 	errs = 0;
2252 	errs += buf_add(buf, &hdr, sizeof(hdr));
2253 	errs += buf_add(buf, lease, sizeof(*lease));
2254 	errs += buf_add(buf, &fn_len, sizeof(fn_len));
2255 	errs += buf_add(buf, lease->filename, fn_len);
2256 	errs += buf_add(buf, &sn_len, sizeof(sn_len));
2257 	errs += buf_add(buf, lease->server_name, sn_len);
2258 	errs += buf_add(buf, &pr_len, sizeof(pr_len));
2259 	errs += buf_add(buf, prefix, pr_len);
2260 
2261 	for (i = 0; i < 256; i++) {
2262 		errs += buf_add(buf, &lease->options[i].len,
2263 		    sizeof(lease->options[i].len));
2264 		errs += buf_add(buf, lease->options[i].data,
2265 		    lease->options[i].len);
2266 	}
2267 
2268 	if (errs)
2269 		error("buf_add: %m");
2270 
2271 	if (buf_close(privfd, buf) == -1)
2272 		error("buf_close: %m");
2273 }
2274 
2275 int
2276 script_go(void)
2277 {
2278 	struct imsg_hdr	 hdr;
2279 	struct buf	*buf;
2280 	int		 ret;
2281 
2282 	hdr.code = IMSG_SCRIPT_GO;
2283 	hdr.len = sizeof(struct imsg_hdr);
2284 
2285 	if ((buf = buf_open(hdr.len)) == NULL)
2286 		error("buf_open: %m");
2287 
2288 	if (buf_add(buf, &hdr, sizeof(hdr)))
2289 		error("buf_add: %m");
2290 
2291 	if (buf_close(privfd, buf) == -1)
2292 		error("buf_close: %m");
2293 
2294 	bzero(&hdr, sizeof(hdr));
2295 	buf_read(privfd, &hdr, sizeof(hdr));
2296 	if (hdr.code != IMSG_SCRIPT_GO_RET)
2297 		error("unexpected msg type %u", hdr.code);
2298 	if (hdr.len != sizeof(hdr) + sizeof(int))
2299 		error("received corrupted message");
2300 	buf_read(privfd, &ret, sizeof(ret));
2301 
2302 	scripttime = time(NULL);
2303 
2304 	return (ret);
2305 }
2306 
2307 int
2308 priv_script_go(void)
2309 {
2310 	char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2311 	static char client_path[] = CLIENT_PATH;
2312 	struct interface_info *ip = ifi;
2313 	int pid, wpid, wstatus;
2314 
2315 	scripttime = time(NULL);
2316 
2317 	if (ip) {
2318 		scriptName = ip->client->config->script_name;
2319 		envp = ip->client->scriptEnv;
2320 	} else {
2321 		scriptName = top_level_config.script_name;
2322 		epp[0] = reason;
2323 		epp[1] = client_path;
2324 		epp[2] = NULL;
2325 		envp = epp;
2326 	}
2327 
2328 	argv[0] = scriptName;
2329 	argv[1] = NULL;
2330 
2331 	pid = fork();
2332 	if (pid < 0) {
2333 		error("fork: %m");
2334 		wstatus = 0;
2335 	} else if (pid) {
2336 		do {
2337 			wpid = wait(&wstatus);
2338 		} while (wpid != pid && wpid > 0);
2339 		if (wpid < 0) {
2340 			error("wait: %m");
2341 			wstatus = 0;
2342 		}
2343 	} else {
2344 		execve(scriptName, argv, envp);
2345 		error("execve (%s, ...): %m", scriptName);
2346 	}
2347 
2348 	if (ip)
2349 		script_flush_env(ip->client);
2350 
2351 	return (wstatus & 0xff);
2352 }
2353 
2354 void
2355 script_set_env(struct client_state *client, const char *prefix,
2356     const char *name, const char *value)
2357 {
2358 	int i, namelen;
2359 	size_t j;
2360 
2361 	/* No `` or $() command substitution allowed in environment values! */
2362 	for (j=0; j < strlen(value); j++)
2363 		switch (value[j]) {
2364 		case '`':
2365 		case '$':
2366 			warning("illegal character (%c) in value '%s'",
2367 			    value[j], value);
2368 			/* Ignore this option */
2369 			return;
2370 		}
2371 
2372 	namelen = strlen(name);
2373 
2374 	for (i = 0; client->scriptEnv[i]; i++)
2375 		if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2376 		    client->scriptEnv[i][namelen] == '=')
2377 			break;
2378 
2379 	if (client->scriptEnv[i])
2380 		/* Reuse the slot. */
2381 		free(client->scriptEnv[i]);
2382 	else {
2383 		/* New variable.  Expand if necessary. */
2384 		if (i >= client->scriptEnvsize - 1) {
2385 			char **newscriptEnv;
2386 			int newscriptEnvsize = client->scriptEnvsize + 50;
2387 
2388 			newscriptEnv = realloc(client->scriptEnv,
2389 			    newscriptEnvsize);
2390 			if (newscriptEnv == NULL) {
2391 				free(client->scriptEnv);
2392 				client->scriptEnv = NULL;
2393 				client->scriptEnvsize = 0;
2394 				error("script_set_env: no memory for variable");
2395 			}
2396 			client->scriptEnv = newscriptEnv;
2397 			client->scriptEnvsize = newscriptEnvsize;
2398 		}
2399 		/* need to set the NULL pointer at end of array beyond
2400 		   the new slot. */
2401 		client->scriptEnv[i + 1] = NULL;
2402 	}
2403 	/* Allocate space and format the variable in the appropriate slot. */
2404 	client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2405 	    strlen(value) + 1);
2406 	if (client->scriptEnv[i] == NULL)
2407 		error("script_set_env: no memory for variable assignment");
2408 	snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2409 	    1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2410 }
2411 
2412 void
2413 script_flush_env(struct client_state *client)
2414 {
2415 	int i;
2416 
2417 	for (i = 0; client->scriptEnv[i]; i++) {
2418 		free(client->scriptEnv[i]);
2419 		client->scriptEnv[i] = NULL;
2420 	}
2421 	client->scriptEnvsize = 0;
2422 }
2423 
2424 int
2425 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2426 {
2427 	size_t i;
2428 
2429 	for (i = 0; option->name[i]; i++) {
2430 		if (i + 1 == buflen)
2431 			return 0;
2432 		if (option->name[i] == '-')
2433 			buf[i] = '_';
2434 		else
2435 			buf[i] = option->name[i];
2436 	}
2437 
2438 	buf[i] = 0;
2439 	return 1;
2440 }
2441 
2442 void
2443 go_daemon(void)
2444 {
2445 	static int state = 0;
2446 	cap_rights_t rights;
2447 
2448 	if (no_daemon || state)
2449 		return;
2450 
2451 	state = 1;
2452 
2453 	/* Stop logging to stderr... */
2454 	log_perror = 0;
2455 
2456 	if (daemonfd(-1, nullfd) == -1)
2457 		error("daemon");
2458 
2459 	cap_rights_init(&rights);
2460 
2461 	if (pidfile != NULL) {
2462 		pidfile_write(pidfile);
2463 
2464 		if (caph_rights_limit(pidfile_fileno(pidfile), &rights) < 0)
2465 			error("can't limit pidfile descriptor: %m");
2466 	}
2467 
2468 	if (nullfd != -1) {
2469 		close(nullfd);
2470 		nullfd = -1;
2471 	}
2472 
2473 	if (caph_rights_limit(STDIN_FILENO, &rights) < 0)
2474 		error("can't limit stdin: %m");
2475 	cap_rights_init(&rights, CAP_WRITE);
2476 	if (caph_rights_limit(STDOUT_FILENO, &rights) < 0)
2477 		error("can't limit stdout: %m");
2478 	if (caph_rights_limit(STDERR_FILENO, &rights) < 0)
2479 		error("can't limit stderr: %m");
2480 }
2481 
2482 int
2483 check_option(struct client_lease *l, int option)
2484 {
2485 	const char *opbuf;
2486 	const char *sbuf;
2487 
2488 	/* we use this, since this is what gets passed to dhclient-script */
2489 
2490 	opbuf = pretty_print_option(option, l->options[option].data,
2491 	    l->options[option].len, 0, 0);
2492 
2493 	sbuf = option_as_string(option, l->options[option].data,
2494 	    l->options[option].len);
2495 
2496 	switch (option) {
2497 	case DHO_SUBNET_MASK:
2498 	case DHO_TIME_SERVERS:
2499 	case DHO_NAME_SERVERS:
2500 	case DHO_ROUTERS:
2501 	case DHO_DOMAIN_NAME_SERVERS:
2502 	case DHO_LOG_SERVERS:
2503 	case DHO_COOKIE_SERVERS:
2504 	case DHO_LPR_SERVERS:
2505 	case DHO_IMPRESS_SERVERS:
2506 	case DHO_RESOURCE_LOCATION_SERVERS:
2507 	case DHO_SWAP_SERVER:
2508 	case DHO_BROADCAST_ADDRESS:
2509 	case DHO_NIS_SERVERS:
2510 	case DHO_NTP_SERVERS:
2511 	case DHO_NETBIOS_NAME_SERVERS:
2512 	case DHO_NETBIOS_DD_SERVER:
2513 	case DHO_FONT_SERVERS:
2514 	case DHO_DHCP_SERVER_IDENTIFIER:
2515 	case DHO_NISPLUS_SERVERS:
2516 	case DHO_MOBILE_IP_HOME_AGENT:
2517 	case DHO_SMTP_SERVER:
2518 	case DHO_POP_SERVER:
2519 	case DHO_NNTP_SERVER:
2520 	case DHO_WWW_SERVER:
2521 	case DHO_FINGER_SERVER:
2522 	case DHO_IRC_SERVER:
2523 	case DHO_STREETTALK_SERVER:
2524 	case DHO_STREETTALK_DA_SERVER:
2525 		if (!ipv4addrs(opbuf)) {
2526 			warning("Invalid IP address in option: %s", opbuf);
2527 			return (0);
2528 		}
2529 		return (1)  ;
2530 	case DHO_HOST_NAME:
2531 	case DHO_NIS_DOMAIN:
2532 	case DHO_NISPLUS_DOMAIN:
2533 	case DHO_TFTP_SERVER_NAME:
2534 		if (!res_hnok(sbuf)) {
2535 			warning("Bogus Host Name option %d: %s (%s)", option,
2536 			    sbuf, opbuf);
2537 			l->options[option].len = 0;
2538 			free(l->options[option].data);
2539 		}
2540 		return (1);
2541 	case DHO_DOMAIN_NAME:
2542 	case DHO_DOMAIN_SEARCH:
2543 		if (!res_hnok(sbuf)) {
2544 			if (!check_search(sbuf)) {
2545 				warning("Bogus domain search list %d: %s (%s)",
2546 				    option, sbuf, opbuf);
2547 				l->options[option].len = 0;
2548 				free(l->options[option].data);
2549 			}
2550 		}
2551 		return (1);
2552 	case DHO_PAD:
2553 	case DHO_TIME_OFFSET:
2554 	case DHO_BOOT_SIZE:
2555 	case DHO_MERIT_DUMP:
2556 	case DHO_ROOT_PATH:
2557 	case DHO_EXTENSIONS_PATH:
2558 	case DHO_IP_FORWARDING:
2559 	case DHO_NON_LOCAL_SOURCE_ROUTING:
2560 	case DHO_POLICY_FILTER:
2561 	case DHO_MAX_DGRAM_REASSEMBLY:
2562 	case DHO_DEFAULT_IP_TTL:
2563 	case DHO_PATH_MTU_AGING_TIMEOUT:
2564 	case DHO_PATH_MTU_PLATEAU_TABLE:
2565 	case DHO_INTERFACE_MTU:
2566 	case DHO_ALL_SUBNETS_LOCAL:
2567 	case DHO_PERFORM_MASK_DISCOVERY:
2568 	case DHO_MASK_SUPPLIER:
2569 	case DHO_ROUTER_DISCOVERY:
2570 	case DHO_ROUTER_SOLICITATION_ADDRESS:
2571 	case DHO_STATIC_ROUTES:
2572 	case DHO_TRAILER_ENCAPSULATION:
2573 	case DHO_ARP_CACHE_TIMEOUT:
2574 	case DHO_IEEE802_3_ENCAPSULATION:
2575 	case DHO_DEFAULT_TCP_TTL:
2576 	case DHO_TCP_KEEPALIVE_INTERVAL:
2577 	case DHO_TCP_KEEPALIVE_GARBAGE:
2578 	case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2579 	case DHO_NETBIOS_NODE_TYPE:
2580 	case DHO_NETBIOS_SCOPE:
2581 	case DHO_X_DISPLAY_MANAGER:
2582 	case DHO_DHCP_REQUESTED_ADDRESS:
2583 	case DHO_DHCP_LEASE_TIME:
2584 	case DHO_DHCP_OPTION_OVERLOAD:
2585 	case DHO_DHCP_MESSAGE_TYPE:
2586 	case DHO_DHCP_PARAMETER_REQUEST_LIST:
2587 	case DHO_DHCP_MESSAGE:
2588 	case DHO_DHCP_MAX_MESSAGE_SIZE:
2589 	case DHO_DHCP_RENEWAL_TIME:
2590 	case DHO_DHCP_REBINDING_TIME:
2591 	case DHO_DHCP_CLASS_IDENTIFIER:
2592 	case DHO_DHCP_CLIENT_IDENTIFIER:
2593 	case DHO_BOOTFILE_NAME:
2594 	case DHO_DHCP_USER_CLASS_ID:
2595 	case DHO_END:
2596 		return (1);
2597 	case DHO_CLASSLESS_ROUTES:
2598 		return (check_classless_option(l->options[option].data,
2599 		    l->options[option].len));
2600 	default:
2601 		warning("unknown dhcp option value 0x%x", option);
2602 		return (unknown_ok);
2603 	}
2604 }
2605 
2606 /* RFC 3442 The Classless Static Routes option checks */
2607 int
2608 check_classless_option(unsigned char *data, int len)
2609 {
2610 	int i = 0;
2611 	unsigned char width;
2612 	in_addr_t addr, mask;
2613 
2614 	if (len < 5) {
2615 		warning("Too small length: %d", len);
2616 		return (0);
2617 	}
2618 	while(i < len) {
2619 		width = data[i++];
2620 		if (width == 0) {
2621 			i += 4;
2622 			continue;
2623 		} else if (width < 9) {
2624 			addr =  (in_addr_t)(data[i]	<< 24);
2625 			i += 1;
2626 		} else if (width < 17) {
2627 			addr =  (in_addr_t)(data[i]	<< 24) +
2628 				(in_addr_t)(data[i + 1]	<< 16);
2629 			i += 2;
2630 		} else if (width < 25) {
2631 			addr =  (in_addr_t)(data[i]	<< 24) +
2632 				(in_addr_t)(data[i + 1]	<< 16) +
2633 				(in_addr_t)(data[i + 2]	<< 8);
2634 			i += 3;
2635 		} else if (width < 33) {
2636 			addr =  (in_addr_t)(data[i]	<< 24) +
2637 				(in_addr_t)(data[i + 1]	<< 16) +
2638 				(in_addr_t)(data[i + 2]	<< 8)  +
2639 				data[i + 3];
2640 			i += 4;
2641 		} else {
2642 			warning("Incorrect subnet width: %d", width);
2643 			return (0);
2644 		}
2645 		mask = (in_addr_t)(~0) << (32 - width);
2646 		addr = ntohl(addr);
2647 		mask = ntohl(mask);
2648 
2649 		/*
2650 		 * From RFC 3442:
2651 		 * ... After deriving a subnet number and subnet mask
2652 		 * from each destination descriptor, the DHCP client
2653 		 * MUST zero any bits in the subnet number where the
2654 		 * corresponding bit in the mask is zero...
2655 		 */
2656 		if ((addr & mask) != addr) {
2657 			addr &= mask;
2658 			data[i - 1] = (unsigned char)(
2659 				(addr >> (((32 - width)/8)*8)) & 0xFF);
2660 		}
2661 		i += 4;
2662 	}
2663 	if (i > len) {
2664 		warning("Incorrect data length: %d (must be %d)", len, i);
2665 		return (0);
2666 	}
2667 	return (1);
2668 }
2669 
2670 int
2671 res_hnok(const char *dn)
2672 {
2673 	int pch = PERIOD, ch = *dn++;
2674 
2675 	while (ch != '\0') {
2676 		int nch = *dn++;
2677 
2678 		if (periodchar(ch)) {
2679 			;
2680 		} else if (periodchar(pch)) {
2681 			if (!borderchar(ch))
2682 				return (0);
2683 		} else if (periodchar(nch) || nch == '\0') {
2684 			if (!borderchar(ch))
2685 				return (0);
2686 		} else {
2687 			if (!middlechar(ch))
2688 				return (0);
2689 		}
2690 		pch = ch, ch = nch;
2691 	}
2692 	return (1);
2693 }
2694 
2695 int
2696 check_search(const char *srch)
2697 {
2698         int pch = PERIOD, ch = *srch++;
2699 	int domains = 1;
2700 
2701 	/* 256 char limit re resolv.conf(5) */
2702 	if (strlen(srch) > 256)
2703 		return (0);
2704 
2705 	while (whitechar(ch))
2706 		ch = *srch++;
2707 
2708         while (ch != '\0') {
2709                 int nch = *srch++;
2710 
2711                 if (periodchar(ch) || whitechar(ch)) {
2712                         ;
2713                 } else if (periodchar(pch)) {
2714                         if (!borderchar(ch))
2715                                 return (0);
2716                 } else if (periodchar(nch) || nch == '\0') {
2717                         if (!borderchar(ch))
2718                                 return (0);
2719                 } else {
2720                         if (!middlechar(ch))
2721                                 return (0);
2722                 }
2723 		if (!whitechar(ch)) {
2724 			pch = ch;
2725 		} else {
2726 			while (whitechar(nch)) {
2727 				nch = *srch++;
2728 			}
2729 			if (nch != '\0')
2730 				domains++;
2731 			pch = PERIOD;
2732 		}
2733 		ch = nch;
2734         }
2735 	/* 6 domain limit re resolv.conf(5) */
2736 	if (domains > 6)
2737 		return (0);
2738         return (1);
2739 }
2740 
2741 /* Does buf consist only of dotted decimal ipv4 addrs?
2742  * return how many if so,
2743  * otherwise, return 0
2744  */
2745 int
2746 ipv4addrs(const char * buf)
2747 {
2748 	struct in_addr jnk;
2749 	int count = 0;
2750 
2751 	while (inet_aton(buf, &jnk) == 1){
2752 		count++;
2753 		while (periodchar(*buf) || digitchar(*buf))
2754 			buf++;
2755 		if (*buf == '\0')
2756 			return (count);
2757 		while (*buf ==  ' ')
2758 			buf++;
2759 	}
2760 	return (0);
2761 }
2762 
2763 
2764 const char *
2765 option_as_string(unsigned int code, unsigned char *data, int len)
2766 {
2767 	static char optbuf[32768]; /* XXX */
2768 	char *op = optbuf;
2769 	int opleft = sizeof(optbuf);
2770 	unsigned char *dp = data;
2771 
2772 	if (code > 255)
2773 		error("option_as_string: bad code %d", code);
2774 
2775 	for (; dp < data + len; dp++) {
2776 		if (!isascii(*dp) || !isprint(*dp)) {
2777 			if (dp + 1 != data + len || *dp != 0) {
2778 				snprintf(op, opleft, "\\%03o", *dp);
2779 				op += 4;
2780 				opleft -= 4;
2781 			}
2782 		} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2783 		    *dp == '`' || *dp == '\\') {
2784 			*op++ = '\\';
2785 			*op++ = *dp;
2786 			opleft -= 2;
2787 		} else {
2788 			*op++ = *dp;
2789 			opleft--;
2790 		}
2791 	}
2792 	if (opleft < 1)
2793 		goto toobig;
2794 	*op = 0;
2795 	return optbuf;
2796 toobig:
2797 	warning("dhcp option too large");
2798 	return "<error>";
2799 }
2800 
2801 int
2802 fork_privchld(int fd, int fd2)
2803 {
2804 	struct pollfd pfd[1];
2805 	int nfds;
2806 
2807 	switch (fork()) {
2808 	case -1:
2809 		error("cannot fork");
2810 	case 0:
2811 		break;
2812 	default:
2813 		return (0);
2814 	}
2815 
2816 	setproctitle("%s [priv]", ifi->name);
2817 
2818 	setsid();
2819 	dup2(nullfd, STDIN_FILENO);
2820 	dup2(nullfd, STDOUT_FILENO);
2821 	dup2(nullfd, STDERR_FILENO);
2822 	close(nullfd);
2823 	close(fd2);
2824 	close(ifi->rfdesc);
2825 	ifi->rfdesc = -1;
2826 
2827 	for (;;) {
2828 		pfd[0].fd = fd;
2829 		pfd[0].events = POLLIN;
2830 		if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2831 			if (errno != EINTR)
2832 				error("poll error");
2833 
2834 		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2835 			continue;
2836 
2837 		dispatch_imsg(ifi, fd);
2838 	}
2839 }
2840