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