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