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