1 /* $OpenBSD: dhcp.c,v 1.27 2008/07/21 16:51:18 millert Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996, 1997, 1998, 1999 5 * The Internet Software Consortium. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of The Internet Software Consortium nor the names 17 * of its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND 21 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * This software has been written for the Internet Software Consortium 35 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie 36 * Enterprises. To learn more about the Internet Software Consortium, 37 * see ``http://www.vix.com/isc''. To learn more about Vixie 38 * Enterprises, see ``http://www.vix.com''. 39 */ 40 41 #include "dhcpd.h" 42 #include "sync.h" 43 44 int outstanding_pings; 45 46 static char dhcp_message[256]; 47 48 void 49 dhcp(struct packet *packet) 50 { 51 if (!locate_network(packet) && packet->packet_type != DHCPREQUEST) 52 return; 53 54 switch (packet->packet_type) { 55 case DHCPDISCOVER: 56 dhcpdiscover(packet); 57 break; 58 59 case DHCPREQUEST: 60 dhcprequest(packet); 61 break; 62 63 case DHCPRELEASE: 64 dhcprelease(packet); 65 break; 66 67 case DHCPDECLINE: 68 dhcpdecline(packet); 69 break; 70 71 case DHCPINFORM: 72 dhcpinform(packet); 73 break; 74 75 default: 76 break; 77 } 78 } 79 80 void 81 dhcpdiscover(struct packet *packet) 82 { 83 struct lease *lease = find_lease(packet, packet->shared_network, 0); 84 struct host_decl *hp; 85 86 note("DHCPDISCOVER from %s via %s", 87 print_hw_addr(packet->raw->htype, packet->raw->hlen, 88 packet->raw->chaddr), 89 packet->raw->giaddr.s_addr ? inet_ntoa(packet->raw->giaddr) : 90 packet->interface->name); 91 92 /* Sourceless packets don't make sense here. */ 93 if (!packet->shared_network) { 94 note("Packet from unknown subnet: %s", 95 inet_ntoa(packet->raw->giaddr)); 96 return; 97 } 98 99 /* If we didn't find a lease, try to allocate one... */ 100 if (!lease) { 101 lease = packet->shared_network->last_lease; 102 103 /* 104 * If there are no leases in that subnet that have 105 * expired, we have nothing to offer this client. 106 */ 107 if (!lease || lease->ends > cur_time) { 108 note("no free leases on subnet %s", 109 packet->shared_network->name); 110 return; 111 } 112 113 /* 114 * If we find an abandoned lease, take it, but print a 115 * warning message, so that if it continues to lose, 116 * the administrator will eventually investigate. 117 */ 118 if ((lease->flags & ABANDONED_LEASE)) { 119 struct lease *lp; 120 121 /* See if we can find an unabandoned lease first. */ 122 for (lp = lease; lp; lp = lp->prev) { 123 if (lp->ends > cur_time) 124 break; 125 if (!(lp->flags & ABANDONED_LEASE)) { 126 lease = lp; 127 break; 128 } 129 } 130 131 /* 132 * If we can't find an unabandoned lease, 133 * reclaim the abandoned lease. 134 */ 135 if ((lease->flags & ABANDONED_LEASE)) { 136 warning("Reclaiming abandoned IP address %s.", 137 piaddr(lease->ip_addr)); 138 lease->flags &= ~ABANDONED_LEASE; 139 140 pfmsg('L', lease); /* unabandon address */ 141 } 142 } 143 144 /* Try to find a host_decl that matches the client 145 identifier or hardware address on the packet, and 146 has no fixed IP address. If there is one, hang 147 it off the lease so that its option definitions 148 can be used. */ 149 if (((packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len != 0) && 150 ((hp = find_hosts_by_uid( 151 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data, 152 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len)) != NULL)) || 153 ((hp = find_hosts_by_haddr(packet->raw->htype, 154 packet->raw->chaddr, packet->raw->hlen)) != NULL)) { 155 for (; hp; hp = hp->n_ipaddr) { 156 if (!hp->fixed_addr) { 157 lease->host = hp; 158 break; 159 } 160 } 161 } else 162 lease->host = NULL; 163 } 164 165 /* If this subnet won't boot unknown clients, ignore the 166 request. */ 167 if (!lease->host && 168 !lease->subnet->group->boot_unknown_clients) { 169 note("Ignoring unknown client %s", 170 print_hw_addr(packet->raw->htype, packet->raw->hlen, 171 packet->raw->chaddr)); 172 } else if (lease->host && !lease->host->group->allow_booting) { 173 note("Declining to boot client %s", 174 lease->host->name ? lease->host->name : 175 print_hw_addr(packet->raw->htype, packet->raw->hlen, 176 packet->raw->chaddr)); 177 } else 178 ack_lease(packet, lease, DHCPOFFER, cur_time + 120); 179 } 180 181 void 182 dhcprequest(struct packet *packet) 183 { 184 struct lease *lease; 185 struct iaddr cip; 186 struct subnet *subnet; 187 int ours = 0; 188 189 cip.len = 4; 190 if (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len) 191 memcpy(cip.iabuf, 192 packet->options[DHO_DHCP_REQUESTED_ADDRESS].data, 4); 193 else 194 memcpy(cip.iabuf, &packet->raw->ciaddr.s_addr, 4); 195 subnet = find_subnet(cip); 196 197 /* Find the lease that matches the address requested by the client. */ 198 199 if (subnet) 200 lease = find_lease(packet, subnet->shared_network, &ours); 201 else 202 lease = NULL; 203 204 note("DHCPREQUEST for %s from %s via %s", piaddr(cip), 205 print_hw_addr(packet->raw->htype, packet->raw->hlen, 206 packet->raw->chaddr), 207 packet->raw->giaddr.s_addr ? inet_ntoa(packet->raw->giaddr) : 208 packet->interface->name); 209 210 /* If a client on a given network REQUESTs a lease on an 211 * address on a different network, NAK it. If the Requested 212 * Address option was used, the protocol says that it must 213 * have been broadcast, so we can trust the source network 214 * information. 215 * 216 * If ciaddr was specified and Requested Address was not, then 217 * we really only know for sure what network a packet came from 218 * if it came through a BOOTP gateway - if it came through an 219 * IP router, we'll just have to assume that it's cool. 220 * 221 * If we don't think we know where the packet came from, it 222 * came through a gateway from an unknown network, so it's not 223 * from a RENEWING client. If we recognize the network it 224 * *thinks* it's on, we can NAK it even though we don't 225 * recognize the network it's *actually* on; otherwise we just 226 * have to ignore it. 227 * 228 * We don't currently try to take advantage of access to the 229 * raw packet, because it's not available on all platforms. 230 * So a packet that was unicast to us through a router from a 231 * RENEWING client is going to look exactly like a packet that 232 * was broadcast to us from an INIT-REBOOT client. 233 * 234 * Since we can't tell the difference between these two kinds 235 * of packets, if the packet appears to have come in off the 236 * local wire, we have to treat it as if it's a RENEWING 237 * client. This means that we can't NAK a RENEWING client on 238 * the local wire that has a bogus address. The good news is 239 * that we won't ACK it either, so it should revert to INIT 240 * state and send us a DHCPDISCOVER, which we *can* work with. 241 * 242 * Because we can't detect that a RENEWING client is on the 243 * wrong wire, it's going to sit there trying to renew until 244 * it gets to the REBIND state, when we *can* NAK it because 245 * the packet will get to us through a BOOTP gateway. We 246 * shouldn't actually see DHCPREQUEST packets from RENEWING 247 * clients on the wrong wire anyway, since their idea of their 248 * local router will be wrong. In any case, the protocol 249 * doesn't really allow us to NAK a DHCPREQUEST from a 250 * RENEWING client, so we can punt on this issue. 251 */ 252 if (!packet->shared_network || 253 (packet->raw->ciaddr.s_addr && packet->raw->giaddr.s_addr) || 254 (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len && 255 !packet->raw->ciaddr.s_addr)) { 256 257 /* 258 * If we don't know where it came from but we do know 259 * where it claims to have come from, it didn't come 260 * from there. Fry it. 261 */ 262 if (!packet->shared_network) { 263 if (subnet && 264 subnet->shared_network->group->authoritative) { 265 nak_lease(packet, &cip); 266 return; 267 } 268 /* Otherwise, ignore it. */ 269 return; 270 } 271 272 /* 273 * If we do know where it came from and it asked for an 274 * address that is not on that shared network, nak it. 275 */ 276 subnet = find_grouped_subnet(packet->shared_network, cip); 277 if (!subnet) { 278 if (packet->shared_network->group->authoritative) 279 nak_lease(packet, &cip); 280 return; 281 } 282 } 283 284 /* 285 * If we found a lease for the client but it's not the one the 286 * client asked for, don't send it - some other server probably 287 * made the cut. 288 */ 289 if (lease && !addr_eq(lease->ip_addr, cip)) { 290 /* 291 * If we found the address the client asked for, but 292 * it wasn't what got picked, the lease belongs to us, 293 * so we should NAK it. 294 */ 295 if (ours) 296 nak_lease(packet, &cip); 297 return; 298 } 299 300 /* 301 * If the address the client asked for is ours, but it wasn't 302 * available for the client, NAK it. 303 */ 304 if (!lease && ours) { 305 nak_lease(packet, &cip); 306 return; 307 } 308 309 /* If we're not allowed to serve this client anymore, don't. */ 310 if (lease && !lease->host && 311 !lease->subnet->group->boot_unknown_clients) { 312 note("Ignoring unknown client %s", 313 print_hw_addr(packet->raw->htype, packet->raw->hlen, 314 packet->raw->chaddr)); 315 return; 316 } else if (lease && lease->host && !lease->host->group->allow_booting) { 317 note("Declining to renew client %s", 318 lease->host->name ? lease->host->name : 319 print_hw_addr(packet->raw->htype, packet->raw->hlen, 320 packet->raw->chaddr)); 321 return; 322 } 323 324 /* 325 * If we own the lease that the client is asking for, 326 * and it's already been assigned to the client, ack it. 327 */ 328 if (lease && 329 ((lease->uid_len && lease->uid_len == 330 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len && 331 !memcmp(packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data, 332 lease->uid, lease->uid_len)) || 333 (lease->hardware_addr.hlen == packet->raw->hlen && 334 lease->hardware_addr.htype == packet->raw->htype && 335 !memcmp(lease->hardware_addr.haddr, packet->raw->chaddr, 336 packet->raw->hlen)))) { 337 ack_lease(packet, lease, DHCPACK, 0); 338 sync_lease(lease); 339 return; 340 } 341 342 /* 343 * At this point, the client has requested a lease, and it's 344 * available, but it wasn't assigned to the client, which 345 * means that the client probably hasn't gone through the 346 * DHCPDISCOVER part of the protocol. We are within our 347 * rights to send a DHCPNAK. We can also send a DHCPACK. 348 * The thing we probably should not do is to remain silent. 349 * For now, we'll just assign the lease to the client anyway. 350 */ 351 if (lease) { 352 ack_lease(packet, lease, DHCPACK, 0); 353 sync_lease(lease); 354 } 355 } 356 357 void 358 dhcprelease(struct packet *packet) 359 { 360 struct lease *lease; 361 struct iaddr cip; 362 int i; 363 364 /* 365 * DHCPRELEASE must not specify address in requested-address 366 * option, but old protocol specs weren't explicit about this, 367 * so let it go. 368 */ 369 if (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len) { 370 note("DHCPRELEASE from %s specified requested-address.", 371 print_hw_addr(packet->raw->htype, packet->raw->hlen, 372 packet->raw->chaddr)); 373 } 374 375 i = DHO_DHCP_CLIENT_IDENTIFIER; 376 if (packet->options[i].len) { 377 lease = find_lease_by_uid(packet->options[i].data, 378 packet->options[i].len); 379 380 /* 381 * See if we can find a lease that matches the 382 * IP address the client is claiming. 383 */ 384 for (; lease; lease = lease->n_uid) { 385 if (!memcmp(&packet->raw->ciaddr, 386 lease->ip_addr.iabuf, 4)) { 387 break; 388 } 389 } 390 } else { 391 /* 392 * The client is supposed to pass a valid client-identifier, 393 * but the spec on this has changed historically, so try the 394 * IP address in ciaddr if the client-identifier fails. 395 */ 396 cip.len = 4; 397 memcpy(cip.iabuf, &packet->raw->ciaddr, 4); 398 lease = find_lease_by_ip_addr(cip); 399 } 400 401 note("DHCPRELEASE of %s from %s via %s (%sfound)", 402 inet_ntoa(packet->raw->ciaddr), 403 print_hw_addr(packet->raw->htype, packet->raw->hlen, 404 packet->raw->chaddr), 405 packet->raw->giaddr.s_addr ? inet_ntoa(packet->raw->giaddr) : 406 packet->interface->name, 407 lease ? "" : "not "); 408 409 /* If we're already acking this lease, don't do it again. */ 410 if (lease && lease->state) { 411 note("DHCPRELEASE already acking lease %s", 412 piaddr(lease->ip_addr)); 413 return; 414 } 415 416 /* If we found a lease, release it. */ 417 if (lease && lease->ends > cur_time) { 418 /* 419 * First, we ping this lease to see if it's still 420 * there. if it is, we don't release it. This avoids 421 * the problem of spoofed releases being used to liberate 422 * addresses from the server. 423 */ 424 if (!lease->releasing) { 425 note("DHCPRELEASE of %s from %s via %s (found)", 426 inet_ntoa(packet->raw->ciaddr), 427 print_hw_addr(packet->raw->htype, 428 packet->raw->hlen, packet->raw->chaddr), 429 packet->raw->giaddr.s_addr ? 430 inet_ntoa(packet->raw->giaddr) : 431 packet->interface->name); 432 433 lease->releasing = 1; 434 add_timeout(cur_time + 1, lease_ping_timeout, lease); 435 icmp_echorequest(&(lease->ip_addr)); 436 ++outstanding_pings; 437 } else { 438 note("DHCPRELEASE of %s from %s via %s ignored " 439 "(release already pending)", 440 inet_ntoa(packet->raw->ciaddr), 441 print_hw_addr(packet->raw->htype, 442 packet->raw->hlen, packet->raw->chaddr), 443 packet->raw->giaddr.s_addr ? 444 inet_ntoa(packet->raw->giaddr) : 445 packet->interface->name); 446 } 447 } else { 448 note("DHCPRELEASE of %s from %s via %s for nonexistent lease", 449 inet_ntoa(packet->raw->ciaddr), 450 print_hw_addr(packet->raw->htype, packet->raw->hlen, 451 packet->raw->chaddr), 452 packet->raw->giaddr.s_addr ? 453 inet_ntoa(packet->raw->giaddr) : 454 packet->interface->name); 455 } 456 } 457 458 void 459 dhcpdecline(struct packet *packet) 460 { 461 struct lease *lease; 462 struct iaddr cip; 463 464 /* DHCPDECLINE must specify address. */ 465 if (!packet->options[DHO_DHCP_REQUESTED_ADDRESS].len) 466 return; 467 468 cip.len = 4; 469 memcpy(cip.iabuf, 470 packet->options[DHO_DHCP_REQUESTED_ADDRESS].data, 4); 471 lease = find_lease_by_ip_addr(cip); 472 473 note("DHCPDECLINE on %s from %s via %s", 474 piaddr(cip), print_hw_addr(packet->raw->htype, 475 packet->raw->hlen, packet->raw->chaddr), 476 packet->raw->giaddr.s_addr ? inet_ntoa(packet->raw->giaddr) : 477 packet->interface->name); 478 479 /* If we're already acking this lease, don't do it again. */ 480 if (lease && lease->state) { 481 note("DHCPDECLINE already acking lease %s", 482 piaddr(lease->ip_addr)); 483 return; 484 } 485 486 /* If we found a lease, mark it as unusable and complain. */ 487 if (lease) 488 abandon_lease(lease, "declined."); 489 } 490 491 void 492 dhcpinform(struct packet *packet) 493 { 494 struct lease *lease; 495 struct iaddr cip; 496 struct subnet *subnet; 497 498 /* 499 * ciaddr should be set to client's IP address but 500 * not all clients are standards compliant. 501 */ 502 cip.len = 4; 503 if (packet->raw->ciaddr.s_addr) 504 memcpy(cip.iabuf, &packet->raw->ciaddr.s_addr, 4); 505 else 506 memcpy(cip.iabuf, &packet->client_addr.iabuf, 4); 507 508 note("DHCPINFORM from %s", piaddr(cip)); 509 510 /* Find the lease that matches the address requested by the client. */ 511 subnet = find_subnet(cip); 512 if (!subnet) 513 return; 514 515 /* Sourceless packets don't make sense here. */ 516 if (!subnet->shared_network) { 517 note("Packet from unknown subnet: %s", 518 inet_ntoa(packet->raw->giaddr)); 519 return; 520 } 521 522 lease = find_lease(packet, subnet->shared_network, 0); 523 if (!lease) { 524 note("DHCPINFORM packet from %s but no lease present", 525 print_hw_addr(packet->raw->htype, packet->raw->hlen, 526 packet->raw->chaddr)); 527 return; 528 } 529 530 /* If this subnet won't boot unknown clients, ignore the 531 request. */ 532 if (!lease->host && 533 !lease->subnet->group->boot_unknown_clients) { 534 note("Ignoring unknown client %s", 535 print_hw_addr(packet->raw->htype, packet->raw->hlen, 536 packet->raw->chaddr)); 537 } else if (lease->host && !lease->host->group->allow_booting) { 538 note("Declining to boot client %s", 539 lease->host->name ? lease->host->name : 540 print_hw_addr(packet->raw->htype, packet->raw->hlen, 541 packet->raw->chaddr)); 542 } else 543 ack_lease(packet, lease, DHCPACK, 0); 544 } 545 546 void 547 nak_lease(struct packet *packet, struct iaddr *cip) 548 { 549 struct sockaddr_in to; 550 struct in_addr from; 551 int result, i; 552 struct dhcp_packet raw; 553 unsigned char nak = DHCPNAK; 554 struct packet outgoing; 555 struct tree_cache *options[256], dhcpnak_tree, dhcpmsg_tree; 556 557 memset(options, 0, sizeof options); 558 memset(&outgoing, 0, sizeof outgoing); 559 memset(&raw, 0, sizeof raw); 560 outgoing.raw = &raw; 561 562 /* Set DHCP_MESSAGE_TYPE to DHCPNAK */ 563 options[DHO_DHCP_MESSAGE_TYPE] = &dhcpnak_tree; 564 options[DHO_DHCP_MESSAGE_TYPE]->value = &nak; 565 options[DHO_DHCP_MESSAGE_TYPE]->len = sizeof nak; 566 options[DHO_DHCP_MESSAGE_TYPE]->buf_size = sizeof nak; 567 options[DHO_DHCP_MESSAGE_TYPE]->timeout = -1; 568 options[DHO_DHCP_MESSAGE_TYPE]->tree = NULL; 569 570 /* Set DHCP_MESSAGE to whatever the message is */ 571 options[DHO_DHCP_MESSAGE] = &dhcpmsg_tree; 572 options[DHO_DHCP_MESSAGE]->value = (unsigned char *)dhcp_message; 573 options[DHO_DHCP_MESSAGE]->len = strlen(dhcp_message); 574 options[DHO_DHCP_MESSAGE]->buf_size = strlen(dhcp_message); 575 options[DHO_DHCP_MESSAGE]->timeout = -1; 576 options[DHO_DHCP_MESSAGE]->tree = NULL; 577 578 /* Do not use the client's requested parameter list. */ 579 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 580 if (packet->options[i].data) { 581 packet->options[i].len = 0; 582 dfree(packet->options[i].data, "nak_lease"); 583 packet->options[i].data = NULL; 584 } 585 586 /* Set up the option buffer... */ 587 outgoing.packet_length = cons_options(packet, outgoing.raw, 588 0, options, 0, 0, 0, NULL, 0); 589 590 /* memset(&raw.ciaddr, 0, sizeof raw.ciaddr);*/ 591 raw.siaddr = packet->interface->primary_address; 592 raw.giaddr = packet->raw->giaddr; 593 memcpy(raw.chaddr, packet->raw->chaddr, sizeof raw.chaddr); 594 raw.hlen = packet->raw->hlen; 595 raw.htype = packet->raw->htype; 596 raw.xid = packet->raw->xid; 597 raw.secs = packet->raw->secs; 598 raw.flags = packet->raw->flags | htons(BOOTP_BROADCAST); 599 raw.hops = packet->raw->hops; 600 raw.op = BOOTREPLY; 601 602 /* Report what we're sending... */ 603 note("DHCPNAK on %s to %s via %s", piaddr(*cip), 604 print_hw_addr(packet->raw->htype, packet->raw->hlen, 605 packet->raw->chaddr), packet->raw->giaddr.s_addr ? 606 inet_ntoa(packet->raw->giaddr) : packet->interface->name); 607 608 /* Set up the common stuff... */ 609 memset(&to, 0, sizeof to); 610 to.sin_family = AF_INET; 611 to.sin_len = sizeof to; 612 613 from = packet->interface->primary_address; 614 615 /* Make sure that the packet is at least as big as a BOOTP packet. */ 616 if (outgoing.packet_length < BOOTP_MIN_LEN) 617 outgoing.packet_length = BOOTP_MIN_LEN; 618 619 /* 620 * If this was gatewayed, send it back to the gateway. 621 * Otherwise, broadcast it on the local network. 622 */ 623 if (raw.giaddr.s_addr) { 624 to.sin_addr = raw.giaddr; 625 to.sin_port = server_port; 626 627 result = send_packet(packet->interface, &raw, 628 outgoing.packet_length, from, &to, packet->haddr); 629 if (result == -1) 630 warning("send_fallback: %m"); 631 return; 632 } else { 633 to.sin_addr.s_addr = htonl(INADDR_BROADCAST); 634 to.sin_port = client_port; 635 } 636 637 errno = 0; 638 result = send_packet(packet->interface, &raw, 639 outgoing.packet_length, from, &to, NULL); 640 } 641 642 void 643 ack_lease(struct packet *packet, struct lease *lease, unsigned int offer, 644 time_t when) 645 { 646 struct lease lt; 647 struct lease_state *state; 648 time_t lease_time, offered_lease_time, max_lease_time, default_lease_time; 649 struct class *vendor_class, *user_class; 650 int ulafdr, i; 651 652 /* If we're already acking this lease, don't do it again. */ 653 if (lease->state) { 654 if ((lease->flags & STATIC_LEASE) || 655 cur_time - lease->timestamp < 60) { 656 note("already acking lease %s", piaddr(lease->ip_addr)); 657 return; 658 } 659 free_lease_state(lease->state, "ACK timed out"); 660 lease->state = NULL; 661 } 662 663 if (packet->options[DHO_DHCP_CLASS_IDENTIFIER].len) { 664 vendor_class = find_class(0, 665 packet->options[DHO_DHCP_CLASS_IDENTIFIER].data, 666 packet->options[DHO_DHCP_CLASS_IDENTIFIER].len); 667 } else 668 vendor_class = NULL; 669 670 if (packet->options[DHO_DHCP_USER_CLASS_ID].len) { 671 user_class = find_class(1, 672 packet->options[DHO_DHCP_USER_CLASS_ID].data, 673 packet->options[DHO_DHCP_USER_CLASS_ID].len); 674 } else 675 user_class = NULL; 676 677 /* 678 * If there is not a specific host entry, and either the 679 * vendor class or user class (if they exist) deny booting, 680 * then bug out. 681 */ 682 if (!lease->host) { 683 if (vendor_class && !vendor_class->group->allow_booting) { 684 debug("Booting denied by vendor class"); 685 return; 686 } 687 688 if (user_class && !user_class->group->allow_booting) { 689 debug("Booting denied by user class"); 690 return; 691 } 692 } 693 694 /* Allocate a lease state structure... */ 695 state = new_lease_state("ack_lease"); 696 if (!state) 697 error("unable to allocate lease state!"); 698 memset(state, 0, sizeof *state); 699 state->got_requested_address = packet->got_requested_address; 700 state->shared_network = packet->interface->shared_network; 701 702 /* Remember if we got a server identifier option. */ 703 if (packet->options[DHO_DHCP_SERVER_IDENTIFIER].len) 704 state->got_server_identifier = 1; 705 706 /* Replace the old lease hostname with the new one, if it's changed. */ 707 if (packet->options[DHO_HOST_NAME].len && 708 lease->client_hostname && 709 (strlen(lease->client_hostname) == packet->options[DHO_HOST_NAME].len) && 710 !memcmp(lease->client_hostname, packet->options[DHO_HOST_NAME].data, 711 packet->options[DHO_HOST_NAME].len)) { 712 } else if (packet->options[DHO_HOST_NAME].len) { 713 if (lease->client_hostname) 714 free(lease->client_hostname); 715 lease->client_hostname = malloc( 716 packet->options[DHO_HOST_NAME].len + 1); 717 if (!lease->client_hostname) 718 error("no memory for client hostname.\n"); 719 memcpy(lease->client_hostname, 720 packet->options[DHO_HOST_NAME].data, 721 packet->options[DHO_HOST_NAME].len); 722 lease->client_hostname[packet->options[DHO_HOST_NAME].len] = 0; 723 } else if (lease->client_hostname) { 724 free(lease->client_hostname); 725 lease->client_hostname = 0; 726 } 727 728 /* 729 * Choose a filename; first from the host_decl, if any, then from 730 * the user class, then from the vendor class. 731 */ 732 if (lease->host && lease->host->group->filename) 733 strlcpy(state->filename, lease->host->group->filename, 734 sizeof state->filename); 735 else if (user_class && user_class->group->filename) 736 strlcpy(state->filename, user_class->group->filename, 737 sizeof state->filename); 738 else if (vendor_class && vendor_class->group->filename) 739 strlcpy(state->filename, vendor_class->group->filename, 740 sizeof state->filename); 741 else if (packet->raw->file[0]) 742 strlcpy(state->filename, packet->raw->file, 743 sizeof state->filename); 744 else if (lease->subnet->group->filename) 745 strlcpy(state->filename, lease->subnet->group->filename, 746 sizeof state->filename); 747 else 748 strlcpy(state->filename, "", sizeof state->filename); 749 750 /* Choose a server name as above. */ 751 if (lease->host && lease->host->group->server_name) 752 state->server_name = lease->host->group->server_name; 753 else if (user_class && user_class->group->server_name) 754 state->server_name = user_class->group->server_name; 755 else if (vendor_class && vendor_class->group->server_name) 756 state->server_name = vendor_class->group->server_name; 757 else if (lease->subnet->group->server_name) 758 state->server_name = lease->subnet->group->server_name; 759 else state->server_name = NULL; 760 761 /* 762 * At this point, we have a lease that we can offer the client. 763 * Now we construct a lease structure that contains what we want, 764 * and call supersede_lease to do the right thing with it. 765 */ 766 memset(<, 0, sizeof lt); 767 768 /* 769 * Use the ip address of the lease that we finally found in 770 * the database. 771 */ 772 lt.ip_addr = lease->ip_addr; 773 774 /* Start now. */ 775 lt.starts = cur_time; 776 777 /* Figure out maximum lease time. */ 778 if (lease->host && lease->host->group->max_lease_time) 779 max_lease_time = lease->host->group->max_lease_time; 780 else 781 max_lease_time = lease->subnet->group->max_lease_time; 782 783 /* Figure out default lease time. */ 784 if (lease->host && lease->host->group->default_lease_time) 785 default_lease_time = lease->host->group->default_lease_time; 786 else 787 default_lease_time = lease->subnet->group->default_lease_time; 788 789 /* 790 * Figure out how long a lease to assign. If this is a 791 * dynamic BOOTP lease, its duration must be infinite. 792 */ 793 if (offer) { 794 if (packet->options[DHO_DHCP_LEASE_TIME].len == 4) { 795 lease_time = getULong( 796 packet->options[DHO_DHCP_LEASE_TIME].data); 797 798 /* 799 * Don't let the client ask for a longer lease than 800 * is supported for this subnet or host. 801 * 802 * time_t is signed, so really large numbers come 803 * back as negative. Don't allow lease_time of 0, 804 * either. 805 */ 806 if (lease_time < 1 || lease_time > max_lease_time) 807 lease_time = max_lease_time; 808 } else 809 lease_time = default_lease_time; 810 811 state->offered_expiry = cur_time + lease_time; 812 if (when) 813 lt.ends = when; 814 else 815 lt.ends = state->offered_expiry; 816 } else { 817 if (lease->host && 818 lease->host->group->bootp_lease_length) 819 lt.ends = (cur_time + 820 lease->host->group->bootp_lease_length); 821 else if (lease->subnet->group->bootp_lease_length) 822 lt.ends = (cur_time + 823 lease->subnet->group->bootp_lease_length); 824 else if (lease->host && 825 lease->host->group->bootp_lease_cutoff) 826 lt.ends = lease->host->group->bootp_lease_cutoff; 827 else 828 lt.ends = lease->subnet->group->bootp_lease_cutoff; 829 state->offered_expiry = lt.ends; 830 lt.flags = BOOTP_LEASE; 831 } 832 833 /* Record the uid, if given... */ 834 i = DHO_DHCP_CLIENT_IDENTIFIER; 835 if (packet->options[i].len) { 836 if (packet->options[i].len <= sizeof lt.uid_buf) { 837 memcpy(lt.uid_buf, packet->options[i].data, 838 packet->options[i].len); 839 lt.uid = lt.uid_buf; 840 lt.uid_max = sizeof lt.uid_buf; 841 lt.uid_len = packet->options[i].len; 842 } else { 843 lt.uid_max = lt.uid_len = packet->options[i].len; 844 lt.uid = (unsigned char *)malloc(lt.uid_max); 845 if (!lt.uid) 846 error("can't allocate memory for large uid."); 847 memcpy(lt.uid, packet->options[i].data, lt.uid_len); 848 } 849 } 850 851 lt.host = lease->host; 852 lt.subnet = lease->subnet; 853 lt.shared_network = lease->shared_network; 854 855 /* Don't call supersede_lease on a mocked-up lease. */ 856 if (lease->flags & STATIC_LEASE) { 857 /* Copy the hardware address into the static lease 858 structure. */ 859 lease->hardware_addr.hlen = packet->raw->hlen; 860 lease->hardware_addr.htype = packet->raw->htype; 861 memcpy(lease->hardware_addr.haddr, packet->raw->chaddr, 862 sizeof packet->raw->chaddr); /* XXX */ 863 } else { 864 /* Record the hardware address, if given... */ 865 lt.hardware_addr.hlen = packet->raw->hlen; 866 lt.hardware_addr.htype = packet->raw->htype; 867 memcpy(lt.hardware_addr.haddr, packet->raw->chaddr, 868 sizeof packet->raw->chaddr); 869 870 /* Install the new information about this lease in the 871 database. If this is a DHCPACK or a dynamic BOOTREPLY 872 and we can't write the lease, don't ACK it (or BOOTREPLY 873 it) either. */ 874 875 if (!(supersede_lease(lease, <, !offer || offer == DHCPACK) || 876 (offer && offer != DHCPACK))) { 877 free_lease_state(state, "ack_lease: !supersede_lease"); 878 return; 879 } 880 } 881 882 /* Remember the interface on which the packet arrived. */ 883 state->ip = packet->interface; 884 885 /* Set a flag if this client is a lame Microsoft client that NUL 886 terminates string options and expects us to do likewise. */ 887 if (packet->options[DHO_HOST_NAME].data && 888 packet->options[DHO_HOST_NAME].data[ 889 packet->options[DHO_HOST_NAME].len - 1] == '\0') 890 lease->flags |= MS_NULL_TERMINATION; 891 else 892 lease->flags &= ~MS_NULL_TERMINATION; 893 894 /* Remember the giaddr, xid, secs, flags and hops. */ 895 state->giaddr = packet->raw->giaddr; 896 state->ciaddr = packet->raw->ciaddr; 897 state->xid = packet->raw->xid; 898 state->secs = packet->raw->secs; 899 state->bootp_flags = packet->raw->flags; 900 state->hops = packet->raw->hops; 901 state->offer = offer; 902 memcpy(&state->haddr, packet->haddr, sizeof state->haddr); 903 904 /* Figure out what options to send to the client: */ 905 906 /* Start out with the subnet options... */ 907 memcpy(state->options, lease->subnet->group->options, 908 sizeof state->options); 909 910 /* Vendor and user classes are only supported for DHCP clients. */ 911 if (state->offer) { 912 /* If we have a vendor class, install those options, 913 superseding any subnet options. */ 914 if (vendor_class) { 915 for (i = 0; i < 256; i++) 916 if (vendor_class->group->options[i]) 917 state->options[i] = 918 vendor_class->group->options[i]; 919 } 920 921 /* If we have a user class, install those options, 922 superseding any subnet and vendor class options. */ 923 if (user_class) { 924 for (i = 0; i < 256; i++) 925 if (user_class->group->options[i]) 926 state->options[i] = 927 user_class->group->options[i]; 928 } 929 930 } 931 932 /* If we have a host_decl structure, install the associated 933 options, superseding anything that's in the way. */ 934 if (lease->host) { 935 for (i = 0; i < 256; i++) 936 if (lease->host->group->options[i]) 937 state->options[i] = 938 lease->host->group->options[i]; 939 } 940 941 /* Get the Maximum Message Size option from the packet, if one 942 was sent. */ 943 i = DHO_DHCP_MAX_MESSAGE_SIZE; 944 if (packet->options[i].data && 945 packet->options[i].len == sizeof(u_int16_t)) 946 state->max_message_size = getUShort(packet->options[i].data); 947 /* Otherwise, if a maximum message size was specified, use that. */ 948 else if (state->options[i] && state->options[i]->value) 949 state->max_message_size = getUShort(state->options[i]->value); 950 951 /* Save the parameter request list if there is one. */ 952 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 953 if (packet->options[i].data) { 954 state->prl = dmalloc(packet->options[i].len, "ack_lease: prl"); 955 if (!state->prl) 956 warning("no memory for parameter request list"); 957 else { 958 memcpy(state->prl, packet->options[i].data, 959 packet->options[i].len); 960 state->prl_len = packet->options[i].len; 961 } 962 } 963 964 /* If we didn't get a hostname from an option somewhere, see if 965 we can get one from the lease. */ 966 i = DHO_HOST_NAME; 967 if (!state->options[i] && lease->hostname) { 968 state->options[i] = new_tree_cache("hostname"); 969 state->options[i]->flags = TC_TEMPORARY; 970 state->options[i]->value = (unsigned char *)lease->hostname; 971 state->options[i]->len = strlen(lease->hostname); 972 state->options[i]->buf_size = state->options[i]->len; 973 state->options[i]->timeout = -1; 974 state->options[i]->tree = NULL; 975 } 976 977 /* 978 * Now, if appropriate, put in DHCP-specific options that 979 * override those. 980 */ 981 if (state->offer) { 982 i = DHO_DHCP_MESSAGE_TYPE; 983 state->options[i] = new_tree_cache("message-type"); 984 state->options[i]->flags = TC_TEMPORARY; 985 state->options[i]->value = &state->offer; 986 state->options[i]->len = sizeof state->offer; 987 state->options[i]->buf_size = sizeof state->offer; 988 state->options[i]->timeout = -1; 989 state->options[i]->tree = NULL; 990 991 i = DHO_DHCP_SERVER_IDENTIFIER; 992 if (!state->options[i]) { 993 use_primary: 994 state->options[i] = new_tree_cache("server-id"); 995 state->options[i]->value = 996 (unsigned char *)&state->ip->primary_address; 997 state->options[i]->len = 998 sizeof state->ip->primary_address; 999 state->options[i]->buf_size = 1000 state->options[i]->len; 1001 state->options[i]->timeout = -1; 1002 state->options[i]->tree = NULL; 1003 state->from.len = sizeof state->ip->primary_address; 1004 memcpy(state->from.iabuf, &state->ip->primary_address, 1005 state->from.len); 1006 } else { 1007 /* Find the value of the server identifier... */ 1008 if (!tree_evaluate(state->options[i])) 1009 goto use_primary; 1010 if (!state->options[i]->value || 1011 (state->options[i]->len > sizeof state->from.iabuf)) 1012 goto use_primary; 1013 1014 state->from.len = state->options[i]->len; 1015 memcpy(state->from.iabuf, state->options[i]->value, 1016 state->from.len); 1017 } 1018 1019 /* Sanity check the lease time. */ 1020 if ((state->offered_expiry - cur_time) < 15) 1021 offered_lease_time = default_lease_time; 1022 else if (state->offered_expiry - cur_time > max_lease_time) 1023 offered_lease_time = max_lease_time; 1024 else 1025 offered_lease_time = 1026 state->offered_expiry - cur_time; 1027 1028 putULong((unsigned char *)&state->expiry, 1029 offered_lease_time); 1030 i = DHO_DHCP_LEASE_TIME; 1031 state->options[i] = new_tree_cache("lease-expiry"); 1032 state->options[i]->flags = TC_TEMPORARY; 1033 state->options[i]->value = (unsigned char *)&state->expiry; 1034 state->options[i]->len = sizeof state->expiry; 1035 state->options[i]->buf_size = sizeof state->expiry; 1036 state->options[i]->timeout = -1; 1037 state->options[i]->tree = NULL; 1038 1039 /* Renewal time is lease time * 0.5. */ 1040 offered_lease_time /= 2; 1041 putULong((unsigned char *)&state->renewal, 1042 offered_lease_time); 1043 i = DHO_DHCP_RENEWAL_TIME; 1044 state->options[i] = new_tree_cache("renewal-time"); 1045 state->options[i]->flags = TC_TEMPORARY; 1046 state->options[i]->value = 1047 (unsigned char *)&state->renewal; 1048 state->options[i]->len = sizeof state->renewal; 1049 state->options[i]->buf_size = sizeof state->renewal; 1050 state->options[i]->timeout = -1; 1051 state->options[i]->tree = NULL; 1052 1053 1054 /* Rebinding time is lease time * 0.875. */ 1055 offered_lease_time += (offered_lease_time / 2 + 1056 offered_lease_time / 4); 1057 putULong((unsigned char *)&state->rebind, 1058 offered_lease_time); 1059 i = DHO_DHCP_REBINDING_TIME; 1060 state->options[i] = new_tree_cache("rebind-time"); 1061 state->options[i]->flags = TC_TEMPORARY; 1062 state->options[i]->value = 1063 (unsigned char *)&state->rebind; 1064 state->options[i]->len = sizeof state->rebind; 1065 state->options[i]->buf_size = sizeof state->rebind; 1066 state->options[i]->timeout = -1; 1067 state->options[i]->tree = NULL; 1068 1069 /* If we used the vendor class the client specified, we 1070 have to return it. */ 1071 if (vendor_class) { 1072 i = DHO_DHCP_CLASS_IDENTIFIER; 1073 state->options[i] = 1074 new_tree_cache("class-identifier"); 1075 state->options[i]->flags = TC_TEMPORARY; 1076 state->options[i]->value = 1077 (unsigned char *)vendor_class->name; 1078 state->options[i]->len = 1079 strlen(vendor_class->name); 1080 state->options[i]->buf_size = 1081 state->options[i]->len; 1082 state->options[i]->timeout = -1; 1083 state->options[i]->tree = NULL; 1084 } 1085 1086 /* If we used the user class the client specified, we 1087 have to return it. */ 1088 if (user_class) { 1089 i = DHO_DHCP_USER_CLASS_ID; 1090 state->options[i] = new_tree_cache("user-class"); 1091 state->options[i]->flags = TC_TEMPORARY; 1092 state->options[i]->value = 1093 (unsigned char *)user_class->name; 1094 state->options[i]->len = 1095 strlen(user_class->name); 1096 state->options[i]->buf_size = 1097 state->options[i]->len; 1098 state->options[i]->timeout = -1; 1099 state->options[i]->tree = NULL; 1100 } 1101 } 1102 1103 /* Use the subnet mask from the subnet declaration if no other 1104 mask has been provided. */ 1105 i = DHO_SUBNET_MASK; 1106 if (!state->options[i]) { 1107 state->options[i] = new_tree_cache("subnet-mask"); 1108 state->options[i]->flags = TC_TEMPORARY; 1109 state->options[i]->value = 1110 lease->subnet->netmask.iabuf; 1111 state->options[i]->len = lease->subnet->netmask.len; 1112 state->options[i]->buf_size = 1113 lease->subnet->netmask.len; 1114 state->options[i]->timeout = -1; 1115 state->options[i]->tree = NULL; 1116 } 1117 1118 /* If so directed, use the leased IP address as the router address. 1119 This supposedly makes Win95 machines ARP for all IP addresses, 1120 so if the local router does proxy arp, you win. */ 1121 1122 ulafdr = 0; 1123 if (lease->host) { 1124 if (lease->host->group->use_lease_addr_for_default_route) 1125 ulafdr = 1; 1126 } else if (user_class) { 1127 if (user_class->group->use_lease_addr_for_default_route) 1128 ulafdr = 1; 1129 } else if (vendor_class) { 1130 if (vendor_class->group->use_lease_addr_for_default_route) 1131 ulafdr = 1; 1132 } else if (lease->subnet->group->use_lease_addr_for_default_route) 1133 ulafdr = 1; 1134 else 1135 ulafdr = 0; 1136 1137 i = DHO_ROUTERS; 1138 if (ulafdr && !state->options[i]) { 1139 state->options[i] = new_tree_cache("routers"); 1140 state->options[i]->flags = TC_TEMPORARY; 1141 state->options[i]->value = lease->ip_addr.iabuf; 1142 state->options[i]->len = lease->ip_addr.len; 1143 state->options[i]->buf_size = lease->ip_addr.len; 1144 state->options[i]->timeout = -1; 1145 state->options[i]->tree = NULL; 1146 } 1147 1148 lease->state = state; 1149 1150 /* If this is a DHCPOFFER, ping the lease address before actually 1151 sending the offer. */ 1152 if (offer == DHCPOFFER && !(lease->flags & STATIC_LEASE) && 1153 cur_time - lease->timestamp > 60) { 1154 lease->timestamp = cur_time; 1155 icmp_echorequest(&lease->ip_addr); 1156 add_timeout(cur_time + 1, lease_ping_timeout, lease); 1157 ++outstanding_pings; 1158 } else { 1159 lease->timestamp = cur_time; 1160 dhcp_reply(lease); 1161 } 1162 } 1163 1164 void 1165 dhcp_reply(struct lease *lease) 1166 { 1167 int bufs = 0, packet_length, i; 1168 struct dhcp_packet raw; 1169 struct sockaddr_in to; 1170 struct in_addr from; 1171 struct lease_state *state = lease->state; 1172 int nulltp, bootpp; 1173 u_int8_t *prl; 1174 int prl_len; 1175 1176 if (!state) 1177 error("dhcp_reply was supplied lease with no state!"); 1178 1179 /* Compose a response for the client... */ 1180 memset(&raw, 0, sizeof raw); 1181 1182 /* Copy in the filename if given; otherwise, flag the filename 1183 buffer as available for options. */ 1184 if (state->filename[0]) 1185 strlcpy(raw.file, state->filename, sizeof raw.file); 1186 else 1187 bufs |= 1; 1188 1189 /* Copy in the server name if given; otherwise, flag the 1190 server_name buffer as available for options. */ 1191 if (state->server_name) 1192 strlcpy(raw.sname, state->server_name, sizeof raw.sname); 1193 else 1194 bufs |= 2; /* XXX */ 1195 1196 memcpy(raw.chaddr, lease->hardware_addr.haddr, sizeof raw.chaddr); 1197 raw.hlen = lease->hardware_addr.hlen; 1198 raw.htype = lease->hardware_addr.htype; 1199 1200 /* See if this is a Microsoft client that NUL-terminates its 1201 strings and expects us to do likewise... */ 1202 if (lease->flags & MS_NULL_TERMINATION) 1203 nulltp = 1; 1204 else 1205 nulltp = 0; 1206 1207 /* See if this is a bootp client... */ 1208 if (state->offer) 1209 bootpp = 0; 1210 else 1211 bootpp = 1; 1212 1213 if (state->options[DHO_DHCP_PARAMETER_REQUEST_LIST] && 1214 state->options[DHO_DHCP_PARAMETER_REQUEST_LIST]->value) { 1215 prl = state->options[DHO_DHCP_PARAMETER_REQUEST_LIST]->value; 1216 prl_len = state->options[DHO_DHCP_PARAMETER_REQUEST_LIST]->len; 1217 } else if (state->prl) { 1218 prl = state->prl; 1219 prl_len = state->prl_len; 1220 } else { 1221 prl = NULL; 1222 prl_len = 0; 1223 } 1224 1225 /* Insert such options as will fit into the buffer. */ 1226 packet_length = cons_options(NULL, &raw, state->max_message_size, 1227 state->options, bufs, nulltp, bootpp, prl, prl_len); 1228 1229 /* Having done the cons_options(), we can release the tree_cache 1230 entries. */ 1231 for (i = 0; i < 256; i++) { 1232 if (state->options[i] && 1233 state->options[i]->flags & TC_TEMPORARY) 1234 free_tree_cache(state->options[i]); 1235 } 1236 1237 memcpy(&raw.ciaddr, &state->ciaddr, sizeof raw.ciaddr); 1238 memcpy(&raw.yiaddr, lease->ip_addr.iabuf, 4); 1239 1240 /* Figure out the address of the next server. */ 1241 if (lease->host && lease->host->group->next_server.len) 1242 memcpy(&raw.siaddr, lease->host->group->next_server.iabuf, 4); 1243 else if (lease->subnet->group->next_server.len) 1244 memcpy(&raw.siaddr, lease->subnet->group->next_server.iabuf, 4); 1245 else if (lease->subnet->interface_address.len) 1246 memcpy(&raw.siaddr, lease->subnet->interface_address.iabuf, 4); 1247 else 1248 raw.siaddr = state->ip->primary_address; 1249 1250 raw.giaddr = state->giaddr; 1251 1252 raw.xid = state->xid; 1253 raw.secs = state->secs; 1254 raw.flags = state->bootp_flags; 1255 raw.hops = state->hops; 1256 raw.op = BOOTREPLY; 1257 1258 /* Say what we're doing... */ 1259 note("%s on %s to %s via %s", 1260 (state->offer ? (state->offer == DHCPACK ? "DHCPACK" : "DHCPOFFER") : 1261 "BOOTREPLY"), 1262 piaddr(lease->ip_addr), 1263 print_hw_addr(lease->hardware_addr.htype, lease->hardware_addr.hlen, 1264 lease->hardware_addr.haddr), 1265 state->giaddr.s_addr ? inet_ntoa(state->giaddr) : state->ip->name); 1266 1267 memset(&to, 0, sizeof to); 1268 to.sin_family = AF_INET; 1269 #ifdef HAVE_SA_LEN 1270 to.sin_len = sizeof to; 1271 #endif 1272 1273 /* Make sure outgoing packets are at least as big 1274 as a BOOTP packet. */ 1275 if (packet_length < BOOTP_MIN_LEN) 1276 packet_length = BOOTP_MIN_LEN; 1277 1278 /* If this was gatewayed, send it back to the gateway... */ 1279 if (raw.giaddr.s_addr) { 1280 to.sin_addr = raw.giaddr; 1281 to.sin_port = server_port; 1282 1283 memcpy(&from, state->from.iabuf, sizeof from); 1284 1285 (void) send_packet(state->ip, &raw, 1286 packet_length, from, &to, &state->haddr); 1287 1288 free_lease_state(state, "dhcp_reply gateway"); 1289 lease->state = NULL; 1290 return; 1291 1292 /* If the client is RENEWING, unicast to the client using the 1293 regular IP stack. Some clients, particularly those that 1294 follow RFC1541, are buggy, and send both ciaddr and 1295 server-identifier. We deal with this situation by assuming 1296 that if we got both dhcp-server-identifier and ciaddr, and 1297 giaddr was not set, then the client is on the local 1298 network, and we can therefore unicast or broadcast to it 1299 successfully. A client in REQUESTING state on another 1300 network that's making this mistake will have set giaddr, 1301 and will therefore get a relayed response from the above 1302 code. */ 1303 } else if (raw.ciaddr.s_addr && 1304 !((state->got_server_identifier || 1305 (raw.flags & htons(BOOTP_BROADCAST))) && 1306 /* XXX This won't work if giaddr isn't zero, but it is: */ 1307 (state->shared_network == lease->shared_network)) && 1308 state->offer == DHCPACK) { 1309 to.sin_addr = raw.ciaddr; 1310 to.sin_port = client_port; 1311 1312 /* If it comes from a client that already knows its address 1313 and is not requesting a broadcast response, and we can 1314 unicast to a client without using the ARP protocol, sent it 1315 directly to that client. */ 1316 } else if (!(raw.flags & htons(BOOTP_BROADCAST))) { 1317 to.sin_addr = raw.yiaddr; 1318 to.sin_port = client_port; 1319 1320 /* Otherwise, broadcast it on the local network. */ 1321 } else { 1322 to.sin_addr.s_addr = htonl(INADDR_BROADCAST); 1323 to.sin_port = client_port; 1324 } 1325 1326 memcpy(&from, state->from.iabuf, sizeof from); 1327 1328 (void) send_packet(state->ip, &raw, packet_length, 1329 from, &to, &state->haddr); 1330 1331 free_lease_state(state, "dhcp_reply"); 1332 lease->state = NULL; 1333 } 1334 1335 struct lease * 1336 find_lease(struct packet *packet, struct shared_network *share, 1337 int *ours) 1338 { 1339 struct lease *uid_lease, *ip_lease, *hw_lease; 1340 struct lease *lease = NULL; 1341 struct iaddr cip; 1342 struct host_decl *hp, *host = NULL; 1343 struct lease *fixed_lease; 1344 1345 /* Figure out what IP address the client is requesting, if any. */ 1346 if (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len && 1347 packet->options[DHO_DHCP_REQUESTED_ADDRESS].len == 4) { 1348 packet->got_requested_address = 1; 1349 cip.len = 4; 1350 memcpy(cip.iabuf, 1351 packet->options[DHO_DHCP_REQUESTED_ADDRESS].data, 1352 cip.len); 1353 } else if (packet->raw->ciaddr.s_addr) { 1354 cip.len = 4; 1355 memcpy(cip.iabuf, &packet->raw->ciaddr, 4); 1356 } else 1357 cip.len = 0; 1358 1359 /* Try to find a host or lease that's been assigned to the 1360 specified unique client identifier. */ 1361 if (packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len) { 1362 /* First, try to find a fixed host entry for the specified 1363 client identifier... */ 1364 hp = find_hosts_by_uid( 1365 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data, 1366 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len); 1367 if (hp) { 1368 host = hp; 1369 fixed_lease = mockup_lease(packet, share, hp); 1370 uid_lease = NULL; 1371 } else { 1372 uid_lease = find_lease_by_uid( 1373 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data, 1374 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len); 1375 /* Find the lease matching this uid that's on the 1376 network the packet came from (if any). */ 1377 for (; uid_lease; uid_lease = uid_lease->n_uid) 1378 if (uid_lease->shared_network == share) 1379 break; 1380 fixed_lease = NULL; 1381 if (uid_lease && (uid_lease->flags & ABANDONED_LEASE)) 1382 uid_lease = NULL; 1383 } 1384 } else { 1385 uid_lease = NULL; 1386 fixed_lease = NULL; 1387 } 1388 1389 /* If we didn't find a fixed lease using the uid, try doing 1390 it with the hardware address... */ 1391 if (!fixed_lease) { 1392 hp = find_hosts_by_haddr(packet->raw->htype, 1393 packet->raw->chaddr, packet->raw->hlen); 1394 if (hp) { 1395 host = hp; /* Save it for later. */ 1396 fixed_lease = mockup_lease(packet, share, hp); 1397 } 1398 } 1399 1400 /* If fixed_lease is present but does not match the requested 1401 IP address, and this is a DHCPREQUEST, then we can't return 1402 any other lease, so we might as well return now. */ 1403 if (packet->packet_type == DHCPREQUEST && fixed_lease && 1404 (fixed_lease->ip_addr.len != cip.len || 1405 memcmp(fixed_lease->ip_addr.iabuf, cip.iabuf, cip.len))) { 1406 if (ours) 1407 *ours = 1; 1408 strlcpy(dhcp_message, "requested address is incorrect", 1409 sizeof(dhcp_message)); 1410 return NULL; 1411 } 1412 1413 /* Try to find a lease that's been attached to the client's 1414 hardware address... */ 1415 hw_lease = find_lease_by_hw_addr(packet->raw->chaddr, 1416 packet->raw->hlen); 1417 /* Find the lease that's on the network the packet came from 1418 (if any). */ 1419 for (; hw_lease; hw_lease = hw_lease->n_hw) { 1420 if (hw_lease->shared_network == share) { 1421 if ((hw_lease->flags & ABANDONED_LEASE)) 1422 continue; 1423 if (packet->packet_type) 1424 break; 1425 if (hw_lease->flags & 1426 (BOOTP_LEASE | DYNAMIC_BOOTP_OK)) 1427 break; 1428 } 1429 } 1430 1431 /* Try to find a lease that's been allocated to the client's 1432 IP address. */ 1433 if (cip.len) 1434 ip_lease = find_lease_by_ip_addr(cip); 1435 else 1436 ip_lease = NULL; 1437 1438 /* If ip_lease is valid at this point, set ours to one, so that 1439 even if we choose a different lease, we know that the address 1440 the client was requesting was ours, and thus we can NAK it. */ 1441 if (ip_lease && ours) 1442 *ours = 1; 1443 1444 /* If the requested IP address isn't on the network the packet 1445 came from, don't use it. Allow abandoned leases to be matched 1446 here - if the client is requesting it, there's a decent chance 1447 that it's because the lease database got trashed and a client 1448 that thought it had this lease answered an ARP or PING, causing the 1449 lease to be abandoned. If so, this request probably came from 1450 that client. */ 1451 if (ip_lease && (ip_lease->shared_network != share)) { 1452 ip_lease = NULL; 1453 strlcpy(dhcp_message, "requested address on bad subnet", 1454 sizeof(dhcp_message)); 1455 } 1456 1457 /* Toss ip_lease if it hasn't yet expired and isn't owned by the 1458 client. */ 1459 if (ip_lease && ip_lease->ends >= cur_time && ip_lease != uid_lease) { 1460 int i = DHO_DHCP_CLIENT_IDENTIFIER; 1461 1462 /* Make sure that ip_lease actually belongs to the client, 1463 and toss it if not. */ 1464 if ((ip_lease->uid_len && packet->options[i].data && 1465 ip_lease->uid_len == packet->options[i].len && 1466 !memcmp(packet->options[i].data, ip_lease->uid, 1467 ip_lease->uid_len)) || 1468 (!ip_lease->uid_len && 1469 ip_lease->hardware_addr.htype == packet->raw->htype && 1470 ip_lease->hardware_addr.hlen == packet->raw->hlen && 1471 !memcmp(ip_lease->hardware_addr.haddr, packet->raw->chaddr, 1472 ip_lease->hardware_addr.hlen))) { 1473 if (uid_lease) { 1474 if (uid_lease->ends > cur_time) { 1475 warning("client %s has duplicate leases on %s", 1476 print_hw_addr(packet->raw->htype, 1477 packet->raw->hlen, packet->raw->chaddr), 1478 ip_lease->shared_network->name); 1479 1480 if (uid_lease && !packet->raw->ciaddr.s_addr) 1481 release_lease(uid_lease); 1482 } 1483 uid_lease = ip_lease; 1484 } 1485 } else { 1486 strlcpy(dhcp_message, "requested address is not available", 1487 sizeof(dhcp_message)); 1488 ip_lease = NULL; 1489 } 1490 1491 /* If we get to here and fixed_lease is not null, that means 1492 that there are both a dynamic lease and a fixed-address 1493 declaration for the same IP address. */ 1494 if (packet->packet_type == DHCPREQUEST && fixed_lease) { 1495 fixed_lease = NULL; 1496 db_conflict: 1497 warning("Both dynamic and static leases present for %s.", 1498 piaddr(cip)); 1499 warning("Either remove host declaration %s or remove %s", 1500 (fixed_lease && fixed_lease->host ? 1501 (fixed_lease->host->name ? fixed_lease->host->name : 1502 piaddr(cip)) : piaddr(cip)), piaddr(cip)); 1503 warning("from the dynamic address pool for %s", 1504 share->name); 1505 if (fixed_lease) 1506 ip_lease = NULL; 1507 strlcpy(dhcp_message, "database conflict - call for help!", 1508 sizeof(dhcp_message)); 1509 } 1510 } 1511 1512 /* If we get to here with both fixed_lease and ip_lease not 1513 null, then we have a configuration file bug. */ 1514 if (packet->packet_type == DHCPREQUEST && fixed_lease && ip_lease) 1515 goto db_conflict; 1516 1517 /* Toss hw_lease if it hasn't yet expired and the uid doesn't 1518 match, except that if the hardware address matches and the 1519 client is now doing dynamic BOOTP (and thus hasn't provided 1520 a uid) we let the client get away with it. */ 1521 if (hw_lease && hw_lease->ends >= cur_time && hw_lease->uid && 1522 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len && 1523 hw_lease != uid_lease) 1524 hw_lease = NULL; 1525 1526 /* Toss extra pointers to the same lease... */ 1527 if (hw_lease == uid_lease) 1528 hw_lease = NULL; 1529 if (ip_lease == hw_lease) 1530 hw_lease = NULL; 1531 if (ip_lease == uid_lease) 1532 uid_lease = NULL; 1533 1534 /* If we've already eliminated the lease, it wasn't there to 1535 begin with. If we have come up with a matching lease, 1536 set the message to bad network in case we have to throw it out. */ 1537 if (!ip_lease) { 1538 strlcpy(dhcp_message, "requested address not available", 1539 sizeof(dhcp_message)); 1540 } 1541 1542 /* Now eliminate leases that are on the wrong network... */ 1543 if (ip_lease && share != ip_lease->shared_network) { 1544 if (packet->packet_type == DHCPREQUEST) 1545 release_lease(ip_lease); 1546 ip_lease = NULL; 1547 } 1548 if (uid_lease && share != uid_lease->shared_network) { 1549 if (packet->packet_type == DHCPREQUEST) 1550 release_lease(uid_lease); 1551 uid_lease = NULL; 1552 } 1553 if (hw_lease && share != hw_lease->shared_network) { 1554 if (packet->packet_type == DHCPREQUEST) 1555 release_lease(hw_lease); 1556 hw_lease = NULL; 1557 } 1558 1559 /* If this is a DHCPREQUEST, make sure the lease we're going to return 1560 matches the requested IP address. If it doesn't, don't return a 1561 lease at all. */ 1562 if (packet->packet_type == DHCPREQUEST && !ip_lease && !fixed_lease) 1563 return NULL; 1564 1565 /* At this point, if fixed_lease is nonzero, we can assign it to 1566 this client. */ 1567 if (fixed_lease) 1568 lease = fixed_lease; 1569 1570 /* If we got a lease that matched the ip address and don't have 1571 a better offer, use that; otherwise, release it. */ 1572 if (ip_lease) { 1573 if (lease) { 1574 if (packet->packet_type == DHCPREQUEST) 1575 release_lease(ip_lease); 1576 } else { 1577 lease = ip_lease; 1578 lease->host = NULL; 1579 } 1580 } 1581 1582 /* If we got a lease that matched the client identifier, we may want 1583 to use it, but if we already have a lease we like, we must free 1584 the lease that matched the client identifier. */ 1585 if (uid_lease) { 1586 if (lease) { 1587 if (packet->packet_type == DHCPREQUEST) 1588 release_lease(uid_lease); 1589 } else { 1590 lease = uid_lease; 1591 lease->host = NULL; 1592 } 1593 } 1594 1595 /* The lease that matched the hardware address is treated likewise. */ 1596 if (hw_lease) { 1597 if (lease) { 1598 if (packet->packet_type == DHCPREQUEST) 1599 release_lease(hw_lease); 1600 } else { 1601 lease = hw_lease; 1602 lease->host = NULL; 1603 } 1604 } 1605 1606 /* If we found a host_decl but no matching address, try to 1607 find a host_decl that has no address, and if there is one, 1608 hang it off the lease so that we can use the supplied 1609 options. */ 1610 if (lease && host && !lease->host) { 1611 for (; host; host = host->n_ipaddr) { 1612 if (!host->fixed_addr) { 1613 lease->host = host; 1614 break; 1615 } 1616 } 1617 } 1618 1619 /* If we find an abandoned lease, take it, but print a 1620 warning message, so that if it continues to lose, 1621 the administrator will eventually investigate. */ 1622 if (lease && (lease->flags & ABANDONED_LEASE)) { 1623 if (packet->packet_type == DHCPREQUEST) { 1624 warning("Reclaiming REQUESTed abandoned IP address %s.", 1625 piaddr(lease->ip_addr)); 1626 lease->flags &= ~ABANDONED_LEASE; 1627 } else 1628 lease = NULL; 1629 } 1630 return lease; 1631 } 1632 1633 /* 1634 * Search the provided host_decl structure list for an address that's on 1635 * the specified shared network. If one is found, mock up and return a 1636 * lease structure for it; otherwise return the null pointer. 1637 */ 1638 struct lease * 1639 mockup_lease(struct packet *packet, struct shared_network *share, 1640 struct host_decl *hp) 1641 { 1642 static struct lease mock; 1643 1644 mock.subnet = find_host_for_network(&hp, &mock.ip_addr, share); 1645 if (!mock.subnet) 1646 return (NULL); 1647 mock.next = mock.prev = NULL; 1648 mock.shared_network = mock.subnet->shared_network; 1649 mock.host = hp; 1650 1651 if (hp->group->options[DHO_DHCP_CLIENT_IDENTIFIER]) { 1652 mock.uid = hp->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->value; 1653 mock.uid_len = hp->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->len; 1654 } else { 1655 mock.uid = NULL; 1656 mock.uid_len = 0; 1657 } 1658 1659 mock.hardware_addr = hp->interface; 1660 mock.starts = mock.timestamp = mock.ends = MIN_TIME; 1661 mock.flags = STATIC_LEASE; 1662 return &mock; 1663 } 1664