Project

General

Profile

Feature #7416 ยป dhclient.c

Fabian Kurtz, 03/21/2017 08:53 AM

 
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
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 *
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
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
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
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
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
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
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
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
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
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
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
/* Start of the updated section. */
856
	if (ip->client->config->default_actions[DHO_DHCP_SERVER_IDENTIFIER] == ACTION_SUPERSEDE) {
857
		memcpy(ip->client->destination.iabuf, ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
858
		ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].len = 4;
859
	} else if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
860
		memcpy(ip->client->destination.iabuf, ip->client->active->
861
		    options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
862
		ip->client->destination.len = 4;
863
	} else
864
	ip->client->destination = iaddr_broadcast;
865
/* End of the updated section */
866
	
867
	ip->client->first_sending = cur_time;
868
	ip->client->interval = ip->client->config->initial_interval;
869
	ip->client->state = S_RENEWING;
870

    
871
	/* Send the first packet immediately. */
872
	send_request(ip);
873
}
874

    
875
void
876
bootp(struct packet *packet)
877
{
878
	struct iaddrlist *ap;
879

    
880
	if (packet->raw->op != BOOTREPLY)
881
		return;
882

    
883
	/* If there's a reject list, make sure this packet's sender isn't
884
	   on it. */
885
	for (ap = packet->interface->client->config->reject_list;
886
	    ap; ap = ap->next) {
887
		if (addr_eq(packet->client_addr, ap->addr)) {
888
			note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
889
			return;
890
		}
891
	}
892
	dhcpoffer(packet);
893
}
894

    
895
void
896
dhcp(struct packet *packet)
897
{
898
	struct iaddrlist *ap;
899
	void (*handler)(struct packet *);
900
	char *type;
901

    
902
	switch (packet->packet_type) {
903
	case DHCPOFFER:
904
		handler = dhcpoffer;
905
		type = "DHCPOFFER";
906
		break;
907
	case DHCPNAK:
908
		handler = dhcpnak;
909
		type = "DHCPNACK";
910
		break;
911
	case DHCPACK:
912
		handler = dhcpack;
913
		type = "DHCPACK";
914
		break;
915
	default:
916
		return;
917
	}
918

    
919
	/* If there's a reject list, make sure this packet's sender isn't
920
	   on it. */
921
	for (ap = packet->interface->client->config->reject_list;
922
	    ap; ap = ap->next) {
923
		if (addr_eq(packet->client_addr, ap->addr)) {
924
			note("%s from %s rejected.", type, piaddr(ap->addr));
925
			return;
926
		}
927
	}
928
	(*handler)(packet);
929
}
930

    
931
void
932
dhcpoffer(struct packet *packet)
933
{
934
	struct interface_info *ip = packet->interface;
935
	struct client_lease *lease, *lp;
936
	int i;
937
	int arp_timeout_needed, stop_selecting;
938
	char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
939
	    "DHCPOFFER" : "BOOTREPLY";
940

    
941
	/* If we're not receptive to an offer right now, or if the offer
942
	   has an unrecognizable transaction id, then just drop it. */
943
	if (ip->client->state != S_SELECTING ||
944
	    packet->interface->client->xid != packet->raw->xid ||
945
	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
946
	    (memcmp(packet->interface->hw_address.haddr,
947
	    packet->raw->chaddr, packet->raw->hlen)))
948
		return;
949

    
950
	note("%s from %s", name, piaddr(packet->client_addr));
951

    
952

    
953
	/* If this lease doesn't supply the minimum required parameters,
954
	   blow it off. */
955
	for (i = 0; ip->client->config->required_options[i]; i++) {
956
		if (!packet->options[ip->client->config->
957
		    required_options[i]].len) {
958
			note("%s isn't satisfactory.", name);
959
			return;
960
		}
961
	}
962

    
963
	/* If we've already seen this lease, don't record it again. */
964
	for (lease = ip->client->offered_leases;
965
	    lease; lease = lease->next) {
966
		if (lease->address.len == sizeof(packet->raw->yiaddr) &&
967
		    !memcmp(lease->address.iabuf,
968
		    &packet->raw->yiaddr, lease->address.len)) {
969
			debug("%s already seen.", name);
970
			return;
971
		}
972
	}
973

    
974
	lease = packet_to_lease(packet);
975
	if (!lease) {
976
		note("packet_to_lease failed.");
977
		return;
978
	}
979

    
980
	/* If this lease was acquired through a BOOTREPLY, record that
981
	   fact. */
982
	if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
983
		lease->is_bootp = 1;
984

    
985
	/* Record the medium under which this lease was offered. */
986
	lease->medium = ip->client->medium;
987

    
988
	/* Send out an ARP Request for the offered IP address. */
989
	script_init("ARPSEND", lease->medium);
990
	script_write_params("check_", lease);
991
	/* If the script can't send an ARP request without waiting,
992
	   we'll be waiting when we do the ARPCHECK, so don't wait now. */
993
	if (script_go())
994
		arp_timeout_needed = 0;
995
	else
996
		arp_timeout_needed = 2;
997

    
998
	/* Figure out when we're supposed to stop selecting. */
999
	stop_selecting =
1000
	    ip->client->first_sending + ip->client->config->select_interval;
1001

    
1002
	/* If this is the lease we asked for, put it at the head of the
1003
	   list, and don't mess with the arp request timeout. */
1004
	if (lease->address.len == ip->client->requested_address.len &&
1005
	    !memcmp(lease->address.iabuf,
1006
	    ip->client->requested_address.iabuf,
1007
	    ip->client->requested_address.len)) {
1008
		lease->next = ip->client->offered_leases;
1009
		ip->client->offered_leases = lease;
1010
	} else {
1011
		/* If we already have an offer, and arping for this
1012
		   offer would take us past the selection timeout,
1013
		   then don't extend the timeout - just hope for the
1014
		   best. */
1015
		if (ip->client->offered_leases &&
1016
		    (cur_time + arp_timeout_needed) > stop_selecting)
1017
			arp_timeout_needed = 0;
1018

    
1019
		/* Put the lease at the end of the list. */
1020
		lease->next = NULL;
1021
		if (!ip->client->offered_leases)
1022
			ip->client->offered_leases = lease;
1023
		else {
1024
			for (lp = ip->client->offered_leases; lp->next;
1025
			    lp = lp->next)
1026
				;	/* nothing */
1027
			lp->next = lease;
1028
		}
1029
	}
1030

    
1031
	/* If we're supposed to stop selecting before we've had time
1032
	   to wait for the ARPREPLY, add some delay to wait for
1033
	   the ARPREPLY. */
1034
	if (stop_selecting - cur_time < arp_timeout_needed)
1035
		stop_selecting = cur_time + arp_timeout_needed;
1036

    
1037
	/* If the selecting interval has expired, go immediately to
1038
	   state_selecting().  Otherwise, time out into
1039
	   state_selecting at the select interval. */
1040
	if (stop_selecting <= 0)
1041
		state_selecting(ip);
1042
	else {
1043
		add_timeout(stop_selecting, state_selecting, ip);
1044
		cancel_timeout(send_discover, ip);
1045
	}
1046
}
1047

    
1048
/* Allocate a client_lease structure and initialize it from the parameters
1049
   in the specified packet. */
1050

    
1051
struct client_lease *
1052
packet_to_lease(struct packet *packet)
1053
{
1054
	struct client_lease *lease;
1055
	int i;
1056

    
1057
	lease = malloc(sizeof(struct client_lease));
1058

    
1059
	if (!lease) {
1060
		warning("dhcpoffer: no memory to record lease.");
1061
		return (NULL);
1062
	}
1063

    
1064
	memset(lease, 0, sizeof(*lease));
1065

    
1066
	/* Copy the lease options. */
1067
	for (i = 0; i < 256; i++) {
1068
		if (packet->options[i].len) {
1069
			lease->options[i].data =
1070
			    malloc(packet->options[i].len + 1);
1071
			if (!lease->options[i].data) {
1072
				warning("dhcpoffer: no memory for option %d", i);
1073
				free_client_lease(lease);
1074
				return (NULL);
1075
			} else {
1076
				memcpy(lease->options[i].data,
1077
				    packet->options[i].data,
1078
				    packet->options[i].len);
1079
				lease->options[i].len =
1080
				    packet->options[i].len;
1081
				lease->options[i].data[lease->options[i].len] =
1082
				    0;
1083
			}
1084
			if (!check_option(lease,i)) {
1085
				/* ignore a bogus lease offer */
1086
				warning("Invalid lease option - ignoring offer");
1087
				free_client_lease(lease);
1088
				return (NULL);
1089
			}
1090
		}
1091
	}
1092

    
1093
	lease->address.len = sizeof(packet->raw->yiaddr);
1094
	memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1095

    
1096
	lease->nextserver.len = sizeof(packet->raw->siaddr);
1097
	memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1098

    
1099
	/* If the server name was filled out, copy it.
1100
	   Do not attempt to validate the server name as a host name.
1101
	   RFC 2131 merely states that sname is NUL-terminated (which do
1102
	   do not assume) and that it is the server's host name.  Since
1103
	   the ISC client and server allow arbitrary characters, we do
1104
	   as well. */
1105
	if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1106
	    !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1107
	    packet->raw->sname[0]) {
1108
		lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1109
		if (!lease->server_name) {
1110
			warning("dhcpoffer: no memory for server name.");
1111
			free_client_lease(lease);
1112
			return (NULL);
1113
		}
1114
		memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1115
		lease->server_name[DHCP_SNAME_LEN]='\0';
1116
	}
