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