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