GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/dhclient/dhclient.c Lines: 0 1281 0.0 %
Date: 2016-12-06 Branches: 0 898 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: dhclient.c,v 1.379 2016/07/23 15:53:19 stsp 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/types.h>
57
#include <sys/socket.h>
58
#include <sys/stat.h>
59
#include <sys/ioctl.h>
60
#include <sys/uio.h>
61
#include <sys/queue.h>
62
63
#include <net/if.h>
64
#include <net/route.h>
65
66
#include <netinet/in.h>
67
#include <netinet/if_ether.h>
68
69
#include <arpa/inet.h>
70
71
#include <ctype.h>
72
#include <errno.h>
73
#include <fcntl.h>
74
#include <ifaddrs.h>
75
#include <imsg.h>
76
#include <limits.h>
77
#include <paths.h>
78
#include <poll.h>
79
#include <pwd.h>
80
#include <resolv.h>
81
#include <signal.h>
82
#include <stdint.h>
83
#include <stdlib.h>
84
#include <string.h>
85
#include <syslog.h>
86
#include <unistd.h>
87
88
#include "dhcp.h"
89
#include "dhcpd.h"
90
#include "privsep.h"
91
92
char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
93
char *path_dhclient_db = NULL;
94
95
char path_option_db[PATH_MAX];
96
97
int log_perror = 1;
98
int nullfd = -1;
99
int no_daemon;
100
int unknown_ok = 1;
101
int routefd = -1;
102
103
volatile sig_atomic_t quit;
104
105
struct in_addr deleting;
106
struct in_addr adding;
107
108
const struct in_addr inaddr_any = { INADDR_ANY };
109
const struct in_addr inaddr_broadcast = { INADDR_BROADCAST };
110
111
struct interface_info *ifi;
112
struct client_state *client;
113
struct client_config *config;
114
struct imsgbuf *unpriv_ibuf;
115
116
void		 sighdlr(int);
117
int		 findproto(char *, int);
118
struct sockaddr	*get_ifa(char *, int);
119
void		 usage(void);
120
int		 res_hnok(const char *dn);
121
int		 res_hnok_list(const char *dn);
122
int		 addressinuse(struct in_addr, char *);
123
124
void		 fork_privchld(int, int);
125
void		 get_ifname(char *);
126
char		*resolv_conf_contents(struct option_data  *,
127
		     struct option_data *, struct option_data *);
128
void		 write_resolv_conf(u_int8_t *, size_t);
129
void		 write_option_db(u_int8_t *, size_t);
130
131
struct client_lease *apply_defaults(struct client_lease *);
132
struct client_lease *clone_lease(struct client_lease *);
133
void		 apply_ignore_list(char *);
134
135
void add_direct_route(struct in_addr, struct in_addr, struct in_addr);
136
void add_default_route(struct in_addr, struct in_addr);
137
void add_static_routes(struct option_data *, struct in_addr);
138
void add_classless_static_routes(struct option_data *, struct in_addr);
139
140
int compare_lease(struct client_lease *, struct client_lease *);
141
void set_lease_times(struct client_lease *);
142
143
void state_preboot(void);
144
void state_reboot(void);
145
void state_init(void);
146
void state_selecting(void);
147
void state_bound(void);
148
void state_panic(void);
149
150
void send_discover(void);
151
void send_request(void);
152
void send_decline(void);
153
154
void bind_lease(void);
155
156
void make_discover(struct client_lease *);
157
void make_request(struct client_lease *);
158
void make_decline(struct client_lease *);
159
160
void rewrite_client_leases(void);
161
void rewrite_option_db(struct client_lease *, struct client_lease *);
162
char *lease_as_string(char *, struct client_lease *);
163
164
struct client_lease *packet_to_lease(struct in_addr, struct option_data *);
165
void go_daemon(void);
166
167
#define	ROUNDUP(a) \
168
	    ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
169
#define	ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
170
171
static FILE *leaseFile;
172
173
void
174
sighdlr(int sig)
175
{
176
	quit = sig;
177
}
178
179
int
180
findproto(char *cp, int n)
181
{
182
	struct sockaddr *sa;
183
	unsigned int i;
184
185
	if (n == 0)
186
		return -1;
187
	for (i = 1; i; i <<= 1) {
188
		if (i & n) {
189
			sa = (struct sockaddr *)cp;
190
			switch (i) {
191
			case RTA_IFA:
192
			case RTA_DST:
193
			case RTA_GATEWAY:
194
			case RTA_NETMASK:
195
				if (sa->sa_family == AF_INET)
196
					return AF_INET;
197
				if (sa->sa_family == AF_INET6)
198
					return AF_INET6;
199
				break;
200
			case RTA_IFP:
201
				break;
202
			}
203
			ADVANCE(cp, sa);
204
		}
205
	}
206
	return (-1);
207
}
208
209
struct sockaddr *
210
get_ifa(char *cp, int n)
211
{
212
	struct sockaddr *sa;
213
	unsigned int i;
214
215
	if (n == 0)
216
		return (NULL);
217
	for (i = 1; i; i <<= 1)
218
		if (i & n) {
219
			sa = (struct sockaddr *)cp;
220
			if (i == RTA_IFA)
221
				return (sa);
222
			ADVANCE(cp, sa);
223
		}
224
225
	return (NULL);
226
}
227
228
void
229
routehandler(void)
230
{
231
	char ntoabuf[INET_ADDRSTRLEN];
232
	struct in_addr a, b;
233
	ssize_t n;
234
	int linkstat, rslt;
235
	struct ether_addr hw;
236
	struct rt_msghdr *rtm;
237
	struct if_msghdr *ifm;
238
	struct ifa_msghdr *ifam;
239
	struct if_announcemsghdr *ifan;
240
	struct sockaddr *sa;
241
	char *errmsg, *rtmmsg;
242
243
	rtmmsg = calloc(1, 2048);
244
	if (rtmmsg == NULL)
245
		error("No memory for rtmmsg");
246
247
	do {
248
		n = read(routefd, rtmmsg, 2048);
249
	} while (n == -1 && errno == EINTR);
250
251
	rtm = (struct rt_msghdr *)rtmmsg;
252
	if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
253
	    rtm->rtm_version != RTM_VERSION)
254
		goto done;
255
256
	switch (rtm->rtm_type) {
257
	case RTM_DESYNC:
258
		warning("route socket buffer overflow");
259
		break;
260
	case RTM_NEWADDR:
261
		ifam = (struct ifa_msghdr *)rtm;
262
		if (ifam->ifam_index != ifi->index)
263
			break;
264
		if (findproto((char *)ifam + ifam->ifam_hdrlen,
265
		    ifam->ifam_addrs) != AF_INET)
266
			break;
267
		sa = get_ifa((char *)ifam + ifam->ifam_hdrlen,
268
		    ifam->ifam_addrs);
269
		if (sa == NULL)
270
			goto done;
271
272
		memcpy(&a, &((struct sockaddr_in *)sa)->sin_addr, sizeof(a));
273
		if (a.s_addr == INADDR_ANY)
274
			break;
275
276
		/*
277
		 * If we are in the process of adding a new address, ignore
278
		 * messages generated by that process.
279
		 */
280
		if (a.s_addr == adding.s_addr) {
281
			adding.s_addr = INADDR_ANY;
282
			note("bound to %s -- renewal in %lld seconds.",
283
			    inet_ntoa(client->active->address),
284
			    (long long)(client->active->renewal -
285
			    time(NULL)));
286
			client->flags |= IS_RESPONSIBLE;
287
			go_daemon();
288
			break;
289
		}
290
		if ((client->flags & IS_RESPONSIBLE) == 0)
291
			/* We're not responsible yet! */
292
			break;
293
		if (adding.s_addr != INADDR_ANY) {
294
			strlcpy(ntoabuf, inet_ntoa(a), sizeof(ntoabuf));
295
			rslt = asprintf(&errmsg, "%s, not %s, added to %s",
296
			    ntoabuf, inet_ntoa(adding), ifi->name);
297
		} else
298
			rslt = asprintf(&errmsg, "%s added to %s",
299
			    inet_ntoa(a), ifi->name);
300
		goto die;
301
	case RTM_DELADDR:
302
		ifam = (struct ifa_msghdr *)rtm;
303
		if (ifam->ifam_index != ifi->index)
304
			break;
305
		if (findproto((char *)ifam + ifam->ifam_hdrlen,
306
		    ifam->ifam_addrs) != AF_INET)
307
			break;
308
		sa = get_ifa((char *)ifam + ifam->ifam_hdrlen,
309
		    ifam->ifam_addrs);
310
		if (sa == NULL)
311
			goto done;
312
313
		memcpy(&a, &((struct sockaddr_in *)sa)->sin_addr, sizeof(a));
314
		if (a.s_addr == INADDR_ANY)
315
			break;
316
317
		/*
318
		 * If we are in the process of deleting an address, ignore
319
		 * messages generated by that process.
320
		 */
321
		if (a.s_addr == deleting.s_addr) {
322
			deleting.s_addr = INADDR_ANY;
323
			break;
324
		}
325
		if ((client->flags & IS_RESPONSIBLE) == 0)
326
			/* We're not responsible yet! */
327
			break;
328
		if (adding.s_addr == INADDR_ANY && client->active &&
329
		    a.s_addr == client->active->address.s_addr) {
330
			/* Tell the priv process active_addr is gone. */
331
			warning("Active address (%s) deleted; exiting",
332
			    inet_ntoa(client->active->address));
333
			memset(&b, 0, sizeof(b));
334
			add_address(b, b);
335
			/* No need to write resolv.conf now. */
336
			client->flags &= ~IS_RESPONSIBLE;
337
			quit = INTERNALSIG;
338
			break;
339
		}
340
		if (deleting.s_addr != INADDR_ANY) {
341
			strlcpy(ntoabuf, inet_ntoa(a), sizeof(ntoabuf));
342
			rslt = asprintf(&errmsg, "%s, not %s, deleted from %s",
343
			    ntoabuf, inet_ntoa(deleting), ifi->name);
344
		} else
345
			rslt = asprintf(&errmsg, "%s deleted from %s",
346
			    inet_ntoa(a), ifi->name);
347
		goto die;
348
	case RTM_IFINFO:
349
		ifm = (struct if_msghdr *)rtm;
350
		if (ifm->ifm_index != ifi->index)
351
			break;
352
		if ((rtm->rtm_flags & RTF_UP) == 0) {
353
			rslt = asprintf(&errmsg, "%s down", ifi->name);
354
			goto die;
355
		}
356
357
		if (ifi->flags & IFI_VALID_LLADDR) {
358
			memcpy(&hw, &ifi->hw_address, sizeof(hw));
359
			get_hw_address();
360
			if (memcmp(&hw, &ifi->hw_address, sizeof(hw))) {
361
				warning("LLADDR changed; restarting");
362
				ifi->flags |= IFI_NEW_LLADDR;
363
				quit = SIGHUP;
364
				goto done;
365
			}
366
		}
367
368
		linkstat = interface_status(ifi->name);
369
		if (linkstat != ifi->linkstat) {
370
#ifdef DEBUG
371
			debug("link state %s -> %s",
372
			    ifi->linkstat ? "up" : "down",
373
			    linkstat ? "up" : "down");
374
#endif
375
			ifi->linkstat = linkstat;
376
			if (ifi->linkstat) {
377
				if (client->state == S_PREBOOT) {
378
					state_preboot();
379
					get_hw_address();
380
				} else {
381
					client->state = S_REBOOTING;
382
					state_reboot();
383
				}
384
			} else {
385
				/* Let monitoring programs see link loss. */
386
				if (strlen(path_option_db))
387
					write_option_db("", 0);
388
				/* No need to wait for anything but link. */
389
				cancel_timeout();
390
			}
391
		}
392
		break;
393
	case RTM_IFANNOUNCE:
394
		ifan = (struct if_announcemsghdr *)rtm;
395
		if (ifan->ifan_what == IFAN_DEPARTURE &&
396
		    ifan->ifan_index == ifi->index) {
397
			rslt = asprintf(&errmsg, "%s departured", ifi->name);
398
			goto die;
399
		}
400
		break;
401
	default:
402
		break;
403
	}
404
405
	/* Something has happened. Try to write out the resolv.conf. */
406
	if (client->active && client->active->resolv_conf &&
407
	    client->flags & IS_RESPONSIBLE)
408
		write_resolv_conf(client->active->resolv_conf,
409
		    strlen(client->active->resolv_conf));
