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