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