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