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