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