00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "dhcpd.h"
00030 #include <errno.h>
00031 #include <limits.h>
00032 #include <sys/time.h>
00033 #include "trace.h"
00034 static void commit_leases_ackout(void *foo);
00035 static void maybe_return_agent_options(struct packet *packet,
00036 struct option_state *options);
00037
00038 int outstanding_pings;
00039
00040 struct leasequeue *ackqueue_head, *ackqueue_tail;
00041 static struct leasequeue *free_ackqueue;
00042 static struct timeval max_fsync;
00043
00044 int outstanding_acks;
00045 int max_outstanding_acks = DEFAULT_DELAYED_ACK;
00046 int max_ack_delay_secs = DEFAULT_ACK_DELAY_SECS;
00047 int max_ack_delay_usecs = DEFAULT_ACK_DELAY_USECS;
00048 int min_ack_delay_usecs = DEFAULT_MIN_ACK_DELAY_USECS;
00049
00050 static char dhcp_message [256];
00051 static int site_code_min;
00052
00053 static int find_min_site_code(struct universe *);
00054 static isc_result_t lowest_site_code(const void *, unsigned, void *);
00055
00056 static const char *dhcp_type_names [] = {
00057 "DHCPDISCOVER",
00058 "DHCPOFFER",
00059 "DHCPREQUEST",
00060 "DHCPDECLINE",
00061 "DHCPACK",
00062 "DHCPNAK",
00063 "DHCPRELEASE",
00064 "DHCPINFORM",
00065 "type 9",
00066 "DHCPLEASEQUERY",
00067 "DHCPLEASEUNASSIGNED",
00068 "DHCPLEASEUNKNOWN",
00069 "DHCPLEASEACTIVE"
00070 };
00071 const int dhcp_type_name_max = ((sizeof dhcp_type_names) / sizeof (char *));
00072
00073 #if defined (TRACING)
00074 # define send_packet trace_packet_send
00075 #endif
00076
00077 char *print_client_identifier_from_packet (packet)
00078 struct packet *packet;
00079 {
00080 struct option_cache *oc;
00081 struct data_string client_identifier;
00082 char *ci;
00083
00084 memset (&client_identifier, 0, sizeof client_identifier);
00085
00086 oc = lookup_option (&dhcp_universe, packet -> options,
00087 DHO_DHCP_CLIENT_IDENTIFIER);
00088 if (oc &&
00089 evaluate_option_cache (&client_identifier,
00090 packet, (struct lease *)0,
00091 (struct client_state *)0,
00092 packet -> options,
00093 (struct option_state *)0,
00094 &global_scope, oc, MDL)) {
00095 ci = print_hw_addr (HTYPE_INFINIBAND, client_identifier.len, client_identifier.data);
00096 data_string_forget (&client_identifier, MDL);
00097 return ci;
00098 } else
00099 return "\"no client id\"";
00100 }
00101
00102 char *print_hw_addr_or_client_id (packet)
00103 struct packet *packet;
00104 {
00105 if (packet -> raw -> htype == HTYPE_INFINIBAND)
00106 return print_client_identifier_from_packet (packet);
00107 else
00108 return print_hw_addr (packet -> raw -> htype,
00109 packet -> raw -> hlen,
00110 packet -> raw -> chaddr);
00111 }
00112
00113 void
00114 dhcp (struct packet *packet) {
00115 int ms_nulltp = 0;
00116 struct option_cache *oc;
00117 struct lease *lease = NULL;
00118 const char *errmsg;
00119 struct data_string data;
00120
00121 if (!locate_network(packet) &&
00122 packet->packet_type != DHCPREQUEST &&
00123 packet->packet_type != DHCPINFORM &&
00124 packet->packet_type != DHCPLEASEQUERY) {
00125 const char *s;
00126 char typebuf[32];
00127 errmsg = "unknown network segment";
00128 bad_packet:
00129
00130 if (packet->packet_type > 0 &&
00131 packet->packet_type <= dhcp_type_name_max) {
00132 s = dhcp_type_names[packet->packet_type - 1];
00133 } else {
00134
00135 sprintf(typebuf, "type %d", packet->packet_type);
00136 s = typebuf;
00137 }
00138
00139 log_info("%s from %s via %s: %s", s,
00140 (packet->raw->htype
00141 ? print_hw_addr_or_client_id(packet)
00142 : "<no identifier>"),
00143 packet->raw->giaddr.s_addr
00144 ? inet_ntoa(packet->raw->giaddr)
00145 : packet->interface->name, errmsg);
00146 goto out;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 if (packet->packet_type == DHCPREQUEST &&
00172 packet->raw->ciaddr.s_addr && !packet->raw->giaddr.s_addr &&
00173 (packet->options->universe_count <= agent_universe.index ||
00174 packet->options->universes[agent_universe.index] == NULL))
00175 {
00176 struct iaddr cip;
00177
00178 cip.len = sizeof packet -> raw -> ciaddr;
00179 memcpy (cip.iabuf, &packet -> raw -> ciaddr,
00180 sizeof packet -> raw -> ciaddr);
00181 if (!find_lease_by_ip_addr (&lease, cip, MDL))
00182 goto nolease;
00183
00184
00185
00186 if (!lease -> agent_options)
00187 goto nolease;
00188
00189
00190
00191
00192 if (lease -> ends < cur_time)
00193 goto nolease;
00194
00195 if (lease -> uid_len) {
00196 oc = lookup_option (&dhcp_universe, packet -> options,
00197 DHO_DHCP_CLIENT_IDENTIFIER);
00198 if (!oc)
00199 goto nolease;
00200
00201 memset (&data, 0, sizeof data);
00202 if (!evaluate_option_cache (&data,
00203 packet, (struct lease *)0,
00204 (struct client_state *)0,
00205 packet -> options,
00206 (struct option_state *)0,
00207 &global_scope, oc, MDL))
00208 goto nolease;
00209 if (lease -> uid_len != data.len ||
00210 memcmp (lease -> uid, data.data, data.len)) {
00211 data_string_forget (&data, MDL);
00212 goto nolease;
00213 }
00214 data_string_forget (&data, MDL);
00215 } else
00216 if ((lease -> hardware_addr.hbuf [0] !=
00217 packet -> raw -> htype) ||
00218 (lease -> hardware_addr.hlen - 1 !=
00219 packet -> raw -> hlen) ||
00220 memcmp (&lease -> hardware_addr.hbuf [1],
00221 packet -> raw -> chaddr,
00222 packet -> raw -> hlen))
00223 goto nolease;
00224
00225
00226 option_chain_head_reference ((struct option_chain_head **)
00227 &(packet -> options -> universes
00228 [agent_universe.index]),
00229 lease -> agent_options, MDL);
00230
00231 if (packet->options->universe_count <= agent_universe.index)
00232 packet->options->universe_count =
00233 agent_universe.index + 1;
00234
00235 packet->agent_options_stashed = ISC_TRUE;
00236 }
00237 nolease:
00238
00239
00240
00241
00242 if ((oc = lookup_option (&dhcp_universe, packet -> options,
00243 DHO_HOST_NAME))) {
00244 if (!oc -> expression)
00245 ms_nulltp = oc->flags & OPTION_HAD_NULLS;
00246 }
00247
00248
00249 classify_client (packet);
00250
00251 switch (packet -> packet_type) {
00252 case DHCPDISCOVER:
00253 dhcpdiscover (packet, ms_nulltp);
00254 break;
00255
00256 case DHCPREQUEST:
00257 dhcprequest (packet, ms_nulltp, lease);
00258 break;
00259
00260 case DHCPRELEASE:
00261 dhcprelease (packet, ms_nulltp);
00262 break;
00263
00264 case DHCPDECLINE:
00265 dhcpdecline (packet, ms_nulltp);
00266 break;
00267
00268 case DHCPINFORM:
00269 dhcpinform (packet, ms_nulltp);
00270 break;
00271
00272 case DHCPLEASEQUERY:
00273 dhcpleasequery(packet, ms_nulltp);
00274 break;
00275
00276 case DHCPACK:
00277 case DHCPOFFER:
00278 case DHCPNAK:
00279 case DHCPLEASEUNASSIGNED:
00280 case DHCPLEASEUNKNOWN:
00281 case DHCPLEASEACTIVE:
00282 break;
00283
00284 default:
00285 errmsg = "unknown packet type";
00286 goto bad_packet;
00287 }
00288 out:
00289 if (lease)
00290 lease_dereference (&lease, MDL);
00291 }
00292
00293 void dhcpdiscover (packet, ms_nulltp)
00294 struct packet *packet;
00295 int ms_nulltp;
00296 {
00297 struct lease *lease = (struct lease *)0;
00298 char msgbuf [1024];
00299 TIME when;
00300 const char *s;
00301 int peer_has_leases = 0;
00302 #if defined (FAILOVER_PROTOCOL)
00303 dhcp_failover_state_t *peer;
00304 #endif
00305
00306 TRACE(DHCPD_DISCOVER_START());
00307
00308 find_lease (&lease, packet, packet -> shared_network,
00309 0, &peer_has_leases, (struct lease *)0, MDL);
00310
00311 if (lease && lease -> client_hostname) {
00312 if ((strlen (lease -> client_hostname) <= 64) &&
00313 db_printable((unsigned char *)lease->client_hostname))
00314 s = lease -> client_hostname;
00315 else
00316 s = "Hostname Unsuitable for Printing";
00317 } else
00318 s = (char *)0;
00319
00320
00321
00322
00323 snprintf (msgbuf, sizeof msgbuf, "DHCPDISCOVER from %s %s%s%svia %s",
00324 (packet -> raw -> htype
00325 ? print_hw_addr_or_client_id (packet)
00326 : (lease
00327 ? print_hex_1(lease->uid_len, lease->uid, 60)
00328 : "<no identifier>")),
00329 s ? "(" : "", s ? s : "", s ? ") " : "",
00330 packet -> raw -> giaddr.s_addr
00331 ? inet_ntoa (packet -> raw -> giaddr)
00332 : packet -> interface -> name);
00333
00334
00335 if (!packet -> shared_network) {
00336 log_info ("Packet from unknown subnet: %s",
00337 inet_ntoa (packet -> raw -> giaddr));
00338 goto out;
00339 }
00340
00341 #if defined (FAILOVER_PROTOCOL)
00342 if (lease && lease -> pool && lease -> pool -> failover_peer) {
00343 peer = lease -> pool -> failover_peer;
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 if (lease->binding_state == FTS_ACTIVE ||
00357 lease->rewind_binding_state == FTS_ACTIVE ||
00358 lease_mine_to_reallocate(lease)) {
00359 ;
00360
00361
00362 } else {
00363 #if defined (DEBUG_FIND_LEASE)
00364 log_debug ("discarding %s - %s",
00365 piaddr (lease -> ip_addr),
00366 binding_state_print (lease -> binding_state));
00367 #endif
00368 lease_dereference (&lease, MDL);
00369 }
00370 }
00371 #endif
00372
00373
00374 if (!lease) {
00375 if (!allocate_lease (&lease, packet,
00376 packet -> shared_network -> pools,
00377 &peer_has_leases)) {
00378 if (peer_has_leases)
00379 log_error ("%s: peer holds all free leases",
00380 msgbuf);
00381 else
00382 log_error ("%s: network %s: no free leases",
00383 msgbuf,
00384 packet -> shared_network -> name);
00385 return;
00386 }
00387 }
00388
00389 #if defined (FAILOVER_PROTOCOL)
00390 if (lease && lease -> pool && lease -> pool -> failover_peer) {
00391 peer = lease -> pool -> failover_peer;
00392 if (peer -> service_state == not_responding ||
00393 peer -> service_state == service_startup) {
00394 log_info ("%s: not responding%s",
00395 msgbuf, peer -> nrr);
00396 goto out;
00397 }
00398 } else
00399 peer = (dhcp_failover_state_t *)0;
00400
00401
00402 if (peer && (peer -> service_state == cooperating) &&
00403 !load_balance_mine (packet, peer)) {
00404 if (peer_has_leases) {
00405 log_debug ("%s: load balance to peer %s",
00406 msgbuf, peer -> name);
00407 goto out;
00408 } else {
00409 log_debug ("%s: cancel load balance to peer %s - %s",
00410 msgbuf, peer -> name, "no free leases");
00411 }
00412 }
00413 #endif
00414
00415
00416 if (lease -> ends < cur_time && lease -> scope)
00417 binding_scope_dereference (&lease -> scope, MDL);
00418
00419
00420
00421 when = cur_time + 120;
00422 if (when < lease -> ends)
00423 when = lease -> ends;
00424
00425 ack_lease (packet, lease, DHCPOFFER, when, msgbuf, ms_nulltp,
00426 (struct host_decl *)0);
00427 out:
00428 if (lease)
00429 lease_dereference (&lease, MDL);
00430
00431 TRACE(DHCPD_DISCOVER_DONE());
00432 }
00433
00434 void dhcprequest (packet, ms_nulltp, ip_lease)
00435 struct packet *packet;
00436 int ms_nulltp;
00437 struct lease *ip_lease;
00438 {
00439 struct lease *lease;
00440 struct iaddr cip;
00441 struct iaddr sip;
00442 struct subnet *subnet;
00443 int ours = 0;
00444 struct option_cache *oc;
00445 struct data_string data;
00446 char msgbuf [1024];
00447 const char *s;
00448 char smbuf [19];
00449 #if defined (FAILOVER_PROTOCOL)
00450 dhcp_failover_state_t *peer;
00451 #endif
00452 int have_requested_addr = 0;
00453
00454 TRACE(DHCPD_REQUEST_START());
00455
00456 oc = lookup_option (&dhcp_universe, packet -> options,
00457 DHO_DHCP_REQUESTED_ADDRESS);
00458 memset (&data, 0, sizeof data);
00459 if (oc &&
00460 evaluate_option_cache (&data, packet, (struct lease *)0,
00461 (struct client_state *)0,
00462 packet -> options, (struct option_state *)0,
00463 &global_scope, oc, MDL)) {
00464 cip.len = 4;
00465 memcpy (cip.iabuf, data.data, 4);
00466 data_string_forget (&data, MDL);
00467 have_requested_addr = 1;
00468 } else {
00469 oc = (struct option_cache *)0;
00470 cip.len = 4;
00471 memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
00472 }
00473
00474
00475
00476
00477 subnet = (struct subnet *)0;
00478 lease = (struct lease *)0;
00479 if (find_subnet (&subnet, cip, MDL))
00480 find_lease (&lease, packet,
00481 subnet -> shared_network, &ours, 0, ip_lease, MDL);
00482
00483 if (lease && lease -> client_hostname) {
00484 if ((strlen (lease -> client_hostname) <= 64) &&
00485 db_printable((unsigned char *)lease->client_hostname))
00486 s = lease -> client_hostname;
00487 else
00488 s = "Hostname Unsuitable for Printing";
00489 } else
00490 s = (char *)0;
00491
00492 oc = lookup_option (&dhcp_universe, packet -> options,
00493 DHO_DHCP_SERVER_IDENTIFIER);
00494 memset (&data, 0, sizeof data);
00495 if (oc &&
00496 evaluate_option_cache (&data, packet, (struct lease *)0,
00497 (struct client_state *)0,
00498 packet -> options, (struct option_state *)0,
00499 &global_scope, oc, MDL)) {
00500 sip.len = 4;
00501 memcpy (sip.iabuf, data.data, 4);
00502 data_string_forget (&data, MDL);
00503
00504
00505
00506 sprintf (smbuf, " (%s)", piaddr (sip));
00507 } else {
00508 smbuf [0] = 0;
00509 sip.len = 0;
00510 }
00511
00512
00513
00514
00515 snprintf (msgbuf, sizeof msgbuf,
00516 "DHCPREQUEST for %s%s from %s %s%s%svia %s",
00517 piaddr (cip), smbuf,
00518 (packet -> raw -> htype
00519 ? print_hw_addr_or_client_id(packet)
00520 : (lease
00521 ? print_hex_1(lease->uid_len, lease->uid, 60)
00522 : "<no identifier>")),
00523 s ? "(" : "", s ? s : "", s ? ") " : "",
00524 packet -> raw -> giaddr.s_addr
00525 ? inet_ntoa (packet -> raw -> giaddr)
00526 : packet -> interface -> name);
00527
00528 #if defined (FAILOVER_PROTOCOL)
00529 if (lease && lease -> pool && lease -> pool -> failover_peer) {
00530 peer = lease -> pool -> failover_peer;
00531 if (peer -> service_state == not_responding ||
00532 peer -> service_state == service_startup) {
00533 log_info ("%s: not responding%s",
00534 msgbuf, peer -> nrr);
00535 goto out;
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 if ((lease -> binding_state == FTS_FREE ||
00557 lease -> binding_state == FTS_BACKUP) &&
00558 !lease_mine_to_reallocate (lease)) {
00559 log_debug ("%s: lease owned by peer", msgbuf);
00560 goto out;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569 if ((lease->binding_state == FTS_RELEASED ||
00570 lease->binding_state == FTS_EXPIRED) &&
00571 lease->rewind_binding_state != FTS_ACTIVE &&
00572 !lease_mine_to_reallocate(lease)) {
00573 log_debug("%s: lease in transition state %s", msgbuf,
00574 (lease->binding_state == FTS_RELEASED)
00575 ? "released" : "expired");
00576 goto out;
00577 }
00578
00579
00580
00581
00582 if (lease -> binding_state == FTS_RESET &&
00583 !lease_mine_to_reallocate (lease)) {
00584 log_debug ("%s: lease reset by administrator", msgbuf);
00585 nak_lease (packet, &cip);
00586 goto out;
00587 }
00588
00589 #if defined(SERVER_ID_CHECK)
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 if ((sip.len == 4) &&
00600 (memcmp(sip.iabuf, "\0\0\0\0", sip.len) != 0)) {
00601 struct in_addr from;
00602 setup_server_source_address(&from, NULL, packet);
00603 if (memcmp(sip.iabuf, &from, sip.len) != 0) {
00604 log_debug("%s: not our server id", msgbuf);
00605 goto out;
00606 }
00607 }
00608 #endif
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 } else
00634 peer = (dhcp_failover_state_t *)0;
00635 #endif
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 if (!packet -> shared_network ||
00680 (packet -> raw -> ciaddr.s_addr &&
00681 packet -> raw -> giaddr.s_addr) ||
00682 (have_requested_addr && !packet -> raw -> ciaddr.s_addr)) {
00683
00684
00685
00686
00687 if (!packet -> shared_network) {
00688 if (subnet && subnet -> group -> authoritative) {
00689 log_info ("%s: wrong network.", msgbuf);
00690 nak_lease (packet, &cip);
00691 goto out;
00692 }
00693
00694 log_info ("%s: ignored (%s).", msgbuf,
00695 (subnet
00696 ? "not authoritative" : "unknown subnet"));
00697 goto out;
00698 }
00699
00700
00701
00702 if (subnet)
00703 subnet_dereference (&subnet, MDL);
00704 if (!find_grouped_subnet (&subnet, packet -> shared_network,
00705 cip, MDL)) {
00706 if (packet -> shared_network -> group -> authoritative)
00707 {
00708 log_info ("%s: wrong network.", msgbuf);
00709 nak_lease (packet, &cip);
00710 goto out;
00711 }
00712 log_info ("%s: ignored (not authoritative).", msgbuf);
00713 return;
00714 }
00715 }
00716
00717
00718
00719 if (!lease && ours) {
00720 log_info ("%s: lease %s unavailable.", msgbuf, piaddr (cip));
00721 nak_lease (packet, &cip);
00722 goto out;
00723 }
00724
00725
00726 if (lease) {
00727 ack_lease (packet, lease, DHCPACK, 0, msgbuf, ms_nulltp,
00728 (struct host_decl *)0);
00729 } else
00730 log_info ("%s: unknown lease %s.", msgbuf, piaddr (cip));
00731
00732 out:
00733
00734 TRACE(DHCPD_REQUEST_DONE());
00735
00736 if (subnet)
00737 subnet_dereference (&subnet, MDL);
00738 if (lease)
00739 lease_dereference (&lease, MDL);
00740 return;
00741 }
00742
00743 void dhcprelease (packet, ms_nulltp)
00744 struct packet *packet;
00745 int ms_nulltp;
00746 {
00747 struct lease *lease = (struct lease *)0, *next = (struct lease *)0;
00748 struct iaddr cip;
00749 struct option_cache *oc;
00750 struct data_string data;
00751 const char *s;
00752 char msgbuf [1024], cstr[16];
00753
00754 TRACE(DHCPD_RELEASE_START());
00755
00756
00757
00758
00759 if ((oc = lookup_option (&dhcp_universe, packet -> options,
00760 DHO_DHCP_REQUESTED_ADDRESS))) {
00761 log_info ("DHCPRELEASE from %s specified requested-address.",
00762 print_hw_addr_or_client_id(packet));
00763 }
00764
00765 oc = lookup_option (&dhcp_universe, packet -> options,
00766 DHO_DHCP_CLIENT_IDENTIFIER);
00767 memset (&data, 0, sizeof data);
00768 if (oc &&
00769 evaluate_option_cache (&data, packet, (struct lease *)0,
00770 (struct client_state *)0,
00771 packet -> options, (struct option_state *)0,
00772 &global_scope, oc, MDL)) {
00773 find_lease_by_uid (&lease, data.data, data.len, MDL);
00774 data_string_forget (&data, MDL);
00775
00776
00777
00778 while (lease) {
00779 if (lease -> n_uid)
00780 lease_reference (&next, lease -> n_uid, MDL);
00781 if (!memcmp (&packet -> raw -> ciaddr,
00782 lease -> ip_addr.iabuf, 4)) {
00783 break;
00784 }
00785 lease_dereference (&lease, MDL);
00786 if (next) {
00787 lease_reference (&lease, next, MDL);
00788 lease_dereference (&next, MDL);
00789 }
00790 }
00791 if (next)
00792 lease_dereference (&next, MDL);
00793 }
00794
00795
00796
00797
00798 if (!lease) {
00799 cip.len = 4;
00800 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
00801 find_lease_by_ip_addr (&lease, cip, MDL);
00802 }
00803
00804
00805
00806 if (lease &&
00807 (lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
00808 lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
00809 memcmp (&lease -> hardware_addr.hbuf [1],
00810 packet -> raw -> chaddr, packet -> raw -> hlen)))
00811 lease_dereference (&lease, MDL);
00812
00813 if (lease && lease -> client_hostname) {
00814 if ((strlen (lease -> client_hostname) <= 64) &&
00815 db_printable((unsigned char *)lease->client_hostname))
00816 s = lease -> client_hostname;
00817 else
00818 s = "Hostname Unsuitable for Printing";
00819 } else
00820 s = (char *)0;
00821
00822
00823
00824
00825
00826 strncpy(cstr, inet_ntoa (packet -> raw -> ciaddr), 15);
00827 cstr[15] = '\0';
00828
00829
00830
00831
00832 snprintf (msgbuf, sizeof msgbuf,
00833 "DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
00834 cstr,
00835 (packet -> raw -> htype
00836 ? print_hw_addr_or_client_id(packet)
00837 : (lease
00838 ? print_hex_1(lease->uid_len, lease->uid, 60)
00839 : "<no identifier>")),
00840 s ? "(" : "", s ? s : "", s ? ") " : "",
00841 packet -> raw -> giaddr.s_addr
00842 ? inet_ntoa (packet -> raw -> giaddr)
00843 : packet -> interface -> name,
00844 lease ? "" : "not ");
00845
00846 #if defined (FAILOVER_PROTOCOL)
00847 if (lease && lease -> pool && lease -> pool -> failover_peer) {
00848 dhcp_failover_state_t *peer = lease -> pool -> failover_peer;
00849 if (peer -> service_state == not_responding ||
00850 peer -> service_state == service_startup) {
00851 log_info ("%s: ignored%s",
00852 peer -> name, peer -> nrr);
00853 goto out;
00854 }
00855
00856
00857
00858
00859
00860
00861
00862 }
00863 #endif
00864
00865
00866 if (lease && lease -> ends > cur_time) {
00867 release_lease (lease, packet);
00868 }
00869 log_info ("%s", msgbuf);
00870 #if defined(FAILOVER_PROTOCOL)
00871 out:
00872 #endif
00873 if (lease)
00874 lease_dereference (&lease, MDL);
00875
00876 TRACE(DHCPD_RELEASE_DONE());
00877 }
00878
00879 void dhcpdecline (packet, ms_nulltp)
00880 struct packet *packet;
00881 int ms_nulltp;
00882 {
00883 struct lease *lease = (struct lease *)0;
00884 struct option_state *options = (struct option_state *)0;
00885 int ignorep = 0;
00886 int i;
00887 const char *status;
00888 const char *s;
00889 char msgbuf [1024];
00890 struct iaddr cip;
00891 struct option_cache *oc;
00892 struct data_string data;
00893
00894 TRACE(DHCPD_DECLINE_START());
00895
00896
00897 if (!(oc = lookup_option (&dhcp_universe, packet -> options,
00898 DHO_DHCP_REQUESTED_ADDRESS)))
00899 return;
00900 memset (&data, 0, sizeof data);
00901 if (!evaluate_option_cache (&data, packet, (struct lease *)0,
00902 (struct client_state *)0,
00903 packet -> options,
00904 (struct option_state *)0,
00905 &global_scope, oc, MDL))
00906 return;
00907
00908 cip.len = 4;
00909 memcpy (cip.iabuf, data.data, 4);
00910 data_string_forget (&data, MDL);
00911 find_lease_by_ip_addr (&lease, cip, MDL);
00912
00913 if (lease && lease -> client_hostname) {
00914 if ((strlen (lease -> client_hostname) <= 64) &&
00915 db_printable((unsigned char *)lease->client_hostname))
00916 s = lease -> client_hostname;
00917 else
00918 s = "Hostname Unsuitable for Printing";
00919 } else
00920 s = (char *)0;
00921
00922
00923
00924
00925 snprintf (msgbuf, sizeof msgbuf,
00926 "DHCPDECLINE of %s from %s %s%s%svia %s",
00927 piaddr (cip),
00928 (packet -> raw -> htype
00929 ? print_hw_addr_or_client_id(packet)
00930 : (lease
00931 ? print_hex_1(lease->uid_len, lease->uid, 60)
00932 : "<no identifier>")),
00933 s ? "(" : "", s ? s : "", s ? ") " : "",
00934 packet -> raw -> giaddr.s_addr
00935 ? inet_ntoa (packet -> raw -> giaddr)
00936 : packet -> interface -> name);
00937
00938 option_state_allocate (&options, MDL);
00939
00940
00941 if (lease)
00942 execute_statements_in_scope(NULL, packet, NULL, NULL,
00943 packet->options, options,
00944 &global_scope,
00945 lease->subnet->group,
00946 NULL, NULL);
00947
00948
00949 for (i = packet -> class_count; i > 0; i--) {
00950 execute_statements_in_scope
00951 (NULL, packet, NULL, NULL, packet->options, options,
00952 &global_scope, packet->classes[i - 1]->group,
00953 lease ? lease->subnet->group : NULL, NULL);
00954 }
00955
00956
00957 oc = lookup_option (&server_universe, options, SV_DECLINES);
00958 if (!oc ||
00959 evaluate_boolean_option_cache (&ignorep, packet, lease,
00960 (struct client_state *)0,
00961 packet -> options, options,
00962 &lease -> scope, oc, MDL)) {
00963
00964 if (lease) {
00965 #if defined (FAILOVER_PROTOCOL)
00966 if (lease -> pool && lease -> pool -> failover_peer) {
00967 dhcp_failover_state_t *peer =
00968 lease -> pool -> failover_peer;
00969 if (peer -> service_state == not_responding ||
00970 peer -> service_state == service_startup) {
00971 if (!ignorep)
00972 log_info ("%s: ignored%s",
00973 peer -> name, peer -> nrr);
00974 goto out;
00975 }
00976
00977
00978
00979
00980
00981 }
00982 #endif
00983
00984 abandon_lease (lease, "declined.");
00985 status = "abandoned";
00986 } else {
00987 status = "not found";
00988 }
00989 } else
00990 status = "ignored";
00991
00992 if (!ignorep)
00993 log_info ("%s: %s", msgbuf, status);
00994
00995 #if defined(FAILOVER_PROTOCOL)
00996 out:
00997 #endif
00998 if (options)
00999 option_state_dereference (&options, MDL);
01000 if (lease)
01001 lease_dereference (&lease, MDL);
01002
01003 TRACE(DHCPD_DECLINE_DONE());
01004 }
01005
01006 void dhcpinform (packet, ms_nulltp)
01007 struct packet *packet;
01008 int ms_nulltp;
01009 {
01010 char msgbuf[1024], *addr_type;
01011 struct data_string d1, prl, fixed_addr;
01012 struct option_cache *oc;
01013 struct option_state *options = NULL;
01014 struct dhcp_packet raw;
01015 struct packet outgoing;
01016 unsigned char dhcpack = DHCPACK;
01017 struct subnet *subnet = NULL;
01018 struct iaddr cip, gip, sip;
01019 unsigned i;
01020 int nulltp;
01021 struct sockaddr_in to;
01022 struct in_addr from;
01023 isc_boolean_t zeroed_ciaddr;
01024 struct interface_info *interface;
01025 int result, h_m_client_ip = 0;
01026 struct host_decl *host = NULL, *hp = NULL, *h;
01027 #if defined (DEBUG_INFORM_HOST)
01028 int h_w_fixed_addr = 0;
01029 #endif
01030
01031 TRACE(DHCPD_INFORM_START());
01032
01033
01034
01035
01036 if (!packet->raw->ciaddr.s_addr) {
01037 zeroed_ciaddr = ISC_TRUE;
01038 cip.len = 4;
01039 memcpy(cip.iabuf, &packet->client_addr.iabuf, 4);
01040 addr_type = "source";
01041 } else {
01042 zeroed_ciaddr = ISC_FALSE;
01043 cip.len = 4;
01044 memcpy(cip.iabuf, &packet->raw->ciaddr, 4);
01045 addr_type = "client";
01046 }
01047 sip.len = 4;
01048 memcpy(sip.iabuf, cip.iabuf, 4);
01049
01050 if (packet->raw->giaddr.s_addr) {
01051 gip.len = 4;
01052 memcpy(gip.iabuf, &packet->raw->giaddr, 4);
01053 if (zeroed_ciaddr == ISC_TRUE) {
01054 addr_type = "relay";
01055 memcpy(sip.iabuf, gip.iabuf, 4);
01056 }
01057 } else
01058 gip.len = 0;
01059
01060
01061
01062
01063 snprintf(msgbuf, sizeof(msgbuf), "DHCPINFORM from %s via %s",
01064 piaddr(cip),
01065 packet->raw->giaddr.s_addr ?
01066 inet_ntoa(packet->raw->giaddr) :
01067 packet->interface->name);
01068
01069
01070 if (!memcmp(cip.iabuf, "\0\0\0", 4)) {
01071 log_info("%s: ignored (null source address).", msgbuf);
01072 return;
01073 }
01074
01075
01076
01077
01078
01079 option_state_allocate(&options, MDL);
01080
01081 if ((oc = lookup_option(&agent_universe, packet->options,
01082 RAI_LINK_SELECT)) == NULL)
01083 oc = lookup_option(&dhcp_universe, packet->options,
01084 DHO_SUBNET_SELECTION);
01085
01086 memset(&d1, 0, sizeof d1);
01087 if (oc && evaluate_option_cache(&d1, packet, NULL, NULL,
01088 packet->options, NULL,
01089 &global_scope, oc, MDL)) {
01090 struct option_cache *noc = NULL;
01091
01092 if (d1.len != 4) {
01093 log_info("%s: ignored (invalid subnet selection option).", msgbuf);
01094 option_state_dereference(&options, MDL);
01095 return;
01096 }
01097
01098 memcpy(sip.iabuf, d1.data, 4);
01099 data_string_forget(&d1, MDL);
01100
01101
01102 if (option_cache_allocate(&noc, MDL)) {
01103 if (oc->data.len)
01104 data_string_copy(&noc->data, &oc->data, MDL);
01105 if (oc->expression)
01106 expression_reference(&noc->expression,
01107 oc->expression, MDL);
01108 if (oc->option)
01109 option_reference(&(noc->option), oc->option,
01110 MDL);
01111 }
01112 save_option(&dhcp_universe, options, noc);
01113 option_cache_dereference(&noc, MDL);
01114
01115 if ((zeroed_ciaddr == ISC_TRUE) && (gip.len != 0))
01116 addr_type = "relay link select";
01117 else
01118 addr_type = "selected";
01119 }
01120
01121 find_subnet(&subnet, sip, MDL);
01122
01123 if (subnet == NULL) {
01124 log_info("%s: unknown subnet for %s address %s",
01125 msgbuf, addr_type, piaddr(sip));
01126 option_state_dereference (&options, MDL);
01127 return;
01128 }
01129
01130
01131
01132
01133
01134 if (subnet && !subnet -> group -> authoritative) {
01135 static int eso = 0;
01136 log_info ("%s: not authoritative for subnet %s",
01137 msgbuf, piaddr (subnet -> net));
01138 if (!eso) {
01139 log_info ("If this DHCP server is authoritative for%s",
01140 " that subnet,");
01141 log_info ("please write an `authoritative;' directi%s",
01142 "ve either in the");
01143 log_info ("subnet declaration or in some scope that%s",
01144 " encloses the");
01145 log_info ("subnet declaration - for example, write %s",
01146 "it at the top");
01147 log_info ("of the dhcpd.conf file.");
01148 }
01149 if (eso++ == 100)
01150 eso = 0;
01151 subnet_dereference (&subnet, MDL);
01152 option_state_dereference (&options, MDL);
01153 return;
01154 }
01155
01156 memset (&outgoing, 0, sizeof outgoing);
01157 memset (&raw, 0, sizeof raw);
01158 outgoing.raw = &raw;
01159
01160 maybe_return_agent_options(packet, options);
01161
01162
01163 if (subnet)
01164 execute_statements_in_scope (NULL, packet, NULL, NULL,
01165 packet->options, options,
01166 &global_scope, subnet->group,
01167 NULL, NULL);
01168
01169
01170 for (i = packet -> class_count; i > 0; i--) {
01171 execute_statements_in_scope(NULL, packet, NULL, NULL,
01172 packet->options, options,
01173 &global_scope,
01174 packet->classes[i - 1]->group,
01175 subnet ? subnet->group : NULL,
01176 NULL);
01177 }
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 oc = lookup_option(&dhcp_universe, packet->options,
01193 DHO_DHCP_CLIENT_IDENTIFIER);
01194 memset(&d1, 0, sizeof(d1));
01195 if (oc &&
01196 evaluate_option_cache(&d1, packet, NULL, NULL,
01197 packet->options, NULL,
01198 &global_scope, oc, MDL)) {
01199 find_hosts_by_uid(&hp, d1.data, d1.len, MDL);
01200 data_string_forget(&d1, MDL);
01201
01202 #if defined (DEBUG_INFORM_HOST)
01203 if (hp)
01204 log_debug ("dhcpinform: found host by ID "
01205 "-- checking fixed-address match");
01206 #endif
01207
01208
01209 for (h = hp; !h_m_client_ip && h; h = h->n_ipaddr) {
01210 if (!h->fixed_addr)
01211 continue;
01212
01213 memset(&fixed_addr, 0, sizeof(fixed_addr));
01214 if (!evaluate_option_cache (&fixed_addr, NULL,
01215 NULL, NULL, NULL, NULL,
01216 &global_scope,
01217 h->fixed_addr, MDL))
01218 continue;
01219
01220 #if defined (DEBUG_INFORM_HOST)
01221 h_w_fixed_addr++;
01222 #endif
01223 for (i = 0;
01224 (i + cip.len) <= fixed_addr.len;
01225 i += cip.len) {
01226 if (memcmp(fixed_addr.data + i,
01227 cip.iabuf, cip.len) == 0) {
01228 #if defined (DEBUG_INFORM_HOST)
01229 log_debug ("dhcpinform: found "
01230 "host with matching "
01231 "fixed-address by ID");
01232 #endif
01233 host_reference(&host, h, MDL);
01234 h_m_client_ip = 1;
01235 break;
01236 }
01237 }
01238 data_string_forget(&fixed_addr, MDL);
01239 }
01240
01241
01242 for (h = hp; !host && h; h = h->n_ipaddr) {
01243 if (h->fixed_addr)
01244 continue;
01245
01246 #if defined (DEBUG_INFORM_HOST)
01247 log_debug ("dhcpinform: found host "
01248 "without fixed-address by ID");
01249 #endif
01250 host_reference(&host, h, MDL);
01251 break;
01252 }
01253 if (hp)
01254 host_dereference (&hp, MDL);
01255 }
01256 if (!host || !h_m_client_ip) {
01257 find_hosts_by_haddr(&hp, packet->raw->htype,
01258 packet->raw->chaddr,
01259 packet->raw->hlen, MDL);
01260
01261 #if defined (DEBUG_INFORM_HOST)
01262 if (hp)
01263 log_debug ("dhcpinform: found host by HW "
01264 "-- checking fixed-address match");
01265 #endif
01266
01267
01268
01269 for (h = hp; !h_m_client_ip && h; h = h->n_ipaddr) {
01270 if (!h->fixed_addr)
01271 continue;
01272
01273 memset (&fixed_addr, 0, sizeof(fixed_addr));
01274 if (!evaluate_option_cache (&fixed_addr, NULL,
01275 NULL, NULL, NULL, NULL,
01276 &global_scope,
01277 h->fixed_addr, MDL))
01278 continue;
01279
01280 #if defined (DEBUG_INFORM_HOST)
01281 h_w_fixed_addr++;
01282 #endif
01283 for (i = 0;
01284 (i + cip.len) <= fixed_addr.len;
01285 i += cip.len) {
01286 if (memcmp(fixed_addr.data + i,
01287 cip.iabuf, cip.len) == 0) {
01288 #if defined (DEBUG_INFORM_HOST)
01289 log_debug ("dhcpinform: found "
01290 "host with matching "
01291 "fixed-address by HW");
01292 #endif
01293
01294
01295
01296
01297
01298 if(host)
01299 host_dereference(&host, MDL);
01300 host_reference(&host, h, MDL);
01301 h_m_client_ip = 1;
01302 break;
01303 }
01304 }
01305 data_string_forget(&fixed_addr, MDL);
01306 }
01307
01308 for (h = hp; !host && h; h = h->n_ipaddr) {
01309 if (h->fixed_addr)
01310 continue;
01311
01312 #if defined (DEBUG_INFORM_HOST)
01313 log_debug ("dhcpinform: found host without "
01314 "fixed-address by HW");
01315 #endif
01316 host_reference (&host, h, MDL);
01317 break;
01318 }
01319
01320 if (hp)
01321 host_dereference (&hp, MDL);
01322 }
01323
01324 #if defined (DEBUG_INFORM_HOST)
01325
01326
01327
01328
01329 if (h_w_fixed_addr && !h_m_client_ip) {
01330 log_info ("dhcpinform: matching host with "
01331 "fixed-address different than "
01332 "client IP detected?!");
01333 }
01334 #endif
01335
01336
01337
01338
01339 if (host) {
01340 #if defined (DEBUG_INFORM_HOST)
01341 log_info ("dhcpinform: applying host (group) options");
01342 #endif
01343 execute_statements_in_scope(NULL, packet, NULL, NULL,
01344 packet->options, options,
01345 &global_scope, host->group,
01346 host->group ?
01347 host->group->next : NULL,
01348 NULL);
01349 host_dereference (&host, MDL);
01350 }
01351
01352
01353
01354
01355 memset (&d1, 0, sizeof d1);
01356 oc = lookup_option (&server_universe, options, SV_FILENAME);
01357 if (oc &&
01358 evaluate_option_cache (&d1, packet, (struct lease *)0,
01359 (struct client_state *)0,
01360 packet -> options, (struct option_state *)0,
01361 &global_scope, oc, MDL)) {
01362 i = d1.len;
01363 if (i >= sizeof(raw.file)) {
01364 log_info("file name longer than packet field "
01365 "truncated - field: %lu name: %d %.*s",
01366 (unsigned long)sizeof(raw.file), i,
01367 (int)i, d1.data);
01368 i = sizeof(raw.file);
01369 } else
01370 raw.file[i] = 0;
01371 memcpy (raw.file, d1.data, i);
01372 data_string_forget (&d1, MDL);
01373 }
01374
01375
01376 oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
01377 if (oc &&
01378 evaluate_option_cache (&d1, packet, (struct lease *)0,
01379 (struct client_state *)0,
01380 packet -> options, (struct option_state *)0,
01381 &global_scope, oc, MDL)) {
01382 i = d1.len;
01383 if (i >= sizeof(raw.sname)) {
01384 log_info("server name longer than packet field "
01385 "truncated - field: %lu name: %d %.*s",
01386 (unsigned long)sizeof(raw.sname), i,
01387 (int)i, d1.data);
01388 i = sizeof(raw.sname);
01389 } else
01390 raw.sname[i] = 0;
01391 memcpy (raw.sname, d1.data, i);
01392 data_string_forget (&d1, MDL);
01393 }
01394
01395
01396
01397 nulltp = 0;
01398 if ((oc = lookup_option (&dhcp_universe, packet -> options,
01399 DHO_HOST_NAME))) {
01400 if (!oc->expression)
01401 nulltp = oc->flags & OPTION_HAD_NULLS;
01402 }
01403
01404
01405 i = DHO_DHCP_MESSAGE_TYPE;
01406 oc = (struct option_cache *)0;
01407 if (option_cache_allocate (&oc, MDL)) {
01408 if (make_const_data (&oc -> expression,
01409 &dhcpack, 1, 0, 0, MDL)) {
01410 option_code_hash_lookup(&oc->option,
01411 dhcp_universe.code_hash,
01412 &i, 0, MDL);
01413 save_option (&dhcp_universe, options, oc);
01414 }
01415 option_cache_dereference (&oc, MDL);
01416 }
01417
01418 get_server_source_address(&from, options, options, packet);
01419
01420
01421
01422 i = DHO_SUBNET_MASK;
01423 if (subnet && !lookup_option (&dhcp_universe, options, i)) {
01424 oc = (struct option_cache *)0;
01425 if (option_cache_allocate (&oc, MDL)) {
01426 if (make_const_data (&oc -> expression,
01427 subnet -> netmask.iabuf,
01428 subnet -> netmask.len,
01429 0, 0, MDL)) {
01430 option_code_hash_lookup(&oc->option,
01431 dhcp_universe.code_hash,
01432 &i, 0, MDL);
01433 save_option (&dhcp_universe, options, oc);
01434 }
01435 option_cache_dereference (&oc, MDL);
01436 }
01437 }
01438
01439
01440
01441 i = SV_SITE_OPTION_SPACE;
01442 if ((oc = lookup_option (&server_universe, options, i)) &&
01443 evaluate_option_cache (&d1, packet, (struct lease *)0,
01444 (struct client_state *)0,
01445 packet -> options, options,
01446 &global_scope, oc, MDL)) {
01447 struct universe *u = (struct universe *)0;
01448
01449 if (!universe_hash_lookup (&u, universe_hash,
01450 (const char *)d1.data, d1.len,
01451 MDL)) {
01452 log_error ("unknown option space %s.", d1.data);
01453 option_state_dereference (&options, MDL);
01454 if (subnet)
01455 subnet_dereference (&subnet, MDL);
01456 return;
01457 }
01458
01459 options -> site_universe = u -> index;
01460 options->site_code_min = find_min_site_code(u);
01461 data_string_forget (&d1, MDL);
01462 } else {
01463 options -> site_universe = dhcp_universe.index;
01464 options -> site_code_min = 0;
01465 }
01466
01467 memset (&prl, 0, sizeof prl);
01468
01469
01470 oc = lookup_option (&dhcp_universe, options,
01471 DHO_DHCP_PARAMETER_REQUEST_LIST);
01472
01473
01474
01475
01476
01477 if (!oc)
01478 oc = lookup_option (&dhcp_universe, packet -> options,
01479 DHO_DHCP_PARAMETER_REQUEST_LIST);
01480
01481 if (oc)
01482 evaluate_option_cache (&prl, packet, (struct lease *)0,
01483 (struct client_state *)0,
01484 packet -> options, options,
01485 &global_scope, oc, MDL);
01486
01487 #ifdef DEBUG_PACKET
01488 dump_packet (packet);
01489 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
01490 #endif
01491
01492 log_info ("%s", msgbuf);
01493
01494
01495 if ((oc =
01496 lookup_option (&server_universe, options, SV_NEXT_SERVER))) {
01497 if (evaluate_option_cache (&d1, packet, (struct lease *)0,
01498 (struct client_state *)0,
01499 packet -> options, options,
01500 &global_scope, oc, MDL)) {
01501
01502
01503 if (d1.len >= 4 && d1.data)
01504 memcpy (&raw.siaddr, d1.data, 4);
01505 data_string_forget (&d1, MDL);
01506 }
01507 }
01508
01509
01510
01511
01512 delete_option(&dhcp_universe, options, DHO_DHCP_LEASE_TIME);
01513 delete_option(&dhcp_universe, options, DHO_DHCP_RENEWAL_TIME);
01514 delete_option(&dhcp_universe, options, DHO_DHCP_REBINDING_TIME);
01515
01516
01517 outgoing.packet_length =
01518 cons_options (packet, outgoing.raw, (struct lease *)0,
01519 (struct client_state *)0,
01520 0, packet -> options, options, &global_scope,
01521 0, nulltp, 0,
01522 prl.len ? &prl : (struct data_string *)0,
01523 (char *)0);
01524 option_state_dereference (&options, MDL);
01525 data_string_forget (&prl, MDL);
01526
01527
01528 if (outgoing.packet_length < BOOTP_MIN_LEN)
01529 outgoing.packet_length = BOOTP_MIN_LEN;
01530
01531 raw.giaddr = packet -> raw -> giaddr;
01532 raw.ciaddr = packet -> raw -> ciaddr;
01533 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
01534 raw.hlen = packet -> raw -> hlen;
01535 raw.htype = packet -> raw -> htype;
01536
01537 raw.xid = packet -> raw -> xid;
01538 raw.secs = packet -> raw -> secs;
01539 raw.flags = packet -> raw -> flags;
01540 raw.hops = packet -> raw -> hops;
01541 raw.op = BOOTREPLY;
01542
01543 #ifdef DEBUG_PACKET
01544 dump_packet (&outgoing);
01545 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
01546 #endif
01547
01548
01549 to.sin_family = AF_INET;
01550 #ifdef HAVE_SA_LEN
01551 to.sin_len = sizeof to;
01552 #endif
01553 memset (to.sin_zero, 0, sizeof to.sin_zero);
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573 if (!raw.ciaddr.s_addr && gip.len) {
01574 memcpy(&to.sin_addr, gip.iabuf, 4);
01575 to.sin_port = local_port;
01576 raw.flags |= htons(BOOTP_BROADCAST);
01577 } else {
01578 gip.len = 0;
01579 memcpy(&to.sin_addr, cip.iabuf, 4);
01580 to.sin_port = remote_port;
01581 }
01582
01583
01584 snprintf(msgbuf, sizeof msgbuf, "DHCPACK to %s (%s) via", piaddr(cip),
01585 (packet->raw->htype && packet->raw->hlen) ?
01586 print_hw_addr_or_client_id(packet) :
01587 "<no client hardware address>");
01588 log_info("%s %s", msgbuf, gip.len ? piaddr(gip) :
01589 packet->interface->name);
01590
01591 errno = 0;
01592 interface = (fallback_interface ? fallback_interface
01593 : packet -> interface);
01594 result = send_packet(interface, &outgoing, &raw,
01595 outgoing.packet_length, from, &to, NULL);
01596 if (result < 0) {
01597 log_error ("%s:%d: Failed to send %d byte long packet over %s "
01598 "interface.", MDL, outgoing.packet_length,
01599 interface->name);
01600 }
01601
01602
01603 if (subnet)
01604 subnet_dereference (&subnet, MDL);
01605
01606 TRACE(DHCPD_INFORM_DONE());
01607 }
01608
01609 void nak_lease (packet, cip)
01610 struct packet *packet;
01611 struct iaddr *cip;
01612 {
01613 struct sockaddr_in to;
01614 struct in_addr from;
01615 int result;
01616 struct dhcp_packet raw;
01617 unsigned char nak = DHCPNAK;
01618 struct packet outgoing;
01619 unsigned i;
01620 struct option_state *options = (struct option_state *)0;
01621 struct option_cache *oc = (struct option_cache *)0;
01622
01623 TRACE(DHCPD_NAK_LEASE_START());
01624
01625 option_state_allocate (&options, MDL);
01626 memset (&outgoing, 0, sizeof outgoing);
01627 memset (&raw, 0, sizeof raw);
01628 outgoing.raw = &raw;
01629
01630
01631 if (!option_cache_allocate (&oc, MDL)) {
01632 log_error ("No memory for DHCPNAK message type.");
01633 option_state_dereference (&options, MDL);
01634 return;
01635 }
01636 if (!make_const_data (&oc -> expression, &nak, sizeof nak,
01637 0, 0, MDL)) {
01638 log_error ("No memory for expr_const expression.");
01639 option_cache_dereference (&oc, MDL);
01640 option_state_dereference (&options, MDL);
01641 return;
01642 }
01643 i = DHO_DHCP_MESSAGE_TYPE;
01644 option_code_hash_lookup(&oc->option, dhcp_universe.code_hash,
01645 &i, 0, MDL);
01646 save_option (&dhcp_universe, options, oc);
01647 option_cache_dereference (&oc, MDL);
01648
01649
01650 if (!option_cache_allocate (&oc, MDL)) {
01651 log_error ("No memory for DHCPNAK message type.");
01652 option_state_dereference (&options, MDL);
01653 return;
01654 }
01655 if (!make_const_data (&oc -> expression,
01656 (unsigned char *)dhcp_message,
01657 strlen (dhcp_message), 1, 0, MDL)) {
01658 log_error ("No memory for expr_const expression.");
01659 option_cache_dereference (&oc, MDL);
01660 option_state_dereference (&options, MDL);
01661 return;
01662 }
01663 i = DHO_DHCP_MESSAGE;
01664 option_code_hash_lookup(&oc->option, dhcp_universe.code_hash,
01665 &i, 0, MDL);
01666 save_option (&dhcp_universe, options, oc);
01667 option_cache_dereference (&oc, MDL);
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679 #if defined(SERVER_ID_FOR_NAK)
01680 setup_server_source_address(&from, options, packet);
01681 #else
01682 get_server_source_address(&from, NULL, options, packet);
01683 #endif
01684
01685
01686
01687
01688
01689
01690
01691 if (packet->options->universe_count > agent_universe.index &&
01692 packet->options->universes [agent_universe.index]) {
01693 option_chain_head_reference
01694 ((struct option_chain_head **)
01695 &(options -> universes [agent_universe.index]),
01696 (struct option_chain_head *)
01697 packet -> options -> universes [agent_universe.index],
01698 MDL);
01699 }
01700
01701
01702 delete_option (&dhcp_universe, packet -> options,
01703 DHO_DHCP_PARAMETER_REQUEST_LIST);
01704
01705
01706 outgoing.packet_length =
01707 cons_options (packet, outgoing.raw, (struct lease *)0,
01708 (struct client_state *)0,
01709 0, packet -> options, options, &global_scope,
01710 0, 0, 0, (struct data_string *)0, (char *)0);
01711 option_state_dereference (&options, MDL);
01712
01713
01714 if (packet->interface->address_count)
01715 raw.siaddr = packet->interface->addresses[0];
01716 raw.giaddr = packet -> raw -> giaddr;
01717 memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
01718 raw.hlen = packet -> raw -> hlen;
01719 raw.htype = packet -> raw -> htype;
01720
01721 raw.xid = packet -> raw -> xid;
01722 raw.secs = packet -> raw -> secs;
01723 raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST);
01724 raw.hops = packet -> raw -> hops;
01725 raw.op = BOOTREPLY;
01726
01727
01728 log_info ("DHCPNAK on %s to %s via %s",
01729 piaddr (*cip),
01730 print_hw_addr_or_client_id(packet),
01731 packet -> raw -> giaddr.s_addr
01732 ? inet_ntoa (packet -> raw -> giaddr)
01733 : packet -> interface -> name);
01734
01735 #ifdef DEBUG_PACKET
01736 dump_packet (packet);
01737 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
01738 dump_packet (&outgoing);
01739 dump_raw ((unsigned char *)&raw, outgoing.packet_length);
01740 #endif
01741
01742
01743 to.sin_family = AF_INET;
01744 #ifdef HAVE_SA_LEN
01745 to.sin_len = sizeof to;
01746 #endif
01747 memset (to.sin_zero, 0, sizeof to.sin_zero);
01748
01749
01750 if (outgoing.packet_length < BOOTP_MIN_LEN)
01751 outgoing.packet_length = BOOTP_MIN_LEN;
01752
01753
01754
01755 if (raw.giaddr.s_addr) {
01756 to.sin_addr = raw.giaddr;
01757 if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
01758 to.sin_port = local_port;
01759 else
01760 to.sin_port = remote_port;
01761
01762 if (fallback_interface) {
01763 result = send_packet(fallback_interface, packet, &raw,
01764 outgoing.packet_length, from, &to,
01765 NULL);
01766 if (result < 0) {
01767 log_error ("%s:%d: Failed to send %d byte long "
01768 "packet over %s interface.", MDL,
01769 outgoing.packet_length,
01770 fallback_interface->name);
01771 }
01772
01773 return;
01774 }
01775 } else {
01776 to.sin_addr = limited_broadcast;
01777 to.sin_port = remote_port;
01778 }
01779
01780 errno = 0;
01781 result = send_packet(packet->interface, packet, &raw,
01782 outgoing.packet_length, from, &to, NULL);
01783 if (result < 0) {
01784 log_error ("%s:%d: Failed to send %d byte long packet over %s "
01785 "interface.", MDL, outgoing.packet_length,
01786 packet->interface->name);
01787 }
01788
01789 TRACE(DHCPD_NAK_LEASE_DONE());
01790 }
01791
01792 void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
01793 struct packet *packet;
01794 struct lease *lease;
01795 unsigned int offer;
01796 TIME when;
01797 char *msg;
01798 int ms_nulltp;
01799 struct host_decl *hp;
01800 {
01801 struct lease *lt;
01802 struct lease_state *state;
01803 struct lease *next;
01804 struct host_decl *host = (struct host_decl *)0;
01805 TIME lease_time;
01806 TIME offered_lease_time;
01807 struct data_string d1;
01808 TIME min_lease_time;
01809 TIME max_lease_time;
01810 TIME default_lease_time;
01811 struct option_cache *oc;
01812 isc_result_t result;
01813 TIME ping_timeout;
01814 TIME lease_cltt;
01815 struct in_addr from;
01816 TIME remaining_time;
01817 struct iaddr cip;
01818 #if defined(DELAYED_ACK)
01819
01820 isc_boolean_t enqueue = ISC_FALSE;
01821 #endif
01822 int use_old_lease = 0;
01823
01824 unsigned i, j;
01825 int s1;
01826 int ignorep;
01827 struct timeval tv;
01828
01829
01830 if (lease -> state)
01831 return;
01832
01833 TRACE(DHCPD_ACK_LEASE_START());
01834
01835
01836 lease_cltt = lease->cltt;
01837
01838
01839 if (hp)
01840 host_reference (&host, hp, MDL);
01841 else if (lease -> host)
01842 host_reference (&host, lease -> host, MDL);
01843
01844
01845 state = new_lease_state (MDL);
01846 if (!state)
01847 log_fatal ("unable to allocate lease state!");
01848 state -> got_requested_address = packet -> got_requested_address;
01849 shared_network_reference (&state -> shared_network,
01850 packet -> interface -> shared_network, MDL);
01851
01852
01853 if (lookup_option (&dhcp_universe,
01854 packet -> options, DHO_DHCP_SERVER_IDENTIFIER))
01855 state -> got_server_identifier = 1;
01856
01857 maybe_return_agent_options(packet, state->options);
01858
01859
01860
01861
01862
01863
01864 if (lease->ends <= cur_time && offer != DHCPOFFER) {
01865
01866
01867
01868 if (lease->on_star.on_expiry)
01869 executable_statement_dereference
01870 (&lease->on_star.on_expiry, MDL);
01871 if (lease->on_star.on_commit)
01872 executable_statement_dereference
01873 (&lease->on_star.on_commit, MDL);
01874 if (lease->on_star.on_release)
01875 executable_statement_dereference
01876 (&lease->on_star.on_release, MDL);
01877 }
01878
01879
01880 execute_statements_in_scope (NULL, packet, lease,
01881 NULL, packet->options,
01882 state->options, &lease->scope,
01883 lease->subnet->group, NULL, NULL);
01884
01885
01886 if (lease->pool)
01887 (execute_statements_in_scope(NULL, packet, lease, NULL,
01888 packet->options, state->options,
01889 &lease->scope, lease->pool->group,
01890 lease->pool->
01891 shared_network->group,
01892 NULL));
01893
01894
01895 for (i = packet -> class_count; i > 0; i--) {
01896 execute_statements_in_scope(NULL, packet, lease, NULL,
01897 packet->options, state->options,
01898 &lease->scope,
01899 packet->classes[i - 1]->group,
01900 (lease->pool ? lease->pool->group
01901 : lease->subnet->group),
01902 NULL);
01903 }
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914 if (packet -> packet_type == DHCPREQUEST &&
01915 (oc = lookup_option (&server_universe, state -> options,
01916 SV_ONE_LEASE_PER_CLIENT)) &&
01917 evaluate_boolean_option_cache (&ignorep,
01918 packet, lease,
01919 (struct client_state *)0,
01920 packet -> options,
01921 state -> options, &lease -> scope,
01922 oc, MDL)) {
01923 struct lease *seek;
01924 if (lease -> uid_len) {
01925 do {
01926 seek = (struct lease *)0;
01927 find_lease_by_uid (&seek, lease -> uid,
01928 lease -> uid_len, MDL);
01929 if (!seek)
01930 break;
01931 if (seek == lease && !seek -> n_uid) {
01932 lease_dereference (&seek, MDL);
01933 break;
01934 }
01935 next = (struct lease *)0;
01936
01937
01938
01939 next = (struct lease *)0;
01940 while (seek) {
01941 if (seek -> n_uid)
01942 lease_reference (&next, seek -> n_uid, MDL);
01943 if (seek != lease &&
01944 seek -> binding_state != FTS_RELEASED &&
01945 seek -> binding_state != FTS_EXPIRED &&
01946 seek -> binding_state != FTS_RESET &&
01947 seek -> binding_state != FTS_FREE &&
01948 seek -> binding_state != FTS_BACKUP)
01949 break;
01950 lease_dereference (&seek, MDL);
01951 if (next) {
01952 lease_reference (&seek, next, MDL);
01953 lease_dereference (&next, MDL);
01954 }
01955 }
01956 if (next)
01957 lease_dereference (&next, MDL);
01958 if (seek) {
01959 release_lease (seek, packet);
01960 lease_dereference (&seek, MDL);
01961 } else
01962 break;
01963 } while (1);
01964 }
01965 if (!lease -> uid_len ||
01966 (host &&
01967 !host -> client_identifier.len &&
01968 (oc = lookup_option (&server_universe, state -> options,
01969 SV_DUPLICATES)) &&
01970 !evaluate_boolean_option_cache (&ignorep, packet, lease,
01971 (struct client_state *)0,
01972 packet -> options,
01973 state -> options,
01974 &lease -> scope,
01975 oc, MDL))) {
01976 do {
01977 seek = (struct lease *)0;
01978 find_lease_by_hw_addr
01979 (&seek, lease -> hardware_addr.hbuf,
01980 lease -> hardware_addr.hlen, MDL);
01981 if (!seek)
01982 break;
01983 if (seek == lease && !seek -> n_hw) {
01984 lease_dereference (&seek, MDL);
01985 break;
01986 }
01987 next = (struct lease *)0;
01988 while (seek) {
01989 if (seek -> n_hw)
01990 lease_reference (&next, seek -> n_hw, MDL);
01991 if (seek != lease &&
01992 seek -> binding_state != FTS_RELEASED &&
01993 seek -> binding_state != FTS_EXPIRED &&
01994 seek -> binding_state != FTS_RESET &&
01995 seek -> binding_state != FTS_FREE &&
01996 seek -> binding_state != FTS_BACKUP)
01997 break;
01998 lease_dereference (&seek, MDL);
01999 if (next) {
02000 lease_reference (&seek, next, MDL);
02001 lease_dereference (&next, MDL);
02002 }
02003 }
02004 if (next)
02005 lease_dereference (&next, MDL);
02006 if (seek) {
02007 release_lease (seek, packet);
02008 lease_dereference (&seek, MDL);
02009 } else
02010 break;
02011 } while (1);
02012 }
02013 }
02014
02015
02016
02017
02018 memset (&d1, 0, sizeof d1);
02019 if (offer == DHCPOFFER &&
02020 (oc = lookup_option (&server_universe, state -> options,
02021 SV_MIN_SECS))) {
02022 if (evaluate_option_cache (&d1, packet, lease,
02023 (struct client_state *)0,
02024 packet -> options, state -> options,
02025 &lease -> scope, oc, MDL)) {
02026 if (d1.len &&
02027 ntohs (packet -> raw -> secs) < d1.data [0]) {
02028 log_info("%s: configured min-secs value (%d) "
02029 "is greater than secs field (%d). "
02030 "message dropped.", msg, d1.data[0],
02031 ntohs(packet->raw->secs));
02032 data_string_forget (&d1, MDL);
02033 free_lease_state (state, MDL);
02034 if (host)
02035 host_dereference (&host, MDL);
02036 return;
02037 }
02038 data_string_forget (&d1, MDL);
02039 }
02040 }
02041
02042
02043
02044 if (!host) {
02045 struct host_decl *hp = (struct host_decl *)0;
02046 struct host_decl *h;
02047
02048
02049
02050
02051
02052
02053 oc = lookup_option (&dhcp_universe, packet -> options,
02054 DHO_DHCP_CLIENT_IDENTIFIER);
02055 if (oc &&
02056 evaluate_option_cache (&d1, packet, lease,
02057 (struct client_state *)0,
02058 packet -> options, state -> options,
02059 &lease -> scope, oc, MDL)) {
02060 find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
02061 data_string_forget (&d1, MDL);
02062 for (h = hp; h; h = h -> n_ipaddr) {
02063 if (!h -> fixed_addr)
02064 break;
02065 }
02066 if (h)
02067 host_reference (&host, h, MDL);
02068 if (hp != NULL)
02069 host_dereference(&hp, MDL);
02070 }
02071 if (!host) {
02072 find_hosts_by_haddr (&hp,
02073 packet -> raw -> htype,
02074 packet -> raw -> chaddr,
02075 packet -> raw -> hlen,
02076 MDL);
02077 for (h = hp; h; h = h -> n_ipaddr) {
02078 if (!h -> fixed_addr)
02079 break;
02080 }
02081 if (h)
02082 host_reference (&host, h, MDL);
02083 if (hp != NULL)
02084 host_dereference(&hp, MDL);
02085 }
02086 if (!host) {
02087 find_hosts_by_option(&hp, packet,
02088 packet->options, MDL);
02089 for (h = hp; h; h = h -> n_ipaddr) {
02090 if (!h -> fixed_addr)
02091 break;
02092 }
02093 if (h)
02094 host_reference (&host, h, MDL);
02095 if (hp != NULL)
02096 host_dereference(&hp, MDL);
02097 }
02098 }
02099
02100
02101
02102 if (host)
02103 execute_statements_in_scope (NULL, packet, lease, NULL,
02104 packet->options, state->options,
02105 &lease->scope, host->group,
02106 (lease->pool
02107 ? lease->pool->group
02108 : lease->subnet->group),
02109 NULL);
02110
02111
02112
02113 if (!host &&
02114 (oc = lookup_option (&server_universe, state -> options,
02115 SV_BOOT_UNKNOWN_CLIENTS)) &&
02116 !evaluate_boolean_option_cache (&ignorep,
02117 packet, lease,
02118 (struct client_state *)0,
02119 packet -> options,
02120 state -> options,
02121 &lease -> scope, oc, MDL)) {
02122 if (!ignorep)
02123 log_info ("%s: unknown client", msg);
02124 free_lease_state (state, MDL);
02125 if (host)
02126 host_dereference (&host, MDL);
02127 return;
02128 }
02129
02130
02131 if (!offer &&
02132 (oc = lookup_option (&server_universe, state -> options,
02133 SV_ALLOW_BOOTP)) &&
02134 !evaluate_boolean_option_cache (&ignorep,
02135 packet, lease,
02136 (struct client_state *)0,
02137 packet -> options,
02138 state -> options,
02139 &lease -> scope, oc, MDL)) {
02140 if (!ignorep)
02141 log_info ("%s: bootp disallowed", msg);
02142 free_lease_state (state, MDL);
02143 if (host)
02144 host_dereference (&host, MDL);
02145 return;
02146 }
02147
02148
02149 oc = lookup_option (&server_universe, state -> options,
02150 SV_ALLOW_BOOTING);
02151 if (oc &&
02152 !evaluate_boolean_option_cache (&ignorep,
02153 packet, lease,
02154 (struct client_state *)0,
02155 packet -> options,
02156 state -> options,
02157 &lease -> scope, oc, MDL)) {
02158 if (!ignorep)
02159 log_info ("%s: booting disallowed", msg);
02160 free_lease_state (state, MDL);
02161 if (host)
02162 host_dereference (&host, MDL);
02163 return;
02164 }
02165
02166
02167 if (have_billing_classes && !(lease -> flags & STATIC_LEASE)) {
02168
02169
02170
02171 if (lease -> billing_class) {
02172 for (i = 0; i < packet -> class_count; i++)
02173 if (packet -> classes [i] ==
02174 lease -> billing_class)
02175 break;
02176 if (i == packet -> class_count)
02177 unbill_class (lease, lease -> billing_class);
02178 }
02179
02180
02181
02182 if (lease->billing_class == NULL) {
02183 char *cname = "";
02184 int bill = 0;
02185
02186 for (i = 0; i < packet->class_count; i++) {
02187 struct class *billclass, *subclass;
02188
02189 billclass = packet->classes[i];
02190 if (billclass->lease_limit) {
02191 bill++;
02192 if (bill_class(lease, billclass))
02193 break;
02194
02195 subclass = billclass->superclass;
02196 if (subclass == NULL)
02197 cname = subclass->name;
02198 else
02199 cname = billclass->name;
02200 }
02201 }
02202 if (bill != 0 && i == packet->class_count) {
02203 log_info("%s: no available billing: lease "
02204 "limit reached in all matching "
02205 "classes (last: '%s')", msg, cname);
02206 free_lease_state(state, MDL);
02207 if (host)
02208 host_dereference(&host, MDL);
02209 return;
02210 }
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221 if (offer == DHCPOFFER &&
02222 lease->billing_class != NULL &&
02223 lease->binding_state != FTS_ACTIVE)
02224 unbill_class(lease, lease->billing_class);
02225 }
02226 }
02227
02228
02229 oc = lookup_option (&server_universe, state -> options, SV_FILENAME);
02230 if (oc)
02231 evaluate_option_cache (&state -> filename, packet, lease,
02232 (struct client_state *)0,
02233 packet -> options, state -> options,
02234 &lease -> scope, oc, MDL);
02235
02236
02237 oc = lookup_option (&server_universe, state -> options,
02238 SV_SERVER_NAME);
02239 if (oc)
02240 evaluate_option_cache (&state -> server_name, packet, lease,
02241 (struct client_state *)0,
02242 packet -> options, state -> options,
02243 &lease -> scope, oc, MDL);
02244
02245
02246
02247
02248 lt = (struct lease *)0;
02249 result = lease_allocate (<, MDL);
02250 if (result != ISC_R_SUCCESS) {
02251 log_info ("%s: can't allocate temporary lease structure: %s",
02252 msg, isc_result_totext (result));
02253 free_lease_state (state, MDL);
02254 if (host)
02255 host_dereference (&host, MDL);
02256 return;
02257 }
02258
02259
02260
02261 lt -> ip_addr = lease -> ip_addr;
02262
02263
02264 lt -> starts = cur_time;
02265
02266
02267
02268 if (offer) {
02269 lt->flags &= ~BOOTP_LEASE;
02270
02271 default_lease_time = DEFAULT_DEFAULT_LEASE_TIME;
02272 if ((oc = lookup_option (&server_universe, state -> options,
02273 SV_DEFAULT_LEASE_TIME))) {
02274 if (evaluate_option_cache (&d1, packet, lease,
02275 (struct client_state *)0,
02276 packet -> options,
02277 state -> options,
02278 &lease -> scope, oc, MDL)) {
02279 if (d1.len == sizeof (u_int32_t))
02280 default_lease_time =
02281 getULong (d1.data);
02282 data_string_forget (&d1, MDL);
02283 }
02284 }
02285
02286 if ((oc = lookup_option (&dhcp_universe, packet -> options,
02287 DHO_DHCP_LEASE_TIME)))
02288 s1 = evaluate_option_cache (&d1, packet, lease,
02289 (struct client_state *)0,
02290 packet -> options,
02291 state -> options,
02292 &lease -> scope, oc, MDL);
02293 else
02294 s1 = 0;
02295
02296 if (s1 && (d1.len == 4)) {
02297 u_int32_t ones = 0xffffffff;
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323 if ((memcmp(d1.data, &ones, 4) == 0) &&
02324 (oc = lookup_option(&server_universe,
02325 state->options,
02326 SV_RESERVE_INFINITE)) &&
02327 evaluate_boolean_option_cache(&ignorep, packet,
02328 lease, NULL, packet->options,
02329 state->options, &lease->scope,
02330 oc, MDL)) {
02331 lt->flags |= RESERVED_LEASE;
02332 if (!ignorep)
02333 log_info("Infinite-leasetime "
02334 "reservation made on %s.",
02335 piaddr(lt->ip_addr));
02336 }
02337
02338 lease_time = getULong (d1.data);
02339 } else
02340 lease_time = default_lease_time;
02341
02342 if (s1)
02343 data_string_forget(&d1, MDL);
02344
02345
02346 max_lease_time = DEFAULT_MAX_LEASE_TIME;
02347 if ((oc = lookup_option (&server_universe, state -> options,
02348 SV_MAX_LEASE_TIME))) {
02349 if (evaluate_option_cache (&d1, packet, lease,
02350 (struct client_state *)0,
02351 packet -> options,
02352 state -> options,
02353 &lease -> scope, oc, MDL)) {
02354 if (d1.len == sizeof (u_int32_t))
02355 max_lease_time =
02356 getULong (d1.data);
02357 data_string_forget (&d1, MDL);
02358 }
02359 }
02360
02361
02362 if (lease_time < 0
02363 || lease_time > max_lease_time)
02364 lease_time = max_lease_time;
02365
02366 min_lease_time = DEFAULT_MIN_LEASE_TIME;
02367 if (min_lease_time > max_lease_time)
02368 min_lease_time = max_lease_time;
02369
02370 if ((oc = lookup_option (&server_universe, state -> options,
02371 SV_MIN_LEASE_TIME))) {
02372 if (evaluate_option_cache (&d1, packet, lease,
02373 (struct client_state *)0,
02374 packet -> options,
02375 state -> options,
02376 &lease -> scope, oc, MDL)) {
02377 if (d1.len == sizeof (u_int32_t))
02378 min_lease_time = getULong (d1.data);
02379 data_string_forget (&d1, MDL);
02380 }
02381 }
02382
02383
02384
02385
02386
02387 memset(&d1, 0, sizeof(d1));
02388 if (lease->pool &&
02389 (oc = lookup_option(&server_universe, state->options,
02390 SV_ADAPTIVE_LEASE_TIME_THRESHOLD)) &&
02391 evaluate_option_cache(&d1, packet, lease, NULL,
02392 packet->options, state->options,
02393 &lease->scope, oc, MDL)) {
02394 if (d1.len == 1 && d1.data[0] > 0 &&
02395 d1.data[0] < 100) {
02396 TIME adaptive_time;
02397 int poolfilled, total, count;
02398
02399 if (min_lease_time)
02400 adaptive_time = min_lease_time;
02401 else
02402 adaptive_time = DEFAULT_MIN_LEASE_TIME;
02403
02404
02405 if (lease->ends - cur_time > adaptive_time)
02406 adaptive_time = lease->ends - cur_time;
02407
02408 count = lease->pool->lease_count;
02409 total = count - (lease->pool->free_leases +
02410 lease->pool->backup_leases);
02411
02412 poolfilled = (total > (INT_MAX / 100)) ?
02413 total / (count / 100) :
02414 (total * 100) / count;
02415
02416 log_debug("Adap-lease: Total: %d, Free: %d, "
02417 "Ends: %d, Adaptive: %d, Fill: %d, "
02418 "Threshold: %d",
02419 lease->pool->lease_count,
02420 lease->pool->free_leases,
02421 (int)(lease->ends - cur_time),
02422 (int)adaptive_time, poolfilled,
02423 d1.data[0]);
02424
02425 if (poolfilled >= d1.data[0] &&
02426 lease_time > adaptive_time) {
02427 log_info("Pool over threshold, time "
02428 "for %s reduced from %d to "
02429 "%d.", piaddr(lease->ip_addr),
02430 (int)lease_time,
02431 (int)adaptive_time);
02432
02433 lease_time = adaptive_time;
02434 }
02435 }
02436 data_string_forget(&d1, MDL);
02437 }
02438
02439
02440 if (lease->pool && lease->pool->valid_from &&
02441 cur_time < lease->pool->valid_from) {
02442
02443 cip.len = 4;
02444 memcpy (cip.iabuf, <->ip_addr.iabuf, 4);
02445 nak_lease(packet, &cip);
02446 free_lease_state (state, MDL);
02447 lease_dereference (<, MDL);
02448 if (host)
02449 host_dereference (&host, MDL);
02450 return;
02451
02452 }
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470 if (lease->pool && lease->pool->valid_until) {
02471 if (cur_time >= lease->pool->valid_until) {
02472
02473 cip.len = 4;
02474 memcpy (cip.iabuf, <->ip_addr.iabuf, 4);
02475 nak_lease(packet, &cip);
02476 free_lease_state (state, MDL);
02477 lease_dereference (<, MDL);
02478 if (host)
02479 host_dereference (&host, MDL);
02480 return;
02481 }
02482 remaining_time = lease->pool->valid_until - cur_time;
02483 if (lease_time > remaining_time)
02484 lease_time = remaining_time;
02485 }
02486
02487 if (lease_time < min_lease_time) {
02488 if (min_lease_time)
02489 lease_time = min_lease_time;
02490 else
02491 lease_time = default_lease_time;
02492 }
02493
02494
02495 #if defined (FAILOVER_PROTOCOL)
02496
02497
02498 if (lease -> pool && lease -> pool -> failover_peer) {
02499 TIME new_lease_time = lease_time;
02500 dhcp_failover_state_t *peer =
02501 lease -> pool -> failover_peer;
02502
02503
02504 lt->tsfp = lease->tsfp;
02505 lt->atsfp = lease->atsfp;
02506
02507
02508
02509
02510 if (lease_time > peer->mclt) {
02511
02512
02513
02514
02515
02516
02517 if (lt->tsfp <= cur_time)
02518 new_lease_time = peer->mclt;
02519 else if ((cur_time + lease_time) >
02520 (lt->tsfp + peer->mclt))
02521 new_lease_time = (lt->tsfp - cur_time)
02522 + peer->mclt;
02523 }
02524
02525
02526
02527
02528
02529
02530
02531
02532 if (offer == DHCPACK) {
02533 lt->tstp = cur_time + lease_time +
02534 (new_lease_time / 2);
02535
02536
02537
02538
02539
02540
02541 if (lt->tstp < lt->tsfp)
02542 lt->tsfp = lt->tstp;
02543 } else
02544 lt->tstp = lease->tstp;
02545
02546
02547 lease_time = new_lease_time;
02548 }
02549 #endif
02550
02551
02552
02553 if (cur_time + lease_time < cur_time)
02554 state -> offered_expiry = MAX_TIME - 1;
02555 else
02556 state -> offered_expiry = cur_time + lease_time;
02557 if (when)
02558 lt -> ends = when;
02559 else
02560 lt -> ends = state -> offered_expiry;
02561
02562
02563
02564 if (offer == DHCPACK)
02565 lt -> next_binding_state = FTS_ACTIVE;
02566 else
02567 lt -> next_binding_state = lease -> binding_state;
02568 } else {
02569 lt->flags |= BOOTP_LEASE;
02570
02571 lease_time = MAX_TIME - cur_time;
02572
02573 if ((oc = lookup_option (&server_universe, state -> options,
02574 SV_BOOTP_LEASE_LENGTH))) {
02575 if (evaluate_option_cache (&d1, packet, lease,
02576 (struct client_state *)0,
02577 packet -> options,
02578 state -> options,
02579 &lease -> scope, oc, MDL)) {
02580 if (d1.len == sizeof (u_int32_t))
02581 lease_time = getULong (d1.data);
02582 data_string_forget (&d1, MDL);
02583 }
02584 }
02585
02586 if ((oc = lookup_option (&server_universe, state -> options,
02587 SV_BOOTP_LEASE_CUTOFF))) {
02588 if (evaluate_option_cache (&d1, packet, lease,
02589 (struct client_state *)0,
02590 packet -> options,
02591 state -> options,
02592 &lease -> scope, oc, MDL)) {
02593 if (d1.len == sizeof (u_int32_t))
02594 lease_time = (getULong (d1.data) -
02595 cur_time);
02596 data_string_forget (&d1, MDL);
02597 }
02598 }
02599
02600 lt -> ends = state -> offered_expiry = cur_time + lease_time;
02601 lt -> next_binding_state = FTS_ACTIVE;
02602 }
02603
02604
02605 lt->cltt = cur_time;
02606
02607
02608 oc = lookup_option(&server_universe, state->options,
02609 SV_IGNORE_CLIENT_UIDS);
02610 if ((oc == NULL) ||
02611 !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
02612 packet->options, state->options,
02613 &lease->scope, oc, MDL)) {
02614
02615
02616 oc = lookup_option (&dhcp_universe, packet -> options,
02617 DHO_DHCP_CLIENT_IDENTIFIER);
02618 if (oc &&
02619 evaluate_option_cache(&d1, packet, lease, NULL,
02620 packet->options, state->options,
02621 &lease->scope, oc, MDL)) {
02622 if (d1.len <= sizeof(lt->uid_buf)) {
02623 memcpy(lt->uid_buf, d1.data, d1.len);
02624 lt->uid = lt->uid_buf;
02625 lt->uid_max = sizeof(lt->uid_buf);
02626 lt->uid_len = d1.len;
02627 } else {
02628 unsigned char *tuid;
02629 lt->uid_max = d1.len;
02630 lt->uid_len = d1.len;
02631 tuid = (unsigned char *)dmalloc(lt->uid_max,
02632 MDL);
02633
02634 if (!tuid)
02635 log_fatal ("no memory for large uid.");
02636 memcpy(tuid, d1.data, lt->uid_len);
02637 lt->uid = tuid;
02638 }
02639 data_string_forget (&d1, MDL);
02640 }
02641 }
02642
02643 if (host) {
02644 host_reference (< -> host, host, MDL);
02645 host_dereference (&host, MDL);
02646 }
02647 if (lease -> subnet)
02648 subnet_reference (< -> subnet, lease -> subnet, MDL);
02649 if (lease -> billing_class)
02650 class_reference (< -> billing_class,
02651 lease -> billing_class, MDL);
02652
02653
02654
02655 if (ms_nulltp)
02656 lease -> flags |= MS_NULL_TERMINATION;
02657 else
02658 lease -> flags &= ~MS_NULL_TERMINATION;
02659
02660
02661 if (lease -> scope) {
02662 binding_scope_reference (< -> scope, lease -> scope, MDL);
02663 binding_scope_dereference (&lease -> scope, MDL);
02664 }
02665 if (lease -> agent_options)
02666 option_chain_head_reference (< -> agent_options,
02667 lease -> agent_options, MDL);
02668
02669
02670 oc = lookup_option(&dhcp_universe, packet->options,
02671 DHO_VENDOR_CLASS_IDENTIFIER);
02672 if (oc != NULL &&
02673 evaluate_option_cache(&d1, packet, NULL, NULL, packet->options,
02674 NULL, &lease->scope, oc, MDL)) {
02675 if (d1.len != 0) {
02676 bind_ds_value(&lease->scope, "vendor-class-identifier",
02677 &d1);
02678 }
02679
02680 data_string_forget(&d1, MDL);
02681 }
02682
02683
02684
02685
02686
02687
02688
02689 if (!packet->agent_options_stashed &&
02690 (packet->options != NULL) &&
02691 packet->options->universe_count > agent_universe.index &&
02692 packet->options->universes[agent_universe.index] != NULL) {
02693 oc = lookup_option (&server_universe, state -> options,
02694 SV_STASH_AGENT_OPTIONS);
02695 if (!oc ||
02696 evaluate_boolean_option_cache (&ignorep, packet, lease,
02697 (struct client_state *)0,
02698 packet -> options,
02699 state -> options,
02700 &lease -> scope, oc, MDL)) {
02701 if (lt -> agent_options)
02702 option_chain_head_dereference (< -> agent_options, MDL);
02703 option_chain_head_reference
02704 (< -> agent_options,
02705 (struct option_chain_head *)
02706 packet -> options -> universes [agent_universe.index],
02707 MDL);
02708 }
02709 }
02710
02711
02712 oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME);
02713 if (oc)
02714 s1 = evaluate_option_cache (&d1, packet, (struct lease *)0,
02715 (struct client_state *)0,
02716 packet -> options,
02717 (struct option_state *)0,
02718 &global_scope, oc, MDL);
02719 else
02720 s1 = 0;
02721
02722 if (oc && s1 &&
02723 lease -> client_hostname &&
02724 strlen (lease -> client_hostname) == d1.len &&
02725 !memcmp (lease -> client_hostname, d1.data, d1.len)) {
02726
02727 data_string_forget (&d1, MDL);
02728 lt -> client_hostname = lease -> client_hostname;
02729 lease -> client_hostname = (char *)0;
02730 } else if (oc && s1) {
02731 lt -> client_hostname = dmalloc (d1.len + 1, MDL);
02732 if (!lt -> client_hostname)
02733 log_error ("no memory for client hostname.");
02734 else {
02735 memcpy (lt -> client_hostname, d1.data, d1.len);
02736 lt -> client_hostname [d1.len] = 0;
02737 }
02738 data_string_forget (&d1, MDL);
02739 }
02740
02741
02742 lt -> hardware_addr.hlen = packet -> raw -> hlen + 1;
02743 lt -> hardware_addr.hbuf [0] = packet -> raw -> htype;
02744 memcpy (< -> hardware_addr.hbuf [1], packet -> raw -> chaddr,
02745 sizeof packet -> raw -> chaddr);
02746
02747 lt -> flags = lease -> flags & ~PERSISTENT_FLAGS;
02748
02749
02750
02751 if (lease->on_star.on_commit && (!offer || offer == DHCPACK)) {
02752 execute_statements (NULL, packet, lt, NULL, packet->options,
02753 state->options, <->scope,
02754 lease->on_star.on_commit, NULL);
02755 if (lease->on_star.on_commit)
02756 executable_statement_dereference
02757 (&lease->on_star.on_commit, MDL);
02758 }
02759
02760 #ifdef NSUPDATE
02761
02762 if ((!offer || offer == DHCPACK) &&
02763 (!(oc = lookup_option (&server_universe, state -> options,
02764 SV_DDNS_UPDATES)) ||
02765 evaluate_boolean_option_cache (&ignorep, packet, lt,
02766 (struct client_state *)0,
02767 packet -> options,
02768 state -> options,
02769 < -> scope, oc, MDL))) {
02770 ddns_updates(packet, lt, lease, NULL, NULL, state->options);
02771 }
02772 #endif
02773
02774
02775 if (lease -> flags & STATIC_LEASE) {
02776
02777
02778 lease -> hardware_addr.hlen = packet -> raw -> hlen + 1;
02779 lease -> hardware_addr.hbuf [0] = packet -> raw -> htype;
02780 memcpy (&lease -> hardware_addr.hbuf [1],
02781 packet -> raw -> chaddr,
02782 sizeof packet -> raw -> chaddr);
02783 } else {
02784 int commit = (!offer || (offer == DHCPACK));
02785 int thresh = DEFAULT_CACHE_THRESHOLD;
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795 if ((oc = lookup_option(&server_universe, state->options,
02796 SV_CACHE_THRESHOLD)) &&
02797 evaluate_option_cache(&d1, packet, lt, NULL,
02798 packet->options, state->options,
02799 <->scope, oc, MDL)) {
02800 if (d1.len == 1 && (d1.data[0] < 100))
02801 thresh = d1.data[0];
02802
02803 data_string_forget(&d1, MDL);
02804 }
02805
02806
02807
02808
02809
02810
02811
02812 if ((lt->ddns_cb == NULL) &&
02813 (thresh > 0) && (offer == DHCPACK) &&
02814 (lease->binding_state == FTS_ACTIVE)) {
02815 int limit;
02816 int prev_lease = lease->ends - lease->starts;
02817
02818
02819 if (prev_lease <= (INT_MAX / thresh))
02820 limit = prev_lease * thresh / 100;
02821 else
02822 limit = prev_lease / 100 * thresh;
02823
02824 if ((lt->starts - lease->starts) <= limit) {
02825 lt->starts = lease->starts;
02826 state->offered_expiry = lt->ends = lease->ends;
02827 commit = 0;
02828 use_old_lease = 1;
02829 }
02830 }
02831
02832 #if !defined(DELAYED_ACK)
02833
02834
02835
02836
02837
02838
02839
02840
02841 if ((use_old_lease == 0) &&
02842 !supersede_lease(lease, lt, commit,
02843 offer == DHCPACK, offer == DHCPACK)) {
02844 #else
02845
02846
02847
02848
02849 if (commit)
02850 enqueue = ISC_TRUE;
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861 if ((use_old_lease == 0) &&
02862 !supersede_lease(lease, lt, 0,
02863 !offer || offer == DHCPACK, 0)) {
02864 #endif
02865 log_info ("%s: database update failed", msg);
02866 free_lease_state (state, MDL);
02867 lease_dereference (<, MDL);
02868 return;
02869 }
02870 }
02871 lease_dereference (<, MDL);
02872
02873
02874 state -> ip = packet -> interface;
02875
02876
02877 state -> giaddr = packet -> raw -> giaddr;
02878 state -> ciaddr = packet -> raw -> ciaddr;
02879 state -> xid = packet -> raw -> xid;
02880 state -> secs = packet -> raw -> secs;
02881 state -> bootp_flags = packet -> raw -> flags;
02882 state -> hops = packet -> raw -> hops;
02883 state -> offer = offer;
02884
02885
02886
02887 if ((oc = lookup_option (&server_universe, state -> options,
02888 SV_ALWAYS_BROADCAST)) &&
02889 evaluate_boolean_option_cache (&ignorep, packet, lease,
02890 (struct client_state *)0,
02891 packet -> options, state -> options,
02892 &lease -> scope, oc, MDL))
02893 state -> bootp_flags |= htons (BOOTP_BROADCAST);
02894
02895
02896
02897 oc = lookup_option (&dhcp_universe, packet -> options,
02898 DHO_DHCP_MAX_MESSAGE_SIZE);
02899 if (oc &&
02900 evaluate_option_cache (&d1, packet, lease,
02901 (struct client_state *)0,
02902 packet -> options, state -> options,
02903 &lease -> scope, oc, MDL)) {
02904 if (d1.len == sizeof (u_int16_t))
02905 state -> max_message_size = getUShort (d1.data);
02906 data_string_forget (&d1, MDL);
02907 } else {
02908 oc = lookup_option (&dhcp_universe, state -> options,
02909 DHO_DHCP_MAX_MESSAGE_SIZE);
02910 if (oc &&
02911 evaluate_option_cache (&d1, packet, lease,
02912 (struct client_state *)0,
02913 packet -> options, state -> options,
02914 &lease -> scope, oc, MDL)) {
02915 if (d1.len == sizeof (u_int16_t))
02916 state -> max_message_size =
02917 getUShort (d1.data);
02918 data_string_forget (&d1, MDL);
02919 }
02920 }
02921
02922
02923
02924 if ((oc = lookup_option (&dhcp_universe, packet -> options,
02925 DHO_SUBNET_SELECTION))) {
02926
02927
02928 struct option_cache *noc = (struct option_cache *)0;
02929 if (option_cache_allocate (&noc, MDL)) {
02930 if (oc -> data.len)
02931 data_string_copy (&noc -> data,
02932 &oc -> data, MDL);
02933 if (oc -> expression)
02934 expression_reference (&noc -> expression,
02935 oc -> expression, MDL);
02936 if (oc -> option)
02937 option_reference(&(noc->option), oc->option,
02938 MDL);
02939
02940 save_option (&dhcp_universe, state -> options, noc);
02941 option_cache_dereference (&noc, MDL);
02942 }
02943 }
02944
02945
02946
02947 if (state -> offer) {
02948 i = DHO_DHCP_MESSAGE_TYPE;
02949 oc = (struct option_cache *)0;
02950 if (option_cache_allocate (&oc, MDL)) {
02951 if (make_const_data (&oc -> expression,
02952 &state -> offer, 1, 0, 0, MDL)) {
02953 option_code_hash_lookup(&oc->option,
02954 dhcp_universe.code_hash,
02955 &i, 0, MDL);
02956 save_option (&dhcp_universe,
02957 state -> options, oc);
02958 }
02959 option_cache_dereference (&oc, MDL);
02960 }
02961
02962 get_server_source_address(&from, state->options,
02963 state->options, packet);
02964 memcpy(state->from.iabuf, &from, sizeof(from));
02965 state->from.len = sizeof(from);
02966
02967 offered_lease_time =
02968 state -> offered_expiry - cur_time;
02969
02970 putULong(state->expiry, (u_int32_t)offered_lease_time);
02971 i = DHO_DHCP_LEASE_TIME;
02972 oc = (struct option_cache *)0;
02973 if (option_cache_allocate (&oc, MDL)) {
02974 if (make_const_data(&oc->expression, state->expiry,
02975 4, 0, 0, MDL)) {
02976 option_code_hash_lookup(&oc->option,
02977 dhcp_universe.code_hash,
02978 &i, 0, MDL);
02979 save_option (&dhcp_universe,
02980 state -> options, oc);
02981 }
02982 option_cache_dereference (&oc, MDL);
02983 }
02984
02985
02986
02987
02988
02989
02990 if ((oc = lookup_option(&dhcp_universe, state->options,
02991 DHO_DHCP_REBINDING_TIME)) != NULL &&
02992 evaluate_option_cache(&d1, packet, lease, NULL,
02993 packet->options, state->options,
02994 &lease->scope, oc, MDL)) {
02995 TIME rebind_time = getULong(d1.data);
02996
02997
02998 if (rebind_time >= offered_lease_time)
02999 delete_option(&dhcp_universe, state->options,
03000 DHO_DHCP_REBINDING_TIME);
03001 else
03002 offered_lease_time = rebind_time;
03003
03004 data_string_forget(&d1, MDL);
03005 }
03006
03007 if ((oc = lookup_option(&dhcp_universe, state->options,
03008 DHO_DHCP_RENEWAL_TIME)) != NULL &&
03009 evaluate_option_cache(&d1, packet, lease, NULL,
03010 packet->options, state->options,
03011 &lease->scope, oc, MDL)) {
03012 if (getULong(d1.data) >= offered_lease_time)
03013 delete_option(&dhcp_universe, state->options,
03014 DHO_DHCP_RENEWAL_TIME);
03015
03016 data_string_forget(&d1, MDL);
03017 }
03018 } else {
03019
03020 if (state -> ip -> address_count) {
03021 state -> from.len =
03022 sizeof state -> ip -> addresses [0];
03023 memcpy (state -> from.iabuf,
03024 &state -> ip -> addresses [0],
03025 state -> from.len);
03026 }
03027 }
03028
03029
03030 memset (&state -> siaddr, 0, sizeof state -> siaddr);
03031 if ((oc =
03032 lookup_option (&server_universe,
03033 state -> options, SV_NEXT_SERVER))) {
03034 if (evaluate_option_cache (&d1, packet, lease,
03035 (struct client_state *)0,
03036 packet -> options, state -> options,
03037 &lease -> scope, oc, MDL)) {
03038
03039
03040 if (d1.len >= 4 && d1.data)
03041 memcpy (&state -> siaddr, d1.data, 4);
03042 data_string_forget (&d1, MDL);
03043 }
03044 }
03045
03046
03047
03048 i = DHO_SUBNET_MASK;
03049 if (!lookup_option (&dhcp_universe, state -> options, i)) {
03050 oc = (struct option_cache *)0;
03051 if (option_cache_allocate (&oc, MDL)) {
03052 if (make_const_data (&oc -> expression,
03053 lease -> subnet -> netmask.iabuf,
03054 lease -> subnet -> netmask.len,
03055 0, 0, MDL)) {
03056 option_code_hash_lookup(&oc->option,
03057 dhcp_universe.code_hash,
03058 &i, 0, MDL);
03059 save_option (&dhcp_universe,
03060 state -> options, oc);
03061 }
03062 option_cache_dereference (&oc, MDL);
03063 }
03064 }
03065
03066
03067
03068
03069 i = DHO_HOST_NAME;
03070 j = SV_USE_HOST_DECL_NAMES;
03071 if (!lookup_option (&dhcp_universe, state -> options, i) &&
03072 lease -> host && lease -> host -> name &&
03073 (evaluate_boolean_option_cache
03074 (&ignorep, packet, lease, (struct client_state *)0,
03075 packet -> options, state -> options, &lease -> scope,
03076 lookup_option (&server_universe, state -> options, j), MDL))) {
03077 oc = (struct option_cache *)0;
03078 if (option_cache_allocate (&oc, MDL)) {
03079 if (make_const_data (&oc -> expression,
03080 ((unsigned char *)
03081 lease -> host -> name),
03082 strlen (lease -> host -> name),
03083 1, 0, MDL)) {
03084 option_code_hash_lookup(&oc->option,
03085 dhcp_universe.code_hash,
03086 &i, 0, MDL);
03087 save_option (&dhcp_universe,
03088 state -> options, oc);
03089 }
03090 option_cache_dereference (&oc, MDL);
03091 }
03092 }
03093
03094
03095
03096 i = DHO_HOST_NAME;
03097 j = SV_GET_LEASE_HOSTNAMES;
03098 if (!lookup_option(&dhcp_universe, state->options, i) &&
03099 evaluate_boolean_option_cache
03100 (&ignorep, packet, lease, NULL,
03101 packet->options, state->options, &lease->scope,
03102 lookup_option (&server_universe, state->options, j), MDL)) {
03103 struct in_addr ia;
03104 struct hostent *h;
03105
03106 memcpy (&ia, lease -> ip_addr.iabuf, 4);
03107
03108 h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
03109 if (!h)
03110 log_error ("No hostname for %s", inet_ntoa (ia));
03111 else {
03112 oc = (struct option_cache *)0;
03113 if (option_cache_allocate (&oc, MDL)) {
03114 if (make_const_data (&oc -> expression,
03115 ((unsigned char *)
03116 h -> h_name),
03117 strlen (h -> h_name) + 1,
03118 1, 1, MDL)) {
03119 option_code_hash_lookup(&oc->option,
03120 dhcp_universe.code_hash,
03121 &i, 0, MDL);
03122 save_option (&dhcp_universe,
03123 state -> options, oc);
03124 }
03125 option_cache_dereference (&oc, MDL);
03126 }
03127 }
03128 }
03129
03130
03131
03132
03133
03134 if (evaluate_boolean_option_cache
03135 (&ignorep, packet, lease, (struct client_state *)0,
03136 packet -> options, state -> options, &lease -> scope,
03137 lookup_option (&server_universe, state -> options,
03138 SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE), MDL)) {
03139 i = DHO_ROUTERS;
03140 oc = lookup_option (&dhcp_universe, state -> options, i);
03141 if (!oc) {
03142 oc = (struct option_cache *)0;
03143 if (option_cache_allocate (&oc, MDL)) {
03144 if (make_const_data (&oc -> expression,
03145 lease -> ip_addr.iabuf,
03146 lease -> ip_addr.len,
03147 0, 0, MDL)) {
03148 option_code_hash_lookup(&oc->option,
03149 dhcp_universe.code_hash,
03150 &i, 0, MDL);
03151 save_option (&dhcp_universe,
03152 state -> options, oc);
03153 }
03154 option_cache_dereference (&oc, MDL);
03155 }
03156 }
03157 }
03158
03159
03160
03161 i = SV_SITE_OPTION_SPACE;
03162 if ((oc = lookup_option (&server_universe, state -> options, i)) &&
03163 evaluate_option_cache (&d1, packet, lease,
03164 (struct client_state *)0,
03165 packet -> options, state -> options,
03166 &lease -> scope, oc, MDL)) {
03167 struct universe *u = (struct universe *)0;
03168
03169 if (!universe_hash_lookup (&u, universe_hash,
03170 (const char *)d1.data, d1.len,
03171 MDL)) {
03172 log_error ("unknown option space %s.", d1.data);
03173 return;
03174 }
03175
03176 state -> options -> site_universe = u -> index;
03177 state->options->site_code_min = find_min_site_code(u);
03178 data_string_forget (&d1, MDL);
03179 } else {
03180 state -> options -> site_code_min = 0;
03181 state -> options -> site_universe = dhcp_universe.index;
03182 }
03183
03184
03185
03186
03187
03188
03189 oc = lookup_option (&dhcp_universe, state -> options,
03190 DHO_DHCP_PARAMETER_REQUEST_LIST);
03191
03192 if (!oc)
03193 oc = lookup_option (&dhcp_universe, packet -> options,
03194 DHO_DHCP_PARAMETER_REQUEST_LIST);
03195 if (oc)
03196 evaluate_option_cache (&state -> parameter_request_list,
03197 packet, lease, (struct client_state *)0,
03198 packet -> options, state -> options,
03199 &lease -> scope, oc, MDL);
03200
03201 #ifdef DEBUG_PACKET
03202 dump_packet (packet);
03203 dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
03204 #endif
03205
03206 lease -> state = state;
03207
03208 log_info ("%s", msg);
03209
03210
03211 packet_reference (&lease -> state -> packet, packet, MDL);
03212
03213
03214
03215 if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE) &&
03216 ((cur_time - lease_cltt) > 60) &&
03217 (!(oc = lookup_option (&server_universe, state -> options,
03218 SV_PING_CHECKS)) ||
03219 evaluate_boolean_option_cache (&ignorep, packet, lease,
03220 (struct client_state *)0,
03221 packet -> options,
03222 state -> options,
03223 &lease -> scope, oc, MDL))) {
03224 icmp_echorequest (&lease -> ip_addr);
03225
03226
03227
03228 if ((oc = lookup_option (&server_universe, state -> options,
03229 SV_PING_TIMEOUT)) &&
03230 evaluate_option_cache (&d1, packet, lease, NULL,
03231 packet -> options,
03232 state -> options,
03233 &lease -> scope, oc, MDL)) {
03234 if (d1.len == sizeof (u_int32_t))
03235 ping_timeout = getULong (d1.data);
03236 else
03237 ping_timeout = DEFAULT_PING_TIMEOUT;
03238
03239 data_string_forget (&d1, MDL);
03240 } else
03241 ping_timeout = DEFAULT_PING_TIMEOUT;
03242
03243 #ifdef DEBUG
03244 log_debug ("Ping timeout: %ld", (long)ping_timeout);
03245 #endif
03246
03247
03248
03249
03250
03251
03252
03253 tv.tv_sec = cur_tv.tv_sec + ping_timeout;
03254 tv.tv_usec = cur_tv.tv_usec;
03255 add_timeout (&tv, lease_ping_timeout, lease,
03256 (tvref_t)lease_reference,
03257 (tvunref_t)lease_dereference);
03258 ++outstanding_pings;
03259 } else {
03260 lease->cltt = cur_time;
03261 #if defined(DELAYED_ACK)
03262 if (enqueue)
03263 delayed_ack_enqueue(lease);
03264 else
03265 #endif
03266 dhcp_reply(lease);
03267 }
03268
03269 TRACE(DHCPD_ACK_LEASE_DONE());
03270 }
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281 void
03282 delayed_ack_enqueue(struct lease *lease)
03283 {
03284 struct leasequeue *q;
03285
03286 if (!write_lease(lease))
03287 return;
03288 if (free_ackqueue) {
03289 q = free_ackqueue;
03290 free_ackqueue = q->next;
03291 } else {
03292 q = ((struct leasequeue *)
03293 dmalloc(sizeof(struct leasequeue), MDL));
03294 if (!q)
03295 log_fatal("delayed_ack_enqueue: no memory!");
03296 }
03297 memset(q, 0, sizeof *q);
03298
03299 lease_reference(&q->lease, lease, MDL);
03300 q->next = ackqueue_head;
03301 ackqueue_head = q;
03302 if (!ackqueue_tail)
03303 ackqueue_tail = q;
03304 else
03305 q->next->prev = q;
03306
03307 outstanding_acks++;
03308 if (outstanding_acks > max_outstanding_acks) {
03309 commit_leases();
03310
03311
03312 memset(&max_fsync, 0, sizeof(max_fsync));
03313 cancel_timeout(commit_leases_ackout, NULL);
03314 } else {
03315 struct timeval next_fsync;
03316
03317 if (max_fsync.tv_sec == 0 && max_fsync.tv_usec == 0) {
03318
03319 max_fsync.tv_sec = cur_tv.tv_sec + max_ack_delay_secs;
03320 max_fsync.tv_usec = cur_tv.tv_usec +
03321 max_ack_delay_usecs;
03322
03323 if (max_fsync.tv_usec >= 1000000) {
03324 max_fsync.tv_sec++;
03325 max_fsync.tv_usec -= 1000000;
03326 }
03327 }
03328
03329
03330 next_fsync.tv_sec = cur_tv.tv_sec;
03331 next_fsync.tv_usec = cur_tv.tv_usec + min_ack_delay_usecs;
03332 if (next_fsync.tv_usec >= 1000000) {
03333 next_fsync.tv_sec++;
03334 next_fsync.tv_usec -= 1000000;
03335 }
03336
03337 if ((next_fsync.tv_sec > max_fsync.tv_sec) ||
03338 ((next_fsync.tv_sec == max_fsync.tv_sec) &&
03339 (next_fsync.tv_usec > max_fsync.tv_usec))) {
03340 next_fsync.tv_sec = max_fsync.tv_sec;
03341 next_fsync.tv_usec = max_fsync.tv_usec;
03342 }
03343
03344 add_timeout(&next_fsync, commit_leases_ackout, NULL,
03345 (tvref_t) NULL, (tvunref_t) NULL);
03346 }
03347 }
03348
03349 static void
03350 commit_leases_ackout(void *foo)
03351 {
03352 if (outstanding_acks) {
03353 commit_leases();
03354
03355 memset(&max_fsync, 0, sizeof(max_fsync));
03356 }
03357 }
03358
03359
03360
03361
03362
03363 void
03364 flush_ackqueue(void *foo)
03365 {
03366 struct leasequeue *ack, *p;
03367
03368 for (ack = ackqueue_tail ; ack ; ack = p) {
03369 p = ack->prev;
03370
03371
03372 if (ack->lease->state == NULL)
03373 log_error("delayed ack for %s has gone stale",
03374 piaddr(ack->lease->ip_addr));
03375 else
03376 dhcp_reply(ack->lease);
03377
03378 lease_dereference(&ack->lease, MDL);
03379 ack->next = free_ackqueue;
03380 free_ackqueue = ack;
03381 }
03382 ackqueue_head = NULL;
03383 ackqueue_tail = NULL;
03384 outstanding_acks = 0;
03385 }
03386
03387 #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
03388 void
03389 relinquish_ackqueue(void)
03390 {
03391 struct leasequeue *q, *n;
03392
03393 for (q = ackqueue_head ; q ; q = n) {
03394 n = q->next;
03395 dfree(q, MDL);
03396 }
03397 for (q = free_ackqueue ; q ; q = n) {
03398 n = q->next;
03399 dfree(q, MDL);
03400 }
03401 }
03402 #endif
03403
03404 void dhcp_reply (lease)
03405 struct lease *lease;
03406 {
03407 int bufs = 0;
03408 unsigned packet_length;
03409 struct dhcp_packet raw;
03410 struct sockaddr_in to;
03411 struct in_addr from;
03412 struct hardware hto;
03413 int result;
03414 struct lease_state *state = lease -> state;
03415 int nulltp, bootpp, unicastp = 1;
03416 struct data_string d1;
03417 const char *s;
03418
03419 if (!state)
03420 log_fatal ("dhcp_reply was supplied lease with no state!");
03421
03422 TRACE(DHCPD_REPLY_START());
03423
03424
03425 memset (&raw, 0, sizeof raw);
03426 memset (&d1, 0, sizeof d1);
03427
03428
03429
03430 if (state -> filename.len && state -> filename.data) {
03431 memcpy (raw.file,
03432 state -> filename.data,
03433 state -> filename.len > sizeof raw.file
03434 ? sizeof raw.file : state -> filename.len);
03435 if (sizeof raw.file > state -> filename.len)
03436 memset (&raw.file [state -> filename.len], 0,
03437 (sizeof raw.file) - state -> filename.len);
03438 else
03439 log_info("file name longer than packet field "
03440 "truncated - field: %lu name: %d %.*s",
03441 (unsigned long)sizeof(raw.file),
03442 state->filename.len, (int)state->filename.len,
03443 state->filename.data);
03444 } else
03445 bufs |= 1;
03446
03447
03448
03449 if (state -> server_name.len && state -> server_name.data) {
03450 memcpy (raw.sname,
03451 state -> server_name.data,
03452 state -> server_name.len > sizeof raw.sname
03453 ? sizeof raw.sname : state -> server_name.len);
03454 if (sizeof raw.sname > state -> server_name.len)
03455 memset (&raw.sname [state -> server_name.len], 0,
03456 (sizeof raw.sname) - state -> server_name.len);
03457 else
03458 log_info("server name longer than packet field "
03459 "truncated - field: %lu name: %d %.*s",
03460 (unsigned long)sizeof(raw.sname),
03461 state->server_name.len,
03462 (int)state->server_name.len,
03463 state->server_name.data);
03464 } else
03465 bufs |= 2;
03466
03467 memcpy (raw.chaddr,
03468 &lease -> hardware_addr.hbuf [1], sizeof raw.chaddr);
03469 raw.hlen = lease -> hardware_addr.hlen - 1;
03470 raw.htype = lease -> hardware_addr.hbuf [0];
03471
03472
03473
03474 if (lease -> flags & MS_NULL_TERMINATION)
03475 nulltp = 1;
03476 else
03477 nulltp = 0;
03478
03479
03480 if (state -> offer)
03481 bootpp = 0;
03482 else
03483 bootpp = 1;
03484
03485
03486 packet_length = cons_options (state -> packet, &raw, lease,
03487 (struct client_state *)0,
03488 state -> max_message_size,
03489 state -> packet -> options,
03490 state -> options, &global_scope,
03491 bufs, nulltp, bootpp,
03492 &state -> parameter_request_list,
03493 (char *)0);
03494
03495 memcpy (&raw.ciaddr, &state -> ciaddr, sizeof raw.ciaddr);
03496 memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
03497 raw.siaddr = state -> siaddr;
03498 raw.giaddr = state -> giaddr;
03499
03500 raw.xid = state -> xid;
03501 raw.secs = state -> secs;
03502 raw.flags = state -> bootp_flags;
03503 raw.hops = state -> hops;
03504 raw.op = BOOTREPLY;
03505
03506 if (lease -> client_hostname) {
03507 if ((strlen (lease -> client_hostname) <= 64) &&
03508 db_printable((unsigned char *)lease->client_hostname))
03509 s = lease -> client_hostname;
03510 else
03511 s = "Hostname Unsuitable for Printing";
03512 } else
03513 s = (char *)0;
03514
03515
03516 log_info ("%s on %s to %s %s%s%svia %s",
03517 (state -> offer
03518 ? (state -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
03519 : "BOOTREPLY"),
03520 piaddr (lease -> ip_addr),
03521 (lease -> hardware_addr.hlen > 1
03522 ? print_hw_addr (lease -> hardware_addr.hbuf [0],
03523 lease -> hardware_addr.hlen - 1,
03524 &lease -> hardware_addr.hbuf [1])
03525 : print_hex_1(lease->uid_len, lease->uid, 60)),
03526 s ? "(" : "", s ? s : "", s ? ") " : "",
03527 (state -> giaddr.s_addr
03528 ? inet_ntoa (state -> giaddr)
03529 : state -> ip -> name));
03530
03531
03532 hto.hlen = lease -> hardware_addr.hlen;
03533 memcpy (hto.hbuf, lease -> hardware_addr.hbuf, hto.hlen);
03534
03535 to.sin_family = AF_INET;
03536 #ifdef HAVE_SA_LEN
03537 to.sin_len = sizeof to;
03538 #endif
03539 memset (to.sin_zero, 0, sizeof to.sin_zero);
03540
03541 #ifdef DEBUG_PACKET
03542 dump_raw ((unsigned char *)&raw, packet_length);
03543 #endif
03544
03545
03546
03547 if (packet_length < BOOTP_MIN_LEN)
03548 packet_length = BOOTP_MIN_LEN;
03549
03550
03551 if (raw.giaddr.s_addr) {
03552 to.sin_addr = raw.giaddr;
03553 if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
03554 to.sin_port = local_port;
03555 else
03556 to.sin_port = remote_port;
03557
03558 if (fallback_interface) {
03559 result = send_packet(fallback_interface, NULL, &raw,
03560 packet_length, raw.siaddr, &to,
03561 NULL);
03562 if (result < 0) {
03563 log_error ("%s:%d: Failed to send %d byte long "
03564 "packet over %s interface.", MDL,
03565 packet_length,
03566 fallback_interface->name);
03567 }
03568
03569
03570 free_lease_state (state, MDL);
03571 lease -> state = (struct lease_state *)0;
03572 return;
03573 }
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586 } else if (raw.ciaddr.s_addr &&
03587 !((state -> got_server_identifier ||
03588 (raw.flags & htons (BOOTP_BROADCAST))) &&
03589
03590 (state -> shared_network ==
03591 lease -> subnet -> shared_network)) &&
03592 state -> offer == DHCPACK) {
03593 to.sin_addr = raw.ciaddr;
03594 to.sin_port = remote_port;
03595
03596 if (fallback_interface) {
03597 result = send_packet(fallback_interface, NULL, &raw,
03598 packet_length, raw.siaddr, &to,
03599 NULL);
03600 if (result < 0) {
03601 log_error("%s:%d: Failed to send %d byte long"
03602 " packet over %s interface.", MDL,
03603 packet_length,
03604 fallback_interface->name);
03605 }
03606
03607 free_lease_state (state, MDL);
03608 lease -> state = (struct lease_state *)0;
03609 return;
03610 }
03611
03612
03613
03614
03615
03616 } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
03617 can_unicast_without_arp (state -> ip)) {
03618 to.sin_addr = raw.yiaddr;
03619 to.sin_port = remote_port;
03620
03621
03622 } else {
03623 to.sin_addr = limited_broadcast;
03624 to.sin_port = remote_port;
03625 if (!(lease -> flags & UNICAST_BROADCAST_HACK))
03626 unicastp = 0;
03627 }
03628
03629 memcpy (&from, state -> from.iabuf, sizeof from);
03630
03631 result = send_packet(state->ip, NULL, &raw, packet_length,
03632 from, &to, unicastp ? &hto : NULL);
03633 if (result < 0) {
03634 log_error ("%s:%d: Failed to send %d byte long "
03635 "packet over %s interface.", MDL,
03636 packet_length, state->ip->name);
03637 }
03638
03639
03640
03641
03642
03643 free_lease_state (state, MDL);
03644 lease -> state = (struct lease_state *)0;
03645
03646 TRACE(DHCPD_REPLY_DONE());
03647 }
03648
03649 int find_lease (struct lease **lp,
03650 struct packet *packet, struct shared_network *share, int *ours,
03651 int *peer_has_leases, struct lease *ip_lease_in,
03652 const char *file, int line)
03653 {
03654 struct lease *uid_lease = (struct lease *)0;
03655 struct lease *ip_lease = (struct lease *)0;
03656 struct lease *hw_lease = (struct lease *)0;
03657 struct lease *lease = (struct lease *)0;
03658 struct iaddr cip;
03659 struct host_decl *hp = (struct host_decl *)0;
03660 struct host_decl *host = (struct host_decl *)0;
03661 struct lease *fixed_lease = (struct lease *)0;
03662 struct lease *next = (struct lease *)0;
03663 struct option_cache *oc;
03664 struct data_string d1;
03665 int have_client_identifier = 0;
03666 struct data_string client_identifier;
03667 struct hardware h;
03668
03669 TRACE(DHCPD_FIND_LEASE_START());
03670
03671 #if defined(FAILOVER_PROTOCOL)
03672
03673 if (peer_has_leases) {
03674 struct pool *pool;
03675
03676 for (pool = share->pools ; pool ; pool = pool->next) {
03677 dhcp_failover_state_t *peer = pool->failover_peer;
03678
03679 if (peer &&
03680 ((peer->i_am == primary && pool->backup_leases) ||
03681 (peer->i_am == secondary && pool->free_leases))) {
03682 *peer_has_leases = 1;
03683 break;
03684 }
03685 }
03686 }
03687 #endif
03688
03689 if (packet -> raw -> ciaddr.s_addr) {
03690 cip.len = 4;
03691 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
03692 } else {
03693
03694 oc = lookup_option (&dhcp_universe, packet -> options,
03695 DHO_DHCP_REQUESTED_ADDRESS);
03696 memset (&d1, 0, sizeof d1);
03697 if (oc &&
03698 evaluate_option_cache (&d1, packet, (struct lease *)0,
03699 (struct client_state *)0,
03700 packet -> options,
03701 (struct option_state *)0,
03702 &global_scope, oc, MDL)) {
03703 packet -> got_requested_address = 1;
03704 cip.len = 4;
03705 memcpy (cip.iabuf, d1.data, cip.len);
03706 data_string_forget (&d1, MDL);
03707 } else
03708 cip.len = 0;
03709 }
03710
03711
03712
03713 oc = lookup_option (&dhcp_universe, packet -> options,
03714 DHO_DHCP_CLIENT_IDENTIFIER);
03715 memset (&client_identifier, 0, sizeof client_identifier);
03716 if (oc &&
03717 evaluate_option_cache (&client_identifier,
03718 packet, (struct lease *)0,
03719 (struct client_state *)0,
03720 packet -> options, (struct option_state *)0,
03721 &global_scope, oc, MDL)) {
03722
03723 have_client_identifier = 1;
03724
03725
03726
03727 if (find_hosts_by_uid (&hp, client_identifier.data,
03728 client_identifier.len, MDL)) {
03729
03730 packet -> known = 1;
03731 mockup_lease (&fixed_lease, packet, share, hp);
03732 }
03733
03734 #if defined (DEBUG_FIND_LEASE)
03735 if (fixed_lease) {
03736 log_info ("Found host for client identifier: %s.",
03737 piaddr (fixed_lease -> ip_addr));
03738 }
03739 #endif
03740 if (hp) {
03741 if (!fixed_lease)
03742 host_reference (&host, hp, MDL);
03743 host_dereference (&hp, MDL);
03744 }
03745
03746 find_lease_by_uid (&uid_lease, client_identifier.data,
03747 client_identifier.len, MDL);
03748 }
03749
03750
03751
03752 if (!fixed_lease && !host) {
03753 if (find_hosts_by_haddr (&hp, packet -> raw -> htype,
03754 packet -> raw -> chaddr,
03755 packet -> raw -> hlen, MDL)) {
03756
03757 packet -> known = 1;
03758 if (host)
03759 host_dereference (&host, MDL);
03760 host_reference (&host, hp, MDL);
03761 host_dereference (&hp, MDL);
03762 mockup_lease (&fixed_lease, packet, share, host);
03763 #if defined (DEBUG_FIND_LEASE)
03764 if (fixed_lease) {
03765 log_info ("Found host for link address: %s.",
03766 piaddr (fixed_lease -> ip_addr));
03767 }
03768 #endif
03769 }
03770 }
03771
03772
03773
03774 if (!fixed_lease && !host) {
03775 if (find_hosts_by_option(&hp, packet,
03776 packet->options, MDL) == 1) {
03777 packet->known = 1;
03778 if (host)
03779 host_dereference(&host, MDL);
03780 host_reference(&host, hp, MDL);
03781 host_dereference(&hp, MDL);
03782 mockup_lease (&fixed_lease, packet, share, host);
03783 #if defined (DEBUG_FIND_LEASE)
03784 if (fixed_lease) {
03785 log_info ("Found host via host-identifier");
03786 }
03787 #endif
03788 }
03789 }
03790
03791
03792
03793
03794 if (packet -> packet_type == DHCPREQUEST && fixed_lease &&
03795 (fixed_lease -> ip_addr.len != cip.len ||
03796 memcmp (fixed_lease -> ip_addr.iabuf,
03797 cip.iabuf, cip.len))) {
03798 if (ours)
03799 *ours = 1;
03800 strcpy (dhcp_message, "requested address is incorrect");
03801 #if defined (DEBUG_FIND_LEASE)
03802 log_info ("Client's fixed-address %s doesn't match %s%s",
03803 piaddr (fixed_lease -> ip_addr), "request ",
03804 print_dotted_quads (cip.len, cip.iabuf));
03805 #endif
03806 goto out;
03807 }
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817
03818
03819 while (uid_lease) {
03820 #if defined (DEBUG_FIND_LEASE)
03821 log_info ("trying next lease matching client id: %s",
03822 piaddr (uid_lease -> ip_addr));
03823 #endif
03824
03825 #if defined (FAILOVER_PROTOCOL)
03826
03827
03828
03829
03830
03831
03832
03833
03834 if (uid_lease->binding_state != FTS_ACTIVE &&
03835 uid_lease->rewind_binding_state != FTS_ACTIVE &&
03836 !lease_mine_to_reallocate(uid_lease)) {
03837 #if defined (DEBUG_FIND_LEASE)
03838 log_info("not active or not mine to allocate: %s",
03839 piaddr(uid_lease->ip_addr));
03840 #endif
03841 goto n_uid;
03842 }
03843 #endif
03844
03845 if (uid_lease -> subnet -> shared_network != share) {
03846 #if defined (DEBUG_FIND_LEASE)
03847 log_info ("wrong network segment: %s",
03848 piaddr (uid_lease -> ip_addr));
03849 #endif
03850 goto n_uid;
03851 }
03852
03853 if ((uid_lease -> pool -> prohibit_list &&
03854 permitted (packet, uid_lease -> pool -> prohibit_list)) ||
03855 (uid_lease -> pool -> permit_list &&
03856 !permitted (packet, uid_lease -> pool -> permit_list))) {
03857 #if defined (DEBUG_FIND_LEASE)
03858 log_info ("not permitted: %s",
03859 piaddr (uid_lease -> ip_addr));
03860 #endif
03861 n_uid:
03862 if (uid_lease -> n_uid)
03863 lease_reference (&next,
03864 uid_lease -> n_uid, MDL);
03865 if (!packet -> raw -> ciaddr.s_addr)
03866 release_lease (uid_lease, packet);
03867 lease_dereference (&uid_lease, MDL);
03868 if (next) {
03869 lease_reference (&uid_lease, next, MDL);
03870 lease_dereference (&next, MDL);
03871 }
03872 continue;
03873 }
03874 break;
03875 }
03876 #if defined (DEBUG_FIND_LEASE)
03877 if (uid_lease)
03878 log_info ("Found lease for client id: %s.",
03879 piaddr (uid_lease -> ip_addr));
03880 #endif
03881
03882
03883
03884
03885
03886
03887
03888
03889 h.hlen = packet -> raw -> hlen + 1;
03890 h.hbuf [0] = packet -> raw -> htype;
03891 memcpy (&h.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
03892 find_lease_by_hw_addr (&hw_lease, h.hbuf, h.hlen, MDL);
03893 while (hw_lease) {
03894 #if defined (DEBUG_FIND_LEASE)
03895 log_info ("trying next lease matching hw addr: %s",
03896 piaddr (hw_lease -> ip_addr));
03897 #endif
03898 #if defined (FAILOVER_PROTOCOL)
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908 if (hw_lease->binding_state != FTS_ACTIVE &&
03909 hw_lease->rewind_binding_state != FTS_ACTIVE &&
03910 !lease_mine_to_reallocate(hw_lease)) {
03911 #if defined (DEBUG_FIND_LEASE)
03912 log_info("not active or not mine to allocate: %s",
03913 piaddr(hw_lease->ip_addr));
03914 #endif
03915 goto n_hw;
03916 }
03917 #endif
03918
03919
03920
03921
03922
03923
03924
03925 if (hw_lease -> binding_state != FTS_FREE &&
03926 hw_lease -> binding_state != FTS_BACKUP &&
03927 hw_lease -> uid &&
03928 (!have_client_identifier ||
03929 hw_lease -> uid_len != client_identifier.len ||
03930 memcmp (hw_lease -> uid, client_identifier.data,
03931 hw_lease -> uid_len))) {
03932 #if defined (DEBUG_FIND_LEASE)
03933 log_info ("wrong client identifier: %s",
03934 piaddr (hw_lease -> ip_addr));
03935 #endif
03936 goto n_hw;
03937 }
03938 if (hw_lease -> subnet -> shared_network != share) {
03939 #if defined (DEBUG_FIND_LEASE)
03940 log_info ("wrong network segment: %s",
03941 piaddr (hw_lease -> ip_addr));
03942 #endif
03943 goto n_hw;
03944 }
03945 if ((hw_lease -> pool -> prohibit_list &&
03946 permitted (packet, hw_lease -> pool -> prohibit_list)) ||
03947 (hw_lease -> pool -> permit_list &&
03948 !permitted (packet, hw_lease -> pool -> permit_list))) {
03949 #if defined (DEBUG_FIND_LEASE)
03950 log_info ("not permitted: %s",
03951 piaddr (hw_lease -> ip_addr));
03952 #endif
03953 if (!packet -> raw -> ciaddr.s_addr)
03954 release_lease (hw_lease, packet);
03955 n_hw:
03956 if (hw_lease -> n_hw)
03957 lease_reference (&next, hw_lease -> n_hw, MDL);
03958 lease_dereference (&hw_lease, MDL);
03959 if (next) {
03960 lease_reference (&hw_lease, next, MDL);
03961 lease_dereference (&next, MDL);
03962 }
03963 continue;
03964 }
03965 break;
03966 }
03967 #if defined (DEBUG_FIND_LEASE)
03968 if (hw_lease)
03969 log_info ("Found lease for hardware address: %s.",
03970 piaddr (hw_lease -> ip_addr));
03971 #endif
03972
03973
03974
03975 if (ip_lease_in)
03976 lease_reference (&ip_lease, ip_lease_in, MDL);
03977 else if (cip.len)
03978 find_lease_by_ip_addr (&ip_lease, cip, MDL);
03979
03980 #if defined (DEBUG_FIND_LEASE)
03981 if (ip_lease)
03982 log_info ("Found lease for requested address: %s.",
03983 piaddr (ip_lease -> ip_addr));
03984 #endif
03985
03986
03987
03988
03989 if (ip_lease && ours)
03990 *ours = 1;
03991
03992
03993
03994
03995
03996
03997
03998
03999 if (ip_lease && (ip_lease -> subnet -> shared_network != share)) {
04000 if (ours)
04001 *ours = 1;
04002 #if defined (DEBUG_FIND_LEASE)
04003 log_info ("...but it was on the wrong shared network.");
04004 #endif
04005 strcpy (dhcp_message, "requested address on bad subnet");
04006 lease_dereference (&ip_lease, MDL);
04007 }
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018 if (ip_lease &&
04019 (ip_lease -> uid ?
04020 (!have_client_identifier ||
04021 ip_lease -> uid_len != client_identifier.len ||
04022 memcmp (ip_lease -> uid, client_identifier.data,
04023 ip_lease -> uid_len)) :
04024 (ip_lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
04025 ip_lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
04026 memcmp (&ip_lease -> hardware_addr.hbuf [1],
04027 packet -> raw -> chaddr,
04028 (unsigned)(ip_lease -> hardware_addr.hlen - 1))))) {
04029
04030
04031
04032
04033
04034
04035
04036
04037 if (ip_lease -> binding_state != FTS_FREE &&
04038 ip_lease -> binding_state != FTS_BACKUP) {
04039 #if defined (DEBUG_FIND_LEASE)
04040 log_info ("rejecting lease for requested address.");
04041 #endif
04042
04043
04044 if (ours && ip_lease -> binding_state != FTS_ACTIVE)
04045 *ours = 0;
04046 lease_dereference (&ip_lease, MDL);
04047 }
04048 }
04049
04050
04051
04052
04053
04054 if (ip_lease && (uid_lease || hw_lease) &&
04055 ip_lease->binding_state != FTS_ACTIVE &&
04056 ip_lease->rewind_binding_state != FTS_ACTIVE &&
04057 #if defined(FAILOVER_PROTOCOL)
04058 !lease_mine_to_reallocate(ip_lease) &&
04059 #endif
04060 packet->packet_type == DHCPDISCOVER) {
04061 #if defined (DEBUG_FIND_LEASE)
04062 log_info("ip lease not active or not ours to offer.");
04063 #endif
04064 lease_dereference(&ip_lease, MDL);
04065 }
04066
04067
04068
04069
04070 if (ip_lease && ip_lease->binding_state == FTS_ACTIVE &&
04071 ip_lease->uid && ip_lease != uid_lease) {
04072 if (have_client_identifier &&
04073 (ip_lease -> uid_len == client_identifier.len) &&
04074 !memcmp (client_identifier.data,
04075 ip_lease -> uid, ip_lease -> uid_len)) {
04076 if (uid_lease) {
04077 if (uid_lease->binding_state == FTS_ACTIVE) {
04078 log_error ("client %s has duplicate%s on %s",
04079 (print_hw_addr_or_client_id(packet)),
04080 " leases",
04081 (ip_lease -> subnet ->
04082 shared_network -> name));
04083
04084
04085
04086
04087 if (uid_lease &&
04088 uid_lease->binding_state == FTS_ACTIVE &&
04089 !packet -> raw -> ciaddr.s_addr &&
04090 (share ==
04091 uid_lease -> subnet -> shared_network) &&
04092 packet -> packet_type == DHCPREQUEST)
04093 release_lease (uid_lease, packet);
04094 }
04095 lease_dereference (&uid_lease, MDL);
04096 lease_reference (&uid_lease, ip_lease, MDL);
04097 }
04098 }
04099
04100
04101
04102
04103 if (packet -> packet_type == DHCPREQUEST && fixed_lease) {
04104 lease_dereference (&fixed_lease, MDL);
04105 db_conflict:
04106 log_error ("Dynamic and static leases present for %s.",
04107 piaddr (cip));
04108 log_error ("Remove host declaration %s or remove %s",
04109 (fixed_lease && fixed_lease -> host
04110 ? (fixed_lease -> host -> name
04111 ? fixed_lease -> host -> name
04112 : piaddr (cip))
04113 : piaddr (cip)),
04114 piaddr (cip));
04115 log_error ("from the dynamic address pool for %s",
04116 ip_lease -> subnet -> shared_network -> name
04117 );
04118 if (fixed_lease)
04119 lease_dereference (&ip_lease, MDL);
04120 strcpy (dhcp_message,
04121 "database conflict - call for help!");
04122 }
04123
04124 if (ip_lease && ip_lease != uid_lease) {
04125 #if defined (DEBUG_FIND_LEASE)
04126 log_info ("requested address not available.");
04127 #endif
04128 lease_dereference (&ip_lease, MDL);
04129 }
04130 }
04131
04132
04133
04134 if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
04135 goto db_conflict;
04136
04137
04138 if (hw_lease && hw_lease == uid_lease) {
04139 #if defined (DEBUG_FIND_LEASE)
04140 log_info ("hardware lease and uid lease are identical.");
04141 #endif
04142 lease_dereference (&hw_lease, MDL);
04143 }
04144 if (ip_lease && ip_lease == hw_lease) {
04145 lease_dereference (&hw_lease, MDL);
04146 #if defined (DEBUG_FIND_LEASE)
04147 log_info ("hardware lease and ip lease are identical.");
04148 #endif
04149 }
04150 if (ip_lease && ip_lease == uid_lease) {
04151 lease_dereference (&uid_lease, MDL);
04152 #if defined (DEBUG_FIND_LEASE)
04153 log_info ("uid lease and ip lease are identical.");
04154 #endif
04155 }
04156
04157
04158 if (ip_lease &&
04159 ((ip_lease -> pool -> prohibit_list &&
04160 permitted (packet, ip_lease -> pool -> prohibit_list)) ||
04161 (ip_lease -> pool -> permit_list &&
04162 !permitted (packet, ip_lease -> pool -> permit_list)))) {
04163 if (!packet->raw->ciaddr.s_addr &&
04164 (ip_lease->binding_state == FTS_ACTIVE))
04165 release_lease (ip_lease, packet);
04166
04167 lease_dereference (&ip_lease, MDL);
04168 }
04169
04170 if (uid_lease &&
04171 ((uid_lease -> pool -> prohibit_list &&
04172 permitted (packet, uid_lease -> pool -> prohibit_list)) ||
04173 (uid_lease -> pool -> permit_list &&
04174 !permitted (packet, uid_lease -> pool -> permit_list)))) {
04175 if (!packet -> raw -> ciaddr.s_addr)
04176 release_lease (uid_lease, packet);
04177 lease_dereference (&uid_lease, MDL);
04178 }
04179
04180 if (hw_lease &&
04181 ((hw_lease -> pool -> prohibit_list &&
04182 permitted (packet, hw_lease -> pool -> prohibit_list)) ||
04183 (hw_lease -> pool -> permit_list &&
04184 !permitted (packet, hw_lease -> pool -> permit_list)))) {
04185 if (!packet -> raw -> ciaddr.s_addr)
04186 release_lease (hw_lease, packet);
04187 lease_dereference (&hw_lease, MDL);
04188 }
04189
04190
04191
04192
04193 if (!ip_lease) {
04194 strcpy (dhcp_message, "requested address not available");
04195 }
04196
04197
04198
04199
04200 if (packet -> packet_type == DHCPREQUEST &&
04201 !ip_lease && !fixed_lease) {
04202 #if defined (DEBUG_FIND_LEASE)
04203 log_info ("no applicable lease found for DHCPREQUEST.");
04204 #endif
04205 goto out;
04206 }
04207
04208
04209
04210 if (fixed_lease) {
04211 lease_reference (&lease, fixed_lease, MDL);
04212 lease_dereference (&fixed_lease, MDL);
04213 #if defined (DEBUG_FIND_LEASE)
04214 log_info ("choosing fixed address.");
04215 #endif
04216 }
04217
04218
04219
04220 if (ip_lease) {
04221 if (lease) {
04222 if (!packet -> raw -> ciaddr.s_addr)
04223 release_lease (ip_lease, packet);
04224 #if defined (DEBUG_FIND_LEASE)
04225 log_info ("not choosing requested address (!).");
04226 #endif
04227 } else {
04228 #if defined (DEBUG_FIND_LEASE)
04229 log_info ("choosing lease on requested address.");
04230 #endif
04231 lease_reference (&lease, ip_lease, MDL);
04232 if (lease -> host)
04233 host_dereference (&lease -> host, MDL);
04234 }
04235 lease_dereference (&ip_lease, MDL);
04236 }
04237
04238
04239
04240
04241 if (uid_lease) {
04242 if (lease) {
04243 log_error("uid lease %s for client %s is duplicate "
04244 "on %s",
04245 piaddr(uid_lease->ip_addr),
04246 print_hw_addr_or_client_id(packet),
04247 uid_lease->subnet->shared_network->name);
04248
04249 if (!packet -> raw -> ciaddr.s_addr &&
04250 packet -> packet_type == DHCPREQUEST &&
04251 uid_lease -> binding_state == FTS_ACTIVE)
04252 release_lease(uid_lease, packet);
04253 #if defined (DEBUG_FIND_LEASE)
04254 log_info ("not choosing uid lease.");
04255 #endif
04256 } else {
04257 lease_reference (&lease, uid_lease, MDL);
04258 if (lease -> host)
04259 host_dereference (&lease -> host, MDL);
04260 #if defined (DEBUG_FIND_LEASE)
04261 log_info ("choosing uid lease.");
04262 #endif
04263 }
04264 lease_dereference (&uid_lease, MDL);
04265 }
04266
04267
04268 if (hw_lease) {
04269 if (lease) {
04270 #if defined (DEBUG_FIND_LEASE)
04271 log_info ("not choosing hardware lease.");
04272 #endif
04273 } else {
04274
04275
04276
04277
04278 if (!hw_lease -> uid_len ||
04279 (have_client_identifier
04280 ? (hw_lease -> uid_len ==
04281 client_identifier.len &&
04282 !memcmp (hw_lease -> uid,
04283 client_identifier.data,
04284 client_identifier.len))
04285 : packet -> packet_type == 0)) {
04286 lease_reference (&lease, hw_lease, MDL);
04287 if (lease -> host)
04288 host_dereference (&lease -> host, MDL);
04289 #if defined (DEBUG_FIND_LEASE)
04290 log_info ("choosing hardware lease.");
04291 #endif
04292 } else {
04293 #if defined (DEBUG_FIND_LEASE)
04294 log_info ("not choosing hardware lease: %s.",
04295 "uid mismatch");
04296 #endif
04297 }
04298 }
04299 lease_dereference (&hw_lease, MDL);
04300 }
04301
04302
04303
04304
04305
04306
04307
04308 if (lease && host && !lease->host) {
04309 struct host_decl *p = NULL;
04310 struct host_decl *n = NULL;
04311
04312 host_reference(&p, host, MDL);
04313 while (p != NULL) {
04314 if (!p->fixed_addr) {
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330 if (lease->binding_state == FTS_ACTIVE)
04331 host_reference(&lease->host, p, MDL);
04332
04333 host_dereference(&p, MDL);
04334 break;
04335 }
04336 if (p->n_ipaddr != NULL)
04337 host_reference(&n, p->n_ipaddr, MDL);
04338 host_dereference(&p, MDL);
04339 if (n != NULL) {
04340 host_reference(&p, n, MDL);
04341 host_dereference(&n, MDL);
04342 }
04343 }
04344 }
04345
04346
04347
04348
04349
04350 if (lease &&
04351 (lease -> binding_state == FTS_ABANDONED) &&
04352 lease == ip_lease &&
04353 packet -> packet_type == DHCPREQUEST) {
04354 log_error ("Reclaiming REQUESTed abandoned IP address %s.",
04355 piaddr (lease -> ip_addr));
04356 } else if (lease && (lease -> binding_state == FTS_ABANDONED)) {
04357
04358
04359
04360
04361 if (ours)
04362 *ours = 1;
04363 lease_dereference (&lease, MDL);
04364 }
04365
04366 out:
04367 if (have_client_identifier)
04368 data_string_forget (&client_identifier, MDL);
04369
04370 if (fixed_lease)
04371 lease_dereference (&fixed_lease, MDL);
04372 if (hw_lease)
04373 lease_dereference (&hw_lease, MDL);
04374 if (uid_lease)
04375 lease_dereference (&uid_lease, MDL);
04376 if (ip_lease)
04377 lease_dereference (&ip_lease, MDL);
04378 if (host)
04379 host_dereference (&host, MDL);
04380
04381 if (lease) {
04382 #if defined (DEBUG_FIND_LEASE)
04383 log_info ("Returning lease: %s.",
04384 piaddr (lease -> ip_addr));
04385 #endif
04386 lease_reference (lp, lease, file, line);
04387 lease_dereference (&lease, MDL);
04388 return 1;
04389 }
04390 #if defined (DEBUG_FIND_LEASE)
04391 log_info ("Not returning a lease.");
04392 #endif
04393
04394 TRACE(DHCPD_FIND_LEASE_DONE());
04395
04396 return 0;
04397 }
04398
04399
04400
04401
04402
04403 int mockup_lease (struct lease **lp, struct packet *packet,
04404 struct shared_network *share, struct host_decl *hp)
04405 {
04406 struct lease *lease = (struct lease *)0;
04407 struct host_decl *rhp = (struct host_decl *)0;
04408
04409 if (lease_allocate (&lease, MDL) != ISC_R_SUCCESS)
04410 return 0;
04411 if (host_reference (&rhp, hp, MDL) != ISC_R_SUCCESS) {
04412 lease_dereference (&lease, MDL);
04413 return 0;
04414 }
04415 if (!find_host_for_network (&lease -> subnet,
04416 &rhp, &lease -> ip_addr, share)) {
04417 lease_dereference (&lease, MDL);
04418 host_dereference (&rhp, MDL);
04419 return 0;
04420 }
04421 host_reference (&lease -> host, rhp, MDL);
04422 if (rhp -> client_identifier.len > sizeof lease -> uid_buf)
04423 lease -> uid = dmalloc (rhp -> client_identifier.len, MDL);
04424 else
04425 lease -> uid = lease -> uid_buf;
04426 if (!lease -> uid) {
04427 lease_dereference (&lease, MDL);
04428 host_dereference (&rhp, MDL);
04429 return 0;
04430 }
04431 memcpy (lease -> uid, rhp -> client_identifier.data,
04432 rhp -> client_identifier.len);
04433 lease -> uid_len = rhp -> client_identifier.len;
04434 lease -> hardware_addr = rhp -> interface;
04435 lease -> starts = lease -> cltt = lease -> ends = MIN_TIME;
04436 lease -> flags = STATIC_LEASE;
04437 lease -> binding_state = FTS_FREE;
04438
04439 lease_reference (lp, lease, MDL);
04440
04441 lease_dereference (&lease, MDL);
04442 host_dereference (&rhp, MDL);
04443 return 1;
04444 }
04445
04446
04447
04448
04449
04450
04451
04452
04453 int allocate_lease (struct lease **lp, struct packet *packet,
04454 struct pool *pool, int *peer_has_leases)
04455 {
04456 struct lease *lease = (struct lease *)0;
04457 struct lease *candl = (struct lease *)0;
04458
04459 for (; pool ; pool = pool -> next) {
04460 if ((pool -> prohibit_list &&
04461 permitted (packet, pool -> prohibit_list)) ||
04462 (pool -> permit_list &&
04463 !permitted (packet, pool -> permit_list)))
04464 continue;
04465
04466 #if defined (FAILOVER_PROTOCOL)
04467
04468
04469
04470
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481 if (pool->failover_peer != NULL) {
04482 if (pool->failover_peer->i_am == primary) {
04483 candl = pool->free;
04484
04485
04486
04487
04488
04489
04490
04491 if (pool->backup != NULL) {
04492 if (((candl == NULL) ||
04493 (candl->ends >
04494 pool->backup->ends)) &&
04495 lease_mine_to_reallocate(
04496 pool->backup)) {
04497 candl = pool->backup;
04498 } else {
04499 *peer_has_leases = 1;
04500 }
04501 }
04502 } else {
04503 candl = pool->backup;
04504
04505 if (pool->free != NULL) {
04506 if (((candl == NULL) ||
04507 (candl->ends >
04508 pool->free->ends)) &&
04509 lease_mine_to_reallocate(
04510 pool->free)) {
04511 candl = pool->free;
04512 } else {
04513 *peer_has_leases = 1;
04514 }
04515 }
04516 }
04517
04518
04519 if ((candl == NULL) &&
04520 (pool->abandoned != NULL) &&
04521 lease_mine_to_reallocate(pool->abandoned))
04522 candl = pool->abandoned;
04523 } else
04524 #endif
04525 {
04526 if (pool -> free)
04527 candl = pool -> free;
04528 else
04529 candl = pool -> abandoned;
04530 }
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541 if (!candl || (candl -> ends > cur_time))
04542 continue;
04543
04544 if (!lease) {
04545 lease = candl;
04546 continue;
04547 }
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560
04561 if ((lease -> binding_state == FTS_ABANDONED) &&
04562 ((candl -> binding_state != FTS_ABANDONED) ||
04563 (candl -> ends < lease -> ends))) {
04564 lease = candl;
04565 continue;
04566 } else if (candl -> binding_state == FTS_ABANDONED)
04567 continue;
04568
04569 if ((lease -> uid_len || lease -> hardware_addr.hlen) &&
04570 ((!candl -> uid_len && !candl -> hardware_addr.hlen) ||
04571 (candl -> ends < lease -> ends))) {
04572 lease = candl;
04573 continue;
04574 } else if (candl -> uid_len || candl -> hardware_addr.hlen)
04575 continue;
04576
04577 if (candl -> ends < lease -> ends)
04578 lease = candl;
04579 }
04580
04581 if (lease != NULL) {
04582 if (lease->binding_state == FTS_ABANDONED)
04583 log_error("Reclaiming abandoned lease %s.",
04584 piaddr(lease->ip_addr));
04585
04586
04587
04588
04589
04590
04591 if (lease->host != NULL) {
04592 log_debug("soft impossible condition (%s:%d): stale "
04593 "host \"%s\" found on lease %s", MDL,
04594 lease->host->name,
04595 piaddr(lease->ip_addr));
04596 host_dereference(&lease->host, MDL);
04597 }
04598
04599 lease_reference (lp, lease, MDL);
04600 return 1;
04601 }
04602
04603 return 0;
04604 }
04605
04606
04607
04608
04609
04610 int permitted (packet, permit_list)
04611 struct packet *packet;
04612 struct permit *permit_list;
04613 {
04614 struct permit *p;
04615 int i;
04616
04617 for (p = permit_list; p; p = p -> next) {
04618 switch (p -> type) {
04619 case permit_unknown_clients:
04620 if (!packet -> known)
04621 return 1;
04622 break;
04623
04624 case permit_known_clients:
04625 if (packet -> known)
04626 return 1;
04627 break;
04628
04629 case permit_authenticated_clients:
04630 if (packet -> authenticated)
04631 return 1;
04632 break;
04633
04634 case permit_unauthenticated_clients:
04635 if (!packet -> authenticated)
04636 return 1;
04637 break;
04638
04639 case permit_all_clients:
04640 return 1;
04641
04642 case permit_dynamic_bootp_clients:
04643 if (!packet -> options_valid ||
04644 !packet -> packet_type)
04645 return 1;
04646 break;
04647
04648 case permit_class:
04649 for (i = 0; i < packet -> class_count; i++) {
04650 if (p -> class == packet -> classes [i])
04651 return 1;
04652 if (packet -> classes [i] &&
04653 packet -> classes [i] -> superclass &&
04654 (packet -> classes [i] -> superclass ==
04655 p -> class))
04656 return 1;
04657 }
04658 break;
04659
04660 case permit_after:
04661 if (cur_time > p->after)
04662 return 1;
04663 break;
04664 }
04665 }
04666 return 0;
04667 }
04668
04669 int locate_network (packet)
04670 struct packet *packet;
04671 {
04672 struct iaddr ia;
04673 struct data_string data;
04674 struct subnet *subnet = (struct subnet *)0;
04675 struct option_cache *oc;
04676 int norelay = 0;
04677
04678
04679
04680
04681
04682
04683 if ((oc = lookup_option(&agent_universe, packet->options,
04684 RAI_LINK_SELECT)) == NULL)
04685 oc = lookup_option(&dhcp_universe, packet->options,
04686 DHO_SUBNET_SELECTION);
04687
04688
04689
04690 if (!oc && !packet -> raw -> giaddr.s_addr) {
04691 if (packet -> interface -> shared_network) {
04692 struct in_addr any_addr;
04693 any_addr.s_addr = INADDR_ANY;
04694
04695 if (!packet -> packet_type && memcmp(&packet -> raw -> ciaddr, &any_addr, 4)) {
04696 struct iaddr cip;
04697 memcpy(cip.iabuf, &packet -> raw -> ciaddr, 4);
04698 cip.len = 4;
04699 if (!find_grouped_subnet(&subnet, packet->interface->shared_network, cip, MDL))
04700 norelay = 2;
04701 }
04702
04703 if (!norelay) {
04704 shared_network_reference(&packet -> shared_network, packet -> interface -> shared_network, MDL);
04705 return 1;
04706 }
04707 } else {
04708 return 0;
04709 }
04710 }
04711
04712
04713
04714
04715 if (oc) {
04716 memset (&data, 0, sizeof data);
04717 if (!evaluate_option_cache (&data, packet, (struct lease *)0,
04718 (struct client_state *)0,
04719 packet -> options,
04720 (struct option_state *)0,
04721 &global_scope, oc, MDL)) {
04722 return 0;
04723 }
04724 if (data.len != 4) {
04725 return 0;
04726 }
04727 ia.len = 4;
04728 memcpy (ia.iabuf, data.data, 4);
04729 data_string_forget (&data, MDL);
04730 } else {
04731 ia.len = 4;
04732 if (norelay)
04733 memcpy (ia.iabuf, &packet->raw->ciaddr, 4);
04734 else
04735 memcpy (ia.iabuf, &packet->raw->giaddr, 4);
04736 }
04737
04738
04739 if (find_subnet (&subnet, ia, MDL)) {
04740 shared_network_reference (&packet -> shared_network,
04741 subnet -> shared_network, MDL);
04742 subnet_dereference (&subnet, MDL);
04743 if (norelay)
04744 return norelay;
04745 else
04746 return 1;
04747 }
04748
04749
04750 return 0;
04751 }
04752
04753
04754
04755
04756
04757
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783 void
04784 get_server_source_address(struct in_addr *from,
04785 struct option_state *options,
04786 struct option_state *out_options,
04787 struct packet *packet) {
04788 unsigned option_num;
04789 struct option_cache *oc = NULL;
04790 struct data_string d;
04791 struct in_addr *a = NULL;
04792 isc_boolean_t found = ISC_FALSE;
04793 int allocate = 0;
04794
04795 memset(&d, 0, sizeof(d));
04796 memset(from, 0, sizeof(*from));
04797
04798 option_num = DHO_DHCP_SERVER_IDENTIFIER;
04799 oc = lookup_option(&dhcp_universe, options, option_num);
04800 if (oc != NULL) {
04801 if (evaluate_option_cache(&d, packet, NULL, NULL,
04802 packet->options, options,
04803 &global_scope, oc, MDL)) {
04804 if (d.len == sizeof(*from)) {
04805 found = ISC_TRUE;
04806 memcpy(from, d.data, sizeof(*from));
04807
04808
04809
04810
04811
04812 if ((out_options != NULL) &&
04813 (options != out_options)) {
04814 a = from;
04815 allocate = 1;
04816 }
04817 }
04818 data_string_forget(&d, MDL);
04819 }
04820 oc = NULL;
04821 }
04822
04823 if ((found == ISC_FALSE) &&
04824 (packet->interface->address_count > 0)) {
04825 *from = packet->interface->addresses[0];
04826
04827 if (out_options != NULL) {
04828 a = &packet->interface->addresses[0];
04829 }
04830 }
04831
04832 if ((a != NULL) &&
04833 (option_cache_allocate(&oc, MDL))) {
04834 if (make_const_data(&oc->expression,
04835 (unsigned char *)a, sizeof(*a),
04836 0, allocate, MDL)) {
04837 option_code_hash_lookup(&oc->option,
04838 dhcp_universe.code_hash,
04839 &option_num, 0, MDL);
04840 save_option(&dhcp_universe, out_options, oc);
04841 }
04842 option_cache_dereference(&oc, MDL);
04843 }
04844
04845 return;
04846 }
04847
04848
04849
04850
04851
04852
04853
04854
04855
04856
04857
04858
04859
04860
04861 void
04862 setup_server_source_address(struct in_addr *from,
04863 struct option_state *options,
04864 struct packet *packet) {
04865
04866 struct option_state *sid_options = NULL;
04867
04868 if (packet->shared_network != NULL) {
04869 option_state_allocate (&sid_options, MDL);
04870
04871
04872
04873
04874
04875
04876 if ((packet->shared_network->subnets != NULL) &&
04877 (packet->shared_network->subnets->group != NULL)) {
04878 execute_statements_in_scope(NULL, packet, NULL, NULL,
04879 packet->options, sid_options,
04880 &global_scope,
04881 packet->shared_network->subnets->group,
04882 NULL, NULL);
04883 } else {
04884 execute_statements_in_scope(NULL, packet, NULL, NULL,
04885 packet->options, sid_options,
04886 &global_scope,
04887 packet->shared_network->group,
04888 NULL, NULL);
04889 }
04890
04891
04892 if (packet->shared_network->pools != NULL) {
04893 execute_statements_in_scope(NULL, packet, NULL, NULL,
04894 packet->options, sid_options,
04895 &global_scope,
04896 packet->shared_network->pools->group,
04897 packet->shared_network->group,
04898 NULL);
04899 }
04900
04901
04902
04903 }
04904
04905
04906 get_server_source_address(from, sid_options, options, packet);
04907
04908
04909 if (sid_options != NULL)
04910 option_state_dereference(&sid_options, MDL);
04911 }
04912
04913
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923 static int
04924 find_min_site_code(struct universe *u)
04925 {
04926 if (u->site_code_min)
04927 return u->site_code_min;
04928
04929
04930
04931
04932
04933
04934 site_code_min = 224;
04935 option_code_hash_foreach(u->code_hash, lowest_site_code);
04936
04937 if (site_code_min < 224) {
04938 log_error("WARNING: site-local option codes less than 224 have "
04939 "been deprecated by RFC3942. You have options "
04940 "listed in site local space %s that number as low as "
04941 "%d. Please investigate if these should be declared "
04942 "as regular options rather than site-local options, "
04943 "or migrated up past 224.",
04944 u->name, site_code_min);
04945 }
04946
04947
04948
04949
04950
04951 if (site_code_min < 128)
04952 site_code_min = 128;
04953
04954
04955
04956
04957
04958
04959 u->site_code_min = site_code_min;
04960
04961 return site_code_min;
04962 }
04963
04964 static isc_result_t
04965 lowest_site_code(const void *key, unsigned len, void *object)
04966 {
04967 struct option *option = object;
04968
04969 if (option->code < site_code_min)
04970 site_code_min = option->code;
04971
04972 return ISC_R_SUCCESS;
04973 }
04974
04975 static void
04976 maybe_return_agent_options(struct packet *packet, struct option_state *options)
04977 {
04978
04979
04980
04981
04982
04983
04984
04985
04986
04987
04988
04989
04990 if (!packet->agent_options_stashed &&
04991 (packet->options != NULL) &&
04992 packet->options->universe_count > agent_universe.index &&
04993 packet->options->universes[agent_universe.index] != NULL &&
04994 (options->universe_count <= agent_universe.index ||
04995 options->universes[agent_universe.index] == NULL)) {
04996 option_chain_head_reference
04997 ((struct option_chain_head **)
04998 &(options->universes[agent_universe.index]),
04999 (struct option_chain_head *)
05000 packet->options->universes[agent_universe.index], MDL);
05001
05002 if (options->universe_count <= agent_universe.index)
05003 options->universe_count = agent_universe.index + 1;
05004 }
05005 }