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