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