xref: /freebsd/sbin/dhclient/dhclient.c (revision c96ae1968a6ab7056427a739bce81bf07447c2d4)
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:qu")) != -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 [-bdqu] ", __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 	/* send host name if not set via config file. */
1466 	char hostname[_POSIX_HOST_NAME_MAX+1];
1467 	if (!options[DHO_HOST_NAME]) {
1468 		if (gethostname(hostname, sizeof(hostname)) == 0) {
1469 			size_t len;
1470 			char* posDot = strchr(hostname, '.');
1471 			if (posDot != NULL)
1472 				len = posDot - hostname;
1473 			else
1474 				len = strlen(hostname);
1475 			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1476 			options[DHO_HOST_NAME]->value = hostname;
1477 			options[DHO_HOST_NAME]->len = len;
1478 			options[DHO_HOST_NAME]->buf_size = len;
1479 			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1480 		}
1481 	}
1482 
1483 	/* set unique client identifier */
1484 	char client_ident[sizeof(struct hardware)];
1485 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1486 		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1487 				ip->hw_address.hlen : sizeof(client_ident)-1;
1488 		client_ident[0] = ip->hw_address.htype;
1489 		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1490 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1491 		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1492 		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1493 		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1494 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1495 	}
1496 
1497 	/* Set up the option buffer... */
1498 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1499 	    options, 0, 0, 0, NULL, 0);
1500 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1501 		ip->client->packet_length = BOOTP_MIN_LEN;
1502 
1503 	ip->client->packet.op = BOOTREQUEST;
1504 	ip->client->packet.htype = ip->hw_address.htype;
1505 	ip->client->packet.hlen = ip->hw_address.hlen;
1506 	ip->client->packet.hops = 0;
1507 	ip->client->packet.xid = arc4random();
1508 	ip->client->packet.secs = 0; /* filled in by send_discover. */
1509 	ip->client->packet.flags = 0;
1510 
1511 	memset(&(ip->client->packet.ciaddr),
1512 	    0, sizeof(ip->client->packet.ciaddr));
1513 	memset(&(ip->client->packet.yiaddr),
1514 	    0, sizeof(ip->client->packet.yiaddr));
1515 	memset(&(ip->client->packet.siaddr),
1516 	    0, sizeof(ip->client->packet.siaddr));
1517 	memset(&(ip->client->packet.giaddr),
1518 	    0, sizeof(ip->client->packet.giaddr));
1519 	memcpy(ip->client->packet.chaddr,
1520 	    ip->hw_address.haddr, ip->hw_address.hlen);
1521 }
1522 
1523 
1524 void
1525 make_request(struct interface_info *ip, struct client_lease * lease)
1526 {
1527 	unsigned char request = DHCPREQUEST;
1528 	struct tree_cache *options[256];
1529 	struct tree_cache option_elements[256];
1530 	int i;
1531 
1532 	memset(options, 0, sizeof(options));
1533 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1534 
1535 	/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1536 	i = DHO_DHCP_MESSAGE_TYPE;
1537 	options[i] = &option_elements[i];
1538 	options[i]->value = &request;
1539 	options[i]->len = sizeof(request);
1540 	options[i]->buf_size = sizeof(request);
1541 	options[i]->timeout = 0xFFFFFFFF;
1542 
1543 	/* Request the options we want */
1544 	i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1545 	options[i] = &option_elements[i];
1546 	options[i]->value = ip->client->config->requested_options;
1547 	options[i]->len = ip->client->config->requested_option_count;
1548 	options[i]->buf_size =
1549 		ip->client->config->requested_option_count;
1550 	options[i]->timeout = 0xFFFFFFFF;
1551 
1552 	/* If we are requesting an address that hasn't yet been assigned
1553 	   to us, use the DHCP Requested Address option. */
1554 	if (ip->client->state == S_REQUESTING) {
1555 		/* Send back the server identifier... */
1556 		i = DHO_DHCP_SERVER_IDENTIFIER;
1557 		options[i] = &option_elements[i];
1558 		options[i]->value = lease->options[i].data;
1559 		options[i]->len = lease->options[i].len;
1560 		options[i]->buf_size = lease->options[i].len;
1561 		options[i]->timeout = 0xFFFFFFFF;
1562 	}
1563 	if (ip->client->state == S_REQUESTING ||
1564 	    ip->client->state == S_REBOOTING) {
1565 		ip->client->requested_address = lease->address;
1566 		i = DHO_DHCP_REQUESTED_ADDRESS;
1567 		options[i] = &option_elements[i];
1568 		options[i]->value = lease->address.iabuf;
1569 		options[i]->len = lease->address.len;
1570 		options[i]->buf_size = lease->address.len;
1571 		options[i]->timeout = 0xFFFFFFFF;
1572 	} else
1573 		ip->client->requested_address.len = 0;
1574 
1575 	/* Send any options requested in the config file. */
1576 	for (i = 0; i < 256; i++)
1577 		if (!options[i] &&
1578 		    ip->client->config->send_options[i].data) {
1579 			options[i] = &option_elements[i];
1580 			options[i]->value =
1581 			    ip->client->config->send_options[i].data;
1582 			options[i]->len =
1583 			    ip->client->config->send_options[i].len;
1584 			options[i]->buf_size =
1585 			    ip->client->config->send_options[i].len;
1586 			options[i]->timeout = 0xFFFFFFFF;
1587 		}
1588 
1589 	/* send host name if not set via config file. */
1590 	char hostname[_POSIX_HOST_NAME_MAX+1];
1591 	if (!options[DHO_HOST_NAME]) {
1592 		if (gethostname(hostname, sizeof(hostname)) == 0) {
1593 			size_t len;
1594 			char* posDot = strchr(hostname, '.');
1595 			if (posDot != NULL)
1596 				len = posDot - hostname;
1597 			else
1598 				len = strlen(hostname);
1599 			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1600 			options[DHO_HOST_NAME]->value = hostname;
1601 			options[DHO_HOST_NAME]->len = len;
1602 			options[DHO_HOST_NAME]->buf_size = len;
1603 			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1604 		}
1605 	}
1606 
1607 	/* set unique client identifier */
1608 	char client_ident[sizeof(struct hardware)];
1609 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1610 		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1611 				ip->hw_address.hlen : sizeof(client_ident)-1;
1612 		client_ident[0] = ip->hw_address.htype;
1613 		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1614 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1615 		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1616 		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1617 		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1618 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1619 	}
1620 
1621 	/* Set up the option buffer... */
1622 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1623 	    options, 0, 0, 0, NULL, 0);
1624 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1625 		ip->client->packet_length = BOOTP_MIN_LEN;
1626 
1627 	ip->client->packet.op = BOOTREQUEST;
1628 	ip->client->packet.htype = ip->hw_address.htype;
1629 	ip->client->packet.hlen = ip->hw_address.hlen;
1630 	ip->client->packet.hops = 0;
1631 	ip->client->packet.xid = ip->client->xid;
1632 	ip->client->packet.secs = 0; /* Filled in by send_request. */
1633 
1634 	/* If we own the address we're requesting, put it in ciaddr;
1635 	   otherwise set ciaddr to zero. */
1636 	if (ip->client->state == S_BOUND ||
1637 	    ip->client->state == S_RENEWING ||
1638 	    ip->client->state == S_REBINDING) {
1639 		memcpy(&ip->client->packet.ciaddr,
1640 		    lease->address.iabuf, lease->address.len);
1641 		ip->client->packet.flags = 0;
1642 	} else {
1643 		memset(&ip->client->packet.ciaddr, 0,
1644 		    sizeof(ip->client->packet.ciaddr));
1645 		ip->client->packet.flags = 0;
1646 	}
1647 
1648 	memset(&ip->client->packet.yiaddr, 0,
1649 	    sizeof(ip->client->packet.yiaddr));
1650 	memset(&ip->client->packet.siaddr, 0,
1651 	    sizeof(ip->client->packet.siaddr));
1652 	memset(&ip->client->packet.giaddr, 0,
1653 	    sizeof(ip->client->packet.giaddr));
1654 	memcpy(ip->client->packet.chaddr,
1655 	    ip->hw_address.haddr, ip->hw_address.hlen);
1656 }
1657 
1658 void
1659 make_decline(struct interface_info *ip, struct client_lease *lease)
1660 {
1661 	struct tree_cache *options[256], message_type_tree;
1662 	struct tree_cache requested_address_tree;
1663 	struct tree_cache server_id_tree, client_id_tree;
1664 	unsigned char decline = DHCPDECLINE;
1665 	int i;
1666 
1667 	memset(options, 0, sizeof(options));
1668 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1669 
1670 	/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1671 	i = DHO_DHCP_MESSAGE_TYPE;
1672 	options[i] = &message_type_tree;
1673 	options[i]->value = &decline;
1674 	options[i]->len = sizeof(decline);
1675 	options[i]->buf_size = sizeof(decline);
1676 	options[i]->timeout = 0xFFFFFFFF;
1677 
1678 	/* Send back the server identifier... */
1679 	i = DHO_DHCP_SERVER_IDENTIFIER;
1680 	options[i] = &server_id_tree;
1681 	options[i]->value = lease->options[i].data;
1682 	options[i]->len = lease->options[i].len;
1683 	options[i]->buf_size = lease->options[i].len;
1684 	options[i]->timeout = 0xFFFFFFFF;
1685 
1686 	/* Send back the address we're declining. */
1687 	i = DHO_DHCP_REQUESTED_ADDRESS;
1688 	options[i] = &requested_address_tree;
1689 	options[i]->value = lease->address.iabuf;
1690 	options[i]->len = lease->address.len;
1691 	options[i]->buf_size = lease->address.len;
1692 	options[i]->timeout = 0xFFFFFFFF;
1693 
1694 	/* Send the uid if the user supplied one. */
1695 	i = DHO_DHCP_CLIENT_IDENTIFIER;
1696 	if (ip->client->config->send_options[i].len) {
1697 		options[i] = &client_id_tree;
1698 		options[i]->value = ip->client->config->send_options[i].data;
1699 		options[i]->len = ip->client->config->send_options[i].len;
1700 		options[i]->buf_size = ip->client->config->send_options[i].len;
1701 		options[i]->timeout = 0xFFFFFFFF;
1702 	}
1703 
1704 
1705 	/* Set up the option buffer... */
1706 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1707 	    options, 0, 0, 0, NULL, 0);
1708 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1709 		ip->client->packet_length = BOOTP_MIN_LEN;
1710 
1711 	ip->client->packet.op = BOOTREQUEST;
1712 	ip->client->packet.htype = ip->hw_address.htype;
1713 	ip->client->packet.hlen = ip->hw_address.hlen;
1714 	ip->client->packet.hops = 0;
1715 	ip->client->packet.xid = ip->client->xid;
1716 	ip->client->packet.secs = 0; /* Filled in by send_request. */
1717 	ip->client->packet.flags = 0;
1718 
1719 	/* ciaddr must always be zero. */
1720 	memset(&ip->client->packet.ciaddr, 0,
1721 	    sizeof(ip->client->packet.ciaddr));
1722 	memset(&ip->client->packet.yiaddr, 0,
1723 	    sizeof(ip->client->packet.yiaddr));
1724 	memset(&ip->client->packet.siaddr, 0,
1725 	    sizeof(ip->client->packet.siaddr));
1726 	memset(&ip->client->packet.giaddr, 0,
1727 	    sizeof(ip->client->packet.giaddr));
1728 	memcpy(ip->client->packet.chaddr,
1729 	    ip->hw_address.haddr, ip->hw_address.hlen);
1730 }
1731 
1732 void
1733 free_client_lease(struct client_lease *lease)
1734 {
1735 	int i;
1736 
1737 	if (lease->server_name)
1738 		free(lease->server_name);
1739 	if (lease->filename)
1740 		free(lease->filename);
1741 	for (i = 0; i < 256; i++) {
1742 		if (lease->options[i].len)
1743 			free(lease->options[i].data);
1744 	}
1745 	free(lease);
1746 }
1747 
1748 FILE *leaseFile;
1749 
1750 void
1751 rewrite_client_leases(void)
1752 {
1753 	struct client_lease *lp;
1754 
1755 	if (!leaseFile) {
1756 		leaseFile = fopen(path_dhclient_db, "w");
1757 		if (!leaseFile)
1758 			error("can't create %s: %m", path_dhclient_db);
1759 	} else {
1760 		fflush(leaseFile);
1761 		rewind(leaseFile);
1762 	}
1763 
1764 	for (lp = ifi->client->leases; lp; lp = lp->next)
1765 		write_client_lease(ifi, lp, 1);
1766 	if (ifi->client->active)
1767 		write_client_lease(ifi, ifi->client->active, 1);
1768 
1769 	fflush(leaseFile);
1770 	ftruncate(fileno(leaseFile), ftello(leaseFile));
1771 	fsync(fileno(leaseFile));
1772 }
1773 
1774 void
1775 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1776     int rewrite)
1777 {
1778 	static int leases_written;
1779 	struct tm *t;
1780 	int i;
1781 
1782 	if (!rewrite) {
1783 		if (leases_written++ > 20) {
1784 			rewrite_client_leases();
1785 			leases_written = 0;
1786 		}
1787 	}
1788 
1789 	/* If the lease came from the config file, we don't need to stash
1790 	   a copy in the lease database. */
1791 	if (lease->is_static)
1792 		return;
1793 
1794 	if (!leaseFile) {	/* XXX */
1795 		leaseFile = fopen(path_dhclient_db, "w");
1796 		if (!leaseFile)
1797 			error("can't create %s: %m", path_dhclient_db);
1798 	}
1799 
1800 	fprintf(leaseFile, "lease {\n");
1801 	if (lease->is_bootp)
1802 		fprintf(leaseFile, "  bootp;\n");
1803 	fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1804 	fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1805 	if (lease->filename)
1806 		fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1807 	if (lease->server_name)
1808 		fprintf(leaseFile, "  server-name \"%s\";\n",
1809 		    lease->server_name);
1810 	if (lease->medium)
1811 		fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1812 	for (i = 0; i < 256; i++)
1813 		if (lease->options[i].len)
1814 			fprintf(leaseFile, "  option %s %s;\n",
1815 			    dhcp_options[i].name,
1816 			    pretty_print_option(i, lease->options[i].data,
1817 			    lease->options[i].len, 1, 1));
1818 
1819 	t = gmtime(&lease->renewal);
1820 	fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
1821 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1822 	    t->tm_hour, t->tm_min, t->tm_sec);
1823 	t = gmtime(&lease->rebind);
1824 	fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1825 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1826 	    t->tm_hour, t->tm_min, t->tm_sec);
1827 	t = gmtime(&lease->expiry);
1828 	fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
1829 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1830 	    t->tm_hour, t->tm_min, t->tm_sec);
1831 	fprintf(leaseFile, "}\n");
1832 	fflush(leaseFile);
1833 }
1834 
1835 void
1836 script_init(char *reason, struct string_list *medium)
1837 {
1838 	size_t		 len, mediumlen = 0;
1839 	struct imsg_hdr	 hdr;
1840 	struct buf	*buf;
1841 	int		 errs;
1842 
1843 	if (medium != NULL && medium->string != NULL)
1844 		mediumlen = strlen(medium->string);
1845 
1846 	hdr.code = IMSG_SCRIPT_INIT;
1847 	hdr.len = sizeof(struct imsg_hdr) +
1848 	    sizeof(size_t) + mediumlen +
1849 	    sizeof(size_t) + strlen(reason);
1850 
1851 	if ((buf = buf_open(hdr.len)) == NULL)
1852 		error("buf_open: %m");
1853 
1854 	errs = 0;
1855 	errs += buf_add(buf, &hdr, sizeof(hdr));
1856 	errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1857 	if (mediumlen > 0)
1858 		errs += buf_add(buf, medium->string, mediumlen);
1859 	len = strlen(reason);
1860 	errs += buf_add(buf, &len, sizeof(len));
1861 	errs += buf_add(buf, reason, len);
1862 
1863 	if (errs)
1864 		error("buf_add: %m");
1865 
1866 	if (buf_close(privfd, buf) == -1)
1867 		error("buf_close: %m");
1868 }
1869 
1870 void
1871 priv_script_init(char *reason, char *medium)
1872 {
1873 	struct interface_info *ip = ifi;
1874 
1875 	if (ip) {
1876 		ip->client->scriptEnvsize = 100;
1877 		if (ip->client->scriptEnv == NULL)
1878 			ip->client->scriptEnv =
1879 			    malloc(ip->client->scriptEnvsize * sizeof(char *));
1880 		if (ip->client->scriptEnv == NULL)
1881 			error("script_init: no memory for environment");
1882 
1883 		ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
1884 		if (ip->client->scriptEnv[0] == NULL)
1885 			error("script_init: no memory for environment");
1886 
1887 		ip->client->scriptEnv[1] = NULL;
1888 
1889 		script_set_env(ip->client, "", "interface", ip->name);
1890 
1891 		if (medium)
1892 			script_set_env(ip->client, "", "medium", medium);
1893 
1894 		script_set_env(ip->client, "", "reason", reason);
1895 	}
1896 }
1897 
1898 void
1899 priv_script_write_params(char *prefix, struct client_lease *lease)
1900 {
1901 	struct interface_info *ip = ifi;
1902 	u_int8_t dbuf[1500], *dp = NULL;
1903 	int i, len;
1904 	char tbuf[128];
1905 
1906 	script_set_env(ip->client, prefix, "ip_address",
1907 	    piaddr(lease->address));
1908 
1909 	if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
1910 	    ACTION_SUPERSEDE) {
1911 		dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
1912 		len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
1913 	} else {
1914 		dp = lease->options[DHO_SUBNET_MASK].data;
1915 		len = lease->options[DHO_SUBNET_MASK].len;
1916 	}
1917 	if (len && (len < sizeof(lease->address.iabuf))) {
1918 		struct iaddr netmask, subnet, broadcast;
1919 
1920 		memcpy(netmask.iabuf, dp, len);
1921 		netmask.len = len;
1922 		subnet = subnet_number(lease->address, netmask);
1923 		if (subnet.len) {
1924 			script_set_env(ip->client, prefix, "network_number",
1925 			    piaddr(subnet));
1926 			if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
1927 				broadcast = broadcast_addr(subnet, netmask);
1928 				if (broadcast.len)
1929 					script_set_env(ip->client, prefix,
1930 					    "broadcast_address",
1931 					    piaddr(broadcast));
1932 			}
1933 		}
1934 	}
1935 
1936 	if (lease->filename)
1937 		script_set_env(ip->client, prefix, "filename", lease->filename);
1938 	if (lease->server_name)
1939 		script_set_env(ip->client, prefix, "server_name",
1940 		    lease->server_name);
1941 	for (i = 0; i < 256; i++) {
1942 		len = 0;
1943 
1944 		if (ip->client->config->defaults[i].len) {
1945 			if (lease->options[i].len) {
1946 				switch (
1947 				    ip->client->config->default_actions[i]) {
1948 				case ACTION_DEFAULT:
1949 					dp = lease->options[i].data;
1950 					len = lease->options[i].len;
1951 					break;
1952 				case ACTION_SUPERSEDE:
1953 supersede:
1954 					dp = ip->client->
1955 						config->defaults[i].data;
1956 					len = ip->client->
1957 						config->defaults[i].len;
1958 					break;
1959 				case ACTION_PREPEND:
1960 					len = ip->client->
1961 					    config->defaults[i].len +
1962 					    lease->options[i].len;
1963 					if (len > sizeof(dbuf)) {
1964 						warning("no space to %s %s",
1965 						    "prepend option",
1966 						    dhcp_options[i].name);
1967 						goto supersede;
1968 					}
1969 					dp = dbuf;
1970 					memcpy(dp,
1971 						ip->client->
1972 						config->defaults[i].data,
1973 						ip->client->
1974 						config->defaults[i].len);
1975 					memcpy(dp + ip->client->
1976 						config->defaults[i].len,
1977 						lease->options[i].data,
1978 						lease->options[i].len);
1979 					dp[len] = '\0';
1980 					break;
1981 				case ACTION_APPEND:
1982 					len = ip->client->
1983 					    config->defaults[i].len +
1984 					    lease->options[i].len;
1985 					if (len > sizeof(dbuf)) {
1986 						warning("no space to %s %s",
1987 						    "append option",
1988 						    dhcp_options[i].name);
1989 						goto supersede;
1990 					}
1991 					dp = dbuf;
1992 					memcpy(dp,
1993 						lease->options[i].data,
1994 						lease->options[i].len);
1995 					memcpy(dp + lease->options[i].len,
1996 						ip->client->
1997 						config->defaults[i].data,
1998 						ip->client->
1999 						config->defaults[i].len);
2000 					dp[len] = '\0';
2001 				}
2002 			} else {
2003 				dp = ip->client->
2004 					config->defaults[i].data;
2005 				len = ip->client->
2006 					config->defaults[i].len;
2007 			}
2008 		} else if (lease->options[i].len) {
2009 			len = lease->options[i].len;
2010 			dp = lease->options[i].data;
2011 		} else {
2012 			len = 0;
2013 		}
2014 		if (len) {
2015 			char name[256];
2016 
2017 			if (dhcp_option_ev_name(name, sizeof(name),
2018 			    &dhcp_options[i]))
2019 				script_set_env(ip->client, prefix, name,
2020 				    pretty_print_option(i, dp, len, 0, 0));
2021 		}
2022 	}
2023 	snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2024 	script_set_env(ip->client, prefix, "expiry", tbuf);
2025 }
2026 
2027 void
2028 script_write_params(char *prefix, struct client_lease *lease)
2029 {
2030 	size_t		 fn_len = 0, sn_len = 0, pr_len = 0;
2031 	struct imsg_hdr	 hdr;
2032 	struct buf	*buf;
2033 	int		 errs, i;
2034 
2035 	if (lease->filename != NULL)
2036 		fn_len = strlen(lease->filename);
2037 	if (lease->server_name != NULL)
2038 		sn_len = strlen(lease->server_name);
2039 	if (prefix != NULL)
2040 		pr_len = strlen(prefix);
2041 
2042 	hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2043 	hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2044 	    sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2045 	    sizeof(size_t) + pr_len;
2046 
2047 	for (i = 0; i < 256; i++)
2048 		hdr.len += sizeof(int) + lease->options[i].len;
2049 
2050 	scripttime = time(NULL);
2051 
2052 	if ((buf = buf_open(hdr.len)) == NULL)
2053 		error("buf_open: %m");
2054 
2055 	errs = 0;
2056 	errs += buf_add(buf, &hdr, sizeof(hdr));
2057 	errs += buf_add(buf, lease, sizeof(struct client_lease));
2058 	errs += buf_add(buf, &fn_len, sizeof(fn_len));
2059 	errs += buf_add(buf, lease->filename, fn_len);
2060 	errs += buf_add(buf, &sn_len, sizeof(sn_len));
2061 	errs += buf_add(buf, lease->server_name, sn_len);
2062 	errs += buf_add(buf, &pr_len, sizeof(pr_len));
2063 	errs += buf_add(buf, prefix, pr_len);
2064 
2065 	for (i = 0; i < 256; i++) {
2066 		errs += buf_add(buf, &lease->options[i].len,
2067 		    sizeof(lease->options[i].len));
2068 		errs += buf_add(buf, lease->options[i].data,
2069 		    lease->options[i].len);
2070 	}
2071 
2072 	if (errs)
2073 		error("buf_add: %m");
2074 
2075 	if (buf_close(privfd, buf) == -1)
2076 		error("buf_close: %m");
2077 }
2078 
2079 int
2080 script_go(void)
2081 {
2082 	struct imsg_hdr	 hdr;
2083 	struct buf	*buf;
2084 	int		 ret;
2085 
2086 	scripttime = time(NULL);
2087 
2088 	hdr.code = IMSG_SCRIPT_GO;
2089 	hdr.len = sizeof(struct imsg_hdr);
2090 
2091 	if ((buf = buf_open(hdr.len)) == NULL)
2092 		error("buf_open: %m");
2093 
2094 	if (buf_add(buf, &hdr, sizeof(hdr)))
2095 		error("buf_add: %m");
2096 
2097 	if (buf_close(privfd, buf) == -1)
2098 		error("buf_close: %m");
2099 
2100 	bzero(&hdr, sizeof(hdr));
2101 	buf_read(privfd, &hdr, sizeof(hdr));
2102 	if (hdr.code != IMSG_SCRIPT_GO_RET)
2103 		error("unexpected msg type %u", hdr.code);
2104 	if (hdr.len != sizeof(hdr) + sizeof(int))
2105 		error("received corrupted message");
2106 	buf_read(privfd, &ret, sizeof(ret));
2107 
2108 	return (ret);
2109 }
2110 
2111 int
2112 priv_script_go(void)
2113 {
2114 	char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2115 	static char client_path[] = CLIENT_PATH;
2116 	struct interface_info *ip = ifi;
2117 	int pid, wpid, wstatus;
2118 
2119 	scripttime = time(NULL);
2120 
2121 	if (ip) {
2122 		scriptName = ip->client->config->script_name;
2123 		envp = ip->client->scriptEnv;
2124 	} else {
2125 		scriptName = top_level_config.script_name;
2126 		epp[0] = reason;
2127 		epp[1] = client_path;
2128 		epp[2] = NULL;
2129 		envp = epp;
2130 	}
2131 
2132 	argv[0] = scriptName;
2133 	argv[1] = NULL;
2134 
2135 	pid = fork();
2136 	if (pid < 0) {
2137 		error("fork: %m");
2138 		wstatus = 0;
2139 	} else if (pid) {
2140 		do {
2141 			wpid = wait(&wstatus);
2142 		} while (wpid != pid && wpid > 0);
2143 		if (wpid < 0) {
2144 			error("wait: %m");
2145 			wstatus = 0;
2146 		}
2147 	} else {
2148 		execve(scriptName, argv, envp);
2149 		error("execve (%s, ...): %m", scriptName);
2150 	}
2151 
2152 	if (ip)
2153 		script_flush_env(ip->client);
2154 
2155 	return (wstatus & 0xff);
2156 }
2157 
2158 void
2159 script_set_env(struct client_state *client, const char *prefix,
2160     const char *name, const char *value)
2161 {
2162 	int i, j, namelen;
2163 
2164 	namelen = strlen(name);
2165 
2166 	for (i = 0; client->scriptEnv[i]; i++)
2167 		if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2168 		    client->scriptEnv[i][namelen] == '=')
2169 			break;
2170 
2171 	if (client->scriptEnv[i])
2172 		/* Reuse the slot. */
2173 		free(client->scriptEnv[i]);
2174 	else {
2175 		/* New variable.  Expand if necessary. */
2176 		if (i >= client->scriptEnvsize - 1) {
2177 			char **newscriptEnv;
2178 			int newscriptEnvsize = client->scriptEnvsize + 50;
2179 
2180 			newscriptEnv = realloc(client->scriptEnv,
2181 			    newscriptEnvsize);
2182 			if (newscriptEnv == NULL) {
2183 				free(client->scriptEnv);
2184 				client->scriptEnv = NULL;
2185 				client->scriptEnvsize = 0;
2186 				error("script_set_env: no memory for variable");
2187 			}
2188 			client->scriptEnv = newscriptEnv;
2189 			client->scriptEnvsize = newscriptEnvsize;
2190 		}
2191 		/* need to set the NULL pointer at end of array beyond
2192 		   the new slot. */
2193 		client->scriptEnv[i + 1] = NULL;
2194 	}
2195 	/* Allocate space and format the variable in the appropriate slot. */
2196 	client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2197 	    strlen(value) + 1);
2198 	if (client->scriptEnv[i] == NULL)
2199 		error("script_set_env: no memory for variable assignment");
2200 
2201 	/* No `` or $() command substitution allowed in environment values! */
2202 	for (j=0; j < strlen(value); j++)
2203 		switch (value[j]) {
2204 		case '`':
2205 		case '$':
2206 			error("illegal character (%c) in value '%s'", value[j],
2207 			    value);
2208 			/* not reached */
2209 		}
2210 	snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2211 	    1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2212 }
2213 
2214 void
2215 script_flush_env(struct client_state *client)
2216 {
2217 	int i;
2218 
2219 	for (i = 0; client->scriptEnv[i]; i++) {
2220 		free(client->scriptEnv[i]);
2221 		client->scriptEnv[i] = NULL;
2222 	}
2223 	client->scriptEnvsize = 0;
2224 }
2225 
2226 int
2227 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2228 {
2229 	int i;
2230 
2231 	for (i = 0; option->name[i]; i++) {
2232 		if (i + 1 == buflen)
2233 			return 0;
2234 		if (option->name[i] == '-')
2235 			buf[i] = '_';
2236 		else
2237 			buf[i] = option->name[i];
2238 	}
2239 
2240 	buf[i] = 0;
2241 	return 1;
2242 }
2243 
2244 void
2245 go_daemon(void)
2246 {
2247 	static int state = 0;
2248 
2249 	if (no_daemon || state)
2250 		return;
2251 
2252 	state = 1;
2253 
2254 	/* Stop logging to stderr... */
2255 	log_perror = 0;
2256 
2257 	if (daemon(1, 0) == -1)
2258 		error("daemon");
2259 
2260 	/* we are chrooted, daemon(3) fails to open /dev/null */
2261 	if (nullfd != -1) {
2262 		dup2(nullfd, STDIN_FILENO);
2263 		dup2(nullfd, STDOUT_FILENO);
2264 		dup2(nullfd, STDERR_FILENO);
2265 		close(nullfd);
2266 		nullfd = -1;
2267 	}
2268 }
2269 
2270 int
2271 check_option(struct client_lease *l, int option)
2272 {
2273 	char *opbuf;
2274 	char *sbuf;
2275 
2276 	/* we use this, since this is what gets passed to dhclient-script */
2277 
2278 	opbuf = pretty_print_option(option, l->options[option].data,
2279 	    l->options[option].len, 0, 0);
2280 
2281 	sbuf = option_as_string(option, l->options[option].data,
2282 	    l->options[option].len);
2283 
2284 	switch (option) {
2285 	case DHO_SUBNET_MASK:
2286 	case DHO_TIME_SERVERS:
2287 	case DHO_NAME_SERVERS:
2288 	case DHO_ROUTERS:
2289 	case DHO_DOMAIN_NAME_SERVERS:
2290 	case DHO_LOG_SERVERS:
2291 	case DHO_COOKIE_SERVERS:
2292 	case DHO_LPR_SERVERS:
2293 	case DHO_IMPRESS_SERVERS:
2294 	case DHO_RESOURCE_LOCATION_SERVERS:
2295 	case DHO_SWAP_SERVER:
2296 	case DHO_BROADCAST_ADDRESS:
2297 	case DHO_NIS_SERVERS:
2298 	case DHO_NTP_SERVERS:
2299 	case DHO_NETBIOS_NAME_SERVERS:
2300 	case DHO_NETBIOS_DD_SERVER:
2301 	case DHO_FONT_SERVERS:
2302 	case DHO_DHCP_SERVER_IDENTIFIER:
2303 	case DHO_SMTP_SERVER:
2304 	case DHO_POP_SERVER:
2305 	case DHO_NNTP_SERVER:
2306 	case DHO_WWW_SERVER:
2307 	case DHO_FINGER_SERVER:
2308 	case DHO_IRC_SERVER:
2309 		if (!ipv4addrs(opbuf)) {
2310 			warning("Invalid IP address in option: %s", opbuf);
2311 			return (0);
2312 		}
2313 		return (1)  ;
2314 	case DHO_HOST_NAME:
2315 	case DHO_NIS_DOMAIN:
2316 		if (!res_hnok(sbuf)) {
2317 			warning("Bogus Host Name option %d: %s (%s)", option,
2318 			    sbuf, opbuf);
2319 			l->options[option].len = 0;
2320 			free(l->options[option].data);
2321 		}
2322 		return (1);
2323 	case DHO_DOMAIN_NAME:
2324 		if (!res_hnok(sbuf)) {
2325 			if (!check_search(sbuf)) {
2326 				warning("Bogus domain search list %d: %s (%s)",
2327 				    option, sbuf, opbuf);
2328 				l->options[option].len = 0;
2329 				free(l->options[option].data);
2330 			}
2331 		}
2332 		return (1);
2333 	case DHO_PAD:
2334 	case DHO_TIME_OFFSET:
2335 	case DHO_BOOT_SIZE:
2336 	case DHO_MERIT_DUMP:
2337 	case DHO_ROOT_PATH:
2338 	case DHO_EXTENSIONS_PATH:
2339 	case DHO_IP_FORWARDING:
2340 	case DHO_NON_LOCAL_SOURCE_ROUTING:
2341 	case DHO_POLICY_FILTER:
2342 	case DHO_MAX_DGRAM_REASSEMBLY:
2343 	case DHO_DEFAULT_IP_TTL:
2344 	case DHO_PATH_MTU_AGING_TIMEOUT:
2345 	case DHO_PATH_MTU_PLATEAU_TABLE:
2346 	case DHO_INTERFACE_MTU:
2347 	case DHO_ALL_SUBNETS_LOCAL:
2348 	case DHO_PERFORM_MASK_DISCOVERY:
2349 	case DHO_MASK_SUPPLIER:
2350 	case DHO_ROUTER_DISCOVERY:
2351 	case DHO_ROUTER_SOLICITATION_ADDRESS:
2352 	case DHO_STATIC_ROUTES:
2353 	case DHO_TRAILER_ENCAPSULATION:
2354 	case DHO_ARP_CACHE_TIMEOUT:
2355 	case DHO_IEEE802_3_ENCAPSULATION:
2356 	case DHO_DEFAULT_TCP_TTL:
2357 	case DHO_TCP_KEEPALIVE_INTERVAL:
2358 	case DHO_TCP_KEEPALIVE_GARBAGE:
2359 	case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2360 	case DHO_NETBIOS_NODE_TYPE:
2361 	case DHO_NETBIOS_SCOPE:
2362 	case DHO_X_DISPLAY_MANAGER:
2363 	case DHO_DHCP_REQUESTED_ADDRESS:
2364 	case DHO_DHCP_LEASE_TIME:
2365 	case DHO_DHCP_OPTION_OVERLOAD:
2366 	case DHO_DHCP_MESSAGE_TYPE:
2367 	case DHO_DHCP_PARAMETER_REQUEST_LIST:
2368 	case DHO_DHCP_MESSAGE:
2369 	case DHO_DHCP_MAX_MESSAGE_SIZE:
2370 	case DHO_DHCP_RENEWAL_TIME:
2371 	case DHO_DHCP_REBINDING_TIME:
2372 	case DHO_DHCP_CLASS_IDENTIFIER:
2373 	case DHO_DHCP_CLIENT_IDENTIFIER:
2374 	case DHO_DHCP_USER_CLASS_ID:
2375 	case DHO_END:
2376 		return (1);
2377 	default:
2378 		warning("unknown dhcp option value 0x%x", option);
2379 		return (unknown_ok);
2380 	}
2381 }
2382 
2383 int
2384 res_hnok(const char *dn)
2385 {
2386 	int pch = PERIOD, ch = *dn++;
2387 
2388 	while (ch != '\0') {
2389 		int nch = *dn++;
2390 
2391 		if (periodchar(ch)) {
2392 			;
2393 		} else if (periodchar(pch)) {
2394 			if (!borderchar(ch))
2395 				return (0);
2396 		} else if (periodchar(nch) || nch == '\0') {
2397 			if (!borderchar(ch))
2398 				return (0);
2399 		} else {
2400 			if (!middlechar(ch))
2401 				return (0);
2402 		}
2403 		pch = ch, ch = nch;
2404 	}
2405 	return (1);
2406 }
2407 
2408 int
2409 check_search(const char *srch)
2410 {
2411         int pch = PERIOD, ch = *srch++;
2412 	int domains = 1;
2413 
2414 	/* 256 char limit re resolv.conf(5) */
2415 	if (strlen(srch) > 256)
2416 		return (0);
2417 
2418 	while (whitechar(ch))
2419 		ch = *srch++;
2420 
2421         while (ch != '\0') {
2422                 int nch = *srch++;
2423 
2424                 if (periodchar(ch) || whitechar(ch)) {
2425                         ;
2426                 } else if (periodchar(pch)) {
2427                         if (!borderchar(ch))
2428                                 return (0);
2429                 } else if (periodchar(nch) || nch == '\0') {
2430                         if (!borderchar(ch))
2431                                 return (0);
2432                 } else {
2433                         if (!middlechar(ch))
2434                                 return (0);
2435                 }
2436 		if (!whitechar(ch)) {
2437 			pch = ch;
2438 		} else {
2439 			while (whitechar(nch)) {
2440 				nch = *srch++;
2441 			}
2442 			if (nch != '\0')
2443 				domains++;
2444 			pch = PERIOD;
2445 		}
2446 		ch = nch;
2447         }
2448 	/* 6 domain limit re resolv.conf(5) */
2449 	if (domains > 6)
2450 		return (0);
2451         return (1);
2452 }
2453 
2454 /* Does buf consist only of dotted decimal ipv4 addrs?
2455  * return how many if so,
2456  * otherwise, return 0
2457  */
2458 int
2459 ipv4addrs(char * buf)
2460 {
2461 	struct in_addr jnk;
2462 	int count = 0;
2463 
2464 	while (inet_aton(buf, &jnk) == 1){
2465 		count++;
2466 		while (periodchar(*buf) || digitchar(*buf))
2467 			buf++;
2468 		if (*buf == '\0')
2469 			return (count);
2470 		while (*buf ==  ' ')
2471 			buf++;
2472 	}
2473 	return (0);
2474 }
2475 
2476 
2477 char *
2478 option_as_string(unsigned int code, unsigned char *data, int len)
2479 {
2480 	static char optbuf[32768]; /* XXX */
2481 	char *op = optbuf;
2482 	int opleft = sizeof(optbuf);
2483 	unsigned char *dp = data;
2484 
2485 	if (code > 255)
2486 		error("option_as_string: bad code %d", code);
2487 
2488 	for (; dp < data + len; dp++) {
2489 		if (!isascii(*dp) || !isprint(*dp)) {
2490 			if (dp + 1 != data + len || *dp != 0) {
2491 				snprintf(op, opleft, "\\%03o", *dp);
2492 				op += 4;
2493 				opleft -= 4;
2494 			}
2495 		} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2496 		    *dp == '`' || *dp == '\\') {
2497 			*op++ = '\\';
2498 			*op++ = *dp;
2499 			opleft -= 2;
2500 		} else {
2501 			*op++ = *dp;
2502 			opleft--;
2503 		}
2504 	}
2505 	if (opleft < 1)
2506 		goto toobig;
2507 	*op = 0;
2508 	return optbuf;
2509 toobig:
2510 	warning("dhcp option too large");
2511 	return "<error>";
2512 }
2513 
2514 int
2515 fork_privchld(int fd, int fd2)
2516 {
2517 	struct pollfd pfd[1];
2518 	int nfds;
2519 
2520 	switch (fork()) {
2521 	case -1:
2522 		error("cannot fork");
2523 	case 0:
2524 		break;
2525 	default:
2526 		return (0);
2527 	}
2528 
2529 	setproctitle("%s [priv]", ifi->name);
2530 
2531 	dup2(nullfd, STDIN_FILENO);
2532 	dup2(nullfd, STDOUT_FILENO);
2533 	dup2(nullfd, STDERR_FILENO);
2534 	close(nullfd);
2535 	close(fd2);
2536 
2537 	for (;;) {
2538 		pfd[0].fd = fd;
2539 		pfd[0].events = POLLIN;
2540 		if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2541 			if (errno != EINTR)
2542 				error("poll error");
2543 
2544 		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2545 			continue;
2546 
2547 		dispatch_imsg(fd);
2548 	}
2549 }
2550