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