]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/dhclient/dhclient.c
camcontrol(8): Fix typo in a source code comment
[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 (caph_rights_limit(privfd, &rights) < 0)
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 (caph_rights_limit(routefd, &rights) < 0)
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                 u_int16_t old_mtu = 0;
867                 bool supersede = (ip->client->config->default_actions[DHO_INTERFACE_MTU] ==
868                         ACTION_SUPERSEDE);
869
870                 if (supersede)
871                         mtu = getUShort(ip->client->config->defaults[DHO_INTERFACE_MTU].data);
872                 else
873                         mtu = be16dec(opt->data);
874
875                 if (ip->client->active) {
876                         opt = &ip->client->active->options[DHO_INTERFACE_MTU];
877                         if (opt->len == sizeof(u_int16_t)) {
878                                 old_mtu = be16dec(opt->data);
879                         }
880                 }
881
882                 if (mtu < MIN_MTU) {
883                         /* Treat 0 like a user intentionally doesn't want to change MTU and,
884                          * therefore, warning is not needed */
885                         if (!supersede || mtu != 0)
886                                 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
887                 } else if (ip->client->state != S_RENEWING || mtu != old_mtu) {
888                         interface_set_mtu_unpriv(privfd, mtu);
889                 }
890         }
891
892         /* Write out the new lease. */
893         write_client_lease(ip, ip->client->new, 0);
894
895         /* Run the client script with the new parameters. */
896         script_init((ip->client->state == S_REQUESTING ? "BOUND" :
897             (ip->client->state == S_RENEWING ? "RENEW" :
898             (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
899             ip->client->new->medium);
900         if (ip->client->active && ip->client->state != S_REBOOTING)
901                 script_write_params("old_", ip->client->active);
902         script_write_params("new_", ip->client->new);
903         if (ip->client->alias)
904                 script_write_params("alias_", ip->client->alias);
905         script_go();
906
907         /* Replace the old active lease with the new one. */
908         if (ip->client->active)
909                 free_client_lease(ip->client->active);
910         ip->client->active = ip->client->new;
911         ip->client->new = NULL;
912
913         /* Set up a timeout to start the renewal process. */
914         add_timeout(ip->client->active->renewal, state_bound, ip);
915
916         note("bound to %s -- renewal in %d seconds.",
917             piaddr(ip->client->active->address),
918             (int)(ip->client->active->renewal - cur_time));
919         ip->client->state = S_BOUND;
920         reinitialize_interfaces();
921         go_daemon();
922 }
923
924 /*
925  * state_bound is called when we've successfully bound to a particular
926  * lease, but the renewal time on that lease has expired.   We are
927  * expected to unicast a DHCPREQUEST to the server that gave us our
928  * original lease.
929  */
930 void
931 state_bound(void *ipp)
932 {
933         struct interface_info *ip = ipp;
934         u_int8_t *dp = NULL;
935         int len;
936
937         ASSERT_STATE(state, S_BOUND);
938
939         /* T1 has expired. */
940         make_request(ip, ip->client->active);
941         ip->client->xid = ip->client->packet.xid;
942
943         if (ip->client->config->default_actions[DHO_DHCP_SERVER_IDENTIFIER] ==
944             ACTION_SUPERSEDE) {
945                 dp = ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].data;
946                 len = ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].len;
947         } else {
948                 dp = ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].data;
949                 len = ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len;
950         }
951         if (len == 4) {
952                 memcpy(ip->client->destination.iabuf, dp, len);
953                 ip->client->destination.len = len;
954         } else
955                 ip->client->destination = iaddr_broadcast;
956
957         ip->client->first_sending = cur_time;
958         ip->client->interval = ip->client->config->initial_interval;
959         ip->client->state = S_RENEWING;
960
961         /* Send the first packet immediately. */
962         send_request(ip);
963 }
964
965 void
966 bootp(struct packet *packet)
967 {
968         struct iaddrlist *ap;
969
970         if (packet->raw->op != BOOTREPLY)
971                 return;
972
973         /* If there's a reject list, make sure this packet's sender isn't
974            on it. */
975         for (ap = packet->interface->client->config->reject_list;
976             ap; ap = ap->next) {
977                 if (addr_eq(packet->client_addr, ap->addr)) {
978                         note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
979                         return;
980                 }
981         }
982         dhcpoffer(packet);
983 }
984
985 void
986 dhcp(struct packet *packet)
987 {
988         struct iaddrlist *ap;
989         void (*handler)(struct packet *);
990         const char *type;
991
992         switch (packet->packet_type) {
993         case DHCPOFFER:
994                 handler = dhcpoffer;
995                 type = "DHCPOFFER";
996                 break;
997         case DHCPNAK:
998                 handler = dhcpnak;
999                 type = "DHCPNACK";
1000                 break;
1001         case DHCPACK:
1002                 handler = dhcpack;
1003                 type = "DHCPACK";
1004                 break;
1005         default:
1006                 return;
1007         }
1008
1009         /* If there's a reject list, make sure this packet's sender isn't
1010            on it. */
1011         for (ap = packet->interface->client->config->reject_list;
1012             ap; ap = ap->next) {
1013                 if (addr_eq(packet->client_addr, ap->addr)) {
1014                         note("%s from %s rejected.", type, piaddr(ap->addr));
1015                         return;
1016                 }
1017         }
1018         (*handler)(packet);
1019 }
1020
1021 void
1022 dhcpoffer(struct packet *packet)
1023 {
1024         struct interface_info *ip = packet->interface;
1025         struct client_lease *lease, *lp;
1026         int i;
1027         int arp_timeout_needed, stop_selecting;
1028         const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
1029             "DHCPOFFER" : "BOOTREPLY";
1030
1031         /* If we're not receptive to an offer right now, or if the offer
1032            has an unrecognizable transaction id, then just drop it. */
1033         if (ip->client->state != S_SELECTING ||
1034             packet->interface->client->xid != packet->raw->xid ||
1035             (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1036             (memcmp(packet->interface->hw_address.haddr,
1037             packet->raw->chaddr, packet->raw->hlen)))
1038                 return;
1039
1040         note("%s from %s", name, piaddr(packet->client_addr));
1041
1042
1043         /* If this lease doesn't supply the minimum required parameters,
1044            blow it off. */
1045         for (i = 0; ip->client->config->required_options[i]; i++) {
1046                 if (!packet->options[ip->client->config->
1047                     required_options[i]].len) {
1048                         note("%s isn't satisfactory.", name);
1049                         return;
1050                 }
1051         }
1052
1053         /* If we've already seen this lease, don't record it again. */
1054         for (lease = ip->client->offered_leases;
1055             lease; lease = lease->next) {
1056                 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1057                     !memcmp(lease->address.iabuf,
1058                     &packet->raw->yiaddr, lease->address.len)) {
1059                         debug("%s already seen.", name);
1060                         return;
1061                 }
1062         }
1063
1064         lease = packet_to_lease(packet);
1065         if (!lease) {
1066                 note("packet_to_lease failed.");
1067                 return;
1068         }
1069
1070         /* If this lease was acquired through a BOOTREPLY, record that
1071            fact. */
1072         if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1073                 lease->is_bootp = 1;
1074
1075         /* Record the medium under which this lease was offered. */
1076         lease->medium = ip->client->medium;
1077
1078         /* Send out an ARP Request for the offered IP address. */
1079         script_init("ARPSEND", lease->medium);
1080         script_write_params("check_", lease);
1081         /* If the script can't send an ARP request without waiting,
1082            we'll be waiting when we do the ARPCHECK, so don't wait now. */
1083         if (script_go())
1084                 arp_timeout_needed = 0;
1085         else
1086                 arp_timeout_needed = 2;
1087
1088         /* Figure out when we're supposed to stop selecting. */
1089         stop_selecting =
1090             ip->client->first_sending + ip->client->config->select_interval;
1091
1092         /* If this is the lease we asked for, put it at the head of the
1093            list, and don't mess with the arp request timeout. */
1094         if (lease->address.len == ip->client->requested_address.len &&
1095             !memcmp(lease->address.iabuf,
1096             ip->client->requested_address.iabuf,
1097             ip->client->requested_address.len)) {
1098                 lease->next = ip->client->offered_leases;
1099                 ip->client->offered_leases = lease;
1100         } else {
1101                 /* If we already have an offer, and arping for this
1102                    offer would take us past the selection timeout,
1103                    then don't extend the timeout - just hope for the
1104                    best. */
1105                 if (ip->client->offered_leases &&
1106                     (cur_time + arp_timeout_needed) > stop_selecting)
1107                         arp_timeout_needed = 0;
1108
1109                 /* Put the lease at the end of the list. */
1110                 lease->next = NULL;
1111                 if (!ip->client->offered_leases)
1112                         ip->client->offered_leases = lease;
1113                 else {
1114                         for (lp = ip->client->offered_leases; lp->next;
1115                             lp = lp->next)
1116                                 ;       /* nothing */
1117                         lp->next = lease;
1118                 }
1119         }
1120
1121         /* If we're supposed to stop selecting before we've had time
1122            to wait for the ARPREPLY, add some delay to wait for
1123            the ARPREPLY. */
1124         if (stop_selecting - cur_time < arp_timeout_needed)
1125                 stop_selecting = cur_time + arp_timeout_needed;
1126
1127         /* If the selecting interval has expired, go immediately to
1128            state_selecting().  Otherwise, time out into
1129            state_selecting at the select interval. */
1130         if (stop_selecting <= 0)
1131                 state_selecting(ip);
1132         else {
1133                 add_timeout(stop_selecting, state_selecting, ip);
1134                 cancel_timeout(send_discover, ip);
1135         }
1136 }
1137
1138 /* Allocate a client_lease structure and initialize it from the parameters
1139    in the specified packet. */
1140
1141 struct client_lease *
1142 packet_to_lease(struct packet *packet)
1143 {
1144         struct client_lease *lease;
1145         int i;
1146
1147         lease = malloc(sizeof(struct client_lease));
1148
1149         if (!lease) {
1150                 warning("dhcpoffer: no memory to record lease.");
1151                 return (NULL);
1152         }
1153
1154         memset(lease, 0, sizeof(*lease));
1155
1156         /* Copy the lease options. */
1157         for (i = 0; i < 256; i++) {
1158                 if (packet->options[i].len) {
1159                         lease->options[i].data =
1160                             malloc(packet->options[i].len + 1);
1161                         if (!lease->options[i].data) {
1162                                 warning("dhcpoffer: no memory for option %d", i);
1163                                 free_client_lease(lease);
1164                                 return (NULL);
1165                         } else {
1166                                 memcpy(lease->options[i].data,
1167                                     packet->options[i].data,
1168                                     packet->options[i].len);
1169                                 lease->options[i].len =
1170                                     packet->options[i].len;
1171                                 lease->options[i].data[lease->options[i].len] =
1172                                     0;
1173                         }
1174                         if (!check_option(lease,i)) {
1175                                 /* ignore a bogus lease offer */
1176                                 warning("Invalid lease option - ignoring offer");
1177                                 free_client_lease(lease);
1178                                 return (NULL);
1179                         }
1180                 }
1181         }
1182
1183         lease->address.len = sizeof(packet->raw->yiaddr);
1184         memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1185
1186         lease->nextserver.len = sizeof(packet->raw->siaddr);
1187         memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1188
1189         /* If the server name was filled out, copy it.
1190            Do not attempt to validate the server name as a host name.
1191            RFC 2131 merely states that sname is NUL-terminated (which do
1192            do not assume) and that it is the server's host name.  Since
1193            the ISC client and server allow arbitrary characters, we do
1194            as well. */
1195         if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1196             !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1197             packet->raw->sname[0]) {
1198                 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1199                 if (!lease->server_name) {
1200                         warning("dhcpoffer: no memory for server name.");
1201                         free_client_lease(lease);
1202                         return (NULL);
1203                 }
1204                 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1205                 lease->server_name[DHCP_SNAME_LEN]='\0';
1206         }
1207
1208         /* Ditto for the filename. */
1209         if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1210             !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1211             packet->raw->file[0]) {
1212                 /* Don't count on the NUL terminator. */
1213                 lease->filename = malloc(DHCP_FILE_LEN + 1);
1214                 if (!lease->filename) {
1215                         warning("dhcpoffer: no memory for filename.");
1216                         free_client_lease(lease);
1217                         return (NULL);
1218                 }
1219                 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1220                 lease->filename[DHCP_FILE_LEN]='\0';
1221         }
1222         return lease;
1223 }
1224
1225 void
1226 dhcpnak(struct packet *packet)
1227 {
1228         struct interface_info *ip = packet->interface;
1229
1230         /* If we're not receptive to an offer right now, or if the offer
1231            has an unrecognizable transaction id, then just drop it. */
1232         if (packet->interface->client->xid != packet->raw->xid ||
1233             (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1234             (memcmp(packet->interface->hw_address.haddr,
1235             packet->raw->chaddr, packet->raw->hlen)))
1236                 return;
1237
1238         if (ip->client->state != S_REBOOTING &&
1239             ip->client->state != S_REQUESTING &&
1240             ip->client->state != S_RENEWING &&
1241             ip->client->state != S_REBINDING)
1242                 return;
1243
1244         note("DHCPNAK from %s", piaddr(packet->client_addr));
1245
1246         if (!ip->client->active) {
1247                 note("DHCPNAK with no active lease.\n");
1248                 return;
1249         }
1250
1251         free_client_lease(ip->client->active);
1252         ip->client->active = NULL;
1253
1254         /* Stop sending DHCPREQUEST packets... */
1255         cancel_timeout(send_request, ip);
1256
1257         ip->client->state = S_INIT;
1258         state_init(ip);
1259 }
1260
1261 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1262    one after the right interval has expired.  If we don't get an offer by
1263    the time we reach the panic interval, call the panic function. */
1264
1265 void
1266 send_discover(void *ipp)
1267 {
1268         struct interface_info *ip = ipp;
1269         int interval, increase = 1;
1270
1271         /* Figure out how long it's been since we started transmitting. */
1272         interval = cur_time - ip->client->first_sending;
1273
1274         /* If we're past the panic timeout, call the script and tell it
1275            we haven't found anything for this interface yet. */
1276         if (interval > ip->client->config->timeout) {
1277                 state_panic(ip);
1278                 return;
1279         }
1280
1281         /* If we're selecting media, try the whole list before doing
1282            the exponential backoff, but if we've already received an
1283            offer, stop looping, because we obviously have it right. */
1284         if (!ip->client->offered_leases &&
1285             ip->client->config->media) {
1286                 int fail = 0;
1287 again:
1288                 if (ip->client->medium) {
1289                         ip->client->medium = ip->client->medium->next;
1290                         increase = 0;
1291                 }
1292                 if (!ip->client->medium) {
1293                         if (fail)
1294                                 error("No valid media types for %s!", ip->name);
1295                         ip->client->medium = ip->client->config->media;
1296                         increase = 1;
1297                 }
1298
1299                 note("Trying medium \"%s\" %d", ip->client->medium->string,
1300                     increase);
1301                 script_init("MEDIUM", ip->client->medium);
1302                 if (script_go())
1303                         goto again;
1304         }
1305
1306         /*
1307          * If we're supposed to increase the interval, do so.  If it's
1308          * currently zero (i.e., we haven't sent any packets yet), set
1309          * it to one; otherwise, add to it a random number between zero
1310          * and two times itself.  On average, this means that it will
1311          * double with every transmission.
1312          */
1313         if (increase) {
1314                 if (!ip->client->interval)
1315                         ip->client->interval =
1316                             ip->client->config->initial_interval;
1317                 else {
1318                         ip->client->interval += (arc4random() >> 2) %
1319                             (2 * ip->client->interval);
1320                 }
1321
1322                 /* Don't backoff past cutoff. */
1323                 if (ip->client->interval >
1324                     ip->client->config->backoff_cutoff)
1325                         ip->client->interval =
1326                                 ((ip->client->config->backoff_cutoff / 2)
1327                                  + ((arc4random() >> 2) %
1328                                     ip->client->config->backoff_cutoff));
1329         } else if (!ip->client->interval)
1330                 ip->client->interval =
1331                         ip->client->config->initial_interval;
1332
1333         /* If the backoff would take us to the panic timeout, just use that
1334            as the interval. */
1335         if (cur_time + ip->client->interval >
1336             ip->client->first_sending + ip->client->config->timeout)
1337                 ip->client->interval =
1338                         (ip->client->first_sending +
1339                          ip->client->config->timeout) - cur_time + 1;
1340
1341         /* Record the number of seconds since we started sending. */
1342         if (interval < 65536)
1343                 ip->client->packet.secs = htons(interval);
1344         else
1345                 ip->client->packet.secs = htons(65535);
1346         ip->client->secs = ip->client->packet.secs;
1347
1348         note("DHCPDISCOVER on %s to %s port %d interval %d",
1349             ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1350             (int)ip->client->interval);
1351
1352         /* Send out a packet. */
1353         send_packet_unpriv(privfd, &ip->client->packet,
1354             ip->client->packet_length, inaddr_any, inaddr_broadcast);
1355
1356         add_timeout(cur_time + ip->client->interval, send_discover, ip);
1357 }
1358
1359 /*
1360  * state_panic gets called if we haven't received any offers in a preset
1361  * amount of time.   When this happens, we try to use existing leases
1362  * that haven't yet expired, and failing that, we call the client script
1363  * and hope it can do something.
1364  */
1365 void
1366 state_panic(void *ipp)
1367 {
1368         struct interface_info *ip = ipp;
1369         struct client_lease *loop = ip->client->active;
1370         struct client_lease *lp;
1371
1372         note("No DHCPOFFERS received.");
1373
1374         /* We may not have an active lease, but we may have some
1375            predefined leases that we can try. */
1376         if (!ip->client->active && ip->client->leases)
1377                 goto activate_next;
1378
1379         /* Run through the list of leases and see if one can be used. */
1380         while (ip->client->active) {
1381                 if (ip->client->active->expiry > cur_time) {
1382                         note("Trying recorded lease %s",
1383                             piaddr(ip->client->active->address));
1384                         /* Run the client script with the existing
1385                            parameters. */
1386                         script_init("TIMEOUT",
1387                             ip->client->active->medium);
1388                         script_write_params("new_", ip->client->active);
1389                         if (ip->client->alias)
1390                                 script_write_params("alias_",
1391                                     ip->client->alias);
1392
1393                         /* If the old lease is still good and doesn't
1394                            yet need renewal, go into BOUND state and
1395                            timeout at the renewal time. */
1396                         if (!script_go()) {
1397                                 if (cur_time <
1398                                     ip->client->active->renewal) {
1399                                         ip->client->state = S_BOUND;
1400                                         note("bound: renewal in %d seconds.",
1401                                             (int)(ip->client->active->renewal -
1402                                             cur_time));
1403                                         add_timeout(
1404                                             ip->client->active->renewal,
1405                                             state_bound, ip);
1406                                 } else {
1407                                         ip->client->state = S_BOUND;
1408                                         note("bound: immediate renewal.");
1409                                         state_bound(ip);
1410                                 }
1411                                 reinitialize_interfaces();
1412                                 go_daemon();
1413                                 return;
1414                         }
1415                 }
1416
1417                 /* If there are no other leases, give up. */
1418                 if (!ip->client->leases) {
1419                         ip->client->leases = ip->client->active;
1420                         ip->client->active = NULL;
1421                         break;
1422                 }
1423
1424 activate_next:
1425                 /* Otherwise, put the active lease at the end of the
1426                    lease list, and try another lease.. */
1427                 for (lp = ip->client->leases; lp->next; lp = lp->next)
1428                         ;
1429                 lp->next = ip->client->active;
1430                 if (lp->next)
1431                         lp->next->next = NULL;
1432                 ip->client->active = ip->client->leases;
1433                 ip->client->leases = ip->client->leases->next;
1434
1435                 /* If we already tried this lease, we've exhausted the
1436                    set of leases, so we might as well give up for
1437                    now. */
1438                 if (ip->client->active == loop)
1439                         break;
1440                 else if (!loop)
1441                         loop = ip->client->active;
1442         }
1443
1444         /* No leases were available, or what was available didn't work, so
1445            tell the shell script that we failed to allocate an address,
1446            and try again later. */
1447         note("No working leases in persistent database - sleeping.\n");
1448         script_init("FAIL", NULL);
1449         if (ip->client->alias)
1450                 script_write_params("alias_", ip->client->alias);
1451         script_go();
1452         ip->client->state = S_INIT;
1453         add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1454             ip);
1455         go_daemon();
1456 }
1457
1458 void
1459 send_request(void *ipp)
1460 {
1461         struct interface_info *ip = ipp;
1462         struct in_addr from, to;
1463         int interval;
1464
1465         /* Figure out how long it's been since we started transmitting. */
1466         interval = cur_time - ip->client->first_sending;
1467
1468         /* If we're in the INIT-REBOOT or REQUESTING state and we're
1469            past the reboot timeout, go to INIT and see if we can
1470            DISCOVER an address... */
1471         /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1472            means either that we're on a network with no DHCP server,
1473            or that our server is down.  In the latter case, assuming
1474            that there is a backup DHCP server, DHCPDISCOVER will get
1475            us a new address, but we could also have successfully
1476            reused our old address.  In the former case, we're hosed
1477            anyway.  This is not a win-prone situation. */
1478         if ((ip->client->state == S_REBOOTING ||
1479             ip->client->state == S_REQUESTING) &&
1480             interval > ip->client->config->reboot_timeout) {
1481 cancel:
1482                 ip->client->state = S_INIT;
1483                 cancel_timeout(send_request, ip);
1484                 state_init(ip);
1485                 return;
1486         }
1487
1488         /* If we're in the reboot state, make sure the media is set up
1489            correctly. */
1490         if (ip->client->state == S_REBOOTING &&
1491             !ip->client->medium &&
1492             ip->client->active->medium ) {
1493                 script_init("MEDIUM", ip->client->active->medium);
1494
1495                 /* If the medium we chose won't fly, go to INIT state. */
1496                 if (script_go())
1497                         goto cancel;
1498
1499                 /* Record the medium. */
1500                 ip->client->medium = ip->client->active->medium;
1501         }
1502
1503         /* If the lease has expired, relinquish the address and go back
1504            to the INIT state. */
1505         if (ip->client->state != S_REQUESTING &&
1506             cur_time > ip->client->active->expiry) {
1507                 /* Run the client script with the new parameters. */
1508                 script_init("EXPIRE", NULL);
1509                 script_write_params("old_", ip->client->active);
1510                 if (ip->client->alias)
1511                         script_write_params("alias_", ip->client->alias);
1512                 script_go();
1513
1514                 /* Now do a preinit on the interface so that we can
1515                    discover a new address. */
1516                 script_init("PREINIT", NULL);
1517                 if (ip->client->alias)
1518                         script_write_params("alias_", ip->client->alias);
1519                 script_go();
1520
1521                 ip->client->state = S_INIT;
1522                 state_init(ip);
1523                 return;
1524         }
1525
1526         /* Do the exponential backoff... */
1527         if (!ip->client->interval)
1528                 ip->client->interval = ip->client->config->initial_interval;
1529         else
1530                 ip->client->interval += ((arc4random() >> 2) %
1531                     (2 * ip->client->interval));
1532
1533         /* Don't backoff past cutoff. */
1534         if (ip->client->interval >
1535             ip->client->config->backoff_cutoff)
1536                 ip->client->interval =
1537                     ((ip->client->config->backoff_cutoff / 2) +
1538                     ((arc4random() >> 2) % ip->client->interval));
1539
1540         /* If the backoff would take us to the expiry time, just set the
1541            timeout to the expiry time. */
1542         if (ip->client->state != S_REQUESTING &&
1543             cur_time + ip->client->interval >
1544             ip->client->active->expiry)
1545                 ip->client->interval =
1546                     ip->client->active->expiry - cur_time + 1;
1547
1548         /* If the lease T2 time has elapsed, or if we're not yet bound,
1549            broadcast the DHCPREQUEST rather than unicasting. */
1550         if (ip->client->state == S_REQUESTING ||
1551             ip->client->state == S_REBOOTING ||
1552             cur_time > ip->client->active->rebind)
1553                 to.s_addr = INADDR_BROADCAST;
1554         else
1555                 memcpy(&to.s_addr, ip->client->destination.iabuf,
1556                     sizeof(to.s_addr));
1557
1558         if (ip->client->state != S_REQUESTING &&
1559             ip->client->state != S_REBOOTING)
1560                 memcpy(&from, ip->client->active->address.iabuf,
1561                     sizeof(from));
1562         else
1563                 from.s_addr = INADDR_ANY;
1564
1565         /* Record the number of seconds since we started sending. */
1566         if (ip->client->state == S_REQUESTING)
1567                 ip->client->packet.secs = ip->client->secs;
1568         else {
1569                 if (interval < 65536)
1570                         ip->client->packet.secs = htons(interval);
1571                 else
1572                         ip->client->packet.secs = htons(65535);
1573         }
1574
1575         note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1576             REMOTE_PORT);
1577
1578         /* Send out a packet. */
1579         send_packet_unpriv(privfd, &ip->client->packet,
1580             ip->client->packet_length, from, to);
1581
1582         add_timeout(cur_time + ip->client->interval, send_request, ip);
1583 }
1584
1585 void
1586 send_decline(void *ipp)
1587 {
1588         struct interface_info *ip = ipp;
1589
1590         note("DHCPDECLINE on %s to %s port %d", ip->name,
1591             inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1592
1593         /* Send out a packet. */
1594         send_packet_unpriv(privfd, &ip->client->packet,
1595             ip->client->packet_length, inaddr_any, inaddr_broadcast);
1596 }
1597
1598 void
1599 make_discover(struct interface_info *ip, struct client_lease *lease)
1600 {
1601         unsigned char discover = DHCPDISCOVER;
1602         struct tree_cache *options[256];
1603         struct tree_cache option_elements[256];
1604         int i;
1605
1606         memset(option_elements, 0, sizeof(option_elements));
1607         memset(options, 0, sizeof(options));
1608         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1609
1610         /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1611         i = DHO_DHCP_MESSAGE_TYPE;
1612         options[i] = &option_elements[i];
1613         options[i]->value = &discover;
1614         options[i]->len = sizeof(discover);
1615         options[i]->buf_size = sizeof(discover);
1616         options[i]->timeout = 0xFFFFFFFF;
1617
1618         /* Request the options we want */
1619         i  = DHO_DHCP_PARAMETER_REQUEST_LIST;
1620         options[i] = &option_elements[i];
1621         options[i]->value = ip->client->config->requested_options;
1622         options[i]->len = ip->client->config->requested_option_count;
1623         options[i]->buf_size =
1624                 ip->client->config->requested_option_count;
1625         options[i]->timeout = 0xFFFFFFFF;
1626
1627         /* If we had an address, try to get it again. */
1628         if (lease) {
1629                 ip->client->requested_address = lease->address;
1630                 i = DHO_DHCP_REQUESTED_ADDRESS;
1631                 options[i] = &option_elements[i];
1632                 options[i]->value = lease->address.iabuf;
1633                 options[i]->len = lease->address.len;
1634                 options[i]->buf_size = lease->address.len;
1635                 options[i]->timeout = 0xFFFFFFFF;
1636         } else
1637                 ip->client->requested_address.len = 0;
1638
1639         /* Send any options requested in the config file. */
1640         for (i = 0; i < 256; i++)
1641                 if (!options[i] &&
1642                     ip->client->config->send_options[i].data) {
1643                         options[i] = &option_elements[i];
1644                         options[i]->value =
1645                             ip->client->config->send_options[i].data;
1646                         options[i]->len =
1647                             ip->client->config->send_options[i].len;
1648                         options[i]->buf_size =
1649                             ip->client->config->send_options[i].len;
1650                         options[i]->timeout = 0xFFFFFFFF;
1651                 }
1652
1653         /* send host name if not set via config file. */
1654         if (!options[DHO_HOST_NAME]) {
1655                 if (hostname[0] != '\0') {
1656                         size_t len;
1657                         char* posDot = strchr(hostname, '.');
1658                         if (posDot != NULL)
1659                                 len = posDot - hostname;
1660                         else
1661                                 len = strlen(hostname);
1662                         options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1663                         options[DHO_HOST_NAME]->value = hostname;
1664                         options[DHO_HOST_NAME]->len = len;
1665                         options[DHO_HOST_NAME]->buf_size = len;
1666                         options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1667                 }
1668         }
1669
1670         /* set unique client identifier */
1671         char client_ident[sizeof(ip->hw_address.haddr) + 1];
1672         if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1673                 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1674                                 ip->hw_address.hlen : sizeof(client_ident)-1;
1675                 client_ident[0] = ip->hw_address.htype;
1676                 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1677                 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1678                 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1679                 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1680                 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1681                 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1682         }
1683
1684         /* Set up the option buffer... */
1685         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1686             options, 0, 0, 0, NULL, 0);
1687         if (ip->client->packet_length < BOOTP_MIN_LEN)
1688                 ip->client->packet_length = BOOTP_MIN_LEN;
1689
1690         ip->client->packet.op = BOOTREQUEST;
1691         ip->client->packet.htype = ip->hw_address.htype;
1692         ip->client->packet.hlen = ip->hw_address.hlen;
1693         ip->client->packet.hops = 0;
1694         ip->client->packet.xid = arc4random();
1695         ip->client->packet.secs = 0; /* filled in by send_discover. */
1696         ip->client->packet.flags = 0;
1697
1698         memset(&(ip->client->packet.ciaddr),
1699             0, sizeof(ip->client->packet.ciaddr));
1700         memset(&(ip->client->packet.yiaddr),
1701             0, sizeof(ip->client->packet.yiaddr));
1702         memset(&(ip->client->packet.siaddr),
1703             0, sizeof(ip->client->packet.siaddr));
1704         memset(&(ip->client->packet.giaddr),
1705             0, sizeof(ip->client->packet.giaddr));
1706         memcpy(ip->client->packet.chaddr,
1707             ip->hw_address.haddr, ip->hw_address.hlen);
1708 }
1709
1710
1711 void
1712 make_request(struct interface_info *ip, struct client_lease * lease)
1713 {
1714         unsigned char request = DHCPREQUEST;
1715         struct tree_cache *options[256];
1716         struct tree_cache option_elements[256];
1717         int i;
1718
1719         memset(options, 0, sizeof(options));
1720         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1721
1722         /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1723         i = DHO_DHCP_MESSAGE_TYPE;
1724         options[i] = &option_elements[i];
1725         options[i]->value = &request;
1726         options[i]->len = sizeof(request);
1727         options[i]->buf_size = sizeof(request);
1728         options[i]->timeout = 0xFFFFFFFF;
1729
1730         /* Request the options we want */
1731         i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1732         options[i] = &option_elements[i];
1733         options[i]->value = ip->client->config->requested_options;
1734         options[i]->len = ip->client->config->requested_option_count;
1735         options[i]->buf_size =
1736                 ip->client->config->requested_option_count;
1737         options[i]->timeout = 0xFFFFFFFF;
1738
1739         /* If we are requesting an address that hasn't yet been assigned
1740            to us, use the DHCP Requested Address option. */
1741         if (ip->client->state == S_REQUESTING) {
1742                 /* Send back the server identifier... */
1743                 i = DHO_DHCP_SERVER_IDENTIFIER;
1744                 options[i] = &option_elements[i];
1745                 options[i]->value = lease->options[i].data;
1746                 options[i]->len = lease->options[i].len;
1747                 options[i]->buf_size = lease->options[i].len;
1748                 options[i]->timeout = 0xFFFFFFFF;
1749         }
1750         if (ip->client->state == S_REQUESTING ||
1751             ip->client->state == S_REBOOTING) {
1752                 ip->client->requested_address = lease->address;
1753                 i = DHO_DHCP_REQUESTED_ADDRESS;
1754                 options[i] = &option_elements[i];
1755                 options[i]->value = lease->address.iabuf;
1756                 options[i]->len = lease->address.len;
1757                 options[i]->buf_size = lease->address.len;
1758                 options[i]->timeout = 0xFFFFFFFF;
1759         } else
1760                 ip->client->requested_address.len = 0;
1761
1762         /* Send any options requested in the config file. */
1763         for (i = 0; i < 256; i++)
1764                 if (!options[i] &&
1765                     ip->client->config->send_options[i].data) {
1766                         options[i] = &option_elements[i];
1767                         options[i]->value =
1768                             ip->client->config->send_options[i].data;
1769                         options[i]->len =
1770                             ip->client->config->send_options[i].len;
1771                         options[i]->buf_size =
1772                             ip->client->config->send_options[i].len;
1773                         options[i]->timeout = 0xFFFFFFFF;
1774                 }
1775
1776         /* send host name if not set via config file. */
1777         if (!options[DHO_HOST_NAME]) {
1778                 if (hostname[0] != '\0') {
1779                         size_t len;
1780                         char* posDot = strchr(hostname, '.');
1781                         if (posDot != NULL)
1782                                 len = posDot - hostname;
1783                         else
1784                                 len = strlen(hostname);
1785                         options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1786                         options[DHO_HOST_NAME]->value = hostname;
1787                         options[DHO_HOST_NAME]->len = len;
1788                         options[DHO_HOST_NAME]->buf_size = len;
1789                         options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1790                 }
1791         }
1792
1793         /* set unique client identifier */
1794         char client_ident[sizeof(ip->hw_address.haddr) + 1];
1795         if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1796                 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1797                                 ip->hw_address.hlen : sizeof(client_ident)-1;
1798                 client_ident[0] = ip->hw_address.htype;
1799                 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1800                 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1801                 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1802                 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1803                 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1804                 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1805         }
1806
1807         /* Set up the option buffer... */
1808         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1809             options, 0, 0, 0, NULL, 0);
1810         if (ip->client->packet_length < BOOTP_MIN_LEN)
1811                 ip->client->packet_length = BOOTP_MIN_LEN;
1812
1813         ip->client->packet.op = BOOTREQUEST;
1814         ip->client->packet.htype = ip->hw_address.htype;
1815         ip->client->packet.hlen = ip->hw_address.hlen;
1816         ip->client->packet.hops = 0;
1817         ip->client->packet.xid = ip->client->xid;
1818         ip->client->packet.secs = 0; /* Filled in by send_request. */
1819
1820         /* If we own the address we're requesting, put it in ciaddr;
1821            otherwise set ciaddr to zero. */
1822         if (ip->client->state == S_BOUND ||
1823             ip->client->state == S_RENEWING ||
1824             ip->client->state == S_REBINDING) {
1825                 memcpy(&ip->client->packet.ciaddr,
1826                     lease->address.iabuf, lease->address.len);
1827                 ip->client->packet.flags = 0;
1828         } else {
1829                 memset(&ip->client->packet.ciaddr, 0,
1830                     sizeof(ip->client->packet.ciaddr));
1831                 ip->client->packet.flags = 0;
1832         }
1833
1834         memset(&ip->client->packet.yiaddr, 0,
1835             sizeof(ip->client->packet.yiaddr));
1836         memset(&ip->client->packet.siaddr, 0,
1837             sizeof(ip->client->packet.siaddr));
1838         memset(&ip->client->packet.giaddr, 0,
1839             sizeof(ip->client->packet.giaddr));
1840         memcpy(ip->client->packet.chaddr,
1841             ip->hw_address.haddr, ip->hw_address.hlen);
1842 }
1843
1844 void
1845 make_decline(struct interface_info *ip, struct client_lease *lease)
1846 {
1847         struct tree_cache *options[256], message_type_tree;
1848         struct tree_cache requested_address_tree;
1849         struct tree_cache server_id_tree, client_id_tree;
1850         unsigned char decline = DHCPDECLINE;
1851         int i;
1852
1853         memset(options, 0, sizeof(options));
1854         memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1855
1856         /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1857         i = DHO_DHCP_MESSAGE_TYPE;
1858         options[i] = &message_type_tree;
1859         options[i]->value = &decline;
1860         options[i]->len = sizeof(decline);
1861         options[i]->buf_size = sizeof(decline);
1862         options[i]->timeout = 0xFFFFFFFF;
1863
1864         /* Send back the server identifier... */
1865         i = DHO_DHCP_SERVER_IDENTIFIER;
1866         options[i] = &server_id_tree;
1867         options[i]->value = lease->options[i].data;
1868         options[i]->len = lease->options[i].len;
1869         options[i]->buf_size = lease->options[i].len;
1870         options[i]->timeout = 0xFFFFFFFF;
1871
1872         /* Send back the address we're declining. */
1873         i = DHO_DHCP_REQUESTED_ADDRESS;
1874         options[i] = &requested_address_tree;
1875         options[i]->value = lease->address.iabuf;
1876         options[i]->len = lease->address.len;
1877         options[i]->buf_size = lease->address.len;
1878         options[i]->timeout = 0xFFFFFFFF;
1879
1880         /* Send the uid if the user supplied one. */
1881         i = DHO_DHCP_CLIENT_IDENTIFIER;
1882         if (ip->client->config->send_options[i].len) {
1883                 options[i] = &client_id_tree;
1884                 options[i]->value = ip->client->config->send_options[i].data;
1885                 options[i]->len = ip->client->config->send_options[i].len;
1886                 options[i]->buf_size = ip->client->config->send_options[i].len;
1887                 options[i]->timeout = 0xFFFFFFFF;
1888         }
1889
1890
1891         /* Set up the option buffer... */
1892         ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1893             options, 0, 0, 0, NULL, 0);
1894         if (ip->client->packet_length < BOOTP_MIN_LEN)
1895                 ip->client->packet_length = BOOTP_MIN_LEN;
1896
1897         ip->client->packet.op = BOOTREQUEST;
1898         ip->client->packet.htype = ip->hw_address.htype;
1899         ip->client->packet.hlen = ip->hw_address.hlen;
1900         ip->client->packet.hops = 0;
1901         ip->client->packet.xid = ip->client->xid;
1902         ip->client->packet.secs = 0; /* Filled in by send_request. */
1903         ip->client->packet.flags = 0;
1904
1905         /* ciaddr must always be zero. */
1906         memset(&ip->client->packet.ciaddr, 0,
1907             sizeof(ip->client->packet.ciaddr));
1908         memset(&ip->client->packet.yiaddr, 0,
1909             sizeof(ip->client->packet.yiaddr));
1910         memset(&ip->client->packet.siaddr, 0,
1911             sizeof(ip->client->packet.siaddr));
1912         memset(&ip->client->packet.giaddr, 0,
1913             sizeof(ip->client->packet.giaddr));
1914         memcpy(ip->client->packet.chaddr,
1915             ip->hw_address.haddr, ip->hw_address.hlen);
1916 }
1917
1918 void
1919 free_client_lease(struct client_lease *lease)
1920 {
1921         int i;
1922
1923         if (lease->server_name)
1924                 free(lease->server_name);
1925         if (lease->filename)
1926                 free(lease->filename);
1927         for (i = 0; i < 256; i++) {
1928                 if (lease->options[i].len)
1929                         free(lease->options[i].data);
1930         }
1931         free(lease);
1932 }
1933
1934 static FILE *leaseFile;
1935
1936 void
1937 rewrite_client_leases(void)
1938 {
1939         struct client_lease *lp;
1940         cap_rights_t rights;
1941
1942         if (!leaseFile) {
1943                 leaseFile = fopen(path_dhclient_db, "w");
1944                 if (!leaseFile)
1945                         error("can't create %s: %m", path_dhclient_db);
1946                 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1947                     CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1948                 if (caph_rights_limit(fileno(leaseFile), &rights) < 0) {
1949                         error("can't limit lease descriptor: %m");
1950                 }
1951                 if (caph_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0) {
1952                         error("can't limit lease descriptor fcntls: %m");
1953                 }
1954         } else {
1955                 fflush(leaseFile);
1956                 rewind(leaseFile);
1957         }
1958
1959         for (lp = ifi->client->leases; lp; lp = lp->next)
1960                 write_client_lease(ifi, lp, 1);
1961         if (ifi->client->active)
1962                 write_client_lease(ifi, ifi->client->active, 1);
1963
1964         fflush(leaseFile);
1965         ftruncate(fileno(leaseFile), ftello(leaseFile));
1966         fsync(fileno(leaseFile));
1967 }
1968
1969 void
1970 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1971     int rewrite)
1972 {
1973         static int leases_written;
1974         struct tm *t;
1975         int i;
1976
1977         if (!rewrite) {
1978                 if (leases_written++ > 20) {
1979                         rewrite_client_leases();
1980                         leases_written = 0;
1981                 }
1982         }
1983
1984         /* If the lease came from the config file, we don't need to stash
1985            a copy in the lease database. */
1986         if (lease->is_static)
1987                 return;
1988
1989         if (!leaseFile) {       /* XXX */
1990                 leaseFile = fopen(path_dhclient_db, "w");
1991                 if (!leaseFile)
1992                         error("can't create %s: %m", path_dhclient_db);
1993         }
1994
1995         fprintf(leaseFile, "lease {\n");
1996         if (lease->is_bootp)
1997                 fprintf(leaseFile, "  bootp;\n");
1998         fprintf(leaseFile, "  interface \"%s\";\n", ip->name);
1999         fprintf(leaseFile, "  fixed-address %s;\n", piaddr(lease->address));
2000         if (lease->nextserver.len == sizeof(inaddr_any) &&
2001             0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
2002             sizeof(inaddr_any)))
2003                 fprintf(leaseFile, "  next-server %s;\n",
2004                     piaddr(lease->nextserver));
2005         if (lease->filename)
2006                 fprintf(leaseFile, "  filename \"%s\";\n", lease->filename);
2007         if (lease->server_name)
2008                 fprintf(leaseFile, "  server-name \"%s\";\n",
2009                     lease->server_name);
2010         if (lease->medium)
2011                 fprintf(leaseFile, "  medium \"%s\";\n", lease->medium->string);
2012         for (i = 0; i < 256; i++)
2013                 if (lease->options[i].len)
2014                         fprintf(leaseFile, "  option %s %s;\n",
2015                             dhcp_options[i].name,
2016                             pretty_print_option(i, lease->options[i].data,
2017                             lease->options[i].len, 1, 1));
2018
2019         t = gmtime(&lease->renewal);
2020         fprintf(leaseFile, "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
2021             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2022             t->tm_hour, t->tm_min, t->tm_sec);
2023         t = gmtime(&lease->rebind);
2024         fprintf(leaseFile, "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2025             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2026             t->tm_hour, t->tm_min, t->tm_sec);
2027         t = gmtime(&lease->expiry);
2028         fprintf(leaseFile, "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
2029             t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2030             t->tm_hour, t->tm_min, t->tm_sec);
2031         fprintf(leaseFile, "}\n");
2032         fflush(leaseFile);
2033 }
2034
2035 void
2036 script_init(const char *reason, struct string_list *medium)
2037 {
2038         size_t           len, mediumlen = 0;
2039         struct imsg_hdr  hdr;
2040         struct buf      *buf;
2041         int              errs;
2042
2043         if (medium != NULL && medium->string != NULL)
2044                 mediumlen = strlen(medium->string);
2045
2046         hdr.code = IMSG_SCRIPT_INIT;
2047         hdr.len = sizeof(struct imsg_hdr) +
2048             sizeof(size_t) + mediumlen +
2049             sizeof(size_t) + strlen(reason);
2050
2051         if ((buf = buf_open(hdr.len)) == NULL)
2052                 error("buf_open: %m");
2053
2054         errs = 0;
2055         errs += buf_add(buf, &hdr, sizeof(hdr));
2056         errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2057         if (mediumlen > 0)
2058                 errs += buf_add(buf, medium->string, mediumlen);
2059         len = strlen(reason);
2060         errs += buf_add(buf, &len, sizeof(len));
2061         errs += buf_add(buf, reason, len);
2062
2063         if (errs)
2064                 error("buf_add: %m");
2065
2066         if (buf_close(privfd, buf) == -1)
2067                 error("buf_close: %m");
2068 }
2069
2070 void
2071 priv_script_init(const char *reason, char *medium)
2072 {
2073         struct interface_info *ip = ifi;
2074
2075         if (ip) {
2076                 ip->client->scriptEnvsize = 100;
2077                 if (ip->client->scriptEnv == NULL)
2078                         ip->client->scriptEnv =
2079                             malloc(ip->client->scriptEnvsize * sizeof(char *));
2080                 if (ip->client->scriptEnv == NULL)
2081                         error("script_init: no memory for environment");
2082
2083                 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2084                 if (ip->client->scriptEnv[0] == NULL)
2085                         error("script_init: no memory for environment");
2086
2087                 ip->client->scriptEnv[1] = NULL;
2088
2089                 script_set_env(ip->client, "", "interface", ip->name);
2090
2091                 if (medium)
2092                         script_set_env(ip->client, "", "medium", medium);
2093
2094                 script_set_env(ip->client, "", "reason", reason);
2095         }
2096 }
2097
2098 void
2099 priv_script_write_params(const char *prefix, struct client_lease *lease)
2100 {
2101         struct interface_info *ip = ifi;
2102         u_int8_t dbuf[1500], *dp = NULL;
2103         int i;
2104         size_t len;
2105         char tbuf[128];
2106
2107         script_set_env(ip->client, prefix, "ip_address",
2108             piaddr(lease->address));
2109
2110         if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2111             ACTION_SUPERSEDE) {
2112                 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2113                 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2114         } else {
2115                 dp = lease->options[DHO_SUBNET_MASK].data;
2116                 len = lease->options[DHO_SUBNET_MASK].len;
2117         }
2118         if (len && (len < sizeof(lease->address.iabuf))) {
2119                 struct iaddr netmask, subnet, broadcast;
2120
2121                 memcpy(netmask.iabuf, dp, len);
2122                 netmask.len = len;
2123                 subnet = subnet_number(lease->address, netmask);
2124                 if (subnet.len) {
2125                         script_set_env(ip->client, prefix, "network_number",
2126                             piaddr(subnet));
2127                         if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2128                                 broadcast = broadcast_addr(subnet, netmask);
2129                                 if (broadcast.len)
2130                                         script_set_env(ip->client, prefix,
2131                                             "broadcast_address",
2132                                             piaddr(broadcast));
2133                         }
2134                 }
2135         }
2136
2137         if (lease->filename)
2138                 script_set_env(ip->client, prefix, "filename", lease->filename);
2139         if (lease->server_name)
2140                 script_set_env(ip->client, prefix, "server_name",
2141                     lease->server_name);
2142         for (i = 0; i < 256; i++) {
2143                 len = 0;
2144
2145                 if (ip->client->config->defaults[i].len) {
2146                         if (lease->options[i].len) {
2147                                 switch (
2148                                     ip->client->config->default_actions[i]) {
2149                                 case ACTION_DEFAULT:
2150                                         dp = lease->options[i].data;
2151                                         len = lease->options[i].len;
2152                                         break;
2153                                 case ACTION_SUPERSEDE:
2154 supersede:
2155                                         dp = ip->client->
2156                                                 config->defaults[i].data;
2157                                         len = ip->client->
2158                                                 config->defaults[i].len;
2159                                         break;
2160                                 case ACTION_PREPEND:
2161                                         len = ip->client->
2162                                             config->defaults[i].len +
2163                                             lease->options[i].len;
2164                                         if (len >= sizeof(dbuf)) {
2165                                                 warning("no space to %s %s",
2166                                                     "prepend option",
2167                                                     dhcp_options[i].name);
2168                                                 goto supersede;
2169                                         }
2170                                         dp = dbuf;
2171                                         memcpy(dp,
2172                                                 ip->client->
2173                                                 config->defaults[i].data,
2174                                                 ip->client->
2175                                                 config->defaults[i].len);
2176                                         memcpy(dp + ip->client->
2177                                                 config->defaults[i].len,
2178                                                 lease->options[i].data,
2179                                                 lease->options[i].len);
2180                                         dp[len] = '\0';
2181                                         break;
2182                                 case ACTION_APPEND:
2183                                         /*
2184                                          * When we append, we assume that we're
2185                                          * appending to text.  Some MS servers
2186                                          * include a NUL byte at the end of
2187                                          * the search string provided.
2188                                          */
2189                                         len = ip->client->
2190                                             config->defaults[i].len +
2191                                             lease->options[i].len;
2192                                         if (len >= sizeof(dbuf)) {
2193                                                 warning("no space to %s %s",
2194                                                     "append option",
2195                                                     dhcp_options[i].name);
2196                                                 goto supersede;
2197                                         }
2198                                         memcpy(dbuf,
2199                                                 lease->options[i].data,
2200                                                 lease->options[i].len);
2201                                         for (dp = dbuf + lease->options[i].len;
2202                                             dp > dbuf; dp--, len--)
2203                                                 if (dp[-1] != '\0')
2204                                                         break;
2205                                         memcpy(dp,
2206                                                 ip->client->
2207                                                 config->defaults[i].data,
2208                                                 ip->client->
2209                                                 config->defaults[i].len);
2210                                         dp = dbuf;
2211                                         dp[len] = '\0';
2212                                 }
2213                         } else {
2214                                 dp = ip->client->
2215                                         config->defaults[i].data;
2216                                 len = ip->client->
2217                                         config->defaults[i].len;
2218                         }
2219                 } else if (lease->options[i].len) {
2220                         len = lease->options[i].len;
2221                         dp = lease->options[i].data;
2222                 } else {
2223                         len = 0;
2224                 }
2225                 if (len) {
2226                         char name[256];
2227
2228                         if (dhcp_option_ev_name(name, sizeof(name),
2229                             &dhcp_options[i]))
2230                                 script_set_env(ip->client, prefix, name,
2231                                     pretty_print_option(i, dp, len, 0, 0));
2232                 }
2233         }
2234         snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2235         script_set_env(ip->client, prefix, "expiry", tbuf);
2236 }
2237
2238 void
2239 script_write_params(const char *prefix, struct client_lease *lease)
2240 {
2241         size_t           fn_len = 0, sn_len = 0, pr_len = 0;
2242         struct imsg_hdr  hdr;
2243         struct buf      *buf;
2244         int              errs, i;
2245
2246         if (lease->filename != NULL)
2247                 fn_len = strlen(lease->filename);
2248         if (lease->server_name != NULL)
2249                 sn_len = strlen(lease->server_name);
2250         if (prefix != NULL)
2251                 pr_len = strlen(prefix);
2252
2253         hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2254         hdr.len = sizeof(hdr) + sizeof(*lease) +
2255             sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2256             sizeof(pr_len) + pr_len;
2257
2258         for (i = 0; i < 256; i++) {
2259                 hdr.len += sizeof(lease->options[i].len);
2260                 hdr.len += lease->options[i].len;
2261         }
2262
2263         scripttime = time(NULL);
2264
2265         if ((buf = buf_open(hdr.len)) == NULL)
2266                 error("buf_open: %m");
2267
2268         errs = 0;
2269         errs += buf_add(buf, &hdr, sizeof(hdr));
2270         errs += buf_add(buf, lease, sizeof(*lease));
2271         errs += buf_add(buf, &fn_len, sizeof(fn_len));
2272         errs += buf_add(buf, lease->filename, fn_len);
2273         errs += buf_add(buf, &sn_len, sizeof(sn_len));
2274         errs += buf_add(buf, lease->server_name, sn_len);
2275         errs += buf_add(buf, &pr_len, sizeof(pr_len));
2276         errs += buf_add(buf, prefix, pr_len);
2277
2278         for (i = 0; i < 256; i++) {
2279                 errs += buf_add(buf, &lease->options[i].len,
2280                     sizeof(lease->options[i].len));
2281                 errs += buf_add(buf, lease->options[i].data,
2282                     lease->options[i].len);
2283         }
2284
2285         if (errs)
2286                 error("buf_add: %m");
2287
2288         if (buf_close(privfd, buf) == -1)
2289                 error("buf_close: %m");
2290 }
2291
2292 int
2293 script_go(void)
2294 {
2295         struct imsg_hdr  hdr;
2296         struct buf      *buf;
2297         int              ret;
2298
2299         hdr.code = IMSG_SCRIPT_GO;
2300         hdr.len = sizeof(struct imsg_hdr);
2301
2302         if ((buf = buf_open(hdr.len)) == NULL)
2303                 error("buf_open: %m");
2304
2305         if (buf_add(buf, &hdr, sizeof(hdr)))
2306                 error("buf_add: %m");
2307
2308         if (buf_close(privfd, buf) == -1)
2309                 error("buf_close: %m");
2310
2311         bzero(&hdr, sizeof(hdr));
2312         buf_read(privfd, &hdr, sizeof(hdr));
2313         if (hdr.code != IMSG_SCRIPT_GO_RET)
2314                 error("unexpected msg type %u", hdr.code);
2315         if (hdr.len != sizeof(hdr) + sizeof(int))
2316                 error("received corrupted message");
2317         buf_read(privfd, &ret, sizeof(ret));
2318
2319         scripttime = time(NULL);
2320
2321         return (ret);
2322 }
2323
2324 int
2325 priv_script_go(void)
2326 {
2327         char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2328         static char client_path[] = CLIENT_PATH;
2329         struct interface_info *ip = ifi;
2330         int pid, wpid, wstatus;
2331
2332         scripttime = time(NULL);
2333
2334         if (ip) {
2335                 scriptName = ip->client->config->script_name;
2336                 envp = ip->client->scriptEnv;
2337         } else {
2338                 scriptName = top_level_config.script_name;
2339                 epp[0] = reason;
2340                 epp[1] = client_path;
2341                 epp[2] = NULL;
2342                 envp = epp;
2343         }
2344
2345         argv[0] = scriptName;
2346         argv[1] = NULL;
2347
2348         pid = fork();
2349         if (pid < 0) {
2350                 error("fork: %m");
2351                 wstatus = 0;
2352         } else if (pid) {
2353                 do {
2354                         wpid = wait(&wstatus);
2355                 } while (wpid != pid && wpid > 0);
2356                 if (wpid < 0) {
2357                         error("wait: %m");
2358                         wstatus = 0;
2359                 }
2360         } else {
2361                 execve(scriptName, argv, envp);
2362                 error("execve (%s, ...): %m", scriptName);
2363         }
2364
2365         if (ip)
2366                 script_flush_env(ip->client);
2367
2368         return (WIFEXITED(wstatus) ?
2369             WEXITSTATUS(wstatus) : 128 + WTERMSIG(wstatus));
2370 }
2371
2372 void
2373 script_set_env(struct client_state *client, const char *prefix,
2374     const char *name, const char *value)
2375 {
2376         int i, namelen;
2377         size_t j;
2378
2379         /* No `` or $() command substitution allowed in environment values! */
2380         for (j=0; j < strlen(value); j++)
2381                 switch (value[j]) {
2382                 case '`':
2383                 case '$':
2384                         warning("illegal character (%c) in value '%s'",
2385                             value[j], value);
2386                         /* Ignore this option */
2387                         return;
2388                 }
2389
2390         namelen = strlen(name);
2391
2392         for (i = 0; client->scriptEnv[i]; i++)
2393                 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2394                     client->scriptEnv[i][namelen] == '=')
2395                         break;
2396
2397         if (client->scriptEnv[i])
2398                 /* Reuse the slot. */
2399                 free(client->scriptEnv[i]);
2400         else {
2401                 /* New variable.  Expand if necessary. */
2402                 if (i >= client->scriptEnvsize - 1) {
2403                         char **newscriptEnv;
2404                         int newscriptEnvsize = client->scriptEnvsize + 50;
2405
2406                         newscriptEnv = realloc(client->scriptEnv,
2407                             newscriptEnvsize);
2408                         if (newscriptEnv == NULL) {
2409                                 free(client->scriptEnv);
2410                                 client->scriptEnv = NULL;
2411                                 client->scriptEnvsize = 0;
2412                                 error("script_set_env: no memory for variable");
2413                         }
2414                         client->scriptEnv = newscriptEnv;
2415                         client->scriptEnvsize = newscriptEnvsize;
2416                 }
2417                 /* need to set the NULL pointer at end of array beyond
2418                    the new slot. */
2419                 client->scriptEnv[i + 1] = NULL;
2420         }
2421         /* Allocate space and format the variable in the appropriate slot. */
2422         client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2423             strlen(value) + 1);
2424         if (client->scriptEnv[i] == NULL)
2425                 error("script_set_env: no memory for variable assignment");
2426         snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2427             1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2428 }
2429
2430 void
2431 script_flush_env(struct client_state *client)
2432 {
2433         int i;
2434
2435         for (i = 0; client->scriptEnv[i]; i++) {
2436                 free(client->scriptEnv[i]);
2437                 client->scriptEnv[i] = NULL;
2438         }
2439         client->scriptEnvsize = 0;
2440 }
2441
2442 int
2443 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2444 {
2445         size_t i;
2446
2447         for (i = 0; option->name[i]; i++) {
2448                 if (i + 1 == buflen)
2449                         return 0;
2450                 if (option->name[i] == '-')
2451                         buf[i] = '_';
2452                 else
2453                         buf[i] = option->name[i];
2454         }
2455
2456         buf[i] = 0;
2457         return 1;
2458 }
2459
2460 void
2461 go_daemon(void)
2462 {
2463         static int state = 0;
2464         cap_rights_t rights;
2465
2466         if (no_daemon || state)
2467                 return;
2468
2469         state = 1;
2470
2471         /* Stop logging to stderr... */
2472         log_perror = 0;
2473
2474         if (daemonfd(-1, nullfd) == -1)
2475                 error("daemon");
2476
2477         cap_rights_init(&rights);
2478
2479         if (pidfile != NULL) {
2480                 pidfile_write(pidfile);
2481
2482                 if (caph_rights_limit(pidfile_fileno(pidfile), &rights) < 0)
2483                         error("can't limit pidfile descriptor: %m");
2484         }
2485
2486         if (nullfd != -1) {
2487                 close(nullfd);
2488                 nullfd = -1;
2489         }
2490
2491         if (caph_rights_limit(STDIN_FILENO, &rights) < 0)
2492                 error("can't limit stdin: %m");
2493         cap_rights_init(&rights, CAP_WRITE);
2494         if (caph_rights_limit(STDOUT_FILENO, &rights) < 0)
2495                 error("can't limit stdout: %m");
2496         if (caph_rights_limit(STDERR_FILENO, &rights) < 0)
2497                 error("can't limit stderr: %m");
2498 }
2499
2500 int
2501 check_option(struct client_lease *l, int option)
2502 {
2503         const char *opbuf;
2504         const char *sbuf;
2505
2506         /* we use this, since this is what gets passed to dhclient-script */
2507
2508         opbuf = pretty_print_option(option, l->options[option].data,
2509             l->options[option].len, 0, 0);
2510
2511         sbuf = option_as_string(option, l->options[option].data,
2512             l->options[option].len);
2513
2514         switch (option) {
2515         case DHO_SUBNET_MASK:
2516         case DHO_TIME_SERVERS:
2517         case DHO_NAME_SERVERS:
2518         case DHO_ROUTERS:
2519         case DHO_DOMAIN_NAME_SERVERS:
2520         case DHO_LOG_SERVERS:
2521         case DHO_COOKIE_SERVERS:
2522         case DHO_LPR_SERVERS:
2523         case DHO_IMPRESS_SERVERS:
2524         case DHO_RESOURCE_LOCATION_SERVERS:
2525         case DHO_SWAP_SERVER:
2526         case DHO_BROADCAST_ADDRESS:
2527         case DHO_NIS_SERVERS:
2528         case DHO_NTP_SERVERS:
2529         case DHO_NETBIOS_NAME_SERVERS:
2530         case DHO_NETBIOS_DD_SERVER:
2531         case DHO_FONT_SERVERS:
2532         case DHO_DHCP_SERVER_IDENTIFIER:
2533         case DHO_NISPLUS_SERVERS:
2534         case DHO_MOBILE_IP_HOME_AGENT:
2535         case DHO_SMTP_SERVER:
2536         case DHO_POP_SERVER:
2537         case DHO_NNTP_SERVER:
2538         case DHO_WWW_SERVER:
2539         case DHO_FINGER_SERVER:
2540         case DHO_IRC_SERVER:
2541         case DHO_STREETTALK_SERVER:
2542         case DHO_STREETTALK_DA_SERVER:
2543                 if (!ipv4addrs(opbuf)) {
2544                         warning("Invalid IP address in option: %s", opbuf);
2545                         return (0);
2546                 }
2547                 return (1)  ;
2548         case DHO_HOST_NAME:
2549         case DHO_NIS_DOMAIN:
2550         case DHO_NISPLUS_DOMAIN:
2551         case DHO_TFTP_SERVER_NAME:
2552                 if (!res_hnok(sbuf)) {
2553                         warning("Bogus Host Name option %d: %s (%s)", option,
2554                             sbuf, opbuf);
2555                         l->options[option].len = 0;
2556                         free(l->options[option].data);
2557                 }
2558                 return (1);
2559         case DHO_DOMAIN_NAME:
2560         case DHO_DOMAIN_SEARCH:
2561                 if (!res_hnok(sbuf)) {
2562                         if (!check_search(sbuf)) {
2563                                 warning("Bogus domain search list %d: %s (%s)",
2564                                     option, sbuf, opbuf);
2565                                 l->options[option].len = 0;
2566                                 free(l->options[option].data);
2567                         }
2568                 }
2569                 return (1);
2570         case DHO_PAD:
2571         case DHO_TIME_OFFSET:
2572         case DHO_BOOT_SIZE:
2573         case DHO_MERIT_DUMP:
2574         case DHO_ROOT_PATH:
2575         case DHO_EXTENSIONS_PATH:
2576         case DHO_IP_FORWARDING:
2577         case DHO_NON_LOCAL_SOURCE_ROUTING:
2578         case DHO_POLICY_FILTER:
2579         case DHO_MAX_DGRAM_REASSEMBLY:
2580         case DHO_DEFAULT_IP_TTL:
2581         case DHO_PATH_MTU_AGING_TIMEOUT:
2582         case DHO_PATH_MTU_PLATEAU_TABLE:
2583         case DHO_INTERFACE_MTU:
2584         case DHO_ALL_SUBNETS_LOCAL:
2585         case DHO_PERFORM_MASK_DISCOVERY:
2586         case DHO_MASK_SUPPLIER:
2587         case DHO_ROUTER_DISCOVERY:
2588         case DHO_ROUTER_SOLICITATION_ADDRESS:
2589         case DHO_STATIC_ROUTES:
2590         case DHO_TRAILER_ENCAPSULATION:
2591         case DHO_ARP_CACHE_TIMEOUT:
2592         case DHO_IEEE802_3_ENCAPSULATION:
2593         case DHO_DEFAULT_TCP_TTL:
2594         case DHO_TCP_KEEPALIVE_INTERVAL:
2595         case DHO_TCP_KEEPALIVE_GARBAGE:
2596         case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2597         case DHO_NETBIOS_NODE_TYPE:
2598         case DHO_NETBIOS_SCOPE:
2599         case DHO_X_DISPLAY_MANAGER:
2600         case DHO_DHCP_REQUESTED_ADDRESS:
2601         case DHO_DHCP_LEASE_TIME:
2602         case DHO_DHCP_OPTION_OVERLOAD:
2603         case DHO_DHCP_MESSAGE_TYPE:
2604         case DHO_DHCP_PARAMETER_REQUEST_LIST:
2605         case DHO_DHCP_MESSAGE:
2606         case DHO_DHCP_MAX_MESSAGE_SIZE:
2607         case DHO_DHCP_RENEWAL_TIME:
2608         case DHO_DHCP_REBINDING_TIME:
2609         case DHO_DHCP_CLASS_IDENTIFIER:
2610         case DHO_DHCP_CLIENT_IDENTIFIER:
2611         case DHO_BOOTFILE_NAME:
2612         case DHO_DHCP_USER_CLASS_ID:
2613         case DHO_URL:
2614         case DHO_END:
2615                 return (1);
2616         case DHO_CLASSLESS_ROUTES:
2617                 return (check_classless_option(l->options[option].data,
2618                     l->options[option].len));
2619         default:
2620                 warning("unknown dhcp option value 0x%x", option);
2621                 return (unknown_ok);
2622         }
2623 }
2624
2625 /* RFC 3442 The Classless Static Routes option checks */
2626 int
2627 check_classless_option(unsigned char *data, int len)
2628 {
2629         int i = 0;
2630         unsigned char width;
2631         in_addr_t addr, mask;
2632
2633         if (len < 5) {
2634                 warning("Too small length: %d", len);
2635                 return (0);
2636         }
2637         while(i < len) {
2638                 width = data[i++];
2639                 if (width == 0) {
2640                         i += 4;
2641                         continue;
2642                 } else if (width < 9) {
2643                         addr =  (in_addr_t)(data[i]     << 24);
2644                         i += 1;
2645                 } else if (width < 17) {
2646                         addr =  (in_addr_t)(data[i]     << 24) +
2647                                 (in_addr_t)(data[i + 1] << 16);
2648                         i += 2;
2649                 } else if (width < 25) {
2650                         addr =  (in_addr_t)(data[i]     << 24) +
2651                                 (in_addr_t)(data[i + 1] << 16) +
2652                                 (in_addr_t)(data[i + 2] << 8);
2653                         i += 3;
2654                 } else if (width < 33) {
2655                         addr =  (in_addr_t)(data[i]     << 24) +
2656                                 (in_addr_t)(data[i + 1] << 16) +
2657                                 (in_addr_t)(data[i + 2] << 8)  +
2658                                 data[i + 3];
2659                         i += 4;
2660                 } else {
2661                         warning("Incorrect subnet width: %d", width);
2662                         return (0);
2663                 }
2664                 mask = (in_addr_t)(~0) << (32 - width);
2665                 addr = ntohl(addr);
2666                 mask = ntohl(mask);
2667
2668                 /*
2669                  * From RFC 3442:
2670                  * ... After deriving a subnet number and subnet mask
2671                  * from each destination descriptor, the DHCP client
2672                  * MUST zero any bits in the subnet number where the
2673                  * corresponding bit in the mask is zero...
2674                  */
2675                 if ((addr & mask) != addr) {
2676                         addr &= mask;
2677                         data[i - 1] = (unsigned char)(
2678                                 (addr >> (((32 - width)/8)*8)) & 0xFF);
2679                 }
2680                 i += 4;
2681         }
2682         if (i > len) {
2683                 warning("Incorrect data length: %d (must be %d)", len, i);
2684                 return (0);
2685         }
2686         return (1);
2687 }
2688
2689 int
2690 res_hnok(const char *dn)
2691 {
2692         int pch = PERIOD, ch = *dn++;
2693
2694         while (ch != '\0') {
2695                 int nch = *dn++;
2696
2697                 if (periodchar(ch)) {
2698                         ;
2699                 } else if (periodchar(pch)) {
2700                         if (!borderchar(ch))
2701                                 return (0);
2702                 } else if (periodchar(nch) || nch == '\0') {
2703                         if (!borderchar(ch))
2704                                 return (0);
2705                 } else {
2706                         if (!middlechar(ch))
2707                                 return (0);
2708                 }
2709                 pch = ch, ch = nch;
2710         }
2711         return (1);
2712 }
2713
2714 int
2715 check_search(const char *srch)
2716 {
2717         int pch = PERIOD, ch = *srch++;
2718         int domains = 1;
2719
2720         /* 256 char limit re resolv.conf(5) */
2721         if (strlen(srch) > 256)
2722                 return (0);
2723
2724         while (whitechar(ch))
2725                 ch = *srch++;
2726
2727         while (ch != '\0') {
2728                 int nch = *srch++;
2729
2730                 if (periodchar(ch) || whitechar(ch)) {
2731                         ;
2732                 } else if (periodchar(pch)) {
2733                         if (!borderchar(ch))
2734                                 return (0);
2735                 } else if (periodchar(nch) || nch == '\0') {
2736                         if (!borderchar(ch))
2737                                 return (0);
2738                 } else {
2739                         if (!middlechar(ch))
2740                                 return (0);
2741                 }
2742                 if (!whitechar(ch)) {
2743                         pch = ch;
2744                 } else {
2745                         while (whitechar(nch)) {
2746                                 nch = *srch++;
2747                         }
2748                         if (nch != '\0')
2749                                 domains++;
2750                         pch = PERIOD;
2751                 }
2752                 ch = nch;
2753         }
2754         /* 6 domain limit re resolv.conf(5) */
2755         if (domains > 6)
2756                 return (0);
2757         return (1);
2758 }
2759
2760 /* Does buf consist only of dotted decimal ipv4 addrs?
2761  * return how many if so,
2762  * otherwise, return 0
2763  */
2764 int
2765 ipv4addrs(const char * buf)
2766 {
2767         struct in_addr jnk;
2768         int count = 0;
2769
2770         while (inet_aton(buf, &jnk) == 1){
2771                 count++;
2772                 while (periodchar(*buf) || digitchar(*buf))
2773                         buf++;
2774                 if (*buf == '\0')
2775                         return (count);
2776                 while (*buf ==  ' ')
2777                         buf++;
2778         }
2779         return (0);
2780 }
2781
2782
2783 const char *
2784 option_as_string(unsigned int code, unsigned char *data, int len)
2785 {
2786         static char optbuf[32768]; /* XXX */
2787         char *op = optbuf;
2788         int opleft = sizeof(optbuf);
2789         unsigned char *dp = data;
2790
2791         if (code > 255)
2792                 error("option_as_string: bad code %d", code);
2793
2794         for (; dp < data + len; dp++) {
2795                 if (!isascii(*dp) || !isprint(*dp)) {
2796                         if (dp + 1 != data + len || *dp != 0) {
2797                                 snprintf(op, opleft, "\\%03o", *dp);
2798                                 op += 4;
2799                                 opleft -= 4;
2800                         }
2801                 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2802                     *dp == '`' || *dp == '\\') {
2803                         *op++ = '\\';
2804                         *op++ = *dp;
2805                         opleft -= 2;
2806                 } else {
2807                         *op++ = *dp;
2808                         opleft--;
2809                 }
2810         }
2811         if (opleft < 1)
2812                 goto toobig;
2813         *op = 0;
2814         return optbuf;
2815 toobig:
2816         warning("dhcp option too large");
2817         return "<error>";
2818 }
2819
2820 int
2821 fork_privchld(int fd, int fd2)
2822 {
2823         struct pollfd pfd[1];
2824         int nfds;
2825
2826         switch (fork()) {
2827         case -1:
2828                 error("cannot fork");
2829         case 0:
2830                 break;
2831         default:
2832                 return (0);
2833         }
2834
2835         setproctitle("%s [priv]", ifi->name);
2836
2837         setsid();
2838         dup2(nullfd, STDIN_FILENO);
2839         dup2(nullfd, STDOUT_FILENO);
2840         dup2(nullfd, STDERR_FILENO);
2841         close(nullfd);
2842         close(fd2);
2843         close(ifi->rfdesc);
2844         ifi->rfdesc = -1;
2845
2846         for (;;) {
2847                 pfd[0].fd = fd;
2848                 pfd[0].events = POLLIN;
2849                 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2850                         if (errno != EINTR)
2851                                 error("poll error");
2852
2853                 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2854                         continue;
2855
2856                 dispatch_imsg(ifi, fd);
2857         }
2858 }