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