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