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