1117

    
1118
	/* Ditto for the filename. */
1119
	if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1120
	    !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1121
	    packet->raw->file[0]) {
1122
		/* Don't count on the NUL terminator. */
1123
		lease->filename = malloc(DHCP_FILE_LEN + 1);
1124
		if (!lease->filename) {
1125
			warning("dhcpoffer: no memory for filename.");
1126
			free_client_lease(lease);
1127
			return (NULL);
1128
		}
1129
		memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1130
		lease->filename[DHCP_FILE_LEN]='\0';
1131
	}
1132
	return lease;
1133
}
1134

    
1135
void
1136
dhcpnak(struct packet *packet)
1137
{
1138
	struct interface_info *ip = packet->interface;
1139

    
1140
	/* If we're not receptive to an offer right now, or if the offer
1141
	   has an unrecognizable transaction id, then just drop it. */
1142
	if (packet->interface->client->xid != packet->raw->xid ||
1143
	    (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1144
	    (memcmp(packet->interface->hw_address.haddr,
1145
	    packet->raw->chaddr, packet->raw->hlen)))
1146
		return;
1147

    
1148
	if (ip->client->state != S_REBOOTING &&
1149
	    ip->client->state != S_REQUESTING &&
1150
	    ip->client->state != S_RENEWING &&
1151
	    ip->client->state != S_REBINDING)
1152
		return;
1153

    
1154
	note("DHCPNAK from %s", piaddr(packet->client_addr));
1155

    
1156
	if (!ip->client->active) {
1157
		note("DHCPNAK with no active lease.\n");
1158
		return;
1159
	}
1160

    
1161
	free_client_lease(ip->client->active);
1162
	ip->client->active = NULL;
1163

    
1164
	/* Stop sending DHCPREQUEST packets... */
1165
	cancel_timeout(send_request, ip);
1166

    
1167
	ip->client->state = S_INIT;
1168
	state_init(ip);
1169
}
1170

    
1171
/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1172
   one after the right interval has expired.  If we don't get an offer by
1173
   the time we reach the panic interval, call the panic function. */
1174

    
1175
void
1176
send_discover(void *ipp)
1177
{
1178
	struct interface_info *ip = ipp;
1179
	int interval, increase = 1;
1180

    
1181
	/* Figure out how long it's been since we started transmitting. */
1182
	interval = cur_time - ip->client->first_sending;
1183

    
1184
	/* If we're past the panic timeout, call the script and tell it
1185
	   we haven't found anything for this interface yet. */
1186
	if (interval > ip->client->config->timeout) {
1187
		state_panic(ip);
1188
		return;
1189
	}
1190

    
1191
	/* If we're selecting media, try the whole list before doing
1192
	   the exponential backoff, but if we've already received an
1193
	   offer, stop looping, because we obviously have it right. */
1194
	if (!ip->client->offered_leases &&
1195
	    ip->client->config->media) {
1196
		int fail = 0;
1197
again:
1198
		if (ip->client->medium) {
1199
			ip->client->medium = ip->client->medium->next;
1200
			increase = 0;
1201
		}
1202
		if (!ip->client->medium) {
1203
			if (fail)
1204
				error("No valid media types for %s!", ip->name);
1205
			ip->client->medium = ip->client->config->media;
1206
			increase = 1;
1207
		}
1208

    
1209
		note("Trying medium \"%s\" %d", ip->client->medium->string,
1210
		    increase);
1211
		script_init("MEDIUM", ip->client->medium);
1212
		if (script_go())
1213
			goto again;
1214
	}
1215

    
1216
	/*
1217
	 * If we're supposed to increase the interval, do so.  If it's
1218
	 * currently zero (i.e., we haven't sent any packets yet), set
1219
	 * it to one; otherwise, add to it a random number between zero
1220
	 * and two times itself.  On average, this means that it will
1221
	 * double with every transmission.
1222
	 */
1223
	if (increase) {
1224
		if (!ip->client->interval)
1225
			ip->client->interval =
1226
			    ip->client->config->initial_interval;
1227
		else {
1228
			ip->client->interval += (arc4random() >> 2) %
1229
			    (2 * ip->client->interval);
1230
		}
1231

    
1232
		/* Don't backoff past cutoff. */
1233
		if (ip->client->interval >
1234
		    ip->client->config->backoff_cutoff)
1235
			ip->client->interval =
1236
				((ip->client->config->backoff_cutoff / 2)
1237
				 + ((arc4random() >> 2) %
1238
				    ip->client->config->backoff_cutoff));
1239
	} else if (!ip->client->interval)
1240
		ip->client->interval =
1241
			ip->client->config->initial_interval;
1242

    
1243
	/* If the backoff would take us to the panic timeout, just use that
1244
	   as the interval. */
1245
	if (cur_time + ip->client->interval >
1246
	    ip->client->first_sending + ip->client->config->timeout)
1247
		ip->client->interval =
1248
			(ip->client->first_sending +
1249
			 ip->client->config->timeout) - cur_time + 1;
1250

    
1251
	/* Record the number of seconds since we started sending. */
1252
	if (interval < 65536)
1253
		ip->client->packet.secs = htons(interval);
1254
	else
1255
		ip->client->packet.secs = htons(65535);
1256
	ip->client->secs = ip->client->packet.secs;
1257

    
1258
	note("DHCPDISCOVER on %s to %s port %d interval %d",
1259
	    ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1260
	    (int)ip->client->interval);
1261

    
1262
	/* Send out a packet. */
1263
	send_packet_unpriv(privfd, &ip->client->packet,
1264
	    ip->client->packet_length, inaddr_any, inaddr_broadcast);
1265

    
1266
	add_timeout(cur_time + ip->client->interval, send_discover, ip);
1267
}
1268

    
1269
/*
1270
 * state_panic gets called if we haven't received any offers in a preset
1271
 * amount of time.   When this happens, we try to use existing leases
1272
 * that haven't yet expired, and failing that, we call the client script
1273
 * and hope it can do something.
1274
 */
1275
void
1276
state_panic(void *ipp)
1277
{
1278
	struct interface_info *ip = ipp;
1279
	struct client_lease *loop = ip->client->active;
1280
	struct client_lease *lp;
1281

    
1282
	note("No DHCPOFFERS received.");
1283

    
1284
	/* We may not have an active lease, but we may have some
1285
	   predefined leases that we can try. */
1286
	if (!ip->client->active && ip->client->leases)
1287
		goto activate_next;
1288

    
1289
	/* Run through the list of leases and see if one can be used. */
1290
	while (ip->client->active) {
1291
		if (ip->client->active->expiry > cur_time) {
1292
			note("Trying recorded lease %s",
1293
			    piaddr(ip->client->active->address));
1294
			/* Run the client script with the existing
1295
			   parameters. */
1296
			script_init("TIMEOUT",
1297
			    ip->client->active->medium);
1298
			script_write_params("new_", ip->client->active);
1299
			if (ip->client->alias)
1300
				script_write_params("alias_",
1301
				    ip->client->alias);
1302

    
1303
			/* If the old lease is still good and doesn't
1304
			   yet need renewal, go into BOUND state and
1305
			   timeout at the renewal time. */
1306
			if (!script_go()) {
1307
				if (cur_time <
1308
				    ip->client->active->renewal) {
1309
					ip->client->state = S_BOUND;
1310
					note("bound: renewal in %d seconds.",
1311
					    (int)(ip->client->active->renewal -
1312
					    cur_time));
1313
					add_timeout(
1314
					    ip->client->active->renewal,
1315
					    state_bound, ip);
1316
				} else {
1317
					ip->client->state = S_BOUND;
1318
					note("bound: immediate renewal.");
1319
					state_bound(ip);
1320
				}
1321
				reinitialize_interfaces();
1322
				go_daemon();
1323
				return;
1324
			}
1325
		}
1326

    
1327
		/* If there are no other leases, give up. */
1328
		if (!ip->client->leases) {
1329
			ip->client->leases = ip->client->active;
1330
			ip->client->active = NULL;
1331
			break;
1332
		}
1333

    
1334
activate_next:
1335
		/* Otherwise, put the active lease at the end of the
1336
		   lease list, and try another lease.. */
1337
		for (lp = ip->client->leases; lp->next; lp = lp->next)
1338
			;
1339
		lp->next = ip->client->active;
1340
		if (lp->next)
1341
			lp->next->next = NULL;
1342
		ip->client->active = ip->client->leases;
1343
		ip->client->leases = ip->client->leases->next;
1344

    
1345
		/* If we already tried this lease, we've exhausted the
1346
		   set of leases, so we might as well give up for
1347
		   now. */
1348
		if (ip->client->active == loop)
1349
			break;
1350
		else if (!loop)
1351
			loop = ip->client->active;
1352
	}
1353

    
1354
	/* No leases were available, or what was available didn't work, so
1355
	   tell the shell script that we failed to allocate an address,
1356
	   and try again later. */
1357
	note("No working leases in persistent database - sleeping.\n");
1358
	script_init("FAIL", NULL);
1359
	if (ip->client->alias)
1360
		script_write_params("alias_", ip->client->alias);
1361
	script_go();
1362
	ip->client->state = S_INIT;
1363
	add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1364
	    ip);
1365
	go_daemon();
1366
}
1367

    
1368
void
1369
send_request(void *ipp)
1370
{
1371
	struct interface_info *ip = ipp;
1372
	struct in_addr from, to;
1373
	int interval;
1374

    
1375
	/* Figure out how long it's been since we started transmitting. */
1376
	interval = cur_time - ip->client->first_sending;
1377

    
1378
	/* If we're in the INIT-REBOOT or REQUESTING state and we're
1379
	   past the reboot timeout, go to INIT and see if we can
1380
	   DISCOVER an address... */
1381
	/* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1382
	   means either that we're on a network with no DHCP server,
1383
	   or that our server is down.  In the latter case, assuming
1384
	   that there is a backup DHCP server, DHCPDISCOVER will get
1385
	   us a new address, but we could also have successfully
1386
	   reused our old address.  In the former case, we're hosed
1387
	   anyway.  This is not a win-prone situation. */
1388
	if ((ip->client->state == S_REBOOTING ||
1389
	    ip->client->state == S_REQUESTING) &&
1390
	    interval > ip->client->config->reboot_timeout) {
1391
cancel:
1392
		ip->client->state = S_INIT;
1393
		cancel_timeout(send_request, ip);
1394
		state_init(ip);
1395
		return;
1396
	}
1397

    
1398
	/* If we're in the reboot state, make sure the media is set up
1399
	   correctly. */
1400
	if (ip->client->state == S_REBOOTING &&
1401
	    !ip->client->medium &&
1402
	    ip->client->active->medium ) {
1403
		script_init("MEDIUM", ip->client->active->medium);
1404

    
1405
		/* If the medium we chose won't fly, go to INIT state. */
1406
		if (script_go())
1407
			goto cancel;
1408

    
1409
		/* Record the medium. */
1410
		ip->client->medium = ip->client->active->medium;
1411
	}
1412

    
1413
	/* If the lease has expired, relinquish the address and go back
1414
	   to the INIT state. */
1415
	if (ip->client->state != S_REQUESTING &&
1416
	    cur_time > ip->client->active->expiry) {
1417
		/* Run the client script with the new parameters. */
1418
		script_init("EXPIRE", NULL);
1419
		script_write_params("old_", ip->client->active);
1420
		if (ip->client->alias)
1421
			script_write_params("alias_", ip->client->alias);
1422
		script_go();
1423

    
1424
		/* Now do a preinit on the interface so that we can
1425
		   discover a new address. */
1426
		script_init("PREINIT", NULL);
1427
		if (ip->client->alias)
1428
			script_write_params("alias_", ip->client->alias);
1429
		script_go();
1430

    
1431
		ip->client->state = S_INIT;
1432
		state_init(ip);
1433
		return;
1434
	}
1435

    
1436
	/* Do the exponential backoff... */
1437
	if (!ip->client->interval)
1438
		ip->client->interval = ip->client->config->initial_interval;
1439
	else
1440
		ip->client->interval += ((arc4random() >> 2) %
1441
		    (2 * ip->client->interval));
1442

    
1443
	/* Don't backoff past cutoff. */
1444
	if (ip->client->interval >
1445
	    ip->client->config->backoff_cutoff)
1446
		ip->client->interval =
1447
		    ((ip->client->config->backoff_cutoff / 2) +
1448
		    ((arc4random() >> 2) % ip->client->interval));
1449

    
1450
	/* If the backoff would take us to the expiry time, just set the
1451
	   timeout to the expiry time. */
1452
	if (ip->client->state != S_REQUESTING &&
1453
	    cur_time + ip->client->interval >
1454
	    ip->client->active->expiry)
1455
		ip->client->interval =
1456
		    ip->client->active->expiry - cur_time + 1;
1457

    
1458
	/* If the lease T2 time has elapsed, or if we're not yet bound,
1459
	   broadcast the DHCPREQUEST rather than unicasting. */
1460
	if (ip->client->state == S_REQUESTING ||
1461
	    ip->client->state == S_REBOOTING ||
1462
	    cur_time > ip->client->active->rebind)
1463
		to.s_addr = INADDR_BROADCAST;
1464
	else
1465
		memcpy(&to.s_addr, ip->client->destination.iabuf,
1466
		    sizeof(to.s_addr));
1467

    
1468
	if (ip->client->state != S_REQUESTING)
1469
		memcpy(&from, ip->client->active->address.iabuf,
1470
		    sizeof(from));
1471
	else
1472
		from.s_addr = INADDR_ANY;
1473

    
1474
	/* Record the number of seconds since we started sending. */
1475
	if (ip->client->state == S_REQUESTING)
1476
		ip->client->packet.secs = ip->client->secs;
1477
	else {
1478
		if (interval < 65536)
1479
			ip->client->packet.secs = htons(interval);
1480
		else
1481
			ip->client->packet.secs = htons(65535);
1482
	}
1483

    
1484
	note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1485
	    REMOTE_PORT);
