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