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