1486

    
1487
	/* Send out a packet. */
1488
	send_packet_unpriv(privfd, &ip->client->packet,
1489
	    ip->client->packet_length, from, to);
1490

    
1491
	add_timeout(cur_time + ip->client->interval, send_request, ip);
1492
}
1493

    
1494
void
1495
send_decline(void *ipp)
1496
{
1497
	struct interface_info *ip = ipp;
1498

    
1499
	note("DHCPDECLINE on %s to %s port %d", ip->name,
1500
	    inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1501

    
1502
	/* Send out a packet. */
1503
	send_packet_unpriv(privfd, &ip->client->packet,
1504
	    ip->client->packet_length, inaddr_any, inaddr_broadcast);
1505
}
1506

    
1507
void
1508
make_discover(struct interface_info *ip, struct client_lease *lease)
1509
{
1510
	unsigned char discover = DHCPDISCOVER;
1511
	struct tree_cache *options[256];
1512
	struct tree_cache option_elements[256];
1513
	int i;
1514

    
1515
	memset(option_elements, 0, sizeof(option_elements));
1516
	memset(options, 0, sizeof(options));
1517
	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1518

    
1519
	/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1520
	i = DHO_DHCP_MESSAGE_TYPE;
1521
	options[i] = &option_elements[i];
1522
	options[i]->value = &discover;
1523
	options[i]->len = sizeof(discover);
1524
	options[i]->buf_size = sizeof(discover);
1525
	options[i]->timeout = 0xFFFFFFFF;
1526

    
1527
	/* Request the options we want */
1528
	i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1529
	options[i] = &option_elements[i];
1530
	options[i]->value = ip->client->config->requested_options;
1531
	options[i]->len = ip->client->config->requested_option_count;
1532
	options[i]->buf_size =
1533
		ip->client->config->requested_option_count;
1534
	options[i]->timeout = 0xFFFFFFFF;
1535

    
1536
	/* If we had an address, try to get it again. */
1537
	if (lease) {
1538
		ip->client->requested_address = lease->address;
1539
		i = DHO_DHCP_REQUESTED_ADDRESS;
1540
		options[i] = &option_elements[i];
1541
		options[i]->value = lease->address.iabuf;
1542
		options[i]->len = lease->address.len;
1543
		options[i]->buf_size = lease->address.len;
1544
		options[i]->timeout = 0xFFFFFFFF;
1545
	} else
1546
		ip->client->requested_address.len = 0;
1547

    
1548
	/* Send any options requested in the config file. */
1549
	for (i = 0; i < 256; i++)
1550
		if (!options[i] &&
1551
		    ip->client->config->send_options[i].data) {
1552
			options[i] = &option_elements[i];
1553
			options[i]->value =
1554
			    ip->client->config->send_options[i].data;
1555
			options[i]->len =
1556
			    ip->client->config->send_options[i].len;
1557
			options[i]->buf_size =
1558
			    ip->client->config->send_options[i].len;
1559
			options[i]->timeout = 0xFFFFFFFF;
1560
		}
1561

    
1562
	/* send host name if not set via config file. */
1563
	if (!options[DHO_HOST_NAME]) {
1564
		if (hostname[0] != '\0') {
1565
			size_t len;
1566
			char* posDot = strchr(hostname, '.');
1567
			if (posDot != NULL)
1568
				len = posDot - hostname;
1569
			else
1570
				len = strlen(hostname);
1571
			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1572
			options[DHO_HOST_NAME]->value = hostname;
1573
			options[DHO_HOST_NAME]->len = len;
1574
			options[DHO_HOST_NAME]->buf_size = len;
1575
			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1576
		}
1577
	}
1578

    
1579
	/* set unique client identifier */
1580
	char client_ident[sizeof(struct hardware)];
1581
	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1582
		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1583
				ip->hw_address.hlen : sizeof(client_ident)-1;
1584
		client_ident[0] = ip->hw_address.htype;
1585
		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1586
		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1587
		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1588
		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1589
		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1590
		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1591
	}
1592

    
1593
	/* Set up the option buffer... */
1594
	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1595
	    options, 0, 0, 0, NULL, 0);
