xref: /dragonfly/sbin/dhclient/dhclient.c (revision d2cd83ff)
1 /*	$OpenBSD: dhclient.c,v 1.118 2008/05/09 05:19:14 reyk Exp $	*/
2 /*	$DragonFly: src/sbin/dhclient/dhclient.c,v 1.2 2008/09/10 10:01:18 matthias Exp $	*/
3 
4 /*
5  * Copyright 2004 Henning Brauer <henning@openbsd.org>
6  * Copyright (c) 1995, 1996, 1997, 1998, 1999
7  * The Internet Software Consortium.    All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of The Internet Software Consortium nor the names
19  *    of its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * This software has been written for the Internet Software Consortium
37  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38  * Enterprises.  To learn more about the Internet Software Consortium,
39  * see ``http://www.vix.com/isc''.  To learn more about Vixie
40  * Enterprises, see ``http://www.vix.com''.
41  *
42  * This client was substantially modified and enhanced by Elliot Poger
43  * for use on Linux while he was working on the MosquitoNet project at
44  * Stanford.
45  *
46  * The current version owes much to Elliot's Linux enhancements, but
47  * was substantially reorganized and partially rewritten by Ted Lemon
48  * so as to use the same networking framework that the Internet Software
49  * Consortium DHCP server uses.   Much system-specific configuration code
50  * was moved into a shell script so that as support for more operating
51  * systems is added, it will not be necessary to port and maintain
52  * system-specific configuration code to these operating systems - instead,
53  * the shell script can invoke the native tools to accomplish the same
54  * purpose.
55  */
56 
57 #include <ctype.h>
58 #include <poll.h>
59 #include <pwd.h>
60 
61 #include "dhcpd.h"
62 #include "privsep.h"
63 
64 #define	CLIENT_PATH 		"PATH=/usr/bin:/usr/sbin:/bin:/sbin"
65 #define DEFAULT_LEASE_TIME	43200	/* 12 hours... */
66 #define TIME_MAX		2147483647
67 
68 time_t cur_time;
69 
70 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
71 char *path_dhclient_db = NULL;
72 
73 int log_perror = 1;
74 int privfd;
75 int nullfd = -1;
76 int no_daemon;
77 int unknown_ok = 1;
78 int routefd = -1;
79 
80 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
81 struct in_addr inaddr_any;
82 struct sockaddr_in sockaddr_broadcast;
83 
84 struct interface_info *ifi;
85 struct client_state *client;
86 struct client_config *config;
87 
88 int		 findproto(char *, int);
89 struct sockaddr	*get_ifa(char *, int);
90 void		 usage(void);
91 int		 check_option(struct client_lease *l, int option);
92 int		 ipv4addrs(char * buf);
93 int		 res_hnok(const char *dn);
94 char		*option_as_string(unsigned int code, unsigned char *data, int len);
95 int		 fork_privchld(int, int);
96 
97 #define	ROUNDUP(a) \
98 	    ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
99 #define	ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
100 
101 time_t	scripttime;
102 static FILE *leaseFile;
103 
104 int
105 findproto(char *cp, int n)
106 {
107 	struct sockaddr *sa;
108 	int i;
109 
110 	if (n == 0)
111 		return -1;
112 	for (i = 1; i; i <<= 1) {
113 		if (i & n) {
114 			sa = (struct sockaddr *)cp;
115 			switch (i) {
116 			case RTA_IFA:
117 			case RTA_DST:
118 			case RTA_GATEWAY:
119 			case RTA_NETMASK:
120 				if (sa->sa_family == AF_INET)
121 					return AF_INET;
122 				if (sa->sa_family == AF_INET6)
123 					return AF_INET6;
124 				break;
125 			case RTA_IFP:
126 				break;
127 			}
128 			ADVANCE(cp, sa);
129 		}
130 	}
131 	return (-1);
132 }
133 
134 struct sockaddr *
135 get_ifa(char *cp, int n)
136 {
137 	struct sockaddr *sa;
138 	int i;
139 
140 	if (n == 0)
141 		return (NULL);
142 	for (i = 1; i; i <<= 1)
143 		if (i & n) {
144 			sa = (struct sockaddr *)cp;
145 			if (i == RTA_IFA)
146 				return (sa);
147 			ADVANCE(cp, sa);
148 		}
149 
150 	return (NULL);
151 }
152 struct iaddr defaddr = { .len = 4 }; /* NULL is for silence warnings */
153 
154 /* ARGSUSED */
155 void
156 routehandler(void)
157 {
158 	int linkstat;
159 	char msg[2048];
160 	struct rt_msghdr *rtm;
161 	struct if_msghdr *ifm;
162 	struct ifa_msghdr *ifam;
163 	struct if_announcemsghdr *ifan;
164 	struct client_lease *l;
165 	time_t t = time(NULL);
166 	struct sockaddr *sa;
167 	struct iaddr a;
168 	ssize_t n;
169 
170 	do {
171 		n = read(routefd, &msg, sizeof(msg));
172 	} while (n == -1 && errno == EINTR);
173 
174 	rtm = (struct rt_msghdr *)msg;
175 	if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
176 	    rtm->rtm_version != RTM_VERSION)
177 		return;
178 
179 	switch (rtm->rtm_type) {
180 	case RTM_NEWADDR:
181 		ifam = (struct ifa_msghdr *)rtm;
182 		if (ifam->ifam_index != ifi->index)
183 			break;
184 		if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
185 			break;
186 		sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
187 		if (sa == NULL)
188 			goto die;
189 
190 		if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
191 			error("king bula sez: len mismatch");
192 		memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
193 		if (addr_eq(a, defaddr))
194 			break;
195 
196 		for (l = client->active; l != NULL; l = l->next)
197 			if (addr_eq(a, l->address))
198 				break;
199 
200 		if (l != NULL || (client->alias &&
201 		    addr_eq(a, client->alias->address)))
202 			/* new addr is the one we set */
203 			break;
204 
205 		goto die;
206 	case RTM_DELADDR:
207 		ifam = (struct ifa_msghdr *)rtm;
208 		if (ifam->ifam_index != ifi->index)
209 			break;
210 		if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
211 			break;
212 		if (scripttime == 0 || t < scripttime + 10)
213 			break;
214 		goto die;
215 	case RTM_IFINFO:
216 		ifm = (struct if_msghdr *)rtm;
217 		if (ifm->ifm_index != ifi->index)
218 			break;
219 		if ((rtm->rtm_flags & RTF_UP) == 0)
220 			goto die;
221 
222 		linkstat =
223 		    LINK_STATE_IS_UP(ifm->ifm_data.ifi_link_state) ? 1 : 0;
224 		if (linkstat != ifi->linkstat) {
225 			debug("link state %s -> %s",
226 			    ifi->linkstat ? "up" : "down",
227 			    linkstat ? "up" : "down");
228 			ifi->linkstat = interface_link_status(ifi->name);
229 			if (ifi->linkstat) {
230 				client->state = S_INIT;
231 				state_reboot();
232 			}
233 		}
234 		break;
235 	case RTM_IFANNOUNCE:
236 		ifan = (struct if_announcemsghdr *)rtm;
237 		if (ifan->ifan_what == IFAN_DEPARTURE &&
238 		    ifan->ifan_index == ifi->index)
239 			goto die;
240 		break;
241 	default:
242 		break;
243 	}
244 	return;
245 
246 die:
247 	script_init("FAIL", NULL);
248 	if (client->alias)
249 		script_write_params("alias_", client->alias);
250 	script_go();
251 	exit(1);
252 }
253 
254 int
255 main(int argc, char *argv[])
256 {
257 	int	 ch, fd, quiet = 0, i = 0, pipe_fd[2];
258 	struct passwd *pw;
259 
260 	/* Initially, log errors to stderr as well as to syslogd. */
261 	openlog(getprogname(), LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
262 	setlogmask(LOG_UPTO(LOG_INFO));
263 
264 	while ((ch = getopt(argc, argv, "c:dl:qu")) != -1)
265 		switch (ch) {
266 		case 'c':
267 			path_dhclient_conf = optarg;
268 			break;
269 		case 'd':
270 			no_daemon = 1;
271 			break;
272 		case 'l':
273 			path_dhclient_db = optarg;
274 			break;
275 		case 'q':
276 			quiet = 1;
277 			break;
278 		case 'u':
279 			unknown_ok = 0;
280 			break;
281 		default:
282 			usage();
283 		}
284 
285 	argc -= optind;
286 	argv += optind;
287 
288 	if (argc != 1)
289 		usage();
290 
291 	ifi = calloc(1, sizeof(*ifi));
292 	if (ifi == NULL)
293 		error("ifi calloc");
294 	client = calloc(1, sizeof(*client));
295 	if (client == NULL)
296 		error("client calloc");
297 	config = calloc(1, sizeof(*config));
298 	if (config == NULL)
299 		error("config calloc");
300 
301 	if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
302 		error("Interface name too long");
303 	if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
304 	    _PATH_DHCLIENT_DB, ifi->name) == -1)
305 		error("asprintf");
306 
307 	if (quiet)
308 		log_perror = 0;
309 
310 	tzset();
311 	time(&cur_time);
312 
313 	memset(&sockaddr_broadcast, 0, sizeof(sockaddr_broadcast));
314 	sockaddr_broadcast.sin_family = AF_INET;
315 	sockaddr_broadcast.sin_port = htons(REMOTE_PORT);
316 	sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
317 	sockaddr_broadcast.sin_len = sizeof(sockaddr_broadcast);
318 	inaddr_any.s_addr = INADDR_ANY;
319 
320 	read_client_conf();
321 
322 	if (interface_status(ifi->name) == 0) {
323 		interface_link_forceup(ifi->name);
324 		/* Give it up to 4 seconds of silent grace to find link */
325 		i = -4;
326 	} else
327 		i = 0;
328 
329 	while (!(ifi->linkstat = interface_link_status(ifi->name))) {
330 		if (i == 0)
331 			fprintf(stderr, "%s: no link ...", ifi->name);
332 		else if (i > 0)
333 			fprintf(stderr, ".");
334 		fflush(stderr);
335 		if (++i > config->link_timeout) {
336 			fprintf(stderr, " sleeping\n");
337 			goto dispatch;
338 		}
339 		sleep(1);
340 	}
341 	if (i >= 0)
342 		fprintf(stderr, " got link\n");
343 
344  dispatch:
345 	if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
346 		error("cannot open %s: %m", _PATH_DEVNULL);
347 
348 	if ((pw = getpwnam("_dhcp")) == NULL) {
349 		warning("no such user: _dhcp, falling back to \"nobody\"");
350 		if ((pw = getpwnam("nobody")) == NULL)
351 			error("no such user: nobody");
352 	}
353 
354 	if (pipe(pipe_fd) == -1)
355 		error("pipe");
356 
357 	fork_privchld(pipe_fd[0], pipe_fd[1]);
358 
359 	close(pipe_fd[0]);
360 	privfd = pipe_fd[1];
361 
362 	if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
363 		error("can't open and lock %s: %m", path_dhclient_db);
364 	read_client_leases();
365 	if ((leaseFile = fopen(path_dhclient_db, "w")) == NULL)
366 		error("can't open %s: %m", path_dhclient_db);
367 	rewrite_client_leases();
368 	close(fd);
369 
370 	priv_script_init("PREINIT", NULL);
371 	if (client->alias)
372 		priv_script_write_params("alias_", client->alias);
373 	priv_script_go();
374 
375 	if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
376 		error("socket(PF_ROUTE, SOCK_RAW): %m");
377 
378 	/* set up the interface */
379 	discover_interface();
380 
381 	if (chroot(_PATH_VAREMPTY) == -1)
382 		error("chroot");
383 	if (chdir("/") == -1)
384 		error("chdir(\"/\")");
385 
386 	if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
387 		error("setresgid");
388 	if (setgroups(1, &pw->pw_gid) == -1)
389 		error("setgroups");
390 	if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
391 		error("setresuid");
392 
393 	endpwent();
394 
395 	setproctitle("%s", ifi->name);
396 
397 	if (ifi->linkstat) {
398 		client->state = S_INIT;
399 		state_reboot();
400 	} else
401 		go_daemon();
402 
403 	dispatch();
404 
405 	/* not reached */
406 	return (0);
407 }
408 
409 void
410 usage(void)
411 {
412 	fprintf(stderr, "usage: %s [-dqu] [-c file] [-l file] interface\n",
413 	    getprogname());
414 	exit(1);
415 }
416 
417 /*
418  * Individual States:
419  *
420  * Each routine is called from the dhclient_state_machine() in one of
421  * these conditions:
422  * -> entering INIT state
423  * -> recvpacket_flag == 0: timeout in this state
424  * -> otherwise: received a packet in this state
425  *
426  * Return conditions as handled by dhclient_state_machine():
427  * Returns 1, sendpacket_flag = 1: send packet, reset timer.
428  * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
429  * Returns 0: finish the nap which was interrupted for no good reason.
430  *
431  * Several per-interface variables are used to keep track of the process:
432  *   active_lease: the lease that is being used on the interface
433  *                 (null pointer if not configured yet).
434  *   offered_leases: leases corresponding to DHCPOFFER messages that have
435  *                   been sent to us by DHCP servers.
436  *   acked_leases: leases corresponding to DHCPACK messages that have been
437  *                 sent to us by DHCP servers.
438  *   sendpacket: DHCP packet we're trying to send.
439  *   destination: IP address to send sendpacket to
440  * In addition, there are several relevant per-lease variables.
441  *   T1_expiry, T2_expiry, lease_expiry: lease milestones
442  * In the active lease, these control the process of renewing the lease;
443  * In leases on the acked_leases list, this simply determines when we
444  * can no longer legitimately use the lease.
445  */
446 void
447 state_reboot(void)
448 {
449 	/* If we don't remember an active lease, go straight to INIT. */
450 	if (!client->active || client->active->is_bootp) {
451 		state_init();
452 		return;
453 	}
454 
455 	/* We are in the rebooting state. */
456 	client->state = S_REBOOTING;
457 
458 	/* make_request doesn't initialize xid because it normally comes
459 	   from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
460 	   so pick an xid now. */
461 	client->xid = arc4random();
462 
463 	/* Make a DHCPREQUEST packet, and set appropriate per-interface
464 	   flags. */
465 	make_request(client->active);
466 	client->destination = iaddr_broadcast;
467 	client->first_sending = cur_time;
468 	client->interval = config->initial_interval;
469 
470 	/* Zap the medium list... */
471 	client->medium = NULL;
472 
473 	/* Send out the first DHCPREQUEST packet. */
474 	send_request();
475 }
476 
477 /*
478  * Called when a lease has completely expired and we've
479  * been unable to renew it.
480  */
481 void
482 state_init(void)
483 {
484 	/* Make a DHCPDISCOVER packet, and set appropriate per-interface
485 	   flags. */
486 	make_discover(client->active);
487 	client->xid = client->packet.xid;
488 	client->destination = iaddr_broadcast;
489 	client->state = S_SELECTING;
490 	client->first_sending = cur_time;
491 	client->interval = config->initial_interval;
492 
493 	/* Add an immediate timeout to cause the first DHCPDISCOVER packet
494 	   to go out. */
495 	send_discover();
496 }
497 
498 /*
499  * state_selecting is called when one or more DHCPOFFER packets
500  * have been received and a configurable period of time has passed.
501  */
502 void
503 state_selecting(void)
504 {
505 	struct client_lease *lp, *next, *picked;
506 
507 	/* Cancel state_selecting and send_discover timeouts, since either
508 	   one could have got us here. */
509 	cancel_timeout(state_selecting);
510 	cancel_timeout(send_discover);
511 
512 	/* We have received one or more DHCPOFFER packets.   Currently,
513 	   the only criterion by which we judge leases is whether or
514 	   not we get a response when we arp for them. */
515 	picked = NULL;
516 	for (lp = client->offered_leases; lp; lp = next) {
517 		next = lp->next;
518 
519 		/* Check to see if we got an ARPREPLY for the address
520 		   in this particular lease. */
521 		if (!picked) {
522 			script_init("ARPCHECK", lp->medium);
523 			script_write_params("check_", lp);
524 
525 			/* If the ARPCHECK code detects another
526 			   machine using the offered address, it exits
527 			   nonzero.  We need to send a DHCPDECLINE and
528 			   toss the lease. */
529 			if (script_go()) {
530 				make_decline(lp);
531 				send_decline();
532 				goto freeit;
533 			}
534 			picked = lp;
535 			picked->next = NULL;
536 		} else {
537 freeit:
538 			free_client_lease(lp);
539 		}
540 	}
541 	client->offered_leases = NULL;
542 
543 	/* If we just tossed all the leases we were offered, go back
544 	   to square one. */
545 	if (!picked) {
546 		client->state = S_INIT;
547 		state_init();
548 		return;
549 	}
550 
551 	/* If it was a BOOTREPLY, we can just take the address right now. */
552 	if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
553 		client->new = picked;
554 
555 		/* Make up some lease expiry times
556 		   XXX these should be configurable. */
557 		client->new->expiry = cur_time + 12000;
558 		client->new->renewal += cur_time + 8000;
559 		client->new->rebind += cur_time + 10000;
560 
561 		client->state = S_REQUESTING;
562 
563 		/* Bind to the address we received. */
564 		bind_lease();
565 		return;
566 	}
567 
568 	/* Go to the REQUESTING state. */
569 	client->destination = iaddr_broadcast;
570 	client->state = S_REQUESTING;
571 	client->first_sending = cur_time;
572 	client->interval = config->initial_interval;
573 
574 	/* Make a DHCPREQUEST packet from the lease we picked. */
575 	make_request(picked);
576 	client->xid = client->packet.xid;
577 
578 	/* Toss the lease we picked - we'll get it back in a DHCPACK. */
579 	free_client_lease(picked);
580 
581 	/* Add an immediate timeout to send the first DHCPREQUEST packet. */
582 	send_request();
583 }
584 
585 void
586 dhcpack(struct iaddr client_addr, struct option_data *options)
587 {
588 	struct client_lease *lease;
589 
590 	if (client->xid != client->packet.xid)
591 		return;
592 
593 	if (client->state != S_REBOOTING &&
594 	    client->state != S_REQUESTING &&
595 	    client->state != S_RENEWING &&
596 	    client->state != S_REBINDING)
597 		return;
598 
599 	note("DHCPACK from %s", piaddr(client_addr));
600 
601 	lease = packet_to_lease(options);
602 	if (!lease) {
603 		note("packet_to_lease failed.");
604 		return;
605 	}
606 
607 	client->new = lease;
608 
609 	/* Stop resending DHCPREQUEST. */
610 	cancel_timeout(send_request);
611 
612 	/* Figure out the lease time. */
613 	if (client->new->options[DHO_DHCP_LEASE_TIME].data)
614 		client->new->expiry =
615 		    getULong(client->new->options[DHO_DHCP_LEASE_TIME].data);
616 	else
617 		client->new->expiry = DEFAULT_LEASE_TIME;
618 	/* A number that looks negative here is really just very large,
619 	   because the lease expiry offset is unsigned. */
620 	if (client->new->expiry < 0)
621 		client->new->expiry = TIME_MAX;
622 	/* XXX should be fixed by resetting the client state */
623 	if (client->new->expiry < 60)
624 		client->new->expiry = 60;
625 
626 	/* Take the server-provided renewal time if there is one;
627 	   otherwise figure it out according to the spec. */
628 	if (client->new->options[DHO_DHCP_RENEWAL_TIME].len)
629 		client->new->renewal =
630 		    getULong(client->new->options[DHO_DHCP_RENEWAL_TIME].data);
631 	else
632 		client->new->renewal = client->new->expiry / 2;
633 
634 	/* Same deal with the rebind time. */
635 	if (client->new->options[DHO_DHCP_REBINDING_TIME].len)
636 		client->new->rebind =
637 		    getULong(client->new->options[DHO_DHCP_REBINDING_TIME].data);
638 	else
639 		client->new->rebind = client->new->renewal +
640 		    client->new->renewal / 2 + client->new->renewal / 4;
641 
642 	client->new->expiry += cur_time;
643 	/* Lease lengths can never be negative. */
644 	if (client->new->expiry < cur_time)
645 		client->new->expiry = TIME_MAX;
646 	client->new->renewal += cur_time;
647 	if (client->new->renewal < cur_time)
648 		client->new->renewal = TIME_MAX;
649 	client->new->rebind += cur_time;
650 	if (client->new->rebind < cur_time)
651 		client->new->rebind = TIME_MAX;
652 
653 	bind_lease();
654 }
655 
656 void
657 bind_lease(void)
658 {
659 	/* Remember the medium. */
660 	client->new->medium = client->medium;
661 
662 	/* Write out the new lease. */
663 	write_client_lease(client->new, 0);
664 
665 	/* Run the client script with the new parameters. */
666 	script_init((client->state == S_REQUESTING ? "BOUND" :
667 	    (client->state == S_RENEWING ? "RENEW" :
668 	    (client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
669 	    client->new->medium);
670 	if (client->active && client->state != S_REBOOTING)
671 		script_write_params("old_", client->active);
672 	script_write_params("new_", client->new);
673 	if (client->alias)
674 		script_write_params("alias_", client->alias);
675 	script_go();
676 
677 	/* Replace the old active lease with the new one. */
678 	if (client->active)
679 		free_client_lease(client->active);
680 	client->active = client->new;
681 	client->new = NULL;
682 
683 	/* Set up a timeout to start the renewal process. */
684 	add_timeout(client->active->renewal, state_bound);
685 
686 	note("bound to %s -- renewal in %ld seconds.",
687 	    piaddr(client->active->address),
688 	    client->active->renewal - cur_time);
689 	client->state = S_BOUND;
690 	reinitialize_interface();
691 	go_daemon();
692 }
693 
694 /*
695  * state_bound is called when we've successfully bound to a particular
696  * lease, but the renewal time on that lease has expired.   We are
697  * expected to unicast a DHCPREQUEST to the server that gave us our
698  * original lease.
699  */
700 void
701 state_bound(void)
702 {
703 	/* T1 has expired. */
704 	make_request(client->active);
705 	client->xid = client->packet.xid;
706 
707 	if (client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
708 		memcpy(client->destination.iabuf,
709 		    client->active->options[DHO_DHCP_SERVER_IDENTIFIER].data,
710 		    4);
711 		client->destination.len = 4;
712 	} else
713 		client->destination = iaddr_broadcast;
714 
715 	client->first_sending = cur_time;
716 	client->interval = config->initial_interval;
717 	client->state = S_RENEWING;
718 
719 	/* Send the first packet immediately. */
720 	send_request();
721 }
722 
723 void
724 dhcpoffer(struct iaddr client_addr, struct option_data *options)
725 {
726 	struct client_lease *lease, *lp;
727 	int i;
728 	int arp_timeout_needed, stop_selecting;
729 	char *name = options[DHO_DHCP_MESSAGE_TYPE].len ? "DHCPOFFER" :
730 	    "BOOTREPLY";
731 
732 	if (client->xid != client->packet.xid)
733 		return;
734 
735 	if (client->state != S_SELECTING)
736 		return;
737 
738 	note("%s from %s", name, piaddr(client_addr));
739 
740 	/* If this lease doesn't supply the minimum required parameters,
741 	   blow it off. */
742 	for (i = 0; config->required_options[i]; i++) {
743 		if (!options[config->required_options[i]].len) {
744 			note("%s isn't satisfactory.", name);
745 			return;
746 		}
747 	}
748 
749 	/* If we've already seen this lease, don't record it again. */
750 	for (lease = client->offered_leases;
751 	    lease; lease = lease->next) {
752 		if (lease->address.len == sizeof(client->packet.yiaddr) &&
753 		    !memcmp(lease->address.iabuf,
754 		    &client->packet.yiaddr, lease->address.len)) {
755 			debug("%s already seen.", name);
756 			return;
757 		}
758 	}
759 
760 	lease = packet_to_lease(options);
761 	if (!lease) {
762 		note("packet_to_lease failed.");
763 		return;
764 	}
765 
766 	/* If this lease was acquired through a BOOTREPLY, record that
767 	   fact. */
768 	if (!options[DHO_DHCP_MESSAGE_TYPE].len)
769 		lease->is_bootp = 1;
770 
771 	/* Record the medium under which this lease was offered. */
772 	lease->medium = client->medium;
773 
774 	/* Send out an ARP Request for the offered IP address. */
775 	script_init("ARPSEND", lease->medium);
776 	script_write_params("check_", lease);
777 	/* If the script can't send an ARP request without waiting,
778 	   we'll be waiting when we do the ARPCHECK, so don't wait now. */
779 	if (script_go())
780 		arp_timeout_needed = 0;
781 	else
782 		arp_timeout_needed = 2;
783 
784 	/* Figure out when we're supposed to stop selecting. */
785 	stop_selecting = client->first_sending + config->select_interval;
786 
787 	/* If this is the lease we asked for, put it at the head of the
788 	   list, and don't mess with the arp request timeout. */
789 	if (lease->address.len == client->requested_address.len &&
790 	    !memcmp(lease->address.iabuf,
791 	    client->requested_address.iabuf,
792 	    client->requested_address.len)) {
793 		lease->next = client->offered_leases;
794 		client->offered_leases = lease;
795 	} else {
796 		/* If we already have an offer, and arping for this
797 		   offer would take us past the selection timeout,
798 		   then don't extend the timeout - just hope for the
799 		   best. */
800 		if (client->offered_leases &&
801 		    (cur_time + arp_timeout_needed) > stop_selecting)
802 			arp_timeout_needed = 0;
803 
804 		/* Put the lease at the end of the list. */
805 		lease->next = NULL;
806 		if (!client->offered_leases)
807 			client->offered_leases = lease;
808 		else {
809 			for (lp = client->offered_leases; lp->next;
810 			    lp = lp->next)
811 				;	/* nothing */
812 			lp->next = lease;
813 		}
814 	}
815 
816 	/* If we're supposed to stop selecting before we've had time
817 	   to wait for the ARPREPLY, add some delay to wait for
818 	   the ARPREPLY. */
819 	if (stop_selecting - cur_time < arp_timeout_needed)
820 		stop_selecting = cur_time + arp_timeout_needed;
821 
822 	/* If the selecting interval has expired, go immediately to
823 	   state_selecting().  Otherwise, time out into
824 	   state_selecting at the select interval. */
825 	if (stop_selecting <= 0)
826 		state_selecting();
827 	else {
828 		add_timeout(stop_selecting, state_selecting);
829 		cancel_timeout(send_discover);
830 	}
831 }
832 
833 /*
834  * Allocate a client_lease structure and initialize it from the
835  * parameters in the specified packet.
836  */
837 struct client_lease *
838 packet_to_lease(struct option_data *options)
839 {
840 	struct client_lease *lease;
841 	int i;
842 
843 	lease = malloc(sizeof(struct client_lease));
844 
845 	if (!lease) {
846 		warning("dhcpoffer: no memory to record lease.");
847 		return (NULL);
848 	}
849 
850 	memset(lease, 0, sizeof(*lease));
851 
852 	/* Copy the lease options. */
853 	for (i = 0; i < 256; i++) {
854 		if (options[i].len) {
855 			lease->options[i] = options[i];
856 			options[i].data = NULL;
857 			options[i].len = 0;
858 			if (!check_option(lease, i)) {
859 				warning("Invalid lease option - ignoring offer");
860 				free_client_lease(lease);
861 				return (NULL);
862 			}
863 		}
864 	}
865 
866 	lease->address.len = sizeof(client->packet.yiaddr);
867 	memcpy(lease->address.iabuf, &client->packet.yiaddr,
868 	    lease->address.len);
869 
870 	/* If the server name was filled out, copy it. */
871 	if ((!lease->options[DHO_DHCP_OPTION_OVERLOAD].len ||
872 	    !(lease->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
873 	    client->packet.sname[0]) {
874 		lease->server_name = malloc(DHCP_SNAME_LEN + 1);
875 		if (!lease->server_name) {
876 			warning("dhcpoffer: no memory for server name.");
877 			free_client_lease(lease);
878 			return (NULL);
879 		}
880 		memcpy(lease->server_name, client->packet.sname,
881 		    DHCP_SNAME_LEN);
882 		lease->server_name[DHCP_SNAME_LEN] = '\0';
883 		if (!res_hnok(lease->server_name)) {
884 			warning("Bogus server name %s", lease->server_name);
885 			free(lease->server_name);
886 			lease->server_name = NULL;
887 		}
888 	}
889 
890 	/* Ditto for the filename. */
891 	if ((!lease->options[DHO_DHCP_OPTION_OVERLOAD].len ||
892 	    !(lease->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
893 	    client->packet.file[0]) {
894 		/* Don't count on the NUL terminator. */
895 		lease->filename = malloc(DHCP_FILE_LEN + 1);
896 		if (!lease->filename) {
897 			warning("dhcpoffer: no memory for filename.");
898 			free_client_lease(lease);
899 			return (NULL);
900 		}
901 		memcpy(lease->filename, client->packet.file, DHCP_FILE_LEN);
902 		lease->filename[DHCP_FILE_LEN] = '\0';
903 	}
904 	return lease;
905 }
906 
907 void
908 dhcpnak(struct iaddr client_addr, struct option_data *options)
909 {
910 	if (client->xid != client->packet.xid)
911 		return;
912 
913 	if (client->state != S_REBOOTING &&
914 	    client->state != S_REQUESTING &&
915 	    client->state != S_RENEWING &&
916 	    client->state != S_REBINDING)
917 		return;
918 
919 	note("DHCPNAK from %s", piaddr(client_addr));
920 
921 	if (!client->active) {
922 		note("DHCPNAK with no active lease.");
923 		return;
924 	}
925 
926 	free_client_lease(client->active);
927 	client->active = NULL;
928 
929 	/* Stop sending DHCPREQUEST packets... */
930 	cancel_timeout(send_request);
931 
932 	client->state = S_INIT;
933 	state_init();
934 }
935 
936 /*
937  * Send out a DHCPDISCOVER packet, and set a timeout to send out another
938  * one after the right interval has expired.  If we don't get an offer by
939  * the time we reach the panic interval, call the panic function.
940  */
941 void
942 send_discover(void)
943 {
944 	int interval, increase = 1;
945 
946 	/* Figure out how long it's been since we started transmitting. */
947 	interval = cur_time - client->first_sending;
948 
949 	/* If we're past the panic timeout, call the script and tell it
950 	   we haven't found anything for this interface yet. */
951 	if (interval > config->timeout) {
952 		state_panic();
953 		return;
954 	}
955 
956 	/* If we're selecting media, try the whole list before doing
957 	   the exponential backoff, but if we've already received an
958 	   offer, stop looping, because we obviously have it right. */
959 	if (!client->offered_leases && config->media) {
960 		int fail = 0;
961 again:
962 		if (client->medium) {
963 			client->medium = client->medium->next;
964 			increase = 0;
965 		}
966 		if (!client->medium) {
967 			if (fail)
968 				error("No valid media types for %s!", ifi->name);
969 			client->medium = config->media;
970 			increase = 1;
971 		}
972 
973 		note("Trying medium \"%s\" %d", client->medium->string,
974 		    increase);
975 		script_init("MEDIUM", client->medium);
976 		if (script_go())
977 			goto again;
978 	}
979 
980 	/*
981 	 * If we're supposed to increase the interval, do so.  If it's
982 	 * currently zero (i.e., we haven't sent any packets yet), set
983 	 * it to initial_interval; otherwise, add to it a random
984 	 * number between zero and two times itself.  On average, this
985 	 * means that it will double with every transmission.
986 	 */
987 	if (increase) {
988 		if (!client->interval)
989 			client->interval = config->initial_interval;
990 		else {
991 			client->interval += (arc4random() >> 2) %
992 			    (2 * client->interval);
993 		}
994 
995 		/* Don't backoff past cutoff. */
996 		if (client->interval > config->backoff_cutoff)
997 			client->interval = ((config->backoff_cutoff / 2)
998 				 + ((arc4random() >> 2) %
999 				    config->backoff_cutoff));
1000 	} else if (!client->interval)
1001 		client->interval = config->initial_interval;
1002 
1003 	/* If the backoff would take us to the panic timeout, just use that
1004 	   as the interval. */
1005 	if (cur_time + client->interval >
1006 	    client->first_sending + config->timeout)
1007 		client->interval = (client->first_sending +
1008 			 config->timeout) - cur_time + 1;
1009 
1010 	/* Record the number of seconds since we started sending. */
1011 	if (interval < 65536)
1012 		client->packet.secs = htons(interval);
1013 	else
1014 		client->packet.secs = htons(65535);
1015 	client->secs = client->packet.secs;
1016 
1017 	note("DHCPDISCOVER on %s to %s port %d interval %ld",
1018 	    ifi->name, inet_ntoa(sockaddr_broadcast.sin_addr),
1019 	    ntohs(sockaddr_broadcast.sin_port), client->interval);
1020 
1021 	/* Send out a packet. */
1022 	send_packet(inaddr_any, &sockaddr_broadcast, NULL);
1023 
1024 	add_timeout(cur_time + client->interval, send_discover);
1025 }
1026 
1027 /*
1028  * state_panic gets called if we haven't received any offers in a preset
1029  * amount of time.   When this happens, we try to use existing leases
1030  * that haven't yet expired, and failing that, we call the client script
1031  * and hope it can do something.
1032  */
1033 void
1034 state_panic(void)
1035 {
1036 	struct client_lease *loop = client->active;
1037 	struct client_lease *lp;
1038 
1039 	note("No DHCPOFFERS received.");
1040 
1041 	/* We may not have an active lease, but we may have some
1042 	   predefined leases that we can try. */
1043 	if (!client->active && client->leases)
1044 		goto activate_next;
1045 
1046 	/* Run through the list of leases and see if one can be used. */
1047 	while (client->active) {
1048 		if (client->active->expiry > cur_time) {
1049 			note("Trying recorded lease %s",
1050 			    piaddr(client->active->address));
1051 			/* Run the client script with the existing
1052 			   parameters. */
1053 			script_init("TIMEOUT",
1054 			    client->active->medium);
1055 			script_write_params("new_", client->active);
1056 			if (client->alias)
1057 				script_write_params("alias_",
1058 				    client->alias);
1059 
1060 			/* If the old lease is still good and doesn't
1061 			   yet need renewal, go into BOUND state and
1062 			   timeout at the renewal time. */
1063 			if (!script_go()) {
1064 				if (cur_time <
1065 				    client->active->renewal) {
1066 					client->state = S_BOUND;
1067 					note("bound: renewal in %ld seconds.",
1068 					    client->active->renewal -
1069 					    cur_time);
1070 					add_timeout(client->active->renewal,
1071 					    state_bound);
1072 				} else {
1073 					client->state = S_BOUND;
1074 					note("bound: immediate renewal.");
1075 					state_bound();
1076 				}
1077 				reinitialize_interface();
1078 				go_daemon();
1079 				return;
1080 			}
1081 		}
1082 
1083 		/* If there are no other leases, give up. */
1084 		if (!client->leases) {
1085 			client->leases = client->active;
1086 			client->active = NULL;
1087 			break;
1088 		}
1089 
1090 activate_next:
1091 		/* Otherwise, put the active lease at the end of the
1092 		   lease list, and try another lease.. */
1093 		for (lp = client->leases; lp->next; lp = lp->next)
1094 			;
1095 		lp->next = client->active;
1096 		if (lp->next)
1097 			lp->next->next = NULL;
1098 		client->active = client->leases;
1099 		client->leases = client->leases->next;
1100 
1101 		/* If we already tried this lease, we've exhausted the
1102 		   set of leases, so we might as well give up for
1103 		   now. */
1104 		if (client->active == loop)
1105 			break;
1106 		else if (!loop)
1107 			loop = client->active;
1108 	}
1109 
1110 	/* No leases were available, or what was available didn't work, so
1111 	   tell the shell script that we failed to allocate an address,
1112 	   and try again later. */
1113 	note("No working leases in persistent database - sleeping.");
1114 	script_init("FAIL", NULL);
1115 	if (client->alias)
1116 		script_write_params("alias_", client->alias);
1117 	script_go();
1118 	client->state = S_INIT;
1119 	add_timeout(cur_time + config->retry_interval, state_init);
1120 	go_daemon();
1121 }
1122 
1123 void
1124 send_request(void)
1125 {
1126 	struct sockaddr_in destination;
1127 	struct in_addr from;
1128 	int interval;
1129 
1130 	/* Figure out how long it's been since we started transmitting. */
1131 	interval = cur_time - client->first_sending;
1132 
1133 	/* If we're in the INIT-REBOOT or REQUESTING state and we're
1134 	   past the reboot timeout, go to INIT and see if we can
1135 	   DISCOVER an address... */
1136 	/* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1137 	   means either that we're on a network with no DHCP server,
1138 	   or that our server is down.  In the latter case, assuming
1139 	   that there is a backup DHCP server, DHCPDISCOVER will get
1140 	   us a new address, but we could also have successfully
1141 	   reused our old address.  In the former case, we're hosed
1142 	   anyway.  This is not a win-prone situation. */
1143 	if ((client->state == S_REBOOTING ||
1144 	    client->state == S_REQUESTING) &&
1145 	    interval > config->reboot_timeout) {
1146 cancel:
1147 		client->state = S_INIT;
1148 		cancel_timeout(send_request);
1149 		state_init();
1150 		return;
1151 	}
1152 
1153 	/* If we're in the reboot state, make sure the media is set up
1154 	   correctly. */
1155 	if (client->state == S_REBOOTING &&
1156 	    !client->medium &&
1157 	    client->active->medium) {
1158 		script_init("MEDIUM", client->active->medium);
1159 
1160 		/* If the medium we chose won't fly, go to INIT state. */
1161 		if (script_go())
1162 			goto cancel;
1163 
1164 		/* Record the medium. */
1165 		client->medium = client->active->medium;
1166 	}
1167 
1168 	/* If the lease has expired, relinquish the address and go back
1169 	   to the INIT state. */
1170 	if (client->state != S_REQUESTING &&
1171 	    cur_time > client->active->expiry) {
1172 		/* Run the client script with the new parameters. */
1173 		script_init("EXPIRE", NULL);
1174 		script_write_params("old_", client->active);
1175 		if (client->alias)
1176 			script_write_params("alias_", client->alias);
1177 		script_go();
1178 
1179 		/* Now do a preinit on the interface so that we can
1180 		   discover a new address. */
1181 		script_init("PREINIT", NULL);
1182 		if (client->alias)
1183 			script_write_params("alias_", client->alias);
1184 		script_go();
1185 
1186 		client->state = S_INIT;
1187 		state_init();
1188 		return;
1189 	}
1190 
1191 	/* Do the exponential backoff... */
1192 	if (!client->interval)
1193 		client->interval = config->initial_interval;
1194 	else
1195 		client->interval += ((arc4random() >> 2) %
1196 		    (2 * client->interval));
1197 
1198 	/* Don't backoff past cutoff. */
1199 	if (client->interval > config->backoff_cutoff)
1200 		client->interval = ((config->backoff_cutoff / 2) +
1201 		    ((arc4random() >> 2) % client->interval));
1202 
1203 	/* If the backoff would take us to the expiry time, just set the
1204 	   timeout to the expiry time. */
1205 	if (client->state != S_REQUESTING && cur_time + client->interval >
1206 	    client->active->expiry)
1207 		client->interval = client->active->expiry - cur_time + 1;
1208 
1209 	/* If the lease T2 time has elapsed, or if we're not yet bound,
1210 	   broadcast the DHCPREQUEST rather than unicasting. */
1211 	memset(&destination, 0, sizeof(destination));
1212 	if (client->state == S_REQUESTING ||
1213 	    client->state == S_REBOOTING ||
1214 	    cur_time > client->active->rebind)
1215 		destination.sin_addr.s_addr = INADDR_BROADCAST;
1216 	else
1217 		memcpy(&destination.sin_addr.s_addr, client->destination.iabuf,
1218 		    sizeof(destination.sin_addr.s_addr));
1219 	destination.sin_port = htons(REMOTE_PORT);
1220 	destination.sin_family = AF_INET;
1221 	destination.sin_len = sizeof(destination);
1222 
1223 	if (client->state != S_REQUESTING)
1224 		memcpy(&from, client->active->address.iabuf, sizeof(from));
1225 	else
1226 		from.s_addr = INADDR_ANY;
1227 
1228 	/* Record the number of seconds since we started sending. */
1229 	if (client->state == S_REQUESTING)
1230 		client->packet.secs = client->secs;
1231 	else {
1232 		if (interval < 65536)
1233 			client->packet.secs = htons(interval);
1234 		else
1235 			client->packet.secs = htons(65535);
1236 	}
1237 
1238 	note("DHCPREQUEST on %s to %s port %d", ifi->name,
1239 	    inet_ntoa(destination.sin_addr), ntohs(destination.sin_port));
1240 
1241 	/* Send out a packet. */
1242 	send_packet(from, &destination, NULL);
1243 
1244 	add_timeout(cur_time + client->interval, send_request);
1245 }
1246 
1247 void
1248 send_decline(void)
1249 {
1250 	note("DHCPDECLINE on %s to %s port %d", ifi->name,
1251 	    inet_ntoa(sockaddr_broadcast.sin_addr),
1252 	    ntohs(sockaddr_broadcast.sin_port));
1253 
1254 	/* Send out a packet. */
1255 	send_packet(inaddr_any, &sockaddr_broadcast, NULL);
1256 }
1257 
1258 void
1259 make_discover(struct client_lease *lease)
1260 {
1261 	unsigned char discover = DHCPDISCOVER;
1262 	struct option_data options[256];
1263 	int i;
1264 
1265 	memset(options, 0, sizeof(options));
1266 	memset(&client->packet, 0, sizeof(client->packet));
1267 
1268 	/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1269 	i = DHO_DHCP_MESSAGE_TYPE;
1270 	options[i].data = &discover;
1271 	options[i].len = sizeof(discover);
1272 
1273 	/* Request the options we want */
1274 	i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1275 	options[i].data = config->requested_options;
1276 	options[i].len = config->requested_option_count;
1277 
1278 	/* If we had an address, try to get it again. */
1279 	if (lease) {
1280 		client->requested_address = lease->address;
1281 		i = DHO_DHCP_REQUESTED_ADDRESS;
1282 		options[i].data = lease->address.iabuf;
1283 		options[i].len = lease->address.len;
1284 	} else
1285 		client->requested_address.len = 0;
1286 
1287 	/* Send any options requested in the config file. */
1288 	for (i = 0; i < 256; i++)
1289 		if (!options[i].data &&
1290 		    config->send_options[i].data) {
1291 			options[i].data = config->send_options[i].data;
1292 			options[i].len = config->send_options[i].len;
1293 		}
1294 
1295 	/* Set up the option buffer to fit in a minimal UDP packet. */
1296 	i = cons_options(client->packet.options, 576 - DHCP_FIXED_LEN,
1297 	    options);
1298 	if (i == -1 || client->packet.options[i] != DHO_END)
1299 		error("options do not fit in DHCPDISCOVER packet.");
1300 	client->packet_length = DHCP_FIXED_NON_UDP+i+1;
1301 	if (client->packet_length < BOOTP_MIN_LEN)
1302 		client->packet_length = BOOTP_MIN_LEN;
1303 
1304 	client->packet.op = BOOTREQUEST;
1305 	client->packet.htype = ifi->hw_address.htype;
1306 	client->packet.hlen = ifi->hw_address.hlen;
1307 	client->packet.hops = 0;
1308 	client->packet.xid = arc4random();
1309 	client->packet.secs = 0; /* filled in by send_discover. */
1310 	client->packet.flags = 0;
1311 
1312 	memset(&client->packet.ciaddr, 0, sizeof(client->packet.ciaddr));
1313 	memset(&client->packet.yiaddr, 0, sizeof(client->packet.yiaddr));
1314 	memset(&client->packet.siaddr, 0, sizeof(client->packet.siaddr));
1315 	memset(&client->packet.giaddr, 0, sizeof(client->packet.giaddr));
1316 	memcpy(client->packet.chaddr, ifi->hw_address.haddr,
1317 	    ifi->hw_address.hlen);
1318 }
1319 
1320 void
1321 make_request(struct client_lease * lease)
1322 {
1323 	unsigned char request = DHCPREQUEST;
1324 	struct option_data options[256];
1325 	int i;
1326 
1327 	memset(options, 0, sizeof(options));
1328 	memset(&client->packet, 0, sizeof(client->packet));
1329 
1330 	/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1331 	i = DHO_DHCP_MESSAGE_TYPE;
1332 	options[i].data = &request;
1333 	options[i].len = sizeof(request);
1334 
1335 	/* Request the options we want */
1336 	i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1337 	options[i].data = config->requested_options;
1338 	options[i].len = config->requested_option_count;
1339 
1340 	/* If we are requesting an address that hasn't yet been assigned
1341 	   to us, use the DHCP Requested Address option. */
1342 	if (client->state == S_REQUESTING) {
1343 		/* Send back the server identifier... */
1344 		i = DHO_DHCP_SERVER_IDENTIFIER;
1345 		options[i].data = lease->options[i].data;
1346 		options[i].len = lease->options[i].len;
1347 	}
1348 	if (client->state == S_REQUESTING ||
1349 	    client->state == S_REBOOTING) {
1350 		client->requested_address = lease->address;
1351 		i = DHO_DHCP_REQUESTED_ADDRESS;
1352 		options[i].data = lease->address.iabuf;
1353 		options[i].len = lease->address.len;
1354 	} else
1355 		client->requested_address.len = 0;
1356 
1357 	/* Send any options requested in the config file. */
1358 	for (i = 0; i < 256; i++)
1359 		if (!options[i].data && config->send_options[i].data) {
1360 			options[i].data = config->send_options[i].data;
1361 			options[i].len = config->send_options[i].len;
1362 		}
1363 
1364 	/* Set up the option buffer to fit in a minimal UDP packet. */
1365 	i = cons_options(client->packet.options, 576 - DHCP_FIXED_LEN,
1366 	    options);
1367 	if (i == -1 || client->packet.options[i] != DHO_END)
1368 		error("options do not fit in DHCPREQUEST packet.");
1369 	client->packet_length = DHCP_FIXED_NON_UDP+i+1;
1370 	if (client->packet_length < BOOTP_MIN_LEN)
1371 		client->packet_length = BOOTP_MIN_LEN;
1372 
1373 	client->packet.op = BOOTREQUEST;
1374 	client->packet.htype = ifi->hw_address.htype;
1375 	client->packet.hlen = ifi->hw_address.hlen;
1376 	client->packet.hops = 0;
1377 	client->packet.xid = client->xid;
1378 	client->packet.secs = 0; /* Filled in by send_request. */
1379 	client->packet.flags = 0;
1380 
1381 	/* If we own the address we're requesting, put it in ciaddr;
1382 	   otherwise set ciaddr to zero. */
1383 	if (client->state == S_BOUND ||
1384 	    client->state == S_RENEWING ||
1385 	    client->state == S_REBINDING) {
1386 		memcpy(&client->packet.ciaddr,
1387 		    lease->address.iabuf, lease->address.len);
1388 	} else {
1389 		memset(&client->packet.ciaddr, 0,
1390 		    sizeof(client->packet.ciaddr));
1391 	}
1392 
1393 	memset(&client->packet.yiaddr, 0, sizeof(client->packet.yiaddr));
1394 	memset(&client->packet.siaddr, 0, sizeof(client->packet.siaddr));
1395 	memset(&client->packet.giaddr, 0, sizeof(client->packet.giaddr));
1396 	memcpy(client->packet.chaddr, ifi->hw_address.haddr,
1397 	    ifi->hw_address.hlen);
1398 }
1399 
1400 void
1401 make_decline(struct client_lease *lease)
1402 {
1403 	struct option_data options[256];
1404 	unsigned char decline = DHCPDECLINE;
1405 	int i;
1406 
1407 	memset(options, 0, sizeof(options));
1408 	memset(&client->packet, 0, sizeof(client->packet));
1409 
1410 	/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1411 	i = DHO_DHCP_MESSAGE_TYPE;
1412 	options[i].data = &decline;
1413 	options[i].len = sizeof(decline);
1414 
1415 	/* Send back the server identifier... */
1416 	i = DHO_DHCP_SERVER_IDENTIFIER;
1417 	options[i].data = lease->options[i].data;
1418 	options[i].len = lease->options[i].len;
1419 
1420 	/* Send back the address we're declining. */
1421 	i = DHO_DHCP_REQUESTED_ADDRESS;
1422 	options[i].data = lease->address.iabuf;
1423 	options[i].len = lease->address.len;
1424 
1425 	/* Send the uid if the user supplied one. */
1426 	i = DHO_DHCP_CLIENT_IDENTIFIER;
1427 	if (config->send_options[i].len) {
1428 		options[i].data = config->send_options[i].data;
1429 		options[i].len = config->send_options[i].len;
1430 	}
1431 
1432 	/* Set up the option buffer to fit in a minimal UDP packet. */
1433 	i = cons_options(client->packet.options, 576 - DHCP_FIXED_LEN,
1434 	    options);
1435 	if (i == -1 || client->packet.options[i] != DHO_END)
1436 		error("options do not fit in DHCPDECLINE packet.");
1437 	client->packet_length = DHCP_FIXED_NON_UDP+i+1;
1438 	if (client->packet_length < BOOTP_MIN_LEN)
1439 		client->packet_length = BOOTP_MIN_LEN;
1440 
1441 	client->packet.op = BOOTREQUEST;
1442 	client->packet.htype = ifi->hw_address.htype;
1443 	client->packet.hlen = ifi->hw_address.hlen;
1444 	client->packet.hops = 0;
1445 	client->packet.xid = client->xid;
1446 	client->packet.secs = 0; /* Filled in by send_request. */
1447 	client->packet.flags = 0;
1448 
1449 	/* ciaddr must always be zero. */
1450 	memset(&client->packet.ciaddr, 0, sizeof(client->packet.ciaddr));
1451 	memset(&client->packet.yiaddr, 0, sizeof(client->packet.yiaddr));
1452 	memset(&client->packet.siaddr, 0, sizeof(client->packet.siaddr));
1453 	memset(&client->packet.giaddr, 0, sizeof(client->packet.giaddr));
1454 	memcpy(client->packet.chaddr, ifi->hw_address.haddr,
1455 	    ifi->hw_address.hlen);
1456 }
1457 
1458 void
1459 free_client_lease(struct client_lease *lease)
1460 {
1461 	int i;
1462 
1463 	if (lease->server_name)
1464 		free(lease->server_name);
1465 	if (lease->filename)
1466 		free(lease->filename);
1467 	for (i = 0; i < 256; i++) {
1468 		if (lease->options[i].len)
1469 			free(lease->options[i].data);
1470 	}
1471 	free(lease);
1472 }
1473 
1474 void
1475 rewrite_client_leases(void)
1476 {
1477 	struct client_lease *lp;
1478 
1479 	if (!leaseFile)	/* XXX */
1480 		error("lease file not open");
1481 
1482 	fflush(leaseFile);
1483 	rewind(leaseFile);
1484 
1485 	for (lp = client->leases; lp; lp = lp->next)
1486 		write_client_lease(lp, 1);
1487 	if (client->active)
1488 		write_client_lease(client->active, 1);
1489 
1490 	fflush(leaseFile);
1491 	ftruncate(fileno(leaseFile), ftello(leaseFile));
1492 	fsync(fileno(leaseFile));
1493 }
1494 
1495 void
1496 write_client_lease(struct client_lease *lease, int rewrite)
1497 {
1498 	static int leases_written;
1499 	struct tm *t;
1500 	int i;
1501 
1502 	if (!rewrite) {
1503 		if (leases_written++ > 20) {
1504 			rewrite_client_leases();
1505 			leases_written = 0;
1506 		}
1507 	}
1508 
1509 	/* If the lease came from the config file, we don't need to stash
1510 	   a copy in the lease database. */
1511 	if (lease->is_static)
1512 		return;
1513 
1514 	if (!leaseFile)	/* XXX */
1515 		error("lease file not open");
1516 
1517 	fprintf(leaseFile, "lease {\n");
1518 	if (lease->is_bootp)
1519 		fprintf(leaseFile, "  bootp;\n");
1520 	fprintf(leaseFile, "  interface \"%s\";\n", ifi->name);
1521 	fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1522 	if (lease->filename)
1523 		fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1524 	if (lease->server_name)
1525 		fprintf(leaseFile, "  server-name \"%s\";\n",
1526 		    lease->server_name);
1527 	if (lease->medium)
1528 		fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1529 	for (i = 0; i < 256; i++)
1530 		if (lease->options[i].len)
1531 			fprintf(leaseFile, "  option %s %s;\n",
1532 			    dhcp_options[i].name,
1533 			    pretty_print_option(i, lease->options[i].data,
1534 			    lease->options[i].len, 1, 1));
1535 
1536 	t = gmtime(&lease->renewal);
1537 	fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
1538 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1539 	    t->tm_hour, t->tm_min, t->tm_sec);
1540 	t = gmtime(&lease->rebind);
1541 	fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1542 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1543 	    t->tm_hour, t->tm_min, t->tm_sec);
1544 	t = gmtime(&lease->expiry);
1545 	fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
1546 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1547 	    t->tm_hour, t->tm_min, t->tm_sec);
1548 	fprintf(leaseFile, "}\n");
1549 	fflush(leaseFile);
1550 }
1551 
1552 void
1553 script_init(char *reason, struct string_list *medium)
1554 {
1555 	size_t		 len, mediumlen = 0;
1556 	struct imsg_hdr	 hdr;
1557 	struct buf	*buf;
1558 
1559 	if (medium != NULL && medium->string != NULL)
1560 		mediumlen = strlen(medium->string);
1561 
1562 	hdr.code = IMSG_SCRIPT_INIT;
1563 	hdr.len = sizeof(struct imsg_hdr) +
1564 	    sizeof(size_t) + mediumlen +
1565 	    sizeof(size_t) + strlen(reason);
1566 
1567 	buf = buf_open(hdr.len);
1568 
1569 	buf_add(buf, &hdr, sizeof(hdr));
1570 	buf_add(buf, &mediumlen, sizeof(mediumlen));
1571 	if (mediumlen > 0)
1572 		buf_add(buf, medium->string, mediumlen);
1573 	len = strlen(reason);
1574 	buf_add(buf, &len, sizeof(len));
1575 	buf_add(buf, reason, len);
1576 
1577 	buf_close(privfd, buf);
1578 }
1579 
1580 void
1581 priv_script_init(char *reason, char *medium)
1582 {
1583 	client->scriptEnvsize = 100;
1584 	if (client->scriptEnv == NULL)
1585 		client->scriptEnv =
1586 		    calloc(client->scriptEnvsize, sizeof(char *));
1587 	if (client->scriptEnv == NULL)
1588 		error("script_init: no memory for environment");
1589 
1590 	client->scriptEnv[0] = strdup(CLIENT_PATH);
1591 	if (client->scriptEnv[0] == NULL)
1592 		error("script_init: no memory for environment");
1593 
1594 	client->scriptEnv[1] = NULL;
1595 
1596 	script_set_env("", "interface", ifi->name);
1597 
1598 	if (medium)
1599 		script_set_env("", "medium", medium);
1600 
1601 	script_set_env("", "reason", reason);
1602 }
1603 
1604 void
1605 priv_script_write_params(char *prefix, struct client_lease *lease)
1606 {
1607 	u_int8_t dbuf[1500];
1608 	int i, len = 0;
1609 	char tbuf[128];
1610 
1611 	script_set_env(prefix, "ip_address", piaddr(lease->address));
1612 
1613 	if (lease->options[DHO_SUBNET_MASK].len &&
1614 	    (lease->options[DHO_SUBNET_MASK].len <
1615 	    sizeof(lease->address.iabuf))) {
1616 		struct iaddr netmask, subnet, broadcast;
1617 
1618 		memcpy(netmask.iabuf, lease->options[DHO_SUBNET_MASK].data,
1619 		    lease->options[DHO_SUBNET_MASK].len);
1620 		netmask.len = lease->options[DHO_SUBNET_MASK].len;
1621 
1622 		subnet = subnet_number(lease->address, netmask);
1623 		if (subnet.len) {
1624 			script_set_env(prefix, "network_number",
1625 			    piaddr(subnet));
1626 			if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
1627 				broadcast = broadcast_addr(subnet, netmask);
1628 				if (broadcast.len)
1629 					script_set_env(prefix,
1630 					    "broadcast_address",
1631 					    piaddr(broadcast));
1632 			}
1633 		}
1634 	}
1635 
1636 	if (lease->filename)
1637 		script_set_env(prefix, "filename", lease->filename);
1638 	if (lease->server_name)
1639 		script_set_env(prefix, "server_name",
1640 		    lease->server_name);
1641 	for (i = 0; i < 256; i++) {
1642 		u_int8_t *dp = NULL;
1643 
1644 		if (config->defaults[i].len) {
1645 			if (lease->options[i].len) {
1646 				switch (config->default_actions[i]) {
1647 				case ACTION_DEFAULT:
1648 					dp = lease->options[i].data;
1649 					len = lease->options[i].len;
1650 					break;
1651 				case ACTION_SUPERSEDE:
1652 supersede:
1653 					dp = config->defaults[i].data;
1654 					len = config->defaults[i].len;
1655 					break;
1656 				case ACTION_PREPEND:
1657 					len = config->defaults[i].len +
1658 					    lease->options[i].len;
1659 					if (len > sizeof(dbuf)) {
1660 						warning("no space to %s %s",
1661 						    "prepend option",
1662 						    dhcp_options[i].name);
1663 						goto supersede;
1664 					}
1665 					dp = dbuf;
1666 					memcpy(dp,
1667 					    config->defaults[i].data,
1668 					    config->defaults[i].len);
1669 					memcpy(dp +
1670 					    config->defaults[i].len,
1671 					    lease->options[i].data,
1672 					    lease->options[i].len);
1673 					dp[len] = '\0';
1674 					break;
1675 				case ACTION_APPEND:
1676 					len = config->defaults[i].len +
1677 					    lease->options[i].len;
1678 					if (len > sizeof(dbuf)) {
1679 						warning("no space to %s %s",
1680 						    "append option",
1681 						    dhcp_options[i].name);
1682 						goto supersede;
1683 					}
1684 					dp = dbuf;
1685 					memcpy(dp, lease->options[i].data,
1686 					    lease->options[i].len);
1687 					memcpy(dp + lease->options[i].len,
1688 					    config->defaults[i].data,
1689 					    config->defaults[i].len);
1690 					dp[len] = '\0';
1691 				}
1692 			} else {
1693 				dp = config->defaults[i].data;
1694 				len = config->defaults[i].len;
1695 			}
1696 		} else if (lease->options[i].len) {
1697 			len = lease->options[i].len;
1698 			dp = lease->options[i].data;
1699 		} else {
1700 			len = 0;
1701 		}
1702 		if (len) {
1703 			char name[256];
1704 
1705 			if (dhcp_option_ev_name(name, sizeof(name),
1706 			    &dhcp_options[i]))
1707 				script_set_env(prefix, name,
1708 				    pretty_print_option(i, dp, len, 0, 0));
1709 		}
1710 	}
1711 	snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
1712 	script_set_env(prefix, "expiry", tbuf);
1713 }
1714 
1715 void
1716 script_write_params(char *prefix, struct client_lease *lease)
1717 {
1718 	size_t		 fn_len = 0, sn_len = 0, pr_len = 0;
1719 	struct imsg_hdr	 hdr;
1720 	struct buf	*buf;
1721 	int		 i;
1722 
1723 	if (lease->filename != NULL)
1724 		fn_len = strlen(lease->filename);
1725 	if (lease->server_name != NULL)
1726 		sn_len = strlen(lease->server_name);
1727 	if (prefix != NULL)
1728 		pr_len = strlen(prefix);
1729 
1730 	hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
1731 	hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
1732 	    sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
1733 	    sizeof(size_t) + pr_len;
1734 
1735 	for (i = 0; i < 256; i++)
1736 		hdr.len += sizeof(int) + lease->options[i].len;
1737 
1738 	scripttime = time(NULL);
1739 
1740 	buf = buf_open(hdr.len);
1741 
1742 	buf_add(buf, &hdr, sizeof(hdr));
1743 	buf_add(buf, lease, sizeof(struct client_lease));
1744 	buf_add(buf, &fn_len, sizeof(fn_len));
1745 	buf_add(buf, lease->filename, fn_len);
1746 	buf_add(buf, &sn_len, sizeof(sn_len));
1747 	buf_add(buf, lease->server_name, sn_len);
1748 	buf_add(buf, &pr_len, sizeof(pr_len));
1749 	buf_add(buf, prefix, pr_len);
1750 
1751 	for (i = 0; i < 256; i++) {
1752 		buf_add(buf, &lease->options[i].len,
1753 		    sizeof(lease->options[i].len));
1754 		buf_add(buf, lease->options[i].data,
1755 		    lease->options[i].len);
1756 	}
1757 
1758 	buf_close(privfd, buf);
1759 }
1760 
1761 int
1762 script_go(void)
1763 {
1764 	struct imsg_hdr	 hdr;
1765 	struct buf	*buf;
1766 	int		 ret;
1767 
1768 	scripttime = time(NULL);
1769 
1770 	hdr.code = IMSG_SCRIPT_GO;
1771 	hdr.len = sizeof(struct imsg_hdr);
1772 
1773 	buf = buf_open(hdr.len);
1774 
1775 	buf_add(buf, &hdr, sizeof(hdr));
1776 	buf_close(privfd, buf);
1777 
1778 	bzero(&hdr, sizeof(hdr));
1779 	buf_read(privfd, &hdr, sizeof(hdr));
1780 	if (hdr.code != IMSG_SCRIPT_GO_RET)
1781 		error("unexpected msg type %u", hdr.code);
1782 	if (hdr.len != sizeof(hdr) + sizeof(int))
1783 		error("received corrupted message");
1784 	buf_read(privfd, &ret, sizeof(ret));
1785 
1786 	return (ret);
1787 }
1788 
1789 int
1790 priv_script_go(void)
1791 {
1792 	char *scriptName, *argv[2], **envp;
1793 	int pid, wpid, wstatus;
1794 
1795 	scripttime = time(NULL);
1796 
1797 	scriptName = config->script_name;
1798 	envp = client->scriptEnv;
1799 
1800 	argv[0] = scriptName;
1801 	argv[1] = NULL;
1802 
1803 	pid = fork();
1804 	if (pid < 0) {
1805 		error("fork: %m");
1806 		wstatus = 0;
1807 	} else if (pid) {
1808 		do {
1809 			wpid = wait(&wstatus);
1810 		} while (wpid != pid && wpid > 0);
1811 		if (wpid < 0) {
1812 			error("wait: %m");
1813 			wstatus = 0;
1814 		}
1815 	} else {
1816 		execve(scriptName, argv, envp);
1817 		error("execve (%s, ...): %m", scriptName);
1818 	}
1819 
1820 	script_flush_env();
1821 
1822 	return (WEXITSTATUS(wstatus));
1823 }
1824 
1825 void
1826 script_set_env(const char *prefix, const char *name, const char *value)
1827 {
1828 	int i, j, namelen;
1829 
1830 	namelen = strlen(name);
1831 
1832 	for (i = 0; client->scriptEnv[i]; i++)
1833 		if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
1834 		    client->scriptEnv[i][namelen] == '=')
1835 			break;
1836 
1837 	if (client->scriptEnv[i])
1838 		/* Reuse the slot. */
1839 		free(client->scriptEnv[i]);
1840 	else {
1841 		/* New variable.  Expand if necessary. */
1842 		if (i >= client->scriptEnvsize - 1) {
1843 			char **newscriptEnv;
1844 			int newscriptEnvsize = client->scriptEnvsize + 50;
1845 
1846 			newscriptEnv = realloc(client->scriptEnv,
1847 			    newscriptEnvsize);
1848 			if (newscriptEnv == NULL) {
1849 				free(client->scriptEnv);
1850 				client->scriptEnv = NULL;
1851 				client->scriptEnvsize = 0;
1852 				error("script_set_env: no memory for variable");
1853 			}
1854 			client->scriptEnv = newscriptEnv;
1855 			client->scriptEnvsize = newscriptEnvsize;
1856 		}
1857 		/* need to set the NULL pointer at end of array beyond
1858 		   the new slot. */
1859 		client->scriptEnv[i + 1] = NULL;
1860 	}
1861 	/* Allocate space and format the variable in the appropriate slot. */
1862 	client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
1863 	    strlen(value) + 1);
1864 	if (client->scriptEnv[i] == NULL)
1865 		error("script_set_env: no memory for variable assignment");
1866 
1867 	/* No `` or $() command substitution allowed in environment values! */
1868 	for (j = 0; j < strlen(value); j++)
1869 		switch (value[j]) {
1870 		case '`':
1871 		case '$':
1872 			error("illegal character (%c) in value '%s'", value[j],
1873 			    value);
1874 			/* not reached */
1875 		}
1876 	snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
1877 	    1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
1878 }
1879 
1880 void
1881 script_flush_env(void)
1882 {
1883 	int i;
1884 
1885 	for (i = 0; client->scriptEnv[i]; i++) {
1886 		free(client->scriptEnv[i]);
1887 		client->scriptEnv[i] = NULL;
1888 	}
1889 	client->scriptEnvsize = 0;
1890 }
1891 
1892 int
1893 dhcp_option_ev_name(char *buf, size_t buflen, const struct option *option)
1894 {
1895 	size_t i;
1896 
1897 	for (i = 0; option->name[i]; i++) {
1898 		if (i + 1 == buflen)
1899 			return 0;
1900 		if (option->name[i] == '-')
1901 			buf[i] = '_';
1902 		else
1903 			buf[i] = option->name[i];
1904 	}
1905 
1906 	buf[i] = 0;
1907 	return 1;
1908 }
1909 
1910 void
1911 go_daemon(void)
1912 {
1913 	static int state = 0;
1914 
1915 	if (no_daemon || state)
1916 		return;
1917 
1918 	state = 1;
1919 
1920 	/* Stop logging to stderr... */
1921 	log_perror = 0;
1922 
1923 	if (daemon(1, 0) == -1)
1924 		error("daemon");
1925 
1926 	/* we are chrooted, daemon(3) fails to open /dev/null */
1927 	if (nullfd != -1) {
1928 		dup2(nullfd, STDIN_FILENO);
1929 		dup2(nullfd, STDOUT_FILENO);
1930 		dup2(nullfd, STDERR_FILENO);
1931 		close(nullfd);
1932 		nullfd = -1;
1933 	}
1934 }
1935 
1936 int
1937 check_option(struct client_lease *l, int option)
1938 {
1939 	char *opbuf;
1940 	char *sbuf;
1941 
1942 	/* we use this, since this is what gets passed to dhclient-script */
1943 
1944 	opbuf = pretty_print_option(option, l->options[option].data,
1945 	    l->options[option].len, 0, 0);
1946 
1947 	sbuf = option_as_string(option, l->options[option].data,
1948 	    l->options[option].len);
1949 
1950 	switch (option) {
1951 	case DHO_SUBNET_MASK:
1952 	case DHO_TIME_SERVERS:
1953 	case DHO_NAME_SERVERS:
1954 	case DHO_ROUTERS:
1955 	case DHO_DOMAIN_NAME_SERVERS:
1956 	case DHO_LOG_SERVERS:
1957 	case DHO_COOKIE_SERVERS:
1958 	case DHO_LPR_SERVERS:
1959 	case DHO_IMPRESS_SERVERS:
1960 	case DHO_RESOURCE_LOCATION_SERVERS:
1961 	case DHO_SWAP_SERVER:
1962 	case DHO_BROADCAST_ADDRESS:
1963 	case DHO_NIS_SERVERS:
1964 	case DHO_NTP_SERVERS:
1965 	case DHO_NETBIOS_NAME_SERVERS:
1966 	case DHO_NETBIOS_DD_SERVER:
1967 	case DHO_FONT_SERVERS:
1968 	case DHO_DHCP_SERVER_IDENTIFIER:
1969 		if (!ipv4addrs(opbuf)) {
1970 			warning("Invalid IP address in option: %s", opbuf);
1971 			return (0);
1972 		}
1973 		return (1);
1974 	case DHO_HOST_NAME:
1975 	case DHO_DOMAIN_NAME:
1976 	case DHO_NIS_DOMAIN:
1977 		if (!res_hnok(sbuf)) {
1978 			warning("Bogus Host Name option %d: %s (%s)", option,
1979 			    sbuf, opbuf);
1980 			l->options[option].len = 0;
1981 			free(l->options[option].data);
1982 		}
1983 		return (1);
1984 	case DHO_PAD:
1985 	case DHO_TIME_OFFSET:
1986 	case DHO_BOOT_SIZE:
1987 	case DHO_MERIT_DUMP:
1988 	case DHO_ROOT_PATH:
1989 	case DHO_EXTENSIONS_PATH:
1990 	case DHO_IP_FORWARDING:
1991 	case DHO_NON_LOCAL_SOURCE_ROUTING:
1992 	case DHO_POLICY_FILTER:
1993 	case DHO_MAX_DGRAM_REASSEMBLY:
1994 	case DHO_DEFAULT_IP_TTL:
1995 	case DHO_PATH_MTU_AGING_TIMEOUT:
1996 	case DHO_PATH_MTU_PLATEAU_TABLE:
1997 	case DHO_INTERFACE_MTU:
1998 	case DHO_ALL_SUBNETS_LOCAL:
1999 	case DHO_PERFORM_MASK_DISCOVERY:
2000 	case DHO_MASK_SUPPLIER:
2001 	case DHO_ROUTER_DISCOVERY:
2002 	case DHO_ROUTER_SOLICITATION_ADDRESS:
2003 	case DHO_STATIC_ROUTES:
2004 	case DHO_TRAILER_ENCAPSULATION:
2005 	case DHO_ARP_CACHE_TIMEOUT:
2006 	case DHO_IEEE802_3_ENCAPSULATION:
2007 	case DHO_DEFAULT_TCP_TTL:
2008 	case DHO_TCP_KEEPALIVE_INTERVAL:
2009 	case DHO_TCP_KEEPALIVE_GARBAGE:
2010 	case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2011 	case DHO_NETBIOS_NODE_TYPE:
2012 	case DHO_NETBIOS_SCOPE:
2013 	case DHO_X_DISPLAY_MANAGER:
2014 	case DHO_DHCP_REQUESTED_ADDRESS:
2015 	case DHO_DHCP_LEASE_TIME:
2016 	case DHO_DHCP_OPTION_OVERLOAD:
2017 	case DHO_DHCP_MESSAGE_TYPE:
2018 	case DHO_DHCP_PARAMETER_REQUEST_LIST:
2019 	case DHO_DHCP_MESSAGE:
2020 	case DHO_DHCP_MAX_MESSAGE_SIZE:
2021 	case DHO_DHCP_RENEWAL_TIME:
2022 	case DHO_DHCP_REBINDING_TIME:
2023 	case DHO_DHCP_CLASS_IDENTIFIER:
2024 	case DHO_DHCP_CLIENT_IDENTIFIER:
2025 	case DHO_DHCP_USER_CLASS_ID:
2026 	case DHO_END:
2027 		return (1);
2028 	default:
2029 		warning("unknown dhcp option value 0x%x", option);
2030 		return (unknown_ok);
2031 	}
2032 }
2033 
2034 int
2035 res_hnok(const char *name)
2036 {
2037 	const char *dn = name;
2038 	int pch = '.', ch = *dn++;
2039 	int warn = 0;
2040 
2041 	while (ch != '\0') {
2042 		int nch = *dn++;
2043 
2044 		if (ch == '.') {
2045 			;
2046 		} else if (pch == '.' || nch == '.' || nch == '\0') {
2047 			if (!isalnum(ch))
2048 				return (0);
2049 		} else if (!isalnum(ch) && ch != '-' && ch != '_')
2050 				return (0);
2051 		else if (ch == '_' && warn == 0) {
2052 			warning("warning: hostname %s contains an "
2053 			    "underscore which violates RFC 952", name);
2054 			warn++;
2055 		}
2056 		pch = ch, ch = nch;
2057 	}
2058 	return (1);
2059 }
2060 
2061 /* Does buf consist only of dotted decimal ipv4 addrs?
2062  * return how many if so,
2063  * otherwise, return 0
2064  */
2065 int
2066 ipv4addrs(char * buf)
2067 {
2068 	struct in_addr jnk;
2069 	int count = 0;
2070 
2071 	while (inet_aton(buf, &jnk) == 1){
2072 		count++;
2073 		while (*buf == '.' || isdigit(*buf))
2074 			buf++;
2075 		if (*buf == '\0')
2076 			return (count);
2077 		while (*buf ==  ' ')
2078 			buf++;
2079 	}
2080 	return (0);
2081 }
2082 
2083 char *
2084 option_as_string(unsigned int code, unsigned char *data, int len)
2085 {
2086 	static char optbuf[32768]; /* XXX */
2087 	char *op = optbuf;
2088 	int opleft = sizeof(optbuf);
2089 	unsigned char *dp = data;
2090 
2091 	if (code > 255)
2092 		error("option_as_string: bad code %d", code);
2093 
2094 	for (; dp < data + len; dp++) {
2095 		if (!isascii(*dp) || !isprint(*dp)) {
2096 			if (dp + 1 != data + len || *dp != 0) {
2097 				size_t oplen;
2098 				snprintf(op, opleft, "\\%03o", *dp);
2099 				oplen = strlen(op);
2100 				op += oplen;
2101 				opleft -= oplen;
2102 			}
2103 		} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2104 		    *dp == '`' || *dp == '\\') {
2105 			*op++ = '\\';
2106 			*op++ = *dp;
2107 			opleft -= 2;
2108 		} else {
2109 			*op++ = *dp;
2110 			opleft--;
2111 		}
2112 	}
2113 	if (opleft < 1)
2114 		goto toobig;
2115 	*op = 0;
2116 	return optbuf;
2117 toobig:
2118 	warning("dhcp option too large");
2119 	return "<error>";
2120 }
2121 
2122 int
2123 fork_privchld(int fd, int fd2)
2124 {
2125 	struct pollfd pfd[1];
2126 	int nfds;
2127 
2128 	switch (fork()) {
2129 	case -1:
2130 		error("cannot fork");
2131 		break;
2132 	case 0:
2133 		break;
2134 	default:
2135 		return (0);
2136 	}
2137 
2138 	if (chdir("/") == -1)
2139 		error("chdir(\"/\")");
2140 
2141 	setproctitle("%s [priv]", ifi->name);
2142 
2143 	dup2(nullfd, STDIN_FILENO);
2144 	dup2(nullfd, STDOUT_FILENO);
2145 	dup2(nullfd, STDERR_FILENO);
2146 	close(nullfd);
2147 	close(fd2);
2148 
2149 	for (;;) {
2150 		pfd[0].fd = fd;
2151 		pfd[0].events = POLLIN;
2152 		if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2153 			if (errno != EINTR)
2154 				error("poll error");
2155 
2156 		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2157 			continue;
2158 
2159 		dispatch_imsg(fd);
2160 	}
2161 }
2162