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