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