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