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