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