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