]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sbin/dhclient/dhclient.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sbin / dhclient / dhclient.c
1 /*      $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $       */
2
3 /*
4  * Copyright 2004 Henning Brauer <henning@openbsd.org>
5  * Copyright (c) 1995, 1996, 1997, 1998, 1999
6  * The Internet Software Consortium.    All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of The Internet Software Consortium nor the names
18  *    of its contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
22  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
26  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
29  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * This software has been written for the Internet Software Consortium
36  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
37  * Enterprises.  To learn more about the Internet Software Consortium,
38  * see ``http://www.vix.com/isc''.  To learn more about Vixie
39  * Enterprises, see ``http://www.vix.com''.
40  *
41  * This client was substantially modified and enhanced by Elliot Poger
42  * for use on Linux while he was working on the MosquitoNet project at
43  * Stanford.
44  *
45  * The current version owes much to Elliot's Linux enhancements, but
46  * was substantially reorganized and partially rewritten by Ted Lemon
47  * so as to use the same networking framework that the Internet Software
48  * Consortium DHCP server uses.   Much system-specific configuration code
49  * was moved into a shell script so that as support for more operating
50  * systems is added, it will not be necessary to port and maintain
51  * system-specific configuration code to these operating systems - instead,
52  * the shell script can invoke the native tools to accomplish the same
53  * purpose.
54  */
55
56 #include <sys/cdefs.h>
57 __FBSDID("$FreeBSD$");
58
59 #include <sys/capability.h>
60
61 #include "dhcpd.h"
62 #include "privsep.h"
63
64 #include <sys/capability.h>
65
66 #include <net80211/ieee80211_freebsd.h>
67
68 #ifndef _PATH_VAREMPTY
69 #define _PATH_VAREMPTY  "/var/empty"
70 #endif
71
72 #define PERIOD 0x2e
73 #define hyphenchar(c) ((c) == 0x2d)
74 #define bslashchar(c) ((c) == 0x5c)
75 #define periodchar(c) ((c) == PERIOD)
76 #define asterchar(c) ((c) == 0x2a)
77 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
78             ((c) >= 0x61 && (c) <= 0x7a))
79 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
80 #define whitechar(c) ((c) == ' ' || (c) == '\t')
81
82 #define borderchar(c) (alphachar(c) || digitchar(c))
83 #define middlechar(c) (borderchar(c) || hyphenchar(c))
84 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
85
86 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
87
88 time_t cur_time;
89 time_t default_lease_time = 43200; /* 12 hours... */
90
91 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
92 char *path_dhclient_db = NULL;
93
94 int log_perror = 1;
95 int privfd;
96 int nullfd = -1;
97
98 char hostname[_POSIX_HOST_NAME_MAX + 1];
99
100 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
101 struct in_addr inaddr_any, inaddr_broadcast;
102
103 char *path_dhclient_pidfile;
104 struct pidfh *pidfile;
105
106 /*
107  * ASSERT_STATE() does nothing now; it used to be
108  * assert (state_is == state_shouldbe).
109  */
110 #define ASSERT_STATE(state_is, state_shouldbe) {}
111
112 #define TIME_MAX 2147483647
113
114 int             log_priority;
115 int             no_daemon;
116 int             unknown_ok = 1;
117 int             routefd;
118
119 struct interface_info   *ifi;
120
121 int              findproto(char *, int);
122 struct sockaddr *get_ifa(char *, int);
123 void             routehandler(struct protocol *);
124 void             usage(void);
125 int              check_option(struct client_lease *l, int option);
126 int              check_classless_option(unsigned char *data, int len);
127 int              ipv4addrs(char * buf);
128 int              res_hnok(const char *dn);
129 int              check_search(const char *srch);
130 char            *option_as_string(unsigned int code, unsigned char *data, int len);
131 int              fork_privchld(int, int);
132
133 #define ROUNDUP(a) \
134             ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
135 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
136
137 static time_t   scripttime;
138
139 int
140 findproto(char *cp, int n)
141 {
142         struct sockaddr *sa;
143         int i;
144
145         if (n == 0)
146                 return -1;
147         for (i = 1; i; i <<= 1) {
148                 if (i & n) {
149                         sa = (struct sockaddr *)cp;
150                         switch (i) {
151                         case RTA_IFA:
152                         case RTA_DST:
153                         case RTA_GATEWAY:
154                         case RTA_NETMASK:
155                                 if (sa->sa_family == AF_INET)
156                                         return AF_INET;
157                                 if (sa->sa_family == AF_INET6)
158                                         return AF_INET6;
159                                 break;
160                         case RTA_IFP:
161                                 break;
162                         }
163                         ADVANCE(cp, sa);
164                 }
165         }
166         return (-1);
167 }
168
169 struct sockaddr *
170 get_ifa(char *cp, int n)
171 {
172         struct sockaddr *sa;
173         int i;
174
175         if (n == 0)
176                 return (NULL);
177         for (i = 1; i; i <<= 1)
178                 if (i & n) {
179                         sa = (struct sockaddr *)cp;
180                         if (i == RTA_IFA)
181                                 return (sa);
182                         ADVANCE(cp, sa);
183                 }
184
185         return (NULL);
186 }
187
188 struct iaddr defaddr = { 4 };
189 uint8_t curbssid[6];
190
191 static void
192 disassoc(void *arg)
193 {
194         struct interface_info *ifi = arg;
195
196         /*
197          * Clear existing state.
198          */
199         if (ifi->client->active != NULL) {
200                 script_init("EXPIRE", NULL);
201                 script_write_params("old_",
202                     ifi->client->active);
203                 if (ifi->client->alias)
204                         script_write_params("alias_",
205                                 ifi->client->alias);
206                 script_go();
207         }
208         ifi->client->state = S_INIT;
209 }
210
211 /* ARGSUSED */
212 void
213 routehandler(struct protocol *p)
214 {
215         char msg[2048], *addr;
216         struct rt_msghdr *rtm;
217         struct if_msghdr *ifm;
218         struct ifa_msghdr *ifam;
219         struct if_announcemsghdr *ifan;
220         struct ieee80211_join_event *jev;
221         struct client_lease *l;
222         time_t t = time(NULL);
223         struct sockaddr *sa;
224         struct iaddr a;
225         ssize_t n;
226         int linkstat;
227
228         n = read(routefd, &msg, sizeof(msg));
229         rtm = (struct rt_msghdr *)msg;
230         if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
231             rtm->rtm_version != RTM_VERSION)
232                 return;
233
234         switch (rtm->rtm_type) {
235         case RTM_NEWADDR:
236         case RTM_DELADDR:
237                 ifam = (struct ifa_msghdr *)rtm;
238
239                 if (ifam->ifam_index != ifi->index)
240                         break;
241                 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
242                         break;
243                 if (scripttime == 0 || t < scripttime + 10)
244                         break;
245
246                 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
247                 if (sa == NULL)
248                         break;
249
250                 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
251                         error("king bula sez: len mismatch");
252                 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
253                 if (addr_eq(a, defaddr))
254                         break;
255
256                 for (l = ifi->client->active; l != NULL; l = l->next)
257                         if (addr_eq(a, l->address))
258                                 break;
259
260                 if (l == NULL)  /* added/deleted addr is not the one we set */
261                         break;
262
263                 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
264                 if (rtm->rtm_type == RTM_NEWADDR)  {
265                         /*
266                          * XXX: If someone other than us adds our address,
267                          * should we assume they are taking over from us,
268                          * delete the lease record, and exit without modifying
269                          * the interface?
270                          */
271                         warning("My address (%s) was re-added", addr);
272                 } else {
273                         warning("My address (%s) was deleted, dhclient exiting",
274                             addr);
275                         goto die;
276                 }
277                 break;
278         case RTM_IFINFO:
279                 ifm = (struct if_msghdr *)rtm;
280                 if (ifm->ifm_index != ifi->index)
281                         break;
282                 if ((rtm->rtm_flags & RTF_UP) == 0) {
283                         warning("Interface %s is down, dhclient exiting",
284                             ifi->name);
285                         goto die;
286                 }
287                 linkstat = interface_link_status(ifi->name);
288                 if (linkstat != ifi->linkstat) {
289                         debug("%s link state %s -> %s", ifi->name,
290                             ifi->linkstat ? "up" : "down",
291                             linkstat ? "up" : "down");
292                         ifi->linkstat = linkstat;
293                         if (linkstat)
294                                 state_reboot(ifi);
295                 }
296                 break;
297         case RTM_IFANNOUNCE:
298                 ifan = (struct if_announcemsghdr *)rtm;
299                 if (ifan->ifan_what == IFAN_DEPARTURE &&
300                     ifan->ifan_index == ifi->index) {
301                         warning("Interface %s is gone, dhclient exiting",
302                             ifi->name);
303                         goto die;
304                 }
305                 break;
306         case RTM_IEEE80211:
307                 ifan = (struct if_announcemsghdr *)rtm;
308                 if (ifan->ifan_index != ifi->index)
309                         break;
310                 switch (ifan->ifan_what) {
311                 case RTM_IEEE80211_ASSOC:
312                 case RTM_IEEE80211_REASSOC:
313                         /*
314                          * Use assoc/reassoc event to kick state machine
315                          * in case we roam.  Otherwise fall back to the
316                          * normal state machine just like a wired network.
317                          */
318                         jev = (struct ieee80211_join_event *) &ifan[1];
319                         if (memcmp(curbssid, jev->iev_addr, 6)) {
320                                 disassoc(ifi);
321                                 state_reboot(ifi);
322                         }
323                         memcpy(curbssid, jev->iev_addr, 6);
324                         break;
325                 }
326                 break;
327         default:
328                 break;
329         }
330         return;
331
332 die:
333         script_init("FAIL", NULL);
334         if (ifi->client->alias)
335                 script_write_params("alias_", ifi->client->alias);
336         script_go();
337         if (pidfile != NULL)
338                 pidfile_remove(pidfile);
339         exit(1);
340 }
341
342 int
343 main(int argc, char *argv[])
344 {
345         extern char             *__progname;
346         int                      ch, fd, quiet = 0, i = 0;
347         int                      pipe_fd[2];
348         int                      immediate_daemon = 0;
349         struct passwd           *pw;
350         pid_t                    otherpid;
351         cap_rights_t             rights;
352
353         /* Initially, log errors to stderr as well as to syslogd. */
354         openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
355         setlogmask(LOG_UPTO(LOG_DEBUG));
356
357         while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
358                 switch (ch) {
359                 case 'b':
360                         immediate_daemon = 1;
361                         break;
362                 case 'c':
363                         path_dhclient_conf = optarg;
364                         break;
365                 case 'd':
366                         no_daemon = 1;
367                         break;
368                 case 'l':
369                         path_dhclient_db = optarg;
370                         break;
371                 case 'p':
372                         path_dhclient_pidfile = optarg;
373                         break;
374                 case 'q':
375                         quiet = 1;
376                         break;
377                 case 'u':
378                         unknown_ok = 0;
379                         break;
380                 default:
381                         usage();
382                 }
383
384         argc -= optind;
385         argv += optind;
386
387         if (argc != 1)
388                 usage();
389
390         if (path_dhclient_pidfile == NULL) {
391                 asprintf(&path_dhclient_pidfile,
392                     "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
393                 if (path_dhclient_pidfile == NULL)
394                         error("asprintf");
395         }
396         pidfile = pidfile_open(path_dhclient_pidfile, 0600, &otherpid);
397         if (pidfile == NULL) {
398                 if (errno == EEXIST)
399                         error("dhclient already running, pid: %d.", otherpid);
400                 if (errno == EAGAIN)
401                         error("dhclient already running.");
402                 warning("Cannot open or create pidfile: %m");
403         }
404
405         if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
406                 error("calloc");
407         if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
408                 error("Interface name too long");
409         if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
410             _PATH_DHCLIENT_DB, ifi->name) == -1)
411                 error("asprintf");
412
413         if (quiet)
414                 log_perror = 0;
415
416         tzset();
417         time(&cur_time);
418
419         inaddr_broadcast.s_addr = INADDR_BROADCAST;
420         inaddr_any.s_addr = INADDR_ANY;
421
422         read_client_conf();
423
424         /* The next bit is potentially very time-consuming, so write out
425            the pidfile right away.  We will write it out again with the
426            correct pid after daemonizing. */
427         if (pidfile != NULL)
428                 pidfile_write(pidfile);
429
430         if (!interface_link_status(ifi->name)) {
431                 fprintf(stderr, "%s: no link ...", ifi->name);
432                 fflush(stderr);
433                 sleep(1);
434                 while (!interface_link_status(ifi->name)) {
435                         fprintf(stderr, ".");
436                         fflush(stderr);
437                         if (++i > 10) {
438                                 fprintf(stderr, " giving up\n");
439                                 exit(1);
440                         }
441                         sleep(1);
442                 }
443                 fprintf(stderr, " got link\n");
444         }
445         ifi->linkstat = 1;
446
447         if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
448                 error("cannot open %s: %m", _PATH_DEVNULL);
449
450         if ((pw = getpwnam("_dhcp")) == NULL) {
451                 warning("no such user: _dhcp, falling back to \"nobody\"");
452                 if ((pw = getpwnam("nobody")) == NULL)
453                         error("no such user: nobody");
454         }
455
456         /*
457          * Obtain hostname before entering capability mode - it won't be
458          * possible then, as reading kern.hostname is not permitted.
459          */
460         if (gethostname(hostname, sizeof(hostname)) < 0)
461                 hostname[0] = '\0';
462
463         priv_script_init("PREINIT", NULL);
464         if (ifi->client->alias)
465                 priv_script_write_params("alias_", ifi->client->alias);
466         priv_script_go();
467
468         /* set up the interface */
469         discover_interfaces(ifi);
470
471         if (pipe(pipe_fd) == -1)
472                 error("pipe");
473
474         fork_privchld(pipe_fd[0], pipe_fd[1]);
475
476         close(ifi->ufdesc);
477         ifi->ufdesc = -1;
478         close(ifi->wfdesc);
479         ifi->wfdesc = -1;
480
481         close(pipe_fd[0]);
482         privfd = pipe_fd[1];
483         cap_rights_init(&rights, CAP_READ, CAP_WRITE);
484         if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
485                 error("can't limit private descriptor: %m");
486
487         if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
488                 error("can't open and lock %s: %m", path_dhclient_db);
489         read_client_leases();
490         rewrite_client_leases();
491         close(fd);
492
493         if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
494                 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
495         if (shutdown(routefd, SHUT_WR) < 0)
496                 error("can't shutdown route socket: %m");
497         cap_rights_init(&rights, CAP_POLL_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         char client_ident[sizeof(struct hardware)];
1576         if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1577                 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1578                                 ip->hw_address.hlen : sizeof(client_ident)-1;
1579                 client_ident[0] = ip->hw_address.htype;
1580                 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1581                 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1582                 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1583                 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1584                 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1585                 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1586         }
1587
1588         /* Set up the option buffer... */
1589         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1590             options, 0, 0, 0, NULL, 0);
1591         if (ip->client->packet_length < BOOTP_MIN_LEN)
1592                 ip->client->packet_length = BOOTP_MIN_LEN;
1593
1594         ip->client->packet.op = BOOTREQUEST;
1595         ip->client->packet.htype = ip->hw_address.htype;
1596         ip->client->packet.hlen = ip->hw_address.hlen;
1597         ip->client->packet.hops = 0;
1598         ip->client->packet.xid = arc4random();
1599         ip->client->packet.secs = 0; /* filled in by send_discover. */
1600         ip->client->packet.flags = 0;
1601
1602         memset(&(ip->client->packet.ciaddr),
1603             0, sizeof(ip->client->packet.ciaddr));
1604         memset(&(ip->client->packet.yiaddr),
1605             0, sizeof(ip->client->packet.yiaddr));
1606         memset(&(ip->client->packet.siaddr),
1607             0, sizeof(ip->client->packet.siaddr));
1608         memset(&(ip->client->packet.giaddr),
1609             0, sizeof(ip->client->packet.giaddr));
1610         memcpy(ip->client->packet.chaddr,
1611             ip->hw_address.haddr, ip->hw_address.hlen);
1612 }
1613
1614
1615 void
1616 make_request(struct interface_info *ip, struct client_lease * lease)
1617 {
1618         unsigned char request = DHCPREQUEST;
1619         struct tree_cache *options[256];
1620         struct tree_cache option_elements[256];
1621         int i;
1622
1623         memset(options, 0, sizeof(options));
1624         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1625
1626         /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1627         i = DHO_DHCP_MESSAGE_TYPE;
1628         options[i] = &option_elements[i];
1629         options[i]->value = &request;
1630         options[i]->len = sizeof(request);
1631         options[i]->buf_size = sizeof(request);
1632         options[i]->timeout = 0xFFFFFFFF;
1633
1634         /* Request the options we want */
1635         i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1636         options[i] = &option_elements[i];
1637         options[i]->value = ip->client->config->requested_options;
1638         options[i]->len = ip->client->config->requested_option_count;
1639         options[i]->buf_size =
1640                 ip->client->config->requested_option_count;
1641         options[i]->timeout = 0xFFFFFFFF;
1642
1643         /* If we are requesting an address that hasn't yet been assigned
1644            to us, use the DHCP Requested Address option. */
1645         if (ip->client->state == S_REQUESTING) {
1646                 /* Send back the server identifier... */
1647                 i = DHO_DHCP_SERVER_IDENTIFIER;
1648                 options[i] = &option_elements[i];
1649                 options[i]->value = lease->options[i].data;
1650                 options[i]->len = lease->options[i].len;
1651                 options[i]->buf_size = lease->options[i].len;
1652                 options[i]->timeout = 0xFFFFFFFF;
1653         }
1654         if (ip->client->state == S_REQUESTING ||
1655             ip->client->state == S_REBOOTING) {
1656                 ip->client->requested_address = lease->address;
1657                 i = DHO_DHCP_REQUESTED_ADDRESS;
1658                 options[i] = &option_elements[i];
1659                 options[i]->value = lease->address.iabuf;
1660                 options[i]->len = lease->address.len;
1661                 options[i]->buf_size = lease->address.len;
1662                 options[i]->timeout = 0xFFFFFFFF;
1663         } else
1664                 ip->client->requested_address.len = 0;
1665
1666         /* Send any options requested in the config file. */
1667         for (i = 0; i < 256; i++)
1668                 if (!options[i] &&
1669                     ip->client->config->send_options[i].data) {
1670                         options[i] = &option_elements[i];
1671                         options[i]->value =
1672                             ip->client->config->send_options[i].data;
1673                         options[i]->len =
1674                             ip->client->config->send_options[i].len;
1675                         options[i]->buf_size =
1676                             ip->client->config->send_options[i].len;
1677                         options[i]->timeout = 0xFFFFFFFF;
1678                 }
1679
1680         /* send host name if not set via config file. */
1681         if (!options[DHO_HOST_NAME]) {
1682                 if (hostname[0] != '\0') {
1683                         size_t len;
1684                         char* posDot = strchr(hostname, '.');
1685                         if (posDot != NULL)
1686                                 len = posDot - hostname;
1687                         else
1688                                 len = strlen(hostname);
1689                         options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1690                         options[DHO_HOST_NAME]->value = hostname;
1691                         options[DHO_HOST_NAME]->len = len;
1692                         options[DHO_HOST_NAME]->buf_size = len;
1693                         options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1694                 }
1695         }
1696
1697         /* set unique client identifier */
1698         char client_ident[sizeof(struct hardware)];
1699         if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1700                 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1701                                 ip->hw_address.hlen : sizeof(client_ident)-1;
1702                 client_ident[0] = ip->hw_address.htype;
1703                 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1704                 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1705                 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1706                 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1707                 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1708                 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1709         }
1710
1711         /* Set up the option buffer... */
1712         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1713             options, 0, 0, 0, NULL, 0);
1714         if (ip->client->packet_length < BOOTP_MIN_LEN)
1715                 ip->client->packet_length = BOOTP_MIN_LEN;
1716
1717         ip->client->packet.op = BOOTREQUEST;
1718         ip->client->packet.htype = ip->hw_address.htype;
1719         ip->client->packet.hlen = ip->hw_address.hlen;
1720         ip->client->packet.hops = 0;
1721         ip->client->packet.xid = ip->client->xid;
1722         ip->client->packet.secs = 0; /* Filled in by send_request. */
1723
1724         /* If we own the address we're requesting, put it in ciaddr;
1725            otherwise set ciaddr to zero. */
1726         if (ip->client->state == S_BOUND ||
1727             ip->client->state == S_RENEWING ||
1728             ip->client->state == S_REBINDING) {
1729                 memcpy(&ip->client->packet.ciaddr,
1730                     lease->address.iabuf, lease->address.len);
1731                 ip->client->packet.flags = 0;
1732         } else {
1733                 memset(&ip->client->packet.ciaddr, 0,
1734                     sizeof(ip->client->packet.ciaddr));
1735                 ip->client->packet.flags = 0;
1736         }
1737
1738         memset(&ip->client->packet.yiaddr, 0,
1739             sizeof(ip->client->packet.yiaddr));
1740         memset(&ip->client->packet.siaddr, 0,
1741             sizeof(ip->client->packet.siaddr));
1742         memset(&ip->client->packet.giaddr, 0,
1743             sizeof(ip->client->packet.giaddr));
1744         memcpy(ip->client->packet.chaddr,
1745             ip->hw_address.haddr, ip->hw_address.hlen);
1746 }
1747
1748 void
1749 make_decline(struct interface_info *ip, struct client_lease *lease)
1750 {
1751         struct tree_cache *options[256], message_type_tree;
1752         struct tree_cache requested_address_tree;
1753         struct tree_cache server_id_tree, client_id_tree;
1754         unsigned char decline = DHCPDECLINE;
1755         int i;
1756
1757         memset(options, 0, sizeof(options));
1758         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1759
1760         /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1761         i = DHO_DHCP_MESSAGE_TYPE;
1762         options[i] = &message_type_tree;
1763         options[i]->value = &decline;
1764         options[i]->len = sizeof(decline);
1765         options[i]->buf_size = sizeof(decline);
1766         options[i]->timeout = 0xFFFFFFFF;
1767
1768         /* Send back the server identifier... */
1769         i = DHO_DHCP_SERVER_IDENTIFIER;
1770         options[i] = &server_id_tree;
1771         options[i]->value = lease->options[i].data;
1772         options[i]->len = lease->options[i].len;
1773         options[i]->buf_size = lease->options[i].len;
1774         options[i]->timeout = 0xFFFFFFFF;
1775
1776         /* Send back the address we're declining. */
1777         i = DHO_DHCP_REQUESTED_ADDRESS;
1778         options[i] = &requested_address_tree;
1779         options[i]->value = lease->address.iabuf;
1780         options[i]->len = lease->address.len;
1781         options[i]->buf_size = lease->address.len;
1782         options[i]->timeout = 0xFFFFFFFF;
1783
1784         /* Send the uid if the user supplied one. */
1785         i = DHO_DHCP_CLIENT_IDENTIFIER;
1786         if (ip->client->config->send_options[i].len) {
1787                 options[i] = &client_id_tree;
1788                 options[i]->value = ip->client->config->send_options[i].data;
1789                 options[i]->len = ip->client->config->send_options[i].len;
1790                 options[i]->buf_size = ip->client->config->send_options[i].len;
1791                 options[i]->timeout = 0xFFFFFFFF;
1792         }
1793
1794
1795         /* Set up the option buffer... */
1796         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1797             options, 0, 0, 0, NULL, 0);
1798         if (ip->client->packet_length < BOOTP_MIN_LEN)
1799                 ip->client->packet_length = BOOTP_MIN_LEN;
1800
1801         ip->client->packet.op = BOOTREQUEST;
1802         ip->client->packet.htype = ip->hw_address.htype;
1803         ip->client->packet.hlen = ip->hw_address.hlen;
1804         ip->client->packet.hops = 0;
1805         ip->client->packet.xid = ip->client->xid;
1806         ip->client->packet.secs = 0; /* Filled in by send_request. */
1807         ip->client->packet.flags = 0;
1808
1809         /* ciaddr must always be zero. */
1810         memset(&ip->client->packet.ciaddr, 0,
1811             sizeof(ip->client->packet.ciaddr));
1812         memset(&ip->client->packet.yiaddr, 0,
1813             sizeof(ip->client->packet.yiaddr));
1814         memset(&ip->client->packet.siaddr, 0,
1815             sizeof(ip->client->packet.siaddr));
1816         memset(&ip->client->packet.giaddr, 0,
1817             sizeof(ip->client->packet.giaddr));
1818         memcpy(ip->client->packet.chaddr,
1819             ip->hw_address.haddr, ip->hw_address.hlen);
1820 }
1821
1822 void
1823 free_client_lease(struct client_lease *lease)
1824 {
1825         int i;
1826
1827         if (lease->server_name)
1828                 free(lease->server_name);
1829         if (lease->filename)
1830                 free(lease->filename);
1831         for (i = 0; i < 256; i++) {
1832                 if (lease->options[i].len)
1833                         free(lease->options[i].data);
1834         }
1835         free(lease);
1836 }
1837
1838 FILE *leaseFile;
1839
1840 void
1841 rewrite_client_leases(void)
1842 {
1843         struct client_lease *lp;
1844         cap_rights_t rights;
1845
1846         if (!leaseFile) {
1847                 leaseFile = fopen(path_dhclient_db, "w");
1848                 if (!leaseFile)
1849                         error("can't create %s: %m", path_dhclient_db);
1850                 cap_rights_init(&rights, CAP_FSTAT, CAP_FSYNC, CAP_FTRUNCATE,
1851                     CAP_SEEK, CAP_WRITE);
1852                 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1853                     errno != ENOSYS) {
1854                         error("can't limit lease descriptor: %m");
1855                 }
1856         } else {
1857                 fflush(leaseFile);
1858                 rewind(leaseFile);
1859         }
1860
1861         for (lp = ifi->client->leases; lp; lp = lp->next)
1862                 write_client_lease(ifi, lp, 1);
1863         if (ifi->client->active)
1864                 write_client_lease(ifi, ifi->client->active, 1);
1865
1866         fflush(leaseFile);
1867         ftruncate(fileno(leaseFile), ftello(leaseFile));
1868         fsync(fileno(leaseFile));
1869 }
1870
1871 void
1872 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1873     int rewrite)
1874 {
1875         static int leases_written;
1876         struct tm *t;
1877         int i;
1878
1879         if (!rewrite) {
1880                 if (leases_written++ > 20) {
1881                         rewrite_client_leases();
1882                         leases_written = 0;
1883                 }
1884         }
1885
1886         /* If the lease came from the config file, we don't need to stash
1887            a copy in the lease database. */
1888         if (lease->is_static)
1889                 return;
1890
1891         if (!leaseFile) {       /* XXX */
1892                 leaseFile = fopen(path_dhclient_db, "w");
1893                 if (!leaseFile)
1894                         error("can't create %s: %m", path_dhclient_db);
1895         }
1896
1897         fprintf(leaseFile, "lease {\n");
1898         if (lease->is_bootp)
1899                 fprintf(leaseFile, "  bootp;\n");
1900         fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1901         fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
1902         if (lease->nextserver.len == sizeof(inaddr_any) &&
1903             0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1904             sizeof(inaddr_any)))
1905                 fprintf(leaseFile, "  next-server %s;\n",
1906                     piaddr(lease->nextserver));
1907         if (lease->filename)
1908                 fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
1909         if (lease->server_name)
1910                 fprintf(leaseFile, "  server-name \"%s\";\n",
1911                     lease->server_name);
1912         if (lease->medium)
1913                 fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
1914         for (i = 0; i < 256; i++)
1915                 if (lease->options[i].len)
1916                         fprintf(leaseFile, "  option %s %s;\n",
1917                             dhcp_options[i].name,
1918                             pretty_print_option(i, lease->options[i].data,
1919                             lease->options[i].len, 1, 1));
1920
1921         t = gmtime(&lease->renewal);
1922         fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
1923             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1924             t->tm_hour, t->tm_min, t->tm_sec);
1925         t = gmtime(&lease->rebind);
1926         fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1927             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1928             t->tm_hour, t->tm_min, t->tm_sec);
1929         t = gmtime(&lease->expiry);
1930         fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
1931             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1932             t->tm_hour, t->tm_min, t->tm_sec);
1933         fprintf(leaseFile, "}\n");
1934         fflush(leaseFile);
1935 }
1936
1937 void
1938 script_init(char *reason, struct string_list *medium)
1939 {
1940         size_t           len, mediumlen = 0;
1941         struct imsg_hdr  hdr;
1942         struct buf      *buf;
1943         int              errs;
1944
1945         if (medium != NULL && medium->string != NULL)
1946                 mediumlen = strlen(medium->string);
1947
1948         hdr.code = IMSG_SCRIPT_INIT;
1949         hdr.len = sizeof(struct imsg_hdr) +
1950             sizeof(size_t) + mediumlen +
1951             sizeof(size_t) + strlen(reason);
1952
1953         if ((buf = buf_open(hdr.len)) == NULL)
1954                 error("buf_open: %m");
1955
1956         errs = 0;
1957         errs += buf_add(buf, &hdr, sizeof(hdr));
1958         errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1959         if (mediumlen > 0)
1960                 errs += buf_add(buf, medium->string, mediumlen);
1961         len = strlen(reason);
1962         errs += buf_add(buf, &len, sizeof(len));
1963         errs += buf_add(buf, reason, len);
1964
1965         if (errs)
1966                 error("buf_add: %m");
1967
1968         if (buf_close(privfd, buf) == -1)
1969                 error("buf_close: %m");
1970 }
1971
1972 void
1973 priv_script_init(char *reason, char *medium)
1974 {
1975         struct interface_info *ip = ifi;
1976
1977         if (ip) {
1978                 ip->client->scriptEnvsize = 100;
1979                 if (ip->client->scriptEnv == NULL)
1980                         ip->client->scriptEnv =
1981                             malloc(ip->client->scriptEnvsize * sizeof(char *));
1982                 if (ip->client->scriptEnv == NULL)
1983                         error("script_init: no memory for environment");
1984
1985                 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
1986                 if (ip->client->scriptEnv[0] == NULL)
1987                         error("script_init: no memory for environment");
1988
1989                 ip->client->scriptEnv[1] = NULL;
1990
1991                 script_set_env(ip->client, "", "interface", ip->name);
1992
1993                 if (medium)
1994                         script_set_env(ip->client, "", "medium", medium);
1995
1996                 script_set_env(ip->client, "", "reason", reason);
1997         }
1998 }
1999
2000 void
2001 priv_script_write_params(char *prefix, struct client_lease *lease)
2002 {
2003         struct interface_info *ip = ifi;
2004         u_int8_t dbuf[1500], *dp = NULL;
2005         int i, len;
2006         char tbuf[128];
2007
2008         script_set_env(ip->client, prefix, "ip_address",
2009             piaddr(lease->address));
2010
2011         if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2012             ACTION_SUPERSEDE) {
2013                 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2014                 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2015         } else {
2016                 dp = lease->options[DHO_SUBNET_MASK].data;
2017                 len = lease->options[DHO_SUBNET_MASK].len;
2018         }
2019         if (len && (len < sizeof(lease->address.iabuf))) {
2020                 struct iaddr netmask, subnet, broadcast;
2021
2022                 memcpy(netmask.iabuf, dp, len);
2023                 netmask.len = len;
2024                 subnet = subnet_number(lease->address, netmask);
2025                 if (subnet.len) {
2026                         script_set_env(ip->client, prefix, "network_number",
2027                             piaddr(subnet));
2028                         if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2029                                 broadcast = broadcast_addr(subnet, netmask);
2030                                 if (broadcast.len)
2031                                         script_set_env(ip->client, prefix,
2032                                             "broadcast_address",
2033                                             piaddr(broadcast));
2034                         }
2035                 }
2036         }
2037
2038         if (lease->filename)
2039                 script_set_env(ip->client, prefix, "filename", lease->filename);
2040         if (lease->server_name)
2041                 script_set_env(ip->client, prefix, "server_name",
2042                     lease->server_name);
2043         for (i = 0; i < 256; i++) {
2044                 len = 0;
2045
2046                 if (ip->client->config->defaults[i].len) {
2047                         if (lease->options[i].len) {
2048                                 switch (
2049                                     ip->client->config->default_actions[i]) {
2050                                 case ACTION_DEFAULT:
2051                                         dp = lease->options[i].data;
2052                                         len = lease->options[i].len;
2053                                         break;
2054                                 case ACTION_SUPERSEDE:
2055 supersede:
2056                                         dp = ip->client->
2057                                                 config->defaults[i].data;
2058                                         len = ip->client->
2059                                                 config->defaults[i].len;
2060                                         break;
2061                                 case ACTION_PREPEND:
2062                                         len = ip->client->
2063                                             config->defaults[i].len +
2064                                             lease->options[i].len;
2065                                         if (len >= sizeof(dbuf)) {
2066                                                 warning("no space to %s %s",
2067                                                     "prepend option",
2068                                                     dhcp_options[i].name);
2069                                                 goto supersede;
2070                                         }
2071                                         dp = dbuf;
2072                                         memcpy(dp,
2073                                                 ip->client->
2074                                                 config->defaults[i].data,
2075                                                 ip->client->
2076                                                 config->defaults[i].len);
2077                                         memcpy(dp + ip->client->
2078                                                 config->defaults[i].len,
2079                                                 lease->options[i].data,
2080                                                 lease->options[i].len);
2081                                         dp[len] = '\0';
2082                                         break;
2083                                 case ACTION_APPEND:
2084                                         /*
2085                                          * When we append, we assume that we're
2086                                          * appending to text.  Some MS servers
2087                                          * include a NUL byte at the end of
2088                                          * the search string provided.
2089                                          */
2090                                         len = ip->client->
2091                                             config->defaults[i].len +
2092                                             lease->options[i].len;
2093                                         if (len >= sizeof(dbuf)) {
2094                                                 warning("no space to %s %s",
2095                                                     "append option",
2096                                                     dhcp_options[i].name);
2097                                                 goto supersede;
2098                                         }
2099                                         memcpy(dbuf,
2100                                                 lease->options[i].data,
2101                                                 lease->options[i].len);
2102                                         for (dp = dbuf + lease->options[i].len;
2103                                             dp > dbuf; dp--, len--)
2104                                                 if (dp[-1] != '\0')
2105                                                         break;
2106                                         memcpy(dp,
2107                                                 ip->client->
2108                                                 config->defaults[i].data,
2109                                                 ip->client->
2110                                                 config->defaults[i].len);
2111                                         dp = dbuf;
2112                                         dp[len] = '\0';
2113                                 }
2114                         } else {
2115                                 dp = ip->client->
2116                                         config->defaults[i].data;
2117                                 len = ip->client->
2118                                         config->defaults[i].len;
2119                         }
2120                 } else if (lease->options[i].len) {
2121                         len = lease->options[i].len;
2122                         dp = lease->options[i].data;
2123                 } else {
2124                         len = 0;
2125                 }
2126                 if (len) {
2127                         char name[256];
2128
2129                         if (dhcp_option_ev_name(name, sizeof(name),
2130                             &dhcp_options[i]))
2131                                 script_set_env(ip->client, prefix, name,
2132                                     pretty_print_option(i, dp, len, 0, 0));
2133                 }
2134         }
2135         snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2136         script_set_env(ip->client, prefix, "expiry", tbuf);
2137 }
2138
2139 void
2140 script_write_params(char *prefix, struct client_lease *lease)
2141 {
2142         size_t           fn_len = 0, sn_len = 0, pr_len = 0;
2143         struct imsg_hdr  hdr;
2144         struct buf      *buf;
2145         int              errs, i;
2146
2147         if (lease->filename != NULL)
2148                 fn_len = strlen(lease->filename);
2149         if (lease->server_name != NULL)
2150                 sn_len = strlen(lease->server_name);
2151         if (prefix != NULL)
2152                 pr_len = strlen(prefix);
2153
2154         hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2155         hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2156             sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2157             sizeof(size_t) + pr_len;
2158
2159         for (i = 0; i < 256; i++)
2160                 hdr.len += sizeof(int) + lease->options[i].len;
2161
2162         scripttime = time(NULL);
2163
2164         if ((buf = buf_open(hdr.len)) == NULL)
2165                 error("buf_open: %m");
2166
2167         errs = 0;
2168         errs += buf_add(buf, &hdr, sizeof(hdr));
2169         errs += buf_add(buf, lease, sizeof(struct client_lease));
2170         errs += buf_add(buf, &fn_len, sizeof(fn_len));
2171         errs += buf_add(buf, lease->filename, fn_len);
2172         errs += buf_add(buf, &sn_len, sizeof(sn_len));
2173         errs += buf_add(buf, lease->server_name, sn_len);
2174         errs += buf_add(buf, &pr_len, sizeof(pr_len));
2175         errs += buf_add(buf, prefix, pr_len);
2176
2177         for (i = 0; i < 256; i++) {
2178                 errs += buf_add(buf, &lease->options[i].len,
2179                     sizeof(lease->options[i].len));
2180                 errs += buf_add(buf, lease->options[i].data,
2181                     lease->options[i].len);
2182         }
2183
2184         if (errs)
2185                 error("buf_add: %m");
2186
2187         if (buf_close(privfd, buf) == -1)
2188                 error("buf_close: %m");
2189 }
2190
2191 int
2192 script_go(void)
2193 {
2194         struct imsg_hdr  hdr;
2195         struct buf      *buf;
2196         int              ret;
2197
2198         hdr.code = IMSG_SCRIPT_GO;
2199         hdr.len = sizeof(struct imsg_hdr);
2200
2201         if ((buf = buf_open(hdr.len)) == NULL)
2202                 error("buf_open: %m");
2203
2204         if (buf_add(buf, &hdr, sizeof(hdr)))
2205                 error("buf_add: %m");
2206
2207         if (buf_close(privfd, buf) == -1)
2208                 error("buf_close: %m");
2209
2210         bzero(&hdr, sizeof(hdr));
2211         buf_read(privfd, &hdr, sizeof(hdr));
2212         if (hdr.code != IMSG_SCRIPT_GO_RET)
2213                 error("unexpected msg type %u", hdr.code);
2214         if (hdr.len != sizeof(hdr) + sizeof(int))
2215                 error("received corrupted message");
2216         buf_read(privfd, &ret, sizeof(ret));
2217
2218         scripttime = time(NULL);
2219
2220         return (ret);
2221 }
2222
2223 int
2224 priv_script_go(void)
2225 {
2226         char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2227         static char client_path[] = CLIENT_PATH;
2228         struct interface_info *ip = ifi;
2229         int pid, wpid, wstatus;
2230
2231         scripttime = time(NULL);
2232
2233         if (ip) {
2234                 scriptName = ip->client->config->script_name;
2235                 envp = ip->client->scriptEnv;
2236         } else {
2237                 scriptName = top_level_config.script_name;
2238                 epp[0] = reason;
2239                 epp[1] = client_path;
2240                 epp[2] = NULL;
2241                 envp = epp;
2242         }
2243
2244         argv[0] = scriptName;
2245         argv[1] = NULL;
2246
2247         pid = fork();
2248         if (pid < 0) {
2249                 error("fork: %m");
2250                 wstatus = 0;
2251         } else if (pid) {
2252                 do {
2253                         wpid = wait(&wstatus);
2254                 } while (wpid != pid && wpid > 0);
2255                 if (wpid < 0) {
2256                         error("wait: %m");
2257                         wstatus = 0;
2258                 }
2259         } else {
2260                 execve(scriptName, argv, envp);
2261                 error("execve (%s, ...): %m", scriptName);
2262         }
2263
2264         if (ip)
2265                 script_flush_env(ip->client);
2266
2267         return (wstatus & 0xff);
2268 }
2269
2270 void
2271 script_set_env(struct client_state *client, const char *prefix,
2272     const char *name, const char *value)
2273 {
2274         int i, j, namelen;
2275
2276         namelen = strlen(name);
2277
2278         for (i = 0; client->scriptEnv[i]; i++)
2279                 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2280                     client->scriptEnv[i][namelen] == '=')
2281                         break;
2282
2283         if (client->scriptEnv[i])
2284                 /* Reuse the slot. */
2285                 free(client->scriptEnv[i]);
2286         else {
2287                 /* New variable.  Expand if necessary. */
2288                 if (i >= client->scriptEnvsize - 1) {
2289                         char **newscriptEnv;
2290                         int newscriptEnvsize = client->scriptEnvsize + 50;
2291
2292                         newscriptEnv = realloc(client->scriptEnv,
2293                             newscriptEnvsize);
2294                         if (newscriptEnv == NULL) {
2295                                 free(client->scriptEnv);
2296                                 client->scriptEnv = NULL;
2297                                 client->scriptEnvsize = 0;
2298                                 error("script_set_env: no memory for variable");
2299                         }
2300                         client->scriptEnv = newscriptEnv;
2301                         client->scriptEnvsize = newscriptEnvsize;
2302                 }
2303                 /* need to set the NULL pointer at end of array beyond
2304                    the new slot. */
2305                 client->scriptEnv[i + 1] = NULL;
2306         }
2307         /* Allocate space and format the variable in the appropriate slot. */
2308         client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2309             strlen(value) + 1);
2310         if (client->scriptEnv[i] == NULL)
2311                 error("script_set_env: no memory for variable assignment");
2312
2313         /* No `` or $() command substitution allowed in environment values! */
2314         for (j=0; j < strlen(value); j++)
2315                 switch (value[j]) {
2316                 case '`':
2317                 case '$':
2318                         error("illegal character (%c) in value '%s'", value[j],
2319                             value);
2320                         /* not reached */
2321                 }
2322         snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2323             1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2324 }
2325
2326 void
2327 script_flush_env(struct client_state *client)
2328 {
2329         int i;
2330
2331         for (i = 0; client->scriptEnv[i]; i++) {
2332                 free(client->scriptEnv[i]);
2333                 client->scriptEnv[i] = NULL;
2334         }
2335         client->scriptEnvsize = 0;
2336 }
2337
2338 int
2339 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2340 {
2341         int i;
2342
2343         for (i = 0; option->name[i]; i++) {
2344                 if (i + 1 == buflen)
2345                         return 0;
2346                 if (option->name[i] == '-')
2347                         buf[i] = '_';
2348                 else
2349                         buf[i] = option->name[i];
2350         }
2351
2352         buf[i] = 0;
2353         return 1;
2354 }
2355
2356 void
2357 go_daemon(void)
2358 {
2359         static int state = 0;
2360         cap_rights_t rights;
2361
2362         if (no_daemon || state)
2363                 return;
2364
2365         state = 1;
2366
2367         /* Stop logging to stderr... */
2368         log_perror = 0;
2369
2370         if (daemon(1, 0) == -1)
2371                 error("daemon");
2372
2373         cap_rights_init(&rights);
2374
2375         if (pidfile != NULL) {
2376                 pidfile_write(pidfile);
2377                 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2378                     errno != ENOSYS) {
2379                         error("can't limit pidfile descriptor: %m");
2380                 }
2381         }
2382
2383         /* we are chrooted, daemon(3) fails to open /dev/null */
2384         if (nullfd != -1) {
2385                 dup2(nullfd, STDIN_FILENO);
2386                 dup2(nullfd, STDOUT_FILENO);
2387                 dup2(nullfd, STDERR_FILENO);
2388                 close(nullfd);
2389                 nullfd = -1;
2390         }
2391
2392         if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2393                 error("can't limit stdin: %m");
2394         cap_rights_init(&rights, CAP_WRITE);
2395         if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2396                 error("can't limit stdout: %m");
2397         if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2398                 error("can't limit stderr: %m");
2399 }
2400
2401 int
2402 check_option(struct client_lease *l, int option)
2403 {
2404         char *opbuf;
2405         char *sbuf;
2406
2407         /* we use this, since this is what gets passed to dhclient-script */
2408
2409         opbuf = pretty_print_option(option, l->options[option].data,
2410             l->options[option].len, 0, 0);
2411
2412         sbuf = option_as_string(option, l->options[option].data,
2413             l->options[option].len);
2414
2415         switch (option) {
2416         case DHO_SUBNET_MASK:
2417         case DHO_TIME_SERVERS:
2418         case DHO_NAME_SERVERS:
2419         case DHO_ROUTERS:
2420         case DHO_DOMAIN_NAME_SERVERS:
2421         case DHO_LOG_SERVERS:
2422         case DHO_COOKIE_SERVERS:
2423         case DHO_LPR_SERVERS:
2424         case DHO_IMPRESS_SERVERS:
2425         case DHO_RESOURCE_LOCATION_SERVERS:
2426         case DHO_SWAP_SERVER:
2427         case DHO_BROADCAST_ADDRESS:
2428         case DHO_NIS_SERVERS:
2429         case DHO_NTP_SERVERS:
2430         case DHO_NETBIOS_NAME_SERVERS:
2431         case DHO_NETBIOS_DD_SERVER:
2432         case DHO_FONT_SERVERS:
2433         case DHO_DHCP_SERVER_IDENTIFIER:
2434         case DHO_NISPLUS_SERVERS:
2435         case DHO_MOBILE_IP_HOME_AGENT:
2436         case DHO_SMTP_SERVER:
2437         case DHO_POP_SERVER:
2438         case DHO_NNTP_SERVER:
2439         case DHO_WWW_SERVER:
2440         case DHO_FINGER_SERVER:
2441         case DHO_IRC_SERVER:
2442         case DHO_STREETTALK_SERVER:
2443         case DHO_STREETTALK_DA_SERVER:
2444                 if (!ipv4addrs(opbuf)) {
2445                         warning("Invalid IP address in option: %s", opbuf);
2446                         return (0);
2447                 }
2448                 return (1)  ;
2449         case DHO_HOST_NAME:
2450         case DHO_NIS_DOMAIN:
2451         case DHO_NISPLUS_DOMAIN:
2452         case DHO_TFTP_SERVER_NAME:
2453                 if (!res_hnok(sbuf)) {
2454                         warning("Bogus Host Name option %d: %s (%s)", option,
2455                             sbuf, opbuf);
2456                         l->options[option].len = 0;
2457                         free(l->options[option].data);
2458                 }
2459                 return (1);
2460         case DHO_DOMAIN_NAME:
2461         case DHO_DOMAIN_SEARCH:
2462                 if (!res_hnok(sbuf)) {
2463                         if (!check_search(sbuf)) {
2464                                 warning("Bogus domain search list %d: %s (%s)",
2465                                     option, sbuf, opbuf);
2466                                 l->options[option].len = 0;
2467                                 free(l->options[option].data);
2468                         }
2469                 }
2470                 return (1);
2471         case DHO_PAD:
2472         case DHO_TIME_OFFSET:
2473         case DHO_BOOT_SIZE:
2474         case DHO_MERIT_DUMP:
2475         case DHO_ROOT_PATH:
2476         case DHO_EXTENSIONS_PATH:
2477         case DHO_IP_FORWARDING:
2478         case DHO_NON_LOCAL_SOURCE_ROUTING:
2479         case DHO_POLICY_FILTER:
2480         case DHO_MAX_DGRAM_REASSEMBLY:
2481         case DHO_DEFAULT_IP_TTL:
2482         case DHO_PATH_MTU_AGING_TIMEOUT:
2483         case DHO_PATH_MTU_PLATEAU_TABLE:
2484         case DHO_INTERFACE_MTU:
2485         case DHO_ALL_SUBNETS_LOCAL:
2486         case DHO_PERFORM_MASK_DISCOVERY:
2487         case DHO_MASK_SUPPLIER:
2488         case DHO_ROUTER_DISCOVERY:
2489         case DHO_ROUTER_SOLICITATION_ADDRESS:
2490         case DHO_STATIC_ROUTES:
2491         case DHO_TRAILER_ENCAPSULATION:
2492         case DHO_ARP_CACHE_TIMEOUT:
2493         case DHO_IEEE802_3_ENCAPSULATION:
2494         case DHO_DEFAULT_TCP_TTL:
2495         case DHO_TCP_KEEPALIVE_INTERVAL:
2496         case DHO_TCP_KEEPALIVE_GARBAGE:
2497         case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2498         case DHO_NETBIOS_NODE_TYPE:
2499         case DHO_NETBIOS_SCOPE:
2500         case DHO_X_DISPLAY_MANAGER:
2501         case DHO_DHCP_REQUESTED_ADDRESS:
2502         case DHO_DHCP_LEASE_TIME:
2503         case DHO_DHCP_OPTION_OVERLOAD:
2504         case DHO_DHCP_MESSAGE_TYPE:
2505         case DHO_DHCP_PARAMETER_REQUEST_LIST:
2506         case DHO_DHCP_MESSAGE:
2507         case DHO_DHCP_MAX_MESSAGE_SIZE:
2508         case DHO_DHCP_RENEWAL_TIME:
2509         case DHO_DHCP_REBINDING_TIME:
2510         case DHO_DHCP_CLASS_IDENTIFIER:
2511         case DHO_DHCP_CLIENT_IDENTIFIER:
2512         case DHO_BOOTFILE_NAME:
2513         case DHO_DHCP_USER_CLASS_ID:
2514         case DHO_END:
2515                 return (1);
2516         case DHO_CLASSLESS_ROUTES:
2517                 return (check_classless_option(l->options[option].data,
2518                     l->options[option].len));
2519         default:
2520                 warning("unknown dhcp option value 0x%x", option);
2521                 return (unknown_ok);
2522         }
2523 }
2524
2525 /* RFC 3442 The Classless Static Routes option checks */
2526 int
2527 check_classless_option(unsigned char *data, int len)
2528 {
2529         int i = 0;
2530         unsigned char width;
2531         in_addr_t addr, mask;
2532
2533         if (len < 5) {
2534                 warning("Too small length: %d", len);
2535                 return (0);
2536         }
2537         while(i < len) {
2538                 width = data[i++];
2539                 if (width == 0) {
2540                         i += 4;
2541                         continue;
2542                 } else if (width < 9) {
2543                         addr =  (in_addr_t)(data[i]     << 24);
2544                         i += 1;
2545                 } else if (width < 17) {
2546                         addr =  (in_addr_t)(data[i]     << 24) +
2547                                 (in_addr_t)(data[i + 1] << 16);
2548                         i += 2;
2549                 } else if (width < 25) {
2550                         addr =  (in_addr_t)(data[i]     << 24) +
2551                                 (in_addr_t)(data[i + 1] << 16) +
2552                                 (in_addr_t)(data[i + 2] << 8);
2553                         i += 3;
2554                 } else if (width < 33) {
2555                         addr =  (in_addr_t)(data[i]     << 24) +
2556                                 (in_addr_t)(data[i + 1] << 16) +
2557                                 (in_addr_t)(data[i + 2] << 8)  +
2558                                 data[i + 3];
2559                         i += 4;
2560                 } else {
2561                         warning("Incorrect subnet width: %d", width);
2562                         return (0);
2563                 }
2564                 mask = (in_addr_t)(~0) << (32 - width);
2565                 addr = ntohl(addr);
2566                 mask = ntohl(mask);
2567
2568                 /*
2569                  * From RFC 3442:
2570                  * ... After deriving a subnet number and subnet mask
2571                  * from each destination descriptor, the DHCP client
2572                  * MUST zero any bits in the subnet number where the
2573                  * corresponding bit in the mask is zero...
2574                  */
2575                 if ((addr & mask) != addr) {
2576                         addr &= mask;
2577                         data[i - 1] = (unsigned char)(
2578                                 (addr >> (((32 - width)/8)*8)) & 0xFF);
2579                 }
2580                 i += 4;
2581         }
2582         if (i > len) {
2583                 warning("Incorrect data length: %d (must be %d)", len, i);
2584                 return (0);
2585         }
2586         return (1);
2587 }
2588
2589 int
2590 res_hnok(const char *dn)
2591 {
2592         int pch = PERIOD, ch = *dn++;
2593
2594         while (ch != '\0') {
2595                 int nch = *dn++;
2596
2597                 if (periodchar(ch)) {
2598                         ;
2599                 } else if (periodchar(pch)) {
2600                         if (!borderchar(ch))
2601                                 return (0);
2602                 } else if (periodchar(nch) || nch == '\0') {
2603                         if (!borderchar(ch))
2604                                 return (0);
2605                 } else {
2606                         if (!middlechar(ch))
2607                                 return (0);
2608                 }
2609                 pch = ch, ch = nch;
2610         }
2611         return (1);
2612 }
2613
2614 int
2615 check_search(const char *srch)
2616 {
2617         int pch = PERIOD, ch = *srch++;
2618         int domains = 1;
2619
2620         /* 256 char limit re resolv.conf(5) */
2621         if (strlen(srch) > 256)
2622                 return (0);
2623
2624         while (whitechar(ch))
2625                 ch = *srch++;
2626
2627         while (ch != '\0') {
2628                 int nch = *srch++;
2629
2630                 if (periodchar(ch) || whitechar(ch)) {
2631                         ;
2632                 } else if (periodchar(pch)) {
2633                         if (!borderchar(ch))
2634                                 return (0);
2635                 } else if (periodchar(nch) || nch == '\0') {
2636                         if (!borderchar(ch))
2637                                 return (0);
2638                 } else {
2639                         if (!middlechar(ch))
2640                                 return (0);
2641                 }
2642                 if (!whitechar(ch)) {
2643                         pch = ch;
2644                 } else {
2645                         while (whitechar(nch)) {
2646                                 nch = *srch++;
2647                         }
2648                         if (nch != '\0')
2649                                 domains++;
2650                         pch = PERIOD;
2651                 }
2652                 ch = nch;
2653         }
2654         /* 6 domain limit re resolv.conf(5) */
2655         if (domains > 6)
2656                 return (0);
2657         return (1);
2658 }
2659
2660 /* Does buf consist only of dotted decimal ipv4 addrs?
2661  * return how many if so,
2662  * otherwise, return 0
2663  */
2664 int
2665 ipv4addrs(char * buf)
2666 {
2667         struct in_addr jnk;
2668         int count = 0;
2669
2670         while (inet_aton(buf, &jnk) == 1){
2671                 count++;
2672                 while (periodchar(*buf) || digitchar(*buf))
2673                         buf++;
2674                 if (*buf == '\0')
2675                         return (count);
2676                 while (*buf ==  ' ')
2677                         buf++;
2678         }
2679         return (0);
2680 }
2681
2682
2683 char *
2684 option_as_string(unsigned int code, unsigned char *data, int len)
2685 {
2686         static char optbuf[32768]; /* XXX */
2687         char *op = optbuf;
2688         int opleft = sizeof(optbuf);
2689         unsigned char *dp = data;
2690
2691         if (code > 255)
2692                 error("option_as_string: bad code %d", code);
2693
2694         for (; dp < data + len; dp++) {
2695                 if (!isascii(*dp) || !isprint(*dp)) {
2696                         if (dp + 1 != data + len || *dp != 0) {
2697                                 snprintf(op, opleft, "\\%03o", *dp);
2698                                 op += 4;
2699                                 opleft -= 4;
2700                         }
2701                 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2702                     *dp == '`' || *dp == '\\') {
2703                         *op++ = '\\';
2704                         *op++ = *dp;
2705                         opleft -= 2;
2706                 } else {
2707                         *op++ = *dp;
2708                         opleft--;
2709                 }
2710         }
2711         if (opleft < 1)
2712                 goto toobig;
2713         *op = 0;
2714         return optbuf;
2715 toobig:
2716         warning("dhcp option too large");
2717         return "<error>";
2718 }
2719
2720 int
2721 fork_privchld(int fd, int fd2)
2722 {
2723         struct pollfd pfd[1];
2724         int nfds;
2725
2726         switch (fork()) {
2727         case -1:
2728                 error("cannot fork");
2729         case 0:
2730                 break;
2731         default:
2732                 return (0);
2733         }
2734
2735         setproctitle("%s [priv]", ifi->name);
2736
2737         setsid();
2738         dup2(nullfd, STDIN_FILENO);
2739         dup2(nullfd, STDOUT_FILENO);
2740         dup2(nullfd, STDERR_FILENO);
2741         close(nullfd);
2742         close(fd2);
2743         close(ifi->rfdesc);
2744         ifi->rfdesc = -1;
2745
2746         for (;;) {
2747                 pfd[0].fd = fd;
2748                 pfd[0].events = POLLIN;
2749                 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2750                         if (errno != EINTR)
2751                                 error("poll error");
2752
2753                 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2754                         continue;
2755
2756                 dispatch_imsg(ifi, fd);
2757         }
2758 }