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