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