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