410
411
done:
412
	free(rtmmsg);
413
	return;
414
415
die:
416
	if (rslt == -1)
417
		error("no memory for errmsg");
418
	error("%s; exiting", errmsg);
419
}
420
421
char **saved_argv;
422
423
int
424
main(int argc, char *argv[])
425
{
426
	struct stat sb;
427
	int	 ch, fd, socket_fd[2];
428
	extern char *__progname;
429
	struct passwd *pw;
430
	char *ignore_list = NULL;
431
	ssize_t tailn;
432
	int rtfilter, tailfd;
433
434
	saved_argv = argv;
435
436
	/* Initially, log errors to stderr as well as to syslogd. */
437
	openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
438
#ifdef DEBUG
439
	setlogmask(LOG_UPTO(LOG_DEBUG));
440
#else
441
	setlogmask(LOG_UPTO(LOG_INFO));
442
#endif
443
444
	while ((ch = getopt(argc, argv, "c:di:l:L:qu")) != -1)
445
		switch (ch) {
446
		case 'c':
447
			path_dhclient_conf = optarg;
448
			break;
449
		case 'd':
450
			if (log_perror == 0)
451
				usage();
452
			no_daemon = log_perror = 1;
453
			break;
454
		case 'i':
455
			ignore_list = optarg;
456
			break;
457
		case 'l':
458
			path_dhclient_db = optarg;
459
			if (lstat(path_dhclient_db, &sb) != -1) {
460
				if (!S_ISREG(sb.st_mode))
461
					error("'%s' is not a regular file",
462
					    path_dhclient_db);
463
			}
464
			break;
465
		case 'L':
466
			strlcat(path_option_db, optarg, PATH_MAX);
467
			if (lstat(path_option_db, &sb) != -1) {
468
				if (!S_ISREG(sb.st_mode))
469
					error("'%s' is not a regular file",
470
					    path_option_db);
471
			}
472
			break;
473
		case 'q':
474
			if (no_daemon == 1)
475
				usage();
476
			no_daemon = log_perror = 0;
477
			break;
478
		case 'u':
479
			unknown_ok = 0;
480
			break;
481
		default:
482
			usage();
483
		}
484
485
	argc -= optind;
486
	argv += optind;
487
488
	if (argc != 1)
489
		usage();
490
491
	ifi = calloc(1, sizeof(struct interface_info));
492
	if (ifi == NULL)
493
		error("ifi calloc");
494
	get_ifname(argv[0]);
495
	ifi->index = if_nametoindex(ifi->name);
496
	if (ifi->index == 0)
497
		error("%s: no such interface", ifi->name);
498
499
	tzset();
500
501
	/* Put us into the correct rdomain */
502
	ifi->rdomain = get_rdomain(ifi->name);
503
	if (setrtable(ifi->rdomain) == -1)
504
		error("setting routing table to %u: '%s'", ifi->rdomain,
505
		    strerror(errno));
506
507
	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
508
	    PF_UNSPEC, socket_fd) == -1)
509
		error("socketpair: %s", strerror(errno));
510
511
	fork_privchld(socket_fd[0], socket_fd[1]);
512
513
	close(socket_fd[0]);
514
	if ((unpriv_ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
515
		error("no memory for unpriv_ibuf");
516
	imsg_init(unpriv_ibuf, socket_fd[1]);
517
518
	config = calloc(1, sizeof(struct client_config));
519
	if (config == NULL)
520
		error("config calloc");
521
	TAILQ_INIT(&config->reject_list);
522
523
	client = calloc(1, sizeof(struct client_state));
524
	if (client == NULL)
525
		error("client calloc");
526
	TAILQ_INIT(&client->leases);
527
	TAILQ_INIT(&client->offered_leases);
528
529
	read_client_conf();
530
531
	if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
532
		error("cannot open %s: %s", _PATH_DEVNULL, strerror(errno));
533
534
	if ((pw = getpwnam("_dhcp")) == NULL)
535
		error("no such user: _dhcp");
536
537
	if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
538
	    _PATH_DHCLIENT_DB, ifi->name) == -1)
539
		error("asprintf");
540
541
	/* 2nd stage (post fork) config setup. */
542
	if (ignore_list)
543
		apply_ignore_list(ignore_list);
544
545
	tailfd = open("/etc/resolv.conf.tail", O_RDONLY);
546
	if (tailfd == -1) {
547
		if (errno != ENOENT)
548
			error("Cannot open /etc/resolv.conf.tail: %s",
549
			    strerror(errno));
550
	} else if (fstat(tailfd, &sb) == -1) {
551
		error("Cannot stat /etc/resolv.conf.tail: %s",
552
		    strerror(errno));
553
	} else {
554
		if (sb.st_size > 0 && sb.st_size < SIZE_MAX) {
555
			config->resolv_tail = calloc(1, sb.st_size + 1);
556
			if (config->resolv_tail == NULL) {
557
				error("no memory for resolv.conf.tail "
558
				    "contents: %s", strerror(errno));
559
			}
560
			tailn = read(tailfd, config->resolv_tail, sb.st_size);
561
			if (tailn == -1)
562
				error("Couldn't read resolv.conf.tail: %s",
563
				    strerror(errno));
564
			else if (tailn == 0)
565
				error("Got no data from resolv.conf.tail");
566
			else if (tailn != sb.st_size)
567
				error("Short read of resolv.conf.tail");
568
		}
569
		close(tailfd);
570
	}
571
572
	if ((fd = open(path_dhclient_db,
573
	    O_RDONLY|O_EXLOCK|O_CREAT|O_NOFOLLOW, 0640)) == -1)
574
		error("can't open and lock %s: %s", path_dhclient_db,
575
		    strerror(errno));
576
	read_client_leases();
577
	if ((leaseFile = fopen(path_dhclient_db, "w")) == NULL)
578
		error("can't open %s: %s", path_dhclient_db, strerror(errno));
579
	rewrite_client_leases();
580
	close(fd);
581
582
	/*
583
	 * Do the initial status check and possible force up before creating
584
	 * the routing socket. If we bounce the interface down and up while
585
	 * the routing socket is listening, the RTM_IFINFO message with the
586
	 * RTF_UP flag reset will cause premature exit.
587
	 */
588
	ifi->linkstat = interface_status(ifi->name);
589
	if (ifi->linkstat == 0)
590
		interface_link_forceup(ifi->name);
591
592
	if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
593
		error("socket(PF_ROUTE, SOCK_RAW): %s", strerror(errno));
594
595
	rtfilter = ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR) |
596
	    ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_IFANNOUNCE);
597
598
	if (setsockopt(routefd, PF_ROUTE, ROUTE_MSGFILTER,
599
	    &rtfilter, sizeof(rtfilter)) == -1)
600
		error("setsockopt(ROUTE_MSGFILTER): %s", strerror(errno));
601
	if (setsockopt(routefd, AF_ROUTE, ROUTE_TABLEFILTER, &ifi->rdomain,
602
	    sizeof(ifi->rdomain)) == -1)
603
		error("setsockopt(ROUTE_TABLEFILTER): %s", strerror(errno));
604
605
	/* Register the interface. */
606
	if_register_receive();
607
	if_register_send();
608
609
	if (chroot(_PATH_VAREMPTY) == -1)
610
		error("chroot");
611
	if (chdir("/") == -1)
612
		error("chdir(\"/\")");
613
614
	if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
615
		error("setresgid");
616
	if (setgroups(1, &pw->pw_gid) == -1)
617
		error("setgroups");
618
	if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
619
		error("setresuid");
620
621
	endpwent();
622
623
	if (no_daemon) {
624
		if (pledge("stdio inet dns route rpath cpath wpath", NULL) == -1)
625
			error("pledge");
626
	} else {
627
		if (pledge("stdio inet dns route proc rpath cpath wpath", NULL) == -1)
628
			error("pledge");
629
	}
630
631
	setproctitle("%s", ifi->name);
632
	time(&client->startup_time);
633
634
	if (ifi->linkstat) {
635
		client->state = S_REBOOTING;
636
		state_reboot();
637
	} else {
638
		client->state = S_PREBOOT;
639
		state_preboot();
640
	}
641
642
	dispatch();
643
644
	/* not reached */
645
	return (0);
646
}
647
648
void
649
usage(void)
650
{
651
	extern char	*__progname;
652
653
	fprintf(stderr,
654
	    "usage: %s [-d | -q] [-u] [-c file] [-i options] [-L file] [-l file] "
655
	    "interface\n", __progname);
656
	exit(1);
657
}
658
659
void
660
state_preboot(void)
661
{
662
	static int preamble;
663
	time_t cur_time;
664
	int interval;
665
666
	time(&cur_time);
667
668
	interval = (int)(cur_time - client->startup_time);
669
670
	ifi->linkstat = interface_status(ifi->name);
671
672
	if (log_perror && interval > 3) {
673
		if (!preamble && !ifi->linkstat) {
674
			fprintf(stderr, "%s: no link ....", ifi->name);
675
			preamble = 1;
676
		}
677
		if (preamble) {
678
			if (ifi->linkstat)
679
				fprintf(stderr, " got link\n");
680
			else if (interval > config->link_timeout)
681
				fprintf(stderr, " sleeping\n");
682
			else
683
				fprintf(stderr, ".");
684
			fflush(stderr);
685
		}
686
	}
687
688
	if (ifi->linkstat) {
689
		client->state = S_REBOOTING;
690
		set_timeout_interval(1, state_reboot);
691
	} else {
692
		if (interval > config->link_timeout)
693
			go_daemon();
694
		client->state = S_PREBOOT;
695
		set_timeout_interval(1, state_preboot);
696
	}
697
}
698
699
/*
700
 * Called when the interface link becomes active.
701
 */
702
void
703
state_reboot(void)
704
{
705
	char ifname[IF_NAMESIZE];
706
	struct client_lease *lp;
707
	struct option_data *opt;
708
	time_t cur_time;
709
710
	cancel_timeout();
711
	deleting.s_addr = INADDR_ANY;
712
	adding.s_addr = INADDR_ANY;
713
714
	get_hw_address();
715
	opt = &config->send_options[DHO_DHCP_CLIENT_IDENTIFIER];
716
	/*
717
	 * Check both len && data so
718
	 *     send dhcp-client-identifier "";
719
	 * can be used to suppress sending the default client
720
	 * identifier.
721
	 */
722
	if (opt->len == 0 && opt->data == NULL) {
723
		/* Build default client identifier. */
724
		opt->data = calloc(1, ETHER_ADDR_LEN + 1);
725
		if (opt->data != NULL) {
726
			opt->data[0] = HTYPE_ETHER;
727
			memcpy(&opt->data[1], ifi->hw_address.ether_addr_octet,
728
			    ETHER_ADDR_LEN);
729
			opt->len = ETHER_ADDR_LEN + 1;
730
		}
731
	}
732
733
	time(&cur_time);
734
	if (client->active) {
735
		if (client->active->expiry <= cur_time)
736
			client->active = NULL;
737
		else if (addressinuse(client->active->address, ifname) &&
738
		    strncmp(ifname, ifi->name, IF_NAMESIZE) != 0)
739
			client->active = NULL;
740
	}
741
742
	/* Run through the list of leases and see if one can be used. */
743
	TAILQ_FOREACH(lp, &client->leases, next) {
744
		if (addressinuse(lp->address, ifname) &&
745
		    strncmp(ifname, ifi->name, IF_NAMESIZE) != 0)
746
			continue;
747
		if (client->active || lp->is_static)
748
			break;
749
		if (lp->expiry > cur_time) {
750
			client->active = lp;
751
			break;
752
		}
753
	}
754
755
	/* If we don't remember an active lease, go straight to INIT. */
756
	if (!client->active || client->active->is_bootp) {
757
		client->state = S_INIT;
758
		state_init();
759
		return;
760
	}
761
762
	client->xid = arc4random();
763
	make_request(client->active);
764
765
	client->destination.s_addr = INADDR_BROADCAST;
766
	client->first_sending = time(NULL);
767
	client->interval = 0;
768
769
	send_request();
770
}
771
772
/*
773
 * Called when a lease has completely expired and we've been unable to renew it.
774
 */
775
void
776
state_init(void)
777
{
778
	client->xid = arc4random();
779
	make_discover(client->active);
780
781
	client->destination.s_addr = INADDR_BROADCAST;
782
	client->state = S_SELECTING;
783
	client->first_sending = time(NULL);
784
	client->interval = 0;
785
786
	send_discover();
787
}
788
789
/*
790
 * Called when one or more DHCPOFFER packets have been received and a
791
 * configurable period of time has passed.
792
 */
