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