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