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