]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/dhclient/dhclient.c
MFC r329754:
[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 const 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(const char * buf);
131 int              res_hnok(const char *dn);
132 int              check_search(const char *srch);
133 const 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         unsigned 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         unsigned 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 = { .len = 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 void
218 routehandler(struct protocol *p __unused)
219 {
220         char msg[2048], *addr;
221         struct rt_msghdr *rtm;
222         struct if_msghdr *ifm;
223         struct ifa_msghdr *ifam;
224         struct if_announcemsghdr *ifan;
225         struct ieee80211_join_event *jev;
226         struct client_lease *l;
227         time_t t = time(NULL);
228         struct sockaddr_in *sa;
229         struct iaddr a;
230         ssize_t n;
231         int linkstat;
232
233         n = read(routefd, &msg, sizeof(msg));
234         rtm = (struct rt_msghdr *)msg;
235         if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
236             n < (ssize_t)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 = (struct sockaddr_in*)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, &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(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         const 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         const 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             ip->client->state != S_REBOOTING)
1497                 memcpy(&from, ip->client->active->address.iabuf,
1498                     sizeof(from));
1499         else
1500                 from.s_addr = INADDR_ANY;
1501
1502         /* Record the number of seconds since we started sending. */
1503         if (ip->client->state == S_REQUESTING)
1504                 ip->client->packet.secs = ip->client->secs;
1505         else {
1506                 if (interval < 65536)
1507                         ip->client->packet.secs = htons(interval);
1508                 else
1509                         ip->client->packet.secs = htons(65535);
1510         }
1511
1512         note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1513             REMOTE_PORT);
1514
1515         /* Send out a packet. */
1516         send_packet_unpriv(privfd, &ip->client->packet,
1517             ip->client->packet_length, from, to);
1518
1519         add_timeout(cur_time + ip->client->interval, send_request, ip);
1520 }
1521
1522 void
1523 send_decline(void *ipp)
1524 {
1525         struct interface_info *ip = ipp;
1526
1527         note("DHCPDECLINE on %s to %s port %d", ip->name,
1528             inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1529
1530         /* Send out a packet. */
1531         send_packet_unpriv(privfd, &ip->client->packet,
1532             ip->client->packet_length, inaddr_any, inaddr_broadcast);
1533 }
1534
1535 void
1536 make_discover(struct interface_info *ip, struct client_lease *lease)
1537 {
1538         unsigned char discover = DHCPDISCOVER;
1539         struct tree_cache *options[256];
1540         struct tree_cache option_elements[256];
1541         int i;
1542
1543         memset(option_elements, 0, sizeof(option_elements));
1544         memset(options, 0, sizeof(options));
1545         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1546
1547         /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1548         i = DHO_DHCP_MESSAGE_TYPE;
1549         options[i] = &option_elements[i];
1550         options[i]->value = &discover;
1551         options[i]->len = sizeof(discover);
1552         options[i]->buf_size = sizeof(discover);
1553         options[i]->timeout = 0xFFFFFFFF;
1554
1555         /* Request the options we want */
1556         i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1557         options[i] = &option_elements[i];
1558         options[i]->value = ip->client->config->requested_options;
1559         options[i]->len = ip->client->config->requested_option_count;
1560         options[i]->buf_size =
1561                 ip->client->config->requested_option_count;
1562         options[i]->timeout = 0xFFFFFFFF;
1563
1564         /* If we had an address, try to get it again. */
1565         if (lease) {
1566                 ip->client->requested_address = lease->address;
1567                 i = DHO_DHCP_REQUESTED_ADDRESS;
1568                 options[i] = &option_elements[i];
1569                 options[i]->value = lease->address.iabuf;
1570                 options[i]->len = lease->address.len;
1571                 options[i]->buf_size = lease->address.len;
1572                 options[i]->timeout = 0xFFFFFFFF;
1573         } else
1574                 ip->client->requested_address.len = 0;
1575
1576         /* Send any options requested in the config file. */
1577         for (i = 0; i < 256; i++)
1578                 if (!options[i] &&
1579                     ip->client->config->send_options[i].data) {
1580                         options[i] = &option_elements[i];
1581                         options[i]->value =
1582                             ip->client->config->send_options[i].data;
1583                         options[i]->len =
1584                             ip->client->config->send_options[i].len;
1585                         options[i]->buf_size =
1586                             ip->client->config->send_options[i].len;
1587                         options[i]->timeout = 0xFFFFFFFF;
1588                 }
1589
1590         /* send host name if not set via config file. */
1591         if (!options[DHO_HOST_NAME]) {
1592                 if (hostname[0] != '\0') {
1593                         size_t len;
1594                         char* posDot = strchr(hostname, '.');
1595                         if (posDot != NULL)
1596                                 len = posDot - hostname;
1597                         else
1598                                 len = strlen(hostname);
1599                         options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1600                         options[DHO_HOST_NAME]->value = hostname;
1601                         options[DHO_HOST_NAME]->len = len;
1602                         options[DHO_HOST_NAME]->buf_size = len;
1603                         options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1604                 }
1605         }
1606
1607         /* set unique client identifier */
1608         char client_ident[sizeof(ip->hw_address.haddr) + 1];
1609         if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1610                 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1611                                 ip->hw_address.hlen : sizeof(client_ident)-1;
1612                 client_ident[0] = ip->hw_address.htype;
1613                 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1614                 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1615                 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1616                 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1617                 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1618                 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1619         }
1620
1621         /* Set up the option buffer... */
1622         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1623             options, 0, 0, 0, NULL, 0);
1624         if (ip->client->packet_length < BOOTP_MIN_LEN)
1625                 ip->client->packet_length = BOOTP_MIN_LEN;
1626
1627         ip->client->packet.op = BOOTREQUEST;
1628         ip->client->packet.htype = ip->hw_address.htype;
1629         ip->client->packet.hlen = ip->hw_address.hlen;
1630         ip->client->packet.hops = 0;
1631         ip->client->packet.xid = arc4random();
1632         ip->client->packet.secs = 0; /* filled in by send_discover. */
1633         ip->client->packet.flags = 0;
1634
1635         memset(&(ip->client->packet.ciaddr),
1636             0, sizeof(ip->client->packet.ciaddr));
1637         memset(&(ip->client->packet.yiaddr),
1638             0, sizeof(ip->client->packet.yiaddr));
1639         memset(&(ip->client->packet.siaddr),
1640             0, sizeof(ip->client->packet.siaddr));
1641         memset(&(ip->client->packet.giaddr),
1642             0, sizeof(ip->client->packet.giaddr));
1643         memcpy(ip->client->packet.chaddr,
1644             ip->hw_address.haddr, ip->hw_address.hlen);
1645 }
1646
1647
1648 void
1649 make_request(struct interface_info *ip, struct client_lease * lease)
1650 {
1651         unsigned char request = DHCPREQUEST;
1652         struct tree_cache *options[256];
1653         struct tree_cache option_elements[256];
1654         int i;
1655
1656         memset(options, 0, sizeof(options));
1657         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1658
1659         /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1660         i = DHO_DHCP_MESSAGE_TYPE;
1661         options[i] = &option_elements[i];
1662         options[i]->value = &request;
1663         options[i]->len = sizeof(request);
1664         options[i]->buf_size = sizeof(request);
1665         options[i]->timeout = 0xFFFFFFFF;
1666
1667         /* Request the options we want */
1668         i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1669         options[i] = &option_elements[i];
1670         options[i]->value = ip->client->config->requested_options;
1671         options[i]->len = ip->client->config->requested_option_count;
1672         options[i]->buf_size =
1673                 ip->client->config->requested_option_count;
1674         options[i]->timeout = 0xFFFFFFFF;
1675
1676         /* If we are requesting an address that hasn't yet been assigned
1677            to us, use the DHCP Requested Address option. */
1678         if (ip->client->state == S_REQUESTING) {
1679                 /* Send back the server identifier... */
1680                 i = DHO_DHCP_SERVER_IDENTIFIER;
1681                 options[i] = &option_elements[i];
1682                 options[i]->value = lease->options[i].data;
1683                 options[i]->len = lease->options[i].len;
1684                 options[i]->buf_size = lease->options[i].len;
1685                 options[i]->timeout = 0xFFFFFFFF;
1686         }
1687         if (ip->client->state == S_REQUESTING ||
1688             ip->client->state == S_REBOOTING) {
1689                 ip->client->requested_address = lease->address;
1690                 i = DHO_DHCP_REQUESTED_ADDRESS;
1691                 options[i] = &option_elements[i];
1692                 options[i]->value = lease->address.iabuf;
1693                 options[i]->len = lease->address.len;
1694                 options[i]->buf_size = lease->address.len;
1695                 options[i]->timeout = 0xFFFFFFFF;
1696         } else
1697                 ip->client->requested_address.len = 0;
1698
1699         /* Send any options requested in the config file. */
1700         for (i = 0; i < 256; i++)
1701                 if (!options[i] &&
1702                     ip->client->config->send_options[i].data) {
1703                         options[i] = &option_elements[i];
1704                         options[i]->value =
1705                             ip->client->config->send_options[i].data;
1706                         options[i]->len =
1707                             ip->client->config->send_options[i].len;
1708                         options[i]->buf_size =
1709                             ip->client->config->send_options[i].len;
1710                         options[i]->timeout = 0xFFFFFFFF;
1711                 }
1712
1713         /* send host name if not set via config file. */
1714         if (!options[DHO_HOST_NAME]) {
1715                 if (hostname[0] != '\0') {
1716                         size_t len;
1717                         char* posDot = strchr(hostname, '.');
1718                         if (posDot != NULL)
1719                                 len = posDot - hostname;
1720                         else
1721                                 len = strlen(hostname);
1722                         options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1723                         options[DHO_HOST_NAME]->value = hostname;
1724                         options[DHO_HOST_NAME]->len = len;
1725                         options[DHO_HOST_NAME]->buf_size = len;
1726                         options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1727                 }
1728         }
1729
1730         /* set unique client identifier */
1731         char client_ident[sizeof(struct hardware)];
1732         if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1733                 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1734                                 ip->hw_address.hlen : sizeof(client_ident)-1;
1735                 client_ident[0] = ip->hw_address.htype;
1736                 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1737                 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1738                 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1739                 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1740                 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1741                 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1742         }
1743
1744         /* Set up the option buffer... */
1745         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1746             options, 0, 0, 0, NULL, 0);
1747         if (ip->client->packet_length < BOOTP_MIN_LEN)
1748                 ip->client->packet_length = BOOTP_MIN_LEN;
1749
1750         ip->client->packet.op = BOOTREQUEST;
1751         ip->client->packet.htype = ip->hw_address.htype;
1752         ip->client->packet.hlen = ip->hw_address.hlen;
1753         ip->client->packet.hops = 0;
1754         ip->client->packet.xid = ip->client->xid;
1755         ip->client->packet.secs = 0; /* Filled in by send_request. */
1756
1757         /* If we own the address we're requesting, put it in ciaddr;
1758            otherwise set ciaddr to zero. */
1759         if (ip->client->state == S_BOUND ||
1760             ip->client->state == S_RENEWING ||
1761             ip->client->state == S_REBINDING) {
1762                 memcpy(&ip->client->packet.ciaddr,
1763                     lease->address.iabuf, lease->address.len);
1764                 ip->client->packet.flags = 0;
1765         } else {
1766                 memset(&ip->client->packet.ciaddr, 0,
1767                     sizeof(ip->client->packet.ciaddr));
1768                 ip->client->packet.flags = 0;
1769         }
1770
1771         memset(&ip->client->packet.yiaddr, 0,
1772             sizeof(ip->client->packet.yiaddr));
1773         memset(&ip->client->packet.siaddr, 0,
1774             sizeof(ip->client->packet.siaddr));
1775         memset(&ip->client->packet.giaddr, 0,
1776             sizeof(ip->client->packet.giaddr));
1777         memcpy(ip->client->packet.chaddr,
1778             ip->hw_address.haddr, ip->hw_address.hlen);
1779 }
1780
1781 void
1782 make_decline(struct interface_info *ip, struct client_lease *lease)
1783 {
1784         struct tree_cache *options[256], message_type_tree;
1785         struct tree_cache requested_address_tree;
1786         struct tree_cache server_id_tree, client_id_tree;
1787         unsigned char decline = DHCPDECLINE;
1788         int i;
1789
1790         memset(options, 0, sizeof(options));
1791         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1792
1793         /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1794         i = DHO_DHCP_MESSAGE_TYPE;
1795         options[i] = &message_type_tree;
1796         options[i]->value = &decline;
1797         options[i]->len = sizeof(decline);
1798         options[i]->buf_size = sizeof(decline);
1799         options[i]->timeout = 0xFFFFFFFF;
1800
1801         /* Send back the server identifier... */
1802         i = DHO_DHCP_SERVER_IDENTIFIER;
1803         options[i] = &server_id_tree;
1804         options[i]->value = lease->options[i].data;
1805         options[i]->len = lease->options[i].len;
1806         options[i]->buf_size = lease->options[i].len;
1807         options[i]->timeout = 0xFFFFFFFF;
1808
1809         /* Send back the address we're declining. */
1810         i = DHO_DHCP_REQUESTED_ADDRESS;
1811         options[i] = &requested_address_tree;
1812         options[i]->value = lease->address.iabuf;
1813         options[i]->len = lease->address.len;
1814         options[i]->buf_size = lease->address.len;
1815         options[i]->timeout = 0xFFFFFFFF;
1816
1817         /* Send the uid if the user supplied one. */
1818         i = DHO_DHCP_CLIENT_IDENTIFIER;
1819         if (ip->client->config->send_options[i].len) {
1820                 options[i] = &client_id_tree;
1821                 options[i]->value = ip->client->config->send_options[i].data;
1822                 options[i]->len = ip->client->config->send_options[i].len;
1823                 options[i]->buf_size = ip->client->config->send_options[i].len;
1824                 options[i]->timeout = 0xFFFFFFFF;
1825         }
1826
1827
1828         /* Set up the option buffer... */
1829         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1830             options, 0, 0, 0, NULL, 0);
1831         if (ip->client->packet_length < BOOTP_MIN_LEN)
1832                 ip->client->packet_length = BOOTP_MIN_LEN;
1833
1834         ip->client->packet.op = BOOTREQUEST;
1835         ip->client->packet.htype = ip->hw_address.htype;
1836         ip->client->packet.hlen = ip->hw_address.hlen;
1837         ip->client->packet.hops = 0;
1838         ip->client->packet.xid = ip->client->xid;
1839         ip->client->packet.secs = 0; /* Filled in by send_request. */
1840         ip->client->packet.flags = 0;
1841
1842         /* ciaddr must always be zero. */
1843         memset(&ip->client->packet.ciaddr, 0,
1844             sizeof(ip->client->packet.ciaddr));
1845         memset(&ip->client->packet.yiaddr, 0,
1846             sizeof(ip->client->packet.yiaddr));
1847         memset(&ip->client->packet.siaddr, 0,
1848             sizeof(ip->client->packet.siaddr));
1849         memset(&ip->client->packet.giaddr, 0,
1850             sizeof(ip->client->packet.giaddr));
1851         memcpy(ip->client->packet.chaddr,
1852             ip->hw_address.haddr, ip->hw_address.hlen);
1853 }
1854
1855 void
1856 free_client_lease(struct client_lease *lease)
1857 {
1858         int i;
1859
1860         if (lease->server_name)
1861                 free(lease->server_name);
1862         if (lease->filename)
1863                 free(lease->filename);
1864         for (i = 0; i < 256; i++) {
1865                 if (lease->options[i].len)
1866                         free(lease->options[i].data);
1867         }
1868         free(lease);
1869 }
1870
1871 FILE *leaseFile;
1872
1873 void
1874 rewrite_client_leases(void)
1875 {
1876         struct client_lease *lp;
1877         cap_rights_t rights;
1878
1879         if (!leaseFile) {
1880                 leaseFile = fopen(path_dhclient_db, "w");
1881                 if (!leaseFile)
1882                         error("can't create %s: %m", path_dhclient_db);
1883                 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1884                     CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1885                 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1886                     errno != ENOSYS) {
1887                         error("can't limit lease descriptor: %m");
1888                 }
1889                 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1890                     errno != ENOSYS) {
1891                         error("can't limit lease descriptor fcntls: %m");
1892                 }
1893         } else {
1894                 fflush(leaseFile);
1895                 rewind(leaseFile);
1896         }
1897
1898         for (lp = ifi->client->leases; lp; lp = lp->next)
1899                 write_client_lease(ifi, lp, 1);
1900         if (ifi->client->active)
1901                 write_client_lease(ifi, ifi->client->active, 1);
1902
1903         fflush(leaseFile);
1904         ftruncate(fileno(leaseFile), ftello(leaseFile));
1905         fsync(fileno(leaseFile));
1906 }
1907
1908 void
1909 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1910     int rewrite)
1911 {
1912         static int leases_written;
1913         struct tm *t;
1914         int i;
1915
1916         if (!rewrite) {
1917                 if (leases_written++ > 20) {
1918                         rewrite_client_leases();
1919                         leases_written = 0;
1920                 }
1921         }
1922
1923         /* If the lease came from the config file, we don't need to stash
1924            a copy in the lease database. */
1925         if (lease->is_static)
1926                 return;
1927
1928         if (!leaseFile) {       /* XXX */
1929                 leaseFile = fopen(path_dhclient_db, "w");
1930                 if (!leaseFile)
1931                         error("can't create %s: %m", path_dhclient_db);
1932         }
1933
1934         fprintf(leaseFile, "lease {\n");
1935         if (lease->is_bootp)
1936                 fprintf(leaseFile, "  bootp;\n");
1937         fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1938         fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1939         if (lease->nextserver.len == sizeof(inaddr_any) &&
1940             0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1941             sizeof(inaddr_any)))
1942                 fprintf(leaseFile, "  next-server %s;\n",
1943                     piaddr(lease->nextserver));
1944         if (lease->filename)
1945                 fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1946         if (lease->server_name)
1947                 fprintf(leaseFile, "  server-name \"%s\";\n",
1948                     lease->server_name);
1949         if (lease->medium)
1950                 fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1951         for (i = 0; i < 256; i++)
1952                 if (lease->options[i].len)
1953                         fprintf(leaseFile, "  option %s %s;\n",
1954                             dhcp_options[i].name,
1955                             pretty_print_option(i, lease->options[i].data,
1956                             lease->options[i].len, 1, 1));
1957
1958         t = gmtime(&lease->renewal);
1959         fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
1960             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1961             t->tm_hour, t->tm_min, t->tm_sec);
1962         t = gmtime(&lease->rebind);
1963         fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1964             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1965             t->tm_hour, t->tm_min, t->tm_sec);
1966         t = gmtime(&lease->expiry);
1967         fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
1968             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1969             t->tm_hour, t->tm_min, t->tm_sec);
1970         fprintf(leaseFile, "}\n");
1971         fflush(leaseFile);
1972 }
1973
1974 void
1975 script_init(const char *reason, struct string_list *medium)
1976 {
1977         size_t           len, mediumlen = 0;
1978         struct imsg_hdr  hdr;
1979         struct buf      *buf;
1980         int              errs;
1981
1982         if (medium != NULL && medium->string != NULL)
1983                 mediumlen = strlen(medium->string);
1984
1985         hdr.code = IMSG_SCRIPT_INIT;
1986         hdr.len = sizeof(struct imsg_hdr) +
1987             sizeof(size_t) + mediumlen +
1988             sizeof(size_t) + strlen(reason);
1989
1990         if ((buf = buf_open(hdr.len)) == NULL)
1991                 error("buf_open: %m");
1992
1993         errs = 0;
1994         errs += buf_add(buf, &hdr, sizeof(hdr));
1995         errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1996         if (mediumlen > 0)
1997                 errs += buf_add(buf, medium->string, mediumlen);
1998         len = strlen(reason);
1999         errs += buf_add(buf, &len, sizeof(len));
2000         errs += buf_add(buf, reason, len);
2001
2002         if (errs)
2003                 error("buf_add: %m");
2004
2005         if (buf_close(privfd, buf) == -1)
2006                 error("buf_close: %m");
2007 }
2008
2009 void
2010 priv_script_init(const char *reason, char *medium)
2011 {
2012         struct interface_info *ip = ifi;
2013
2014         if (ip) {
2015                 ip->client->scriptEnvsize = 100;
2016                 if (ip->client->scriptEnv == NULL)
2017                         ip->client->scriptEnv =
2018                             malloc(ip->client->scriptEnvsize * sizeof(char *));
2019                 if (ip->client->scriptEnv == NULL)
2020                         error("script_init: no memory for environment");
2021
2022                 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2023                 if (ip->client->scriptEnv[0] == NULL)
2024                         error("script_init: no memory for environment");
2025
2026                 ip->client->scriptEnv[1] = NULL;
2027
2028                 script_set_env(ip->client, "", "interface", ip->name);
2029
2030                 if (medium)
2031                         script_set_env(ip->client, "", "medium", medium);
2032
2033                 script_set_env(ip->client, "", "reason", reason);
2034         }
2035 }
2036
2037 void
2038 priv_script_write_params(const char *prefix, struct client_lease *lease)
2039 {
2040         struct interface_info *ip = ifi;
2041         u_int8_t dbuf[1500], *dp = NULL;
2042         int i;
2043         size_t len;
2044         char tbuf[128];
2045
2046         script_set_env(ip->client, prefix, "ip_address",
2047             piaddr(lease->address));
2048
2049         if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2050             ACTION_SUPERSEDE) {
2051                 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2052                 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2053         } else {
2054                 dp = lease->options[DHO_SUBNET_MASK].data;
2055                 len = lease->options[DHO_SUBNET_MASK].len;
2056         }
2057         if (len && (len < sizeof(lease->address.iabuf))) {
2058                 struct iaddr netmask, subnet, broadcast;
2059
2060                 memcpy(netmask.iabuf, dp, len);
2061                 netmask.len = len;
2062                 subnet = subnet_number(lease->address, netmask);
2063                 if (subnet.len) {
2064                         script_set_env(ip->client, prefix, "network_number",
2065                             piaddr(subnet));
2066                         if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2067                                 broadcast = broadcast_addr(subnet, netmask);
2068                                 if (broadcast.len)
2069                                         script_set_env(ip->client, prefix,
2070                                             "broadcast_address",
2071                                             piaddr(broadcast));
2072                         }
2073                 }
2074         }
2075
2076         if (lease->filename)
2077                 script_set_env(ip->client, prefix, "filename", lease->filename);
2078         if (lease->server_name)
2079                 script_set_env(ip->client, prefix, "server_name",
2080                     lease->server_name);
2081         for (i = 0; i < 256; i++) {
2082                 len = 0;
2083
2084                 if (ip->client->config->defaults[i].len) {
2085                         if (lease->options[i].len) {
2086                                 switch (
2087                                     ip->client->config->default_actions[i]) {
2088                                 case ACTION_DEFAULT:
2089                                         dp = lease->options[i].data;
2090                                         len = lease->options[i].len;
2091                                         break;
2092                                 case ACTION_SUPERSEDE:
2093 supersede:
2094                                         dp = ip->client->
2095                                                 config->defaults[i].data;
2096                                         len = ip->client->
2097                                                 config->defaults[i].len;
2098                                         break;
2099                                 case ACTION_PREPEND:
2100                                         len = ip->client->
2101                                             config->defaults[i].len +
2102                                             lease->options[i].len;
2103                                         if (len >= sizeof(dbuf)) {
2104                                                 warning("no space to %s %s",
2105                                                     "prepend option",
2106                                                     dhcp_options[i].name);
2107                                                 goto supersede;
2108                                         }
2109                                         dp = dbuf;
2110                                         memcpy(dp,
2111                                                 ip->client->
2112                                                 config->defaults[i].data,
2113                                                 ip->client->
2114                                                 config->defaults[i].len);
2115                                         memcpy(dp + ip->client->
2116                                                 config->defaults[i].len,
2117                                                 lease->options[i].data,
2118                                                 lease->options[i].len);
2119                                         dp[len] = '\0';
2120                                         break;
2121                                 case ACTION_APPEND:
2122                                         /*
2123                                          * When we append, we assume that we're
2124                                          * appending to text.  Some MS servers
2125                                          * include a NUL byte at the end of
2126                                          * the search string provided.
2127                                          */
2128                                         len = ip->client->
2129                                             config->defaults[i].len +
2130                                             lease->options[i].len;
2131                                         if (len >= sizeof(dbuf)) {
2132                                                 warning("no space to %s %s",
2133                                                     "append option",
2134                                                     dhcp_options[i].name);
2135                                                 goto supersede;
2136                                         }
2137                                         memcpy(dbuf,
2138                                                 lease->options[i].data,
2139                                                 lease->options[i].len);
2140                                         for (dp = dbuf + lease->options[i].len;
2141                                             dp > dbuf; dp--, len--)
2142                                                 if (dp[-1] != '\0')
2143                                                         break;
2144                                         memcpy(dp,
2145                                                 ip->client->
2146                                                 config->defaults[i].data,
2147                                                 ip->client->
2148                                                 config->defaults[i].len);
2149                                         dp = dbuf;
2150                                         dp[len] = '\0';
2151                                 }
2152                         } else {
2153                                 dp = ip->client->
2154                                         config->defaults[i].data;
2155                                 len = ip->client->
2156                                         config->defaults[i].len;
2157                         }
2158                 } else if (lease->options[i].len) {
2159                         len = lease->options[i].len;
2160                         dp = lease->options[i].data;
2161                 } else {
2162                         len = 0;
2163                 }
2164                 if (len) {
2165                         char name[256];
2166
2167                         if (dhcp_option_ev_name(name, sizeof(name),
2168                             &dhcp_options[i]))
2169                                 script_set_env(ip->client, prefix, name,
2170                                     pretty_print_option(i, dp, len, 0, 0));
2171                 }
2172         }
2173         snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2174         script_set_env(ip->client, prefix, "expiry", tbuf);
2175 }
2176
2177 void
2178 script_write_params(const char *prefix, struct client_lease *lease)
2179 {
2180         size_t           fn_len = 0, sn_len = 0, pr_len = 0;
2181         struct imsg_hdr  hdr;
2182         struct buf      *buf;
2183         int              errs, i;
2184
2185         if (lease->filename != NULL)
2186                 fn_len = strlen(lease->filename);
2187         if (lease->server_name != NULL)
2188                 sn_len = strlen(lease->server_name);
2189         if (prefix != NULL)
2190                 pr_len = strlen(prefix);
2191
2192         hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2193         hdr.len = sizeof(hdr) + sizeof(*lease) +
2194             sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2195             sizeof(pr_len) + pr_len;
2196
2197         for (i = 0; i < 256; i++) {
2198                 hdr.len += sizeof(lease->options[i].len);
2199                 hdr.len += lease->options[i].len;
2200         }
2201
2202         scripttime = time(NULL);
2203
2204         if ((buf = buf_open(hdr.len)) == NULL)
2205                 error("buf_open: %m");
2206
2207         errs = 0;
2208         errs += buf_add(buf, &hdr, sizeof(hdr));
2209         errs += buf_add(buf, lease, sizeof(*lease));
2210         errs += buf_add(buf, &fn_len, sizeof(fn_len));
2211         errs += buf_add(buf, lease->filename, fn_len);
2212         errs += buf_add(buf, &sn_len, sizeof(sn_len));
2213         errs += buf_add(buf, lease->server_name, sn_len);
2214         errs += buf_add(buf, &pr_len, sizeof(pr_len));
2215         errs += buf_add(buf, prefix, pr_len);
2216
2217         for (i = 0; i < 256; i++) {
2218                 errs += buf_add(buf, &lease->options[i].len,
2219                     sizeof(lease->options[i].len));
2220                 errs += buf_add(buf, lease->options[i].data,
2221                     lease->options[i].len);
2222         }
2223
2224         if (errs)
2225                 error("buf_add: %m");
2226
2227         if (buf_close(privfd, buf) == -1)
2228                 error("buf_close: %m");
2229 }
2230
2231 int
2232 script_go(void)
2233 {
2234         struct imsg_hdr  hdr;
2235         struct buf      *buf;
2236         int              ret;
2237
2238         hdr.code = IMSG_SCRIPT_GO;
2239         hdr.len = sizeof(struct imsg_hdr);
2240
2241         if ((buf = buf_open(hdr.len)) == NULL)
2242                 error("buf_open: %m");
2243
2244         if (buf_add(buf, &hdr, sizeof(hdr)))
2245                 error("buf_add: %m");
2246
2247         if (buf_close(privfd, buf) == -1)
2248                 error("buf_close: %m");
2249
2250         bzero(&hdr, sizeof(hdr));
2251         buf_read(privfd, &hdr, sizeof(hdr));
2252         if (hdr.code != IMSG_SCRIPT_GO_RET)
2253                 error("unexpected msg type %u", hdr.code);
2254         if (hdr.len != sizeof(hdr) + sizeof(int))
2255                 error("received corrupted message");
2256         buf_read(privfd, &ret, sizeof(ret));
2257
2258         scripttime = time(NULL);
2259
2260         return (ret);
2261 }
2262
2263 int
2264 priv_script_go(void)
2265 {
2266         char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2267         static char client_path[] = CLIENT_PATH;
2268         struct interface_info *ip = ifi;
2269         int pid, wpid, wstatus;
2270
2271         scripttime = time(NULL);
2272
2273         if (ip) {
2274                 scriptName = ip->client->config->script_name;
2275                 envp = ip->client->scriptEnv;
2276         } else {
2277                 scriptName = top_level_config.script_name;
2278                 epp[0] = reason;
2279                 epp[1] = client_path;
2280                 epp[2] = NULL;
2281                 envp = epp;
2282         }
2283
2284         argv[0] = scriptName;
2285         argv[1] = NULL;
2286
2287         pid = fork();
2288         if (pid < 0) {
2289                 error("fork: %m");
2290                 wstatus = 0;
2291         } else if (pid) {
2292                 do {
2293                         wpid = wait(&wstatus);
2294                 } while (wpid != pid && wpid > 0);
2295                 if (wpid < 0) {
2296                         error("wait: %m");
2297                         wstatus = 0;
2298                 }
2299         } else {
2300                 execve(scriptName, argv, envp);
2301                 error("execve (%s, ...): %m", scriptName);
2302         }
2303
2304         if (ip)
2305                 script_flush_env(ip->client);
2306
2307         return (wstatus & 0xff);
2308 }
2309
2310 void
2311 script_set_env(struct client_state *client, const char *prefix,
2312     const char *name, const char *value)
2313 {
2314         int i, namelen;
2315         size_t j;
2316
2317         /* No `` or $() command substitution allowed in environment values! */
2318         for (j=0; j < strlen(value); j++)
2319                 switch (value[j]) {
2320                 case '`':
2321                 case '$':
2322                         warning("illegal character (%c) in value '%s'",
2323                             value[j], value);
2324                         /* Ignore this option */
2325                         return;
2326                 }
2327
2328         namelen = strlen(name);
2329
2330         for (i = 0; client->scriptEnv[i]; i++)
2331                 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2332                     client->scriptEnv[i][namelen] == '=')
2333                         break;
2334
2335         if (client->scriptEnv[i])
2336                 /* Reuse the slot. */
2337                 free(client->scriptEnv[i]);
2338         else {
2339                 /* New variable.  Expand if necessary. */
2340                 if (i >= client->scriptEnvsize - 1) {
2341                         char **newscriptEnv;
2342                         int newscriptEnvsize = client->scriptEnvsize + 50;
2343
2344                         newscriptEnv = realloc(client->scriptEnv,
2345                             newscriptEnvsize);
2346                         if (newscriptEnv == NULL) {
2347                                 free(client->scriptEnv);
2348                                 client->scriptEnv = NULL;
2349                                 client->scriptEnvsize = 0;
2350                                 error("script_set_env: no memory for variable");
2351                         }
2352                         client->scriptEnv = newscriptEnv;
2353                         client->scriptEnvsize = newscriptEnvsize;
2354                 }
2355                 /* need to set the NULL pointer at end of array beyond
2356                    the new slot. */
2357                 client->scriptEnv[i + 1] = NULL;
2358         }
2359         /* Allocate space and format the variable in the appropriate slot. */
2360         client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2361             strlen(value) + 1);
2362         if (client->scriptEnv[i] == NULL)
2363                 error("script_set_env: no memory for variable assignment");
2364         snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2365             1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2366 }
2367
2368 void
2369 script_flush_env(struct client_state *client)
2370 {
2371         int i;
2372
2373         for (i = 0; client->scriptEnv[i]; i++) {
2374                 free(client->scriptEnv[i]);
2375                 client->scriptEnv[i] = NULL;
2376         }
2377         client->scriptEnvsize = 0;
2378 }
2379
2380 int
2381 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2382 {
2383         size_t i;
2384
2385         for (i = 0; option->name[i]; i++) {
2386                 if (i + 1 == buflen)
2387                         return 0;
2388                 if (option->name[i] == '-')
2389                         buf[i] = '_';
2390                 else
2391                         buf[i] = option->name[i];
2392         }
2393
2394         buf[i] = 0;
2395         return 1;
2396 }
2397
2398 void
2399 go_daemon(void)
2400 {
2401         static int state = 0;
2402         cap_rights_t rights;
2403
2404         if (no_daemon || state)
2405                 return;
2406
2407         state = 1;
2408
2409         /* Stop logging to stderr... */
2410         log_perror = 0;
2411
2412         if (daemon(1, 0) == -1)
2413                 error("daemon");
2414
2415         cap_rights_init(&rights);
2416
2417         if (pidfile != NULL) {
2418                 pidfile_write(pidfile);
2419                 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2420                     errno != ENOSYS) {
2421                         error("can't limit pidfile descriptor: %m");
2422                 }
2423         }
2424
2425         /* we are chrooted, daemon(3) fails to open /dev/null */
2426         if (nullfd != -1) {
2427                 dup2(nullfd, STDIN_FILENO);
2428                 dup2(nullfd, STDOUT_FILENO);
2429                 dup2(nullfd, STDERR_FILENO);
2430                 close(nullfd);
2431                 nullfd = -1;
2432         }
2433
2434         if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2435                 error("can't limit stdin: %m");
2436         cap_rights_init(&rights, CAP_WRITE);
2437         if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2438                 error("can't limit stdout: %m");
2439         if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2440                 error("can't limit stderr: %m");
2441 }
2442
2443 int
2444 check_option(struct client_lease *l, int option)
2445 {
2446         const char *opbuf;
2447         const char *sbuf;
2448
2449         /* we use this, since this is what gets passed to dhclient-script */
2450
2451         opbuf = pretty_print_option(option, l->options[option].data,
2452             l->options[option].len, 0, 0);
2453
2454         sbuf = option_as_string(option, l->options[option].data,
2455             l->options[option].len);
2456
2457         switch (option) {
2458         case DHO_SUBNET_MASK:
2459         case DHO_TIME_SERVERS:
2460         case DHO_NAME_SERVERS:
2461         case DHO_ROUTERS:
2462         case DHO_DOMAIN_NAME_SERVERS:
2463         case DHO_LOG_SERVERS:
2464         case DHO_COOKIE_SERVERS:
2465         case DHO_LPR_SERVERS:
2466         case DHO_IMPRESS_SERVERS:
2467         case DHO_RESOURCE_LOCATION_SERVERS:
2468         case DHO_SWAP_SERVER:
2469         case DHO_BROADCAST_ADDRESS:
2470         case DHO_NIS_SERVERS:
2471         case DHO_NTP_SERVERS:
2472         case DHO_NETBIOS_NAME_SERVERS:
2473         case DHO_NETBIOS_DD_SERVER:
2474         case DHO_FONT_SERVERS:
2475         case DHO_DHCP_SERVER_IDENTIFIER:
2476         case DHO_NISPLUS_SERVERS:
2477         case DHO_MOBILE_IP_HOME_AGENT:
2478         case DHO_SMTP_SERVER:
2479         case DHO_POP_SERVER:
2480         case DHO_NNTP_SERVER:
2481         case DHO_WWW_SERVER:
2482         case DHO_FINGER_SERVER:
2483         case DHO_IRC_SERVER:
2484         case DHO_STREETTALK_SERVER:
2485         case DHO_STREETTALK_DA_SERVER:
2486                 if (!ipv4addrs(opbuf)) {
2487                         warning("Invalid IP address in option: %s", opbuf);
2488                         return (0);
2489                 }
2490                 return (1)  ;
2491         case DHO_HOST_NAME:
2492         case DHO_NIS_DOMAIN:
2493         case DHO_NISPLUS_DOMAIN:
2494         case DHO_TFTP_SERVER_NAME:
2495                 if (!res_hnok(sbuf)) {
2496                         warning("Bogus Host Name option %d: %s (%s)", option,
2497                             sbuf, opbuf);
2498                         l->options[option].len = 0;
2499                         free(l->options[option].data);
2500                 }
2501                 return (1);
2502         case DHO_DOMAIN_NAME:
2503         case DHO_DOMAIN_SEARCH:
2504                 if (!res_hnok(sbuf)) {
2505                         if (!check_search(sbuf)) {
2506                                 warning("Bogus domain search list %d: %s (%s)",
2507                                     option, sbuf, opbuf);
2508                                 l->options[option].len = 0;
2509                                 free(l->options[option].data);
2510                         }
2511                 }
2512                 return (1);
2513         case DHO_PAD:
2514         case DHO_TIME_OFFSET:
2515         case DHO_BOOT_SIZE:
2516         case DHO_MERIT_DUMP:
2517         case DHO_ROOT_PATH:
2518         case DHO_EXTENSIONS_PATH:
2519         case DHO_IP_FORWARDING:
2520         case DHO_NON_LOCAL_SOURCE_ROUTING:
2521         case DHO_POLICY_FILTER:
2522         case DHO_MAX_DGRAM_REASSEMBLY:
2523         case DHO_DEFAULT_IP_TTL:
2524         case DHO_PATH_MTU_AGING_TIMEOUT:
2525         case DHO_PATH_MTU_PLATEAU_TABLE:
2526         case DHO_INTERFACE_MTU:
2527         case DHO_ALL_SUBNETS_LOCAL:
2528         case DHO_PERFORM_MASK_DISCOVERY:
2529         case DHO_MASK_SUPPLIER:
2530         case DHO_ROUTER_DISCOVERY:
2531         case DHO_ROUTER_SOLICITATION_ADDRESS:
2532         case DHO_STATIC_ROUTES:
2533         case DHO_TRAILER_ENCAPSULATION:
2534         case DHO_ARP_CACHE_TIMEOUT:
2535         case DHO_IEEE802_3_ENCAPSULATION:
2536         case DHO_DEFAULT_TCP_TTL:
2537         case DHO_TCP_KEEPALIVE_INTERVAL:
2538         case DHO_TCP_KEEPALIVE_GARBAGE:
2539         case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2540         case DHO_NETBIOS_NODE_TYPE:
2541         case DHO_NETBIOS_SCOPE:
2542         case DHO_X_DISPLAY_MANAGER:
2543         case DHO_DHCP_REQUESTED_ADDRESS:
2544         case DHO_DHCP_LEASE_TIME:
2545         case DHO_DHCP_OPTION_OVERLOAD:
2546         case DHO_DHCP_MESSAGE_TYPE:
2547         case DHO_DHCP_PARAMETER_REQUEST_LIST:
2548         case DHO_DHCP_MESSAGE:
2549         case DHO_DHCP_MAX_MESSAGE_SIZE:
2550         case DHO_DHCP_RENEWAL_TIME:
2551         case DHO_DHCP_REBINDING_TIME:
2552         case DHO_DHCP_CLASS_IDENTIFIER:
2553         case DHO_DHCP_CLIENT_IDENTIFIER:
2554         case DHO_BOOTFILE_NAME:
2555         case DHO_DHCP_USER_CLASS_ID:
2556         case DHO_END:
2557                 return (1);
2558         case DHO_CLASSLESS_ROUTES:
2559                 return (check_classless_option(l->options[option].data,
2560                     l->options[option].len));
2561         default:
2562                 warning("unknown dhcp option value 0x%x", option);
2563                 return (unknown_ok);
2564         }
2565 }
2566
2567 /* RFC 3442 The Classless Static Routes option checks */
2568 int
2569 check_classless_option(unsigned char *data, int len)
2570 {
2571         int i = 0;
2572         unsigned char width;
2573         in_addr_t addr, mask;
2574
2575         if (len < 5) {
2576                 warning("Too small length: %d", len);
2577                 return (0);
2578         }
2579         while(i < len) {
2580                 width = data[i++];
2581                 if (width == 0) {
2582                         i += 4;
2583                         continue;
2584                 } else if (width < 9) {
2585                         addr =  (in_addr_t)(data[i]     << 24);
2586                         i += 1;
2587                 } else if (width < 17) {
2588                         addr =  (in_addr_t)(data[i]     << 24) +
2589                                 (in_addr_t)(data[i + 1] << 16);
2590                         i += 2;
2591                 } else if (width < 25) {
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                         i += 3;
2596                 } else if (width < 33) {
2597                         addr =  (in_addr_t)(data[i]     << 24) +
2598                                 (in_addr_t)(data[i + 1] << 16) +
2599                                 (in_addr_t)(data[i + 2] << 8)  +
2600                                 data[i + 3];
2601                         i += 4;
2602                 } else {
2603                         warning("Incorrect subnet width: %d", width);
2604                         return (0);
2605                 }
2606                 mask = (in_addr_t)(~0) << (32 - width);
2607                 addr = ntohl(addr);
2608                 mask = ntohl(mask);
2609
2610                 /*
2611                  * From RFC 3442:
2612                  * ... After deriving a subnet number and subnet mask
2613                  * from each destination descriptor, the DHCP client
2614                  * MUST zero any bits in the subnet number where the
2615                  * corresponding bit in the mask is zero...
2616                  */
2617                 if ((addr & mask) != addr) {
2618                         addr &= mask;
2619                         data[i - 1] = (unsigned char)(
2620                                 (addr >> (((32 - width)/8)*8)) & 0xFF);
2621                 }
2622                 i += 4;
2623         }
2624         if (i > len) {
2625                 warning("Incorrect data length: %d (must be %d)", len, i);
2626                 return (0);
2627         }
2628         return (1);
2629 }
2630
2631 int
2632 res_hnok(const char *dn)
2633 {
2634         int pch = PERIOD, ch = *dn++;
2635
2636         while (ch != '\0') {
2637                 int nch = *dn++;
2638
2639                 if (periodchar(ch)) {
2640                         ;
2641                 } else if (periodchar(pch)) {
2642                         if (!borderchar(ch))
2643                                 return (0);
2644                 } else if (periodchar(nch) || nch == '\0') {
2645                         if (!borderchar(ch))
2646                                 return (0);
2647                 } else {
2648                         if (!middlechar(ch))
2649                                 return (0);
2650                 }
2651                 pch = ch, ch = nch;
2652         }
2653         return (1);
2654 }
2655
2656 int
2657 check_search(const char *srch)
2658 {
2659         int pch = PERIOD, ch = *srch++;
2660         int domains = 1;
2661
2662         /* 256 char limit re resolv.conf(5) */
2663         if (strlen(srch) > 256)
2664                 return (0);
2665
2666         while (whitechar(ch))
2667                 ch = *srch++;
2668
2669         while (ch != '\0') {
2670                 int nch = *srch++;
2671
2672                 if (periodchar(ch) || whitechar(ch)) {
2673                         ;
2674                 } else if (periodchar(pch)) {
2675                         if (!borderchar(ch))
2676                                 return (0);
2677                 } else if (periodchar(nch) || nch == '\0') {
2678                         if (!borderchar(ch))
2679                                 return (0);
2680                 } else {
2681                         if (!middlechar(ch))
2682                                 return (0);
2683                 }
2684                 if (!whitechar(ch)) {
2685                         pch = ch;
2686                 } else {
2687                         while (whitechar(nch)) {
2688                                 nch = *srch++;
2689                         }
2690                         if (nch != '\0')
2691                                 domains++;
2692                         pch = PERIOD;
2693                 }
2694                 ch = nch;
2695         }
2696         /* 6 domain limit re resolv.conf(5) */
2697         if (domains > 6)
2698                 return (0);
2699         return (1);
2700 }
2701
2702 /* Does buf consist only of dotted decimal ipv4 addrs?
2703  * return how many if so,
2704  * otherwise, return 0
2705  */
2706 int
2707 ipv4addrs(const char * buf)
2708 {
2709         struct in_addr jnk;
2710         int count = 0;
2711
2712         while (inet_aton(buf, &jnk) == 1){
2713                 count++;
2714                 while (periodchar(*buf) || digitchar(*buf))
2715                         buf++;
2716                 if (*buf == '\0')
2717                         return (count);
2718                 while (*buf ==  ' ')
2719                         buf++;
2720         }
2721         return (0);
2722 }
2723
2724
2725 const char *
2726 option_as_string(unsigned int code, unsigned char *data, int len)
2727 {
2728         static char optbuf[32768]; /* XXX */
2729         char *op = optbuf;
2730         int opleft = sizeof(optbuf);
2731         unsigned char *dp = data;
2732
2733         if (code > 255)
2734                 error("option_as_string: bad code %d", code);
2735
2736         for (; dp < data + len; dp++) {
2737                 if (!isascii(*dp) || !isprint(*dp)) {
2738                         if (dp + 1 != data + len || *dp != 0) {
2739                                 snprintf(op, opleft, "\\%03o", *dp);
2740                                 op += 4;
2741                                 opleft -= 4;
2742                         }
2743                 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2744                     *dp == '`' || *dp == '\\') {
2745                         *op++ = '\\';
2746                         *op++ = *dp;
2747                         opleft -= 2;
2748                 } else {
2749                         *op++ = *dp;
2750                         opleft--;
2751                 }
2752         }
2753         if (opleft < 1)
2754                 goto toobig;
2755         *op = 0;
2756         return optbuf;
2757 toobig:
2758         warning("dhcp option too large");
2759         return "<error>";
2760 }
2761
2762 int
2763 fork_privchld(int fd, int fd2)
2764 {
2765         struct pollfd pfd[1];
2766         int nfds;
2767
2768         switch (fork()) {
2769         case -1:
2770                 error("cannot fork");
2771         case 0:
2772                 break;
2773         default:
2774                 return (0);
2775         }
2776
2777         setproctitle("%s [priv]", ifi->name);
2778
2779         setsid();
2780         dup2(nullfd, STDIN_FILENO);
2781         dup2(nullfd, STDOUT_FILENO);
2782         dup2(nullfd, STDERR_FILENO);
2783         close(nullfd);
2784         close(fd2);
2785         close(ifi->rfdesc);
2786         ifi->rfdesc = -1;
2787
2788         for (;;) {
2789                 pfd[0].fd = fd;
2790                 pfd[0].events = POLLIN;
2791                 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2792                         if (errno != EINTR)
2793                                 error("poll error");
2794
2795                 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2796                         continue;
2797
2798                 dispatch_imsg(ifi, fd);
2799         }
2800 }