xref: /freebsd/sbin/dhclient/dhclient.c (revision 6ae1554a5d9b318f8ad53ccc39fa5a961403da73)
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_FCNTL, CAP_FSTAT, CAP_FSYNC,
1849 		    CAP_FTRUNCATE, 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 		if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1855 		    errno != ENOSYS) {
1856 			error("can't limit lease descriptor fcntls: %m");
1857 		}
1858 	} else {
1859 		fflush(leaseFile);
1860 		rewind(leaseFile);
1861 	}
1862 
1863 	for (lp = ifi->client->leases; lp; lp = lp->next)
1864 		write_client_lease(ifi, lp, 1);
1865 	if (ifi->client->active)
1866 		write_client_lease(ifi, ifi->client->active, 1);
1867 
1868 	fflush(leaseFile);
1869 	ftruncate(fileno(leaseFile), ftello(leaseFile));
1870 	fsync(fileno(leaseFile));
1871 }
1872 
1873 void
1874 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1875     int rewrite)
1876 {
1877 	static int leases_written;
1878 	struct tm *t;
1879 	int i;
1880 
1881 	if (!rewrite) {
1882 		if (leases_written++ > 20) {
1883 			rewrite_client_leases();
1884 			leases_written = 0;
1885 		}
1886 	}
1887 
1888 	/* If the lease came from the config file, we don't need to stash
1889 	   a copy in the lease database. */
1890 	if (lease->is_static)
1891 		return;
1892 
1893 	if (!leaseFile) {	/* XXX */
1894 		leaseFile = fopen(path_dhclient_db, "w");
1895 		if (!leaseFile)
1896 			error("can't create %s: %m", path_dhclient_db);
1897 	}
1898 
1899 	fprintf(leaseFile, "lease {\n");
1900 	if (lease->is_bootp)
1901 		fprintf(leaseFile, "  bootp;\n");
1902 	fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1903 	fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1904 	if (lease->nextserver.len == sizeof(inaddr_any) &&
1905 	    0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1906 	    sizeof(inaddr_any)))
1907 		fprintf(leaseFile, "  next-server %s;\n",
1908 		    piaddr(lease->nextserver));
1909 	if (lease->filename)
1910 		fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1911 	if (lease->server_name)
1912 		fprintf(leaseFile, "  server-name \"%s\";\n",
1913 		    lease->server_name);
1914 	if (lease->medium)
1915 		fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1916 	for (i = 0; i < 256; i++)
1917 		if (lease->options[i].len)
1918 			fprintf(leaseFile, "  option %s %s;\n",
1919 			    dhcp_options[i].name,
1920 			    pretty_print_option(i, lease->options[i].data,
1921 			    lease->options[i].len, 1, 1));
1922 
1923 	t = gmtime(&lease->renewal);
1924 	fprintf(leaseFile, "  renew %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->rebind);
1928 	fprintf(leaseFile, "  rebind %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 	t = gmtime(&lease->expiry);
1932 	fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
1933 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1934 	    t->tm_hour, t->tm_min, t->tm_sec);
1935 	fprintf(leaseFile, "}\n");
1936 	fflush(leaseFile);
1937 }
1938 
1939 void
1940 script_init(char *reason, struct string_list *medium)
1941 {
1942 	size_t		 len, mediumlen = 0;
1943 	struct imsg_hdr	 hdr;
1944 	struct buf	*buf;
1945 	int		 errs;
1946 
1947 	if (medium != NULL && medium->string != NULL)
1948 		mediumlen = strlen(medium->string);
1949 
1950 	hdr.code = IMSG_SCRIPT_INIT;
1951 	hdr.len = sizeof(struct imsg_hdr) +
1952 	    sizeof(size_t) + mediumlen +
1953 	    sizeof(size_t) + strlen(reason);
1954 
1955 	if ((buf = buf_open(hdr.len)) == NULL)
1956 		error("buf_open: %m");
1957 
1958 	errs = 0;
1959 	errs += buf_add(buf, &hdr, sizeof(hdr));
1960 	errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1961 	if (mediumlen > 0)
1962 		errs += buf_add(buf, medium->string, mediumlen);
1963 	len = strlen(reason);
1964 	errs += buf_add(buf, &len, sizeof(len));
1965 	errs += buf_add(buf, reason, len);
1966 
1967 	if (errs)
1968 		error("buf_add: %m");
1969 
1970 	if (buf_close(privfd, buf) == -1)
1971 		error("buf_close: %m");
1972 }
1973 
1974 void
1975 priv_script_init(char *reason, char *medium)
1976 {
1977 	struct interface_info *ip = ifi;
1978 
1979 	if (ip) {
1980 		ip->client->scriptEnvsize = 100;
1981 		if (ip->client->scriptEnv == NULL)
1982 			ip->client->scriptEnv =
1983 			    malloc(ip->client->scriptEnvsize * sizeof(char *));
1984 		if (ip->client->scriptEnv == NULL)
1985 			error("script_init: no memory for environment");
1986 
1987 		ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
1988 		if (ip->client->scriptEnv[0] == NULL)
1989 			error("script_init: no memory for environment");
1990 
1991 		ip->client->scriptEnv[1] = NULL;
1992 
1993 		script_set_env(ip->client, "", "interface", ip->name);
1994 
1995 		if (medium)
1996 			script_set_env(ip->client, "", "medium", medium);
1997 
1998 		script_set_env(ip->client, "", "reason", reason);
1999 	}
2000 }
2001 
2002 void
2003 priv_script_write_params(char *prefix, struct client_lease *lease)
2004 {
2005 	struct interface_info *ip = ifi;
2006 	u_int8_t dbuf[1500], *dp = NULL;
2007 	int i, len;
2008 	char tbuf[128];
2009 
2010 	script_set_env(ip->client, prefix, "ip_address",
2011 	    piaddr(lease->address));
2012 
2013 	if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2014 	    ACTION_SUPERSEDE) {
2015 		dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2016 		len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2017 	} else {
2018 		dp = lease->options[DHO_SUBNET_MASK].data;
2019 		len = lease->options[DHO_SUBNET_MASK].len;
2020 	}
2021 	if (len && (len < sizeof(lease->address.iabuf))) {
2022 		struct iaddr netmask, subnet, broadcast;
2023 
2024 		memcpy(netmask.iabuf, dp, len);
2025 		netmask.len = len;
2026 		subnet = subnet_number(lease->address, netmask);
2027 		if (subnet.len) {
2028 			script_set_env(ip->client, prefix, "network_number",
2029 			    piaddr(subnet));
2030 			if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2031 				broadcast = broadcast_addr(subnet, netmask);
2032 				if (broadcast.len)
2033 					script_set_env(ip->client, prefix,
2034 					    "broadcast_address",
2035 					    piaddr(broadcast));
2036 			}
2037 		}
2038 	}
2039 
2040 	if (lease->filename)
2041 		script_set_env(ip->client, prefix, "filename", lease->filename);
2042 	if (lease->server_name)
2043 		script_set_env(ip->client, prefix, "server_name",
2044 		    lease->server_name);
2045 	for (i = 0; i < 256; i++) {
2046 		len = 0;
2047 
2048 		if (ip->client->config->defaults[i].len) {
2049 			if (lease->options[i].len) {
2050 				switch (
2051 				    ip->client->config->default_actions[i]) {
2052 				case ACTION_DEFAULT:
2053 					dp = lease->options[i].data;
2054 					len = lease->options[i].len;
2055 					break;
2056 				case ACTION_SUPERSEDE:
2057 supersede:
2058 					dp = ip->client->
2059 						config->defaults[i].data;
2060 					len = ip->client->
2061 						config->defaults[i].len;
2062 					break;
2063 				case ACTION_PREPEND:
2064 					len = ip->client->
2065 					    config->defaults[i].len +
2066 					    lease->options[i].len;
2067 					if (len >= sizeof(dbuf)) {
2068 						warning("no space to %s %s",
2069 						    "prepend option",
2070 						    dhcp_options[i].name);
2071 						goto supersede;
2072 					}
2073 					dp = dbuf;
2074 					memcpy(dp,
2075 						ip->client->
2076 						config->defaults[i].data,
2077 						ip->client->
2078 						config->defaults[i].len);
2079 					memcpy(dp + ip->client->
2080 						config->defaults[i].len,
2081 						lease->options[i].data,
2082 						lease->options[i].len);
2083 					dp[len] = '\0';
2084 					break;
2085 				case ACTION_APPEND:
2086 					/*
2087 					 * When we append, we assume that we're
2088 					 * appending to text.  Some MS servers
2089 					 * include a NUL byte at the end of
2090 					 * the search string provided.
2091 					 */
2092 					len = ip->client->
2093 					    config->defaults[i].len +
2094 					    lease->options[i].len;
2095 					if (len >= sizeof(dbuf)) {
2096 						warning("no space to %s %s",
2097 						    "append option",
2098 						    dhcp_options[i].name);
2099 						goto supersede;
2100 					}
2101 					memcpy(dbuf,
2102 						lease->options[i].data,
2103 						lease->options[i].len);
2104 					for (dp = dbuf + lease->options[i].len;
2105 					    dp > dbuf; dp--, len--)
2106 						if (dp[-1] != '\0')
2107 							break;
2108 					memcpy(dp,
2109 						ip->client->
2110 						config->defaults[i].data,
2111 						ip->client->
2112 						config->defaults[i].len);
2113 					dp = dbuf;
2114 					dp[len] = '\0';
2115 				}
2116 			} else {
2117 				dp = ip->client->
2118 					config->defaults[i].data;
2119 				len = ip->client->
2120 					config->defaults[i].len;
2121 			}
2122 		} else if (lease->options[i].len) {
2123 			len = lease->options[i].len;
2124 			dp = lease->options[i].data;
2125 		} else {
2126 			len = 0;
2127 		}
2128 		if (len) {
2129 			char name[256];
2130 
2131 			if (dhcp_option_ev_name(name, sizeof(name),
2132 			    &dhcp_options[i]))
2133 				script_set_env(ip->client, prefix, name,
2134 				    pretty_print_option(i, dp, len, 0, 0));
2135 		}
2136 	}
2137 	snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2138 	script_set_env(ip->client, prefix, "expiry", tbuf);
2139 }
2140 
2141 void
2142 script_write_params(char *prefix, struct client_lease *lease)
2143 {
2144 	size_t		 fn_len = 0, sn_len = 0, pr_len = 0;
2145 	struct imsg_hdr	 hdr;
2146 	struct buf	*buf;
2147 	int		 errs, i;
2148 
2149 	if (lease->filename != NULL)
2150 		fn_len = strlen(lease->filename);
2151 	if (lease->server_name != NULL)
2152 		sn_len = strlen(lease->server_name);
2153 	if (prefix != NULL)
2154 		pr_len = strlen(prefix);
2155 
2156 	hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2157 	hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2158 	    sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2159 	    sizeof(size_t) + pr_len;
2160 
2161 	for (i = 0; i < 256; i++)
2162 		hdr.len += sizeof(int) + lease->options[i].len;
2163 
2164 	scripttime = time(NULL);
2165 
2166 	if ((buf = buf_open(hdr.len)) == NULL)
2167 		error("buf_open: %m");
2168 
2169 	errs = 0;
2170 	errs += buf_add(buf, &hdr, sizeof(hdr));
2171 	errs += buf_add(buf, lease, sizeof(struct client_lease));
2172 	errs += buf_add(buf, &fn_len, sizeof(fn_len));
2173 	errs += buf_add(buf, lease->filename, fn_len);
2174 	errs += buf_add(buf, &sn_len, sizeof(sn_len));
2175 	errs += buf_add(buf, lease->server_name, sn_len);
2176 	errs += buf_add(buf, &pr_len, sizeof(pr_len));
2177 	errs += buf_add(buf, prefix, pr_len);
2178 
2179 	for (i = 0; i < 256; i++) {
2180 		errs += buf_add(buf, &lease->options[i].len,
2181 		    sizeof(lease->options[i].len));
2182 		errs += buf_add(buf, lease->options[i].data,
2183 		    lease->options[i].len);
2184 	}
2185 
2186 	if (errs)
2187 		error("buf_add: %m");
2188 
2189 	if (buf_close(privfd, buf) == -1)
2190 		error("buf_close: %m");
2191 }
2192 
2193 int
2194 script_go(void)
2195 {
2196 	struct imsg_hdr	 hdr;
2197 	struct buf	*buf;
2198 	int		 ret;
2199 
2200 	hdr.code = IMSG_SCRIPT_GO;
2201 	hdr.len = sizeof(struct imsg_hdr);
2202 
2203 	if ((buf = buf_open(hdr.len)) == NULL)
2204 		error("buf_open: %m");
2205 
2206 	if (buf_add(buf, &hdr, sizeof(hdr)))
2207 		error("buf_add: %m");
2208 
2209 	if (buf_close(privfd, buf) == -1)
2210 		error("buf_close: %m");
2211 
2212 	bzero(&hdr, sizeof(hdr));
2213 	buf_read(privfd, &hdr, sizeof(hdr));
2214 	if (hdr.code != IMSG_SCRIPT_GO_RET)
2215 		error("unexpected msg type %u", hdr.code);
2216 	if (hdr.len != sizeof(hdr) + sizeof(int))
2217 		error("received corrupted message");
2218 	buf_read(privfd, &ret, sizeof(ret));
2219 
2220 	scripttime = time(NULL);
2221 
2222 	return (ret);
2223 }
2224 
2225 int
2226 priv_script_go(void)
2227 {
2228 	char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2229 	static char client_path[] = CLIENT_PATH;
2230 	struct interface_info *ip = ifi;
2231 	int pid, wpid, wstatus;
2232 
2233 	scripttime = time(NULL);
2234 
2235 	if (ip) {
2236 		scriptName = ip->client->config->script_name;
2237 		envp = ip->client->scriptEnv;
2238 	} else {
2239 		scriptName = top_level_config.script_name;
2240 		epp[0] = reason;
2241 		epp[1] = client_path;
2242 		epp[2] = NULL;
2243 		envp = epp;
2244 	}
2245 
2246 	argv[0] = scriptName;
2247 	argv[1] = NULL;
2248 
2249 	pid = fork();
2250 	if (pid < 0) {
2251 		error("fork: %m");
2252 		wstatus = 0;
2253 	} else if (pid) {
2254 		do {
2255 			wpid = wait(&wstatus);
2256 		} while (wpid != pid && wpid > 0);
2257 		if (wpid < 0) {
2258 			error("wait: %m");
2259 			wstatus = 0;
2260 		}
2261 	} else {
2262 		execve(scriptName, argv, envp);
2263 		error("execve (%s, ...): %m", scriptName);
2264 	}
2265 
2266 	if (ip)
2267 		script_flush_env(ip->client);
2268 
2269 	return (wstatus & 0xff);
2270 }
2271 
2272 void
2273 script_set_env(struct client_state *client, const char *prefix,
2274     const char *name, const char *value)
2275 {
2276 	int i, j, namelen;
2277 
2278 	namelen = strlen(name);
2279 
2280 	for (i = 0; client->scriptEnv[i]; i++)
2281 		if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2282 		    client->scriptEnv[i][namelen] == '=')
2283 			break;
2284 
2285 	if (client->scriptEnv[i])
2286 		/* Reuse the slot. */
2287 		free(client->scriptEnv[i]);
2288 	else {
2289 		/* New variable.  Expand if necessary. */
2290 		if (i >= client->scriptEnvsize - 1) {
2291 			char **newscriptEnv;
2292 			int newscriptEnvsize = client->scriptEnvsize + 50;
2293 
2294 			newscriptEnv = realloc(client->scriptEnv,
2295 			    newscriptEnvsize);
2296 			if (newscriptEnv == NULL) {
2297 				free(client->scriptEnv);
2298 				client->scriptEnv = NULL;
2299 				client->scriptEnvsize = 0;
2300 				error("script_set_env: no memory for variable");
2301 			}
2302 			client->scriptEnv = newscriptEnv;
2303 			client->scriptEnvsize = newscriptEnvsize;
2304 		}
2305 		/* need to set the NULL pointer at end of array beyond
2306 		   the new slot. */
2307 		client->scriptEnv[i + 1] = NULL;
2308 	}
2309 	/* Allocate space and format the variable in the appropriate slot. */
2310 	client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2311 	    strlen(value) + 1);
2312 	if (client->scriptEnv[i] == NULL)
2313 		error("script_set_env: no memory for variable assignment");
2314 
2315 	/* No `` or $() command substitution allowed in environment values! */
2316 	for (j=0; j < strlen(value); j++)
2317 		switch (value[j]) {
2318 		case '`':
2319 		case '$':
2320 			error("illegal character (%c) in value '%s'", value[j],
2321 			    value);
2322 			/* not reached */
2323 		}
2324 	snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2325 	    1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2326 }
2327 
2328 void
2329 script_flush_env(struct client_state *client)
2330 {
2331 	int i;
2332 
2333 	for (i = 0; client->scriptEnv[i]; i++) {
2334 		free(client->scriptEnv[i]);
2335 		client->scriptEnv[i] = NULL;
2336 	}
2337 	client->scriptEnvsize = 0;
2338 }
2339 
2340 int
2341 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2342 {
2343 	int i;
2344 
2345 	for (i = 0; option->name[i]; i++) {
2346 		if (i + 1 == buflen)
2347 			return 0;
2348 		if (option->name[i] == '-')
2349 			buf[i] = '_';
2350 		else
2351 			buf[i] = option->name[i];
2352 	}
2353 
2354 	buf[i] = 0;
2355 	return 1;
2356 }
2357 
2358 void
2359 go_daemon(void)
2360 {
2361 	static int state = 0;
2362 	cap_rights_t rights;
2363 
2364 	if (no_daemon || state)
2365 		return;
2366 
2367 	state = 1;
2368 
2369 	/* Stop logging to stderr... */
2370 	log_perror = 0;
2371 
2372 	if (daemon(1, 0) == -1)
2373 		error("daemon");
2374 
2375 	cap_rights_init(&rights);
2376 
2377 	if (pidfile != NULL) {
2378 		pidfile_write(pidfile);
2379 		if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2380 		    errno != ENOSYS) {
2381 			error("can't limit pidfile descriptor: %m");
2382 		}
2383 	}
2384 
2385 	/* we are chrooted, daemon(3) fails to open /dev/null */
2386 	if (nullfd != -1) {
2387 		dup2(nullfd, STDIN_FILENO);
2388 		dup2(nullfd, STDOUT_FILENO);
2389 		dup2(nullfd, STDERR_FILENO);
2390 		close(nullfd);
2391 		nullfd = -1;
2392 	}
2393 
2394 	if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2395 		error("can't limit stdin: %m");
2396 	cap_rights_init(&rights, CAP_WRITE);
2397 	if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2398 		error("can't limit stdout: %m");
2399 	if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2400 		error("can't limit stderr: %m");
2401 }
2402 
2403 int
2404 check_option(struct client_lease *l, int option)
2405 {
2406 	char *opbuf;
2407 	char *sbuf;
2408 
2409 	/* we use this, since this is what gets passed to dhclient-script */
2410 
2411 	opbuf = pretty_print_option(option, l->options[option].data,
2412 	    l->options[option].len, 0, 0);
2413 
2414 	sbuf = option_as_string(option, l->options[option].data,
2415 	    l->options[option].len);
2416 
2417 	switch (option) {
2418 	case DHO_SUBNET_MASK:
2419 	case DHO_TIME_SERVERS:
2420 	case DHO_NAME_SERVERS:
2421 	case DHO_ROUTERS:
2422 	case DHO_DOMAIN_NAME_SERVERS:
2423 	case DHO_LOG_SERVERS:
2424 	case DHO_COOKIE_SERVERS:
2425 	case DHO_LPR_SERVERS:
2426 	case DHO_IMPRESS_SERVERS:
2427 	case DHO_RESOURCE_LOCATION_SERVERS:
2428 	case DHO_SWAP_SERVER:
2429 	case DHO_BROADCAST_ADDRESS:
2430 	case DHO_NIS_SERVERS:
2431 	case DHO_NTP_SERVERS:
2432 	case DHO_NETBIOS_NAME_SERVERS:
2433 	case DHO_NETBIOS_DD_SERVER:
2434 	case DHO_FONT_SERVERS:
2435 	case DHO_DHCP_SERVER_IDENTIFIER:
2436 	case DHO_NISPLUS_SERVERS:
2437 	case DHO_MOBILE_IP_HOME_AGENT:
2438 	case DHO_SMTP_SERVER:
2439 	case DHO_POP_SERVER:
2440 	case DHO_NNTP_SERVER:
2441 	case DHO_WWW_SERVER:
2442 	case DHO_FINGER_SERVER:
2443 	case DHO_IRC_SERVER:
2444 	case DHO_STREETTALK_SERVER:
2445 	case DHO_STREETTALK_DA_SERVER:
2446 		if (!ipv4addrs(opbuf)) {
2447 			warning("Invalid IP address in option: %s", opbuf);
2448 			return (0);
2449 		}
2450 		return (1)  ;
2451 	case DHO_HOST_NAME:
2452 	case DHO_NIS_DOMAIN:
2453 	case DHO_NISPLUS_DOMAIN:
2454 	case DHO_TFTP_SERVER_NAME:
2455 		if (!res_hnok(sbuf)) {
2456 			warning("Bogus Host Name option %d: %s (%s)", option,
2457 			    sbuf, opbuf);
2458 			l->options[option].len = 0;
2459 			free(l->options[option].data);
2460 		}
2461 		return (1);
2462 	case DHO_DOMAIN_NAME:
2463 	case DHO_DOMAIN_SEARCH:
2464 		if (!res_hnok(sbuf)) {
2465 			if (!check_search(sbuf)) {
2466 				warning("Bogus domain search list %d: %s (%s)",
2467 				    option, sbuf, opbuf);
2468 				l->options[option].len = 0;
2469 				free(l->options[option].data);
2470 			}
2471 		}
2472 		return (1);
2473 	case DHO_PAD:
2474 	case DHO_TIME_OFFSET:
2475 	case DHO_BOOT_SIZE:
2476 	case DHO_MERIT_DUMP:
2477 	case DHO_ROOT_PATH:
2478 	case DHO_EXTENSIONS_PATH:
2479 	case DHO_IP_FORWARDING:
2480 	case DHO_NON_LOCAL_SOURCE_ROUTING:
2481 	case DHO_POLICY_FILTER:
2482 	case DHO_MAX_DGRAM_REASSEMBLY:
2483 	case DHO_DEFAULT_IP_TTL:
2484 	case DHO_PATH_MTU_AGING_TIMEOUT:
2485 	case DHO_PATH_MTU_PLATEAU_TABLE:
2486 	case DHO_INTERFACE_MTU:
2487 	case DHO_ALL_SUBNETS_LOCAL:
2488 	case DHO_PERFORM_MASK_DISCOVERY:
2489 	case DHO_MASK_SUPPLIER:
2490 	case DHO_ROUTER_DISCOVERY:
2491 	case DHO_ROUTER_SOLICITATION_ADDRESS:
2492 	case DHO_STATIC_ROUTES:
2493 	case DHO_TRAILER_ENCAPSULATION:
2494 	case DHO_ARP_CACHE_TIMEOUT:
2495 	case DHO_IEEE802_3_ENCAPSULATION:
2496 	case DHO_DEFAULT_TCP_TTL:
2497 	case DHO_TCP_KEEPALIVE_INTERVAL:
2498 	case DHO_TCP_KEEPALIVE_GARBAGE:
2499 	case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2500 	case DHO_NETBIOS_NODE_TYPE:
2501 	case DHO_NETBIOS_SCOPE:
2502 	case DHO_X_DISPLAY_MANAGER:
2503 	case DHO_DHCP_REQUESTED_ADDRESS:
2504 	case DHO_DHCP_LEASE_TIME:
2505 	case DHO_DHCP_OPTION_OVERLOAD:
2506 	case DHO_DHCP_MESSAGE_TYPE:
2507 	case DHO_DHCP_PARAMETER_REQUEST_LIST:
2508 	case DHO_DHCP_MESSAGE:
2509 	case DHO_DHCP_MAX_MESSAGE_SIZE:
2510 	case DHO_DHCP_RENEWAL_TIME:
2511 	case DHO_DHCP_REBINDING_TIME:
2512 	case DHO_DHCP_CLASS_IDENTIFIER:
2513 	case DHO_DHCP_CLIENT_IDENTIFIER:
2514 	case DHO_BOOTFILE_NAME:
2515 	case DHO_DHCP_USER_CLASS_ID:
2516 	case DHO_END:
2517 		return (1);
2518 	case DHO_CLASSLESS_ROUTES:
2519 		return (check_classless_option(l->options[option].data,
2520 		    l->options[option].len));
2521 	default:
2522 		warning("unknown dhcp option value 0x%x", option);
2523 		return (unknown_ok);
2524 	}
2525 }
2526 
2527 /* RFC 3442 The Classless Static Routes option checks */
2528 int
2529 check_classless_option(unsigned char *data, int len)
2530 {
2531 	int i = 0;
2532 	unsigned char width;
2533 	in_addr_t addr, mask;
2534 
2535 	if (len < 5) {
2536 		warning("Too small length: %d", len);
2537 		return (0);
2538 	}
2539 	while(i < len) {
2540 		width = data[i++];
2541 		if (width == 0) {
2542 			i += 4;
2543 			continue;
2544 		} else if (width < 9) {
2545 			addr =  (in_addr_t)(data[i]	<< 24);
2546 			i += 1;
2547 		} else if (width < 17) {
2548 			addr =  (in_addr_t)(data[i]	<< 24) +
2549 				(in_addr_t)(data[i + 1]	<< 16);
2550 			i += 2;
2551 		} else if (width < 25) {
2552 			addr =  (in_addr_t)(data[i]	<< 24) +
2553 				(in_addr_t)(data[i + 1]	<< 16) +
2554 				(in_addr_t)(data[i + 2]	<< 8);
2555 			i += 3;
2556 		} else if (width < 33) {
2557 			addr =  (in_addr_t)(data[i]	<< 24) +
2558 				(in_addr_t)(data[i + 1]	<< 16) +
2559 				(in_addr_t)(data[i + 2]	<< 8)  +
2560 				data[i + 3];
2561 			i += 4;
2562 		} else {
2563 			warning("Incorrect subnet width: %d", width);
2564 			return (0);
2565 		}
2566 		mask = (in_addr_t)(~0) << (32 - width);
2567 		addr = ntohl(addr);
2568 		mask = ntohl(mask);
2569 
2570 		/*
2571 		 * From RFC 3442:
2572 		 * ... After deriving a subnet number and subnet mask
2573 		 * from each destination descriptor, the DHCP client
2574 		 * MUST zero any bits in the subnet number where the
2575 		 * corresponding bit in the mask is zero...
2576 		 */
2577 		if ((addr & mask) != addr) {
2578 			addr &= mask;
2579 			data[i - 1] = (unsigned char)(
2580 				(addr >> (((32 - width)/8)*8)) & 0xFF);
2581 		}
2582 		i += 4;
2583 	}
2584 	if (i > len) {
2585 		warning("Incorrect data length: %d (must be %d)", len, i);
2586 		return (0);
2587 	}
2588 	return (1);
2589 }
2590 
2591 int
2592 res_hnok(const char *dn)
2593 {
2594 	int pch = PERIOD, ch = *dn++;
2595 
2596 	while (ch != '\0') {
2597 		int nch = *dn++;
2598 
2599 		if (periodchar(ch)) {
2600 			;
2601 		} else if (periodchar(pch)) {
2602 			if (!borderchar(ch))
2603 				return (0);
2604 		} else if (periodchar(nch) || nch == '\0') {
2605 			if (!borderchar(ch))
2606 				return (0);
2607 		} else {
2608 			if (!middlechar(ch))
2609 				return (0);
2610 		}
2611 		pch = ch, ch = nch;
2612 	}
2613 	return (1);
2614 }
2615 
2616 int
2617 check_search(const char *srch)
2618 {
2619         int pch = PERIOD, ch = *srch++;
2620 	int domains = 1;
2621 
2622 	/* 256 char limit re resolv.conf(5) */
2623 	if (strlen(srch) > 256)
2624 		return (0);
2625 
2626 	while (whitechar(ch))
2627 		ch = *srch++;
2628 
2629         while (ch != '\0') {
2630                 int nch = *srch++;
2631 
2632                 if (periodchar(ch) || whitechar(ch)) {
2633                         ;
2634                 } else if (periodchar(pch)) {
2635                         if (!borderchar(ch))
2636                                 return (0);
2637                 } else if (periodchar(nch) || nch == '\0') {
2638                         if (!borderchar(ch))
2639                                 return (0);
2640                 } else {
2641                         if (!middlechar(ch))
2642                                 return (0);
2643                 }
2644 		if (!whitechar(ch)) {
2645 			pch = ch;
2646 		} else {
2647 			while (whitechar(nch)) {
2648 				nch = *srch++;
2649 			}
2650 			if (nch != '\0')
2651 				domains++;
2652 			pch = PERIOD;
2653 		}
2654 		ch = nch;
2655         }
2656 	/* 6 domain limit re resolv.conf(5) */
2657 	if (domains > 6)
2658 		return (0);
2659         return (1);
2660 }
2661 
2662 /* Does buf consist only of dotted decimal ipv4 addrs?
2663  * return how many if so,
2664  * otherwise, return 0
2665  */
2666 int
2667 ipv4addrs(char * buf)
2668 {
2669 	struct in_addr jnk;
2670 	int count = 0;
2671 
2672 	while (inet_aton(buf, &jnk) == 1){
2673 		count++;
2674 		while (periodchar(*buf) || digitchar(*buf))
2675 			buf++;
2676 		if (*buf == '\0')
2677 			return (count);
2678 		while (*buf ==  ' ')
2679 			buf++;
2680 	}
2681 	return (0);
2682 }
2683 
2684 
2685 char *
2686 option_as_string(unsigned int code, unsigned char *data, int len)
2687 {
2688 	static char optbuf[32768]; /* XXX */
2689 	char *op = optbuf;
2690 	int opleft = sizeof(optbuf);
2691 	unsigned char *dp = data;
2692 
2693 	if (code > 255)
2694 		error("option_as_string: bad code %d", code);
2695 
2696 	for (; dp < data + len; dp++) {
2697 		if (!isascii(*dp) || !isprint(*dp)) {
2698 			if (dp + 1 != data + len || *dp != 0) {
2699 				snprintf(op, opleft, "\\%03o", *dp);
2700 				op += 4;
2701 				opleft -= 4;
2702 			}
2703 		} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2704 		    *dp == '`' || *dp == '\\') {
2705 			*op++ = '\\';
2706 			*op++ = *dp;
2707 			opleft -= 2;
2708 		} else {
2709 			*op++ = *dp;
2710 			opleft--;
2711 		}
2712 	}
2713 	if (opleft < 1)
2714 		goto toobig;
2715 	*op = 0;
2716 	return optbuf;
2717 toobig:
2718 	warning("dhcp option too large");
2719 	return "<error>";
2720 }
2721 
2722 int
2723 fork_privchld(int fd, int fd2)
2724 {
2725 	struct pollfd pfd[1];
2726 	int nfds;
2727 
2728 	switch (fork()) {
2729 	case -1:
2730 		error("cannot fork");
2731 	case 0:
2732 		break;
2733 	default:
2734 		return (0);
2735 	}
2736 
2737 	setproctitle("%s [priv]", ifi->name);
2738 
2739 	setsid();
2740 	dup2(nullfd, STDIN_FILENO);
2741 	dup2(nullfd, STDOUT_FILENO);
2742 	dup2(nullfd, STDERR_FILENO);
2743 	close(nullfd);
2744 	close(fd2);
2745 	close(ifi->rfdesc);
2746 	ifi->rfdesc = -1;
2747 
2748 	for (;;) {
2749 		pfd[0].fd = fd;
2750 		pfd[0].events = POLLIN;
2751 		if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2752 			if (errno != EINTR)
2753 				error("poll error");
2754 
2755 		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2756 			continue;
2757 
2758 		dispatch_imsg(ifi, fd);
2759 	}
2760 }
2761