1596
	if (ip->client->packet_length < BOOTP_MIN_LEN)
1597
		ip->client->packet_length = BOOTP_MIN_LEN;
1598

    
1599
	ip->client->packet.op = BOOTREQUEST;
1600
	ip->client->packet.htype = ip->hw_address.htype;
1601
	ip->client->packet.hlen = ip->hw_address.hlen;
1602
	ip->client->packet.hops = 0;
1603
	ip->client->packet.xid = arc4random();
1604
	ip->client->packet.secs = 0; /* filled in by send_discover. */
1605
	ip->client->packet.flags = 0;
1606

    
1607
	memset(&(ip->client->packet.ciaddr),
1608
	    0, sizeof(ip->client->packet.ciaddr));
1609
	memset(&(ip->client->packet.yiaddr),
1610
	    0, sizeof(ip->client->packet.yiaddr));
1611
	memset(&(ip->client->packet.siaddr),
1612
	    0, sizeof(ip->client->packet.siaddr));
1613
	memset(&(ip->client->packet.giaddr),
1614
	    0, sizeof(ip->client->packet.giaddr));
1615
	memcpy(ip->client->packet.chaddr,
1616
	    ip->hw_address.haddr, ip->hw_address.hlen);
1617
}
1618

    
1619

    
1620
void
1621
make_request(struct interface_info *ip, struct client_lease * lease)
1622
{
1623
	unsigned char request = DHCPREQUEST;
1624
	struct tree_cache *options[256];
1625
	struct tree_cache option_elements[256];
1626
	int i;
1627

    
1628
	memset(options, 0, sizeof(options));
1629
	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1630

    
1631
	/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1632
	i = DHO_DHCP_MESSAGE_TYPE;
1633
	options[i] = &option_elements[i];
1634
	options[i]->value = &request;
1635
	options[i]->len = sizeof(request);
1636
	options[i]->buf_size = sizeof(request);
1637
	options[i]->timeout = 0xFFFFFFFF;
1638

    
1639
	/* Request the options we want */
1640
	i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1641
	options[i] = &option_elements[i];
1642
	options[i]->value = ip->client->config->requested_options;
1643
	options[i]->len = ip->client->config->requested_option_count;
1644
	options[i]->buf_size =
1645
		ip->client->config->requested_option_count;
1646
	options[i]->timeout = 0xFFFFFFFF;
1647

    
1648
	/* If we are requesting an address that hasn't yet been assigned
1649
	   to us, use the DHCP Requested Address option. */
1650
	if (ip->client->state == S_REQUESTING) {
1651
		/* Send back the server identifier... */
1652
		i = DHO_DHCP_SERVER_IDENTIFIER;
1653
		options[i] = &option_elements[i];
1654
		options[i]->value = lease->options[i].data;
1655
		options[i]->len = lease->options[i].len;
1656
		options[i]->buf_size = lease->options[i].len;
1657
		options[i]->timeout = 0xFFFFFFFF;
1658
	}
1659
	if (ip->client->state == S_REQUESTING ||
1660
	    ip->client->state == S_REBOOTING) {
1661
		ip->client->requested_address = lease->address;
1662
		i = DHO_DHCP_REQUESTED_ADDRESS;
1663
		options[i] = &option_elements[i];
1664
		options[i]->value = lease->address.iabuf;
1665
		options[i]->len = lease->address.len;
1666
		options[i]->buf_size = lease->address.len;
1667
		options[i]->timeout = 0xFFFFFFFF;
1668
	} else
1669
		ip->client->requested_address.len = 0;
1670

    
1671
	/* Send any options requested in the config file. */
1672
	for (i = 0; i < 256; i++)
1673
		if (!options[i] &&
1674
		    ip->client->config->send_options[i].data) {
1675
			options[i] = &option_elements[i];
1676
			options[i]->value =
1677
			    ip->client->config->send_options[i].data;
1678
			options[i]->len =
1679
			    ip->client->config->send_options[i].len;
1680
			options[i]->buf_size =
1681
			    ip->client->config->send_options[i].len;
1682
			options[i]->timeout = 0xFFFFFFFF;
1683
		}
1684

    
1685
	/* send host name if not set via config file. */
1686
	if (!options[DHO_HOST_NAME]) {
1687
		if (hostname[0] != '\0') {
1688
			size_t len;
1689
			char* posDot = strchr(hostname, '.');
1690
			if (posDot != NULL)
1691
				len = posDot - hostname;
1692
			else
1693
				len = strlen(hostname);
1694
			options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1695
			options[DHO_HOST_NAME]->value = hostname;
1696
			options[DHO_HOST_NAME]->len = len;
1697
			options[DHO_HOST_NAME]->buf_size = len;
1698
			options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1699
		}
1700
	}
1701

    
1702
	/* set unique client identifier */
1703
	char client_ident[sizeof(struct hardware)];
1704
	if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1705
		int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1706
				ip->hw_address.hlen : sizeof(client_ident)-1;
1707
		client_ident[0] = ip->hw_address.htype;
1708
		memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1709
		options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1710
		options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1711
		options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1712
		options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1713
		options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1714
	}
1715

    
1716
	/* Set up the option buffer... */
1717
	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1718
	    options, 0, 0, 0, NULL, 0);
1719
	if (ip->client->packet_length < BOOTP_MIN_LEN)
1720
		ip->client->packet_length = BOOTP_MIN_LEN;
1721

    
1722
	ip->client->packet.op = BOOTREQUEST;
1723
	ip->client->packet.htype = ip->hw_address.htype;
1724
	ip->client->packet.hlen = ip->hw_address.hlen;
1725
	ip->client->packet.hops = 0;
1726
	ip->client->packet.xid = ip->client->xid;
1727
	ip->client->packet.secs = 0; /* Filled in by send_request. */
1728

    
1729
	/* If we own the address we're requesting, put it in ciaddr;
1730
	   otherwise set ciaddr to zero. */
1731
	if (ip->client->state == S_BOUND ||
1732
	    ip->client->state == S_RENEWING ||
1733
	    ip->client->state == S_REBINDING) {
1734
		memcpy(&ip->client->packet.ciaddr,
1735
		    lease->address.iabuf, lease->address.len);
1736
		ip->client->packet.flags = 0;
1737
	} else {
1738
		memset(&ip->client->packet.ciaddr, 0,
1739
		    sizeof(ip->client->packet.ciaddr));
1740
		ip->client->packet.flags = 0;
1741
	}
1742

    
1743
	memset(&ip->client->packet.yiaddr, 0,
1744
	    sizeof(ip->client->packet.yiaddr));
1745
	memset(&ip->client->packet.siaddr, 0,
1746
	    sizeof(ip->client->packet.siaddr));
1747
	memset(&ip->client->packet.giaddr, 0,
1748
	    sizeof(ip->client->packet.giaddr));
1749
	memcpy(ip->client->packet.chaddr,
1750
	    ip->hw_address.haddr, ip->hw_address.hlen);
1751
}
1752

    
1753
void
1754
make_decline(struct interface_info *ip, struct client_lease *lease)
1755
{
1756
	struct tree_cache *options[256], message_type_tree;
1757
	struct tree_cache requested_address_tree;
1758
	struct tree_cache server_id_tree, client_id_tree;
1759
	unsigned char decline = DHCPDECLINE;
1760
	int i;
1761

    
1762
	memset(options, 0, sizeof(options));
1763
	memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1764

    
1765
	/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1766
	i = DHO_DHCP_MESSAGE_TYPE;
1767
	options[i] = &message_type_tree;
1768
	options[i]->value = &decline;
1769
	options[i]->len = sizeof(decline);
1770
	options[i]->buf_size = sizeof(decline);
1771
	options[i]->timeout = 0xFFFFFFFF;
1772

    
1773
	/* Send back the server identifier... */
1774
	i = DHO_DHCP_SERVER_IDENTIFIER;
1775
	options[i] = &server_id_tree;
1776
	options[i]->value = lease->options[i].data;
1777
	options[i]->len = lease->options[i].len;
1778
	options[i]->buf_size = lease->options[i].len;
1779
	options[i]->timeout = 0xFFFFFFFF;
1780

    
1781
	/* Send back the address we're declining. */
1782
	i = DHO_DHCP_REQUESTED_ADDRESS;
1783
	options[i] = &requested_address_tree;
1784
	options[i]->value = lease->address.iabuf;
1785
	options[i]->len = lease->address.len;
1786
	options[i]->buf_size = lease->address.len;
1787
	options[i]->timeout = 0xFFFFFFFF;
1788

    
1789
	/* Send the uid if the user supplied one. */
1790
	i = DHO_DHCP_CLIENT_IDENTIFIER;
1791
	if (ip->client->config->send_options[i].len) {
1792
		options[i] = &client_id_tree;
1793
		options[i]->value = ip->client->config->send_options[i].data;
1794
		options[i]->len = ip->client->config->send_options[i].len;
1795
		options[i]->buf_size = ip->client->config->send_options[i].len;
1796
		options[i]->timeout = 0xFFFFFFFF;
1797
	}
1798

    
1799

    
1800
	/* Set up the option buffer... */
1801
	ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1802
	    options, 0, 0, 0, NULL, 0);
