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