xref: /freebsd/sbin/dhclient/dhclient.c (revision 43d19e6a4c42ade0f276ceca18a09e2e3829fce4)
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(1, &pw->pw_gid) != 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 do
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) {
1223 			warning("dhcpoffer: no memory for server name.");
1224 			free_client_lease(lease);
1225 			return (NULL);
1226 		}
1227 		memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1228 		lease->server_name[DHCP_SNAME_LEN]='\0';
1229 	}
1230 
1231 	/* Ditto for the filename. */
1232 	if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1233 	    !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1234 	    packet->raw->file[0]) {
1235 		/* Don't count on the NUL terminator. */
1236 		lease->filename = malloc(DHCP_FILE_LEN + 1);
1237 		if (!lease->filename) {
1238 			warning("dhcpoffer: no memory for filename.");
1239 			free_client_lease(lease);
1240 			return (NULL);
1241 		}
1242 		memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1243 		lease->filename[DHCP_FILE_LEN]='\0';
1244 	}
1245 	return lease;
1246 }
1247 
1248 void
dhcpnak(struct packet * packet)1249 dhcpnak(struct packet *packet)
1250 {
1251 	struct interface_info *ip = packet->interface;
1252 
1253 	/* If we're not receptive to an offer right now, or if the offer
1254 	   has an unrecognizable transaction id, then just drop it. */
1255 	if (packet->interface->client->xid != packet->raw->xid ||
1256 	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1257 	    (memcmp(packet->interface->hw_address.haddr,
1258 	    packet->raw->chaddr, packet->raw->hlen)))
1259 		return;
1260 
1261 	if (ip->client->state != S_REBOOTING &&
1262 	    ip->client->state != S_REQUESTING &&
1263 	    ip->client->state != S_RENEWING &&
1264 	    ip->client->state != S_REBINDING)
1265 		return;
1266 
1267 	note("DHCPNAK from %s", piaddr(packet->client_addr));
1268 
1269 	if (!ip->client->active) {
1270 		note("DHCPNAK with no active lease.\n");
1271 		return;
1272 	}
1273 
1274 	free_client_lease(ip->client->active);
1275 	ip->client->active = NULL;
1276 
1277 	/* Stop sending DHCPREQUEST packets... */
1278 	cancel_timeout(send_request, ip);
1279 
1280 	ip->client->state = S_INIT;
1281 	state_init(ip);
1282 }
1283 
1284 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1285    one after the right interval has expired.  If we don't get an offer by
1286    the time we reach the panic interval, call the panic function. */
1287 
1288 void
send_discover(void * ipp)1289 send_discover(void *ipp)
1290 {
1291 	struct interface_info *ip = ipp;
1292 	int interval, increase = 1;
1293 
1294 	/* Figure out how long it's been since we started transmitting. */
1295 	interval = cur_time - ip->client->first_sending;
1296 
1297 	/* If we're past the panic timeout, call the script and tell it
1298 	   we haven't found anything for this interface yet. */
1299 	if (interval > ip->client->config->timeout) {
1300 		state_panic(ip);
1301 		return;
1302 	}
1303 
1304 	/* If we're selecting media, try the whole list before doing
1305 	   the exponential backoff, but if we've already received an
1306 	   offer, stop looping, because we obviously have it right. */
1307 	if (!ip->client->offered_leases &&
1308 	    ip->client->config->media) {
1309 		int fail = 0;
1310 again:
1311 		if (ip->client->medium) {
1312 			ip->client->medium = ip->client->medium->next;
1313 			increase = 0;
1314 		}
1315 		if (!ip->client->medium) {
1316 			if (fail)
1317 				error("No valid media types for %s!", ip->name);
1318 			ip->client->medium = ip->client->config->media;
1319 			increase = 1;
1320 		}
1321 
1322 		note("Trying medium \"%s\" %d", ip->client->medium->string,
1323 		    increase);
1324 		script_init("MEDIUM", ip->client->medium);
1325 		if (script_go())
1326 			goto again;
1327 	}
1328 
1329 	/*
1330 	 * If we're supposed to increase the interval, do so.  If it's
1331 	 * currently zero (i.e., we haven't sent any packets yet), set
1332 	 * it to one; otherwise, add to it a random number between zero
1333 	 * and two times itself.  On average, this means that it will
1334 	 * double with every transmission.
1335 	 */
1336 	if (increase) {
1337 		if (!ip->client->interval)
1338 			ip->client->interval =
1339 			    ip->client->config->initial_interval;
1340 		else {
1341 			ip->client->interval += (arc4random() >> 2) %
1342 			    (2 * ip->client->interval);
1343 		}
1344 
1345 		/* Don't backoff past cutoff. */
1346 		if (ip->client->interval >
1347 		    ip->client->config->backoff_cutoff)
1348 			ip->client->interval =
1349 				((ip->client->config->backoff_cutoff / 2)
1350 				 + ((arc4random() >> 2) %
1351 				    ip->client->config->backoff_cutoff));
1352 	} else if (!ip->client->interval)
1353 		ip->client->interval =
1354 			ip->client->config->initial_interval;
1355 
1356 	/* If the backoff would take us to the panic timeout, just use that
1357 	   as the interval. */
1358 	if (cur_time + ip->client->interval >
1359 	    ip->client->first_sending + ip->client->config->timeout)
1360 		ip->client->interval =
1361 			(ip->client->first_sending +
1362 			 ip->client->config->timeout) - cur_time + 1;
1363 
1364 	/* Record the number of seconds since we started sending. */
1365 	if (interval < 65536)
1366 		ip->client->packet.secs = htons(interval);
1367 	else
1368 		ip->client->packet.secs = htons(65535);
1369 	ip->client->secs = ip->client->packet.secs;
1370 
1371 	note("DHCPDISCOVER on %s to %s port %d interval %d",
1372 	    ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1373 	    (int)ip->client->interval);
1374 
1375 	/* Send out a packet. */
1376 	send_packet_unpriv(privfd, &ip->client->packet,
1377 	    ip->client->packet_length, inaddr_any, inaddr_broadcast);
1378 
1379 	add_timeout(cur_time + ip->client->interval, send_discover, ip);
1380 }
1381 
1382 /*
1383  * state_panic gets called if we haven't received any offers in a preset
1384  * amount of time.   When this happens, we try to use existing leases
1385  * that haven't yet expired, and failing that, we call the client script
1386  * and hope it can do something.
1387  */
1388 void
state_panic(void * ipp)1389 state_panic(void *ipp)
1390 {
1391 	struct interface_info *ip = ipp;
1392 	struct client_lease *loop = ip->client->active;
1393 	struct client_lease *lp;
1394 
1395 	note("No DHCPOFFERS received.");
1396 
1397 	/* We may not have an active lease, but we may have some
1398 	   predefined leases that we can try. */
1399 	if (!ip->client->active && ip->client->leases)
1400 		goto activate_next;
1401 
1402 	/* Run through the list of leases and see if one can be used. */
1403 	while (ip->client->active) {
1404 		if (ip->client->active->expiry > cur_time) {
1405 			note("Trying recorded lease %s",
1406 			    piaddr(ip->client->active->address));
1407 			/* Run the client script with the existing
1408 			   parameters. */
1409 			script_init("TIMEOUT",
1410 			    ip->client->active->medium);
1411 			script_write_params("new_", ip->client->active);
1412 			if (ip->client->alias)
1413 				script_write_params("alias_",
1414 				    ip->client->alias);
1415 
1416 			/* If the old lease is still good and doesn't
1417 			   yet need renewal, go into BOUND state and
1418 			   timeout at the renewal time. */
1419 			if (!script_go()) {
1420 				if (cur_time <
1421 				    ip->client->active->renewal) {
1422 					ip->client->state = S_BOUND;
1423 					note("bound: renewal in %d seconds.",
1424 					    (int)(ip->client->active->renewal -
1425 					    cur_time));
1426 					add_timeout(
1427 					    ip->client->active->renewal,
1428 					    state_bound, ip);
1429 				} else {
1430 					ip->client->state = S_BOUND;
1431 					note("bound: immediate renewal.");
1432 					state_bound(ip);
1433 				}
1434 				reinitialize_interfaces();
1435 				go_daemon();
1436 				return;
1437 			}
1438 		}
1439 
1440 		/* If there are no other leases, give up. */
1441 		if (!ip->client->leases) {
1442 			ip->client->leases = ip->client->active;
1443 			ip->client->active = NULL;
1444 			break;
1445 		}
1446 
1447 activate_next:
1448 		/* Otherwise, put the active lease at the end of the
1449 		   lease list, and try another lease.. */
1450 		for (lp = ip->client->leases; lp->next; lp = lp->next)
1451 			;
1452 		lp->next = ip->client->active;
1453 		if (lp->next)
1454 			lp->next->next = NULL;
1455 		ip->client->active = ip->client->leases;
1456 		ip->client->leases = ip->client->leases->next;
1457 
1458 		/* If we already tried this lease, we've exhausted the
1459 		   set of leases, so we might as well give up for
1460 		   now. */
1461 		if (ip->client->active == loop)
1462 			break;
1463 		else if (!loop)
1464 			loop = ip->client->active;
1465 	}
1466 
1467 	/* No leases were available, or what was available didn't work, so
1468 	   tell the shell script that we failed to allocate an address,
1469 	   and try again later. */
1470 	note("No working leases in persistent database - sleeping.\n");
1471 	script_init("FAIL", NULL);
1472 	if (ip->client->alias)
1473 		script_write_params("alias_", ip->client->alias);
1474 	script_go();
1475 	ip->client->state = S_INIT;
1476 	add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1477 	    ip);
1478 	go_daemon();
1479 }
1480 
1481 void
send_request(void * ipp)1482 send_request(void *ipp)
1483 {
1484 	struct interface_info *ip = ipp;
1485 	struct in_addr from, to;
1486 	int interval;
1487 
1488 	/* Figure out how long it's been since we started transmitting. */
1489 	interval = cur_time - ip->client->first_sending;
1490 
1491 	/* If we're in the INIT-REBOOT or REQUESTING state and we're
1492 	   past the reboot timeout, go to INIT and see if we can
1493 	   DISCOVER an address... */
1494 	/* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1495 	   means either that we're on a network with no DHCP server,
1496 	   or that our server is down.  In the latter case, assuming
1497 	   that there is a backup DHCP server, DHCPDISCOVER will get
1498 	   us a new address, but we could also have successfully
1499 	   reused our old address.  In the former case, we're hosed
1500 	   anyway.  This is not a win-prone situation. */
1501 	if ((ip->client->state == S_REBOOTING ||
1502 	    ip->client->state == S_REQUESTING) &&
1503 	    interval > ip->client->config->reboot_timeout) {
1504 cancel:
1505 		ip->client->state = S_INIT;
1506 		cancel_timeout(send_request, ip);
1507 		state_init(ip);
1508 		return;
1509 	}
1510 
1511 	/* If we're in the reboot state, make sure the media is set up
1512 	   correctly. */
1513 	if (ip->client->state == S_REBOOTING &&
1514 	    !ip->client->medium &&
1515 	    ip->client->active->medium ) {
1516 		script_init("MEDIUM", ip->client->active->medium);
1517 
1518 		/* If the medium we chose won't fly, go to INIT state. */
1519 		if (script_go())
1520 			goto cancel;
1521 
1522 		/* Record the medium. */
1523 		ip->client->medium = ip->client->active->medium;
1524 	}
1525 
1526 	/* If the lease has expired, relinquish the address and go back
1527 	   to the INIT state. */
1528 	if (ip->client->state != S_REQUESTING &&
1529 	    cur_time > ip->client->active->expiry) {
1530 		/* Run the client script with the new parameters. */
1531 		script_init("EXPIRE", NULL);
1532 		script_write_params("old_", ip->client->active);
1533 		if (ip->client->alias)
1534 			script_write_params("alias_", ip->client->alias);
1535 		script_go();
1536 
1537 		/* Now do a preinit on the interface so that we can
1538 		   discover a new address. */
1539 		script_init("PREINIT", NULL);
1540 		if (ip->client->alias)
1541 			script_write_params("alias_", ip->client->alias);
1542 		script_go();
1543 
1544 		ip->client->state = S_INIT;
1545 		state_init(ip);
1546 		return;
1547 	}
1548 
1549 	/* Do the exponential backoff... */
1550 	if (!ip->client->interval)
1551 		ip->client->interval = ip->client->config->initial_interval;
1552 	else
1553 		ip->client->interval += ((arc4random() >> 2) %
1554 		    (2 * ip->client->interval));
1555 
1556 	/* Don't backoff past cutoff. */
1557 	if (ip->client->interval >
1558 	    ip->client->config->backoff_cutoff)
1559 		ip->client->interval =
1560 		    ((ip->client->config->backoff_cutoff / 2) +
1561 		    ((arc4random() >> 2) % ip->client->interval));
1562 
1563 	/* If the backoff would take us to the expiry time, just set the
1564 	   timeout to the expiry time. */
1565 	if (ip->client->state != S_REQUESTING &&
1566 	    cur_time + ip->client->interval >
1567 	    ip->client->active->expiry)
1568 		ip->client->interval =
1569 		    ip->client->active->expiry - cur_time + 1;
1570 
1571 	/* If the lease T2 time has elapsed, or if we're not yet bound,
1572 	   broadcast the DHCPREQUEST rather than unicasting. */
1573 	if (ip->client->state == S_REQUESTING ||
1574 	    ip->client->state == S_REBOOTING ||
1575 	    cur_time > ip->client->active->rebind)
1576 		to.s_addr = INADDR_BROADCAST;
1577 	else
1578 		memcpy(&to.s_addr, ip->client->destination.iabuf,
1579 		    sizeof(to.s_addr));
1580 
1581 	if (ip->client->state != S_REQUESTING &&
1582 	    ip->client->state != S_REBOOTING)
1583 		memcpy(&from, ip->client->active->address.iabuf,
1584 		    sizeof(from));
1585 	else
1586 		from.s_addr = INADDR_ANY;
1587 
1588 	/* Record the number of seconds since we started sending. */
1589 	if (ip->client->state == S_REQUESTING)
1590 		ip->client->packet.secs = ip->client->secs;
1591 	else {
1592 		if (interval < 65536)
1593 			ip->client->packet.secs = htons(interval);
1594 		else
1595 			ip->client->packet.secs = htons(65535);
1596 	}
1597 
1598 	note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1599 	    REMOTE_PORT);
1600 
1601 	/* Send out a packet. */
1602 	send_packet_unpriv(privfd, &ip->client->packet,
1603 	    ip->client->packet_length, from, to);
1604 
1605 	add_timeout(cur_time + ip->client->interval, send_request, ip);
1606 }
1607 
1608 void
send_decline(void * ipp)1609 send_decline(void *ipp)
1610 {
1611 	struct interface_info *ip = ipp;
1612 
1613 	note("DHCPDECLINE on %s to %s port %d", ip->name,
1614 	    inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1615 
1616 	/* Send out a packet. */
1617 	send_packet_unpriv(privfd, &ip->client->packet,
1618 	    ip->client->packet_length, inaddr_any, inaddr_broadcast);
1619 }
1620 
1621 void
make_discover(struct interface_info * ip,struct client_lease * lease)1622 make_discover(struct interface_info *ip, struct client_lease *lease)
1623 {
1624 	unsigned char discover = DHCPDISCOVER;
1625 	struct tree_cache *options[256];
1626 	struct tree_cache option_elements[256];
1627 	int i;
1628 
1629 	memset(option_elements, 0, sizeof(option_elements));
1630 	memset(options, 0, sizeof(options));
1631 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1632 
1633 	/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1634 	i = DHO_DHCP_MESSAGE_TYPE;
1635 	options[i] = &option_elements[i];
1636 	options[i]->value = &discover;
1637 	options[i]->len = sizeof(discover);
1638 	options[i]->buf_size = sizeof(discover);
1639 	options[i]->timeout = 0xFFFFFFFF;
1640 
1641 	/* Request the options we want */
1642 	i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1643 	options[i] = &option_elements[i];
1644 	options[i]->value = ip->client->config->requested_options;
1645 	options[i]->len = ip->client->config->requested_option_count;
1646 	options[i]->buf_size =
1647 		ip->client->config->requested_option_count;
1648 	options[i]->timeout = 0xFFFFFFFF;
1649 
1650 	/* If we had an address, try to get it again. */
1651 	if (lease) {
1652 		ip->client->requested_address = lease->address;
1653 		i = DHO_DHCP_REQUESTED_ADDRESS;
1654 		options[i] = &option_elements[i];
1655 		options[i]->value = lease->address.iabuf;
1656 		options[i]->len = lease->address.len;
1657 		options[i]->buf_size = lease->address.len;
1658 		options[i]->timeout = 0xFFFFFFFF;
1659 	} else
1660 		ip->client->requested_address.len = 0;
1661 
1662 	/* Send any options requested in the config file. */
1663 	for (i = 0; i < 256; i++)
1664 		if (!options[i] &&
1665 		    ip->client->config->send_options[i].data) {
1666 			options[i] = &option_elements[i];
1667 			options[i]->value =
1668 			    ip->client->config->send_options[i].data;
1669 			options[i]->len =
1670 			    ip->client->config->send_options[i].len;
1671 			options[i]->buf_size =
1672 			    ip->client->config->send_options[i].len;
1673 			options[i]->timeout = 0xFFFFFFFF;
1674 		}
1675 
1676 	/* send host name if not set via config file. */
1677 	if (!options[DHO_HOST_NAME]) {
1678 		if (hostname[0] != '\0') {
1679 			size_t len;
1680 			char* posDot = strchr(hostname, '.');
1681 			if (posDot != NULL)
1682 				len = posDot - hostname;
1683 			else
1684 				len = strlen(hostname);
1685 			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1686 			options[DHO_HOST_NAME]->value = hostname;
1687 			options[DHO_HOST_NAME]->len = len;
1688 			options[DHO_HOST_NAME]->buf_size = len;
1689 			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1690 		}
1691 	}
1692 
1693 	/* set unique client identifier */
1694 	char client_ident[sizeof(ip->hw_address.haddr) + 1];
1695 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1696 		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1697 				ip->hw_address.hlen : sizeof(client_ident)-1;
1698 		client_ident[0] = ip->hw_address.htype;
1699 		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1700 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1701 		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1702 		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1703 		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1704 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1705 	}
1706 
1707 	/* Set up the option buffer... */
1708 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1709 	    options, 0, 0, 0, NULL, 0);
1710 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1711 		ip->client->packet_length = BOOTP_MIN_LEN;
1712 
1713 	ip->client->packet.op = BOOTREQUEST;
1714 	ip->client->packet.htype = ip->hw_address.htype;
1715 	ip->client->packet.hlen = ip->hw_address.hlen;
1716 	ip->client->packet.hops = 0;
1717 	ip->client->packet.xid = arc4random();
1718 	ip->client->packet.secs = 0; /* filled in by send_discover. */
1719 	ip->client->packet.flags = 0;
1720 
1721 	memset(&(ip->client->packet.ciaddr),
1722 	    0, sizeof(ip->client->packet.ciaddr));
1723 	memset(&(ip->client->packet.yiaddr),
1724 	    0, sizeof(ip->client->packet.yiaddr));
1725 	memset(&(ip->client->packet.siaddr),
1726 	    0, sizeof(ip->client->packet.siaddr));
1727 	memset(&(ip->client->packet.giaddr),
1728 	    0, sizeof(ip->client->packet.giaddr));
1729 	memcpy(ip->client->packet.chaddr,
1730 	    ip->hw_address.haddr, ip->hw_address.hlen);
1731 }
1732 
1733 
1734 void
make_request(struct interface_info * ip,struct client_lease * lease)1735 make_request(struct interface_info *ip, struct client_lease * lease)
1736 {
1737 	unsigned char request = DHCPREQUEST;
1738 	struct tree_cache *options[256];
1739 	struct tree_cache option_elements[256];
1740 	int i;
1741 
1742 	memset(options, 0, sizeof(options));
1743 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1744 
1745 	/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1746 	i = DHO_DHCP_MESSAGE_TYPE;
1747 	options[i] = &option_elements[i];
1748 	options[i]->value = &request;
1749 	options[i]->len = sizeof(request);
1750 	options[i]->buf_size = sizeof(request);
1751 	options[i]->timeout = 0xFFFFFFFF;
1752 
1753 	/* Request the options we want */
1754 	i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1755 	options[i] = &option_elements[i];
1756 	options[i]->value = ip->client->config->requested_options;
1757 	options[i]->len = ip->client->config->requested_option_count;
1758 	options[i]->buf_size =
1759 		ip->client->config->requested_option_count;
1760 	options[i]->timeout = 0xFFFFFFFF;
1761 
1762 	/* If we are requesting an address that hasn't yet been assigned
1763 	   to us, use the DHCP Requested Address option. */
1764 	if (ip->client->state == S_REQUESTING) {
1765 		/* Send back the server identifier... */
1766 		i = DHO_DHCP_SERVER_IDENTIFIER;
1767 		options[i] = &option_elements[i];
1768 		options[i]->value = lease->options[i].data;
1769 		options[i]->len = lease->options[i].len;
1770 		options[i]->buf_size = lease->options[i].len;
1771 		options[i]->timeout = 0xFFFFFFFF;
1772 	}
1773 	if (ip->client->state == S_REQUESTING ||
1774 	    ip->client->state == S_REBOOTING) {
1775 		ip->client->requested_address = lease->address;
1776 		i = DHO_DHCP_REQUESTED_ADDRESS;
1777 		options[i] = &option_elements[i];
1778 		options[i]->value = lease->address.iabuf;
1779 		options[i]->len = lease->address.len;
1780 		options[i]->buf_size = lease->address.len;
1781 		options[i]->timeout = 0xFFFFFFFF;
1782 	} else
1783 		ip->client->requested_address.len = 0;
1784 
1785 	/* Send any options requested in the config file. */
1786 	for (i = 0; i < 256; i++)
1787 		if (!options[i] &&
1788 		    ip->client->config->send_options[i].data) {
1789 			options[i] = &option_elements[i];
1790 			options[i]->value =
1791 			    ip->client->config->send_options[i].data;
1792 			options[i]->len =
1793 			    ip->client->config->send_options[i].len;
1794 			options[i]->buf_size =
1795 			    ip->client->config->send_options[i].len;
1796 			options[i]->timeout = 0xFFFFFFFF;
1797 		}
1798 
1799 	/* send host name if not set via config file. */
1800 	if (!options[DHO_HOST_NAME]) {
1801 		if (hostname[0] != '\0') {
1802 			size_t len;
1803 			char* posDot = strchr(hostname, '.');
1804 			if (posDot != NULL)
1805 				len = posDot - hostname;
1806 			else
1807 				len = strlen(hostname);
1808 			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1809 			options[DHO_HOST_NAME]->value = hostname;
1810 			options[DHO_HOST_NAME]->len = len;
1811 			options[DHO_HOST_NAME]->buf_size = len;
1812 			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1813 		}
1814 	}
1815 
1816 	/* set unique client identifier */
1817 	char client_ident[sizeof(ip->hw_address.haddr) + 1];
1818 	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1819 		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1820 				ip->hw_address.hlen : sizeof(client_ident)-1;
1821 		client_ident[0] = ip->hw_address.htype;
1822 		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1823 		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1824 		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1825 		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1826 		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1827 		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1828 	}
1829 
1830 	/* Set up the option buffer... */
1831 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1832 	    options, 0, 0, 0, NULL, 0);
1833 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1834 		ip->client->packet_length = BOOTP_MIN_LEN;
1835 
1836 	ip->client->packet.op = BOOTREQUEST;
1837 	ip->client->packet.htype = ip->hw_address.htype;
1838 	ip->client->packet.hlen = ip->hw_address.hlen;
1839 	ip->client->packet.hops = 0;
1840 	ip->client->packet.xid = ip->client->xid;
1841 	ip->client->packet.secs = 0; /* Filled in by send_request. */
1842 
1843 	/* If we own the address we're requesting, put it in ciaddr;
1844 	   otherwise set ciaddr to zero. */
1845 	if (ip->client->state == S_BOUND ||
1846 	    ip->client->state == S_RENEWING ||
1847 	    ip->client->state == S_REBINDING) {
1848 		memcpy(&ip->client->packet.ciaddr,
1849 		    lease->address.iabuf, lease->address.len);
1850 		ip->client->packet.flags = 0;
1851 	} else {
1852 		memset(&ip->client->packet.ciaddr, 0,
1853 		    sizeof(ip->client->packet.ciaddr));
1854 		ip->client->packet.flags = 0;
1855 	}
1856 
1857 	memset(&ip->client->packet.yiaddr, 0,
1858 	    sizeof(ip->client->packet.yiaddr));
1859 	memset(&ip->client->packet.siaddr, 0,
1860 	    sizeof(ip->client->packet.siaddr));
1861 	memset(&ip->client->packet.giaddr, 0,
1862 	    sizeof(ip->client->packet.giaddr));
1863 	memcpy(ip->client->packet.chaddr,
1864 	    ip->hw_address.haddr, ip->hw_address.hlen);
1865 }
1866 
1867 void
make_decline(struct interface_info * ip,struct client_lease * lease)1868 make_decline(struct interface_info *ip, struct client_lease *lease)
1869 {
1870 	struct tree_cache *options[256], message_type_tree;
1871 	struct tree_cache requested_address_tree;
1872 	struct tree_cache server_id_tree, client_id_tree;
1873 	unsigned char decline = DHCPDECLINE;
1874 	int i;
1875 
1876 	memset(options, 0, sizeof(options));
1877 	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1878 
1879 	/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1880 	i = DHO_DHCP_MESSAGE_TYPE;
1881 	options[i] = &message_type_tree;
1882 	options[i]->value = &decline;
1883 	options[i]->len = sizeof(decline);
1884 	options[i]->buf_size = sizeof(decline);
1885 	options[i]->timeout = 0xFFFFFFFF;
1886 
1887 	/* Send back the server identifier... */
1888 	i = DHO_DHCP_SERVER_IDENTIFIER;
1889 	options[i] = &server_id_tree;
1890 	options[i]->value = lease->options[i].data;
1891 	options[i]->len = lease->options[i].len;
1892 	options[i]->buf_size = lease->options[i].len;
1893 	options[i]->timeout = 0xFFFFFFFF;
1894 
1895 	/* Send back the address we're declining. */
1896 	i = DHO_DHCP_REQUESTED_ADDRESS;
1897 	options[i] = &requested_address_tree;
1898 	options[i]->value = lease->address.iabuf;
1899 	options[i]->len = lease->address.len;
1900 	options[i]->buf_size = lease->address.len;
1901 	options[i]->timeout = 0xFFFFFFFF;
1902 
1903 	/* Send the uid if the user supplied one. */
1904 	i = DHO_DHCP_CLIENT_IDENTIFIER;
1905 	if (ip->client->config->send_options[i].len) {
1906 		options[i] = &client_id_tree;
1907 		options[i]->value = ip->client->config->send_options[i].data;
1908 		options[i]->len = ip->client->config->send_options[i].len;
1909 		options[i]->buf_size = ip->client->config->send_options[i].len;
1910 		options[i]->timeout = 0xFFFFFFFF;
1911 	}
1912 
1913 
1914 	/* Set up the option buffer... */
1915 	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1916 	    options, 0, 0, 0, NULL, 0);
1917 	if (ip->client->packet_length < BOOTP_MIN_LEN)
1918 		ip->client->packet_length = BOOTP_MIN_LEN;
1919 
1920 	ip->client->packet.op = BOOTREQUEST;
1921 	ip->client->packet.htype = ip->hw_address.htype;
1922 	ip->client->packet.hlen = ip->hw_address.hlen;
1923 	ip->client->packet.hops = 0;
1924 	ip->client->packet.xid = ip->client->xid;
1925 	ip->client->packet.secs = 0; /* Filled in by send_request. */
1926 	ip->client->packet.flags = 0;
1927 
1928 	/* ciaddr must always be zero. */
1929 	memset(&ip->client->packet.ciaddr, 0,
1930 	    sizeof(ip->client->packet.ciaddr));
1931 	memset(&ip->client->packet.yiaddr, 0,
1932 	    sizeof(ip->client->packet.yiaddr));
1933 	memset(&ip->client->packet.siaddr, 0,
1934 	    sizeof(ip->client->packet.siaddr));
1935 	memset(&ip->client->packet.giaddr, 0,
1936 	    sizeof(ip->client->packet.giaddr));
1937 	memcpy(ip->client->packet.chaddr,
1938 	    ip->hw_address.haddr, ip->hw_address.hlen);
1939 }
1940 
1941 void
free_client_lease(struct client_lease * lease)1942 free_client_lease(struct client_lease *lease)
1943 {
1944 	int i;
1945 
1946 	if (lease->server_name)
1947 		free(lease->server_name);
1948 	if (lease->filename)
1949 		free(lease->filename);
1950 	for (i = 0; i < 256; i++) {
1951 		if (lease->options[i].len)
1952 			free(lease->options[i].data);
1953 	}
1954 	free(lease);
1955 }
1956 
1957 static FILE *leaseFile;
1958 
1959 void
rewrite_client_leases(void)1960 rewrite_client_leases(void)
1961 {
1962 	struct client_lease *lp;
1963 	cap_rights_t rights;
1964 
1965 	if (!leaseFile) {
1966 		leaseFile = fopen(path_dhclient_db, "w");
1967 		if (!leaseFile)
1968 			error("can't create %s: %m", path_dhclient_db);
1969 		cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1970 		    CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1971 		if (caph_rights_limit(fileno(leaseFile), &rights) < 0) {
1972 			error("can't limit lease descriptor: %m");
1973 		}
1974 		if (caph_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0) {
1975 			error("can't limit lease descriptor fcntls: %m");
1976 		}
1977 	} else {
1978 		fflush(leaseFile);
1979 		rewind(leaseFile);
1980 	}
1981 
1982 	for (lp = ifi->client->leases; lp; lp = lp->next)
1983 		write_client_lease(ifi, lp, 1);
1984 	if (ifi->client->active)
1985 		write_client_lease(ifi, ifi->client->active, 1);
1986 
1987 	fflush(leaseFile);
1988 	ftruncate(fileno(leaseFile), ftello(leaseFile));
1989 	fsync(fileno(leaseFile));
1990 }
1991 
1992 void
write_client_lease(struct interface_info * ip,struct client_lease * lease,int rewrite)1993 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1994     int rewrite)
1995 {
1996 	static int leases_written;
1997 	struct tm *t;
1998 	int i;
1999 
2000 	if (!rewrite) {
2001 		if (leases_written++ > 20) {
2002 			rewrite_client_leases();
2003 			leases_written = 0;
2004 		}
2005 	}
2006 
2007 	/* If the lease came from the config file, we don't need to stash
2008 	   a copy in the lease database. */
2009 	if (lease->is_static)
2010 		return;
2011 
2012 	if (!leaseFile) {	/* XXX */
2013 		leaseFile = fopen(path_dhclient_db, "w");
2014 		if (!leaseFile)
2015 			error("can't create %s: %m", path_dhclient_db);
2016 	}
2017 
2018 	fprintf(leaseFile, "lease {\n");
2019 	if (lease->is_bootp)
2020 		fprintf(leaseFile, "  bootp;\n");
2021 	fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
2022 	fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
2023 	if (lease->nextserver.len == sizeof(inaddr_any) &&
2024 	    0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
2025 	    sizeof(inaddr_any)))
2026 		fprintf(leaseFile, "  next-server %s;\n",
2027 		    piaddr(lease->nextserver));
2028 	if (lease->filename)
2029 		fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
2030 	if (lease->server_name)
2031 		fprintf(leaseFile, "  server-name \"%s\";\n",
2032 		    lease->server_name);
2033 	if (lease->medium)
2034 		fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
2035 	for (i = 0; i < 256; i++)
2036 		if (lease->options[i].len)
2037 			fprintf(leaseFile, "  option %s %s;\n",
2038 			    dhcp_options[i].name,
2039 			    pretty_print_option(i, lease->options[i].data,
2040 			    lease->options[i].len, 1, 1));
2041 
2042 	t = gmtime(&lease->renewal);
2043 	fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
2044 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2045 	    t->tm_hour, t->tm_min, t->tm_sec);
2046 	t = gmtime(&lease->rebind);
2047 	fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2048 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2049 	    t->tm_hour, t->tm_min, t->tm_sec);
2050 	t = gmtime(&lease->expiry);
2051 	fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
2052 	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2053 	    t->tm_hour, t->tm_min, t->tm_sec);
2054 	fprintf(leaseFile, "}\n");
2055 	fflush(leaseFile);
2056 }
2057 
2058 void
script_init(const char * reason,struct string_list * medium)2059 script_init(const char *reason, struct string_list *medium)
2060 {
2061 	size_t		 len, mediumlen = 0;
2062 	struct imsg_hdr	 hdr;
2063 	struct buf	*buf;
2064 	int		 errs;
2065 
2066 	if (medium != NULL && medium->string != NULL)
2067 		mediumlen = strlen(medium->string);
2068 
2069 	hdr.code = IMSG_SCRIPT_INIT;
2070 	hdr.len = sizeof(struct imsg_hdr) +
2071 	    sizeof(size_t) + mediumlen +
2072 	    sizeof(size_t) + strlen(reason);
2073 
2074 	if ((buf = buf_open(hdr.len)) == NULL)
2075 		error("buf_open: %m");
2076 
2077 	errs = 0;
2078 	errs += buf_add(buf, &hdr, sizeof(hdr));
2079 	errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2080 	if (mediumlen > 0)
2081 		errs += buf_add(buf, medium->string, mediumlen);
2082 	len = strlen(reason);
2083 	errs += buf_add(buf, &len, sizeof(len));
2084 	errs += buf_add(buf, reason, len);
2085 
2086 	if (errs)
2087 		error("buf_add: %m");
2088 
2089 	if (buf_close(privfd, buf) == -1)
2090 		error("buf_close: %m");
2091 }
2092 
2093 void
priv_script_init(const char * reason,char * medium)2094 priv_script_init(const char *reason, char *medium)
2095 {
2096 	struct interface_info *ip = ifi;
2097 
2098 	if (ip) {
2099 		ip->client->scriptEnvsize = 100;
2100 		if (ip->client->scriptEnv == NULL)
2101 			ip->client->scriptEnv =
2102 			    malloc(ip->client->scriptEnvsize * sizeof(char *));
2103 		if (ip->client->scriptEnv == NULL)
2104 			error("script_init: no memory for environment");
2105 
2106 		ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2107 		if (ip->client->scriptEnv[0] == NULL)
2108 			error("script_init: no memory for environment");
2109 
2110 		ip->client->scriptEnv[1] = NULL;
2111 
2112 		script_set_env(ip->client, "", "interface", ip->name);
2113 
2114 		if (medium)
2115 			script_set_env(ip->client, "", "medium", medium);
2116 
2117 		script_set_env(ip->client, "", "reason", reason);
2118 	}
2119 }
2120 
2121 void
priv_script_write_params(const char * prefix,struct client_lease * lease)2122 priv_script_write_params(const char *prefix, struct client_lease *lease)
2123 {
2124 	struct interface_info *ip = ifi;
2125 	u_int8_t dbuf[1500], *dp = NULL;
2126 	int i;
2127 	size_t len;
2128 	char tbuf[128];
2129 
2130 	script_set_env(ip->client, prefix, "ip_address",
2131 	    piaddr(lease->address));
2132 
2133 	if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2134 	    ACTION_SUPERSEDE) {
2135 		dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2136 		len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2137 	} else {
2138 		dp = lease->options[DHO_SUBNET_MASK].data;
2139 		len = lease->options[DHO_SUBNET_MASK].len;
2140 	}
2141 	if (len && (len < sizeof(lease->address.iabuf))) {
2142 		struct iaddr netmask, subnet, broadcast;
2143 
2144 		memcpy(netmask.iabuf, dp, len);
2145 		netmask.len = len;
2146 		subnet = subnet_number(lease->address, netmask);
2147 		if (subnet.len) {
2148 			script_set_env(ip->client, prefix, "network_number",
2149 			    piaddr(subnet));
2150 			if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2151 				broadcast = broadcast_addr(subnet, netmask);
2152 				if (broadcast.len)
2153 					script_set_env(ip->client, prefix,
2154 					    "broadcast_address",
2155 					    piaddr(broadcast));
2156 			}
2157 		}
2158 	}
2159 
2160 	if (lease->filename)
2161 		script_set_env(ip->client, prefix, "filename", lease->filename);
2162 	if (lease->server_name)
2163 		script_set_env(ip->client, prefix, "server_name",
2164 		    lease->server_name);
2165 	for (i = 0; i < 256; i++) {
2166 		len = 0;
2167 
2168 		if (ip->client->config->defaults[i].len) {
2169 			if (lease->options[i].len) {
2170 				switch (
2171 				    ip->client->config->default_actions[i]) {
2172 				case ACTION_DEFAULT:
2173 					dp = lease->options[i].data;
2174 					len = lease->options[i].len;
2175 					break;
2176 				case ACTION_SUPERSEDE:
2177 supersede:
2178 					dp = ip->client->
2179 						config->defaults[i].data;
2180 					len = ip->client->
2181 						config->defaults[i].len;
2182 					break;
2183 				case ACTION_PREPEND:
2184 					len = ip->client->
2185 					    config->defaults[i].len +
2186 					    lease->options[i].len;
2187 					if (len >= sizeof(dbuf)) {
2188 						warning("no space to %s %s",
2189 						    "prepend option",
2190 						    dhcp_options[i].name);
2191 						goto supersede;
2192 					}
2193 					dp = dbuf;
2194 					memcpy(dp,
2195 						ip->client->
2196 						config->defaults[i].data,
2197 						ip->client->
2198 						config->defaults[i].len);
2199 					memcpy(dp + ip->client->
2200 						config->defaults[i].len,
2201 						lease->options[i].data,
2202 						lease->options[i].len);
2203 					dp[len] = '\0';
2204 					break;
2205 				case ACTION_APPEND:
2206 					/*
2207 					 * When we append, we assume that we're
2208 					 * appending to text.  Some MS servers
2209 					 * include a NUL byte at the end of
2210 					 * the search string provided.
2211 					 */
2212 					len = ip->client->
2213 					    config->defaults[i].len +
2214 					    lease->options[i].len;
2215 					if (len >= sizeof(dbuf)) {
2216 						warning("no space to %s %s",
2217 						    "append option",
2218 						    dhcp_options[i].name);
2219 						goto supersede;
2220 					}
2221 					memcpy(dbuf,
2222 						lease->options[i].data,
2223 						lease->options[i].len);
2224 					for (dp = dbuf + lease->options[i].len;
2225 					    dp > dbuf; dp--, len--)
2226 						if (dp[-1] != '\0')
2227 							break;
2228 					memcpy(dp,
2229 						ip->client->
2230 						config->defaults[i].data,
2231 						ip->client->
2232 						config->defaults[i].len);
2233 					dp = dbuf;
2234 					dp[len] = '\0';
2235 				}
2236 			} else {
2237 				dp = ip->client->
2238 					config->defaults[i].data;
2239 				len = ip->client->
2240 					config->defaults[i].len;
2241 			}
2242 		} else if (lease->options[i].len) {
2243 			len = lease->options[i].len;
2244 			dp = lease->options[i].data;
2245 		} else {
2246 			len = 0;
2247 		}
2248 		if (len) {
2249 			char name[256];
2250 
2251 			if (dhcp_option_ev_name(name, sizeof(name),
2252 			    &dhcp_options[i]))
2253 				script_set_env(ip->client, prefix, name,
2254 				    pretty_print_option(i, dp, len, 0, 0));
2255 		}
2256 	}
2257 	snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2258 	script_set_env(ip->client, prefix, "expiry", tbuf);
2259 }
2260 
2261 void
script_write_params(const char * prefix,struct client_lease * lease)2262 script_write_params(const char *prefix, struct client_lease *lease)
2263 {
2264 	size_t		 fn_len = 0, sn_len = 0, pr_len = 0;
2265 	struct imsg_hdr	 hdr;
2266 	struct buf	*buf;
2267 	int		 errs, i;
2268 
2269 	if (lease->filename != NULL)
2270 		fn_len = strlen(lease->filename);
2271 	if (lease->server_name != NULL)
2272 		sn_len = strlen(lease->server_name);
2273 	if (prefix != NULL)
2274 		pr_len = strlen(prefix);
2275 
2276 	hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2277 	hdr.len = sizeof(hdr) + sizeof(*lease) +
2278 	    sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2279 	    sizeof(pr_len) + pr_len;
2280 
2281 	for (i = 0; i < 256; i++) {
2282 		hdr.len += sizeof(lease->options[i].len);
2283 		hdr.len += lease->options[i].len;
2284 	}
2285 
2286 	scripttime = time(NULL);
2287 
2288 	if ((buf = buf_open(hdr.len)) == NULL)
2289 		error("buf_open: %m");
2290 
2291 	errs = 0;
2292 	errs += buf_add(buf, &hdr, sizeof(hdr));
2293 	errs += buf_add(buf, lease, sizeof(*lease));
2294 	errs += buf_add(buf, &fn_len, sizeof(fn_len));
2295 	errs += buf_add(buf, lease->filename, fn_len);
2296 	errs += buf_add(buf, &sn_len, sizeof(sn_len));
2297 	errs += buf_add(buf, lease->server_name, sn_len);
2298 	errs += buf_add(buf, &pr_len, sizeof(pr_len));
2299 	errs += buf_add(buf, prefix, pr_len);
2300 
2301 	for (i = 0; i < 256; i++) {
2302 		errs += buf_add(buf, &lease->options[i].len,
2303 		    sizeof(lease->options[i].len));
2304 		errs += buf_add(buf, lease->options[i].data,
2305 		    lease->options[i].len);
2306 	}
2307 
2308 	if (errs)
2309 		error("buf_add: %m");
2310 
2311 	if (buf_close(privfd, buf) == -1)
2312 		error("buf_close: %m");
2313 }
2314 
2315 int
script_go(void)2316 script_go(void)
2317 {
2318 	struct imsg_hdr	 hdr;
2319 	struct buf	*buf;
2320 	int		 ret;
2321 
2322 	hdr.code = IMSG_SCRIPT_GO;
2323 	hdr.len = sizeof(struct imsg_hdr);
2324 
2325 	if ((buf = buf_open(hdr.len)) == NULL)
2326 		error("buf_open: %m");
2327 
2328 	if (buf_add(buf, &hdr, sizeof(hdr)))
2329 		error("buf_add: %m");
2330 
2331 	if (buf_close(privfd, buf) == -1)
2332 		error("buf_close: %m");
2333 
2334 	bzero(&hdr, sizeof(hdr));
2335 	buf_read(privfd, &hdr, sizeof(hdr));
2336 	if (hdr.code != IMSG_SCRIPT_GO_RET)
2337 		error("unexpected msg type %u", hdr.code);
2338 	if (hdr.len != sizeof(hdr) + sizeof(int))
2339 		error("received corrupted message");
2340 	buf_read(privfd, &ret, sizeof(ret));
2341 
2342 	scripttime = time(NULL);
2343 
2344 	return (ret);
2345 }
2346 
2347 int
priv_script_go(void)2348 priv_script_go(void)
2349 {
2350 	char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2351 	static char client_path[] = CLIENT_PATH;
2352 	struct interface_info *ip = ifi;
2353 	int pid, wpid, wstatus;
2354 
2355 	scripttime = time(NULL);
2356 
2357 	if (ip) {
2358 		scriptName = ip->client->config->script_name;
2359 		envp = ip->client->scriptEnv;
2360 	} else {
2361 		scriptName = top_level_config.script_name;
2362 		epp[0] = reason;
2363 		epp[1] = client_path;
2364 		epp[2] = NULL;
2365 		envp = epp;
2366 	}
2367 
2368 	argv[0] = scriptName;
2369 	argv[1] = NULL;
2370 
2371 	pid = fork();
2372 	if (pid < 0) {
2373 		error("fork: %m");
2374 		wstatus = 0;
2375 	} else if (pid) {
2376 		do {
2377 			wpid = wait(&wstatus);
2378 		} while (wpid != pid && wpid > 0);
2379 		if (wpid < 0) {
2380 			error("wait: %m");
2381 			wstatus = 0;
2382 		}
2383 	} else {
2384 		execve(scriptName, argv, envp);
2385 		error("execve (%s, ...): %m", scriptName);
2386 	}
2387 
2388 	if (ip)
2389 		script_flush_env(ip->client);
2390 
2391 	return (WIFEXITED(wstatus) ?
2392 	    WEXITSTATUS(wstatus) : 128 + WTERMSIG(wstatus));
2393 }
2394 
2395 void
script_set_env(struct client_state * client,const char * prefix,const char * name,const char * value)2396 script_set_env(struct client_state *client, const char *prefix,
2397     const char *name, const char *value)
2398 {
2399 	int i, namelen;
2400 	size_t j;
2401 
2402 	/* No `` or $() command substitution allowed in environment values! */
2403 	for (j=0; j < strlen(value); j++)
2404 		switch (value[j]) {
2405 		case '`':
2406 		case '$':
2407 			warning("illegal character (%c) in value '%s'",
2408 			    value[j], value);
2409 			/* Ignore this option */
2410 			return;
2411 		}
2412 
2413 	namelen = strlen(name);
2414 
2415 	for (i = 0; client->scriptEnv[i]; i++)
2416 		if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2417 		    client->scriptEnv[i][namelen] == '=')
2418 			break;
2419 
2420 	if (client->scriptEnv[i])
2421 		/* Reuse the slot. */
2422 		free(client->scriptEnv[i]);
2423 	else {
2424 		/* New variable.  Expand if necessary. */
2425 		if (i >= client->scriptEnvsize - 1) {
2426 			char **newscriptEnv;
2427 			int newscriptEnvsize = client->scriptEnvsize + 50;
2428 
2429 			newscriptEnv = realloc(client->scriptEnv,
2430 			    newscriptEnvsize);
2431 			if (newscriptEnv == NULL) {
2432 				free(client->scriptEnv);
2433 				client->scriptEnv = NULL;
2434 				client->scriptEnvsize = 0;
2435 				error("script_set_env: no memory for variable");
2436 			}
2437 			client->scriptEnv = newscriptEnv;
2438 			client->scriptEnvsize = newscriptEnvsize;
2439 		}
2440 		/* need to set the NULL pointer at end of array beyond
2441 		   the new slot. */
2442 		client->scriptEnv[i + 1] = NULL;
2443 	}
2444 	/* Allocate space and format the variable in the appropriate slot. */
2445 	client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2446 	    strlen(value) + 1);
2447 	if (client->scriptEnv[i] == NULL)
2448 		error("script_set_env: no memory for variable assignment");
2449 	snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2450 	    1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2451 }
2452 
2453 void
script_flush_env(struct client_state * client)2454 script_flush_env(struct client_state *client)
2455 {
2456 	int i;
2457 
2458 	for (i = 0; client->scriptEnv[i]; i++) {
2459 		free(client->scriptEnv[i]);
2460 		client->scriptEnv[i] = NULL;
2461 	}
2462 	client->scriptEnvsize = 0;
2463 }
2464 
2465 int
dhcp_option_ev_name(char * buf,size_t buflen,struct option * option)2466 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2467 {
2468 	size_t i;
2469 
2470 	for (i = 0; option->name[i]; i++) {
2471 		if (i + 1 == buflen)
2472 			return 0;
2473 		if (option->name[i] == '-')
2474 			buf[i] = '_';
2475 		else
2476 			buf[i] = option->name[i];
2477 	}
2478 
2479 	buf[i] = 0;
2480 	return 1;
2481 }
2482 
2483 void
go_daemon(void)2484 go_daemon(void)
2485 {
2486 	static int state = 0;
2487 	cap_rights_t rights;
2488 
2489 	if (no_daemon || state)
2490 		return;
2491 
2492 	state = 1;
2493 
2494 	/* Stop logging to stderr... */
2495 	log_perror = 0;
2496 
2497 	if (daemonfd(-1, nullfd) == -1)
2498 		error("daemon");
2499 
2500 	cap_rights_init(&rights);
2501 
2502 	if (pidfile != NULL) {
2503 		pidfile_write(pidfile);
2504 
2505 		if (caph_rights_limit(pidfile_fileno(pidfile), &rights) < 0)
2506 			error("can't limit pidfile descriptor: %m");
2507 	}
2508 
2509 	if (nullfd != -1) {
2510 		close(nullfd);
2511 		nullfd = -1;
2512 	}
2513 
2514 	if (caph_rights_limit(STDIN_FILENO, &rights) < 0)
2515 		error("can't limit stdin: %m");
2516 	cap_rights_init(&rights, CAP_WRITE);
2517 	if (caph_rights_limit(STDOUT_FILENO, &rights) < 0)
2518 		error("can't limit stdout: %m");
2519 	if (caph_rights_limit(STDERR_FILENO, &rights) < 0)
2520 		error("can't limit stderr: %m");
2521 }
2522 
2523 int
check_option(struct client_lease * l,int option)2524 check_option(struct client_lease *l, int option)
2525 {
2526 	const char *opbuf;
2527 	const char *sbuf;
2528 
2529 	/* we use this, since this is what gets passed to dhclient-script */
2530 
2531 	opbuf = pretty_print_option(option, l->options[option].data,
2532 	    l->options[option].len, 0, 0);
2533 
2534 	sbuf = option_as_string(option, l->options[option].data,
2535 	    l->options[option].len);
2536 
2537 	switch (option) {
2538 	case DHO_SUBNET_MASK:
2539 	case DHO_TIME_SERVERS:
2540 	case DHO_NAME_SERVERS:
2541 	case DHO_ROUTERS:
2542 	case DHO_DOMAIN_NAME_SERVERS:
2543 	case DHO_LOG_SERVERS:
2544 	case DHO_COOKIE_SERVERS:
2545 	case DHO_LPR_SERVERS:
2546 	case DHO_IMPRESS_SERVERS:
2547 	case DHO_RESOURCE_LOCATION_SERVERS:
2548 	case DHO_SWAP_SERVER:
2549 	case DHO_BROADCAST_ADDRESS:
2550 	case DHO_NIS_SERVERS:
2551 	case DHO_NTP_SERVERS:
2552 	case DHO_NETBIOS_NAME_SERVERS:
2553 	case DHO_NETBIOS_DD_SERVER:
2554 	case DHO_FONT_SERVERS:
2555 	case DHO_DHCP_SERVER_IDENTIFIER:
2556 	case DHO_NISPLUS_SERVERS:
2557 	case DHO_MOBILE_IP_HOME_AGENT:
2558 	case DHO_SMTP_SERVER:
2559 	case DHO_POP_SERVER:
2560 	case DHO_NNTP_SERVER:
2561 	case DHO_WWW_SERVER:
2562 	case DHO_FINGER_SERVER:
2563 	case DHO_IRC_SERVER:
2564 	case DHO_STREETTALK_SERVER:
2565 	case DHO_STREETTALK_DA_SERVER:
2566 		if (!ipv4addrs(opbuf)) {
2567 			warning("Invalid IP address in option: %s", opbuf);
2568 			return (0);
2569 		}
2570 		return (1)  ;
2571 	case DHO_HOST_NAME:
2572 	case DHO_NIS_DOMAIN:
2573 	case DHO_NISPLUS_DOMAIN:
2574 	case DHO_TFTP_SERVER_NAME:
2575 		if (!res_hnok(sbuf)) {
2576 			warning("Bogus Host Name option %d: %s (%s)", option,
2577 			    sbuf, opbuf);
2578 			l->options[option].len = 0;
2579 			free(l->options[option].data);
2580 		}
2581 		return (1);
2582 	case DHO_DOMAIN_NAME:
2583 	case DHO_DOMAIN_SEARCH:
2584 		if (!res_hnok(sbuf)) {
2585 			if (!check_search(sbuf)) {
2586 				warning("Bogus domain search list %d: %s (%s)",
2587 				    option, sbuf, opbuf);
2588 				l->options[option].len = 0;
2589 				free(l->options[option].data);
2590 			}
2591 		}
2592 		return (1);
2593 	case DHO_PAD:
2594 	case DHO_TIME_OFFSET:
2595 	case DHO_BOOT_SIZE:
2596 	case DHO_MERIT_DUMP:
2597 	case DHO_ROOT_PATH:
2598 	case DHO_EXTENSIONS_PATH:
2599 	case DHO_IP_FORWARDING:
2600 	case DHO_NON_LOCAL_SOURCE_ROUTING:
2601 	case DHO_POLICY_FILTER:
2602 	case DHO_MAX_DGRAM_REASSEMBLY:
2603 	case DHO_DEFAULT_IP_TTL:
2604 	case DHO_PATH_MTU_AGING_TIMEOUT:
2605 	case DHO_PATH_MTU_PLATEAU_TABLE:
2606 	case DHO_INTERFACE_MTU:
2607 	case DHO_ALL_SUBNETS_LOCAL:
2608 	case DHO_PERFORM_MASK_DISCOVERY:
2609 	case DHO_MASK_SUPPLIER:
2610 	case DHO_ROUTER_DISCOVERY:
2611 	case DHO_ROUTER_SOLICITATION_ADDRESS:
2612 	case DHO_STATIC_ROUTES:
2613 	case DHO_TRAILER_ENCAPSULATION:
2614 	case DHO_ARP_CACHE_TIMEOUT:
2615 	case DHO_IEEE802_3_ENCAPSULATION:
2616 	case DHO_DEFAULT_TCP_TTL:
2617 	case DHO_TCP_KEEPALIVE_INTERVAL:
2618 	case DHO_TCP_KEEPALIVE_GARBAGE:
2619 	case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2620 	case DHO_NETBIOS_NODE_TYPE:
2621 	case DHO_NETBIOS_SCOPE:
2622 	case DHO_X_DISPLAY_MANAGER:
2623 	case DHO_DHCP_REQUESTED_ADDRESS:
2624 	case DHO_DHCP_LEASE_TIME:
2625 	case DHO_DHCP_OPTION_OVERLOAD:
2626 	case DHO_DHCP_MESSAGE_TYPE:
2627 	case DHO_DHCP_PARAMETER_REQUEST_LIST:
2628 	case DHO_DHCP_MESSAGE:
2629 	case DHO_DHCP_MAX_MESSAGE_SIZE:
2630 	case DHO_DHCP_RENEWAL_TIME:
2631 	case DHO_DHCP_REBINDING_TIME:
2632 	case DHO_DHCP_CLASS_IDENTIFIER:
2633 	case DHO_DHCP_CLIENT_IDENTIFIER:
2634 	case DHO_BOOTFILE_NAME:
2635 	case DHO_DHCP_USER_CLASS_ID:
2636 	case DHO_URL:
2637 	case DHO_SIP_SERVERS:
2638 	case DHO_V_I_VENDOR_CLASS:
2639 	case DHO_V_I_VENDOR_OPTS:
2640 	case DHO_END:
2641 		return (1);
2642 	case DHO_CLASSLESS_ROUTES:
2643 		return (check_classless_option(l->options[option].data,
2644 		    l->options[option].len));
2645 	default:
2646 		warning("unknown dhcp option value 0x%x", option);
2647 		return (unknown_ok);
2648 	}
2649 }
2650 
2651 /* RFC 3442 The Classless Static Routes option checks */
2652 int
check_classless_option(unsigned char * data,int len)2653 check_classless_option(unsigned char *data, int len)
2654 {
2655 	int i = 0;
2656 	unsigned char width;
2657 	in_addr_t addr, mask;
2658 
2659 	if (len < 5) {
2660 		warning("Too small length: %d", len);
2661 		return (0);
2662 	}
2663 	while(i < len) {
2664 		width = data[i++];
2665 		if (width == 0) {
2666 			i += 4;
2667 			continue;
2668 		} else if (width < 9) {
2669 			addr =  (in_addr_t)(data[i]	<< 24);
2670 			i += 1;
2671 		} else if (width < 17) {
2672 			addr =  (in_addr_t)(data[i]	<< 24) +
2673 				(in_addr_t)(data[i + 1]	<< 16);
2674 			i += 2;
2675 		} else if (width < 25) {
2676 			addr =  (in_addr_t)(data[i]	<< 24) +
2677 				(in_addr_t)(data[i + 1]	<< 16) +
2678 				(in_addr_t)(data[i + 2]	<< 8);
2679 			i += 3;
2680 		} else if (width < 33) {
2681 			addr =  (in_addr_t)(data[i]	<< 24) +
2682 				(in_addr_t)(data[i + 1]	<< 16) +
2683 				(in_addr_t)(data[i + 2]	<< 8)  +
2684 				data[i + 3];
2685 			i += 4;
2686 		} else {
2687 			warning("Incorrect subnet width: %d", width);
2688 			return (0);
2689 		}
2690 		mask = (in_addr_t)(~0) << (32 - width);
2691 		addr = ntohl(addr);
2692 		mask = ntohl(mask);
2693 
2694 		/*
2695 		 * From RFC 3442:
2696 		 * ... After deriving a subnet number and subnet mask
2697 		 * from each destination descriptor, the DHCP client
2698 		 * MUST zero any bits in the subnet number where the
2699 		 * corresponding bit in the mask is zero...
2700 		 */
2701 		if ((addr & mask) != addr) {
2702 			addr &= mask;
2703 			data[i - 1] = (unsigned char)(
2704 				(addr >> (((32 - width)/8)*8)) & 0xFF);
2705 		}
2706 		i += 4;
2707 	}
2708 	if (i > len) {
2709 		warning("Incorrect data length: %d (must be %d)", len, i);
2710 		return (0);
2711 	}
2712 	return (1);
2713 }
2714 
2715 int
res_hnok(const char * dn)2716 res_hnok(const char *dn)
2717 {
2718 	int pch = PERIOD, ch = *dn++;
2719 
2720 	while (ch != '\0') {
2721 		int nch = *dn++;
2722 
2723 		if (periodchar(ch)) {
2724 			;
2725 		} else if (periodchar(pch)) {
2726 			if (!borderchar(ch))
2727 				return (0);
2728 		} else if (periodchar(nch) || nch == '\0') {
2729 			if (!borderchar(ch))
2730 				return (0);
2731 		} else {
2732 			if (!middlechar(ch))
2733 				return (0);
2734 		}
2735 		pch = ch, ch = nch;
2736 	}
2737 	return (1);
2738 }
2739 
2740 int
check_search(const char * srch)2741 check_search(const char *srch)
2742 {
2743         int pch = PERIOD, ch = *srch++;
2744 	int domains = 1;
2745 
2746 	/* 256 char limit re resolv.conf(5) */
2747 	if (strlen(srch) > 256)
2748 		return (0);
2749 
2750 	while (whitechar(ch))
2751 		ch = *srch++;
2752 
2753         while (ch != '\0') {
2754                 int nch = *srch++;
2755 
2756                 if (periodchar(ch) || whitechar(ch)) {
2757                         ;
2758                 } else if (periodchar(pch)) {
2759                         if (!borderchar(ch))
2760                                 return (0);
2761                 } else if (periodchar(nch) || nch == '\0') {
2762                         if (!borderchar(ch))
2763                                 return (0);
2764                 } else {
2765                         if (!middlechar(ch))
2766                                 return (0);
2767                 }
2768 		if (!whitechar(ch)) {
2769 			pch = ch;
2770 		} else {
2771 			while (whitechar(nch)) {
2772 				nch = *srch++;
2773 			}
2774 			if (nch != '\0')
2775 				domains++;
2776 			pch = PERIOD;
2777 		}
2778 		ch = nch;
2779         }
2780 	/* 6 domain limit re resolv.conf(5) */
2781 	if (domains > 6)
2782 		return (0);
2783         return (1);
2784 }
2785 
2786 /* Does buf consist only of dotted decimal ipv4 addrs?
2787  * return how many if so,
2788  * otherwise, return 0
2789  */
2790 int
ipv4addrs(const char * buf)2791 ipv4addrs(const char * buf)
2792 {
2793 	struct in_addr jnk;
2794 	int count = 0;
2795 
2796 	while (inet_aton(buf, &jnk) == 1){
2797 		count++;
2798 		while (periodchar(*buf) || digitchar(*buf))
2799 			buf++;
2800 		if (*buf == '\0')
2801 			return (count);
2802 		while (*buf ==  ' ')
2803 			buf++;
2804 	}
2805 	return (0);
2806 }
2807 
2808 
2809 const char *
option_as_string(unsigned int code,unsigned char * data,int len)2810 option_as_string(unsigned int code, unsigned char *data, int len)
2811 {
2812 	static char optbuf[32768]; /* XXX */
2813 	char *op = optbuf;
2814 	int opleft = sizeof(optbuf);
2815 	unsigned char *dp = data;
2816 
2817 	if (code > 255)
2818 		error("option_as_string: bad code %d", code);
2819 
2820 	for (; dp < data + len; dp++) {
2821 		if (!isascii(*dp) || !isprint(*dp)) {
2822 			if (dp + 1 != data + len || *dp != 0) {
2823 				snprintf(op, opleft, "\\%03o", *dp);
2824 				op += 4;
2825 				opleft -= 4;
2826 			}
2827 		} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2828 		    *dp == '`' || *dp == '\\') {
2829 			*op++ = '\\';
2830 			*op++ = *dp;
2831 			opleft -= 2;
2832 		} else {
2833 			*op++ = *dp;
2834 			opleft--;
2835 		}
2836 	}
2837 	if (opleft < 1)
2838 		goto toobig;
2839 	*op = 0;
2840 	return optbuf;
2841 toobig:
2842 	warning("dhcp option too large");
2843 	return "<error>";
2844 }
2845 
2846 int
fork_privchld(int fd,int fd2)2847 fork_privchld(int fd, int fd2)
2848 {
2849 	struct pollfd pfd[1];
2850 	int nfds;
2851 
2852 	switch (fork()) {
2853 	case -1:
2854 		error("cannot fork");
2855 	case 0:
2856 		break;
2857 	default:
2858 		return (0);
2859 	}
2860 
2861 	setproctitle("%s [priv]", ifi->name);
2862 
2863 	setsid();
2864 	dup2(nullfd, STDIN_FILENO);
2865 	dup2(nullfd, STDOUT_FILENO);
2866 	dup2(nullfd, STDERR_FILENO);
2867 	close(nullfd);
2868 	close(fd2);
2869 	close(ifi->rfdesc);
2870 	ifi->rfdesc = -1;
2871 
2872 	for (;;) {
2873 		pfd[0].fd = fd;
2874 		pfd[0].events = POLLIN;
2875 		if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2876 			if (errno != EINTR)
2877 				error("poll error");
2878 
2879 		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2880 			continue;
2881 
2882 		dispatch_imsg(ifi, fd);
2883 	}
2884 }
2885