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