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