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