1803
	if (ip->client->packet_length < BOOTP_MIN_LEN)
1804
		ip->client->packet_length = BOOTP_MIN_LEN;
1805

    
1806
	ip->client->packet.op = BOOTREQUEST;
1807
	ip->client->packet.htype = ip->hw_address.htype;
1808
	ip->client->packet.hlen = ip->hw_address.hlen;
1809
	ip->client->packet.hops = 0;
1810
	ip->client->packet.xid = ip->client->xid;
1811
	ip->client->packet.secs = 0; /* Filled in by send_request. */
1812
	ip->client->packet.flags = 0;
1813

    
1814
	/* ciaddr must always be zero. */
1815
	memset(&ip->client->packet.ciaddr, 0,
1816
	    sizeof(ip->client->packet.ciaddr));
1817
	memset(&ip->client->packet.yiaddr, 0,
1818
	    sizeof(ip->client->packet.yiaddr));
1819
	memset(&ip->client->packet.siaddr, 0,
1820
	    sizeof(ip->client->packet.siaddr));
1821
	memset(&ip->client->packet.giaddr, 0,
1822
	    sizeof(ip->client->packet.giaddr));
1823
	memcpy(ip->client->packet.chaddr,
1824
	    ip->hw_address.haddr, ip->hw_address.hlen);
1825
}
1826

    
1827
void
1828
free_client_lease(struct client_lease *lease)
1829
{
1830
	int i;
1831

    
1832
	if (lease->server_name)
1833
		free(lease->server_name);
1834
	if (lease->filename)
1835
		free(lease->filename);
1836
	for (i = 0; i < 256; i++) {
1837
		if (lease->options[i].len)
1838
			free(lease->options[i].data);
1839
	}
1840
	free(lease);
1841
}
1842

    
1843
FILE *leaseFile;
1844

    
1845
void
1846
rewrite_client_leases(void)
1847
{
1848
	struct client_lease *lp;
1849
	cap_rights_t rights;
1850

    
1851
	if (!leaseFile) {
1852
		leaseFile = fopen(path_dhclient_db, "w");
1853
		if (!leaseFile)
1854
			error("can't create %s: %m", path_dhclient_db);
1855
		cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1856
		    CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1857
		if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1858
		    errno != ENOSYS) {
1859
			error("can't limit lease descriptor: %m");
1860
		}
1861
		if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1862
		    errno != ENOSYS) {
1863
			error("can't limit lease descriptor fcntls: %m");
1864
		}
1865
	} else {
1866
		fflush(leaseFile);
1867
		rewind(leaseFile);
1868
	}
1869

    
1870
	for (lp = ifi->client->leases; lp; lp = lp->next)
1871
		write_client_lease(ifi, lp, 1);
1872
	if (ifi->client->active)
1873
		write_client_lease(ifi, ifi->client->active, 1);
1874

    
1875
	fflush(leaseFile);
1876
	ftruncate(fileno(leaseFile), ftello(leaseFile));
1877
	fsync(fileno(leaseFile));
1878
}
1879

    
1880
void
1881
write_client_lease(struct interface_info *ip, struct client_lease *lease,
1882
    int rewrite)
1883
{
1884
	static int leases_written;
1885
	struct tm *t;
1886
	int i;
1887

    
1888
	if (!rewrite) {
1889
		if (leases_written++ > 20) {
1890
			rewrite_client_leases();
1891
			leases_written = 0;
1892
		}
1893
	}
1894

    
1895
	/* If the lease came from the config file, we don't need to stash
1896
	   a copy in the lease database. */
1897
	if (lease->is_static)
1898
		return;
1899

    
1900
	if (!leaseFile) {	/* XXX */
1901
		leaseFile = fopen(path_dhclient_db, "w");
1902
		if (!leaseFile)
1903
			error("can't create %s: %m", path_dhclient_db);
1904
	}
1905

    
1906
	fprintf(leaseFile, "lease {\n");
1907
	if (lease->is_bootp)
1908
		fprintf(leaseFile, "  bootp;\n");
1909
	fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1910
	fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1911
	if (lease->nextserver.len == sizeof(inaddr_any) &&
1912
	    0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1913
	    sizeof(inaddr_any)))
1914
		fprintf(leaseFile, "  next-server %s;\n",
1915
		    piaddr(lease->nextserver));
1916
	if (lease->filename)
1917
		fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1918
	if (lease->server_name)
1919
		fprintf(leaseFile, "  server-name \"%s\";\n",
1920
		    lease->server_name);
1921
	if (lease->medium)
1922
		fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1923
	for (i = 0; i < 256; i++)
1924
		if (lease->options[i].len)
1925
			fprintf(leaseFile, "  option %s %s;\n",
1926
			    dhcp_options[i].name,
1927
			    pretty_print_option(i, lease->options[i].data,
1928
			    lease->options[i].len, 1, 1));
1929

    
1930
	t = gmtime(&lease->renewal);
1931
	fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
1932
	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1933
	    t->tm_hour, t->tm_min, t->tm_sec);
1934
	t = gmtime(&lease->rebind);
1935
	fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1936
	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1937
	    t->tm_hour, t->tm_min, t->tm_sec);
1938
	t = gmtime(&lease->expiry);
1939
	fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
1940
	    t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1941
	    t->tm_hour, t->tm_min, t->tm_sec);
1942
	fprintf(leaseFile, "}\n");
1943
	fflush(leaseFile);
1944
}
1945

    
1946
void
1947
script_init(char *reason, struct string_list *medium)
1948
{
1949
	size_t		 len, mediumlen = 0;
1950
	struct imsg_hdr	 hdr;
1951
	struct buf	*buf;
1952
	int		 errs;
1953

    
1954
	if (medium != NULL && medium->string != NULL)
1955
		mediumlen = strlen(medium->string);
1956

    
1957
	hdr.code = IMSG_SCRIPT_INIT;
1958
	hdr.len = sizeof(struct imsg_hdr) +
1959
	    sizeof(size_t) + mediumlen +
1960
	    sizeof(size_t) + strlen(reason);
1961

    
1962
	if ((buf = buf_open(hdr.len)) == NULL)
1963
		error("buf_open: %m");
1964

    
1965
	errs = 0;
1966
	errs += buf_add(buf, &hdr, sizeof(hdr));
1967
	errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1968
	if (mediumlen > 0)
1969
		errs += buf_add(buf, medium->string, mediumlen);
1970
	len = strlen(reason);
1971
	errs += buf_add(buf, &len, sizeof(len));
1972
	errs += buf_add(buf, reason, len);
1973

    
1974
	if (errs)
1975
		error("buf_add: %m");
1976

    
1977
	if (buf_close(privfd, buf) == -1)
1978
		error("buf_close: %m");
1979
}
1980

    
1981
void
1982
priv_script_init(char *reason, char *medium)
1983
{
1984
	struct interface_info *ip = ifi;
1985

    
1986
	if (ip) {
1987
		ip->client->scriptEnvsize = 100;
1988
		if (ip->client->scriptEnv == NULL)
1989
			ip->client->scriptEnv =
1990
			    malloc(ip->client->scriptEnvsize * sizeof(char *));
1991
		if (ip->client->scriptEnv == NULL)
1992
			error("script_init: no memory for environment");
1993

    
1994
		ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
1995
		if (ip->client->scriptEnv[0] == NULL)
1996
			error("script_init: no memory for environment");
1997

    
1998
		ip->client->scriptEnv[1] = NULL;
1999

    
2000
		script_set_env(ip->client, "", "interface", ip->name);
2001

    
2002
		if (medium)
2003
			script_set_env(ip->client, "", "medium", medium);
2004

    
2005
		script_set_env(ip->client, "", "reason", reason);
2006
	}
2007
}
2008

    
2009
void
2010
priv_script_write_params(char *prefix, struct client_lease *lease)
2011
{
2012
	struct interface_info *ip = ifi;
2013
	u_int8_t dbuf[1500], *dp = NULL;
2014
	int i, len;
2015
	char tbuf[128];
2016

    
2017
	script_set_env(ip->client, prefix, "ip_address",
2018
	    piaddr(lease->address));
2019

    
2020
	if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2021
	    ACTION_SUPERSEDE) {
2022
		dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2023
		len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2024
	} else {
2025
		dp = lease->options[DHO_SUBNET_MASK].data;
2026
		len = lease->options[DHO_SUBNET_MASK].len;
2027
	}
