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 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(char * buf); 135 int res_hnok(const char *dn); 136 int check_search(const char *srch); 137 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 int 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 int 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 = { 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 /* ARGSUSED */ 222 void 223 routehandler(struct protocol *p) 224 { 225 char msg[2048], *addr; 226 struct rt_msghdr *rtm; 227 struct if_msghdr *ifm; 228 struct ifa_msghdr *ifam; 229 struct if_announcemsghdr *ifan; 230 struct ieee80211_join_event *jev; 231 struct client_lease *l; 232 time_t t = time(NULL); 233 struct sockaddr *sa; 234 struct iaddr a; 235 ssize_t n; 236 int linkstat; 237 238 n = read(routefd, &msg, sizeof(msg)); 239 rtm = (struct rt_msghdr *)msg; 240 if (n < sizeof(rtm->rtm_msglen) || n < 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 = 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, &((struct sockaddr_in *)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(((struct sockaddr_in *)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 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 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 memcpy(&from, ip->client->active->address.iabuf, 1518 sizeof(from)); 1519 else 1520 from.s_addr = INADDR_ANY; 1521 1522 /* Record the number of seconds since we started sending. */ 1523 if (ip->client->state == S_REQUESTING) 1524 ip->client->packet.secs = ip->client->secs; 1525 else { 1526 if (interval < 65536) 1527 ip->client->packet.secs = htons(interval); 1528 else 1529 ip->client->packet.secs = htons(65535); 1530 } 1531 1532 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to), 1533 REMOTE_PORT); 1534 1535 /* Send out a packet. */ 1536 send_packet_unpriv(privfd, &ip->client->packet, 1537 ip->client->packet_length, from, to); 1538 1539 add_timeout(cur_time + ip->client->interval, send_request, ip); 1540 } 1541 1542 void 1543 send_decline(void *ipp) 1544 { 1545 struct interface_info *ip = ipp; 1546 1547 note("DHCPDECLINE on %s to %s port %d", ip->name, 1548 inet_ntoa(inaddr_broadcast), REMOTE_PORT); 1549 1550 /* Send out a packet. */ 1551 send_packet_unpriv(privfd, &ip->client->packet, 1552 ip->client->packet_length, inaddr_any, inaddr_broadcast); 1553 } 1554 1555 void 1556 make_discover(struct interface_info *ip, struct client_lease *lease) 1557 { 1558 unsigned char discover = DHCPDISCOVER; 1559 struct tree_cache *options[256]; 1560 struct tree_cache option_elements[256]; 1561 int i; 1562 1563 memset(option_elements, 0, sizeof(option_elements)); 1564 memset(options, 0, sizeof(options)); 1565 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1566 1567 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */ 1568 i = DHO_DHCP_MESSAGE_TYPE; 1569 options[i] = &option_elements[i]; 1570 options[i]->value = &discover; 1571 options[i]->len = sizeof(discover); 1572 options[i]->buf_size = sizeof(discover); 1573 options[i]->timeout = 0xFFFFFFFF; 1574 1575 /* Request the options we want */ 1576 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 1577 options[i] = &option_elements[i]; 1578 options[i]->value = ip->client->config->requested_options; 1579 options[i]->len = ip->client->config->requested_option_count; 1580 options[i]->buf_size = 1581 ip->client->config->requested_option_count; 1582 options[i]->timeout = 0xFFFFFFFF; 1583 1584 /* If we had an address, try to get it again. */ 1585 if (lease) { 1586 ip->client->requested_address = lease->address; 1587 i = DHO_DHCP_REQUESTED_ADDRESS; 1588 options[i] = &option_elements[i]; 1589 options[i]->value = lease->address.iabuf; 1590 options[i]->len = lease->address.len; 1591 options[i]->buf_size = lease->address.len; 1592 options[i]->timeout = 0xFFFFFFFF; 1593 } else 1594 ip->client->requested_address.len = 0; 1595 1596 /* Send any options requested in the config file. */ 1597 for (i = 0; i < 256; i++) 1598 if (!options[i] && 1599 ip->client->config->send_options[i].data) { 1600 options[i] = &option_elements[i]; 1601 options[i]->value = 1602 ip->client->config->send_options[i].data; 1603 options[i]->len = 1604 ip->client->config->send_options[i].len; 1605 options[i]->buf_size = 1606 ip->client->config->send_options[i].len; 1607 options[i]->timeout = 0xFFFFFFFF; 1608 } 1609 1610 /* send host name if not set via config file. */ 1611 if (!options[DHO_HOST_NAME]) { 1612 if (hostname[0] != '\0') { 1613 size_t len; 1614 char* posDot = strchr(hostname, '.'); 1615 if (posDot != NULL) 1616 len = posDot - hostname; 1617 else 1618 len = strlen(hostname); 1619 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME]; 1620 options[DHO_HOST_NAME]->value = hostname; 1621 options[DHO_HOST_NAME]->len = len; 1622 options[DHO_HOST_NAME]->buf_size = len; 1623 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF; 1624 } 1625 } 1626 1627 /* set unique client identifier */ 1628 char client_ident[sizeof(ip->hw_address.haddr) + 1]; 1629 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) { 1630 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ? 1631 ip->hw_address.hlen : sizeof(client_ident)-1; 1632 client_ident[0] = ip->hw_address.htype; 1633 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); 1634 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER]; 1635 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident; 1636 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1; 1637 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1; 1638 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF; 1639 } 1640 1641 /* Set up the option buffer... */ 1642 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1643 options, 0, 0, 0, NULL, 0); 1644 if (ip->client->packet_length < BOOTP_MIN_LEN) 1645 ip->client->packet_length = BOOTP_MIN_LEN; 1646 1647 ip->client->packet.op = BOOTREQUEST; 1648 ip->client->packet.htype = ip->hw_address.htype; 1649 ip->client->packet.hlen = ip->hw_address.hlen; 1650 ip->client->packet.hops = 0; 1651 ip->client->packet.xid = arc4random(); 1652 ip->client->packet.secs = 0; /* filled in by send_discover. */ 1653 ip->client->packet.flags = 0; 1654 1655 memset(&(ip->client->packet.ciaddr), 1656 0, sizeof(ip->client->packet.ciaddr)); 1657 memset(&(ip->client->packet.yiaddr), 1658 0, sizeof(ip->client->packet.yiaddr)); 1659 memset(&(ip->client->packet.siaddr), 1660 0, sizeof(ip->client->packet.siaddr)); 1661 memset(&(ip->client->packet.giaddr), 1662 0, sizeof(ip->client->packet.giaddr)); 1663 memcpy(ip->client->packet.chaddr, 1664 ip->hw_address.haddr, ip->hw_address.hlen); 1665 } 1666 1667 1668 void 1669 make_request(struct interface_info *ip, struct client_lease * lease) 1670 { 1671 unsigned char request = DHCPREQUEST; 1672 struct tree_cache *options[256]; 1673 struct tree_cache option_elements[256]; 1674 int i; 1675 1676 memset(options, 0, sizeof(options)); 1677 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1678 1679 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */ 1680 i = DHO_DHCP_MESSAGE_TYPE; 1681 options[i] = &option_elements[i]; 1682 options[i]->value = &request; 1683 options[i]->len = sizeof(request); 1684 options[i]->buf_size = sizeof(request); 1685 options[i]->timeout = 0xFFFFFFFF; 1686 1687 /* Request the options we want */ 1688 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 1689 options[i] = &option_elements[i]; 1690 options[i]->value = ip->client->config->requested_options; 1691 options[i]->len = ip->client->config->requested_option_count; 1692 options[i]->buf_size = 1693 ip->client->config->requested_option_count; 1694 options[i]->timeout = 0xFFFFFFFF; 1695 1696 /* If we are requesting an address that hasn't yet been assigned 1697 to us, use the DHCP Requested Address option. */ 1698 if (ip->client->state == S_REQUESTING) { 1699 /* Send back the server identifier... */ 1700 i = DHO_DHCP_SERVER_IDENTIFIER; 1701 options[i] = &option_elements[i]; 1702 options[i]->value = lease->options[i].data; 1703 options[i]->len = lease->options[i].len; 1704 options[i]->buf_size = lease->options[i].len; 1705 options[i]->timeout = 0xFFFFFFFF; 1706 } 1707 if (ip->client->state == S_REQUESTING || 1708 ip->client->state == S_REBOOTING) { 1709 ip->client->requested_address = lease->address; 1710 i = DHO_DHCP_REQUESTED_ADDRESS; 1711 options[i] = &option_elements[i]; 1712 options[i]->value = lease->address.iabuf; 1713 options[i]->len = lease->address.len; 1714 options[i]->buf_size = lease->address.len; 1715 options[i]->timeout = 0xFFFFFFFF; 1716 } else 1717 ip->client->requested_address.len = 0; 1718 1719 /* Send any options requested in the config file. */ 1720 for (i = 0; i < 256; i++) 1721 if (!options[i] && 1722 ip->client->config->send_options[i].data) { 1723 options[i] = &option_elements[i]; 1724 options[i]->value = 1725 ip->client->config->send_options[i].data; 1726 options[i]->len = 1727 ip->client->config->send_options[i].len; 1728 options[i]->buf_size = 1729 ip->client->config->send_options[i].len; 1730 options[i]->timeout = 0xFFFFFFFF; 1731 } 1732 1733 /* send host name if not set via config file. */ 1734 if (!options[DHO_HOST_NAME]) { 1735 if (hostname[0] != '\0') { 1736 size_t len; 1737 char* posDot = strchr(hostname, '.'); 1738 if (posDot != NULL) 1739 len = posDot - hostname; 1740 else 1741 len = strlen(hostname); 1742 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME]; 1743 options[DHO_HOST_NAME]->value = hostname; 1744 options[DHO_HOST_NAME]->len = len; 1745 options[DHO_HOST_NAME]->buf_size = len; 1746 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF; 1747 } 1748 } 1749 1750 /* set unique client identifier */ 1751 char client_ident[sizeof(struct hardware)]; 1752 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) { 1753 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ? 1754 ip->hw_address.hlen : sizeof(client_ident)-1; 1755 client_ident[0] = ip->hw_address.htype; 1756 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); 1757 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER]; 1758 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident; 1759 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1; 1760 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1; 1761 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF; 1762 } 1763 1764 /* Set up the option buffer... */ 1765 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1766 options, 0, 0, 0, NULL, 0); 1767 if (ip->client->packet_length < BOOTP_MIN_LEN) 1768 ip->client->packet_length = BOOTP_MIN_LEN; 1769 1770 ip->client->packet.op = BOOTREQUEST; 1771 ip->client->packet.htype = ip->hw_address.htype; 1772 ip->client->packet.hlen = ip->hw_address.hlen; 1773 ip->client->packet.hops = 0; 1774 ip->client->packet.xid = ip->client->xid; 1775 ip->client->packet.secs = 0; /* Filled in by send_request. */ 1776 1777 /* If we own the address we're requesting, put it in ciaddr; 1778 otherwise set ciaddr to zero. */ 1779 if (ip->client->state == S_BOUND || 1780 ip->client->state == S_RENEWING || 1781 ip->client->state == S_REBINDING) { 1782 memcpy(&ip->client->packet.ciaddr, 1783 lease->address.iabuf, lease->address.len); 1784 ip->client->packet.flags = 0; 1785 } else { 1786 memset(&ip->client->packet.ciaddr, 0, 1787 sizeof(ip->client->packet.ciaddr)); 1788 ip->client->packet.flags = 0; 1789 } 1790 1791 memset(&ip->client->packet.yiaddr, 0, 1792 sizeof(ip->client->packet.yiaddr)); 1793 memset(&ip->client->packet.siaddr, 0, 1794 sizeof(ip->client->packet.siaddr)); 1795 memset(&ip->client->packet.giaddr, 0, 1796 sizeof(ip->client->packet.giaddr)); 1797 memcpy(ip->client->packet.chaddr, 1798 ip->hw_address.haddr, ip->hw_address.hlen); 1799 } 1800 1801 void 1802 make_decline(struct interface_info *ip, struct client_lease *lease) 1803 { 1804 struct tree_cache *options[256], message_type_tree; 1805 struct tree_cache requested_address_tree; 1806 struct tree_cache server_id_tree, client_id_tree; 1807 unsigned char decline = DHCPDECLINE; 1808 int i; 1809 1810 memset(options, 0, sizeof(options)); 1811 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1812 1813 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */ 1814 i = DHO_DHCP_MESSAGE_TYPE; 1815 options[i] = &message_type_tree; 1816 options[i]->value = &decline; 1817 options[i]->len = sizeof(decline); 1818 options[i]->buf_size = sizeof(decline); 1819 options[i]->timeout = 0xFFFFFFFF; 1820 1821 /* Send back the server identifier... */ 1822 i = DHO_DHCP_SERVER_IDENTIFIER; 1823 options[i] = &server_id_tree; 1824 options[i]->value = lease->options[i].data; 1825 options[i]->len = lease->options[i].len; 1826 options[i]->buf_size = lease->options[i].len; 1827 options[i]->timeout = 0xFFFFFFFF; 1828 1829 /* Send back the address we're declining. */ 1830 i = DHO_DHCP_REQUESTED_ADDRESS; 1831 options[i] = &requested_address_tree; 1832 options[i]->value = lease->address.iabuf; 1833 options[i]->len = lease->address.len; 1834 options[i]->buf_size = lease->address.len; 1835 options[i]->timeout = 0xFFFFFFFF; 1836 1837 /* Send the uid if the user supplied one. */ 1838 i = DHO_DHCP_CLIENT_IDENTIFIER; 1839 if (ip->client->config->send_options[i].len) { 1840 options[i] = &client_id_tree; 1841 options[i]->value = ip->client->config->send_options[i].data; 1842 options[i]->len = ip->client->config->send_options[i].len; 1843 options[i]->buf_size = ip->client->config->send_options[i].len; 1844 options[i]->timeout = 0xFFFFFFFF; 1845 } 1846 1847 1848 /* Set up the option buffer... */ 1849 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1850 options, 0, 0, 0, NULL, 0); 1851 if (ip->client->packet_length < BOOTP_MIN_LEN) 1852 ip->client->packet_length = BOOTP_MIN_LEN; 1853 1854 ip->client->packet.op = BOOTREQUEST; 1855 ip->client->packet.htype = ip->hw_address.htype; 1856 ip->client->packet.hlen = ip->hw_address.hlen; 1857 ip->client->packet.hops = 0; 1858 ip->client->packet.xid = ip->client->xid; 1859 ip->client->packet.secs = 0; /* Filled in by send_request. */ 1860 ip->client->packet.flags = 0; 1861 1862 /* ciaddr must always be zero. */ 1863 memset(&ip->client->packet.ciaddr, 0, 1864 sizeof(ip->client->packet.ciaddr)); 1865 memset(&ip->client->packet.yiaddr, 0, 1866 sizeof(ip->client->packet.yiaddr)); 1867 memset(&ip->client->packet.siaddr, 0, 1868 sizeof(ip->client->packet.siaddr)); 1869 memset(&ip->client->packet.giaddr, 0, 1870 sizeof(ip->client->packet.giaddr)); 1871 memcpy(ip->client->packet.chaddr, 1872 ip->hw_address.haddr, ip->hw_address.hlen); 1873 } 1874 1875 void 1876 free_client_lease(struct client_lease *lease) 1877 { 1878 int i; 1879 1880 if (lease->server_name) 1881 free(lease->server_name); 1882 if (lease->filename) 1883 free(lease->filename); 1884 for (i = 0; i < 256; i++) { 1885 if (lease->options[i].len) 1886 free(lease->options[i].data); 1887 } 1888 free(lease); 1889 } 1890 1891 FILE *leaseFile; 1892 1893 void 1894 rewrite_client_leases(void) 1895 { 1896 struct client_lease *lp; 1897 cap_rights_t rights; 1898 1899 if (!leaseFile) { 1900 leaseFile = fopen(path_dhclient_db, "w"); 1901 if (!leaseFile) 1902 error("can't create %s: %m", path_dhclient_db); 1903 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC, 1904 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE); 1905 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 && 1906 errno != ENOSYS) { 1907 error("can't limit lease descriptor: %m"); 1908 } 1909 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 && 1910 errno != ENOSYS) { 1911 error("can't limit lease descriptor fcntls: %m"); 1912 } 1913 } else { 1914 fflush(leaseFile); 1915 rewind(leaseFile); 1916 } 1917 1918 for (lp = ifi->client->leases; lp; lp = lp->next) 1919 write_client_lease(ifi, lp, 1); 1920 if (ifi->client->active) 1921 write_client_lease(ifi, ifi->client->active, 1); 1922 1923 fflush(leaseFile); 1924 ftruncate(fileno(leaseFile), ftello(leaseFile)); 1925 fsync(fileno(leaseFile)); 1926 } 1927 1928 void 1929 write_client_lease(struct interface_info *ip, struct client_lease *lease, 1930 int rewrite) 1931 { 1932 static int leases_written; 1933 struct tm *t; 1934 int i; 1935 1936 if (!rewrite) { 1937 if (leases_written++ > 20) { 1938 rewrite_client_leases(); 1939 leases_written = 0; 1940 } 1941 } 1942 1943 /* If the lease came from the config file, we don't need to stash 1944 a copy in the lease database. */ 1945 if (lease->is_static) 1946 return; 1947 1948 if (!leaseFile) { /* XXX */ 1949 leaseFile = fopen(path_dhclient_db, "w"); 1950 if (!leaseFile) 1951 error("can't create %s: %m", path_dhclient_db); 1952 } 1953 1954 fprintf(leaseFile, "lease {\n"); 1955 if (lease->is_bootp) 1956 fprintf(leaseFile, " bootp;\n"); 1957 fprintf(leaseFile, " interface \"%s\";\n", ip->name); 1958 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address)); 1959 if (lease->nextserver.len == sizeof(inaddr_any) && 1960 0 != memcmp(lease->nextserver.iabuf, &inaddr_any, 1961 sizeof(inaddr_any))) 1962 fprintf(leaseFile, " next-server %s;\n", 1963 piaddr(lease->nextserver)); 1964 if (lease->filename) 1965 fprintf(leaseFile, " filename \"%s\";\n", lease->filename); 1966 if (lease->server_name) 1967 fprintf(leaseFile, " server-name \"%s\";\n", 1968 lease->server_name); 1969 if (lease->medium) 1970 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string); 1971 for (i = 0; i < 256; i++) 1972 if (lease->options[i].len) 1973 fprintf(leaseFile, " option %s %s;\n", 1974 dhcp_options[i].name, 1975 pretty_print_option(i, lease->options[i].data, 1976 lease->options[i].len, 1, 1)); 1977 1978 t = gmtime(&lease->renewal); 1979 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n", 1980 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 1981 t->tm_hour, t->tm_min, t->tm_sec); 1982 t = gmtime(&lease->rebind); 1983 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n", 1984 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 1985 t->tm_hour, t->tm_min, t->tm_sec); 1986 t = gmtime(&lease->expiry); 1987 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n", 1988 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 1989 t->tm_hour, t->tm_min, t->tm_sec); 1990 fprintf(leaseFile, "}\n"); 1991 fflush(leaseFile); 1992 } 1993 1994 void 1995 script_init(char *reason, struct string_list *medium) 1996 { 1997 size_t len, mediumlen = 0; 1998 struct imsg_hdr hdr; 1999 struct buf *buf; 2000 int errs; 2001 2002 if (medium != NULL && medium->string != NULL) 2003 mediumlen = strlen(medium->string); 2004 2005 hdr.code = IMSG_SCRIPT_INIT; 2006 hdr.len = sizeof(struct imsg_hdr) + 2007 sizeof(size_t) + mediumlen + 2008 sizeof(size_t) + strlen(reason); 2009 2010 if ((buf = buf_open(hdr.len)) == NULL) 2011 error("buf_open: %m"); 2012 2013 errs = 0; 2014 errs += buf_add(buf, &hdr, sizeof(hdr)); 2015 errs += buf_add(buf, &mediumlen, sizeof(mediumlen)); 2016 if (mediumlen > 0) 2017 errs += buf_add(buf, medium->string, mediumlen); 2018 len = strlen(reason); 2019 errs += buf_add(buf, &len, sizeof(len)); 2020 errs += buf_add(buf, reason, len); 2021 2022 if (errs) 2023 error("buf_add: %m"); 2024 2025 if (buf_close(privfd, buf) == -1) 2026 error("buf_close: %m"); 2027 } 2028 2029 void 2030 priv_script_init(char *reason, char *medium) 2031 { 2032 struct interface_info *ip = ifi; 2033 2034 if (ip) { 2035 ip->client->scriptEnvsize = 100; 2036 if (ip->client->scriptEnv == NULL) 2037 ip->client->scriptEnv = 2038 malloc(ip->client->scriptEnvsize * sizeof(char *)); 2039 if (ip->client->scriptEnv == NULL) 2040 error("script_init: no memory for environment"); 2041 2042 ip->client->scriptEnv[0] = strdup(CLIENT_PATH); 2043 if (ip->client->scriptEnv[0] == NULL) 2044 error("script_init: no memory for environment"); 2045 2046 ip->client->scriptEnv[1] = NULL; 2047 2048 script_set_env(ip->client, "", "interface", ip->name); 2049 2050 if (medium) 2051 script_set_env(ip->client, "", "medium", medium); 2052 2053 script_set_env(ip->client, "", "reason", reason); 2054 } 2055 } 2056 2057 void 2058 priv_script_write_params(char *prefix, struct client_lease *lease) 2059 { 2060 struct interface_info *ip = ifi; 2061 u_int8_t dbuf[1500], *dp = NULL; 2062 int i, len; 2063 char tbuf[128]; 2064 2065 script_set_env(ip->client, prefix, "ip_address", 2066 piaddr(lease->address)); 2067 2068 if (ip->client->config->default_actions[DHO_SUBNET_MASK] == 2069 ACTION_SUPERSEDE) { 2070 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data; 2071 len = ip->client->config->defaults[DHO_SUBNET_MASK].len; 2072 } else { 2073 dp = lease->options[DHO_SUBNET_MASK].data; 2074 len = lease->options[DHO_SUBNET_MASK].len; 2075 } 2076 if (len && (len < sizeof(lease->address.iabuf))) { 2077 struct iaddr netmask, subnet, broadcast; 2078 2079 memcpy(netmask.iabuf, dp, len); 2080 netmask.len = len; 2081 subnet = subnet_number(lease->address, netmask); 2082 if (subnet.len) { 2083 script_set_env(ip->client, prefix, "network_number", 2084 piaddr(subnet)); 2085 if (!lease->options[DHO_BROADCAST_ADDRESS].len) { 2086 broadcast = broadcast_addr(subnet, netmask); 2087 if (broadcast.len) 2088 script_set_env(ip->client, prefix, 2089 "broadcast_address", 2090 piaddr(broadcast)); 2091 } 2092 } 2093 } 2094 2095 if (lease->filename) 2096 script_set_env(ip->client, prefix, "filename", lease->filename); 2097 if (lease->server_name) 2098 script_set_env(ip->client, prefix, "server_name", 2099 lease->server_name); 2100 for (i = 0; i < 256; i++) { 2101 len = 0; 2102 2103 if (ip->client->config->defaults[i].len) { 2104 if (lease->options[i].len) { 2105 switch ( 2106 ip->client->config->default_actions[i]) { 2107 case ACTION_DEFAULT: 2108 dp = lease->options[i].data; 2109 len = lease->options[i].len; 2110 break; 2111 case ACTION_SUPERSEDE: 2112 supersede: 2113 dp = ip->client-> 2114 config->defaults[i].data; 2115 len = ip->client-> 2116 config->defaults[i].len; 2117 break; 2118 case ACTION_PREPEND: 2119 len = ip->client-> 2120 config->defaults[i].len + 2121 lease->options[i].len; 2122 if (len >= sizeof(dbuf)) { 2123 warning("no space to %s %s", 2124 "prepend option", 2125 dhcp_options[i].name); 2126 goto supersede; 2127 } 2128 dp = dbuf; 2129 memcpy(dp, 2130 ip->client-> 2131 config->defaults[i].data, 2132 ip->client-> 2133 config->defaults[i].len); 2134 memcpy(dp + ip->client-> 2135 config->defaults[i].len, 2136 lease->options[i].data, 2137 lease->options[i].len); 2138 dp[len] = '\0'; 2139 break; 2140 case ACTION_APPEND: 2141 /* 2142 * When we append, we assume that we're 2143 * appending to text. Some MS servers 2144 * include a NUL byte at the end of 2145 * the search string provided. 2146 */ 2147 len = ip->client-> 2148 config->defaults[i].len + 2149 lease->options[i].len; 2150 if (len >= sizeof(dbuf)) { 2151 warning("no space to %s %s", 2152 "append option", 2153 dhcp_options[i].name); 2154 goto supersede; 2155 } 2156 memcpy(dbuf, 2157 lease->options[i].data, 2158 lease->options[i].len); 2159 for (dp = dbuf + lease->options[i].len; 2160 dp > dbuf; dp--, len--) 2161 if (dp[-1] != '\0') 2162 break; 2163 memcpy(dp, 2164 ip->client-> 2165 config->defaults[i].data, 2166 ip->client-> 2167 config->defaults[i].len); 2168 dp = dbuf; 2169 dp[len] = '\0'; 2170 } 2171 } else { 2172 dp = ip->client-> 2173 config->defaults[i].data; 2174 len = ip->client-> 2175 config->defaults[i].len; 2176 } 2177 } else if (lease->options[i].len) { 2178 len = lease->options[i].len; 2179 dp = lease->options[i].data; 2180 } else { 2181 len = 0; 2182 } 2183 if (len) { 2184 char name[256]; 2185 2186 if (dhcp_option_ev_name(name, sizeof(name), 2187 &dhcp_options[i])) 2188 script_set_env(ip->client, prefix, name, 2189 pretty_print_option(i, dp, len, 0, 0)); 2190 } 2191 } 2192 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry); 2193 script_set_env(ip->client, prefix, "expiry", tbuf); 2194 } 2195 2196 void 2197 script_write_params(char *prefix, struct client_lease *lease) 2198 { 2199 size_t fn_len = 0, sn_len = 0, pr_len = 0; 2200 struct imsg_hdr hdr; 2201 struct buf *buf; 2202 int errs, i; 2203 2204 if (lease->filename != NULL) 2205 fn_len = strlen(lease->filename); 2206 if (lease->server_name != NULL) 2207 sn_len = strlen(lease->server_name); 2208 if (prefix != NULL) 2209 pr_len = strlen(prefix); 2210 2211 hdr.code = IMSG_SCRIPT_WRITE_PARAMS; 2212 hdr.len = sizeof(hdr) + sizeof(struct client_lease) + 2213 sizeof(size_t) + fn_len + sizeof(size_t) + sn_len + 2214 sizeof(size_t) + pr_len; 2215 2216 for (i = 0; i < 256; i++) 2217 hdr.len += sizeof(int) + lease->options[i].len; 2218 2219 scripttime = time(NULL); 2220 2221 if ((buf = buf_open(hdr.len)) == NULL) 2222 error("buf_open: %m"); 2223 2224 errs = 0; 2225 errs += buf_add(buf, &hdr, sizeof(hdr)); 2226 errs += buf_add(buf, lease, sizeof(struct client_lease)); 2227 errs += buf_add(buf, &fn_len, sizeof(fn_len)); 2228 errs += buf_add(buf, lease->filename, fn_len); 2229 errs += buf_add(buf, &sn_len, sizeof(sn_len)); 2230 errs += buf_add(buf, lease->server_name, sn_len); 2231 errs += buf_add(buf, &pr_len, sizeof(pr_len)); 2232 errs += buf_add(buf, prefix, pr_len); 2233 2234 for (i = 0; i < 256; i++) { 2235 errs += buf_add(buf, &lease->options[i].len, 2236 sizeof(lease->options[i].len)); 2237 errs += buf_add(buf, lease->options[i].data, 2238 lease->options[i].len); 2239 } 2240 2241 if (errs) 2242 error("buf_add: %m"); 2243 2244 if (buf_close(privfd, buf) == -1) 2245 error("buf_close: %m"); 2246 } 2247 2248 int 2249 script_go(void) 2250 { 2251 struct imsg_hdr hdr; 2252 struct buf *buf; 2253 int ret; 2254 2255 hdr.code = IMSG_SCRIPT_GO; 2256 hdr.len = sizeof(struct imsg_hdr); 2257 2258 if ((buf = buf_open(hdr.len)) == NULL) 2259 error("buf_open: %m"); 2260 2261 if (buf_add(buf, &hdr, sizeof(hdr))) 2262 error("buf_add: %m"); 2263 2264 if (buf_close(privfd, buf) == -1) 2265 error("buf_close: %m"); 2266 2267 bzero(&hdr, sizeof(hdr)); 2268 buf_read(privfd, &hdr, sizeof(hdr)); 2269 if (hdr.code != IMSG_SCRIPT_GO_RET) 2270 error("unexpected msg type %u", hdr.code); 2271 if (hdr.len != sizeof(hdr) + sizeof(int)) 2272 error("received corrupted message"); 2273 buf_read(privfd, &ret, sizeof(ret)); 2274 2275 scripttime = time(NULL); 2276 2277 return (ret); 2278 } 2279 2280 int 2281 priv_script_go(void) 2282 { 2283 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI"; 2284 static char client_path[] = CLIENT_PATH; 2285 struct interface_info *ip = ifi; 2286 int pid, wpid, wstatus; 2287 2288 scripttime = time(NULL); 2289 2290 if (ip) { 2291 scriptName = ip->client->config->script_name; 2292 envp = ip->client->scriptEnv; 2293 } else { 2294 scriptName = top_level_config.script_name; 2295 epp[0] = reason; 2296 epp[1] = client_path; 2297 epp[2] = NULL; 2298 envp = epp; 2299 } 2300 2301 argv[0] = scriptName; 2302 argv[1] = NULL; 2303 2304 pid = fork(); 2305 if (pid < 0) { 2306 error("fork: %m"); 2307 wstatus = 0; 2308 } else if (pid) { 2309 do { 2310 wpid = wait(&wstatus); 2311 } while (wpid != pid && wpid > 0); 2312 if (wpid < 0) { 2313 error("wait: %m"); 2314 wstatus = 0; 2315 } 2316 } else { 2317 execve(scriptName, argv, envp); 2318 error("execve (%s, ...): %m", scriptName); 2319 } 2320 2321 if (ip) 2322 script_flush_env(ip->client); 2323 2324 return (wstatus & 0xff); 2325 } 2326 2327 void 2328 script_set_env(struct client_state *client, const char *prefix, 2329 const char *name, const char *value) 2330 { 2331 int i, j, namelen; 2332 2333 /* No `` or $() command substitution allowed in environment values! */ 2334 for (j=0; j < strlen(value); j++) 2335 switch (value[j]) { 2336 case '`': 2337 case '$': 2338 warning("illegal character (%c) in value '%s'", 2339 value[j], value); 2340 /* Ignore this option */ 2341 return; 2342 } 2343 2344 namelen = strlen(name); 2345 2346 for (i = 0; client->scriptEnv[i]; i++) 2347 if (strncmp(client->scriptEnv[i], name, namelen) == 0 && 2348 client->scriptEnv[i][namelen] == '=') 2349 break; 2350 2351 if (client->scriptEnv[i]) 2352 /* Reuse the slot. */ 2353 free(client->scriptEnv[i]); 2354 else { 2355 /* New variable. Expand if necessary. */ 2356 if (i >= client->scriptEnvsize - 1) { 2357 char **newscriptEnv; 2358 int newscriptEnvsize = client->scriptEnvsize + 50; 2359 2360 newscriptEnv = realloc(client->scriptEnv, 2361 newscriptEnvsize); 2362 if (newscriptEnv == NULL) { 2363 free(client->scriptEnv); 2364 client->scriptEnv = NULL; 2365 client->scriptEnvsize = 0; 2366 error("script_set_env: no memory for variable"); 2367 } 2368 client->scriptEnv = newscriptEnv; 2369 client->scriptEnvsize = newscriptEnvsize; 2370 } 2371 /* need to set the NULL pointer at end of array beyond 2372 the new slot. */ 2373 client->scriptEnv[i + 1] = NULL; 2374 } 2375 /* Allocate space and format the variable in the appropriate slot. */ 2376 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 + 2377 strlen(value) + 1); 2378 if (client->scriptEnv[i] == NULL) 2379 error("script_set_env: no memory for variable assignment"); 2380 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) + 2381 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value); 2382 } 2383 2384 void 2385 script_flush_env(struct client_state *client) 2386 { 2387 int i; 2388 2389 for (i = 0; client->scriptEnv[i]; i++) { 2390 free(client->scriptEnv[i]); 2391 client->scriptEnv[i] = NULL; 2392 } 2393 client->scriptEnvsize = 0; 2394 } 2395 2396 int 2397 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option) 2398 { 2399 int i; 2400 2401 for (i = 0; option->name[i]; i++) { 2402 if (i + 1 == buflen) 2403 return 0; 2404 if (option->name[i] == '-') 2405 buf[i] = '_'; 2406 else 2407 buf[i] = option->name[i]; 2408 } 2409 2410 buf[i] = 0; 2411 return 1; 2412 } 2413 2414 void 2415 go_daemon(void) 2416 { 2417 static int state = 0; 2418 cap_rights_t rights; 2419 2420 if (no_daemon || state) 2421 return; 2422 2423 state = 1; 2424 2425 /* Stop logging to stderr... */ 2426 log_perror = 0; 2427 2428 if (daemon(1, 1) == -1) 2429 error("daemon"); 2430 2431 cap_rights_init(&rights); 2432 2433 if (pidfile != NULL) { 2434 pidfile_write(pidfile); 2435 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 && 2436 errno != ENOSYS) { 2437 error("can't limit pidfile descriptor: %m"); 2438 } 2439 } 2440 2441 /* we are chrooted, daemon(3) fails to open /dev/null */ 2442 if (nullfd != -1) { 2443 dup2(nullfd, STDIN_FILENO); 2444 dup2(nullfd, STDOUT_FILENO); 2445 dup2(nullfd, STDERR_FILENO); 2446 close(nullfd); 2447 nullfd = -1; 2448 } 2449 2450 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) 2451 error("can't limit stdin: %m"); 2452 cap_rights_init(&rights, CAP_WRITE); 2453 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) 2454 error("can't limit stdout: %m"); 2455 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) 2456 error("can't limit stderr: %m"); 2457 } 2458 2459 int 2460 check_option(struct client_lease *l, int option) 2461 { 2462 char *opbuf; 2463 char *sbuf; 2464 2465 /* we use this, since this is what gets passed to dhclient-script */ 2466 2467 opbuf = pretty_print_option(option, l->options[option].data, 2468 l->options[option].len, 0, 0); 2469 2470 sbuf = option_as_string(option, l->options[option].data, 2471 l->options[option].len); 2472 2473 switch (option) { 2474 case DHO_SUBNET_MASK: 2475 case DHO_TIME_SERVERS: 2476 case DHO_NAME_SERVERS: 2477 case DHO_ROUTERS: 2478 case DHO_DOMAIN_NAME_SERVERS: 2479 case DHO_LOG_SERVERS: 2480 case DHO_COOKIE_SERVERS: 2481 case DHO_LPR_SERVERS: 2482 case DHO_IMPRESS_SERVERS: 2483 case DHO_RESOURCE_LOCATION_SERVERS: 2484 case DHO_SWAP_SERVER: 2485 case DHO_BROADCAST_ADDRESS: 2486 case DHO_NIS_SERVERS: 2487 case DHO_NTP_SERVERS: 2488 case DHO_NETBIOS_NAME_SERVERS: 2489 case DHO_NETBIOS_DD_SERVER: 2490 case DHO_FONT_SERVERS: 2491 case DHO_DHCP_SERVER_IDENTIFIER: 2492 case DHO_NISPLUS_SERVERS: 2493 case DHO_MOBILE_IP_HOME_AGENT: 2494 case DHO_SMTP_SERVER: 2495 case DHO_POP_SERVER: 2496 case DHO_NNTP_SERVER: 2497 case DHO_WWW_SERVER: 2498 case DHO_FINGER_SERVER: 2499 case DHO_IRC_SERVER: 2500 case DHO_STREETTALK_SERVER: 2501 case DHO_STREETTALK_DA_SERVER: 2502 if (!ipv4addrs(opbuf)) { 2503 warning("Invalid IP address in option: %s", opbuf); 2504 return (0); 2505 } 2506 return (1) ; 2507 case DHO_HOST_NAME: 2508 case DHO_NIS_DOMAIN: 2509 case DHO_NISPLUS_DOMAIN: 2510 case DHO_TFTP_SERVER_NAME: 2511 if (!res_hnok(sbuf)) { 2512 warning("Bogus Host Name option %d: %s (%s)", option, 2513 sbuf, opbuf); 2514 l->options[option].len = 0; 2515 free(l->options[option].data); 2516 } 2517 return (1); 2518 case DHO_DOMAIN_NAME: 2519 case DHO_DOMAIN_SEARCH: 2520 if (!res_hnok(sbuf)) { 2521 if (!check_search(sbuf)) { 2522 warning("Bogus domain search list %d: %s (%s)", 2523 option, sbuf, opbuf); 2524 l->options[option].len = 0; 2525 free(l->options[option].data); 2526 } 2527 } 2528 return (1); 2529 case DHO_PAD: 2530 case DHO_TIME_OFFSET: 2531 case DHO_BOOT_SIZE: 2532 case DHO_MERIT_DUMP: 2533 case DHO_ROOT_PATH: 2534 case DHO_EXTENSIONS_PATH: 2535 case DHO_IP_FORWARDING: 2536 case DHO_NON_LOCAL_SOURCE_ROUTING: 2537 case DHO_POLICY_FILTER: 2538 case DHO_MAX_DGRAM_REASSEMBLY: 2539 case DHO_DEFAULT_IP_TTL: 2540 case DHO_PATH_MTU_AGING_TIMEOUT: 2541 case DHO_PATH_MTU_PLATEAU_TABLE: 2542 case DHO_INTERFACE_MTU: 2543 case DHO_ALL_SUBNETS_LOCAL: 2544 case DHO_PERFORM_MASK_DISCOVERY: 2545 case DHO_MASK_SUPPLIER: 2546 case DHO_ROUTER_DISCOVERY: 2547 case DHO_ROUTER_SOLICITATION_ADDRESS: 2548 case DHO_STATIC_ROUTES: 2549 case DHO_TRAILER_ENCAPSULATION: 2550 case DHO_ARP_CACHE_TIMEOUT: 2551 case DHO_IEEE802_3_ENCAPSULATION: 2552 case DHO_DEFAULT_TCP_TTL: 2553 case DHO_TCP_KEEPALIVE_INTERVAL: 2554 case DHO_TCP_KEEPALIVE_GARBAGE: 2555 case DHO_VENDOR_ENCAPSULATED_OPTIONS: 2556 case DHO_NETBIOS_NODE_TYPE: 2557 case DHO_NETBIOS_SCOPE: 2558 case DHO_X_DISPLAY_MANAGER: 2559 case DHO_DHCP_REQUESTED_ADDRESS: 2560 case DHO_DHCP_LEASE_TIME: 2561 case DHO_DHCP_OPTION_OVERLOAD: 2562 case DHO_DHCP_MESSAGE_TYPE: 2563 case DHO_DHCP_PARAMETER_REQUEST_LIST: 2564 case DHO_DHCP_MESSAGE: 2565 case DHO_DHCP_MAX_MESSAGE_SIZE: 2566 case DHO_DHCP_RENEWAL_TIME: 2567 case DHO_DHCP_REBINDING_TIME: 2568 case DHO_DHCP_CLASS_IDENTIFIER: 2569 case DHO_DHCP_CLIENT_IDENTIFIER: 2570 case DHO_BOOTFILE_NAME: 2571 case DHO_DHCP_USER_CLASS_ID: 2572 case DHO_END: 2573 return (1); 2574 case DHO_CLASSLESS_ROUTES: 2575 return (check_classless_option(l->options[option].data, 2576 l->options[option].len)); 2577 default: 2578 warning("unknown dhcp option value 0x%x", option); 2579 return (unknown_ok); 2580 } 2581 } 2582 2583 /* RFC 3442 The Classless Static Routes option checks */ 2584 int 2585 check_classless_option(unsigned char *data, int len) 2586 { 2587 int i = 0; 2588 unsigned char width; 2589 in_addr_t addr, mask; 2590 2591 if (len < 5) { 2592 warning("Too small length: %d", len); 2593 return (0); 2594 } 2595 while(i < len) { 2596 width = data[i++]; 2597 if (width == 0) { 2598 i += 4; 2599 continue; 2600 } else if (width < 9) { 2601 addr = (in_addr_t)(data[i] << 24); 2602 i += 1; 2603 } else if (width < 17) { 2604 addr = (in_addr_t)(data[i] << 24) + 2605 (in_addr_t)(data[i + 1] << 16); 2606 i += 2; 2607 } else if (width < 25) { 2608 addr = (in_addr_t)(data[i] << 24) + 2609 (in_addr_t)(data[i + 1] << 16) + 2610 (in_addr_t)(data[i + 2] << 8); 2611 i += 3; 2612 } else if (width < 33) { 2613 addr = (in_addr_t)(data[i] << 24) + 2614 (in_addr_t)(data[i + 1] << 16) + 2615 (in_addr_t)(data[i + 2] << 8) + 2616 data[i + 3]; 2617 i += 4; 2618 } else { 2619 warning("Incorrect subnet width: %d", width); 2620 return (0); 2621 } 2622 mask = (in_addr_t)(~0) << (32 - width); 2623 addr = ntohl(addr); 2624 mask = ntohl(mask); 2625 2626 /* 2627 * From RFC 3442: 2628 * ... After deriving a subnet number and subnet mask 2629 * from each destination descriptor, the DHCP client 2630 * MUST zero any bits in the subnet number where the 2631 * corresponding bit in the mask is zero... 2632 */ 2633 if ((addr & mask) != addr) { 2634 addr &= mask; 2635 data[i - 1] = (unsigned char)( 2636 (addr >> (((32 - width)/8)*8)) & 0xFF); 2637 } 2638 i += 4; 2639 } 2640 if (i > len) { 2641 warning("Incorrect data length: %d (must be %d)", len, i); 2642 return (0); 2643 } 2644 return (1); 2645 } 2646 2647 int 2648 res_hnok(const char *dn) 2649 { 2650 int pch = PERIOD, ch = *dn++; 2651 2652 while (ch != '\0') { 2653 int nch = *dn++; 2654 2655 if (periodchar(ch)) { 2656 ; 2657 } else if (periodchar(pch)) { 2658 if (!borderchar(ch)) 2659 return (0); 2660 } else if (periodchar(nch) || nch == '\0') { 2661 if (!borderchar(ch)) 2662 return (0); 2663 } else { 2664 if (!middlechar(ch)) 2665 return (0); 2666 } 2667 pch = ch, ch = nch; 2668 } 2669 return (1); 2670 } 2671 2672 int 2673 check_search(const char *srch) 2674 { 2675 int pch = PERIOD, ch = *srch++; 2676 int domains = 1; 2677 2678 /* 256 char limit re resolv.conf(5) */ 2679 if (strlen(srch) > 256) 2680 return (0); 2681 2682 while (whitechar(ch)) 2683 ch = *srch++; 2684 2685 while (ch != '\0') { 2686 int nch = *srch++; 2687 2688 if (periodchar(ch) || whitechar(ch)) { 2689 ; 2690 } else if (periodchar(pch)) { 2691 if (!borderchar(ch)) 2692 return (0); 2693 } else if (periodchar(nch) || nch == '\0') { 2694 if (!borderchar(ch)) 2695 return (0); 2696 } else { 2697 if (!middlechar(ch)) 2698 return (0); 2699 } 2700 if (!whitechar(ch)) { 2701 pch = ch; 2702 } else { 2703 while (whitechar(nch)) { 2704 nch = *srch++; 2705 } 2706 if (nch != '\0') 2707 domains++; 2708 pch = PERIOD; 2709 } 2710 ch = nch; 2711 } 2712 /* 6 domain limit re resolv.conf(5) */ 2713 if (domains > 6) 2714 return (0); 2715 return (1); 2716 } 2717 2718 /* Does buf consist only of dotted decimal ipv4 addrs? 2719 * return how many if so, 2720 * otherwise, return 0 2721 */ 2722 int 2723 ipv4addrs(char * buf) 2724 { 2725 struct in_addr jnk; 2726 int count = 0; 2727 2728 while (inet_aton(buf, &jnk) == 1){ 2729 count++; 2730 while (periodchar(*buf) || digitchar(*buf)) 2731 buf++; 2732 if (*buf == '\0') 2733 return (count); 2734 while (*buf == ' ') 2735 buf++; 2736 } 2737 return (0); 2738 } 2739 2740 2741 char * 2742 option_as_string(unsigned int code, unsigned char *data, int len) 2743 { 2744 static char optbuf[32768]; /* XXX */ 2745 char *op = optbuf; 2746 int opleft = sizeof(optbuf); 2747 unsigned char *dp = data; 2748 2749 if (code > 255) 2750 error("option_as_string: bad code %d", code); 2751 2752 for (; dp < data + len; dp++) { 2753 if (!isascii(*dp) || !isprint(*dp)) { 2754 if (dp + 1 != data + len || *dp != 0) { 2755 snprintf(op, opleft, "\\%03o", *dp); 2756 op += 4; 2757 opleft -= 4; 2758 } 2759 } else if (*dp == '"' || *dp == '\'' || *dp == '$' || 2760 *dp == '`' || *dp == '\\') { 2761 *op++ = '\\'; 2762 *op++ = *dp; 2763 opleft -= 2; 2764 } else { 2765 *op++ = *dp; 2766 opleft--; 2767 } 2768 } 2769 if (opleft < 1) 2770 goto toobig; 2771 *op = 0; 2772 return optbuf; 2773 toobig: 2774 warning("dhcp option too large"); 2775 return "<error>"; 2776 } 2777 2778 int 2779 fork_privchld(int fd, int fd2) 2780 { 2781 struct pollfd pfd[1]; 2782 int nfds; 2783 2784 switch (fork()) { 2785 case -1: 2786 error("cannot fork"); 2787 case 0: 2788 break; 2789 default: 2790 return (0); 2791 } 2792 2793 setproctitle("%s [priv]", ifi->name); 2794 2795 setsid(); 2796 dup2(nullfd, STDIN_FILENO); 2797 dup2(nullfd, STDOUT_FILENO); 2798 dup2(nullfd, STDERR_FILENO); 2799 close(nullfd); 2800 close(fd2); 2801 close(ifi->rfdesc); 2802 ifi->rfdesc = -1; 2803 2804 for (;;) { 2805 pfd[0].fd = fd; 2806 pfd[0].events = POLLIN; 2807 if ((nfds = poll(pfd, 1, INFTIM)) == -1) 2808 if (errno != EINTR) 2809 error("poll error"); 2810 2811 if (nfds == 0 || !(pfd[0].revents & POLLIN)) 2812 continue; 2813 2814 dispatch_imsg(ifi, fd); 2815 } 2816 } 2817