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