2028
	if (len && (len < sizeof(lease->address.iabuf))) {
2029
		struct iaddr netmask, subnet, broadcast;
2030

    
2031
		memcpy(netmask.iabuf, dp, len);
2032
		netmask.len = len;
2033
		subnet = subnet_number(lease->address, netmask);
2034
		if (subnet.len) {
2035
			script_set_env(ip->client, prefix, "network_number",
2036
			    piaddr(subnet));
2037
			if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2038
				broadcast = broadcast_addr(subnet, netmask);
2039
				if (broadcast.len)
2040
					script_set_env(ip->client, prefix,
2041
					    "broadcast_address",
2042
					    piaddr(broadcast));
2043
			}
2044
		}
2045
	}
2046

    
2047
	if (lease->filename)
2048
		script_set_env(ip->client, prefix, "filename", lease->filename);
2049
	if (lease->server_name)
2050
		script_set_env(ip->client, prefix, "server_name",
2051
		    lease->server_name);
2052
	for (i = 0; i < 256; i++) {
2053
		len = 0;
2054

    
2055
		if (ip->client->config->defaults[i].len) {
2056
			if (lease->options[i].len) {
2057
				switch (
2058
				    ip->client->config->default_actions[i]) {
2059
				case ACTION_DEFAULT:
2060
					dp = lease->options[i].data;
2061
					len = lease->options[i].len;
2062
					break;
2063
				case ACTION_SUPERSEDE:
2064
supersede:
2065
					dp = ip->client->
2066
						config->defaults[i].data;
2067
					len = ip->client->
2068
						config->defaults[i].len;
2069
					break;
2070
				case ACTION_PREPEND:
2071
					len = ip->client->
2072
					    config->defaults[i].len +
2073
					    lease->options[i].len;
2074
					if (len >= sizeof(dbuf)) {
2075
						warning("no space to %s %s",
2076
						    "prepend option",
2077
						    dhcp_options[i].name);
2078
						goto supersede;
2079
					}
2080
					dp = dbuf;
2081
					memcpy(dp,
2082
						ip->client->
2083
						config->defaults[i].data,
2084
						ip->client->
2085
						config->defaults[i].len);
2086
					memcpy(dp + ip->client->
2087
						config->defaults[i].len,
2088
						lease->options[i].data,
2089
						lease->options[i].len);
2090
					dp[len] = '\0';
2091
					break;
2092
				case ACTION_APPEND:
2093
					/*
2094
					 * When we append, we assume that we're
2095
					 * appending to text.  Some MS servers
2096
					 * include a NUL byte at the end of
2097
					 * the search string provided.
2098
					 */
2099
					len = ip->client->
2100
					    config->defaults[i].len +
2101
					    lease->options[i].len;
2102
					if (len >= sizeof(dbuf)) {
2103
						warning("no space to %s %s",
2104
						    "append option",
2105
						    dhcp_options[i].name);
2106
						goto supersede;
2107
					}
2108
					memcpy(dbuf,
2109
						lease->options[i].data,
2110
						lease->options[i].len);
2111
					for (dp = dbuf + lease->options[i].len;
2112
					    dp > dbuf; dp--, len--)
2113
						if (dp[-1] != '\0')
2114
							break;
2115
					memcpy(dp,
2116
						ip->client->
2117
						config->defaults[i].data,
2118
						ip->client->
2119
						config->defaults[i].len);
2120
					dp = dbuf;
2121
					dp[len] = '\0';
2122
				}
2123
			} else {
2124
				dp = ip->client->
2125
					config->defaults[i].data;
2126
				len = ip->client->
2127
					config->defaults[i].len;
2128
			}
2129
		} else if (lease->options[i].len) {
2130
			len = lease->options[i].len;
2131
			dp = lease->options[i].data;
2132
		} else {
2133
			len = 0;
2134
		}
2135
		if (len) {
2136
			char name[256];
2137

    
2138
			if (dhcp_option_ev_name(name, sizeof(name),
2139
			    &dhcp_options[i]))
2140
				script_set_env(ip->client, prefix, name,
2141
				    pretty_print_option(i, dp, len, 0, 0));
2142
		}
2143
	}
2144
	snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2145
	script_set_env(ip->client, prefix, "expiry", tbuf);
2146
}
2147

    
2148
void
2149
script_write_params(char *prefix, struct client_lease *lease)
2150
{
2151
	size_t		 fn_len = 0, sn_len = 0, pr_len = 0;
2152
	struct imsg_hdr	 hdr;
2153
	struct buf	*buf;
2154
	int		 errs, i;
2155

    
2156
	if (lease->filename != NULL)
2157
		fn_len = strlen(lease->filename);
2158
	if (lease->server_name != NULL)
2159
		sn_len = strlen(lease->server_name);
2160
	if (prefix != NULL)
2161
		pr_len = strlen(prefix);
2162

    
2163
	hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2164
	hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2165
	    sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2166
	    sizeof(size_t) + pr_len;
2167

    
2168
	for (i = 0; i < 256; i++)
2169
		hdr.len += sizeof(int) + lease->options[i].len;
2170

    
2171
	scripttime = time(NULL);
2172

    
2173
	if ((buf = buf_open(hdr.len)) == NULL)
2174
		error("buf_open: %m");
2175

    
2176
	errs = 0;
2177
	errs += buf_add(buf, &hdr, sizeof(hdr));
2178
	errs += buf_add(buf, lease, sizeof(struct client_lease));
2179
	errs += buf_add(buf, &fn_len, sizeof(fn_len));
2180
	errs += buf_add(buf, lease->filename, fn_len);
2181
	errs += buf_add(buf, &sn_len, sizeof(sn_len));
2182
	errs += buf_add(buf, lease->server_name, sn_len);
2183
	errs += buf_add(buf, &pr_len, sizeof(pr_len));
2184
	errs += buf_add(buf, prefix, pr_len);
2185

    
2186
	for (i = 0; i < 256; i++) {
2187
		errs += buf_add(buf, &lease->options[i].len,
2188
		    sizeof(lease->options[i].len));
2189
		errs += buf_add(buf, lease->options[i].data,
2190
		    lease->options[i].len);
2191
	}
2192

    
2193
	if (errs)
2194
		error("buf_add: %m");
2195

    
2196
	if (buf_close(privfd, buf) == -1)
2197
		error("buf_close: %m");
2198
}
2199

    
2200
int
2201
script_go(void)
2202
{
2203
	struct imsg_hdr	 hdr;
2204
	struct buf	*buf;
2205
	int		 ret;
2206

    
2207
	hdr.code = IMSG_SCRIPT_GO;
2208
	hdr.len = sizeof(struct imsg_hdr);
2209

    
2210
	if ((buf = buf_open(hdr.len)) == NULL)
2211
		error("buf_open: %m");
2212

    
2213
	if (buf_add(buf, &hdr, sizeof(hdr)))
2214
		error("buf_add: %m");
2215

    
2216
	if (buf_close(privfd, buf) == -1)
2217
		error("buf_close: %m");
2218

    
2219
	bzero(&hdr, sizeof(hdr));
2220
	buf_read(privfd, &hdr, sizeof(hdr));
2221
	if (hdr.code != IMSG_SCRIPT_GO_RET)
2222
		error("unexpected msg type %u", hdr.code);
2223
	if (hdr.len != sizeof(hdr) + sizeof(int))
2224
		error("received corrupted message");
2225
	buf_read(privfd, &ret, sizeof(ret));
2226

    
2227
	scripttime = time(NULL);
2228

    
2229
	return (ret);
2230
}
2231

    
2232
int
2233
priv_script_go(void)
2234
{
2235
	char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2236
	static char client_path[] = CLIENT_PATH;
2237
	struct interface_info *ip = ifi;
2238
	int pid, wpid, wstatus;
2239

    
2240
	scripttime = time(NULL);
2241

    
2242
	if (ip) {
2243
		scriptName = ip->client->config->script_name;
2244
		envp = ip->client->scriptEnv;
2245
	} else {
2246
		scriptName = top_level_config.script_name;
2247
		epp[0] = reason;
2248
		epp[1] = client_path;
2249
		epp[2] = NULL;
2250
		envp = epp;
2251
	}
2252

    
2253
	argv[0] = scriptName;
2254
	argv[1] = NULL;
2255

    
2256
	pid = fork();
2257
	if (pid < 0) {
2258
		error("fork: %m");
2259
		wstatus = 0;
2260
	} else if (pid) {
2261
		do {
2262
			wpid = wait(&wstatus);
2263
		} while (wpid != pid && wpid > 0);
2264
		if (wpid < 0) {
2265
			error("wait: %m");
2266
			wstatus = 0;
2267
		}
2268
	} else {
2269
		execve(scriptName, argv, envp);
2270
		error("execve (%s, ...): %m", scriptName);
2271
	}
2272

    
2273
	if (ip)
2274
		script_flush_env(ip->client);
2275

    
2276
	return (wstatus & 0xff);
2277
}
2278

    
2279
void
2280
script_set_env(struct client_state *client, const char *prefix,
2281
    const char *name, const char *value)
