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