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