2282
{
2283
	int i, j, namelen;
2284

    
2285
	/* No `` or $() command substitution allowed in environment values! */
2286
	for (j=0; j < strlen(value); j++)
2287
		switch (value[j]) {
2288
		case '`':
2289
		case '$':
2290
			warning("illegal character (%c) in value '%s'",
2291
			    value[j], value);
2292
			/* Ignore this option */
2293
			return;
2294
		}
2295

    
2296
	namelen = strlen(name);
2297

    
2298
	for (i = 0; client->scriptEnv[i]; i++)
2299
		if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2300
		    client->scriptEnv[i][namelen] == '=')
2301
			break;
2302

    
2303
	if (client->scriptEnv[i])
2304
		/* Reuse the slot. */
2305
		free(client->scriptEnv[i]);
2306
	else {
2307
		/* New variable.  Expand if necessary. */
2308
		if (i >= client->scriptEnvsize - 1) {
2309
			char **newscriptEnv;
2310
			int newscriptEnvsize = client->scriptEnvsize + 50;
2311

    
2312
			newscriptEnv = realloc(client->scriptEnv,
2313
			    newscriptEnvsize);
2314
			if (newscriptEnv == NULL) {
2315
				free(client->scriptEnv);
2316
				client->scriptEnv = NULL;
2317
				client->scriptEnvsize = 0;
2318
				error("script_set_env: no memory for variable");
2319
			}
2320
			client->scriptEnv = newscriptEnv;
2321
			client->scriptEnvsize = newscriptEnvsize;
2322
		}
2323
		/* need to set the NULL pointer at end of array beyond
2324
		   the new slot. */
2325
		client->scriptEnv[i + 1] = NULL;
2326
	}
2327
	/* Allocate space and format the variable in the appropriate slot. */
2328
	client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2329
	    strlen(value) + 1);
2330
	if (client->scriptEnv[i] == NULL)
2331
		error("script_set_env: no memory for variable assignment");
2332
	snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2333
	    1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2334
}
2335

    
2336
void
2337
script_flush_env(struct client_state *client)
2338
{
2339
	int i;
2340

    
2341
	for (i = 0; client->scriptEnv[i]; i++) {
2342
		free(client->scriptEnv[i]);
2343
		client->scriptEnv[i] = NULL;
2344
	}
2345
	client->scriptEnvsize = 0;
2346
}
2347

    
2348
int
2349
dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2350
{
2351
	int i;
2352

    
2353
	for (i = 0; option->name[i]; i++) {
2354
		if (i + 1 == buflen)
2355
			return 0;
2356
		if (option->name[i] == '-')
2357
			buf[i] = '_';
2358
		else
2359
			buf[i] = option->name[i];
2360
	}
2361

    
2362
	buf[i] = 0;
2363
	return 1;
2364
}
2365

    
2366
void
2367
go_daemon(void)
2368
{
2369
	static int state = 0;
2370
	cap_rights_t rights;
2371

    
2372
	if (no_daemon || state)
2373
		return;
2374

    
2375
	state = 1;
2376

    
2377
	/* Stop logging to stderr... */
2378
	log_perror = 0;
2379

    
2380
	if (daemon(1, 0) == -1)
2381
		error("daemon");
2382

    
2383
	cap_rights_init(&rights);
2384

    
2385
	if (pidfile != NULL) {
2386
		pidfile_write(pidfile);
2387
		if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2388
		    errno != ENOSYS) {
2389
			error("can't limit pidfile descriptor: %m");
2390
		}
2391
	}
2392

    
2393
	/* we are chrooted, daemon(3) fails to open /dev/null */
2394
	if (nullfd != -1) {
2395
		dup2(nullfd, STDIN_FILENO);
2396
		dup2(nullfd, STDOUT_FILENO);
2397
		dup2(nullfd, STDERR_FILENO);
2398
		close(nullfd);
2399
		nullfd = -1;
2400
	}
2401

    
2402
	if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2403
		error("can't limit stdin: %m");
2404
	cap_rights_init(&rights, CAP_WRITE);
2405
	if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2406
		error("can't limit stdout: %m");
2407
	if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2408
		error("can't limit stderr: %m");
