dhclient.c revision 280250
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 280250 2015-03-19 12:32:48Z rwatson $");
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_FSTAT, CAP_FSYNC, CAP_FTRUNCATE,
1851		    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	} else {
1857		fflush(leaseFile);
1858		rewind(leaseFile);
1859	}
1860
1861	for (lp = ifi->client->leases; lp; lp = lp->next)
1862		write_client_lease(ifi, lp, 1);
1863	if (ifi->client->active)
1864		write_client_lease(ifi, ifi->client->active, 1);
1865
1866	fflush(leaseFile);
1867	ftruncate(fileno(leaseFile), ftello(leaseFile));
1868	fsync(fileno(leaseFile));
1869}
1870
1871void
1872write_client_lease(struct interface_info *ip, struct client_lease *lease,
1873    int rewrite)
1874{
1875	static int leases_written;
1876	struct tm *t;
1877	int i;
1878
1879	if (!rewrite) {
1880		if (leases_written++ > 20) {
1881			rewrite_client_leases();
1882			leases_written = 0;
1883		}
1884	}
1885
1886	/* If the lease came from the config file, we don't need to stash
1887	   a copy in the lease database. */
1888	if (lease->is_static)
1889		return;
1890
1891	if (!leaseFile) {	/* XXX */
1892		leaseFile = fopen(path_dhclient_db, "w");
1893		if (!leaseFile)
1894			error("can't create %s: %m", path_dhclient_db);
1895	}
1896
1897	fprintf(leaseFile, "lease {\n");
1898	if (lease->is_bootp)
1899		fprintf(leaseFile, "  bootp;\n");
1900	fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1901	fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1902	if (lease->nextserver.len == sizeof(inaddr_any) &&
1903	    0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1904	    sizeof(inaddr_any)))
1905		fprintf(leaseFile, "  next-server %s;\n",
1906		    piaddr(lease->nextserver));
1907	if (lease->filename)
1908		fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1909	if (lease->server_name)
1910		fprintf(leaseFile, "  server-name \"%s\";\n",
1911		    lease->server_name);
1912	if (lease->medium)
1913		fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1914	for (i = 0; i < 256; i++)
1915		if (lease->options[i].len)
1916			fprintf(leaseFile, "  option %s %s;\n",
1917			    dhcp_options[i].name,
1918			    pretty_print_option(i, lease->options[i].data,
1919			    lease->options[i].len, 1, 1));
1920
1921	t = gmtime(&lease->renewal);
1922	fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
1923	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1924	    t->tm_hour, t->tm_min, t->tm_sec);
1925	t = gmtime(&lease->rebind);
1926	fprintf(leaseFile, "  rebind %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->expiry);
1930	fprintf(leaseFile, "  expire %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	fprintf(leaseFile, "}\n");
1934	fflush(leaseFile);
1935}
1936
1937void
1938script_init(char *reason, struct string_list *medium)
1939{
1940	size_t		 len, mediumlen = 0;
1941	struct imsg_hdr	 hdr;
1942	struct buf	*buf;
1943	int		 errs;
1944
1945	if (medium != NULL && medium->string != NULL)
1946		mediumlen = strlen(medium->string);
1947
1948	hdr.code = IMSG_SCRIPT_INIT;
1949	hdr.len = sizeof(struct imsg_hdr) +
1950	    sizeof(size_t) + mediumlen +
1951	    sizeof(size_t) + strlen(reason);
1952
1953	if ((buf = buf_open(hdr.len)) == NULL)
1954		error("buf_open: %m");
1955
1956	errs = 0;
1957	errs += buf_add(buf, &hdr, sizeof(hdr));
1958	errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1959	if (mediumlen > 0)
1960		errs += buf_add(buf, medium->string, mediumlen);
1961	len = strlen(reason);
1962	errs += buf_add(buf, &len, sizeof(len));
1963	errs += buf_add(buf, reason, len);
1964
1965	if (errs)
1966		error("buf_add: %m");
1967
1968	if (buf_close(privfd, buf) == -1)
1969		error("buf_close: %m");
1970}
1971
1972void
1973priv_script_init(char *reason, char *medium)
1974{
1975	struct interface_info *ip = ifi;
1976
1977	if (ip) {
1978		ip->client->scriptEnvsize = 100;
1979		if (ip->client->scriptEnv == NULL)
1980			ip->client->scriptEnv =
1981			    malloc(ip->client->scriptEnvsize * sizeof(char *));
1982		if (ip->client->scriptEnv == NULL)
1983			error("script_init: no memory for environment");
1984
1985		ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
1986		if (ip->client->scriptEnv[0] == NULL)
1987			error("script_init: no memory for environment");
1988
1989		ip->client->scriptEnv[1] = NULL;
1990
1991		script_set_env(ip->client, "", "interface", ip->name);
1992
1993		if (medium)
1994			script_set_env(ip->client, "", "medium", medium);
1995
1996		script_set_env(ip->client, "", "reason", reason);
1997	}
1998}
1999
2000void
2001priv_script_write_params(char *prefix, struct client_lease *lease)
2002{
2003	struct interface_info *ip = ifi;
2004	u_int8_t dbuf[1500], *dp = NULL;
2005	int i, len;
2006	char tbuf[128];
2007
2008	script_set_env(ip->client, prefix, "ip_address",
2009	    piaddr(lease->address));
2010
2011	if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2012	    ACTION_SUPERSEDE) {
2013		dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2014		len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2015	} else {
2016		dp = lease->options[DHO_SUBNET_MASK].data;
2017		len = lease->options[DHO_SUBNET_MASK].len;
2018	}
2019	if (len && (len < sizeof(lease->address.iabuf))) {
2020		struct iaddr netmask, subnet, broadcast;
2021
2022		memcpy(netmask.iabuf, dp, len);
2023		netmask.len = len;
2024		subnet = subnet_number(lease->address, netmask);
2025		if (subnet.len) {
2026			script_set_env(ip->client, prefix, "network_number",
2027			    piaddr(subnet));
2028			if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2029				broadcast = broadcast_addr(subnet, netmask);
2030				if (broadcast.len)
2031					script_set_env(ip->client, prefix,
2032					    "broadcast_address",
2033					    piaddr(broadcast));
2034			}
2035		}
2036	}
2037
2038	if (lease->filename)
2039		script_set_env(ip->client, prefix, "filename", lease->filename);
2040	if (lease->server_name)
2041		script_set_env(ip->client, prefix, "server_name",
2042		    lease->server_name);
2043	for (i = 0; i < 256; i++) {
2044		len = 0;
2045
2046		if (ip->client->config->defaults[i].len) {
2047			if (lease->options[i].len) {
2048				switch (
2049				    ip->client->config->default_actions[i]) {
2050				case ACTION_DEFAULT:
2051					dp = lease->options[i].data;
2052					len = lease->options[i].len;
2053					break;
2054				case ACTION_SUPERSEDE:
2055supersede:
2056					dp = ip->client->
2057						config->defaults[i].data;
2058					len = ip->client->
2059						config->defaults[i].len;
2060					break;
2061				case ACTION_PREPEND:
2062					len = ip->client->
2063					    config->defaults[i].len +
2064					    lease->options[i].len;
2065					if (len >= sizeof(dbuf)) {
2066						warning("no space to %s %s",
2067						    "prepend option",
2068						    dhcp_options[i].name);
2069						goto supersede;
2070					}
2071					dp = dbuf;
2072					memcpy(dp,
2073						ip->client->
2074						config->defaults[i].data,
2075						ip->client->
2076						config->defaults[i].len);
2077					memcpy(dp + ip->client->
2078						config->defaults[i].len,
2079						lease->options[i].data,
2080						lease->options[i].len);
2081					dp[len] = '\0';
2082					break;
2083				case ACTION_APPEND:
2084					/*
2085					 * When we append, we assume that we're
2086					 * appending to text.  Some MS servers
2087					 * include a NUL byte at the end of
2088					 * the search string provided.
2089					 */
2090					len = ip->client->
2091					    config->defaults[i].len +
2092					    lease->options[i].len;
2093					if (len >= sizeof(dbuf)) {
2094						warning("no space to %s %s",
2095						    "append option",
2096						    dhcp_options[i].name);
2097						goto supersede;
2098					}
2099					memcpy(dbuf,
2100						lease->options[i].data,
2101						lease->options[i].len);
2102					for (dp = dbuf + lease->options[i].len;
2103					    dp > dbuf; dp--, len--)
2104						if (dp[-1] != '\0')
2105							break;
2106					memcpy(dp,
2107						ip->client->
2108						config->defaults[i].data,
2109						ip->client->
2110						config->defaults[i].len);
2111					dp = dbuf;
2112					dp[len] = '\0';
2113				}
2114			} else {
2115				dp = ip->client->
2116					config->defaults[i].data;
2117				len = ip->client->
2118					config->defaults[i].len;
2119			}
2120		} else if (lease->options[i].len) {
2121			len = lease->options[i].len;
2122			dp = lease->options[i].data;
2123		} else {
2124			len = 0;
2125		}
2126		if (len) {
2127			char name[256];
2128
2129			if (dhcp_option_ev_name(name, sizeof(name),
2130			    &dhcp_options[i]))
2131				script_set_env(ip->client, prefix, name,
2132				    pretty_print_option(i, dp, len, 0, 0));
2133		}
2134	}
2135	snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2136	script_set_env(ip->client, prefix, "expiry", tbuf);
2137}
2138
2139void
2140script_write_params(char *prefix, struct client_lease *lease)
2141{
2142	size_t		 fn_len = 0, sn_len = 0, pr_len = 0;
2143	struct imsg_hdr	 hdr;
2144	struct buf	*buf;
2145	int		 errs, i;
2146
2147	if (lease->filename != NULL)
2148		fn_len = strlen(lease->filename);
2149	if (lease->server_name != NULL)
2150		sn_len = strlen(lease->server_name);
2151	if (prefix != NULL)
2152		pr_len = strlen(prefix);
2153
2154	hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2155	hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2156	    sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2157	    sizeof(size_t) + pr_len;
2158
2159	for (i = 0; i < 256; i++)
2160		hdr.len += sizeof(int) + lease->options[i].len;
2161
2162	scripttime = time(NULL);
2163
2164	if ((buf = buf_open(hdr.len)) == NULL)
2165		error("buf_open: %m");
2166
2167	errs = 0;
2168	errs += buf_add(buf, &hdr, sizeof(hdr));
2169	errs += buf_add(buf, lease, sizeof(struct client_lease));
2170	errs += buf_add(buf, &fn_len, sizeof(fn_len));
2171	errs += buf_add(buf, lease->filename, fn_len);
2172	errs += buf_add(buf, &sn_len, sizeof(sn_len));
2173	errs += buf_add(buf, lease->server_name, sn_len);
2174	errs += buf_add(buf, &pr_len, sizeof(pr_len));
2175	errs += buf_add(buf, prefix, pr_len);
2176
2177	for (i = 0; i < 256; i++) {
2178		errs += buf_add(buf, &lease->options[i].len,
2179		    sizeof(lease->options[i].len));
2180		errs += buf_add(buf, lease->options[i].data,
2181		    lease->options[i].len);
2182	}
2183
2184	if (errs)
2185		error("buf_add: %m");
2186
2187	if (buf_close(privfd, buf) == -1)
2188		error("buf_close: %m");
2189}
2190
2191int
2192script_go(void)
2193{
2194	struct imsg_hdr	 hdr;
2195	struct buf	*buf;
2196	int		 ret;
2197
2198	hdr.code = IMSG_SCRIPT_GO;
2199	hdr.len = sizeof(struct imsg_hdr);
2200
2201	if ((buf = buf_open(hdr.len)) == NULL)
2202		error("buf_open: %m");
2203
2204	if (buf_add(buf, &hdr, sizeof(hdr)))
2205		error("buf_add: %m");
2206
2207	if (buf_close(privfd, buf) == -1)
2208		error("buf_close: %m");
2209
2210	bzero(&hdr, sizeof(hdr));
2211	buf_read(privfd, &hdr, sizeof(hdr));
2212	if (hdr.code != IMSG_SCRIPT_GO_RET)
2213		error("unexpected msg type %u", hdr.code);
2214	if (hdr.len != sizeof(hdr) + sizeof(int))
2215		error("received corrupted message");
2216	buf_read(privfd, &ret, sizeof(ret));
2217
2218	scripttime = time(NULL);
2219
2220	return (ret);
2221}
2222
2223int
2224priv_script_go(void)
2225{
2226	char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2227	static char client_path[] = CLIENT_PATH;
2228	struct interface_info *ip = ifi;
2229	int pid, wpid, wstatus;
2230
2231	scripttime = time(NULL);
2232
2233	if (ip) {
2234		scriptName = ip->client->config->script_name;
2235		envp = ip->client->scriptEnv;
2236	} else {
2237		scriptName = top_level_config.script_name;
2238		epp[0] = reason;
2239		epp[1] = client_path;
2240		epp[2] = NULL;
2241		envp = epp;
2242	}
2243
2244	argv[0] = scriptName;
2245	argv[1] = NULL;
2246
2247	pid = fork();
2248	if (pid < 0) {
2249		error("fork: %m");
2250		wstatus = 0;
2251	} else if (pid) {
2252		do {
2253			wpid = wait(&wstatus);
2254		} while (wpid != pid && wpid > 0);
2255		if (wpid < 0) {
2256			error("wait: %m");
2257			wstatus = 0;
2258		}
2259	} else {
2260		execve(scriptName, argv, envp);
2261		error("execve (%s, ...): %m", scriptName);
2262	}
2263
2264	if (ip)
2265		script_flush_env(ip->client);
2266
2267	return (wstatus & 0xff);
2268}
2269
2270void
2271script_set_env(struct client_state *client, const char *prefix,
2272    const char *name, const char *value)
2273{
2274	int i, j, namelen;
2275
2276	namelen = strlen(name);
2277
2278	for (i = 0; client->scriptEnv[i]; i++)
2279		if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2280		    client->scriptEnv[i][namelen] == '=')
2281			break;
2282
2283	if (client->scriptEnv[i])
2284		/* Reuse the slot. */
2285		free(client->scriptEnv[i]);
2286	else {
2287		/* New variable.  Expand if necessary. */
2288		if (i >= client->scriptEnvsize - 1) {
2289			char **newscriptEnv;
2290			int newscriptEnvsize = client->scriptEnvsize + 50;
2291
2292			newscriptEnv = realloc(client->scriptEnv,
2293			    newscriptEnvsize);
2294			if (newscriptEnv == NULL) {
2295				free(client->scriptEnv);
2296				client->scriptEnv = NULL;
2297				client->scriptEnvsize = 0;
2298				error("script_set_env: no memory for variable");
2299			}
2300			client->scriptEnv = newscriptEnv;
2301			client->scriptEnvsize = newscriptEnvsize;
2302		}
2303		/* need to set the NULL pointer at end of array beyond
2304		   the new slot. */
2305		client->scriptEnv[i + 1] = NULL;
2306	}
2307	/* Allocate space and format the variable in the appropriate slot. */
2308	client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2309	    strlen(value) + 1);
2310	if (client->scriptEnv[i] == NULL)
2311		error("script_set_env: no memory for variable assignment");
2312
2313	/* No `` or $() command substitution allowed in environment values! */
2314	for (j=0; j < strlen(value); j++)
2315		switch (value[j]) {
2316		case '`':
2317		case '$':
2318			error("illegal character (%c) in value '%s'", value[j],
2319			    value);
2320			/* not reached */
2321		}
2322	snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2323	    1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2324}
2325
2326void
2327script_flush_env(struct client_state *client)
2328{
2329	int i;
2330
2331	for (i = 0; client->scriptEnv[i]; i++) {
2332		free(client->scriptEnv[i]);
2333		client->scriptEnv[i] = NULL;
2334	}
2335	client->scriptEnvsize = 0;
2336}
2337
2338int
2339dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2340{
2341	int i;
2342
2343	for (i = 0; option->name[i]; i++) {
2344		if (i + 1 == buflen)
2345			return 0;
2346		if (option->name[i] == '-')
2347			buf[i] = '_';
2348		else
2349			buf[i] = option->name[i];
2350	}
2351
2352	buf[i] = 0;
2353	return 1;
2354}
2355
2356void
2357go_daemon(void)
2358{
2359	static int state = 0;
2360	cap_rights_t rights;
2361
2362	if (no_daemon || state)
2363		return;
2364
2365	state = 1;
2366
2367	/* Stop logging to stderr... */
2368	log_perror = 0;
2369
2370	if (daemon(1, 0) == -1)
2371		error("daemon");
2372
2373	cap_rights_init(&rights);
2374
2375	if (pidfile != NULL) {
2376		pidfile_write(pidfile);
2377		if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2378		    errno != ENOSYS) {
2379			error("can't limit pidfile descriptor: %m");
2380		}
2381	}
2382
2383	/* we are chrooted, daemon(3) fails to open /dev/null */
2384	if (nullfd != -1) {
2385		dup2(nullfd, STDIN_FILENO);
2386		dup2(nullfd, STDOUT_FILENO);
2387		dup2(nullfd, STDERR_FILENO);
2388		close(nullfd);
2389		nullfd = -1;
2390	}
2391
2392	if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2393		error("can't limit stdin: %m");
2394	cap_rights_init(&rights, CAP_WRITE);
2395	if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2396		error("can't limit stdout: %m");
2397	if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2398		error("can't limit stderr: %m");
2399}
2400
2401int
2402check_option(struct client_lease *l, int option)
2403{
2404	char *opbuf;
2405	char *sbuf;
2406
2407	/* we use this, since this is what gets passed to dhclient-script */
2408
2409	opbuf = pretty_print_option(option, l->options[option].data,
2410	    l->options[option].len, 0, 0);
2411
2412	sbuf = option_as_string(option, l->options[option].data,
2413	    l->options[option].len);
2414
2415	switch (option) {
2416	case DHO_SUBNET_MASK:
2417	case DHO_TIME_SERVERS:
2418	case DHO_NAME_SERVERS:
2419	case DHO_ROUTERS:
2420	case DHO_DOMAIN_NAME_SERVERS:
2421	case DHO_LOG_SERVERS:
2422	case DHO_COOKIE_SERVERS:
2423	case DHO_LPR_SERVERS:
2424	case DHO_IMPRESS_SERVERS:
2425	case DHO_RESOURCE_LOCATION_SERVERS:
2426	case DHO_SWAP_SERVER:
2427	case DHO_BROADCAST_ADDRESS:
2428	case DHO_NIS_SERVERS:
2429	case DHO_NTP_SERVERS:
2430	case DHO_NETBIOS_NAME_SERVERS:
2431	case DHO_NETBIOS_DD_SERVER:
2432	case DHO_FONT_SERVERS:
2433	case DHO_DHCP_SERVER_IDENTIFIER:
2434	case DHO_NISPLUS_SERVERS:
2435	case DHO_MOBILE_IP_HOME_AGENT:
2436	case DHO_SMTP_SERVER:
2437	case DHO_POP_SERVER:
2438	case DHO_NNTP_SERVER:
2439	case DHO_WWW_SERVER:
2440	case DHO_FINGER_SERVER:
2441	case DHO_IRC_SERVER:
2442	case DHO_STREETTALK_SERVER:
2443	case DHO_STREETTALK_DA_SERVER:
2444		if (!ipv4addrs(opbuf)) {
2445			warning("Invalid IP address in option: %s", opbuf);
2446			return (0);
2447		}
2448		return (1)  ;
2449	case DHO_HOST_NAME:
2450	case DHO_NIS_DOMAIN:
2451	case DHO_NISPLUS_DOMAIN:
2452	case DHO_TFTP_SERVER_NAME:
2453		if (!res_hnok(sbuf)) {
2454			warning("Bogus Host Name option %d: %s (%s)", option,
2455			    sbuf, opbuf);
2456			l->options[option].len = 0;
2457			free(l->options[option].data);
2458		}
2459		return (1);
2460	case DHO_DOMAIN_NAME:
2461	case DHO_DOMAIN_SEARCH:
2462		if (!res_hnok(sbuf)) {
2463			if (!check_search(sbuf)) {
2464				warning("Bogus domain search list %d: %s (%s)",
2465				    option, sbuf, opbuf);
2466				l->options[option].len = 0;
2467				free(l->options[option].data);
2468			}
2469		}
2470		return (1);
2471	case DHO_PAD:
2472	case DHO_TIME_OFFSET:
2473	case DHO_BOOT_SIZE:
2474	case DHO_MERIT_DUMP:
2475	case DHO_ROOT_PATH:
2476	case DHO_EXTENSIONS_PATH:
2477	case DHO_IP_FORWARDING:
2478	case DHO_NON_LOCAL_SOURCE_ROUTING:
2479	case DHO_POLICY_FILTER:
2480	case DHO_MAX_DGRAM_REASSEMBLY:
2481	case DHO_DEFAULT_IP_TTL:
2482	case DHO_PATH_MTU_AGING_TIMEOUT:
2483	case DHO_PATH_MTU_PLATEAU_TABLE:
2484	case DHO_INTERFACE_MTU:
2485	case DHO_ALL_SUBNETS_LOCAL:
2486	case DHO_PERFORM_MASK_DISCOVERY:
2487	case DHO_MASK_SUPPLIER:
2488	case DHO_ROUTER_DISCOVERY:
2489	case DHO_ROUTER_SOLICITATION_ADDRESS:
2490	case DHO_STATIC_ROUTES:
2491	case DHO_TRAILER_ENCAPSULATION:
2492	case DHO_ARP_CACHE_TIMEOUT:
2493	case DHO_IEEE802_3_ENCAPSULATION:
2494	case DHO_DEFAULT_TCP_TTL:
2495	case DHO_TCP_KEEPALIVE_INTERVAL:
2496	case DHO_TCP_KEEPALIVE_GARBAGE:
2497	case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2498	case DHO_NETBIOS_NODE_TYPE:
2499	case DHO_NETBIOS_SCOPE:
2500	case DHO_X_DISPLAY_MANAGER:
2501	case DHO_DHCP_REQUESTED_ADDRESS:
2502	case DHO_DHCP_LEASE_TIME:
2503	case DHO_DHCP_OPTION_OVERLOAD:
2504	case DHO_DHCP_MESSAGE_TYPE:
2505	case DHO_DHCP_PARAMETER_REQUEST_LIST:
2506	case DHO_DHCP_MESSAGE:
2507	case DHO_DHCP_MAX_MESSAGE_SIZE:
2508	case DHO_DHCP_RENEWAL_TIME:
2509	case DHO_DHCP_REBINDING_TIME:
2510	case DHO_DHCP_CLASS_IDENTIFIER:
2511	case DHO_DHCP_CLIENT_IDENTIFIER:
2512	case DHO_BOOTFILE_NAME:
2513	case DHO_DHCP_USER_CLASS_ID:
2514	case DHO_END:
2515		return (1);
2516	case DHO_CLASSLESS_ROUTES:
2517		return (check_classless_option(l->options[option].data,
2518		    l->options[option].len));
2519	default:
2520		warning("unknown dhcp option value 0x%x", option);
2521		return (unknown_ok);
2522	}
2523}
2524
2525/* RFC 3442 The Classless Static Routes option checks */
2526int
2527check_classless_option(unsigned char *data, int len)
2528{
2529	int i = 0;
2530	unsigned char width;
2531	in_addr_t addr, mask;
2532
2533	if (len < 5) {
2534		warning("Too small length: %d", len);
2535		return (0);
2536	}
2537	while(i < len) {
2538		width = data[i++];
2539		if (width == 0) {
2540			i += 4;
2541			continue;
2542		} else if (width < 9) {
2543			addr =  (in_addr_t)(data[i]	<< 24);
2544			i += 1;
2545		} else if (width < 17) {
2546			addr =  (in_addr_t)(data[i]	<< 24) +
2547				(in_addr_t)(data[i + 1]	<< 16);
2548			i += 2;
2549		} else if (width < 25) {
2550			addr =  (in_addr_t)(data[i]	<< 24) +
2551				(in_addr_t)(data[i + 1]	<< 16) +
2552				(in_addr_t)(data[i + 2]	<< 8);
2553			i += 3;
2554		} else if (width < 33) {
2555			addr =  (in_addr_t)(data[i]	<< 24) +
2556				(in_addr_t)(data[i + 1]	<< 16) +
2557				(in_addr_t)(data[i + 2]	<< 8)  +
2558				data[i + 3];
2559			i += 4;
2560		} else {
2561			warning("Incorrect subnet width: %d", width);
2562			return (0);
2563		}
2564		mask = (in_addr_t)(~0) << (32 - width);
2565		addr = ntohl(addr);
2566		mask = ntohl(mask);
2567
2568		/*
2569		 * From RFC 3442:
2570		 * ... After deriving a subnet number and subnet mask
2571		 * from each destination descriptor, the DHCP client
2572		 * MUST zero any bits in the subnet number where the
2573		 * corresponding bit in the mask is zero...
2574		 */
2575		if ((addr & mask) != addr) {
2576			addr &= mask;
2577			data[i - 1] = (unsigned char)(
2578				(addr >> (((32 - width)/8)*8)) & 0xFF);
2579		}
2580		i += 4;
2581	}
2582	if (i > len) {
2583		warning("Incorrect data length: %d (must be %d)", len, i);
2584		return (0);
2585	}
2586	return (1);
2587}
2588
2589int
2590res_hnok(const char *dn)
2591{
2592	int pch = PERIOD, ch = *dn++;
2593
2594	while (ch != '\0') {
2595		int nch = *dn++;
2596
2597		if (periodchar(ch)) {
2598			;
2599		} else if (periodchar(pch)) {
2600			if (!borderchar(ch))
2601				return (0);
2602		} else if (periodchar(nch) || nch == '\0') {
2603			if (!borderchar(ch))
2604				return (0);
2605		} else {
2606			if (!middlechar(ch))
2607				return (0);
2608		}
2609		pch = ch, ch = nch;
2610	}
2611	return (1);
2612}
2613
2614int
2615check_search(const char *srch)
2616{
2617        int pch = PERIOD, ch = *srch++;
2618	int domains = 1;
2619
2620	/* 256 char limit re resolv.conf(5) */
2621	if (strlen(srch) > 256)
2622		return (0);
2623
2624	while (whitechar(ch))
2625		ch = *srch++;
2626
2627        while (ch != '\0') {
2628                int nch = *srch++;
2629
2630                if (periodchar(ch) || whitechar(ch)) {
2631                        ;
2632                } else if (periodchar(pch)) {
2633                        if (!borderchar(ch))
2634                                return (0);
2635                } else if (periodchar(nch) || nch == '\0') {
2636                        if (!borderchar(ch))
2637                                return (0);
2638                } else {
2639                        if (!middlechar(ch))
2640                                return (0);
2641                }
2642		if (!whitechar(ch)) {
2643			pch = ch;
2644		} else {
2645			while (whitechar(nch)) {
2646				nch = *srch++;
2647			}
2648			if (nch != '\0')
2649				domains++;
2650			pch = PERIOD;
2651		}
2652		ch = nch;
2653        }
2654	/* 6 domain limit re resolv.conf(5) */
2655	if (domains > 6)
2656		return (0);
2657        return (1);
2658}
2659
2660/* Does buf consist only of dotted decimal ipv4 addrs?
2661 * return how many if so,
2662 * otherwise, return 0
2663 */
2664int
2665ipv4addrs(char * buf)
2666{
2667	struct in_addr jnk;
2668	int count = 0;
2669
2670	while (inet_aton(buf, &jnk) == 1){
2671		count++;
2672		while (periodchar(*buf) || digitchar(*buf))
2673			buf++;
2674		if (*buf == '\0')
2675			return (count);
2676		while (*buf ==  ' ')
2677			buf++;
2678	}
2679	return (0);
2680}
2681
2682
2683char *
2684option_as_string(unsigned int code, unsigned char *data, int len)
2685{
2686	static char optbuf[32768]; /* XXX */
2687	char *op = optbuf;
2688	int opleft = sizeof(optbuf);
2689	unsigned char *dp = data;
2690
2691	if (code > 255)
2692		error("option_as_string: bad code %d", code);
2693
2694	for (; dp < data + len; dp++) {
2695		if (!isascii(*dp) || !isprint(*dp)) {
2696			if (dp + 1 != data + len || *dp != 0) {
2697				snprintf(op, opleft, "\\%03o", *dp);
2698				op += 4;
2699				opleft -= 4;
2700			}
2701		} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2702		    *dp == '`' || *dp == '\\') {
2703			*op++ = '\\';
2704			*op++ = *dp;
2705			opleft -= 2;
2706		} else {
2707			*op++ = *dp;
2708			opleft--;
2709		}
2710	}
2711	if (opleft < 1)
2712		goto toobig;
2713	*op = 0;
2714	return optbuf;
2715toobig:
2716	warning("dhcp option too large");
2717	return "<error>";
2718}
2719
2720int
2721fork_privchld(int fd, int fd2)
2722{
2723	struct pollfd pfd[1];
2724	int nfds;
2725
2726	switch (fork()) {
2727	case -1:
2728		error("cannot fork");
2729	case 0:
2730		break;
2731	default:
2732		return (0);
2733	}
2734
2735	setproctitle("%s [priv]", ifi->name);
2736
2737	setsid();
2738	dup2(nullfd, STDIN_FILENO);
2739	dup2(nullfd, STDOUT_FILENO);
2740	dup2(nullfd, STDERR_FILENO);
2741	close(nullfd);
2742	close(fd2);
2743	close(ifi->rfdesc);
2744	ifi->rfdesc = -1;
2745
2746	for (;;) {
2747		pfd[0].fd = fd;
2748		pfd[0].events = POLLIN;
2749		if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2750			if (errno != EINTR)
2751				error("poll error");
2752
2753		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2754			continue;
2755
2756		dispatch_imsg(ifi, fd);
2757	}
2758}
2759