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