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