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