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