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