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