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