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