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