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