793
void
794
state_selecting(void)
795
{
796
	struct client_lease *lease, *picked;
797
798
	cancel_timeout();
799
800
	/* Take the first valid DHCPOFFER. */
801
	TAILQ_FOREACH_SAFE(picked, &client->offered_leases, next, lease) {
802
		if (picked->is_invalid == 0) {
803
			TAILQ_REMOVE(&client->offered_leases, picked, next);
804
			break;
805
		}
806
	}
807
	/* DECLINE the rest of the offers. */
808
	while (!TAILQ_EMPTY(&client->offered_leases)) {
809
		lease = TAILQ_FIRST(&client->offered_leases);
810
		TAILQ_REMOVE(&client->offered_leases, lease, next);
811
		make_decline(lease);
812
		send_decline();
813
		free_client_lease(lease);
814
	}
815
816
	if (!picked) {
817
		state_panic();
818
		return;
819
	}
820
821
	/* If it was a BOOTREPLY, we can just take the lease right now. */
822
	if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
823
		struct option_data *option;
824
825
		client->new = picked;
826
827
		/*
828
		 * Set (unsigned 32 bit) options
829
		 *
830
		 * DHO_DHCP_LEASE_TIME (12000 seconds),
831
		 * DHO_RENEWAL_TIME (8000 seconds)
832
		 * DHO_REBINDING_TIME (10000 seconds)
833
		 *
834
		 * so bind_lease() can set the lease times. Note that the
835
		 * values must be big-endian.
836
		 */
837
		option = &client->new->options[DHO_DHCP_LEASE_TIME];
838
		option->data = malloc(4);
839
		if (option->data) {
840
			option->len = 4;
841
			memcpy(option->data, "\x00\x00\x2e\xe0", 4);
842
		}
843
		option = &client->new->options[DHO_DHCP_RENEWAL_TIME];
844
		option->data = malloc(4);
845
		if (option->data) {
846
			option->len = 4;
847
			memcpy(option->data, "\x00\x00\x1f\x40", 4);
848
		}
849
		option = &client->new->options[DHO_DHCP_REBINDING_TIME];
850
		option->data = malloc(4);
851
		if (option->data) {
852
			option->len = 4;
853
			memcpy(option->data, "\x00\x00\x27\x10", 4);
854
		}
855
856
		client->state = S_REQUESTING;
857
		bind_lease();
858
859
		return;
860
	}
861
862
	client->destination.s_addr = INADDR_BROADCAST;
863
	client->state = S_REQUESTING;
864
	client->first_sending = time(NULL);
865
866
	client->interval = 0;
867
868
	/*
869
	 * Make a DHCPREQUEST packet from the lease we picked. Keep
870
	 * the current xid, as all offers should have had the same
871
	 * one.
872
	 */
873
	make_request(picked);
874
875
	/* Toss the lease we picked - we'll get it back in a DHCPACK. */
876
	free_client_lease(picked);
877
878
	send_request();
879
}
880
881
void
882
dhcpack(struct in_addr client_addr, struct option_data *options, char *info)
883
{
884
	struct client_lease *lease;
885
886
	if (client->state != S_REBOOTING &&
887
	    client->state != S_REQUESTING &&
888
	    client->state != S_RENEWING &&
889
	    client->state != S_REBINDING) {
890
#ifdef DEBUG
891
		debug("Unexpected %s. State #%d", info, client->state);
892
#endif
893
		return;
894
	}
895
896
	note("%s", info);
897
898
	lease = packet_to_lease(client_addr, options);
899
	if (lease->is_invalid) {
900
		note("Unsatisfactory %s", info);
901
		make_decline(lease);
902
		send_decline();
903
		free_client_lease(lease);
904
		client->state = S_INIT;
905
		state_init();
906
		return;
907
	}
908
909
	client->new = lease;
910
911
	/* Stop resending DHCPREQUEST. */
912
	cancel_timeout();
913
914
	bind_lease();
915
}
916
917
void
918
bind_lease(void)
919
{
920
	struct in_addr gateway, mask;
921
	struct option_data *options, *opt;
922
	struct client_lease *lease, *pl;
923
	time_t cur_time;
924
	int seen;
925
926
	/*
927
	 * Clear out any old resolv_conf in case the lease has been here
928
	 * before (e.g. static lease).
929
	 */
930
	free(client->new->resolv_conf);
931
	client->new->resolv_conf = NULL;
932
933
	lease = apply_defaults(client->new);
934
	options = lease->options;
935
936
	set_lease_times(lease);
937
938
	client->new->expiry = lease->expiry;
939
	client->new->renewal = lease->renewal;
940
	client->new->rebind = lease->rebind;
941
942
	/*
943
	 * A duplicate lease once we are responsible & S_RENEWING means we don't
944
	 * need to change the interface, routing table or resolv.conf.
945
	 */
946
	if ((client->flags & IS_RESPONSIBLE) && client->state == S_RENEWING &&
947
	    compare_lease(client->active, client->new) == 0) {
948
		client->new->resolv_conf = client->active->resolv_conf;
949
		client->active->resolv_conf = NULL;
950
		client->active = client->new;
951
		client->new = NULL;
952
		note("bound to %s -- renewal in %lld seconds.",
953
		    inet_ntoa(client->active->address),
954
		    (long long)(client->active->renewal - time(NULL)));
955
		goto newlease;
956
	}
957
958
	client->new->resolv_conf = resolv_conf_contents(
959
	    &options[DHO_DOMAIN_NAME], &options[DHO_DOMAIN_NAME_SERVERS],
960
	    &options[DHO_DOMAIN_SEARCH]);
961
962
	/* Replace the old active lease with the new one. */
963
	client->active = client->new;
964
	client->new = NULL;
965
966
	/* Deleting the addresses also clears out arp entries. */
967
	delete_addresses();
968
	flush_routes();
969
970
	opt = &options[DHO_INTERFACE_MTU];
971
	if (opt->len == sizeof(u_int16_t)) {
972
		u_int16_t mtu;
973
		memcpy(&mtu, opt->data, sizeof(mtu));
974
		mtu = ntohs(mtu);
975
		/* "The minimum legal value for the MTU is 68." */
976
		if (mtu < 68)
977
			warning("mtu size %u < 68: ignored", mtu);
978
		else
979
			set_interface_mtu(mtu);
980
	}
981
982
	opt = &options[DHO_SUBNET_MASK];
983
	if (opt->len == sizeof(mask))
984
		mask.s_addr = ((struct in_addr *)opt->data)->s_addr;
985
	else
986
		mask.s_addr = INADDR_ANY;
987
988
        /*
989
	 * Add address and default route last, so we know when the binding
990
	 * is done by the RTM_NEWADDR message being received.
991
	 */
992
	add_address(client->active->address, mask);
993
	if (options[DHO_CLASSLESS_STATIC_ROUTES].len) {
994
		add_classless_static_routes(
995
		    &options[DHO_CLASSLESS_STATIC_ROUTES],
996
		    client->active->address);
997
	} else if (options[DHO_CLASSLESS_MS_STATIC_ROUTES].len) {
998
		add_classless_static_routes(
999
		    &options[DHO_CLASSLESS_MS_STATIC_ROUTES],
1000
		    client->active->address);
1001
	} else {
1002
		opt = &options[DHO_ROUTERS];
1003
		if (opt->len >= sizeof(gateway)) {
1004
			/* XXX Only use FIRST router address for now. */
1005
			gateway.s_addr = ((struct in_addr *)opt->data)->s_addr;
1006
1007
			/*
1008
			 * To be compatible with ISC DHCP behavior on Linux, if
1009
			 * we were given a /32 IP assignment, then add a /32
1010
			 * direct route for the gateway to make it routable.
1011
			 */
1012
			if (mask.s_addr == INADDR_BROADCAST) {
1013
				add_direct_route(gateway, mask,
1014
				    client->active->address);
1015
			}
1016
1017
			add_default_route(client->active->address, gateway);
1018
		}
1019
		if (options[DHO_STATIC_ROUTES].len)
1020
			add_static_routes(&options[DHO_STATIC_ROUTES],
1021
			    client->active->address);
1022
	}
1023
1024
newlease:
1025
	rewrite_option_db(client->active, lease);
1026
	free_client_lease(lease);
1027
1028
	/*
1029
	 * Remove previous dynamic lease(es) for this address, and any expired
1030
	 * dynamic leases.
1031
	 */
1032
	seen = 0;
1033
	time(&cur_time);
1034
	TAILQ_FOREACH_SAFE(lease, &client->leases, next, pl) {
1035
		if (lease->is_static)
1036
			break;
1037
		if (client->active == lease)
1038
			seen = 1;
1039
		else if (lease->expiry <= cur_time || lease->address.s_addr ==
1040
		    client->active->address.s_addr) {
1041
			TAILQ_REMOVE(&client->leases, lease, next);
1042
			free_client_lease(lease);
1043
		}
1044
	}
1045
	if (!client->active->is_static && !seen)
1046
		TAILQ_INSERT_HEAD(&client->leases, client->active,  next);
1047
1048
	client->state = S_BOUND;
1049
1050
	/* Write out new leases file. */
1051
	rewrite_client_leases();
1052
1053
	/* Set timeout to start the renewal process. */
1054
	set_timeout(client->active->renewal, state_bound);
1055
}
1056
1057
/*
1058
 * Called when we've successfully bound to a particular lease, but the renewal
1059
 * time on that lease has expired.  We are expected to unicast a DHCPREQUEST to
1060
 * the server that gave us our original lease.
1061
 */
1062
void
1063
state_bound(void)
1064
{
1065
	struct option_data *opt;
1066
	struct in_addr *dest;
1067
1068
	client->xid = arc4random();
1069
	make_request(client->active);
1070
1071
	dest = &client->destination;
1072
	opt = &client->active->options[DHO_DHCP_SERVER_IDENTIFIER];
1073
1074
	if (opt->len == sizeof(*dest))
1075
		dest->s_addr = ((struct in_addr *)opt->data)->s_addr;
1076
	else
1077
		dest->s_addr = INADDR_BROADCAST;
1078
1079
	client->first_sending = time(NULL);
1080
	client->interval = 0;
1081
	client->state = S_RENEWING;
1082
1083
	send_request();
1084
}
1085
1086
void
1087
dhcpoffer(struct in_addr client_addr, struct option_data *options, char *info)
1088
{
1089
	struct client_lease *lease, *lp;
1090
	time_t stop_selecting;
1091
1092
	if (client->state != S_SELECTING) {
1093
#ifdef DEBUG
1094
		debug("Unexpected %s. State #%d.", info, client->state);
1095
#endif
1096
		return;
1097
	}
1098
1099
	note("%s", info);
1100
1101
	/* If we've already seen this lease, don't record it again. */
1102
	TAILQ_FOREACH(lp, &client->offered_leases, next) {
1103
		if (!memcmp(&lp->address.s_addr, &client->packet.yiaddr,
1104
		    sizeof(in_addr_t))) {
1105
#ifdef DEBUG
1106
			debug("Duplicate %s.", info);
1107
#endif
1108
			return;
1109
		}
1110
	}
1111
1112
	lease = packet_to_lease(client_addr, options);
1113
1114
	/*
1115
	 * If this lease was acquired through a BOOTREPLY, record that
1116
	 * fact.
1117
	 */
1118
	if (!options[DHO_DHCP_MESSAGE_TYPE].len)
1119
		lease->is_bootp = 1;
1120
1121
	/* Figure out when we're supposed to stop selecting. */
1122
	stop_selecting = client->first_sending + config->select_interval;
1123
1124
	if (TAILQ_EMPTY(&client->offered_leases)) {
1125
		TAILQ_INSERT_HEAD(&client->offered_leases, lease, next);
1126
	} else if (lease->address.s_addr == client->requested_address.s_addr) {
1127
		/* The lease we expected - put it at the head of the list. */
1128
		TAILQ_INSERT_HEAD(&client->offered_leases, lease, next);
1129
	} else {
1130
		/* Not the lease we expected - put it at the end of the list. */
1131
		TAILQ_INSERT_TAIL(&client->offered_leases, lease, next);
1132
	}
1133
1134
	if (stop_selecting <= time(NULL))
1135
		state_selecting();
1136
	else
1137
		set_timeout(stop_selecting, state_selecting);
1138
}
1139
1140
int
1141
addressinuse(struct in_addr address, char *ifname)
1142
{
1143
	struct ifaddrs *ifap, *ifa;
1144
	struct sockaddr_in *sin;
1145
	int used = 0;
1146
1147
	if (getifaddrs(&ifap) != 0) {
1148
		warning("addressinuse: getifaddrs: %s", strerror(errno));
1149
		return (0);
1150
	}
1151
1152
	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1153
		if (ifa->ifa_addr == NULL ||
1154
		    ifa->ifa_addr->sa_family != AF_INET)
1155
			continue;
1156
1157
		sin = (struct sockaddr_in *)ifa->ifa_addr;
1158
		if (memcmp(&address, &sin->sin_addr, sizeof(address)) == 0) {
1159
			strlcpy(ifname, ifa->ifa_name, IF_NAMESIZE);
1160
			used = 1;
1161
			if (strncmp(ifname, ifi->name, IF_NAMESIZE) != 0)
1162
				break;
1163
		}
1164
	}
