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