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