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