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