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