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