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