1165
1166
	freeifaddrs(ifap);
1167
	return (used);
1168
}
1169
1170
/*
1171
 * Allocate a client_lease structure and initialize it from the
1172
 * parameters in the specified packet.
1173
 */
1174
struct client_lease *
1175
packet_to_lease(struct in_addr client_addr, struct option_data *options)
1176
{
1177
	char ifname[IF_NAMESIZE];
1178
	struct client_lease *lease;
1179
	char *pretty, *buf;
1180
	int i, sz;
1181
1182
	lease = calloc(1, sizeof(struct client_lease));
1183
	if (!lease) {
1184
		warning("dhcpoffer: no memory to create lease.");
1185
		return (NULL);
1186
	}
1187
1188
	/* Copy the lease options. */
1189
	for (i = 0; i < 256; i++) {
1190
		if (options[i].len == 0)
1191
			continue;
1192
		if (!unknown_ok && strncmp("option-",
1193
		    dhcp_options[i].name, 7) != 0) {
1194
			warning("dhcpoffer: unknown option %d", i);
1195
			lease->is_invalid = 1;
1196
		}
1197
		pretty = pretty_print_option(i, &options[i], 0);
1198
		if (strlen(pretty) == 0)
1199
			continue;
1200
		switch (i) {
1201
		case DHO_DOMAIN_SEARCH:
1202
			/* Must decode the option into text to check names. */
1203
			buf = calloc(1, DHCP_DOMAIN_SEARCH_LEN);
1204
			if (buf == NULL)
1205
				error("No memory to decode domain search");
1206
			sz = pretty_print_domain_search(buf,
1207
			    DHCP_DOMAIN_SEARCH_LEN,
1208
			    options[i].data, options[i].len);
1209
			if (strlen(buf) == 0)
1210
				continue;
1211
			if (sz == -1 || !res_hnok_list(buf))
1212
				warning("Bogus data for option %s",
1213
				    dhcp_options[i].name);
1214
			free(buf);
1215
			break;
1216
		case DHO_DOMAIN_NAME:
1217
			/*
1218
			 * Allow deviant but historically blessed
1219
			 * practice of supplying multiple domain names
1220
			 * with DHO_DOMAIN_NAME. Thus allowing multiple
1221
			 * entries in the resolv.conf 'search' statement.
1222
			 */
1223
			if (!res_hnok_list(pretty)) {
1224
				warning("Bogus data for option %s",
1225
				    dhcp_options[i].name);
1226
				continue;
1227
			}
1228
			break;
1229
		case DHO_HOST_NAME:
1230
		case DHO_NIS_DOMAIN:
1231
			if (!res_hnok(pretty)) {
1232
				warning("Bogus data for option %s",
1233
				    dhcp_options[i].name);
1234
				continue;
1235
			}
1236
			break;
1237
		default:
1238
			break;
1239
		}
1240
		lease->options[i] = options[i];
1241
		options[i].data = NULL;
1242
		options[i].len = 0;
1243
	}
1244
1245
	/*
1246
	 * If this lease doesn't supply a required parameter, blow it off.
1247
	 */
1248
	for (i = 0; i < config->required_option_count; i++) {
1249
		if (!lease->options[config->required_options[i]].len) {
1250
			warning("Missing required parameter %s",
1251
			    dhcp_options[i].name);
1252
			lease->is_invalid = 1;
1253
		}
1254
	}
1255
1256
	/*
1257
	 * If this lease is trying to sell us an address we are already
1258
	 * using, blow it off.
1259
	 */
1260
	lease->address.s_addr = client->packet.yiaddr.s_addr;
1261
	memset(ifname, 0, sizeof(ifname));
1262
	if (addressinuse(lease->address, ifname) &&
1263
	    strncmp(ifname, ifi->name, IF_NAMESIZE) != 0) {
1264
		warning("%s already configured on %s",
1265
		    inet_ntoa(lease->address), ifname);
1266
		lease->is_invalid = 1;
1267
	}
1268
1269
	/* Save the siaddr (a.k.a. next-server) info. */
1270
	lease->next_server.s_addr = client->packet.siaddr.s_addr;
1271
1272
	/* If the server name was filled out, copy it. */
1273
	if ((!lease->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1274
	    !(lease->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1275
	    client->packet.sname[0]) {
1276
		lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1277
		if (!lease->server_name) {
1278
			warning("dhcpoffer: no memory for server name.");
1279
			lease->is_invalid = 1;
1280
		}
1281
		memcpy(lease->server_name, client->packet.sname,
1282
		    DHCP_SNAME_LEN);
1283
		lease->server_name[DHCP_SNAME_LEN] = '\0';
1284
		if (!res_hnok(lease->server_name)) {
1285
			warning("Bogus server name %s", lease->server_name);
1286
			lease->is_invalid = 1;
1287
		}
1288
	}
1289
1290
	/* Ditto for the filename. */
1291
	if ((!lease->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1292
	    !(lease->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1293
	    client->packet.file[0]) {
1294
		/* Don't count on the NUL terminator. */
1295
		lease->filename = malloc(DHCP_FILE_LEN + 1);
1296
		if (!lease->filename) {
1297
			warning("dhcpoffer: no memory for filename.");
1298
			lease->is_invalid = 1;
1299
		}
1300
		memcpy(lease->filename, client->packet.file, DHCP_FILE_LEN);
1301
		lease->filename[DHCP_FILE_LEN] = '\0';
1302
	}
1303
	return lease;
1304
}
1305
1306
void
1307
dhcpnak(struct in_addr client_addr, struct option_data *options, char *info)
1308
{
1309
	if (client->state != S_REBOOTING &&
1310
	    client->state != S_REQUESTING &&
1311
	    client->state != S_RENEWING &&
1312
	    client->state != S_REBINDING) {
1313
#ifdef DEBUG
1314
		debug("Unexpected %s. State #%d", info, client->state);
1315
#endif
1316
		return;
1317
	}
1318
1319
	if (!client->active) {
1320
#ifdef DEBUG
1321
		debug("Unexpected %s. No active lease.", info);
1322
#endif
1323
		return;
1324
	}
1325
1326
	note("%s", info);
1327
1328
	/* XXX Do we really want to remove a NAK'd lease from the database? */
1329
	if (!client->active->is_static) {
1330
		TAILQ_REMOVE(&client->leases, client->active, next);
1331
		free_client_lease(client->active);
1332
	}
1333
1334
	client->active = NULL;
1335
1336
	/* Stop sending DHCPREQUEST packets. */
1337
	cancel_timeout();
1338
1339
	client->state = S_INIT;
1340
	state_init();
1341
}
1342
1343
/*
1344
 * Send out a DHCPDISCOVER packet, and set a timeout to send out another
1345
 * one after the right interval has expired.  If we don't get an offer by
1346
 * the time we reach the panic interval, call the panic function.
1347
 */
1348
void
1349
send_discover(void)
1350
{
1351
	time_t cur_time;
1352
	ssize_t rslt;
1353
	int interval;
1354
1355
	time(&cur_time);
1356
1357
	/* Figure out how long it's been since we started transmitting. */
1358
	interval = cur_time - client->first_sending;
1359
1360
	if (interval > config->timeout) {
1361
		state_panic();
1362
		return;
1363
	}
1364
1365
	/*
1366
	 * If we're supposed to increase the interval, do so.  If it's
1367
	 * currently zero (i.e., we haven't sent any packets yet), set
1368
	 * it to initial_interval; otherwise, add to it a random
1369
	 * number between zero and two times itself.  On average, this
1370
	 * means that it will double with every transmission.
1371
	 */
1372
	if (!client->interval)
1373
		client->interval = config->initial_interval;
1374
	else {
1375
		client->interval += arc4random_uniform(2 * client->interval);
1376
	}
1377
1378
	/* Don't backoff past cutoff. */
1379
	if (client->interval > config->backoff_cutoff)
1380
		client->interval = (config->backoff_cutoff / 2) +
1381
		    arc4random_uniform(config->backoff_cutoff);
1382
1383
	/* If the backoff would take us to the panic timeout, just use that
1384
	   as the interval. */
1385
	if (cur_time + client->interval >
1386
	    client->first_sending + config->timeout)
1387
		client->interval = (client->first_sending +
1388
			 config->timeout) - cur_time + 1;
1389
1390
	/* Record the number of seconds since we started sending. */
1391
	if (interval < UINT16_MAX)
1392
		client->bootrequest_packet.secs = htons(interval);
1393
	else
1394
		client->bootrequest_packet.secs = htons(UINT16_MAX);
1395
	client->secs = client->bootrequest_packet.secs;
1396
1397
	note("DHCPDISCOVER on %s - interval %lld", ifi->name,
1398
	    (long long)client->interval);
1399
1400
	rslt = send_packet(inaddr_any, inaddr_broadcast);
1401
	if (rslt == -1 && errno == EAFNOSUPPORT) {
1402
		warning("dhclient cannot be used on %s", ifi->name);
1403
		quit = INTERNALSIG;
1404
	} else
1405
		set_timeout_interval(client->interval, send_discover);
1406
}
1407
1408
/*
1409
 * Called if we haven't received any offers in a preset amount of time. When
1410
 * this happens, we try to use existing leases that haven't yet expired.
1411
 */
1412
void
1413
state_panic(void)
1414
{
1415
	char ifname[IF_NAMESIZE];
1416
	struct client_lease *lp;
1417
	time_t cur_time;
1418
1419
	time(&cur_time);
1420
	note("No acceptable DHCPOFFERS received.");
1421
1422
	/* Run through the list of leases and see if one can be used. */
1423
	time(&cur_time);
1424
	TAILQ_FOREACH(lp, &client->leases, next) {
1425
		if (addressinuse(lp->address, ifname) &&
1426
		    strncmp(ifname, ifi->name, IF_NAMESIZE) != 0)
1427
			continue;
1428
		if (lp->is_static) {
1429
			set_lease_times(lp);
1430
			note("Trying static lease %s", inet_ntoa(lp->address));
1431
		} else if (lp->expiry <= cur_time) {
1432
			continue;
1433
		} else
1434
			note("Trying recorded lease %s",
1435
			    inet_ntoa(lp->address));
1436
1437
		client->new = lp;
1438
		client->state = S_REQUESTING;
1439
		bind_lease();
1440
1441
		return;
1442
	}
1443
1444
	/*
1445
	 * No leases were available, or what was available didn't work
1446
	 */
1447
	note("No working leases in persistent database - sleeping.");
1448
	client->state = S_INIT;
1449
	set_timeout_interval(config->retry_interval, state_init);
1450
	go_daemon();
1451
}
1452
1453
void
1454
send_request(void)
1455
{
1456
	struct sockaddr_in destination;
1457
	struct in_addr from;
1458
	time_t cur_time;
1459
	int interval;
1460
1461
	time(&cur_time);
1462
1463
	/* Figure out how long it's been since we started transmitting. */
1464
	interval = (int)(cur_time - client->first_sending);
1465
1466
	/*
1467
	 * If we're in the INIT-REBOOT or REQUESTING state and we're
1468
	 * past the reboot timeout, go to INIT and see if we can
1469
	 * DISCOVER an address.
1470
	 *
1471
	 * XXX In the INIT-REBOOT state, if we don't get an ACK, it
1472
	 * means either that we're on a network with no DHCP server,
1473
	 * or that our server is down.  In the latter case, assuming
1474
	 * that there is a backup DHCP server, DHCPDISCOVER will get
1475
	 * us a new address, but we could also have successfully
1476
	 * reused our old address.  In the former case, we're hosed
1477
	 * anyway.  This is not a win-prone situation.
1478
	 */
1479
	if ((client->state == S_REBOOTING ||
1480
	    client->state == S_REQUESTING) &&
1481
	    interval > config->reboot_timeout) {
1482
		client->state = S_INIT;
1483
		cancel_timeout();
1484
		state_init();
1485
		return;
1486
	}
1487
1488
	/*
1489
	 * If the lease has expired, relinquish the address and go back to the
1490
	 * INIT state.
1491
	 */
1492
	if (client->state != S_REQUESTING &&
1493
	    cur_time > client->active->expiry) {
1494
		if (client->active)
1495
			delete_address(client->active->address);
1496
		client->state = S_INIT;
1497
		state_init();
1498
		return;
1499
	}
1500
1501
	/* Do the exponential backoff. */
1502
	if (!client->interval)
1503
		client->interval = config->initial_interval;
1504
	else
1505
		client->interval += arc4random_uniform(2 * client->interval);
1506
1507
	/* Don't backoff past cutoff. */
1508
	if (client->interval > config->backoff_cutoff)
1509
		client->interval = (config->backoff_cutoff / 2) +
1510
		    arc4random_uniform(client->interval);
1511
1512
	/*
1513
	 * If the backoff would take us to the expiry time, just set the
1514
	 * timeout to the expiry time.
1515
	 */
1516
	if (client->state != S_REQUESTING && cur_time + client->interval >
1517
	    client->active->expiry)
1518
		client->interval = client->active->expiry - cur_time + 1;
1519
1520
	/*
1521
	 * If the reboot timeout has expired, or the lease rebind time has
1522
	 * elapsed, or if we're not yet bound, broadcast the DHCPREQUEST rather
1523
	 * than unicasting.
1524
	 */
1525
	memset(&destination, 0, sizeof(destination));
1526
	if (client->state == S_REQUESTING ||
1527
	    client->state == S_REBOOTING ||
1528
	    cur_time > client->active->rebind ||
1529
	    interval > config->reboot_timeout)
1530
		destination.sin_addr.s_addr = INADDR_BROADCAST;
1531
	else
1532
		destination.sin_addr.s_addr = client->destination.s_addr;
1533
1534
	if (client->state != S_REQUESTING)
1535
		from.s_addr = client->active->address.s_addr;
1536
	else
1537
		from.s_addr = INADDR_ANY;
1538
1539
	/* Record the number of seconds since we started sending. */
1540
	if (client->state == S_REQUESTING)
1541
		client->bootrequest_packet.secs = client->secs;
1542
	else {
1543
		if (interval < UINT16_MAX)
1544
			client->bootrequest_packet.secs = htons(interval);
1545
		else
1546
			client->bootrequest_packet.secs = htons(UINT16_MAX);
1547
	}
1548
1549
	note("DHCPREQUEST on %s to %s", ifi->name,
1550
	    inet_ntoa(destination.sin_addr));
1551
1552
	send_packet(from, destination.sin_addr);
1553
1554
	set_timeout_interval(client->interval, send_request);
1555
}
1556
1557
void
1558
send_decline(void)
1559
{
1560
	note("DHCPDECLINE on %s", ifi->name);
1561
1562
	send_packet(inaddr_any, inaddr_broadcast);
1563
}
1564
1565
void
1566
make_discover(struct client_lease *lease)
1567
{
1568
	struct option_data options[256];
1569
	struct dhcp_packet *packet = &client->bootrequest_packet;
1570
	unsigned char discover = DHCPDISCOVER;
1571
	int i;
1572
1573
	memset(options, 0, sizeof(options));
1574
	memset(packet, 0, sizeof(*packet));
1575
1576
	/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1577
	i = DHO_DHCP_MESSAGE_TYPE;
1578
	options[i].data = &discover;
1579
	options[i].len = sizeof(discover);
1580
1581
	/* Request the options we want */
1582
	i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1583
	options[i].data = config->requested_options;
1584
	options[i].len = config->requested_option_count;
1585
1586
	/* If we had an address, try to get it again. */
1587
	if (lease) {
1588
		client->requested_address = lease->address;
1589
		i = DHO_DHCP_REQUESTED_ADDRESS;
1590
		options[i].data = (char *)&lease->address;
1591
		options[i].len = sizeof(lease->address);
1592
	} else
1593
		client->requested_address.s_addr = INADDR_ANY;
1594
1595
	/* Send any options requested in the config file. */
1596
	for (i = 0; i < 256; i++)
1597
		if (!options[i].data &&
1598
		    config->send_options[i].data) {
1599
			options[i].data = config->send_options[i].data;
1600
			options[i].len = config->send_options[i].len;
1601
		}
1602
1603
	/* Set up the option buffer to fit in a minimal UDP packet. */
1604
	i = cons_options(options);
1605
	if (i == -1 || packet->options[i] != DHO_END)
1606
		error("options do not fit in DHCPDISCOVER packet.");
1607
	client->bootrequest_packet_length = DHCP_FIXED_NON_UDP+i+1;
1608
	if (client->bootrequest_packet_length < BOOTP_MIN_LEN)
1609
		client->bootrequest_packet_length = BOOTP_MIN_LEN;
1610
1611
	packet->op = BOOTREQUEST;
1612
	packet->htype = HTYPE_ETHER ;
1613
	packet->hlen = ETHER_ADDR_LEN;
1614
	packet->hops = 0;
1615
	packet->xid = client->xid;
1616
	packet->secs = 0; /* filled in by send_discover. */
1617
	packet->flags = 0;
1618
1619
	packet->ciaddr.s_addr = INADDR_ANY;
1620
	packet->yiaddr.s_addr = INADDR_ANY;
1621
	packet->siaddr.s_addr = INADDR_ANY;
1622
	packet->giaddr.s_addr = INADDR_ANY;
1623
1624
	memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1625
	    ETHER_ADDR_LEN);
1626
}
1627
1628
void
1629
make_request(struct client_lease * lease)
1630
{
1631
	struct option_data options[256];
1632
	struct dhcp_packet *packet = &client->bootrequest_packet;
1633
	unsigned char request = DHCPREQUEST;
1634
	int i;
1635
1636
	memset(options, 0, sizeof(options));
1637
	memset(packet, 0, sizeof(*packet));
1638
1639
	/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1640
	i = DHO_DHCP_MESSAGE_TYPE;
1641
	options[i].data = &request;
1642
	options[i].len = sizeof(request);
1643
1644
	/* Request the options we want */
1645
	i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1646
	options[i].data = config->requested_options;
1647
	options[i].len = config->requested_option_count;
1648
1649
	/*
1650
	 * If we are requesting an address that hasn't yet been assigned
1651
	 * to us, use the DHCP Requested Address option.
1652
	 */
1653
	if (client->state == S_REQUESTING) {
1654
		/* Send back the server identifier. */
1655
		i = DHO_DHCP_SERVER_IDENTIFIER;
1656
		options[i].data = lease->options[i].data;
1657
		options[i].len = lease->options[i].len;
1658
	}
1659
	if (client->state == S_REQUESTING ||
1660
	    client->state == S_REBOOTING) {
1661
		client->requested_address = lease->address;
1662
		i = DHO_DHCP_REQUESTED_ADDRESS;
1663
		options[i].data = (char *)&lease->address.s_addr;
1664
		options[i].len = sizeof(in_addr_t);
1665
	}
1666
1667
	/* Send any options requested in the config file. */
1668
	for (i = 0; i < 256; i++)
1669
		if (!options[i].data && config->send_options[i].data) {
1670
			options[i].data = config->send_options[i].data;
1671
			options[i].len = config->send_options[i].len;
1672
		}
1673
1674
	/* Set up the option buffer to fit in a minimal UDP packet. */
1675
	i = cons_options(options);
1676
	if (i == -1 || packet->options[i] != DHO_END)
1677
		error("options do not fit in DHCPREQUEST packet.");
1678
	client->bootrequest_packet_length = DHCP_FIXED_NON_UDP+i+1;
1679
	if (client->bootrequest_packet_length < BOOTP_MIN_LEN)
1680
		client->bootrequest_packet_length = BOOTP_MIN_LEN;
1681
1682
	packet->op = BOOTREQUEST;
1683
	packet->htype = HTYPE_ETHER ;
1684
	packet->hlen = ETHER_ADDR_LEN;
1685
	packet->hops = 0;
1686
	packet->xid = client->xid;
1687
	packet->secs = 0; /* Filled in by send_request. */
1688
	packet->flags = 0;
1689
1690
	/*
1691
	 * If we own the address we're requesting, put it in ciaddr. Otherwise
1692
	 * set ciaddr to zero.
1693
	 */
1694
	if (client->state == S_BOUND ||
1695
	    client->state == S_RENEWING ||
1696
	    client->state == S_REBINDING)
1697
		packet->ciaddr.s_addr = lease->address.s_addr;
1698
	else
1699
		packet->ciaddr.s_addr = INADDR_ANY;
1700
1701
	packet->yiaddr.s_addr = INADDR_ANY;
1702
	packet->siaddr.s_addr = INADDR_ANY;
1703
	packet->giaddr.s_addr = INADDR_ANY;
1704
1705
	memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1706
	    ETHER_ADDR_LEN);
1707
}
1708
1709
void
1710
make_decline(struct client_lease *lease)
1711
{
1712
	struct option_data options[256];
1713
	struct dhcp_packet *packet = &client->bootrequest_packet;
1714
	unsigned char decline = DHCPDECLINE;
1715
	int i;
1716
1717
	memset(options, 0, sizeof(options));
1718
	memset(packet, 0, sizeof(*packet));
1719
1720
	/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1721
	i = DHO_DHCP_MESSAGE_TYPE;
1722
	options[i].data = &decline;
1723
	options[i].len = sizeof(decline);
1724
1725
	/* Send back the server identifier. */
1726
	i = DHO_DHCP_SERVER_IDENTIFIER;
1727
	options[i].data = lease->options[i].data;
1728
	options[i].len = lease->options[i].len;
1729
1730
	/* Send back the address we're declining. */
1731
	i = DHO_DHCP_REQUESTED_ADDRESS;
1732
	options[i].data = (char *)&lease->address.s_addr;
1733
	options[i].len = sizeof(in_addr_t);
1734
1735
	/* Send the uid if the user supplied one. */
1736
	i = DHO_DHCP_CLIENT_IDENTIFIER;
1737
	if (config->send_options[i].len) {
1738
		options[i].data = config->send_options[i].data;
1739
		options[i].len = config->send_options[i].len;
1740
	}
1741
1742
	/* Set up the option buffer to fit in a minimal UDP packet. */
1743
	i = cons_options(options);
1744
	if (i == -1 || packet->options[i] != DHO_END)
1745
		error("options do not fit in DHCPDECLINE packet.");
1746
	client->bootrequest_packet_length = DHCP_FIXED_NON_UDP+i+1;
1747
	if (client->bootrequest_packet_length < BOOTP_MIN_LEN)
1748
		client->bootrequest_packet_length = BOOTP_MIN_LEN;
1749
1750
	packet->op = BOOTREQUEST;
1751
	packet->htype = HTYPE_ETHER ;
1752
	packet->hlen = ETHER_ADDR_LEN;
1753
	packet->hops = 0;
1754
	packet->xid = client->xid;
1755
	packet->secs = 0; /* Filled in by send_request. */
1756
	packet->flags = 0;
1757
1758
	/* ciaddr must always be zero. */
1759
	packet->ciaddr.s_addr = INADDR_ANY;
1760
	packet->yiaddr.s_addr = INADDR_ANY;
1761
	packet->siaddr.s_addr = INADDR_ANY;
1762
	packet->giaddr.s_addr = INADDR_ANY;
1763
1764
	memcpy(&packet->chaddr, ifi->hw_address.ether_addr_octet,
1765
	    ETHER_ADDR_LEN);
1766
}
1767
1768
void
1769
free_client_lease(struct client_lease *lease)
1770
{
1771
	int i;
1772
1773
	/* Static leases are forever. */
1774
	if (lease->is_static)
1775
		return;
1776
1777
	free(lease->server_name);
1778
	free(lease->filename);
1779
	free(lease->resolv_conf);
1780
	for (i = 0; i < 256; i++)
1781
		free(lease->options[i].data);
1782
1783
	free(lease);
1784
}
1785
1786
void
1787
rewrite_client_leases(void)
1788
{
1789
	struct client_lease *lp;
1790
	char *leasestr;
1791
	time_t cur_time;
1792
1793
	if (!leaseFile)	/* XXX */
1794
		error("lease file not open");
1795
1796
	fflush(leaseFile);
1797
	rewind(leaseFile);
1798
1799
	/*
1800
	 * The leases file is kept in chronological order, with the
1801
	 * most recently bound lease last. When the file was read
1802
	 * leases that were not expired were added to the head of the
1803
	 * TAILQ client->leases as they were read. Therefore write out
1804
	 * the leases in client->leases in reverse order to recreate
1805
	 * the chonological order required.
1806
	 */
1807
	time(&cur_time);
1808
	TAILQ_FOREACH_REVERSE(lp, &client->leases, _leases, next) {
1809
		/* Don't write out static leases from dhclient.conf. */
1810
		if (lp->is_static)
1811
			continue;
1812
		if (lp->expiry <= cur_time)
1813
			continue;
1814
		leasestr = lease_as_string("lease", lp);
1815
		if (leasestr)
1816
			fprintf(leaseFile, "%s", leasestr);
1817
		else
1818
			warning("cannot make lease into string");
1819
	}
1820
1821
	fflush(leaseFile);
1822
	ftruncate(fileno(leaseFile), ftello(leaseFile));
1823
	fsync(fileno(leaseFile));
1824
}
1825
1826
void
1827
rewrite_option_db(struct client_lease *offered, struct client_lease *effective)
1828
{
1829
	u_int8_t db[8192];
1830
	char *leasestr;
1831
	size_t n;
1832
1833
	if (strlen(path_option_db) == 0)
1834
		return;
1835
1836
	memset(db, 0, sizeof(db));
1837
1838
	leasestr = lease_as_string("offered", offered);
1839
	if (leasestr) {
1840
		n = strlcat(db, leasestr, sizeof(db));
1841
		if (n >= sizeof(db))
1842
			warning("cannot fit offered lease into option db");
1843
	} else
1844
		warning("cannot make offered lease into string");
1845
1846
	leasestr = lease_as_string("effective", effective);
1847
	if (leasestr) {
1848
		n = strlcat(db, leasestr, sizeof(db));
1849
		if (n >= sizeof(db))
1850
			warning("cannot fit effective lease into option db");
1851
	} else
1852
		warning("cannot make effective lease into string");
1853
1854
	write_option_db(db, strlen(db));
1855
}
1856
1857
char *
1858
lease_as_string(char *type, struct client_lease *lease)
1859
{
1860
	static char leasestr[8192];
1861
	struct option_data *opt;
1862
	char *p;
1863
	size_t sz, rsltsz;
1864
	int i, rslt;
1865
1866
	sz = sizeof(leasestr);
1867
	p = leasestr;
1868
	memset(p, 0, sz);
1869
1870
	rslt = snprintf(p, sz, "%s {\n"
1871
	    "%s  interface \"%s\";\n  fixed-address %s;\n",
1872
	    type, (lease->is_bootp) ? "  bootp;\n" : "", ifi->name,
1873
	    inet_ntoa(lease->address));
1874
	if (rslt == -1 || rslt >= sz)
1875
		return (NULL);
1876
	p += rslt;
1877
	sz -= rslt;
1878
1879
	rslt = snprintf(p, sz, "  next-server %s;\n",
1880
	    inet_ntoa(lease->next_server));
1881
	if (rslt == -1 || rslt >= sz)
1882
		return (NULL);
1883
	p += rslt;
1884
	sz -= rslt;
1885
1886
	if (lease->filename) {
1887
		rslt = snprintf(p, sz, "  filename ");
1888
		if (rslt == -1 || rslt >= sz)
1889
			return (NULL);
1890
		p += rslt;
1891
		sz -= rslt;
1892
		rslt = pretty_print_string(p, sz, lease->filename,
1893
		    strlen(lease->filename), 1);
1894
		if (rslt == -1 || rslt >= sz)
1895
			return (NULL);
1896
		p += rslt;
1897
		sz -= rslt;
1898
		rslt = snprintf(p, sz, ";\n");
1899
		if (rslt == -1 || rslt >= sz)
1900
			return (NULL);
1901
		p += rslt;
1902
		sz -= rslt;
1903
	}
1904
	if (lease->server_name) {
1905
		rslt = snprintf(p, sz, "  server-name ");
1906
		if (rslt == -1 || rslt >= sz)
1907
			return (NULL);
1908
		p += rslt;
1909
		sz -= rslt;
1910
		rslt = pretty_print_string(p, sz, lease->server_name,
1911
		    strlen(lease->server_name), 1);
1912
		if (rslt == -1 || rslt >= sz)
1913
			return (NULL);
1914
		p += rslt;
1915
		sz -= rslt;
1916
		rslt = snprintf(p, sz, ";\n");
1917
		if (rslt == -1 || rslt >= sz)
1918
			return (NULL);
1919
		p += rslt;
1920
		sz -= rslt;
1921
	}
1922
1923
	for (i = 0; i < 256; i++) {
1924
		if (i == DHO_DHCP_CLIENT_IDENTIFIER) {
1925
			/* Ignore any CLIENT_IDENTIFIER from server. */
1926
			opt = &config->send_options[i];
1927
		} else if (lease->options[i].len)
1928
			opt = &lease->options[i];
1929
		else
1930
			continue;
1931
1932
		rslt = snprintf(p, sz, "  option %s %s;\n",
1933
		    dhcp_options[i].name, pretty_print_option(i, opt,  1));
1934
		if (rslt == -1 || rslt >= sz)
1935
			return (NULL);
1936
		p += rslt;
1937
		sz -= rslt;
1938
	}
1939
1940
	rsltsz = strftime(p, sz, "  renew " DB_TIMEFMT ";\n",
1941
	    gmtime(&lease->renewal));
1942
	if (rsltsz == 0)
1943
		return (NULL);
1944
	p += rsltsz;
1945
	sz -= rsltsz;
1946
	rsltsz = strftime(p, sz, "  rebind " DB_TIMEFMT ";\n",
1947
	    gmtime(&lease->rebind));
1948
	if (rsltsz == 0)
1949
		return (NULL);
1950
	p += rsltsz;
1951
	sz -= rsltsz;
1952
	rsltsz = strftime(p, sz, "  expire " DB_TIMEFMT ";\n",
1953
	    gmtime(&lease->expiry));
1954
	if (rsltsz == 0)
1955
		return (NULL);
1956
	p += rsltsz;
1957
	sz -= rsltsz;
1958
	rslt = snprintf(p, sz, "}\n");
1959
	if (rslt == -1 || rslt >= sz)
1960
		return (NULL);
1961
1962
	return (leasestr);
1963
}
1964
1965
void
1966
go_daemon(void)
1967
{
1968
	static int state = 0;
1969
1970
	if (no_daemon || state)
1971
		return;
1972
1973
	state = 1;
1974
1975
	/* Stop logging to stderr. */
1976
	log_perror = 0;
1977
1978
	if (daemon(1, 0) == -1)
1979
		error("daemon");
1980
1981
	/* we are chrooted, daemon(3) fails to open /dev/null */
1982
	if (nullfd != -1) {
1983
		dup2(nullfd, STDIN_FILENO);
1984
		dup2(nullfd, STDOUT_FILENO);
1985
		dup2(nullfd, STDERR_FILENO);
1986
		close(nullfd);
1987
		nullfd = -1;
1988
	}
1989
1990
	/* Catch stuff that might be trying to terminate the program. */
1991
	signal(SIGHUP, sighdlr);
1992
	signal(SIGINT, sighdlr);
1993
	signal(SIGTERM, sighdlr);
1994
	signal(SIGUSR1, sighdlr);
1995
	signal(SIGUSR2, sighdlr);
1996
1997
	signal(SIGPIPE, SIG_IGN);
1998
}
1999
2000
int
2001
res_hnok(const char *name)
2002
{
2003
	const char *dn = name;
2004
	int pch = '.', ch = (unsigned char)*dn++;
2005
	int warn = 0;
2006
2007
	while (ch != '\0') {
2008
		int nch = (unsigned char)*dn++;
2009
2010
		if (ch == '.') {
2011
			;
2012
		} else if (pch == '.' || nch == '.' || nch == '\0') {
2013
			if (!isalnum(ch))
2014
				return (0);
2015
		} else if (!isalnum(ch) && ch != '-' && ch != '_')
2016
				return (0);
2017
		else if (ch == '_' && warn == 0) {
2018
			warning("warning: hostname %s contains an "
2019
			    "underscore which violates RFC 952", name);
2020
			warn++;
2021
		}
2022
		pch = ch, ch = nch;
2023
	}
2024
	return (1);
2025
}
2026
2027
/*
2028
 * resolv_conf(5) says a max of DHCP_DOMAIN_SEARCH_CNT domains and total
2029
 * length of DHCP_DOMAIN_SEARCH_LEN bytes are acceptable for the 'search'
2030
 * statement.
2031
 */
2032
int
2033
res_hnok_list(const char *names)
2034
{
2035
	char *dupnames, *hn, *inputstring;
2036
	int count;
2037
2038
	if (strlen(names) >= DHCP_DOMAIN_SEARCH_LEN)
2039
		return (0);
2040
2041
	dupnames = inputstring = strdup(names);
2042
	if (inputstring == NULL)
2043
		error("Cannot copy domain name list");
2044
2045
	count = 0;
2046
	while ((hn = strsep(&inputstring, " \t")) != NULL) {
2047
		if (strlen(hn) == 0)
2048
			continue;
2049
		if (res_hnok(hn) == 0)
2050
			break;
2051
		count++;
2052
		if (count > DHCP_DOMAIN_SEARCH_CNT)
2053
			break;
2054
	}
2055
2056
	free(dupnames);
2057
2058
	return (count > 0 && count < 7 && hn == NULL);
2059
}
2060
2061
void
2062
fork_privchld(int fd, int fd2)
2063
{
2064
	struct imsg_hup imsg;
2065
	struct pollfd pfd[1];
2066
	struct imsgbuf *priv_ibuf;
2067
	ssize_t n;
2068
	int nfds, rslt;
2069
2070
	switch (fork()) {
2071
	case -1:
2072
		error("cannot fork");
2073
		break;
2074
	case 0:
2075
		break;
2076
	default:
2077
		return;
2078
	}
2079
2080
	if (chdir("/") == -1)
2081
		error("chdir(\"/\")");
2082
2083
	setproctitle("%s [priv]", ifi->name);
2084
2085
	go_daemon();
2086
2087
	close(fd2);
2088
2089
	if ((priv_ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
2090
		error("no memory for priv_ibuf");
2091
2092
	imsg_init(priv_ibuf, fd);
2093
2094
	while (quit == 0) {
2095
		pfd[0].fd = priv_ibuf->fd;
2096
		pfd[0].events = POLLIN;
2097
		if ((nfds = poll(pfd, 1, INFTIM)) == -1) {
2098
			if (errno != EINTR) {
2099
				warning("poll error: %s", strerror(errno));
2100
				quit = INTERNALSIG;
2101
			}
2102
			continue;
2103
		}
2104
2105
		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2106
			continue;
2107
2108
		if ((n = imsg_read(priv_ibuf)) == -1 && errno != EAGAIN) {
2109
			warning("imsg_read(priv_ibuf): %s", strerror(errno));
2110
			quit = INTERNALSIG;
2111
			continue;
2112
		}
2113
2114
		if (n == 0) {
2115
			/* Connection closed -- other end should log message. */
2116
			quit = INTERNALSIG;
2117
			continue;
2118
		}
2119
2120
		dispatch_imsg(priv_ibuf);
2121
	}
2122
2123
	imsg_clear(priv_ibuf);
2124
	close(fd);
2125
2126
	if (strlen(path_option_db)) {
2127
		/* Truncate the file so monitoring process see exit. */
2128
		rslt = truncate(path_option_db, 0);
2129
		if (rslt == -1)
2130
			warning("Unable to truncate '%s': %s", path_option_db,
2131
			    strerror(errno));
2132
	}
2133
2134
	/*
2135
	 * SIGTERM is used by system at shut down. Be nice and don't cleanup
2136
	 * routes, possibly preventing NFS from properly shutting down.
2137
	 */
2138
	if (quit != SIGTERM) {
2139
		memset(&imsg, 0, sizeof(imsg));
2140
		imsg.addr = active_addr;
2141
		priv_cleanup(&imsg);
2142
	}
2143
2144
	if (quit == SIGHUP) {
2145
		if (!(ifi->flags & IFI_HUP) &&
2146
		   (!(ifi->flags & IFI_NEW_LLADDR)))
2147
			warning("%s; restarting.", strsignal(quit));
2148
		signal(SIGHUP, SIG_IGN); /* will be restored after exec */
2149
		execvp(saved_argv[0], saved_argv);
2150
		error("RESTART FAILED: '%s': %s", saved_argv[0],
2151
		    strerror(errno));
2152
	}
2153
2154
	if (quit != INTERNALSIG)
2155
		warning("%s; exiting", strsignal(quit));
2156
2157
	exit(1);
2158
}
2159
2160
void
2161
get_ifname(char *arg)
2162
{
2163
	struct ifgroupreq ifgr;
2164
	struct ifg_req *ifg;
2165
	int s, len;
2166
2167
	if (strcmp(arg, "egress") == 0) {
2168
		s = socket(AF_INET, SOCK_DGRAM, 0);
2169
		if (s == -1)
2170
			error("socket error");
2171
		memset(&ifgr, 0, sizeof(ifgr));
2172
		strlcpy(ifgr.ifgr_name, "egress", sizeof(ifgr.ifgr_name));
2173
		if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
2174
			if (errno == ENOENT)
2175
				error("no interface in group egress found");
2176
			error("ioctl SIOCGIFGMEMB: %s", strerror(errno));
2177
		}
2178
		len = ifgr.ifgr_len;
2179
		if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
2180
			error("get_ifname");
2181
		if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
2182
			error("ioctl SIOCGIFGMEMB: %s", strerror(errno));
2183
2184
		arg = NULL;
2185
		for (ifg = ifgr.ifgr_groups;
2186
		    ifg && len >= sizeof(struct ifg_req); ifg++) {
2187
			len -= sizeof(struct ifg_req);
2188
			if (arg)
2189
				error("too many interfaces in group egress");
2190
			arg = ifg->ifgrq_member;
2191
		}
2192
2193
		if (strlcpy(ifi->name, arg, IFNAMSIZ) >= IFNAMSIZ)
2194
			error("Interface name too long: %s", strerror(errno));
2195
2196
		free(ifgr.ifgr_groups);
2197
		close(s);
2198
	} else if (strlcpy(ifi->name, arg, IFNAMSIZ) >= IFNAMSIZ)
2199
		error("Interface name too long");
2200
}
2201
2202
/*
2203
 * Update resolv.conf.
2204
 */
2205
char *
2206
resolv_conf_contents(struct option_data  *domainname,
2207
    struct option_data *nameservers, struct option_data *domainsearch)
2208
{
2209
	char *dn, *ns, *nss[MAXNS], *contents, *courtesy, *p, *buf;
2210
	size_t len;
2211
	int i, rslt, sz;
2212
2213
	memset(nss, 0, sizeof(nss));
2214
2215
	if (domainsearch->len) {
2216
		buf = calloc(1, DHCP_DOMAIN_SEARCH_LEN);
2217
		if (buf == NULL)
2218
			error("No memory to decode domain search");
2219
		sz = pretty_print_domain_search(buf, DHCP_DOMAIN_SEARCH_LEN,
2220
		    domainsearch->data, domainsearch->len);
2221
		if (sz == -1)
2222
			dn = strdup("");
2223
		else {
2224
			rslt = asprintf(&dn, "search %s\n", buf);
2225
			if (rslt == -1)
2226
				dn = NULL;
2227
		}
2228
		free(buf);
2229
	} else if (domainname->len) {
2230
		rslt = asprintf(&dn, "search %s\n",
2231
		    pretty_print_option(DHO_DOMAIN_NAME, domainname, 0));
2232
		if (rslt == -1)
2233
			dn = NULL;
2234
	} else
2235
		dn = strdup("");
2236
	if (dn == NULL)
2237
		error("no memory for domainname");
2238
2239
	if (nameservers->len) {
2240
		ns = pretty_print_option(DHO_DOMAIN_NAME_SERVERS, nameservers,
2241
		    0);
2242
		for (i = 0; i < MAXNS; i++) {
2243
			p = strsep(&ns, " ");
2244
			if (p == NULL)
2245
				break;
2246
			if (*p == '\0')
2247
				continue;
2248
			rslt = asprintf(&nss[i], "nameserver %s\n", p);
2249
			if (rslt == -1)
2250
				error("no memory for nameserver");
2251
		}
2252
	}
2253
2254
	len = strlen(dn);
2255
	for (i = 0; i < MAXNS; i++)
2256
		if (nss[i])
2257
			len += strlen(nss[i]);
2258
2259
	if (len > 0 && config->resolv_tail)
2260
		len += strlen(config->resolv_tail);
2261
2262
	if (len == 0) {
2263
		free(dn);
2264
		return (NULL);
2265
	}
2266
2267
	rslt = asprintf(&courtesy, "# Generated by %s dhclient\n", ifi->name);
2268
	if (rslt == -1)
2269
		error("no memory for courtesy line");
2270
	len += strlen(courtesy);
2271
2272
	len++; /* Need room for terminating NUL. */
2273
	contents = calloc(1, len);
2274
	if (contents == NULL)
2275
		error("no memory for resolv.conf contents");
2276
2277
	strlcat(contents, courtesy, len);
2278
	free(courtesy);
2279
2280
	strlcat(contents, dn, len);
2281
	free(dn);
2282
2283
	for (i = 0; i < MAXNS; i++) {
2284
		if (nss[i]) {
2285
			strlcat(contents, nss[i], len);
2286
			free(nss[i]);
2287
		}
2288
	}
2289
2290
	if (config->resolv_tail)
2291
		strlcat(contents, config->resolv_tail, len);
2292
2293
	return (contents);
2294
}
2295
2296
struct client_lease *
2297
apply_defaults(struct client_lease *lease)
2298
{
2299
	struct client_lease *newlease;
2300
	int i, j;
2301
2302
	newlease = clone_lease(lease);
2303
	if (newlease == NULL)
2304
		error("Unable to clone lease");
2305
2306
	if (config->filename) {
2307
		free(newlease->filename);
2308
		newlease->filename = strdup(config->filename);
2309
	}
2310
	if (config->server_name) {
2311
		free(newlease->server_name);
2312
		newlease->server_name = strdup(config->server_name);
2313
	}
2314
	if (config->address.s_addr != INADDR_ANY)
2315
		newlease->address.s_addr = config->address.s_addr;
2316
	if (config->next_server.s_addr != INADDR_ANY)
2317
		newlease->next_server.s_addr = config->next_server.s_addr;
2318
2319
	for (i = 0; i < 256; i++) {
2320
		for (j = 0; j < config->ignored_option_count; j++) {
2321
			if (config->ignored_options[j] == i) {
2322
				free(newlease->options[i].data);
2323
				newlease->options[i].data = NULL;
2324
				newlease->options[i].len = 0;
2325
				break;
2326
			}
2327
		}
2328
		if (j < config->ignored_option_count)
2329
			continue;
2330
2331
		switch (config->default_actions[i]) {
2332
		case ACTION_SUPERSEDE:
2333
			free(newlease->options[i].data);
2334
			newlease->options[i].len = config->defaults[i].len;
2335
			newlease->options[i].data = calloc(1,
2336
			    config->defaults[i].len);
2337
			if (newlease->options[i].data == NULL)
2338
				goto cleanup;
2339
			memcpy(newlease->options[i].data,
2340
			    config->defaults[i].data, config->defaults[i].len);
2341
			break;
2342
2343
		case ACTION_PREPEND:
2344
			free(newlease->options[i].data);
2345
			newlease->options[i].len = config->defaults[i].len +
2346
			    lease->options[i].len;
2347
			newlease->options[i].data = calloc(1,
2348
			    newlease->options[i].len);
2349
			if (newlease->options[i].data == NULL)
2350
				goto cleanup;
2351
			memcpy(newlease->options[i].data,
2352
			    config->defaults[i].data, config->defaults[i].len);
2353
			memcpy(newlease->options[i].data +
2354
			    config->defaults[i].len, lease->options[i].data,
2355
			    lease->options[i].len);
2356
			break;
2357
2358
		case ACTION_APPEND:
2359
			free(newlease->options[i].data);
2360
			newlease->options[i].len = config->defaults[i].len +
2361
			    lease->options[i].len;
2362
			newlease->options[i].data = calloc(1,
2363
			    newlease->options[i].len);
2364
			if (newlease->options[i].data == NULL)
2365
				goto cleanup;
2366
			memcpy(newlease->options[i].data,
2367
			    lease->options[i].data, lease->options[i].len);
2368
			memcpy(newlease->options[i].data +
2369
			    lease->options[i].len, config->defaults[i].data,
2370
			    config->defaults[i].len);
2371
			break;
2372
2373
		case ACTION_DEFAULT:
2374
			if ((newlease->options[i].len == 0) &&
2375
			    (config->defaults[i].len != 0)) {
2376
				newlease->options[i].len =
2377
				    config->defaults[i].len;
2378
				newlease->options[i].data = calloc(1,
2379
				    config->defaults[i].len);
2380
				if (newlease->options[i].data == NULL)
2381
					goto cleanup;
2382
				memcpy(newlease->options[i].data,
2383
				    config->defaults[i].data,
2384
				    config->defaults[i].len);
2385
			}
2386
			break;
2387
2388
		default:
2389
			break;
2390
		}
2391
	}
2392
2393
	return (newlease);
2394
2395
cleanup:
2396
	if (newlease) {
2397
		newlease->is_static = 0;
2398
		free_client_lease(newlease);
2399
	}
2400
2401
	error("Unable to apply defaults");
2402
	/* NOTREACHED */
2403
2404
	return (NULL);
2405
}
2406
2407
struct client_lease *
2408
clone_lease(struct client_lease *oldlease)
2409
{
2410
	struct client_lease *newlease;
2411
	int i;
2412
2413
	newlease = calloc(1, sizeof(struct client_lease));
2414
	if (newlease == NULL)
2415
		goto cleanup;
2416
2417
	newlease->expiry = oldlease->expiry;
2418
	newlease->renewal = oldlease->renewal;
2419
	newlease->rebind = oldlease->rebind;
2420
	newlease->is_static = oldlease->is_static;
2421
	newlease->is_bootp = oldlease->is_bootp;
2422
	newlease->address = oldlease->address;
2423
	newlease->next_server = oldlease->next_server;
2424
2425
	if (oldlease->server_name) {
2426
		newlease->server_name = strdup(oldlease->server_name);
2427
		if (newlease->server_name == NULL)
2428
			goto cleanup;
2429
	}
2430
	if (oldlease->filename) {
2431
		newlease->filename = strdup(oldlease->filename);
2432
		if (newlease->filename == NULL)
2433
			goto cleanup;
2434
	}
2435
	if (oldlease->resolv_conf) {
2436
		newlease->resolv_conf = strdup(oldlease->resolv_conf);
2437
		if (newlease->resolv_conf == NULL)
2438
			goto cleanup;
2439
	}
2440
2441
	for (i = 0; i < 256; i++) {
2442
		if (oldlease->options[i].len == 0)
2443
			continue;
2444
		newlease->options[i].len = oldlease->options[i].len;
2445
		newlease->options[i].data = calloc(1, newlease->options[i].len);
2446
		if (newlease->options[i].data == NULL)
2447
			goto cleanup;
2448
		memcpy(newlease->options[i].data, oldlease->options[i].data,
2449
		    newlease->options[i].len);
2450
	}
2451
2452
	return (newlease);
2453
2454
cleanup:
2455
	if (newlease) {
2456
		newlease->is_static = 0;
2457
		free_client_lease(newlease);
2458
	}
2459
2460
	return (NULL);
2461
}
2462
2463
/*
2464
 * Apply the list of options to be ignored that was provided on the
2465
 * command line. This will override any ignore list obtained from
2466
 * dhclient.conf.
2467
 */
2468
void
2469
apply_ignore_list(char *ignore_list)
2470
{
2471
	u_int8_t list[256];
2472
	char *p;
2473
	int ix, i, j;
2474
2475
	memset(list, 0, sizeof(list));
2476
	ix = 0;
2477
2478
	for (p = strsep(&ignore_list, ", "); p != NULL;
2479
	    p = strsep(&ignore_list, ", ")) {
2480
		if (*p == '\0')
2481
			continue;
2482
2483
		for (i = 1; i < DHO_END; i++)
2484
			if (!strcasecmp(dhcp_options[i].name, p))
2485
				break;
2486
2487
		if (i == DHO_END) {
2488
			note("Invalid option name: '%s'", p);
2489
			return;
2490
		}
2491
2492
		/* Avoid storing duplicate options in the list. */
2493
		for (j = 0; j < ix && list[j] != i; j++)
2494
			;
2495
		if (j == ix)
2496
			list[ix++] = i;
2497
	}
2498
2499
	config->ignored_option_count = ix;
2500
	memcpy(config->ignored_options, list, sizeof(config->ignored_options));
2501
}
2502
2503
void
2504
write_resolv_conf(u_int8_t *contents, size_t sz)
2505
{
2506
	int rslt;
2507
2508
	rslt = imsg_compose(unpriv_ibuf, IMSG_WRITE_RESOLV_CONF,
2509
	    0, 0, -1, contents, sz);
2510
	if (rslt == -1)
2511
		warning("write_resolv_conf: imsg_compose: %s", strerror(errno));
2512
2513
	flush_unpriv_ibuf("write_resolv_conf");
2514
}
2515
2516
void
2517
write_option_db(u_int8_t *contents, size_t sz)
2518
{
2519
	int rslt;
2520
2521
	rslt = imsg_compose(unpriv_ibuf, IMSG_WRITE_OPTION_DB,
2522
	    0, 0, -1, contents, sz);
2523
	if (rslt == -1)
2524
		warning("write_option_db: imsg_compose: %s", strerror(errno));
2525
2526
	flush_unpriv_ibuf("write_option_db");
2527
}
2528
2529
void
2530
priv_write_resolv_conf(struct imsg *imsg)
2531
{
2532
	u_int8_t *contents;
2533
	size_t sz;
2534
2535
	if (imsg->hdr.len < IMSG_HEADER_SIZE) {
2536
		warning("short IMSG_WRITE_RESOLV_CONF");
2537
		return;
2538
	}
2539
2540
	if (!resolv_conf_priority())
2541
		return;
2542
2543
	contents = imsg->data;
2544
	sz = imsg->hdr.len - IMSG_HEADER_SIZE;
2545
2546
	priv_write_file("/etc/resolv.conf",
2547
	    O_WRONLY | O_CREAT | O_TRUNC,
2548
	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, contents, sz);
2549
}
2550
2551
void
2552
priv_write_option_db(struct imsg *imsg)
2553
{
2554
	u_int8_t *contents;
2555
	size_t sz;
2556
2557
	if (imsg->hdr.len < IMSG_HEADER_SIZE) {
2558
		warning("short IMSG_WRITE_OPTION_DB");
2559
		return;
2560
	}
2561
2562
	contents = imsg->data;
2563
	sz = imsg->hdr.len - IMSG_HEADER_SIZE;
2564
2565
	priv_write_file(path_option_db,
2566
	    O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW,
2567
	    S_IRUSR | S_IWUSR | S_IRGRP, contents, sz);
2568
}
2569
2570
void
2571
priv_write_file(char *path, int flags, mode_t mode,
2572
    u_int8_t *contents, size_t sz)
2573
{
2574
	ssize_t n;
2575
	int fd;
2576
2577
	fd = open(path, flags, mode);
2578
	if (fd == -1) {
2579
		note("Couldn't open '%s': %s", path, strerror(errno));
2580
		return;
2581
	}
2582
2583
	n = write(fd, contents, sz);
2584
	if (n == -1)
2585
		note("Couldn't write contents to '%s': %s", path,
2586
		    strerror(errno));
2587
	else if (n < sz)
2588
		note("Short contents write to '%s' (%zd vs %zu)", path,
2589
		    n, sz);
2590
2591
	if (fchown(fd, 0, 0) == -1)
2592
		note("fchown(fd, %d, %d) of '%s' failed (%s)",
2593
		    0, 0, path, strerror(errno));
2594
	if (fchmod(fd, mode) == -1)
2595
		note("fchmod(fd, 0x%x) of '%s' failed (%s)", mode,
2596
		    path, strerror(errno));
2597
2598
	close(fd);
2599
}
2600
2601
/*
2602
 * add_direct_route is the equivalent of
2603
 *
2604
 *     route add -net $dest -netmask $mask -cloning -iface $iface
2605
 */
2606
void
2607
add_direct_route(struct in_addr dest, struct in_addr mask, struct in_addr iface)
2608
{
2609
	struct in_addr ifa = { INADDR_ANY };
2610
2611
	add_route(dest, mask, iface, ifa,
2612
	    RTA_DST | RTA_NETMASK | RTA_GATEWAY, RTF_CLONING | RTF_STATIC);
2613
}
2614
2615
/*
2616
 * add_default_route is the equivalent of
2617
 *
2618
 *	route -q $rdomain add default -iface $router
2619
 *
2620
 *	or
2621
 *
2622
 *	route -q $rdomain add default $router
2623
 */
2624
void
2625
add_default_route(struct in_addr addr, struct in_addr gateway)
2626
{
2627
	struct in_addr netmask, dest;
2628
	int addrs, flags;
2629
2630
	memset(&netmask, 0, sizeof(netmask));
2631
	memset(&dest, 0, sizeof(dest));
2632
	addrs = RTA_DST | RTA_NETMASK;
2633
	flags = 0;
2634
2635
	/*
2636
	 * When 'addr' and 'gateway' are identical the desired behaviour is
2637
	 * to emulate the '-iface' variant of 'route'. This is done by
2638
	 * claiming there is no gateway address to use.
2639
	 */
2640
	if (memcmp(&gateway, &addr, sizeof(addr)) != 0) {
2641
		addrs |= RTA_GATEWAY | RTA_IFA;
2642
		flags |= RTF_GATEWAY | RTF_STATIC;
2643
	}
2644
2645
	add_route(dest, netmask, gateway, addr, addrs, flags);
2646
}
2647
2648
void
2649
add_static_routes(struct option_data *static_routes, struct in_addr iface)
2650
{
2651
	struct in_addr		 dest, netmask, gateway;
2652
	struct in_addr		 *addr;
2653
	int			 i;
2654
2655
	netmask.s_addr = INADDR_ANY;	/* Not used for CLASSFULL! */
2656
2657
	for (i = 0; (i + 2*sizeof(*addr)) <= static_routes->len;
2658
	    i += 2*sizeof(*addr)) {
2659
		addr = (struct in_addr *)&static_routes->data[i];
2660
		if (addr->s_addr == INADDR_ANY)
2661
			continue; /* RFC 2132 says 0.0.0.0 is not allowed. */
2662
2663
		dest.s_addr = addr->s_addr;
2664
		gateway.s_addr = (addr+1)->s_addr;
2665
2666
		/* XXX Order implies priority but we're ignoring that. */
2667
		add_route(dest, netmask, gateway, iface,
2668
		    RTA_DST | RTA_GATEWAY | RTA_IFA, RTF_GATEWAY | RTF_STATIC);
2669
	}
2670
}
2671
2672
void
2673
add_classless_static_routes(struct option_data *opt, struct in_addr iface)
2674
{
2675
	struct in_addr	 dest, netmask, gateway;
2676
	int		 bits, bytes, i;
2677
2678
	i = 0;
2679
	while (i < opt->len) {
2680
		bits = opt->data[i++];
2681
		bytes = (bits + 7) / 8;
2682
2683
		if (bytes > sizeof(netmask))
2684
			return;
2685
		else if (i + bytes > opt->len)
2686
			return;
2687
2688
		if (bits)
2689
			netmask.s_addr = htonl(0xffffffff << (32 - bits));
2690
		else
2691
			netmask.s_addr = INADDR_ANY;
2692
2693
		memcpy(&dest, &opt->data[i], bytes);
2694
		dest.s_addr = dest.s_addr & netmask.s_addr;
2695
		i += bytes;
2696
2697
		if (i + sizeof(gateway) > opt->len)
2698
			return;
2699
		memcpy(&gateway, &opt->data[i], sizeof(gateway));
2700
		i += sizeof(gateway);
2701
2702
		if (gateway.s_addr == INADDR_ANY)
2703
			add_direct_route(dest, netmask, iface);
2704
		else
2705
			add_route(dest, netmask, gateway, iface,
2706
			    RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFA,
2707
			    RTF_GATEWAY | RTF_STATIC);
2708
	}
2709
}
2710
2711
int
2712
compare_lease(struct client_lease *active, struct client_lease *new)
2713
{
2714
	int i;
2715
2716
	if (active == new)
2717
		return (0);
2718
2719
	if (!new || !active)
2720
		return (1);
2721
2722
	if (active->address.s_addr != new->address.s_addr ||
2723
	    active->is_static != new->is_static ||
2724
	    active->is_bootp != new->is_bootp)
2725
		return (1);
2726
2727
	if (active->server_name != new->server_name) {
2728
		if (!active->server_name || !new->server_name)
2729
			return (1);
2730
		if (strcmp(active->server_name, new->server_name) != 0)
2731
			return (1);
2732
	}
2733
2734
	if (active->filename != new->filename) {
2735
		if (!active->filename || !new->filename)
2736
			return (1);
2737
		if (strcmp(active->filename, new->filename) != 0)
2738
			return (1);
2739
	}
2740
2741
	for (i = 0; i < 256; i++) {
2742
		if (active->options[i].len != new->options[i].len)
2743
			return (1);
2744
		if (memcmp(active->options[i].data, new->options[i].data,
2745
		    active->options[i].len))
2746
			return (1);
2747
	}
2748
2749
	return (0);
2750
}
2751
2752
void
2753
set_lease_times(struct client_lease *lease)
2754
{
2755
	time_t cur_time, time_max;
2756
	u_int32_t uint32val;
2757
2758
	time(&cur_time);
2759
2760
	time_max = LLONG_MAX - cur_time;
2761
	if (time_max > UINT32_MAX)
2762
		time_max = UINT32_MAX;
2763
2764
	/*
2765
	 * Take the server-provided times if available.  Otherwise
2766
	 * figure them out according to the spec.
2767
	 *
2768
	 * expiry  == time to discard lease.
2769
	 * renewal == time to renew lease from server that provided it.
2770
	 * rebind  == time to renew lease from any server.
2771
	 *
2772
	 * 0 <= renewal <= rebind <= expiry <= time_max
2773
	 * &&
2774
	 * expiry >= MIN(time_max, 60)
2775
	 */
2776
2777
	lease->expiry = 43200;	/* Default to 12 hours */
2778
	if (lease->options[DHO_DHCP_LEASE_TIME].len == sizeof(uint32val)) {
2779
		memcpy(&uint32val, lease->options[DHO_DHCP_LEASE_TIME].data,
2780
		    sizeof(uint32val));
2781
		lease->expiry = ntohl(uint32val);
2782
		if (lease->expiry < 60)
2783
			lease->expiry = 60;
2784
	}
2785
	if (lease->expiry > time_max)
2786
		lease->expiry = time_max;
2787
2788
	lease->renewal = lease->expiry / 2;
2789
	if (lease->options[DHO_DHCP_RENEWAL_TIME].len == sizeof(uint32val)) {
2790
		memcpy(&uint32val, lease->options[DHO_DHCP_RENEWAL_TIME].data,
2791
		    sizeof(uint32val));
2792
		lease->renewal = ntohl(uint32val);
2793
		if (lease->renewal > lease->expiry)
2794
			lease->renewal = lease->expiry;
2795
	}
2796
2797
	lease->rebind = (lease->expiry * 7) / 8;
2798
	if (lease->options[DHO_DHCP_REBINDING_TIME].len == sizeof(uint32val)) {
2799
		memcpy(&uint32val, lease->options[DHO_DHCP_REBINDING_TIME].data,
2800
		    sizeof(uint32val));
2801
		lease->rebind = ntohl(uint32val);
2802
		if (lease->rebind > lease->expiry)
2803
			lease->rebind = lease->expiry;
2804
	}
2805
	if (lease->rebind < lease->renewal)
2806
		lease->rebind = lease->renewal;
2807
2808
	/* Convert lease lengths to times. */
2809
	lease->expiry += cur_time;
2810
	lease->renewal += cur_time;
2811
	lease->rebind += cur_time;
2812
}