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