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