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