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