xref: /freebsd/sbin/dhclient/dhclient.c (revision cd0d51baaa4509a1db83251a601d34404d20c990)
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 		u_int16_t old_mtu = 0;
867 		bool supersede = (ip->client->config->default_actions[DHO_INTERFACE_MTU] ==
868 			ACTION_SUPERSEDE);
869 
870 		if (supersede)
871 			mtu = getUShort(ip->client->config->defaults[DHO_INTERFACE_MTU].data);
872 		else
873 			mtu = be16dec(opt->data);
874 
875 		if (ip->client->active) {
876 			opt = &ip->client->active->options[DHO_INTERFACE_MTU];
877 			if (opt->len == sizeof(u_int16_t)) {
878 				old_mtu = be16dec(opt->data);
879 			}
880 		}
881 
882 		if (mtu < MIN_MTU) {
883 			/* Treat 0 like a user intentionally doesn't want to change MTU and,
884 			 * therefore, warning is not needed */
885 			if (!supersede || mtu != 0)
886 				warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
887 		} else if (ip->client->state != S_RENEWING || mtu != old_mtu) {
888 			interface_set_mtu_unpriv(privfd, mtu);
889 		}
890 	}
891 
892 	/* Write out the new lease. */
893 	write_client_lease(ip, ip->client->new, 0);
894 
895 	/* Run the client script with the new parameters. */
896 	script_init((ip->client->state == S_REQUESTING ? "BOUND" :
897 	    (ip->client->state == S_RENEWING ? "RENEW" :
898 	    (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
899 	    ip->client->new->medium);
900 	if (ip->client->active && ip->client->state != S_REBOOTING)
901 		script_write_params("old_", ip->client->active);
902 	script_write_params("new_", ip->client->new);
903 	if (ip->client->alias)
904 		script_write_params("alias_", ip->client->alias);
905 	script_go();
906 
907 	/* Replace the old active lease with the new one. */
908 	if (ip->client->active)
909 		free_client_lease(ip->client->active);
910 	ip->client->active = ip->client->new;
911 	ip->client->new = NULL;
912 
913 	/* Set up a timeout to start the renewal process. */
914 	add_timeout(ip->client->active->renewal, state_bound, ip);
915 
916 	note("bound to %s -- renewal in %d seconds.",
917 	    piaddr(ip->client->active->address),
918 	    (int)(ip->client->active->renewal - cur_time));
919 	ip->client->state = S_BOUND;
920 	reinitialize_interfaces();
921 	go_daemon();
922 }
923 
924 /*
925  * state_bound is called when we've successfully bound to a particular
926  * lease, but the renewal time on that lease has expired.   We are
927  * expected to unicast a DHCPREQUEST to the server that gave us our
928  * original lease.
929  */
930 void
931 state_bound(void *ipp)
932 {
933 	struct interface_info *ip = ipp;
934 
935 	ASSERT_STATE(state, S_BOUND);
936 
937 	/* T1 has expired. */
938 	make_request(ip, ip->client->active);
939 	ip->client->xid = ip->client->packet.xid;
940 
941 	if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
942 		memcpy(ip->client->destination.iabuf, ip->client->active->
943 		    options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
944 		ip->client->destination.len = 4;
945 	} else
946 		ip->client->destination = iaddr_broadcast;
947 
948 	ip->client->first_sending = cur_time;
949 	ip->client->interval = ip->client->config->initial_interval;
950 	ip->client->state = S_RENEWING;
951 
952 	/* Send the first packet immediately. */
953 	send_request(ip);
954 }
955 
956 void
957 bootp(struct packet *packet)
958 {
959 	struct iaddrlist *ap;
960 
961 	if (packet->raw->op != BOOTREPLY)
962 		return;
963 
964 	/* If there's a reject list, make sure this packet's sender isn't
965 	   on it. */
966 	for (ap = packet->interface->client->config->reject_list;
967 	    ap; ap = ap->next) {
968 		if (addr_eq(packet->client_addr, ap->addr)) {
969 			note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
970 			return;
971 		}
972 	}
973 	dhcpoffer(packet);
974 }
975 
976 void
977 dhcp(struct packet *packet)
978 {
979 	struct iaddrlist *ap;
980 	void (*handler)(struct packet *);
981 	const char *type;
982 
983 	switch (packet->packet_type) {
984 	case DHCPOFFER:
985 		handler = dhcpoffer;
986 		type = "DHCPOFFER";
987 		break;
988 	case DHCPNAK:
989 		handler = dhcpnak;
990 		type = "DHCPNACK";
991 		break;
992 	case DHCPACK:
993 		handler = dhcpack;
994 		type = "DHCPACK";
995 		break;
996 	default:
997 		return;
998 	}
999 
1000 	/* If there's a reject list, make sure this packet's sender isn't
1001 	   on it. */
1002 	for (ap = packet->interface->client->config->reject_list;
1003 	    ap; ap = ap->next) {
1004 		if (addr_eq(packet->client_addr, ap->addr)) {
1005 			note("%s from %s rejected.", type, piaddr(ap->addr));
1006 			return;
1007 		}
1008 	}
1009 	(*handler)(packet);
1010 }
1011 
1012 void
1013 dhcpoffer(struct packet *packet)
1014 {
1015 	struct interface_info *ip = packet->interface;
1016 	struct client_lease *lease, *lp;
1017 	int i;
1018 	int arp_timeout_needed, stop_selecting;
1019 	const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
1020 	    "DHCPOFFER" : "BOOTREPLY";
1021 
1022 	/* If we're not receptive to an offer right now, or if the offer
1023 	   has an unrecognizable transaction id, then just drop it. */
1024 	if (ip->client->state != S_SELECTING ||
1025 	    packet->interface->client->xid != packet->raw->xid ||
1026 	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1027 	    (memcmp(packet->interface->hw_address.haddr,
1028 	    packet->raw->chaddr, packet->raw->hlen)))
1029 		return;
1030 
1031 	note("%s from %s", name, piaddr(packet->client_addr));
1032 
1033 
1034 	/* If this lease doesn't supply the minimum required parameters,
1035 	   blow it off. */
1036 	for (i = 0; ip->client->config->required_options[i]; i++) {
1037 		if (!packet->options[ip->client->config->
1038 		    required_options[i]].len) {
1039 			note("%s isn't satisfactory.", name);
1040 			return;
1041 		}
1042 	}
1043 
1044 	/* If we've already seen this lease, don't record it again. */
1045 	for (lease = ip->client->offered_leases;
1046 	    lease; lease = lease->next) {
1047 		if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1048 		    !memcmp(lease->address.iabuf,
1049 		    &packet->raw->yiaddr, lease->address.len)) {
1050 			debug("%s already seen.", name);
1051 			return;
1052 		}
1053 	}
1054 
1055 	lease = packet_to_lease(packet);
1056 	if (!lease) {
1057 		note("packet_to_lease failed.");
1058 		return;
1059 	}
1060 
1061 	/* If this lease was acquired through a BOOTREPLY, record that
1062 	   fact. */
1063 	if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1064 		lease->is_bootp = 1;
1065 
1066 	/* Record the medium under which this lease was offered. */
1067 	lease->medium = ip->client->medium;
1068 
1069 	/* Send out an ARP Request for the offered IP address. */
1070 	script_init("ARPSEND", lease->medium);
1071 	script_write_params("check_", lease);
1072 	/* If the script can't send an ARP request without waiting,
1073 	   we'll be waiting when we do the ARPCHECK, so don't wait now. */
1074 	if (script_go())
1075 		arp_timeout_needed = 0;
1076 	else
1077 		arp_timeout_needed = 2;
1078 
1079 	/* Figure out when we're supposed to stop selecting. */
1080 	stop_selecting =
1081 	    ip->client->first_sending + ip->client->config->select_interval;
1082 
1083 	/* If this is the lease we asked for, put it at the head of the
1084 	   list, and don't mess with the arp request timeout. */
1085 	if (lease->address.len == ip->client->requested_address.len &&
1086 	    !memcmp(lease->address.iabuf,
1087 	    ip->client->requested_address.iabuf,
1088 	    ip->client->requested_address.len)) {
1089 		lease->next = ip->client->offered_leases;
1090 		ip->client->offered_leases = lease;
1091 	} else {
1092 		/* If we already have an offer, and arping for this
1093 		   offer would take us past the selection timeout,
1094 		   then don't extend the timeout - just hope for the
1095 		   best. */
1096 		if (ip->client->offered_leases &&
1097 		    (cur_time + arp_timeout_needed) > stop_selecting)
1098 			arp_timeout_needed = 0;
1099 
1100 		/* Put the lease at the end of the list. */
1101 		lease->next = NULL;
1102 		if (!ip->client->offered_leases)
1103 			ip->client->offered_leases = lease;
1104 		else {
1105 			for (lp = ip->client->offered_leases; lp->next;
1106 			    lp = lp->next)
1107 				;	/* nothing */
1108 			lp->next = lease;
1109 		}
1110 	}
1111 
1112 	/* If we're supposed to stop selecting before we've had time
1113 	   to wait for the ARPREPLY, add some delay to wait for
1114 	   the ARPREPLY. */
1115 	if (stop_selecting - cur_time < arp_timeout_needed)
1116 		stop_selecting = cur_time + arp_timeout_needed;
1117 
1118 	/* If the selecting interval has expired, go immediately to
1119 	   state_selecting().  Otherwise, time out into
1120 	   state_selecting at the select interval. */
1121 	if (stop_selecting <= 0)
1122 		state_selecting(ip);
1123 	else {
1124 		add_timeout(stop_selecting, state_selecting, ip);
1125 		cancel_timeout(send_discover, ip);
1126 	}
1127 }
1128 
1129 /* Allocate a client_lease structure and initialize it from the parameters
1130    in the specified packet. */
1131 
1132 struct client_lease *
1133 packet_to_lease(struct packet *packet)
1134 {
1135 	struct client_lease *lease;
1136 	int i;
1137 
1138 	lease = malloc(sizeof(struct client_lease));
1139 
1140 	if (!lease) {
1141 		warning("dhcpoffer: no memory to record lease.");
1142 		return (NULL);
1143 	}
1144 
1145 	memset(lease, 0, sizeof(*lease));
1146 
1147 	/* Copy the lease options. */
1148 	for (i = 0; i < 256; i++) {
1149 		if (packet->options[i].len) {
1150 			lease->options[i].data =
1151 			    malloc(packet->options[i].len + 1);
1152 			if (!lease->options[i].data) {
1153 				warning("dhcpoffer: no memory for option %d", i);
1154 				free_client_lease(lease);
1155 				return (NULL);
1156 			} else {
1157 				memcpy(lease->options[i].data,
1158 				    packet->options[i].data,
1159 				    packet->options[i].len);
1160 				lease->options[i].len =
1161 				    packet->options[i].len;
1162 				lease->options[i].data[lease->options[i].len] =
1163 				    0;
1164 			}
1165 			if (!check_option(lease,i)) {
1166 				/* ignore a bogus lease offer */
1167 				warning("Invalid lease option - ignoring offer");
1168 				free_client_lease(lease);
1169 				return (NULL);
1170 			}
1171 		}
1172 	}
1173 
1174 	lease->address.len = sizeof(packet->raw->yiaddr);
1175 	memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1176 
1177 	lease->nextserver.len = sizeof(packet->raw->siaddr);
1178 	memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1179 
1180 	/* If the server name was filled out, copy it.
1181 	   Do not attempt to validate the server name as a host name.
1182 	   RFC 2131 merely states that sname is NUL-terminated (which do
1183 	   do not assume) and that it is the server's host name.  Since
1184 	   the ISC client and server allow arbitrary characters, we do
1185 	   as well. */
1186 	if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1187 	    !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1188 	    packet->raw->sname[0]) {
1189 		lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1190 		if (!lease->server_name) {
1191 			warning("dhcpoffer: no memory for server name.");
1192 			free_client_lease(lease);
1193 			return (NULL);
1194 		}
1195 		memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1196 		lease->server_name[DHCP_SNAME_LEN]='\0';
1197 	}
1198 
1199 	/* Ditto for the filename. */
1200 	if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1201 	    !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1202 	    packet->raw->file[0]) {
1203 		/* Don't count on the NUL terminator. */
1204 		lease->filename = malloc(DHCP_FILE_LEN + 1);
1205 		if (!lease->filename) {
1206 			warning("dhcpoffer: no memory for filename.");
1207 			free_client_lease(lease);
1208 			return (NULL);
1209 		}
1210 		memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1211 		lease->filename[DHCP_FILE_LEN]='\0';
1212 	}
1213 	return lease;
1214 }
1215 
1216 void
1217 dhcpnak(struct packet *packet)
1218 {
1219 	struct interface_info *ip = packet->interface;
1220 
1221 	/* If we're not receptive to an offer right now, or if the offer
1222 	   has an unrecognizable transaction id, then just drop it. */
1223 	if (packet->interface->client->xid != packet->raw->xid ||
1224 	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1225 	    (memcmp(packet->interface->hw_address.haddr,
1226 	    packet->raw->chaddr, packet->raw->hlen)))
1227 		return;
1228 
1229 	if (ip->client->state != S_REBOOTING &&
1230 	    ip->client->state != S_REQUESTING &&
1231 	    ip->client->state != S_RENEWING &&
1232 	    ip->client->state != S_REBINDING)
1233 		return;
1234 
1235 	note("DHCPNAK from %s", piaddr(packet->client_addr));
1236 
1237 	if (!ip->client->active) {
1238 		note("DHCPNAK with no active lease.\n");
1239 		return;
1240 	}
1241 
1242 	free_client_lease(ip->client->active);
1243 	ip->client->active = NULL;
1244 
1245 	/* Stop sending DHCPREQUEST packets... */
1246 	cancel_timeout(send_request, ip);
1247 
1248 	ip->client->state = S_INIT;
1249 	state_init(ip);
1250 }
1251 
1252 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1253    one after the right interval has expired.  If we don't get an offer by
1254    the time we reach the panic interval, call the panic function. */
1255 
1256 void
1257 send_discover(void *ipp)
1258 {
1259 	struct interface_info *ip = ipp;
1260 	int interval, increase = 1;
1261 
1262 	/* Figure out how long it's been since we started transmitting. */
1263 	interval = cur_time - ip->client->first_sending;
1264 
1265 	/* If we're past the panic timeout, call the script and tell it
1266 	   we haven't found anything for this interface yet. */
1267 	if (interval > ip->client->config->timeout) {
1268 		state_panic(ip);
1269 		return;
1270 	}
1271 
1272 	/* If we're selecting media, try the whole list before doing
1273 	   the exponential backoff, but if we've already received an
1274 	   offer, stop looping, because we obviously have it right. */
1275 	if (!ip->client->offered_leases &&
1276 	    ip->client->config->media) {
1277 		int fail = 0;
1278 again:
1279 		if (ip->client->medium) {
1280 			ip->client->medium = ip->client->medium->next;
1281 			increase = 0;
1282 		}
1283 		if (!ip->client->medium) {
1284 			if (fail)
1285 				error("No valid media types for %s!", ip->name);
1286 			ip->client->medium = ip->client->config->media;
1287 			increase = 1;
1288 		}
1289 
1290 		note("Trying medium \"%s\" %d", ip->client->medium->string,
1291 		    increase);
1292 		script_init("MEDIUM", ip->client->medium);
1293 		if (script_go())
1294 			goto again;
1295 	}
1296 
1297 	/*
1298 	 * If we're supposed to increase the interval, do so.  If it's
1299 	 * currently zero (i.e., we haven't sent any packets yet), set
1300 	 * it to one; otherwise, add to it a random number between zero
1301 	 * and two times itself.  On average, this means that it will
1302 	 * double with every transmission.
1303 	 */
1304 	if (increase) {
1305 		if (!ip->client->interval)
1306 			ip->client->interval =
1307 			    ip->client->config->initial_interval;
1308 		else {
1309 			ip->client->interval += (arc4random() >> 2) %
1310 			    (2 * ip->client->interval);
1311 		}
1312 
1313 		/* Don't backoff past cutoff. */
1314 		if (ip->client->interval >
1315 		    ip->client->config->backoff_cutoff)
1316 			ip->client->interval =
1317 				((ip->client->config->backoff_cutoff / 2)
1318 				 + ((arc4random() >> 2) %
1319 				    ip->client->config->backoff_cutoff));
1320 	} else if (!ip->client->interval)
1321 		ip->client->interval =
1322 			ip->client->config->initial_interval;
1323 
1324 	/* If the backoff would take us to the panic timeout, just use that
1325 	   as the interval. */
1326 	if (cur_time + ip->client->interval >
1327 	    ip->client->first_sending + ip->client->config->timeout)
1328 		ip->client->interval =
1329 			(ip->client->first_sending +
1330 			 ip->client->config->timeout) - cur_time + 1;
1331 
1332 	/* Record the number of seconds since we started sending. */
1333 	if (interval < 65536)
1334 		ip->client->packet.secs = htons(interval);
1335 	else
1336 		ip->client->packet.secs = htons(65535);
1337 	ip->client->secs = ip->client->packet.secs;
1338 
1339 	note("DHCPDISCOVER on %s to %s port %d interval %d",
1340 	    ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1341 	    (int)ip->client->interval);
1342 
1343 	/* Send out a packet. */
1344 	send_packet_unpriv(privfd, &ip->client->packet,
1345 	    ip->client->packet_length, inaddr_any, inaddr_broadcast);
1346 
1347 	add_timeout(cur_time + ip->client->interval, send_discover, ip);
1348 }
1349 
1350 /*
1351  * state_panic gets called if we haven't received any offers in a preset
1352  * amount of time.   When this happens, we try to use existing leases
1353  * that haven't yet expired, and failing that, we call the client script
1354  * and hope it can do something.
1355  */
1356 void
1357 state_panic(void *ipp)
1358 {
1359 	struct interface_info *ip = ipp;
1360 	struct client_lease *loop = ip->client->active;
1361 	struct client_lease *lp;
1362 
1363 	note("No DHCPOFFERS received.");
1364 
1365 	/* We may not have an active lease, but we may have some
1366 	   predefined leases that we can try. */
1367 	if (!ip->client->active && ip->client->leases)
1368 		goto activate_next;
1369 
1370 	/* Run through the list of leases and see if one can be used. */
1371 	while (ip->client->active) {
1372 		if (ip->client->active->expiry > cur_time) {
1373 			note("Trying recorded lease %s",
1374 			    piaddr(ip->client->active->address));
1375 			/* Run the client script with the existing
1376 			   parameters. */
1377 			script_init("TIMEOUT",
1378 			    ip->client->active->medium);
1379 			script_write_params("new_", ip->client->active);
1380 			if (ip->client->alias)
1381 				script_write_params("alias_",
1382 				    ip->client->alias);
1383 
1384 			/* If the old lease is still good and doesn't
1385 			   yet need renewal, go into BOUND state and
1386 			   timeout at the renewal time. */
1387 			if (!script_go()) {
1388 				if (cur_time <
1389 				    ip->client->active->renewal) {
1390 					ip->client->state = S_BOUND;
1391 					note("bound: renewal in %d seconds.",
1392 					    (int)(ip->client->active->renewal -
1393 					    cur_time));
1394 					add_timeout(
1395 					    ip->client->active->renewal,
1396 					    state_bound, ip);
1397 				} else {
1398 					ip->client->state = S_BOUND;
1399 					note("bound: immediate renewal.");
1400 					state_bound(ip);
1401 				}
1402 				reinitialize_interfaces();
1403 				go_daemon();
1404 				return;
1405 			}
1406 		}
1407 
1408 		/* If there are no other leases, give up. */
1409 		if (!ip->client->leases) {
1410 			ip->client->leases = ip->client->active;
1411 			ip->client->active = NULL;
1412 			break;
1413 		}
1414 
1415 activate_next:
1416 		/* Otherwise, put the active lease at the end of the
1417 		   lease list, and try another lease.. */
1418 		for (lp = ip->client->leases; lp->next; lp = lp->next)
1419 			;
1420 		lp->next = ip->client->active;
1421 		if (lp->next)
1422 			lp->next->next = NULL;
1423 		ip->client->active = ip->client->leases;
1424 		ip->client->leases = ip->client->leases->next;
1425 
1426 		/* If we already tried this lease, we've exhausted the
1427 		   set of leases, so we might as well give up for
1428 		   now. */
1429 		if (ip->client->active == loop)
1430 			break;
1431 		else if (!loop)
1432 			loop = ip->client->active;
1433 	}
1434 
1435 	/* No leases were available, or what was available didn't work, so
1436 	   tell the shell script that we failed to allocate an address,
1437 	   and try again later. */
1438 	note("No working leases in persistent database - sleeping.\n");
1439 	script_init("FAIL", NULL);
1440 	if (ip->client->alias)
1441 		script_write_params("alias_", ip->client->alias);
1442 	script_go();
1443 	ip->client->state = S_INIT;
1444 	add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1445 	    ip);
1446 	go_daemon();
1447 }
1448 
1449 void
1450 send_request(void *ipp)
1451 {
1452 	struct interface_info *ip = ipp;
1453 	struct in_addr from, to;
1454 	int interval;
1455 
1456 	/* Figure out how long it's been since we started transmitting. */
1457 	interval = cur_time - ip->client->first_sending;
1458 
1459 	/* If we're in the INIT-REBOOT or REQUESTING state and we're
1460 	   past the reboot timeout, go to INIT and see if we can
1461 	   DISCOVER an address... */
1462 	/* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1463 	   means either that we're on a network with no DHCP server,
1464 	   or that our server is down.  In the latter case, assuming
1465 	   that there is a backup DHCP server, DHCPDISCOVER will get
1466 	   us a new address, but we could also have successfully
1467 	   reused our old address.  In the former case, we're hosed
1468 	   anyway.  This is not a win-prone situation. */
1469 	if ((ip->client->state == S_REBOOTING ||
1470 	    ip->client->state == S_REQUESTING) &&
1471 	    interval > ip->client->config->reboot_timeout) {
1472 cancel:
1473 		ip->client->state = S_INIT;
1474 		cancel_timeout(send_request, ip);
1475 		state_init(ip);
1476 		return;
1477 	}
1478 
1479 	/* If we're in the reboot state, make sure the media is set up
1480 	   correctly. */
1481 	if (ip->client->state == S_REBOOTING &&
1482 	    !ip->client->medium &&
1483 	    ip->client->active->medium ) {
1484 		script_init("MEDIUM", ip->client->active->medium);
1485 
1486 		/* If the medium we chose won't fly, go to INIT state. */
1487 		if (script_go())
1488 			goto cancel;
1489 
1490 		/* Record the medium. */
1491 		ip->client->medium = ip->client->active->medium;
1492 	}
1493 
1494 	/* If the lease has expired, relinquish the address and go back
1495 	   to the INIT state. */
1496 	if (ip->client->state != S_REQUESTING &&
1497 	    cur_time > ip->client->active->expiry) {
1498 		/* Run the client script with the new parameters. */
1499 		script_init("EXPIRE", NULL);
1500 		script_write_params("old_", ip->client->active);
1501 		if (ip->client->alias)
1502 			script_write_params("alias_", ip->client->alias);
1503 		script_go();
1504 
1505 		/* Now do a preinit on the interface so that we can
1506 		   discover a new address. */
1507 		script_init("PREINIT", NULL);
1508 		if (ip->client->alias)
1509 			script_write_params("alias_", ip->client->alias);
1510 		script_go();
1511 
1512 		ip->client->state = S_INIT;
1513 		state_init(ip);
1514 		return;
1515 	}
1516 
1517 	/* Do the exponential backoff... */
1518 	if (!ip->client->interval)
1519 		ip->client->interval = ip->client->config->initial_interval;
1520 	else
1521 		ip->client->interval += ((arc4random() >> 2) %
1522 		    (2 * ip->client->interval));
1523 
1524 	/* Don't backoff past cutoff. */
1525 	if (ip->client->interval >
1526 	    ip->client->config->backoff_cutoff)
1527 		ip->client->interval =
1528 		    ((ip->client->config->backoff_cutoff / 2) +
1529 		    ((arc4random() >> 2) % ip->client->interval));
1530 
1531 	/* If the backoff would take us to the expiry time, just set the
1532 	   timeout to the expiry time. */
1533 	if (ip->client->state != S_REQUESTING &&
1534 	    cur_time + ip->client->interval >
1535 	    ip->client->active->expiry)
1536 		ip->client->interval =
1537 		    ip->client->active->expiry - cur_time + 1;
1538 
1539 	/* If the lease T2 time has elapsed, or if we're not yet bound,
1540 	   broadcast the DHCPREQUEST rather than unicasting. */
1541 	if (ip->client->state == S_REQUESTING ||
1542 	    ip->client->state == S_REBOOTING ||
1543 	    cur_time > ip->client->active->rebind)
1544 		to.s_addr = INADDR_BROADCAST;
1545 	else
1546 		memcpy(&to.s_addr, ip->client->destination.iabuf,
1547 		    sizeof(to.s_addr));
1548 
1549 	if (ip->client->state != S_REQUESTING &&
1550 	    ip->client->state != S_REBOOTING)
1551 		memcpy(&from, ip->client->active->address.iabuf,
1552 		    sizeof(from));
1553 	else
1554 		from.s_addr = INADDR_ANY;
1555 
1556 	/* Record the number of seconds since we started sending. */
1557 	if (ip->client->state == S_REQUESTING)
1558 		ip->client->packet.secs = ip->client->secs;
1559 	else {
1560 		if (interval < 65536)
1561 			ip->client->packet.secs = htons(interval);
1562 		else
1563 			ip->client->packet.secs = htons(65535);
1564 	}
1565 
1566 	note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1567 	    REMOTE_PORT);
1568 
1569 	/* Send out a packet. */
1570 	send_packet_unpriv(privfd, &ip->client->packet,
1571 	    ip->client->packet_length, from, to);
1572 
1573 	add_timeout(cur_time + ip->client->interval, send_request, ip);
1574 }
1575 
1576 void
1577 send_decline(void *ipp)
1578 {
1579 	struct interface_info *ip = ipp;
1580 
1581 	note("DHCPDECLINE on %s to %s port %d", ip->name,
1582 	    inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1583 
1584 	/* Send out a packet. */
1585 	send_packet_unpriv(privfd, &ip->client->packet,
1586 	    ip->client->packet_length, inaddr_any, inaddr_broadcast);
1587 }
1588 
1589 void
1590 make_discover(struct interface_info *ip, struct client_lease *lease)
1591 {
1592 	unsigned char discover = DHCPDISCOVER;
1593 	struct tree_cache *options[256];
1594 	struct tree_cache option_elements[256];
1595 	int i;
1596 
1597 	memset(option_elements, 0, sizeof(option_elements));
1598 	memset(options, 0, sizeof(options));
1599 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1600 
1601 	/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1602 	i = DHO_DHCP_MESSAGE_TYPE;
1603 	options[i] = &option_elements[i];
1604 	options[i]->value = &discover;
1605 	options[i]->len = sizeof(discover);
1606 	options[i]->buf_size = sizeof(discover);
1607 	options[i]->timeout = 0xFFFFFFFF;
1608 
1609 	/* Request the options we want */
1610 	i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1611 	options[i] = &option_elements[i];
1612 	options[i]->value = ip->client->config->requested_options;
1613 	options[i]->len = ip->client->config->requested_option_count;
1614 	options[i]->buf_size =
1615 		ip->client->config->requested_option_count;
1616 	options[i]->timeout = 0xFFFFFFFF;
1617 
1618 	/* If we had an address, try to get it again. */
1619 	if (lease) {
1620 		ip->client->requested_address = lease->address;
1621 		i = DHO_DHCP_REQUESTED_ADDRESS;
1622 		options[i] = &option_elements[i];
1623 		options[i]->value = lease->address.iabuf;
1624 		options[i]->len = lease->address.len;
1625 		options[i]->buf_size = lease->address.len;
1626 		options[i]->timeout = 0xFFFFFFFF;
1627 	} else
1628 		ip->client->requested_address.len = 0;
1629 
1630 	/* Send any options requested in the config file. */
1631 	for (i = 0; i < 256; i++)
1632 		if (!options[i] &&
1633 		    ip->client->config->send_options[i].data) {
1634 			options[i] = &option_elements[i];
1635 			options[i]->value =
1636 			    ip->client->config->send_options[i].data;
1637 			options[i]->len =
1638 			    ip->client->config->send_options[i].len;
1639 			options[i]->buf_size =
1640 			    ip->client->config->send_options[i].len;
1641 			options[i]->timeout = 0xFFFFFFFF;
1642 		}
1643 
1644 	/* send host name if not set via config file. */
1645 	if (!options[DHO_HOST_NAME]) {
1646 		if (hostname[0] != '\0') {
1647 			size_t len;
1648 			char* posDot = strchr(hostname, '.');
1649 			if (posDot != NULL)
1650 				len = posDot - hostname;
1651 			else
1652 				len = strlen(hostname);
1653 			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1654 			options[DHO_HOST_NAME]->value = hostname;
1655 			options[DHO_HOST_NAME]->len = len;
1656 			options[DHO_HOST_NAME]->buf_size = len;
1657 			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1658 		}
1659 	}
1660 
1661 	/* set unique client identifier */
1662 	char client_ident[sizeof(ip->hw_address.haddr) + 1];
1663 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1664 		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1665 				ip->hw_address.hlen : sizeof(client_ident)-1;
1666 		client_ident[0] = ip->hw_address.htype;
1667 		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1668 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1669 		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1670 		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1671 		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1672 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1673 	}
1674 
1675 	/* Set up the option buffer... */
1676 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1677 	    options, 0, 0, 0, NULL, 0);
1678 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1679 		ip->client->packet_length = BOOTP_MIN_LEN;
1680 
1681 	ip->client->packet.op = BOOTREQUEST;
1682 	ip->client->packet.htype = ip->hw_address.htype;
1683 	ip->client->packet.hlen = ip->hw_address.hlen;
1684 	ip->client->packet.hops = 0;
1685 	ip->client->packet.xid = arc4random();
1686 	ip->client->packet.secs = 0; /* filled in by send_discover. */
1687 	ip->client->packet.flags = 0;
1688 
1689 	memset(&(ip->client->packet.ciaddr),
1690 	    0, sizeof(ip->client->packet.ciaddr));
1691 	memset(&(ip->client->packet.yiaddr),
1692 	    0, sizeof(ip->client->packet.yiaddr));
1693 	memset(&(ip->client->packet.siaddr),
1694 	    0, sizeof(ip->client->packet.siaddr));
1695 	memset(&(ip->client->packet.giaddr),
1696 	    0, sizeof(ip->client->packet.giaddr));
1697 	memcpy(ip->client->packet.chaddr,
1698 	    ip->hw_address.haddr, ip->hw_address.hlen);
1699 }
1700 
1701 
1702 void
1703 make_request(struct interface_info *ip, struct client_lease * lease)
1704 {
1705 	unsigned char request = DHCPREQUEST;
1706 	struct tree_cache *options[256];
1707 	struct tree_cache option_elements[256];
1708 	int i;
1709 
1710 	memset(options, 0, sizeof(options));
1711 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1712 
1713 	/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1714 	i = DHO_DHCP_MESSAGE_TYPE;
1715 	options[i] = &option_elements[i];
1716 	options[i]->value = &request;
1717 	options[i]->len = sizeof(request);
1718 	options[i]->buf_size = sizeof(request);
1719 	options[i]->timeout = 0xFFFFFFFF;
1720 
1721 	/* Request the options we want */
1722 	i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1723 	options[i] = &option_elements[i];
1724 	options[i]->value = ip->client->config->requested_options;
1725 	options[i]->len = ip->client->config->requested_option_count;
1726 	options[i]->buf_size =
1727 		ip->client->config->requested_option_count;
1728 	options[i]->timeout = 0xFFFFFFFF;
1729 
1730 	/* If we are requesting an address that hasn't yet been assigned
1731 	   to us, use the DHCP Requested Address option. */
1732 	if (ip->client->state == S_REQUESTING) {
1733 		/* Send back the server identifier... */
1734 		i = DHO_DHCP_SERVER_IDENTIFIER;
1735 		options[i] = &option_elements[i];
1736 		options[i]->value = lease->options[i].data;
1737 		options[i]->len = lease->options[i].len;
1738 		options[i]->buf_size = lease->options[i].len;
1739 		options[i]->timeout = 0xFFFFFFFF;
1740 	}
1741 	if (ip->client->state == S_REQUESTING ||
1742 	    ip->client->state == S_REBOOTING) {
1743 		ip->client->requested_address = lease->address;
1744 		i = DHO_DHCP_REQUESTED_ADDRESS;
1745 		options[i] = &option_elements[i];
1746 		options[i]->value = lease->address.iabuf;
1747 		options[i]->len = lease->address.len;
1748 		options[i]->buf_size = lease->address.len;
1749 		options[i]->timeout = 0xFFFFFFFF;
1750 	} else
1751 		ip->client->requested_address.len = 0;
1752 
1753 	/* Send any options requested in the config file. */
1754 	for (i = 0; i < 256; i++)
1755 		if (!options[i] &&
1756 		    ip->client->config->send_options[i].data) {
1757 			options[i] = &option_elements[i];
1758 			options[i]->value =
1759 			    ip->client->config->send_options[i].data;
1760 			options[i]->len =
1761 			    ip->client->config->send_options[i].len;
1762 			options[i]->buf_size =
1763 			    ip->client->config->send_options[i].len;
1764 			options[i]->timeout = 0xFFFFFFFF;
1765 		}
1766 
1767 	/* send host name if not set via config file. */
1768 	if (!options[DHO_HOST_NAME]) {
1769 		if (hostname[0] != '\0') {
1770 			size_t len;
1771 			char* posDot = strchr(hostname, '.');
1772 			if (posDot != NULL)
1773 				len = posDot - hostname;
1774 			else
1775 				len = strlen(hostname);
1776 			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1777 			options[DHO_HOST_NAME]->value = hostname;
1778 			options[DHO_HOST_NAME]->len = len;
1779 			options[DHO_HOST_NAME]->buf_size = len;
1780 			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1781 		}
1782 	}
1783 
1784 	/* set unique client identifier */
1785 	char client_ident[sizeof(ip->hw_address.haddr) + 1];
1786 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1787 		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1788 				ip->hw_address.hlen : sizeof(client_ident)-1;
1789 		client_ident[0] = ip->hw_address.htype;
1790 		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1791 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1792 		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1793 		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1794 		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1795 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1796 	}
1797 
1798 	/* Set up the option buffer... */
1799 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1800 	    options, 0, 0, 0, NULL, 0);
1801 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1802 		ip->client->packet_length = BOOTP_MIN_LEN;
1803 
1804 	ip->client->packet.op = BOOTREQUEST;
1805 	ip->client->packet.htype = ip->hw_address.htype;
1806 	ip->client->packet.hlen = ip->hw_address.hlen;
1807 	ip->client->packet.hops = 0;
1808 	ip->client->packet.xid = ip->client->xid;
1809 	ip->client->packet.secs = 0; /* Filled in by send_request. */
1810 
1811 	/* If we own the address we're requesting, put it in ciaddr;
1812 	   otherwise set ciaddr to zero. */
1813 	if (ip->client->state == S_BOUND ||
1814 	    ip->client->state == S_RENEWING ||
1815 	    ip->client->state == S_REBINDING) {
1816 		memcpy(&ip->client->packet.ciaddr,
1817 		    lease->address.iabuf, lease->address.len);
1818 		ip->client->packet.flags = 0;
1819 	} else {
1820 		memset(&ip->client->packet.ciaddr, 0,
1821 		    sizeof(ip->client->packet.ciaddr));
1822 		ip->client->packet.flags = 0;
1823 	}
1824 
1825 	memset(&ip->client->packet.yiaddr, 0,
1826 	    sizeof(ip->client->packet.yiaddr));
1827 	memset(&ip->client->packet.siaddr, 0,
1828 	    sizeof(ip->client->packet.siaddr));
1829 	memset(&ip->client->packet.giaddr, 0,
1830 	    sizeof(ip->client->packet.giaddr));
1831 	memcpy(ip->client->packet.chaddr,
1832 	    ip->hw_address.haddr, ip->hw_address.hlen);
1833 }
1834 
1835 void
1836 make_decline(struct interface_info *ip, struct client_lease *lease)
1837 {
1838 	struct tree_cache *options[256], message_type_tree;
1839 	struct tree_cache requested_address_tree;
1840 	struct tree_cache server_id_tree, client_id_tree;
1841 	unsigned char decline = DHCPDECLINE;
1842 	int i;
1843 
1844 	memset(options, 0, sizeof(options));
1845 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1846 
1847 	/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1848 	i = DHO_DHCP_MESSAGE_TYPE;
1849 	options[i] = &message_type_tree;
1850 	options[i]->value = &decline;
1851 	options[i]->len = sizeof(decline);
1852 	options[i]->buf_size = sizeof(decline);
1853 	options[i]->timeout = 0xFFFFFFFF;
1854 
1855 	/* Send back the server identifier... */
1856 	i = DHO_DHCP_SERVER_IDENTIFIER;
1857 	options[i] = &server_id_tree;
1858 	options[i]->value = lease->options[i].data;
1859 	options[i]->len = lease->options[i].len;
1860 	options[i]->buf_size = lease->options[i].len;
1861 	options[i]->timeout = 0xFFFFFFFF;
1862 
1863 	/* Send back the address we're declining. */
1864 	i = DHO_DHCP_REQUESTED_ADDRESS;
1865 	options[i] = &requested_address_tree;
1866 	options[i]->value = lease->address.iabuf;
1867 	options[i]->len = lease->address.len;
1868 	options[i]->buf_size = lease->address.len;
1869 	options[i]->timeout = 0xFFFFFFFF;
1870 
1871 	/* Send the uid if the user supplied one. */
1872 	i = DHO_DHCP_CLIENT_IDENTIFIER;
1873 	if (ip->client->config->send_options[i].len) {
1874 		options[i] = &client_id_tree;
1875 		options[i]->value = ip->client->config->send_options[i].data;
1876 		options[i]->len = ip->client->config->send_options[i].len;
1877 		options[i]->buf_size = ip->client->config->send_options[i].len;
1878 		options[i]->timeout = 0xFFFFFFFF;
1879 	}
1880 
1881 
1882 	/* Set up the option buffer... */
1883 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1884 	    options, 0, 0, 0, NULL, 0);
1885 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1886 		ip->client->packet_length = BOOTP_MIN_LEN;
1887 
1888 	ip->client->packet.op = BOOTREQUEST;
1889 	ip->client->packet.htype = ip->hw_address.htype;
1890 	ip->client->packet.hlen = ip->hw_address.hlen;
1891 	ip->client->packet.hops = 0;
1892 	ip->client->packet.xid = ip->client->xid;
1893 	ip->client->packet.secs = 0; /* Filled in by send_request. */
1894 	ip->client->packet.flags = 0;
1895 
1896 	/* ciaddr must always be zero. */
1897 	memset(&ip->client->packet.ciaddr, 0,
1898 	    sizeof(ip->client->packet.ciaddr));
1899 	memset(&ip->client->packet.yiaddr, 0,
1900 	    sizeof(ip->client->packet.yiaddr));
1901 	memset(&ip->client->packet.siaddr, 0,
1902 	    sizeof(ip->client->packet.siaddr));
1903 	memset(&ip->client->packet.giaddr, 0,
1904 	    sizeof(ip->client->packet.giaddr));
1905 	memcpy(ip->client->packet.chaddr,
1906 	    ip->hw_address.haddr, ip->hw_address.hlen);
1907 }
1908 
1909 void
1910 free_client_lease(struct client_lease *lease)
1911 {
1912 	int i;
1913 
1914 	if (lease->server_name)
1915 		free(lease->server_name);
1916 	if (lease->filename)
1917 		free(lease->filename);
1918 	for (i = 0; i < 256; i++) {
1919 		if (lease->options[i].len)
1920 			free(lease->options[i].data);
1921 	}
1922 	free(lease);
1923 }
1924 
1925 static FILE *leaseFile;
1926 
1927 void
1928 rewrite_client_leases(void)
1929 {
1930 	struct client_lease *lp;
1931 	cap_rights_t rights;
1932 
1933 	if (!leaseFile) {
1934 		leaseFile = fopen(path_dhclient_db, "w");
1935 		if (!leaseFile)
1936 			error("can't create %s: %m", path_dhclient_db);
1937 		cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1938 		    CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1939 		if (caph_rights_limit(fileno(leaseFile), &rights) < 0) {
1940 			error("can't limit lease descriptor: %m");
1941 		}
1942 		if (caph_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0) {
1943 			error("can't limit lease descriptor fcntls: %m");
1944 		}
1945 	} else {
1946 		fflush(leaseFile);
1947 		rewind(leaseFile);
1948 	}
1949 
1950 	for (lp = ifi->client->leases; lp; lp = lp->next)
1951 		write_client_lease(ifi, lp, 1);
1952 	if (ifi->client->active)
1953 		write_client_lease(ifi, ifi->client->active, 1);
1954 
1955 	fflush(leaseFile);
1956 	ftruncate(fileno(leaseFile), ftello(leaseFile));
1957 	fsync(fileno(leaseFile));
1958 }
1959 
1960 void
1961 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1962     int rewrite)
1963 {
1964 	static int leases_written;
1965 	struct tm *t;
1966 	int i;
1967 
1968 	if (!rewrite) {
1969 		if (leases_written++ > 20) {
1970 			rewrite_client_leases();
1971 			leases_written = 0;
1972 		}
1973 	}
1974 
1975 	/* If the lease came from the config file, we don't need to stash
1976 	   a copy in the lease database. */
1977 	if (lease->is_static)
1978 		return;
1979 
1980 	if (!leaseFile) {	/* XXX */
1981 		leaseFile = fopen(path_dhclient_db, "w");
1982 		if (!leaseFile)
1983 			error("can't create %s: %m", path_dhclient_db);
1984 	}
1985 
1986 	fprintf(leaseFile, "lease {\n");
1987 	if (lease->is_bootp)
1988 		fprintf(leaseFile, "  bootp;\n");
1989 	fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1990 	fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1991 	if (lease->nextserver.len == sizeof(inaddr_any) &&
1992 	    0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1993 	    sizeof(inaddr_any)))
1994 		fprintf(leaseFile, "  next-server %s;\n",
1995 		    piaddr(lease->nextserver));
1996 	if (lease->filename)
1997 		fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1998 	if (lease->server_name)
1999 		fprintf(leaseFile, "  server-name \"%s\";\n",
2000 		    lease->server_name);
2001 	if (lease->medium)
2002 		fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
2003 	for (i = 0; i < 256; i++)
2004 		if (lease->options[i].len)
2005 			fprintf(leaseFile, "  option %s %s;\n",
2006 			    dhcp_options[i].name,
2007 			    pretty_print_option(i, lease->options[i].data,
2008 			    lease->options[i].len, 1, 1));
2009 
2010 	t = gmtime(&lease->renewal);
2011 	fprintf(leaseFile, "  renew %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 	t = gmtime(&lease->rebind);
2015 	fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2016 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2017 	    t->tm_hour, t->tm_min, t->tm_sec);
2018 	t = gmtime(&lease->expiry);
2019 	fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
2020 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2021 	    t->tm_hour, t->tm_min, t->tm_sec);
2022 	fprintf(leaseFile, "}\n");
2023 	fflush(leaseFile);
2024 }
2025 
2026 void
2027 script_init(const char *reason, struct string_list *medium)
2028 {
2029 	size_t		 len, mediumlen = 0;
2030 	struct imsg_hdr	 hdr;
2031 	struct buf	*buf;
2032 	int		 errs;
2033 
2034 	if (medium != NULL && medium->string != NULL)
2035 		mediumlen = strlen(medium->string);
2036 
2037 	hdr.code = IMSG_SCRIPT_INIT;
2038 	hdr.len = sizeof(struct imsg_hdr) +
2039 	    sizeof(size_t) + mediumlen +
2040 	    sizeof(size_t) + strlen(reason);
2041 
2042 	if ((buf = buf_open(hdr.len)) == NULL)
2043 		error("buf_open: %m");
2044 
2045 	errs = 0;
2046 	errs += buf_add(buf, &hdr, sizeof(hdr));
2047 	errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2048 	if (mediumlen > 0)
2049 		errs += buf_add(buf, medium->string, mediumlen);
2050 	len = strlen(reason);
2051 	errs += buf_add(buf, &len, sizeof(len));
2052 	errs += buf_add(buf, reason, len);
2053 
2054 	if (errs)
2055 		error("buf_add: %m");
2056 
2057 	if (buf_close(privfd, buf) == -1)
2058 		error("buf_close: %m");
2059 }
2060 
2061 void
2062 priv_script_init(const char *reason, char *medium)
2063 {
2064 	struct interface_info *ip = ifi;
2065 
2066 	if (ip) {
2067 		ip->client->scriptEnvsize = 100;
2068 		if (ip->client->scriptEnv == NULL)
2069 			ip->client->scriptEnv =
2070 			    malloc(ip->client->scriptEnvsize * sizeof(char *));
2071 		if (ip->client->scriptEnv == NULL)
2072 			error("script_init: no memory for environment");
2073 
2074 		ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2075 		if (ip->client->scriptEnv[0] == NULL)
2076 			error("script_init: no memory for environment");
2077 
2078 		ip->client->scriptEnv[1] = NULL;
2079 
2080 		script_set_env(ip->client, "", "interface", ip->name);
2081 
2082 		if (medium)
2083 			script_set_env(ip->client, "", "medium", medium);
2084 
2085 		script_set_env(ip->client, "", "reason", reason);
2086 	}
2087 }
2088 
2089 void
2090 priv_script_write_params(const char *prefix, struct client_lease *lease)
2091 {
2092 	struct interface_info *ip = ifi;
2093 	u_int8_t dbuf[1500], *dp = NULL;
2094 	int i;
2095 	size_t len;
2096 	char tbuf[128];
2097 
2098 	script_set_env(ip->client, prefix, "ip_address",
2099 	    piaddr(lease->address));
2100 
2101 	if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2102 	    ACTION_SUPERSEDE) {
2103 		dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2104 		len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2105 	} else {
2106 		dp = lease->options[DHO_SUBNET_MASK].data;
2107 		len = lease->options[DHO_SUBNET_MASK].len;
2108 	}
2109 	if (len && (len < sizeof(lease->address.iabuf))) {
2110 		struct iaddr netmask, subnet, broadcast;
2111 
2112 		memcpy(netmask.iabuf, dp, len);
2113 		netmask.len = len;
2114 		subnet = subnet_number(lease->address, netmask);
2115 		if (subnet.len) {
2116 			script_set_env(ip->client, prefix, "network_number",
2117 			    piaddr(subnet));
2118 			if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2119 				broadcast = broadcast_addr(subnet, netmask);
2120 				if (broadcast.len)
2121 					script_set_env(ip->client, prefix,
2122 					    "broadcast_address",
2123 					    piaddr(broadcast));
2124 			}
2125 		}
2126 	}
2127 
2128 	if (lease->filename)
2129 		script_set_env(ip->client, prefix, "filename", lease->filename);
2130 	if (lease->server_name)
2131 		script_set_env(ip->client, prefix, "server_name",
2132 		    lease->server_name);
2133 	for (i = 0; i < 256; i++) {
2134 		len = 0;
2135 
2136 		if (ip->client->config->defaults[i].len) {
2137 			if (lease->options[i].len) {
2138 				switch (
2139 				    ip->client->config->default_actions[i]) {
2140 				case ACTION_DEFAULT:
2141 					dp = lease->options[i].data;
2142 					len = lease->options[i].len;
2143 					break;
2144 				case ACTION_SUPERSEDE:
2145 supersede:
2146 					dp = ip->client->
2147 						config->defaults[i].data;
2148 					len = ip->client->
2149 						config->defaults[i].len;
2150 					break;
2151 				case ACTION_PREPEND:
2152 					len = ip->client->
2153 					    config->defaults[i].len +
2154 					    lease->options[i].len;
2155 					if (len >= sizeof(dbuf)) {
2156 						warning("no space to %s %s",
2157 						    "prepend option",
2158 						    dhcp_options[i].name);
2159 						goto supersede;
2160 					}
2161 					dp = dbuf;
2162 					memcpy(dp,
2163 						ip->client->
2164 						config->defaults[i].data,
2165 						ip->client->
2166 						config->defaults[i].len);
2167 					memcpy(dp + ip->client->
2168 						config->defaults[i].len,
2169 						lease->options[i].data,
2170 						lease->options[i].len);
2171 					dp[len] = '\0';
2172 					break;
2173 				case ACTION_APPEND:
2174 					/*
2175 					 * When we append, we assume that we're
2176 					 * appending to text.  Some MS servers
2177 					 * include a NUL byte at the end of
2178 					 * the search string provided.
2179 					 */
2180 					len = ip->client->
2181 					    config->defaults[i].len +
2182 					    lease->options[i].len;
2183 					if (len >= sizeof(dbuf)) {
2184 						warning("no space to %s %s",
2185 						    "append option",
2186 						    dhcp_options[i].name);
2187 						goto supersede;
2188 					}
2189 					memcpy(dbuf,
2190 						lease->options[i].data,
2191 						lease->options[i].len);
2192 					for (dp = dbuf + lease->options[i].len;
2193 					    dp > dbuf; dp--, len--)
2194 						if (dp[-1] != '\0')
2195 							break;
2196 					memcpy(dp,
2197 						ip->client->
2198 						config->defaults[i].data,
2199 						ip->client->
2200 						config->defaults[i].len);
2201 					dp = dbuf;
2202 					dp[len] = '\0';
2203 				}
2204 			} else {
2205 				dp = ip->client->
2206 					config->defaults[i].data;
2207 				len = ip->client->
2208 					config->defaults[i].len;
2209 			}
2210 		} else if (lease->options[i].len) {
2211 			len = lease->options[i].len;
2212 			dp = lease->options[i].data;
2213 		} else {
2214 			len = 0;
2215 		}
2216 		if (len) {
2217 			char name[256];
2218 
2219 			if (dhcp_option_ev_name(name, sizeof(name),
2220 			    &dhcp_options[i]))
2221 				script_set_env(ip->client, prefix, name,
2222 				    pretty_print_option(i, dp, len, 0, 0));
2223 		}
2224 	}
2225 	snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2226 	script_set_env(ip->client, prefix, "expiry", tbuf);
2227 }
2228 
2229 void
2230 script_write_params(const char *prefix, struct client_lease *lease)
2231 {
2232 	size_t		 fn_len = 0, sn_len = 0, pr_len = 0;
2233 	struct imsg_hdr	 hdr;
2234 	struct buf	*buf;
2235 	int		 errs, i;
2236 
2237 	if (lease->filename != NULL)
2238 		fn_len = strlen(lease->filename);
2239 	if (lease->server_name != NULL)
2240 		sn_len = strlen(lease->server_name);
2241 	if (prefix != NULL)
2242 		pr_len = strlen(prefix);
2243 
2244 	hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2245 	hdr.len = sizeof(hdr) + sizeof(*lease) +
2246 	    sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2247 	    sizeof(pr_len) + pr_len;
2248 
2249 	for (i = 0; i < 256; i++) {
2250 		hdr.len += sizeof(lease->options[i].len);
2251 		hdr.len += lease->options[i].len;
2252 	}
2253 
2254 	scripttime = time(NULL);
2255 
2256 	if ((buf = buf_open(hdr.len)) == NULL)
2257 		error("buf_open: %m");
2258 
2259 	errs = 0;
2260 	errs += buf_add(buf, &hdr, sizeof(hdr));
2261 	errs += buf_add(buf, lease, sizeof(*lease));
2262 	errs += buf_add(buf, &fn_len, sizeof(fn_len));
2263 	errs += buf_add(buf, lease->filename, fn_len);
2264 	errs += buf_add(buf, &sn_len, sizeof(sn_len));
2265 	errs += buf_add(buf, lease->server_name, sn_len);
2266 	errs += buf_add(buf, &pr_len, sizeof(pr_len));
2267 	errs += buf_add(buf, prefix, pr_len);
2268 
2269 	for (i = 0; i < 256; i++) {
2270 		errs += buf_add(buf, &lease->options[i].len,
2271 		    sizeof(lease->options[i].len));
2272 		errs += buf_add(buf, lease->options[i].data,
2273 		    lease->options[i].len);
2274 	}
2275 
2276 	if (errs)
2277 		error("buf_add: %m");
2278 
2279 	if (buf_close(privfd, buf) == -1)
2280 		error("buf_close: %m");
2281 }
2282 
2283 int
2284 script_go(void)
2285 {
2286 	struct imsg_hdr	 hdr;
2287 	struct buf	*buf;
2288 	int		 ret;
2289 
2290 	hdr.code = IMSG_SCRIPT_GO;
2291 	hdr.len = sizeof(struct imsg_hdr);
2292 
2293 	if ((buf = buf_open(hdr.len)) == NULL)
2294 		error("buf_open: %m");
2295 
2296 	if (buf_add(buf, &hdr, sizeof(hdr)))
2297 		error("buf_add: %m");
2298 
2299 	if (buf_close(privfd, buf) == -1)
2300 		error("buf_close: %m");
2301 
2302 	bzero(&hdr, sizeof(hdr));
2303 	buf_read(privfd, &hdr, sizeof(hdr));
2304 	if (hdr.code != IMSG_SCRIPT_GO_RET)
2305 		error("unexpected msg type %u", hdr.code);
2306 	if (hdr.len != sizeof(hdr) + sizeof(int))
2307 		error("received corrupted message");
2308 	buf_read(privfd, &ret, sizeof(ret));
2309 
2310 	scripttime = time(NULL);
2311 
2312 	return (ret);
2313 }
2314 
2315 int
2316 priv_script_go(void)
2317 {
2318 	char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2319 	static char client_path[] = CLIENT_PATH;
2320 	struct interface_info *ip = ifi;
2321 	int pid, wpid, wstatus;
2322 
2323 	scripttime = time(NULL);
2324 
2325 	if (ip) {
2326 		scriptName = ip->client->config->script_name;
2327 		envp = ip->client->scriptEnv;
2328 	} else {
2329 		scriptName = top_level_config.script_name;
2330 		epp[0] = reason;
2331 		epp[1] = client_path;
2332 		epp[2] = NULL;
2333 		envp = epp;
2334 	}
2335 
2336 	argv[0] = scriptName;
2337 	argv[1] = NULL;
2338 
2339 	pid = fork();
2340 	if (pid < 0) {
2341 		error("fork: %m");
2342 		wstatus = 0;
2343 	} else if (pid) {
2344 		do {
2345 			wpid = wait(&wstatus);
2346 		} while (wpid != pid && wpid > 0);
2347 		if (wpid < 0) {
2348 			error("wait: %m");
2349 			wstatus = 0;
2350 		}
2351 	} else {
2352 		execve(scriptName, argv, envp);
2353 		error("execve (%s, ...): %m", scriptName);
2354 	}
2355 
2356 	if (ip)
2357 		script_flush_env(ip->client);
2358 
2359 	return (WIFEXITED(wstatus) ?
2360 	    WEXITSTATUS(wstatus) : 128 + WTERMSIG(wstatus));
2361 }
2362 
2363 void
2364 script_set_env(struct client_state *client, const char *prefix,
2365     const char *name, const char *value)
2366 {
2367 	int i, namelen;
2368 	size_t j;
2369 
2370 	/* No `` or $() command substitution allowed in environment values! */
2371 	for (j=0; j < strlen(value); j++)
2372 		switch (value[j]) {
2373 		case '`':
2374 		case '$':
2375 			warning("illegal character (%c) in value '%s'",
2376 			    value[j], value);
2377 			/* Ignore this option */
2378 			return;
2379 		}
2380 
2381 	namelen = strlen(name);
2382 
2383 	for (i = 0; client->scriptEnv[i]; i++)
2384 		if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2385 		    client->scriptEnv[i][namelen] == '=')
2386 			break;
2387 
2388 	if (client->scriptEnv[i])
2389 		/* Reuse the slot. */
2390 		free(client->scriptEnv[i]);
2391 	else {
2392 		/* New variable.  Expand if necessary. */
2393 		if (i >= client->scriptEnvsize - 1) {
2394 			char **newscriptEnv;
2395 			int newscriptEnvsize = client->scriptEnvsize + 50;
2396 
2397 			newscriptEnv = realloc(client->scriptEnv,
2398 			    newscriptEnvsize);
2399 			if (newscriptEnv == NULL) {
2400 				free(client->scriptEnv);
2401 				client->scriptEnv = NULL;
2402 				client->scriptEnvsize = 0;
2403 				error("script_set_env: no memory for variable");
2404 			}
2405 			client->scriptEnv = newscriptEnv;
2406 			client->scriptEnvsize = newscriptEnvsize;
2407 		}
2408 		/* need to set the NULL pointer at end of array beyond
2409 		   the new slot. */
2410 		client->scriptEnv[i + 1] = NULL;
2411 	}
2412 	/* Allocate space and format the variable in the appropriate slot. */
2413 	client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2414 	    strlen(value) + 1);
2415 	if (client->scriptEnv[i] == NULL)
2416 		error("script_set_env: no memory for variable assignment");
2417 	snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2418 	    1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2419 }
2420 
2421 void
2422 script_flush_env(struct client_state *client)
2423 {
2424 	int i;
2425 
2426 	for (i = 0; client->scriptEnv[i]; i++) {
2427 		free(client->scriptEnv[i]);
2428 		client->scriptEnv[i] = NULL;
2429 	}
2430 	client->scriptEnvsize = 0;
2431 }
2432 
2433 int
2434 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2435 {
2436 	size_t i;
2437 
2438 	for (i = 0; option->name[i]; i++) {
2439 		if (i + 1 == buflen)
2440 			return 0;
2441 		if (option->name[i] == '-')
2442 			buf[i] = '_';
2443 		else
2444 			buf[i] = option->name[i];
2445 	}
2446 
2447 	buf[i] = 0;
2448 	return 1;
2449 }
2450 
2451 void
2452 go_daemon(void)
2453 {
2454 	static int state = 0;
2455 	cap_rights_t rights;
2456 
2457 	if (no_daemon || state)
2458 		return;
2459 
2460 	state = 1;
2461 
2462 	/* Stop logging to stderr... */
2463 	log_perror = 0;
2464 
2465 	if (daemonfd(-1, nullfd) == -1)
2466 		error("daemon");
2467 
2468 	cap_rights_init(&rights);
2469 
2470 	if (pidfile != NULL) {
2471 		pidfile_write(pidfile);
2472 
2473 		if (caph_rights_limit(pidfile_fileno(pidfile), &rights) < 0)
2474 			error("can't limit pidfile descriptor: %m");
2475 	}
2476 
2477 	if (nullfd != -1) {
2478 		close(nullfd);
2479 		nullfd = -1;
2480 	}
2481 
2482 	if (caph_rights_limit(STDIN_FILENO, &rights) < 0)
2483 		error("can't limit stdin: %m");
2484 	cap_rights_init(&rights, CAP_WRITE);
2485 	if (caph_rights_limit(STDOUT_FILENO, &rights) < 0)
2486 		error("can't limit stdout: %m");
2487 	if (caph_rights_limit(STDERR_FILENO, &rights) < 0)
2488 		error("can't limit stderr: %m");
2489 }
2490 
2491 int
2492 check_option(struct client_lease *l, int option)
2493 {
2494 	const char *opbuf;
2495 	const char *sbuf;
2496 
2497 	/* we use this, since this is what gets passed to dhclient-script */
2498 
2499 	opbuf = pretty_print_option(option, l->options[option].data,
2500 	    l->options[option].len, 0, 0);
2501 
2502 	sbuf = option_as_string(option, l->options[option].data,
2503 	    l->options[option].len);
2504 
2505 	switch (option) {
2506 	case DHO_SUBNET_MASK:
2507 	case DHO_TIME_SERVERS:
2508 	case DHO_NAME_SERVERS:
2509 	case DHO_ROUTERS:
2510 	case DHO_DOMAIN_NAME_SERVERS:
2511 	case DHO_LOG_SERVERS:
2512 	case DHO_COOKIE_SERVERS:
2513 	case DHO_LPR_SERVERS:
2514 	case DHO_IMPRESS_SERVERS:
2515 	case DHO_RESOURCE_LOCATION_SERVERS:
2516 	case DHO_SWAP_SERVER:
2517 	case DHO_BROADCAST_ADDRESS:
2518 	case DHO_NIS_SERVERS:
2519 	case DHO_NTP_SERVERS:
2520 	case DHO_NETBIOS_NAME_SERVERS:
2521 	case DHO_NETBIOS_DD_SERVER:
2522 	case DHO_FONT_SERVERS:
2523 	case DHO_DHCP_SERVER_IDENTIFIER:
2524 	case DHO_NISPLUS_SERVERS:
2525 	case DHO_MOBILE_IP_HOME_AGENT:
2526 	case DHO_SMTP_SERVER:
2527 	case DHO_POP_SERVER:
2528 	case DHO_NNTP_SERVER:
2529 	case DHO_WWW_SERVER:
2530 	case DHO_FINGER_SERVER:
2531 	case DHO_IRC_SERVER:
2532 	case DHO_STREETTALK_SERVER:
2533 	case DHO_STREETTALK_DA_SERVER:
2534 		if (!ipv4addrs(opbuf)) {
2535 			warning("Invalid IP address in option: %s", opbuf);
2536 			return (0);
2537 		}
2538 		return (1)  ;
2539 	case DHO_HOST_NAME:
2540 	case DHO_NIS_DOMAIN:
2541 	case DHO_NISPLUS_DOMAIN:
2542 	case DHO_TFTP_SERVER_NAME:
2543 		if (!res_hnok(sbuf)) {
2544 			warning("Bogus Host Name option %d: %s (%s)", option,
2545 			    sbuf, opbuf);
2546 			l->options[option].len = 0;
2547 			free(l->options[option].data);
2548 		}
2549 		return (1);
2550 	case DHO_DOMAIN_NAME:
2551 	case DHO_DOMAIN_SEARCH:
2552 		if (!res_hnok(sbuf)) {
2553 			if (!check_search(sbuf)) {
2554 				warning("Bogus domain search list %d: %s (%s)",
2555 				    option, sbuf, opbuf);
2556 				l->options[option].len = 0;
2557 				free(l->options[option].data);
2558 			}
2559 		}
2560 		return (1);
2561 	case DHO_PAD:
2562 	case DHO_TIME_OFFSET:
2563 	case DHO_BOOT_SIZE:
2564 	case DHO_MERIT_DUMP:
2565 	case DHO_ROOT_PATH:
2566 	case DHO_EXTENSIONS_PATH:
2567 	case DHO_IP_FORWARDING:
2568 	case DHO_NON_LOCAL_SOURCE_ROUTING:
2569 	case DHO_POLICY_FILTER:
2570 	case DHO_MAX_DGRAM_REASSEMBLY:
2571 	case DHO_DEFAULT_IP_TTL:
2572 	case DHO_PATH_MTU_AGING_TIMEOUT:
2573 	case DHO_PATH_MTU_PLATEAU_TABLE:
2574 	case DHO_INTERFACE_MTU:
2575 	case DHO_ALL_SUBNETS_LOCAL:
2576 	case DHO_PERFORM_MASK_DISCOVERY:
2577 	case DHO_MASK_SUPPLIER:
2578 	case DHO_ROUTER_DISCOVERY:
2579 	case DHO_ROUTER_SOLICITATION_ADDRESS:
2580 	case DHO_STATIC_ROUTES:
2581 	case DHO_TRAILER_ENCAPSULATION:
2582 	case DHO_ARP_CACHE_TIMEOUT:
2583 	case DHO_IEEE802_3_ENCAPSULATION:
2584 	case DHO_DEFAULT_TCP_TTL:
2585 	case DHO_TCP_KEEPALIVE_INTERVAL:
2586 	case DHO_TCP_KEEPALIVE_GARBAGE:
2587 	case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2588 	case DHO_NETBIOS_NODE_TYPE:
2589 	case DHO_NETBIOS_SCOPE:
2590 	case DHO_X_DISPLAY_MANAGER:
2591 	case DHO_DHCP_REQUESTED_ADDRESS:
2592 	case DHO_DHCP_LEASE_TIME:
2593 	case DHO_DHCP_OPTION_OVERLOAD:
2594 	case DHO_DHCP_MESSAGE_TYPE:
2595 	case DHO_DHCP_PARAMETER_REQUEST_LIST:
2596 	case DHO_DHCP_MESSAGE:
2597 	case DHO_DHCP_MAX_MESSAGE_SIZE:
2598 	case DHO_DHCP_RENEWAL_TIME:
2599 	case DHO_DHCP_REBINDING_TIME:
2600 	case DHO_DHCP_CLASS_IDENTIFIER:
2601 	case DHO_DHCP_CLIENT_IDENTIFIER:
2602 	case DHO_BOOTFILE_NAME:
2603 	case DHO_DHCP_USER_CLASS_ID:
2604 	case DHO_URL:
2605 	case DHO_END:
2606 		return (1);
2607 	case DHO_CLASSLESS_ROUTES:
2608 		return (check_classless_option(l->options[option].data,
2609 		    l->options[option].len));
2610 	default:
2611 		warning("unknown dhcp option value 0x%x", option);
2612 		return (unknown_ok);
2613 	}
2614 }
2615 
2616 /* RFC 3442 The Classless Static Routes option checks */
2617 int
2618 check_classless_option(unsigned char *data, int len)
2619 {
2620 	int i = 0;
2621 	unsigned char width;
2622 	in_addr_t addr, mask;
2623 
2624 	if (len < 5) {
2625 		warning("Too small length: %d", len);
2626 		return (0);
2627 	}
2628 	while(i < len) {
2629 		width = data[i++];
2630 		if (width == 0) {
2631 			i += 4;
2632 			continue;
2633 		} else if (width < 9) {
2634 			addr =  (in_addr_t)(data[i]	<< 24);
2635 			i += 1;
2636 		} else if (width < 17) {
2637 			addr =  (in_addr_t)(data[i]	<< 24) +
2638 				(in_addr_t)(data[i + 1]	<< 16);
2639 			i += 2;
2640 		} else if (width < 25) {
2641 			addr =  (in_addr_t)(data[i]	<< 24) +
2642 				(in_addr_t)(data[i + 1]	<< 16) +
2643 				(in_addr_t)(data[i + 2]	<< 8);
2644 			i += 3;
2645 		} else if (width < 33) {
2646 			addr =  (in_addr_t)(data[i]	<< 24) +
2647 				(in_addr_t)(data[i + 1]	<< 16) +
2648 				(in_addr_t)(data[i + 2]	<< 8)  +
2649 				data[i + 3];
2650 			i += 4;
2651 		} else {
2652 			warning("Incorrect subnet width: %d", width);
2653 			return (0);
2654 		}
2655 		mask = (in_addr_t)(~0) << (32 - width);
2656 		addr = ntohl(addr);
2657 		mask = ntohl(mask);
2658 
2659 		/*
2660 		 * From RFC 3442:
2661 		 * ... After deriving a subnet number and subnet mask
2662 		 * from each destination descriptor, the DHCP client
2663 		 * MUST zero any bits in the subnet number where the
2664 		 * corresponding bit in the mask is zero...
2665 		 */
2666 		if ((addr & mask) != addr) {
2667 			addr &= mask;
2668 			data[i - 1] = (unsigned char)(
2669 				(addr >> (((32 - width)/8)*8)) & 0xFF);
2670 		}
2671 		i += 4;
2672 	}
2673 	if (i > len) {
2674 		warning("Incorrect data length: %d (must be %d)", len, i);
2675 		return (0);
2676 	}
2677 	return (1);
2678 }
2679 
2680 int
2681 res_hnok(const char *dn)
2682 {
2683 	int pch = PERIOD, ch = *dn++;
2684 
2685 	while (ch != '\0') {
2686 		int nch = *dn++;
2687 
2688 		if (periodchar(ch)) {
2689 			;
2690 		} else if (periodchar(pch)) {
2691 			if (!borderchar(ch))
2692 				return (0);
2693 		} else if (periodchar(nch) || nch == '\0') {
2694 			if (!borderchar(ch))
2695 				return (0);
2696 		} else {
2697 			if (!middlechar(ch))
2698 				return (0);
2699 		}
2700 		pch = ch, ch = nch;
2701 	}
2702 	return (1);
2703 }
2704 
2705 int
2706 check_search(const char *srch)
2707 {
2708         int pch = PERIOD, ch = *srch++;
2709 	int domains = 1;
2710 
2711 	/* 256 char limit re resolv.conf(5) */
2712 	if (strlen(srch) > 256)
2713 		return (0);
2714 
2715 	while (whitechar(ch))
2716 		ch = *srch++;
2717 
2718         while (ch != '\0') {
2719                 int nch = *srch++;
2720 
2721                 if (periodchar(ch) || whitechar(ch)) {
2722                         ;
2723                 } else if (periodchar(pch)) {
2724                         if (!borderchar(ch))
2725                                 return (0);
2726                 } else if (periodchar(nch) || nch == '\0') {
2727                         if (!borderchar(ch))
2728                                 return (0);
2729                 } else {
2730                         if (!middlechar(ch))
2731                                 return (0);
2732                 }
2733 		if (!whitechar(ch)) {
2734 			pch = ch;
2735 		} else {
2736 			while (whitechar(nch)) {
2737 				nch = *srch++;
2738 			}
2739 			if (nch != '\0')
2740 				domains++;
2741 			pch = PERIOD;
2742 		}
2743 		ch = nch;
2744         }
2745 	/* 6 domain limit re resolv.conf(5) */
2746 	if (domains > 6)
2747 		return (0);
2748         return (1);
2749 }
2750 
2751 /* Does buf consist only of dotted decimal ipv4 addrs?
2752  * return how many if so,
2753  * otherwise, return 0
2754  */
2755 int
2756 ipv4addrs(const char * buf)
2757 {
2758 	struct in_addr jnk;
2759 	int count = 0;
2760 
2761 	while (inet_aton(buf, &jnk) == 1){
2762 		count++;
2763 		while (periodchar(*buf) || digitchar(*buf))
2764 			buf++;
2765 		if (*buf == '\0')
2766 			return (count);
2767 		while (*buf ==  ' ')
2768 			buf++;
2769 	}
2770 	return (0);
2771 }
2772 
2773 
2774 const char *
2775 option_as_string(unsigned int code, unsigned char *data, int len)
2776 {
2777 	static char optbuf[32768]; /* XXX */
2778 	char *op = optbuf;
2779 	int opleft = sizeof(optbuf);
2780 	unsigned char *dp = data;
2781 
2782 	if (code > 255)
2783 		error("option_as_string: bad code %d", code);
2784 
2785 	for (; dp < data + len; dp++) {
2786 		if (!isascii(*dp) || !isprint(*dp)) {
2787 			if (dp + 1 != data + len || *dp != 0) {
2788 				snprintf(op, opleft, "\\%03o", *dp);
2789 				op += 4;
2790 				opleft -= 4;
2791 			}
2792 		} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2793 		    *dp == '`' || *dp == '\\') {
2794 			*op++ = '\\';
2795 			*op++ = *dp;
2796 			opleft -= 2;
2797 		} else {
2798 			*op++ = *dp;
2799 			opleft--;
2800 		}
2801 	}
2802 	if (opleft < 1)
2803 		goto toobig;
2804 	*op = 0;
2805 	return optbuf;
2806 toobig:
2807 	warning("dhcp option too large");
2808 	return "<error>";
2809 }
2810 
2811 int
2812 fork_privchld(int fd, int fd2)
2813 {
2814 	struct pollfd pfd[1];
2815 	int nfds;
2816 
2817 	switch (fork()) {
2818 	case -1:
2819 		error("cannot fork");
2820 	case 0:
2821 		break;
2822 	default:
2823 		return (0);
2824 	}
2825 
2826 	setproctitle("%s [priv]", ifi->name);
2827 
2828 	setsid();
2829 	dup2(nullfd, STDIN_FILENO);
2830 	dup2(nullfd, STDOUT_FILENO);
2831 	dup2(nullfd, STDERR_FILENO);
2832 	close(nullfd);
2833 	close(fd2);
2834 	close(ifi->rfdesc);
2835 	ifi->rfdesc = -1;
2836 
2837 	for (;;) {
2838 		pfd[0].fd = fd;
2839 		pfd[0].events = POLLIN;
2840 		if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2841 			if (errno != EINTR)
2842 				error("poll error");
2843 
2844 		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2845 			continue;
2846 
2847 		dispatch_imsg(ifi, fd);
2848 	}
2849 }
2850