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