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