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