2409
}
2410

    
2411
int
2412
check_option(struct client_lease *l, int option)
2413
{
2414
	char *opbuf;
2415
	char *sbuf;
2416

    
2417
	/* we use this, since this is what gets passed to dhclient-script */
2418

    
2419
	opbuf = pretty_print_option(option, l->options[option].data,
2420
	    l->options[option].len, 0, 0);
2421

    
2422
	sbuf = option_as_string(option, l->options[option].data,
2423
	    l->options[option].len);
2424

    
2425
	switch (option) {
2426
	case DHO_SUBNET_MASK:
2427
	case DHO_TIME_SERVERS:
2428
	case DHO_NAME_SERVERS:
2429
	case DHO_ROUTERS:
2430
	case DHO_DOMAIN_NAME_SERVERS:
2431
	case DHO_LOG_SERVERS:
2432
	case DHO_COOKIE_SERVERS:
2433
	case DHO_LPR_SERVERS:
2434
	case DHO_IMPRESS_SERVERS:
2435
	case DHO_RESOURCE_LOCATION_SERVERS:
2436
	case DHO_SWAP_SERVER:
2437
	case DHO_BROADCAST_ADDRESS:
2438
	case DHO_NIS_SERVERS:
2439
	case DHO_NTP_SERVERS:
2440
	case DHO_NETBIOS_NAME_SERVERS:
2441
	case DHO_NETBIOS_DD_SERVER:
2442
	case DHO_FONT_SERVERS:
2443
	case DHO_DHCP_SERVER_IDENTIFIER:
2444
	case DHO_NISPLUS_SERVERS:
2445
	case DHO_MOBILE_IP_HOME_AGENT:
2446
	case DHO_SMTP_SERVER:
2447
	case DHO_POP_SERVER:
2448
	case DHO_NNTP_SERVER:
2449
	case DHO_WWW_SERVER:
2450
	case DHO_FINGER_SERVER:
2451
	case DHO_IRC_SERVER:
2452
	case DHO_STREETTALK_SERVER:
2453
	case DHO_STREETTALK_DA_SERVER:
2454
		if (!ipv4addrs(opbuf)) {
2455
			warning("Invalid IP address in option: %s", opbuf);
2456
			return (0);
2457
		}
2458
		return (1)  ;
2459
	case DHO_HOST_NAME:
2460
	case DHO_NIS_DOMAIN:
2461
	case DHO_NISPLUS_DOMAIN:
2462
	case DHO_TFTP_SERVER_NAME:
2463
		if (!res_hnok(sbuf)) {
2464
			warning("Bogus Host Name option %d: %s (%s)", option,
2465
			    sbuf, opbuf);
2466
			l->options[option].len = 0;
2467
			free(l->options[option].data);
2468
		}
2469
		return (1);
2470
	case DHO_DOMAIN_NAME:
2471
	case DHO_DOMAIN_SEARCH:
2472
		if (!res_hnok(sbuf)) {
2473
			if (!check_search(sbuf)) {
2474
				warning("Bogus domain search list %d: %s (%s)",
2475
				    option, sbuf, opbuf);
2476
				l->options[option].len = 0;
2477
				free(l->options[option].data);
2478
			}
2479
		}
2480
		return (1);
2481
	case DHO_PAD:
2482
	case DHO_TIME_OFFSET:
2483
	case DHO_BOOT_SIZE:
2484
	case DHO_MERIT_DUMP:
2485
	case DHO_ROOT_PATH:
2486
	case DHO_EXTENSIONS_PATH:
2487
	case DHO_IP_FORWARDING:
2488
	case DHO_NON_LOCAL_SOURCE_ROUTING:
2489
	case DHO_POLICY_FILTER:
2490
	case DHO_MAX_DGRAM_REASSEMBLY:
2491
	case DHO_DEFAULT_IP_TTL:
2492
	case DHO_PATH_MTU_AGING_TIMEOUT:
2493
	case DHO_PATH_MTU_PLATEAU_TABLE:
2494
	case DHO_INTERFACE_MTU:
2495
	case DHO_ALL_SUBNETS_LOCAL:
2496
	case DHO_PERFORM_MASK_DISCOVERY:
2497
	case DHO_MASK_SUPPLIER:
2498
	case DHO_ROUTER_DISCOVERY:
2499
	case DHO_ROUTER_SOLICITATION_ADDRESS:
2500
	case DHO_STATIC_ROUTES:
2501
	case DHO_TRAILER_ENCAPSULATION:
2502
	case DHO_ARP_CACHE_TIMEOUT:
2503
	case DHO_IEEE802_3_ENCAPSULATION:
2504
	case DHO_DEFAULT_TCP_TTL:
2505
	case DHO_TCP_KEEPALIVE_INTERVAL:
2506
	case DHO_TCP_KEEPALIVE_GARBAGE:
2507
	case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2508
	case DHO_NETBIOS_NODE_TYPE:
2509
	case DHO_NETBIOS_SCOPE:
2510
	case DHO_X_DISPLAY_MANAGER:
2511
	case DHO_DHCP_REQUESTED_ADDRESS:
2512
	case DHO_DHCP_LEASE_TIME:
2513
	case DHO_DHCP_OPTION_OVERLOAD:
2514
	case DHO_DHCP_MESSAGE_TYPE:
2515
	case DHO_DHCP_PARAMETER_REQUEST_LIST:
2516
	case DHO_DHCP_MESSAGE:
2517
	case DHO_DHCP_MAX_MESSAGE_SIZE:
2518
	case DHO_DHCP_RENEWAL_TIME:
2519
	case DHO_DHCP_REBINDING_TIME:
2520
	case DHO_DHCP_CLASS_IDENTIFIER:
2521
	case DHO_DHCP_CLIENT_IDENTIFIER:
2522
	case DHO_BOOTFILE_NAME:
2523
	case DHO_DHCP_USER_CLASS_ID:
2524
	case DHO_END:
2525
		return (1);
2526
	case DHO_CLASSLESS_ROUTES:
2527
		return (check_classless_option(l->options[option].data,
2528
		    l->options[option].len));
2529
	default:
2530
		warning("unknown dhcp option value 0x%x", option);
2531
		return (unknown_ok);
2532
	}
2533
}
2534

    
2535
/* RFC 3442 The Classless Static Routes option checks */
2536
int
2537
check_classless_option(unsigned char *data, int len)
2538
{
2539
	int i = 0;
2540
	unsigned char width;
2541
	in_addr_t addr, mask;
2542

    
2543
	if (len < 5) {
2544
		warning("Too small length: %d", len);
2545
		return (0);
2546
	}
2547
	while(i < len) {
2548
		width = data[i++];
2549
		if (width == 0) {
2550
			i += 4;
2551
			continue;
2552
		} else if (width < 9) {
2553
			addr =  (in_addr_t)(data[i]	<< 24);
2554
			i += 1;
2555
		} else if (width < 17) {
2556
			addr =  (in_addr_t)(data[i]	<< 24) +
2557
				(in_addr_t)(data[i + 1]	<< 16);
2558
			i += 2;
2559
		} else if (width < 25) {
2560
			addr =  (in_addr_t)(data[i]	<< 24) +
2561
				(in_addr_t)(data[i + 1]	<< 16) +
2562
				(in_addr_t)(data[i + 2]	<< 8);
2563
			i += 3;
2564
		} else if (width < 33) {
2565
			addr =  (in_addr_t)(data[i]	<< 24) +
2566
				(in_addr_t)(data[i + 1]	<< 16) +
2567
				(in_addr_t)(data[i + 2]	<< 8)  +
2568
				data[i + 3];
2569
			i += 4;
2570
		} else {
2571
			warning("Incorrect subnet width: %d", width);
2572
			return (0);
2573
		}
2574
		mask = (in_addr_t)(~0) << (32 - width);
2575
		addr = ntohl(addr);
2576
		mask = ntohl(mask);
2577

    
2578
		/*
2579
		 * From RFC 3442:
2580
		 * ... After deriving a subnet number and subnet mask
2581
		 * from each destination descriptor, the DHCP client
2582
		 * MUST zero any bits in the subnet number where the
2583
		 * corresponding bit in the mask is zero...
2584
		 */
2585
		if ((addr & mask) != addr) {
2586
			addr &= mask;
2587
			data[i - 1] = (unsigned char)(
2588
				(addr >> (((32 - width)/8)*8)) & 0xFF);
2589
		}
2590
		i += 4;
2591
	}
2592
	if (i > len) {
2593
		warning("Incorrect data length: %d (must be %d)", len, i);
2594
		return (0);
2595
	}
2596
	return (1);
2597
}
2598

    
2599
int
2600
res_hnok(const char *dn)
2601
{
2602
	int pch = PERIOD, ch = *dn++;
2603

    
2604
	while (ch != '\0') {
2605
		int nch = *dn++;
2606

    
2607
		if (periodchar(ch)) {
2608
			;
2609
		} else if (periodchar(pch)) {
2610
			if (!borderchar(ch))
2611
				return (0);
2612
		} else if (periodchar(nch) || nch == '\0') {
2613
			if (!borderchar(ch))
2614
				return (0);
2615
		} else {
2616
			if (!middlechar(ch))
2617
				return (0);
2618
		}
2619
		pch = ch, ch = nch;
2620
	}
2621
	return (1);
2622
}
2623

    
2624
int
2625
check_search(const char *srch)
2626
{
2627
        int pch = PERIOD, ch = *srch++;
2628
	int domains = 1;
2629

    
2630
	/* 256 char limit re resolv.conf(5) */
2631
	if (strlen(srch) > 256)
2632
		return (0);
2633

    
2634
	while (whitechar(ch))
2635
		ch = *srch++;
2636

    
2637
        while (ch != '\0') {
2638
                int nch = *srch++;
2639

    
2640
                if (periodchar(ch) || whitechar(ch)) {
2641
                        ;
2642
                } else if (periodchar(pch)) {
2643
                        if (!borderchar(ch))
2644
                                return (0);
2645
                } else if (periodchar(nch) || nch == '\0') {
2646
                        if (!borderchar(ch))
2647
                                return (0);
2648
                } else {
2649
                        if (!middlechar(ch))
2650
                                return (0);
2651
                }
2652
		if (!whitechar(ch)) {
2653
			pch = ch;
2654
		} else {
2655
			while (whitechar(nch)) {
2656
				nch = *srch++;
2657
			}
2658
			if (nch != '\0')
2659
				domains++;
2660
			pch = PERIOD;
2661
		}
2662
		ch = nch;
2663
        }
2664
	/* 6 domain limit re resolv.conf(5) */
2665
	if (domains > 6)
2666
		return (0);
2667
        return (1);
2668
}
2669

    
2670
/* Does buf consist only of dotted decimal ipv4 addrs?
2671
 * return how many if so,
2672
 * otherwise, return 0
2673
 */
2674
int
2675
ipv4addrs(char * buf)
2676
{
2677
	struct in_addr jnk;
2678
	int count = 0;
2679

    
2680
	while (inet_aton(buf, &jnk) == 1){
2681
		count++;
2682
		while (periodchar(*buf) || digitchar(*buf))
2683
			buf++;
2684
		if (*buf == '\0')
2685
			return (count);
2686
		while (*buf ==  ' ')
2687
			buf++;
2688
	}
2689
	return (0);
2690
}
2691

    
2692

    
2693
char *
2694
option_as_string(unsigned int code, unsigned char *data, int len)
2695
{
2696
	static char optbuf[32768]; /* XXX */
2697
	char *op = optbuf;
2698
	int opleft = sizeof(optbuf);
2699
	unsigned char *dp = data;
2700

    
2701
	if (code > 255)
2702
		error("option_as_string: bad code %d", code);
2703

    
2704
	for (; dp < data + len; dp++) {
2705
		if (!isascii(*dp) || !isprint(*dp)) {
2706
			if (dp + 1 != data + len || *dp != 0) {
2707
				snprintf(op, opleft, "\\%03o", *dp);
2708
				op += 4;
2709
				opleft -= 4;
2710
			}
2711
		} else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2712
		    *dp == '`' || *dp == '\\') {
2713
			*op++ = '\\';
2714
			*op++ = *dp;
2715
			opleft -= 2;
2716
		} else {
2717
			*op++ = *dp;
2718
			opleft--;
2719
		}
2720
	}
2721
	if (opleft < 1)
2722
		goto toobig;
2723
	*op = 0;
2724
	return optbuf;
2725
toobig:
2726
	warning("dhcp option too large");
2727
	return "<error>";
2728
}
2729

    
2730
int
2731
fork_privchld(int fd, int fd2)
2732
{
2733
	struct pollfd pfd[1];
2734
	int nfds;
2735

    
2736
	switch (fork()) {
2737
	case -1:
2738
		error("cannot fork");
2739
	case 0:
2740
		break;
2741
	default:
2742
		return (0);
2743
	}
2744

    
2745
	setproctitle("%s [priv]", ifi->name);
2746

    
2747
	setsid();
2748
	dup2(nullfd, STDIN_FILENO);
2749
	dup2(nullfd, STDOUT_FILENO);
2750
	dup2(nullfd, STDERR_FILENO);
2751
	close(nullfd);
2752
	close(fd2);
2753
	close(ifi->rfdesc);
2754
	ifi->rfdesc = -1;
2755

    
2756
	for (;;) {
2757
		pfd[0].fd = fd;
2758
		pfd[0].events = POLLIN;
2759
		if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2760
			if (errno != EINTR)
2761
				error("poll error");
2762

    
2763
		if (nfds == 0 || !(pfd[0].revents & POLLIN))
2764
			continue;
2765

    
2766
		dispatch_imsg(ifi, fd);
2767
	}
2768
}
    (1-1/1)