]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/dhclient/dhclient.c
dhclient: Fix some trivial buffer overruns
[FreeBSD/FreeBSD.git] / sbin / dhclient / dhclient.c
1 /*      $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $       */
2
3 /*
4  * Copyright 2004 Henning Brauer <henning@openbsd.org>
5  * Copyright (c) 1995, 1996, 1997, 1998, 1999
6  * The Internet Software Consortium.    All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of The Internet Software Consortium nor the names
18  *    of its contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
22  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
26  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
29  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * This software has been written for the Internet Software Consortium
36  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
37  * Enterprises.  To learn more about the Internet Software Consortium,
38  * see ``http://www.vix.com/isc''.  To learn more about Vixie
39  * Enterprises, see ``http://www.vix.com''.
40  *
41  * This client was substantially modified and enhanced by Elliot Poger
42  * for use on Linux while he was working on the MosquitoNet project at
43  * Stanford.
44  *
45  * The current version owes much to Elliot's Linux enhancements, but
46  * was substantially reorganized and partially rewritten by Ted Lemon
47  * so as to use the same networking framework that the Internet Software
48  * Consortium DHCP server uses.   Much system-specific configuration code
49  * was moved into a shell script so that as support for more operating
50  * systems is added, it will not be necessary to port and maintain
51  * system-specific configuration code to these operating systems - instead,
52  * the shell script can invoke the native tools to accomplish the same
53  * purpose.
54  */
55
56 #include <sys/cdefs.h>
57 __FBSDID("$FreeBSD$");
58
59 #include <stddef.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, 0644, &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                 memcpy(&from, ip->client->active->address.iabuf,
1465                     sizeof(from));
1466         else
1467                 from.s_addr = INADDR_ANY;
1468
1469         /* Record the number of seconds since we started sending. */
1470         if (ip->client->state == S_REQUESTING)
1471                 ip->client->packet.secs = ip->client->secs;
1472         else {
1473                 if (interval < 65536)
1474                         ip->client->packet.secs = htons(interval);
1475                 else
1476                         ip->client->packet.secs = htons(65535);
1477         }
1478
1479         note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1480             REMOTE_PORT);
1481
1482         /* Send out a packet. */
1483         send_packet_unpriv(privfd, &ip->client->packet,
1484             ip->client->packet_length, from, to);
1485
1486         add_timeout(cur_time + ip->client->interval, send_request, ip);
1487 }
1488
1489 void
1490 send_decline(void *ipp)
1491 {
1492         struct interface_info *ip = ipp;
1493
1494         note("DHCPDECLINE on %s to %s port %d", ip->name,
1495             inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1496
1497         /* Send out a packet. */
1498         send_packet_unpriv(privfd, &ip->client->packet,
1499             ip->client->packet_length, inaddr_any, inaddr_broadcast);
1500 }
1501
1502 void
1503 make_discover(struct interface_info *ip, struct client_lease *lease)
1504 {
1505         unsigned char discover = DHCPDISCOVER;
1506         struct tree_cache *options[256];
1507         struct tree_cache option_elements[256];
1508         int i;
1509
1510         memset(option_elements, 0, sizeof(option_elements));
1511         memset(options, 0, sizeof(options));
1512         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1513
1514         /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1515         i = DHO_DHCP_MESSAGE_TYPE;
1516         options[i] = &option_elements[i];
1517         options[i]->value = &discover;
1518         options[i]->len = sizeof(discover);
1519         options[i]->buf_size = sizeof(discover);
1520         options[i]->timeout = 0xFFFFFFFF;
1521
1522         /* Request the options we want */
1523         i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1524         options[i] = &option_elements[i];
1525         options[i]->value = ip->client->config->requested_options;
1526         options[i]->len = ip->client->config->requested_option_count;
1527         options[i]->buf_size =
1528                 ip->client->config->requested_option_count;
1529         options[i]->timeout = 0xFFFFFFFF;
1530
1531         /* If we had an address, try to get it again. */
1532         if (lease) {
1533                 ip->client->requested_address = lease->address;
1534                 i = DHO_DHCP_REQUESTED_ADDRESS;
1535                 options[i] = &option_elements[i];
1536                 options[i]->value = lease->address.iabuf;
1537                 options[i]->len = lease->address.len;
1538                 options[i]->buf_size = lease->address.len;
1539                 options[i]->timeout = 0xFFFFFFFF;
1540         } else
1541                 ip->client->requested_address.len = 0;
1542
1543         /* Send any options requested in the config file. */
1544         for (i = 0; i < 256; i++)
1545                 if (!options[i] &&
1546                     ip->client->config->send_options[i].data) {
1547                         options[i] = &option_elements[i];
1548                         options[i]->value =
1549                             ip->client->config->send_options[i].data;
1550                         options[i]->len =
1551                             ip->client->config->send_options[i].len;
1552                         options[i]->buf_size =
1553                             ip->client->config->send_options[i].len;
1554                         options[i]->timeout = 0xFFFFFFFF;
1555                 }
1556
1557         /* send host name if not set via config file. */
1558         if (!options[DHO_HOST_NAME]) {
1559                 if (hostname[0] != '\0') {
1560                         size_t len;
1561                         char* posDot = strchr(hostname, '.');
1562                         if (posDot != NULL)
1563                                 len = posDot - hostname;
1564                         else
1565                                 len = strlen(hostname);
1566                         options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1567                         options[DHO_HOST_NAME]->value = hostname;
1568                         options[DHO_HOST_NAME]->len = len;
1569                         options[DHO_HOST_NAME]->buf_size = len;
1570                         options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1571                 }
1572         }
1573
1574         /* set unique client identifier */
1575         struct hardware client_ident;
1576         if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1577                 size_t hwlen = MIN(ip->hw_address.hlen,
1578                     sizeof(client_ident.haddr));
1579                 client_ident.htype = ip->hw_address.htype;
1580                 client_ident.hlen = hwlen;
1581                 memcpy(client_ident.haddr, ip->hw_address.haddr, hwlen);
1582                 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1583                 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = (void *)&client_ident;
1584                 hwlen += offsetof(struct hardware, haddr);
1585                 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen;
1586                 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen;
1587                 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1588         }
1589
1590         /* Set up the option buffer... */
1591         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1592             options, 0, 0, 0, NULL, 0);
1593         if (ip->client->packet_length < BOOTP_MIN_LEN)
1594                 ip->client->packet_length = BOOTP_MIN_LEN;
1595
1596         ip->client->packet.op = BOOTREQUEST;
1597         ip->client->packet.htype = ip->hw_address.htype;
1598         ip->client->packet.hlen = ip->hw_address.hlen;
1599         ip->client->packet.hops = 0;
1600         ip->client->packet.xid = arc4random();
1601         ip->client->packet.secs = 0; /* filled in by send_discover. */
1602         ip->client->packet.flags = 0;
1603
1604         memset(&(ip->client->packet.ciaddr),
1605             0, sizeof(ip->client->packet.ciaddr));
1606         memset(&(ip->client->packet.yiaddr),
1607             0, sizeof(ip->client->packet.yiaddr));
1608         memset(&(ip->client->packet.siaddr),
1609             0, sizeof(ip->client->packet.siaddr));
1610         memset(&(ip->client->packet.giaddr),
1611             0, sizeof(ip->client->packet.giaddr));
1612         memcpy(ip->client->packet.chaddr, ip->hw_address.haddr,
1613             MIN(ip->hw_address.hlen, sizeof(ip->client->packet.chaddr)));
1614 }
1615
1616
1617 void
1618 make_request(struct interface_info *ip, struct client_lease * lease)
1619 {
1620         unsigned char request = DHCPREQUEST;
1621         struct tree_cache *options[256];
1622         struct tree_cache option_elements[256];
1623         int i;
1624
1625         memset(options, 0, sizeof(options));
1626         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1627
1628         /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1629         i = DHO_DHCP_MESSAGE_TYPE;
1630         options[i] = &option_elements[i];
1631         options[i]->value = &request;
1632         options[i]->len = sizeof(request);
1633         options[i]->buf_size = sizeof(request);
1634         options[i]->timeout = 0xFFFFFFFF;
1635
1636         /* Request the options we want */
1637         i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1638         options[i] = &option_elements[i];
1639         options[i]->value = ip->client->config->requested_options;
1640         options[i]->len = ip->client->config->requested_option_count;
1641         options[i]->buf_size =
1642                 ip->client->config->requested_option_count;
1643         options[i]->timeout = 0xFFFFFFFF;
1644
1645         /* If we are requesting an address that hasn't yet been assigned
1646            to us, use the DHCP Requested Address option. */
1647         if (ip->client->state == S_REQUESTING) {
1648                 /* Send back the server identifier... */
1649                 i = DHO_DHCP_SERVER_IDENTIFIER;
1650                 options[i] = &option_elements[i];
1651                 options[i]->value = lease->options[i].data;
1652                 options[i]->len = lease->options[i].len;
1653                 options[i]->buf_size = lease->options[i].len;
1654                 options[i]->timeout = 0xFFFFFFFF;
1655         }
1656         if (ip->client->state == S_REQUESTING ||
1657             ip->client->state == S_REBOOTING) {
1658                 ip->client->requested_address = lease->address;
1659                 i = DHO_DHCP_REQUESTED_ADDRESS;
1660                 options[i] = &option_elements[i];
1661                 options[i]->value = lease->address.iabuf;
1662                 options[i]->len = lease->address.len;
1663                 options[i]->buf_size = lease->address.len;
1664                 options[i]->timeout = 0xFFFFFFFF;
1665         } else
1666                 ip->client->requested_address.len = 0;
1667
1668         /* Send any options requested in the config file. */
1669         for (i = 0; i < 256; i++)
1670                 if (!options[i] &&
1671                     ip->client->config->send_options[i].data) {
1672                         options[i] = &option_elements[i];
1673                         options[i]->value =
1674                             ip->client->config->send_options[i].data;
1675                         options[i]->len =
1676                             ip->client->config->send_options[i].len;
1677                         options[i]->buf_size =
1678                             ip->client->config->send_options[i].len;
1679                         options[i]->timeout = 0xFFFFFFFF;
1680                 }
1681
1682         /* send host name if not set via config file. */
1683         if (!options[DHO_HOST_NAME]) {
1684                 if (hostname[0] != '\0') {
1685                         size_t len;
1686                         char* posDot = strchr(hostname, '.');
1687                         if (posDot != NULL)
1688                                 len = posDot - hostname;
1689                         else
1690                                 len = strlen(hostname);
1691                         options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1692                         options[DHO_HOST_NAME]->value = hostname;
1693                         options[DHO_HOST_NAME]->len = len;
1694                         options[DHO_HOST_NAME]->buf_size = len;
1695                         options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1696                 }
1697         }
1698
1699         /* set unique client identifier */
1700         char client_ident[sizeof(struct hardware)];
1701         if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1702                 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1703                                 ip->hw_address.hlen : sizeof(client_ident)-1;
1704                 client_ident[0] = ip->hw_address.htype;
1705                 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1706                 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1707                 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1708                 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1709                 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1710                 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1711         }
1712
1713         /* Set up the option buffer... */
1714         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1715             options, 0, 0, 0, NULL, 0);
1716         if (ip->client->packet_length < BOOTP_MIN_LEN)
1717                 ip->client->packet_length = BOOTP_MIN_LEN;
1718
1719         ip->client->packet.op = BOOTREQUEST;
1720         ip->client->packet.htype = ip->hw_address.htype;
1721         ip->client->packet.hlen = ip->hw_address.hlen;
1722         ip->client->packet.hops = 0;
1723         ip->client->packet.xid = ip->client->xid;
1724         ip->client->packet.secs = 0; /* Filled in by send_request. */
1725
1726         /* If we own the address we're requesting, put it in ciaddr;
1727            otherwise set ciaddr to zero. */
1728         if (ip->client->state == S_BOUND ||
1729             ip->client->state == S_RENEWING ||
1730             ip->client->state == S_REBINDING) {
1731                 memcpy(&ip->client->packet.ciaddr,
1732                     lease->address.iabuf, lease->address.len);
1733                 ip->client->packet.flags = 0;
1734         } else {
1735                 memset(&ip->client->packet.ciaddr, 0,
1736                     sizeof(ip->client->packet.ciaddr));
1737                 ip->client->packet.flags = 0;
1738         }
1739
1740         memset(&ip->client->packet.yiaddr, 0,
1741             sizeof(ip->client->packet.yiaddr));
1742         memset(&ip->client->packet.siaddr, 0,
1743             sizeof(ip->client->packet.siaddr));
1744         memset(&ip->client->packet.giaddr, 0,
1745             sizeof(ip->client->packet.giaddr));
1746         memcpy(ip->client->packet.chaddr,
1747             ip->hw_address.haddr, ip->hw_address.hlen);
1748 }
1749
1750 void
1751 make_decline(struct interface_info *ip, struct client_lease *lease)
1752 {
1753         struct tree_cache *options[256], message_type_tree;
1754         struct tree_cache requested_address_tree;
1755         struct tree_cache server_id_tree, client_id_tree;
1756         unsigned char decline = DHCPDECLINE;
1757         int i;
1758
1759         memset(options, 0, sizeof(options));
1760         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1761
1762         /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1763         i = DHO_DHCP_MESSAGE_TYPE;
1764         options[i] = &message_type_tree;
1765         options[i]->value = &decline;
1766         options[i]->len = sizeof(decline);
1767         options[i]->buf_size = sizeof(decline);
1768         options[i]->timeout = 0xFFFFFFFF;
1769
1770         /* Send back the server identifier... */
1771         i = DHO_DHCP_SERVER_IDENTIFIER;
1772         options[i] = &server_id_tree;
1773         options[i]->value = lease->options[i].data;
1774         options[i]->len = lease->options[i].len;
1775         options[i]->buf_size = lease->options[i].len;
1776         options[i]->timeout = 0xFFFFFFFF;
1777
1778         /* Send back the address we're declining. */
1779         i = DHO_DHCP_REQUESTED_ADDRESS;
1780         options[i] = &requested_address_tree;
1781         options[i]->value = lease->address.iabuf;
1782         options[i]->len = lease->address.len;
1783         options[i]->buf_size = lease->address.len;
1784         options[i]->timeout = 0xFFFFFFFF;
1785
1786         /* Send the uid if the user supplied one. */
1787         i = DHO_DHCP_CLIENT_IDENTIFIER;
1788         if (ip->client->config->send_options[i].len) {
1789                 options[i] = &client_id_tree;
1790                 options[i]->value = ip->client->config->send_options[i].data;
1791                 options[i]->len = ip->client->config->send_options[i].len;
1792                 options[i]->buf_size = ip->client->config->send_options[i].len;
1793                 options[i]->timeout = 0xFFFFFFFF;
1794         }
1795
1796
1797         /* Set up the option buffer... */
1798         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1799             options, 0, 0, 0, NULL, 0);
1800         if (ip->client->packet_length < BOOTP_MIN_LEN)
1801                 ip->client->packet_length = BOOTP_MIN_LEN;
1802
1803         ip->client->packet.op = BOOTREQUEST;
1804         ip->client->packet.htype = ip->hw_address.htype;
1805         ip->client->packet.hlen = ip->hw_address.hlen;
1806         ip->client->packet.hops = 0;
1807         ip->client->packet.xid = ip->client->xid;
1808         ip->client->packet.secs = 0; /* Filled in by send_request. */
1809         ip->client->packet.flags = 0;
1810
1811         /* ciaddr must always be zero. */
1812         memset(&ip->client->packet.ciaddr, 0,
1813             sizeof(ip->client->packet.ciaddr));
1814         memset(&ip->client->packet.yiaddr, 0,
1815             sizeof(ip->client->packet.yiaddr));
1816         memset(&ip->client->packet.siaddr, 0,
1817             sizeof(ip->client->packet.siaddr));
1818         memset(&ip->client->packet.giaddr, 0,
1819             sizeof(ip->client->packet.giaddr));
1820         memcpy(ip->client->packet.chaddr,
1821             ip->hw_address.haddr, ip->hw_address.hlen);
1822 }
1823
1824 void
1825 free_client_lease(struct client_lease *lease)
1826 {
1827         int i;
1828
1829         if (lease->server_name)
1830                 free(lease->server_name);
1831         if (lease->filename)
1832                 free(lease->filename);
1833         for (i = 0; i < 256; i++) {
1834                 if (lease->options[i].len)
1835                         free(lease->options[i].data);
1836         }
1837         free(lease);
1838 }
1839
1840 FILE *leaseFile;
1841
1842 void
1843 rewrite_client_leases(void)
1844 {
1845         struct client_lease *lp;
1846         cap_rights_t rights;
1847
1848         if (!leaseFile) {
1849                 leaseFile = fopen(path_dhclient_db, "w");
1850                 if (!leaseFile)
1851                         error("can't create %s: %m", path_dhclient_db);
1852                 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1853                     CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1854                 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1855                     errno != ENOSYS) {
1856                         error("can't limit lease descriptor: %m");
1857                 }
1858                 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1859                     errno != ENOSYS) {
1860                         error("can't limit lease descriptor fcntls: %m");
1861                 }
1862         } else {
1863                 fflush(leaseFile);
1864                 rewind(leaseFile);
1865         }
1866
1867         for (lp = ifi->client->leases; lp; lp = lp->next)
1868                 write_client_lease(ifi, lp, 1);
1869         if (ifi->client->active)
1870                 write_client_lease(ifi, ifi->client->active, 1);
1871
1872         fflush(leaseFile);
1873         ftruncate(fileno(leaseFile), ftello(leaseFile));
1874         fsync(fileno(leaseFile));
1875 }
1876
1877 void
1878 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1879     int rewrite)
1880 {
1881         static int leases_written;
1882         struct tm *t;
1883         int i;
1884
1885         if (!rewrite) {
1886                 if (leases_written++ > 20) {
1887                         rewrite_client_leases();
1888                         leases_written = 0;
1889                 }
1890         }
1891
1892         /* If the lease came from the config file, we don't need to stash
1893            a copy in the lease database. */
1894         if (lease->is_static)
1895                 return;
1896
1897         if (!leaseFile) {       /* XXX */
1898                 leaseFile = fopen(path_dhclient_db, "w");
1899                 if (!leaseFile)
1900                         error("can't create %s: %m", path_dhclient_db);
1901         }
1902
1903         fprintf(leaseFile, "lease {\n");
1904         if (lease->is_bootp)
1905                 fprintf(leaseFile, "  bootp;\n");
1906         fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1907         fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1908         if (lease->nextserver.len == sizeof(inaddr_any) &&
1909             0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1910             sizeof(inaddr_any)))
1911                 fprintf(leaseFile, "  next-server %s;\n",
1912                     piaddr(lease->nextserver));
1913         if (lease->filename)
1914                 fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1915         if (lease->server_name)
1916                 fprintf(leaseFile, "  server-name \"%s\";\n",
1917                     lease->server_name);
1918         if (lease->medium)
1919                 fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1920         for (i = 0; i < 256; i++)
1921                 if (lease->options[i].len)
1922                         fprintf(leaseFile, "  option %s %s;\n",
1923                             dhcp_options[i].name,
1924                             pretty_print_option(i, lease->options[i].data,
1925                             lease->options[i].len, 1, 1));
1926
1927         t = gmtime(&lease->renewal);
1928         fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
1929             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1930             t->tm_hour, t->tm_min, t->tm_sec);
1931         t = gmtime(&lease->rebind);
1932         fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1933             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1934             t->tm_hour, t->tm_min, t->tm_sec);
1935         t = gmtime(&lease->expiry);
1936         fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
1937             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1938             t->tm_hour, t->tm_min, t->tm_sec);
1939         fprintf(leaseFile, "}\n");
1940         fflush(leaseFile);
1941 }
1942
1943 void
1944 script_init(char *reason, struct string_list *medium)
1945 {
1946         size_t           len, mediumlen = 0;
1947         struct imsg_hdr  hdr;
1948         struct buf      *buf;
1949         int              errs;
1950
1951         if (medium != NULL && medium->string != NULL)
1952                 mediumlen = strlen(medium->string);
1953
1954         hdr.code = IMSG_SCRIPT_INIT;
1955         hdr.len = sizeof(struct imsg_hdr) +
1956             sizeof(size_t) + mediumlen +
1957             sizeof(size_t) + strlen(reason);
1958
1959         if ((buf = buf_open(hdr.len)) == NULL)
1960                 error("buf_open: %m");
1961
1962         errs = 0;
1963         errs += buf_add(buf, &hdr, sizeof(hdr));
1964         errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1965         if (mediumlen > 0)
1966                 errs += buf_add(buf, medium->string, mediumlen);
1967         len = strlen(reason);
1968         errs += buf_add(buf, &len, sizeof(len));
1969         errs += buf_add(buf, reason, len);
1970
1971         if (errs)
1972                 error("buf_add: %m");
1973
1974         if (buf_close(privfd, buf) == -1)
1975                 error("buf_close: %m");
1976 }
1977
1978 void
1979 priv_script_init(char *reason, char *medium)
1980 {
1981         struct interface_info *ip = ifi;
1982
1983         if (ip) {
1984                 ip->client->scriptEnvsize = 100;
1985                 if (ip->client->scriptEnv == NULL)
1986                         ip->client->scriptEnv =
1987                             malloc(ip->client->scriptEnvsize * sizeof(char *));
1988                 if (ip->client->scriptEnv == NULL)
1989                         error("script_init: no memory for environment");
1990
1991                 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
1992                 if (ip->client->scriptEnv[0] == NULL)
1993                         error("script_init: no memory for environment");
1994
1995                 ip->client->scriptEnv[1] = NULL;
1996
1997                 script_set_env(ip->client, "", "interface", ip->name);
1998
1999                 if (medium)
2000                         script_set_env(ip->client, "", "medium", medium);
2001
2002                 script_set_env(ip->client, "", "reason", reason);
2003         }
2004 }
2005
2006 void
2007 priv_script_write_params(char *prefix, struct client_lease *lease)
2008 {
2009         struct interface_info *ip = ifi;
2010         u_int8_t dbuf[1500], *dp = NULL;
2011         int i, len;
2012         char tbuf[128];
2013
2014         script_set_env(ip->client, prefix, "ip_address",
2015             piaddr(lease->address));
2016
2017         if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2018             ACTION_SUPERSEDE) {
2019                 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2020                 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2021         } else {
2022                 dp = lease->options[DHO_SUBNET_MASK].data;
2023                 len = lease->options[DHO_SUBNET_MASK].len;
2024         }
2025         if (len && (len < sizeof(lease->address.iabuf))) {
2026                 struct iaddr netmask, subnet, broadcast;
2027
2028                 memcpy(netmask.iabuf, dp, len);
2029                 netmask.len = len;
2030                 subnet = subnet_number(lease->address, netmask);
2031                 if (subnet.len) {
2032                         script_set_env(ip->client, prefix, "network_number",
2033                             piaddr(subnet));
2034                         if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2035                                 broadcast = broadcast_addr(subnet, netmask);
2036                                 if (broadcast.len)
2037                                         script_set_env(ip->client, prefix,
2038                                             "broadcast_address",
2039                                             piaddr(broadcast));
2040                         }
2041                 }
2042         }
2043
2044         if (lease->filename)
2045                 script_set_env(ip->client, prefix, "filename", lease->filename);
2046         if (lease->server_name)
2047                 script_set_env(ip->client, prefix, "server_name",
2048                     lease->server_name);
2049         for (i = 0; i < 256; i++) {
2050                 len = 0;
2051
2052                 if (ip->client->config->defaults[i].len) {
2053                         if (lease->options[i].len) {
2054                                 switch (
2055                                     ip->client->config->default_actions[i]) {
2056                                 case ACTION_DEFAULT:
2057                                         dp = lease->options[i].data;
2058                                         len = lease->options[i].len;
2059                                         break;
2060                                 case ACTION_SUPERSEDE:
2061 supersede:
2062                                         dp = ip->client->
2063                                                 config->defaults[i].data;
2064                                         len = ip->client->
2065                                                 config->defaults[i].len;
2066                                         break;
2067                                 case ACTION_PREPEND:
2068                                         len = ip->client->
2069                                             config->defaults[i].len +
2070                                             lease->options[i].len;
2071                                         if (len >= sizeof(dbuf)) {
2072                                                 warning("no space to %s %s",
2073                                                     "prepend option",
2074                                                     dhcp_options[i].name);
2075                                                 goto supersede;
2076                                         }
2077                                         dp = dbuf;
2078                                         memcpy(dp,
2079                                                 ip->client->
2080                                                 config->defaults[i].data,
2081                                                 ip->client->
2082                                                 config->defaults[i].len);
2083                                         memcpy(dp + ip->client->
2084                                                 config->defaults[i].len,
2085                                                 lease->options[i].data,
2086                                                 lease->options[i].len);
2087                                         dp[len] = '\0';
2088                                         break;
2089                                 case ACTION_APPEND:
2090                                         /*
2091                                          * When we append, we assume that we're
2092                                          * appending to text.  Some MS servers
2093                                          * include a NUL byte at the end of
2094                                          * the search string provided.
2095                                          */
2096                                         len = ip->client->
2097                                             config->defaults[i].len +
2098                                             lease->options[i].len;
2099                                         if (len >= sizeof(dbuf)) {
2100                                                 warning("no space to %s %s",
2101                                                     "append option",
2102                                                     dhcp_options[i].name);
2103                                                 goto supersede;
2104                                         }
2105                                         memcpy(dbuf,
2106                                                 lease->options[i].data,
2107                                                 lease->options[i].len);
2108                                         for (dp = dbuf + lease->options[i].len;
2109                                             dp > dbuf; dp--, len--)
2110                                                 if (dp[-1] != '\0')
2111                                                         break;
2112                                         memcpy(dp,
2113                                                 ip->client->
2114                                                 config->defaults[i].data,
2115                                                 ip->client->
2116                                                 config->defaults[i].len);
2117                                         dp = dbuf;
2118                                         dp[len] = '\0';
2119                                 }
2120                         } else {
2121                                 dp = ip->client->
2122                                         config->defaults[i].data;
2123                                 len = ip->client->
2124                                         config->defaults[i].len;
2125                         }
2126                 } else if (lease->options[i].len) {
2127                         len = lease->options[i].len;
2128                         dp = lease->options[i].data;
2129                 } else {
2130                         len = 0;
2131                 }
2132                 if (len) {
2133                         char name[256];
2134
2135                         if (dhcp_option_ev_name(name, sizeof(name),
2136                             &dhcp_options[i]))
2137                                 script_set_env(ip->client, prefix, name,
2138                                     pretty_print_option(i, dp, len, 0, 0));
2139                 }
2140         }
2141         snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2142         script_set_env(ip->client, prefix, "expiry", tbuf);
2143 }
2144
2145 void
2146 script_write_params(char *prefix, struct client_lease *lease)
2147 {
2148         size_t           fn_len = 0, sn_len = 0, pr_len = 0;
2149         struct imsg_hdr  hdr;
2150         struct buf      *buf;
2151         int              errs, i;
2152
2153         if (lease->filename != NULL)
2154                 fn_len = strlen(lease->filename);
2155         if (lease->server_name != NULL)
2156                 sn_len = strlen(lease->server_name);
2157         if (prefix != NULL)
2158                 pr_len = strlen(prefix);
2159
2160         hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2161         hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2162             sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2163             sizeof(size_t) + pr_len;
2164
2165         for (i = 0; i < 256; i++)
2166                 hdr.len += sizeof(int) + lease->options[i].len;
2167
2168         scripttime = time(NULL);
2169
2170         if ((buf = buf_open(hdr.len)) == NULL)
2171                 error("buf_open: %m");
2172
2173         errs = 0;
2174         errs += buf_add(buf, &hdr, sizeof(hdr));
2175         errs += buf_add(buf, lease, sizeof(struct client_lease));
2176         errs += buf_add(buf, &fn_len, sizeof(fn_len));
2177         errs += buf_add(buf, lease->filename, fn_len);
2178         errs += buf_add(buf, &sn_len, sizeof(sn_len));
2179         errs += buf_add(buf, lease->server_name, sn_len);
2180         errs += buf_add(buf, &pr_len, sizeof(pr_len));
2181         errs += buf_add(buf, prefix, pr_len);
2182
2183         for (i = 0; i < 256; i++) {
2184                 errs += buf_add(buf, &lease->options[i].len,
2185                     sizeof(lease->options[i].len));
2186                 errs += buf_add(buf, lease->options[i].data,
2187                     lease->options[i].len);
2188         }
2189
2190         if (errs)
2191                 error("buf_add: %m");
2192
2193         if (buf_close(privfd, buf) == -1)
2194                 error("buf_close: %m");
2195 }
2196
2197 int
2198 script_go(void)
2199 {
2200         struct imsg_hdr  hdr;
2201         struct buf      *buf;
2202         int              ret;
2203
2204         hdr.code = IMSG_SCRIPT_GO;
2205         hdr.len = sizeof(struct imsg_hdr);
2206
2207         if ((buf = buf_open(hdr.len)) == NULL)
2208                 error("buf_open: %m");
2209
2210         if (buf_add(buf, &hdr, sizeof(hdr)))
2211                 error("buf_add: %m");
2212
2213         if (buf_close(privfd, buf) == -1)
2214                 error("buf_close: %m");
2215
2216         bzero(&hdr, sizeof(hdr));
2217         buf_read(privfd, &hdr, sizeof(hdr));
2218         if (hdr.code != IMSG_SCRIPT_GO_RET)
2219                 error("unexpected msg type %u", hdr.code);
2220         if (hdr.len != sizeof(hdr) + sizeof(int))
2221                 error("received corrupted message");
2222         buf_read(privfd, &ret, sizeof(ret));
2223
2224         scripttime = time(NULL);
2225
2226         return (ret);
2227 }
2228
2229 int
2230 priv_script_go(void)
2231 {
2232         char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2233         static char client_path[] = CLIENT_PATH;
2234         struct interface_info *ip = ifi;
2235         int pid, wpid, wstatus;
2236
2237         scripttime = time(NULL);
2238
2239         if (ip) {
2240                 scriptName = ip->client->config->script_name;
2241                 envp = ip->client->scriptEnv;
2242         } else {
2243                 scriptName = top_level_config.script_name;
2244                 epp[0] = reason;
2245                 epp[1] = client_path;
2246                 epp[2] = NULL;
2247                 envp = epp;
2248         }
2249
2250         argv[0] = scriptName;
2251         argv[1] = NULL;
2252
2253         pid = fork();
2254         if (pid < 0) {
2255                 error("fork: %m");
2256                 wstatus = 0;
2257         } else if (pid) {
2258                 do {
2259                         wpid = wait(&wstatus);
2260                 } while (wpid != pid && wpid > 0);
2261                 if (wpid < 0) {
2262                         error("wait: %m");
2263                         wstatus = 0;
2264                 }
2265         } else {
2266                 execve(scriptName, argv, envp);
2267                 error("execve (%s, ...): %m", scriptName);
2268         }
2269
2270         if (ip)
2271                 script_flush_env(ip->client);
2272
2273         return (wstatus & 0xff);
2274 }
2275
2276 void
2277 script_set_env(struct client_state *client, const char *prefix,
2278     const char *name, const char *value)
2279 {
2280         int i, j, namelen;
2281
2282         /* No `` or $() command substitution allowed in environment values! */
2283         for (j=0; j < strlen(value); j++)
2284                 switch (value[j]) {
2285                 case '`':
2286                 case '$':
2287                         warning("illegal character (%c) in value '%s'",
2288                             value[j], value);
2289                         /* Ignore this option */
2290                         return;
2291                 }
2292
2293         namelen = strlen(name);
2294
2295         for (i = 0; client->scriptEnv[i]; i++)
2296                 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2297                     client->scriptEnv[i][namelen] == '=')
2298                         break;
2299
2300         if (client->scriptEnv[i])
2301                 /* Reuse the slot. */
2302                 free(client->scriptEnv[i]);
2303         else {
2304                 /* New variable.  Expand if necessary. */
2305                 if (i >= client->scriptEnvsize - 1) {
2306                         char **newscriptEnv;
2307                         int newscriptEnvsize = client->scriptEnvsize + 50;
2308
2309                         newscriptEnv = realloc(client->scriptEnv,
2310                             newscriptEnvsize);
2311                         if (newscriptEnv == NULL) {
2312                                 free(client->scriptEnv);
2313                                 client->scriptEnv = NULL;
2314                                 client->scriptEnvsize = 0;
2315                                 error("script_set_env: no memory for variable");
2316                         }
2317                         client->scriptEnv = newscriptEnv;
2318                         client->scriptEnvsize = newscriptEnvsize;
2319                 }
2320                 /* need to set the NULL pointer at end of array beyond
2321                    the new slot. */
2322                 client->scriptEnv[i + 1] = NULL;
2323         }
2324         /* Allocate space and format the variable in the appropriate slot. */
2325         client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2326             strlen(value) + 1);
2327         if (client->scriptEnv[i] == NULL)
2328                 error("script_set_env: no memory for variable assignment");
2329         snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2330             1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2331 }
2332
2333 void
2334 script_flush_env(struct client_state *client)
2335 {
2336         int i;
2337
2338         for (i = 0; client->scriptEnv[i]; i++) {
2339                 free(client->scriptEnv[i]);
2340                 client->scriptEnv[i] = NULL;
2341         }
2342         client->scriptEnvsize = 0;
2343 }
2344
2345 int
2346 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2347 {
2348         int i;
2349
2350         for (i = 0; option->name[i]; i++) {
2351                 if (i + 1 == buflen)
2352                         return 0;
2353                 if (option->name[i] == '-')
2354                         buf[i] = '_';
2355                 else
2356                         buf[i] = option->name[i];
2357         }
2358
2359         buf[i] = 0;
2360         return 1;
2361 }
2362
2363 void
2364 go_daemon(void)
2365 {
2366         static int state = 0;
2367         cap_rights_t rights;
2368
2369         if (no_daemon || state)
2370                 return;
2371
2372         state = 1;
2373
2374         /* Stop logging to stderr... */
2375         log_perror = 0;
2376
2377         if (daemon(1, 0) == -1)
2378                 error("daemon");
2379
2380         cap_rights_init(&rights);
2381
2382         if (pidfile != NULL) {
2383                 pidfile_write(pidfile);
2384                 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2385                     errno != ENOSYS) {
2386                         error("can't limit pidfile descriptor: %m");
2387                 }
2388         }
2389
2390         /* we are chrooted, daemon(3) fails to open /dev/null */
2391         if (nullfd != -1) {
2392                 dup2(nullfd, STDIN_FILENO);
2393                 dup2(nullfd, STDOUT_FILENO);
2394                 dup2(nullfd, STDERR_FILENO);
2395                 close(nullfd);
2396                 nullfd = -1;
2397         }
2398
2399         if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2400                 error("can't limit stdin: %m");
2401         cap_rights_init(&rights, CAP_WRITE);
2402         if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2403                 error("can't limit stdout: %m");
2404         if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2405                 error("can't limit stderr: %m");
2406 }
2407
2408 int
2409 check_option(struct client_lease *l, int option)
2410 {
2411         char *opbuf;
2412         char *sbuf;
2413
2414         /* we use this, since this is what gets passed to dhclient-script */
2415
2416         opbuf = pretty_print_option(option, l->options[option].data,
2417             l->options[option].len, 0, 0);
2418
2419         sbuf = option_as_string(option, l->options[option].data,
2420             l->options[option].len);
2421
2422         switch (option) {
2423         case DHO_SUBNET_MASK:
2424         case DHO_TIME_SERVERS:
2425         case DHO_NAME_SERVERS:
2426         case DHO_ROUTERS:
2427         case DHO_DOMAIN_NAME_SERVERS:
2428         case DHO_LOG_SERVERS:
2429         case DHO_COOKIE_SERVERS:
2430         case DHO_LPR_SERVERS:
2431         case DHO_IMPRESS_SERVERS:
2432         case DHO_RESOURCE_LOCATION_SERVERS:
2433         case DHO_SWAP_SERVER:
2434         case DHO_BROADCAST_ADDRESS:
2435         case DHO_NIS_SERVERS:
2436         case DHO_NTP_SERVERS:
2437         case DHO_NETBIOS_NAME_SERVERS:
2438         case DHO_NETBIOS_DD_SERVER:
2439         case DHO_FONT_SERVERS:
2440         case DHO_DHCP_SERVER_IDENTIFIER:
2441         case DHO_NISPLUS_SERVERS:
2442         case DHO_MOBILE_IP_HOME_AGENT:
2443         case DHO_SMTP_SERVER:
2444         case DHO_POP_SERVER:
2445         case DHO_NNTP_SERVER:
2446         case DHO_WWW_SERVER:
2447         case DHO_FINGER_SERVER:
2448         case DHO_IRC_SERVER:
2449         case DHO_STREETTALK_SERVER:
2450         case DHO_STREETTALK_DA_SERVER:
2451                 if (!ipv4addrs(opbuf)) {
2452                         warning("Invalid IP address in option: %s", opbuf);
2453                         return (0);
2454                 }
2455                 return (1)  ;
2456         case DHO_HOST_NAME:
2457         case DHO_NIS_DOMAIN:
2458         case DHO_NISPLUS_DOMAIN:
2459         case DHO_TFTP_SERVER_NAME:
2460                 if (!res_hnok(sbuf)) {
2461                         warning("Bogus Host Name option %d: %s (%s)", option,
2462                             sbuf, opbuf);
2463                         l->options[option].len = 0;
2464                         free(l->options[option].data);
2465                 }
2466                 return (1);
2467         case DHO_DOMAIN_NAME:
2468         case DHO_DOMAIN_SEARCH:
2469                 if (!res_hnok(sbuf)) {
2470                         if (!check_search(sbuf)) {
2471                                 warning("Bogus domain search list %d: %s (%s)",
2472                                     option, sbuf, opbuf);
2473                                 l->options[option].len = 0;
2474                                 free(l->options[option].data);
2475                         }
2476                 }
2477                 return (1);
2478         case DHO_PAD:
2479         case DHO_TIME_OFFSET:
2480         case DHO_BOOT_SIZE:
2481         case DHO_MERIT_DUMP:
2482         case DHO_ROOT_PATH:
2483         case DHO_EXTENSIONS_PATH:
2484         case DHO_IP_FORWARDING:
2485         case DHO_NON_LOCAL_SOURCE_ROUTING:
2486         case DHO_POLICY_FILTER:
2487         case DHO_MAX_DGRAM_REASSEMBLY:
2488         case DHO_DEFAULT_IP_TTL:
2489         case DHO_PATH_MTU_AGING_TIMEOUT:
2490         case DHO_PATH_MTU_PLATEAU_TABLE:
2491         case DHO_INTERFACE_MTU:
2492         case DHO_ALL_SUBNETS_LOCAL:
2493         case DHO_PERFORM_MASK_DISCOVERY:
2494         case DHO_MASK_SUPPLIER:
2495         case DHO_ROUTER_DISCOVERY:
2496         case DHO_ROUTER_SOLICITATION_ADDRESS:
2497         case DHO_STATIC_ROUTES:
2498         case DHO_TRAILER_ENCAPSULATION:
2499         case DHO_ARP_CACHE_TIMEOUT:
2500         case DHO_IEEE802_3_ENCAPSULATION:
2501         case DHO_DEFAULT_TCP_TTL:
2502         case DHO_TCP_KEEPALIVE_INTERVAL:
2503         case DHO_TCP_KEEPALIVE_GARBAGE:
2504         case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2505         case DHO_NETBIOS_NODE_TYPE:
2506         case DHO_NETBIOS_SCOPE:
2507         case DHO_X_DISPLAY_MANAGER:
2508         case DHO_DHCP_REQUESTED_ADDRESS:
2509         case DHO_DHCP_LEASE_TIME:
2510         case DHO_DHCP_OPTION_OVERLOAD:
2511         case DHO_DHCP_MESSAGE_TYPE:
2512         case DHO_DHCP_PARAMETER_REQUEST_LIST:
2513         case DHO_DHCP_MESSAGE:
2514         case DHO_DHCP_MAX_MESSAGE_SIZE:
2515         case DHO_DHCP_RENEWAL_TIME:
2516         case DHO_DHCP_REBINDING_TIME:
2517         case DHO_DHCP_CLASS_IDENTIFIER:
2518         case DHO_DHCP_CLIENT_IDENTIFIER:
2519         case DHO_BOOTFILE_NAME:
2520         case DHO_DHCP_USER_CLASS_ID:
2521         case DHO_END:
2522                 return (1);
2523         case DHO_CLASSLESS_ROUTES:
2524                 return (check_classless_option(l->options[option].data,
2525                     l->options[option].len));
2526         default:
2527                 warning("unknown dhcp option value 0x%x", option);
2528                 return (unknown_ok);
2529         }
2530 }
2531
2532 /* RFC 3442 The Classless Static Routes option checks */
2533 int
2534 check_classless_option(unsigned char *data, int len)
2535 {
2536         int i = 0;
2537         unsigned char width;
2538         in_addr_t addr, mask;
2539
2540         if (len < 5) {
2541                 warning("Too small length: %d", len);
2542                 return (0);
2543         }
2544         while(i < len) {
2545                 width = data[i++];
2546                 if (width == 0) {
2547                         i += 4;
2548                         continue;
2549                 } else if (width < 9) {
2550                         addr =  (in_addr_t)(data[i]     << 24);
2551                         i += 1;
2552                 } else if (width < 17) {
2553                         addr =  (in_addr_t)(data[i]     << 24) +
2554                                 (in_addr_t)(data[i + 1] << 16);
2555                         i += 2;
2556                 } else if (width < 25) {
2557                         addr =  (in_addr_t)(data[i]     << 24) +
2558                                 (in_addr_t)(data[i + 1] << 16) +
2559                                 (in_addr_t)(data[i + 2] << 8);
2560                         i += 3;
2561                 } else if (width < 33) {
2562                         addr =  (in_addr_t)(data[i]     << 24) +
2563                                 (in_addr_t)(data[i + 1] << 16) +
2564                                 (in_addr_t)(data[i + 2] << 8)  +
2565                                 data[i + 3];
2566                         i += 4;
2567                 } else {
2568                         warning("Incorrect subnet width: %d", width);
2569                         return (0);
2570                 }
2571                 mask = (in_addr_t)(~0) << (32 - width);
2572                 addr = ntohl(addr);
2573                 mask = ntohl(mask);
2574
2575                 /*
2576                  * From RFC 3442:
2577                  * ... After deriving a subnet number and subnet mask
2578                  * from each destination descriptor, the DHCP client
2579                  * MUST zero any bits in the subnet number where the
2580                  * corresponding bit in the mask is zero...
2581                  */
2582                 if ((addr & mask) != addr) {
2583                         addr &= mask;
2584                         data[i - 1] = (unsigned char)(
2585                                 (addr >> (((32 - width)/8)*8)) & 0xFF);
2586                 }
2587                 i += 4;
2588         }
2589         if (i > len) {
2590                 warning("Incorrect data length: %d (must be %d)", len, i);
2591                 return (0);
2592         }
2593         return (1);
2594 }
2595
2596 int
2597 res_hnok(const char *dn)
2598 {
2599         int pch = PERIOD, ch = *dn++;
2600
2601         while (ch != '\0') {
2602                 int nch = *dn++;
2603
2604                 if (periodchar(ch)) {
2605                         ;
2606                 } else if (periodchar(pch)) {
2607                         if (!borderchar(ch))
2608                                 return (0);
2609                 } else if (periodchar(nch) || nch == '\0') {
2610                         if (!borderchar(ch))
2611                                 return (0);
2612                 } else {
2613                         if (!middlechar(ch))
2614                                 return (0);
2615                 }
2616                 pch = ch, ch = nch;
2617         }
2618         return (1);
2619 }
2620
2621 int
2622 check_search(const char *srch)
2623 {
2624         int pch = PERIOD, ch = *srch++;
2625         int domains = 1;
2626
2627         /* 256 char limit re resolv.conf(5) */
2628         if (strlen(srch) > 256)
2629                 return (0);
2630
2631         while (whitechar(ch))
2632                 ch = *srch++;
2633
2634         while (ch != '\0') {
2635                 int nch = *srch++;
2636
2637                 if (periodchar(ch) || whitechar(ch)) {
2638                         ;
2639                 } else if (periodchar(pch)) {
2640                         if (!borderchar(ch))
2641                                 return (0);
2642                 } else if (periodchar(nch) || nch == '\0') {
2643                         if (!borderchar(ch))
2644                                 return (0);
2645                 } else {
2646                         if (!middlechar(ch))
2647                                 return (0);
2648                 }
2649                 if (!whitechar(ch)) {
2650                         pch = ch;
2651                 } else {
2652                         while (whitechar(nch)) {
2653                                 nch = *srch++;
2654                         }
2655                         if (nch != '\0')
2656                                 domains++;
2657                         pch = PERIOD;
2658                 }
2659                 ch = nch;
2660         }
2661         /* 6 domain limit re resolv.conf(5) */
2662         if (domains > 6)
2663                 return (0);
2664         return (1);
2665 }
2666
2667 /* Does buf consist only of dotted decimal ipv4 addrs?
2668  * return how many if so,
2669  * otherwise, return 0
2670  */
2671 int
2672 ipv4addrs(char * buf)
2673 {
2674         struct in_addr jnk;
2675         int count = 0;
2676
2677         while (inet_aton(buf, &jnk) == 1){
2678                 count++;
2679                 while (periodchar(*buf) || digitchar(*buf))
2680                         buf++;
2681                 if (*buf == '\0')
2682                         return (count);
2683                 while (*buf ==  ' ')
2684                         buf++;
2685         }
2686         return (0);
2687 }
2688
2689
2690 char *
2691 option_as_string(unsigned int code, unsigned char *data, int len)
2692 {
2693         static char optbuf[32768]; /* XXX */
2694         char *op = optbuf;
2695         int opleft = sizeof(optbuf);
2696         unsigned char *dp = data;
2697
2698         if (code > 255)
2699                 error("option_as_string: bad code %d", code);
2700
2701         for (; dp < data + len; dp++) {
2702                 if (!isascii(*dp) || !isprint(*dp)) {
2703                         if (dp + 1 != data + len || *dp != 0) {
2704                                 snprintf(op, opleft, "\\%03o", *dp);
2705                                 op += 4;
2706                                 opleft -= 4;
2707                         }
2708                 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2709                     *dp == '`' || *dp == '\\') {
2710                         *op++ = '\\';
2711                         *op++ = *dp;
2712                         opleft -= 2;
2713                 } else {
2714                         *op++ = *dp;
2715                         opleft--;
2716                 }
2717         }
2718         if (opleft < 1)
2719                 goto toobig;
2720         *op = 0;
2721         return optbuf;
2722 toobig:
2723         warning("dhcp option too large");
2724         return "<error>";
2725 }
2726
2727 int
2728 fork_privchld(int fd, int fd2)
2729 {
2730         struct pollfd pfd[1];
2731         int nfds;
2732
2733         switch (fork()) {
2734         case -1:
2735                 error("cannot fork");
2736         case 0:
2737                 break;
2738         default:
2739                 return (0);
2740         }
2741
2742         setproctitle("%s [priv]", ifi->name);
2743
2744         setsid();
2745         dup2(nullfd, STDIN_FILENO);
2746         dup2(nullfd, STDOUT_FILENO);
2747         dup2(nullfd, STDERR_FILENO);
2748         close(nullfd);
2749         close(fd2);
2750         close(ifi->rfdesc);
2751         ifi->rfdesc = -1;
2752
2753         for (;;) {
2754                 pfd[0].fd = fd;
2755                 pfd[0].events = POLLIN;
2756                 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2757                         if (errno != EINTR)
2758                                 error("poll error");
2759
2760                 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2761                         continue;
2762
2763                 dispatch_imsg(ifi, fd);
2764         }
2765 }