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