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