server/dhcp.c

Go to the documentation of this file.
00001 /* dhcp.c
00002 
00003    DHCP Protocol engine. */
00004 
00005 /*
00006  * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 1995-2003 by Internet Software Consortium
00008  *
00009  * Permission to use, copy, modify, and distribute this software for any
00010  * purpose with or without fee is hereby granted, provided that the above
00011  * copyright notice and this permission notice appear in all copies.
00012  *
00013  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00014  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00015  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00016  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00017  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00018  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00019  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00020  *
00021  *   Internet Systems Consortium, Inc.
00022  *   950 Charter Street
00023  *   Redwood City, CA 94063
00024  *   <info@isc.org>
00025  *   https://www.isc.org/
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                         /* %Audit% Cannot exceed 28 bytes. %2004.06.17,Safe% */
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         /* There is a problem with the relay agent information option,
00150          * which is that in order for a normal relay agent to append
00151          * this option, the relay agent has to have been involved in
00152          * getting the packet from the client to the server.  Note
00153          * that this is the software entity known as the relay agent,
00154          * _not_ the hardware entity known as a router in which the
00155          * relay agent may be running, so the fact that a router has
00156          * forwarded a packet does not mean that the relay agent in
00157          * the router was involved.
00158          *
00159          * So when the client broadcasts (DHCPDISCOVER, or giaddr is set),
00160          * we can be sure that there are either agent options in the
00161          * packet, or there aren't supposed to be.  When the giaddr is not
00162          * set, it's still possible that the client is on a directly
00163          * attached subnet, and agent options are being appended by an l2
00164          * device that has no address, and so sets no giaddr.
00165          *
00166          * But in either case it's possible that the packets we receive
00167          * from the client in RENEW state may not include the agent options,
00168          * so if they are not in the packet we must "pretend" the last values
00169          * we observed were provided.
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                 /* If there are no agent options on the lease, it's not
00185                    interesting. */
00186                 if (!lease -> agent_options)
00187                         goto nolease;
00188 
00189                 /* The client should not be unicasting a renewal if its lease
00190                    has expired, so make it go through the process of getting
00191                    its agent options legally. */
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                 /* Okay, so we found a lease that matches the client. */
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         /* If a client null terminates options it sends, it probably
00240          * expects the server to reciprocate.
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         /* Classify the client. */
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]; /* XXX */
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         /* %Audit% This is log output. %2004.06.17,Safe%
00321          * If we truncate we hope the user can get a hint from the log.
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         /* Sourceless packets don't make sense here. */
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                  * If the lease is ours to (re)allocate, then allocate it.
00347                  *
00348                  * If the lease is active, it belongs to the client.  This
00349                  * is the right lease, if we are to offer one.  We decide
00350                  * whether or not to offer later on.
00351                  *
00352                  * If the lease was last active, and we've reached this
00353                  * point, then it was last active with the same client.  We
00354                  * can safely re-activate the lease with this client.
00355                  */
00356                 if (lease->binding_state == FTS_ACTIVE ||
00357                     lease->rewind_binding_state == FTS_ACTIVE ||
00358                     lease_mine_to_reallocate(lease)) {
00359                         ; /* This space intentionally left blank. */
00360 
00361                 /* Otherwise, we can't let the client have this lease. */
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         /* If we didn't find a lease, try to allocate one... */
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         /* Do load balancing if configured. */
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         /* If it's an expired lease, get rid of any bindings. */
00416         if (lease -> ends < cur_time && lease -> scope)
00417                 binding_scope_dereference (&lease -> scope, MDL);
00418 
00419         /* Set the lease to really expire in 2 minutes, unless it has
00420            not yet expired, in which case leave its expiry time alone. */
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]; /* XXX */
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         /* Find the lease that matches the address requested by the
00475            client. */
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                 /* piaddr() should not return more than a 15 byte string.
00504                  * safe.
00505                  */
00506                 sprintf (smbuf, " (%s)", piaddr (sip));
00507         } else {
00508                 smbuf [0] = 0;
00509                 sip.len = 0;
00510         }
00511 
00512         /* %Audit% This is log output. %2004.06.17,Safe%
00513          * If we truncate we hope the user can get a hint from the log.
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                 /* "load balance to peer" - is not done at all for request.
00539                  *
00540                  * If it's RENEWING, we are the only server to hear it, so
00541                  * we have to serve it.   If it's REBINDING, it's out of
00542                  * communication with the other server, so there's no point
00543                  * in waiting to serve it.    However, if the lease we're
00544                  * offering is not a free lease, then we may be the only
00545                  * server that can offer it, so we can't load balance if
00546                  * the lease isn't in the free or backup state.  If it is
00547                  * in the free or backup state, then that state is what
00548                  * mandates one server or the other should perform the
00549                  * allocation, not the LBA...we know the peer cannot
00550                  * allocate a request for an address in our free state.
00551                  *
00552                  * So our only compass is lease_mine_to_reallocate().  This
00553                  * effects both load balancing, and a sanity-check that we
00554                  * are not going to try to allocate a lease that isn't ours.
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                  * If the lease is in a transitional state, we can't
00565                  * renew it unless we can rewind it to a non-transitional
00566                  * state (active, free, or backup).  lease_mine_to_reallocate()
00567                  * checks for free/backup, so we only need to check for active.
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                 /* It's actually very unlikely that we'll ever get here,
00580                    but if we do, tell the client to stop using the lease,
00581                    because the administrator reset it. */
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                 /* Do a quick check on the server source address to see if
00591                    it is ours.  sip is the incoming servrer id.  To avoid
00592                    problems with confused clients we do some sanity checks
00593                    to verify sip's length and that it isn't all zeros.
00594                    We then get the server id we would likely use for this
00595                    packet and compare them.  If they don't match it we assume
00596                    we didn't send the offer and so we don't process the request.
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 /* if defined(SERVER_ID_CHECK) */
00609 
00610                 /* At this point it's possible that we will get a broadcast
00611                    DHCPREQUEST for a lease that we didn't offer, because
00612                    both we and the peer are in a position to offer it.
00613                    In that case, we probably shouldn't answer.   In order
00614                    to not answer, we would have to compare the server
00615                    identifier sent by the client with the list of possible
00616                    server identifiers we can send, and if the client's
00617                    identifier isn't on the list, drop the DHCPREQUEST.
00618                    We aren't currently doing that for two reasons - first,
00619                    it's not clear that all clients do the right thing
00620                    with respect to sending the client identifier, which
00621                    could mean that we might simply not respond to a client
00622                    that is depending on us to respond.   Secondly, we allow
00623                    the user to specify the server identifier to send, and
00624                    we don't enforce that the server identifier should be
00625                    one of our IP addresses.   This is probably not a big
00626                    deal, but it's theoretically an issue.
00627 
00628                    The reason we care about this is that if both servers
00629                    send a DHCPACK to the DHCPREQUEST, they are then going
00630                    to send dueling BNDUPD messages, which could cause
00631                    trouble.   I think it causes no harm, but it seems
00632                    wrong. */
00633         } else
00634                 peer = (dhcp_failover_state_t *)0;
00635 #endif
00636 
00637         /* If a client on a given network REQUESTs a lease on an
00638            address on a different network, NAK it.  If the Requested
00639            Address option was used, the protocol says that it must
00640            have been broadcast, so we can trust the source network
00641            information.
00642 
00643            If ciaddr was specified and Requested Address was not, then
00644            we really only know for sure what network a packet came from
00645            if it came through a BOOTP gateway - if it came through an
00646            IP router, we'll just have to assume that it's cool.
00647 
00648            If we don't think we know where the packet came from, it
00649            came through a gateway from an unknown network, so it's not
00650            from a RENEWING client.  If we recognize the network it
00651            *thinks* it's on, we can NAK it even though we don't
00652            recognize the network it's *actually* on; otherwise we just
00653            have to ignore it.
00654 
00655            We don't currently try to take advantage of access to the
00656            raw packet, because it's not available on all platforms.
00657            So a packet that was unicast to us through a router from a
00658            RENEWING client is going to look exactly like a packet that
00659            was broadcast to us from an INIT-REBOOT client.
00660 
00661            Since we can't tell the difference between these two kinds
00662            of packets, if the packet appears to have come in off the
00663            local wire, we have to treat it as if it's a RENEWING
00664            client.  This means that we can't NAK a RENEWING client on
00665            the local wire that has a bogus address.  The good news is
00666            that we won't ACK it either, so it should revert to INIT
00667            state and send us a DHCPDISCOVER, which we *can* work with.
00668 
00669            Because we can't detect that a RENEWING client is on the
00670            wrong wire, it's going to sit there trying to renew until
00671            it gets to the REBIND state, when we *can* NAK it because
00672            the packet will get to us through a BOOTP gateway.  We
00673            shouldn't actually see DHCPREQUEST packets from RENEWING
00674            clients on the wrong wire anyway, since their idea of their
00675            local router will be wrong.  In any case, the protocol
00676            doesn't really allow us to NAK a DHCPREQUEST from a
00677            RENEWING client, so we can punt on this issue. */
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                 /* If we don't know where it came from but we do know
00685                    where it claims to have come from, it didn't come
00686                    from there. */
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                         /* Otherwise, ignore it. */
00694                         log_info ("%s: ignored (%s).", msgbuf,
00695                                   (subnet
00696                                    ? "not authoritative" : "unknown subnet"));
00697                         goto out;
00698                 }
00699 
00700                 /* If we do know where it came from and it asked for an
00701                    address that is not on that shared network, nak it. */
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         /* If the address the client asked for is ours, but it wasn't
00718            available for the client, NAK it. */
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         /* Otherwise, send the lease to the client if we found one. */
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]; /* XXX */
00753 
00754         TRACE(DHCPD_RELEASE_START());
00755 
00756         /* DHCPRELEASE must not specify address in requested-address
00757            option, but old protocol specs weren't explicit about this,
00758            so let it go. */
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                 /* See if we can find a lease that matches the IP address
00777                    the client is claiming. */
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         /* The client is supposed to pass a valid client-identifier,
00796            but the spec on this has changed historically, so try the
00797            IP address in ciaddr if the client-identifier fails. */
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         /* If the hardware address doesn't match, don't do the release. */
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         /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe%
00823          * We copy this out to stack because we actually want to log two
00824          * inet_ntoa()'s in this message.
00825          */
00826         strncpy(cstr, inet_ntoa (packet -> raw -> ciaddr), 15);
00827         cstr[15] = '\0';
00828 
00829         /* %Audit% This is log output. %2004.06.17,Safe%
00830          * If we truncate we hope the user can get a hint from the log.
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                 /* DHCPRELEASE messages are unicast, so if the client
00857                    sent the DHCPRELEASE to us, it's not going to send it
00858                    to the peer.   Not sure why this would happen, and
00859                    if it does happen I think we still have to change the
00860                    lease state, so that's what we're doing.
00861                    XXX See what it says in the draft about this. */
00862         }
00863 #endif
00864 
00865         /* If we found a lease, release it. */
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]; /* XXX */
00890         struct iaddr cip;
00891         struct option_cache *oc;
00892         struct data_string data;
00893 
00894         TRACE(DHCPD_DECLINE_START());
00895 
00896         /* DHCPDECLINE must specify address. */
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         /* %Audit% This is log output. %2004.06.17,Safe%
00923          * If we truncate we hope the user can get a hint from the log.
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         /* Execute statements in scope starting with the subnet scope. */
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         /* Execute statements in the class scopes. */
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         /* Drop the request if dhcpdeclines are being ignored. */
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             /* If we found a lease, mark it as unusable and complain. */
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                     /* DHCPDECLINE messages are broadcast, so we can safely
00978                        ignore the DHCPDECLINE if the peer has the lease.
00979                        XXX Of course, at this point that information has been
00980                        lost. */
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         /* The client should set ciaddr to its IP address, but apparently
01034            it's common for clients not to do this, so we'll use their IP
01035            source address if they didn't set ciaddr. */
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         /* %Audit% This is log output. %2004.06.17,Safe%
01061          * If we truncate we hope the user can get a hint from the log.
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         /* If the IP source address is zero, don't respond. */
01070         if (!memcmp(cip.iabuf, "\0\0\0", 4)) {
01071                 log_info("%s: ignored (null source address).", msgbuf);
01072                 return;
01073         }
01074 
01075         /* Find the subnet that the client is on. 
01076          * CC: Do the link selection / subnet selection
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                 /* Make a copy of the data. */
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         /* We don't respond to DHCPINFORM packets if we're not authoritative.
01131            It would be nice if a per-host value could override this, but
01132            there's overhead involved in checking this, so let's see how people
01133            react first. */
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         /* Execute statements in scope starting with the subnet scope. */
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         /* Execute statements in the class scopes. */
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          * Process host declarations during DHCPINFORM, 
01181          * Try to find a matching host declaration by cli ID or HW addr.
01182          *
01183          * Look through the host decls for one that matches the
01184          * client identifer or the hardware address.  The preference
01185          * order is:
01186          * client id with matching ip address
01187          * hardware address with matching ip address
01188          * client id without a ip fixed address
01189          * hardware address without a fixed ip address
01190          * If found, set host to use its option definitions.
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                 /* check if we have one with fixed-address
01208                  * matching the client ip first */
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                 /* fallback to a host without fixed-address */
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                 /* check if we have one with fixed-address
01268                  * matching the client ip first */
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                                          * Hmm.. we've found one
01295                                          * without IP by ID and now
01296                                          * (better) one with IP by HW.
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                 /* fallback to a host without fixed-address */
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         /* Hmm..: what when there is a host with a fixed-address,
01326          * that matches by hw or id, but the fixed-addresses
01327          * didn't match client ip?
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         /* If we have a host_decl structure, run the options
01337          * associated with its group. Whether the host decl
01338          * struct is old or not. */
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         /* CC: end of host entry processing.... */
01353         
01354         /* Figure out the filename. */
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         /* Choose a server name as above. */
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         /* Set a flag if this client is a lame Microsoft client that NUL
01396            terminates string options and expects us to do likewise. */
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         /* Put in DHCP-specific options. */
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         /* Use the subnet mask from the subnet declaration if no other
01421            mask has been provided. */
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         /* If a site option space has been specified, use that for
01440            site option codes. */
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; /* Trust me, it works. */
01465         }
01466 
01467         memset (&prl, 0, sizeof prl);
01468 
01469         /* Use the parameter list from the scope if there is one. */
01470         oc = lookup_option (&dhcp_universe, options,
01471                             DHO_DHCP_PARAMETER_REQUEST_LIST);
01472 
01473         /* Otherwise, if the client has provided a list of options
01474            that it wishes returned, use it to prioritize.  Otherwise,
01475            prioritize based on the default priority list. */
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         /* Figure out the address of the boot file server. */
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                         /* If there was more than one answer,
01502                            take the first. */
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          * Remove any time options, per section 3.4 RFC 2131
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         /* Set up the option buffer... */
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         /* Make sure that the packet is at least as big as a BOOTP packet. */
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         /* Set up the common stuff... */
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         /* RFC2131 states the server SHOULD unciast to ciaddr.
01556          * There are two wrinkles - relays, and when ciaddr is zero.
01557          * There's actually no mention of relays at all in rfc2131 in
01558          * regard to DHCPINFORM, except to say we might get packets from
01559          * clients via them.  Note: relays unicast to clients to the
01560          * "yiaddr" address, which servers are forbidden to set when
01561          * answering an inform.
01562          *
01563          * The solution: If ciaddr is zero, and giaddr is set, go via the
01564          * relay with the broadcast flag set to help the relay (with no
01565          * yiaddr and very likely no chaddr, it will have no idea where to
01566          * send the packet).
01567          *
01568          * If the ciaddr is zero and giaddr is not set, go via the source
01569          * IP address (but you are permitted to barf on their shoes).
01570          *
01571          * If ciaddr is not zero, send the packet there always.
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         /* Report what we're sending. */
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         /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
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         /* Set DHCP_MESSAGE to whatever the message is */
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          * If we are configured to do so we try to find a server id
01671          * option even for NAKS by calling setup_server_source_address().
01672          * This function will set up an options list from the global
01673          * and subnet scopes before trying to get the source address.
01674          * 
01675          * Otherwise we simply call get_server_source_address()
01676          * directly, without a server options list, this means
01677          * we'll get the source address from the interface address.
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 /* if defined(SERVER_ID_FOR_NAK) */
01684 
01685 
01686         /* If there were agent options in the incoming packet, return
01687          * them.  We do not check giaddr to detect the presence of a
01688          * relay, as this excludes "l2" relay agents which have no
01689          * giaddr to set.
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         /* Do not use the client's requested parameter list. */
01702         delete_option (&dhcp_universe, packet -> options,
01703                        DHO_DHCP_PARAMETER_REQUEST_LIST);
01704 
01705         /* Set up the option buffer... */
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 /*      memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
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         /* Report what we're sending... */
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         /* Set up the common stuff... */
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         /* Make sure that the packet is at least as big as a BOOTP packet. */
01750         if (outgoing.packet_length < BOOTP_MIN_LEN)
01751                 outgoing.packet_length = BOOTP_MIN_LEN;
01752 
01753         /* If this was gatewayed, send it back to the gateway.
01754            Otherwise, broadcast it on the local network. */
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; /* for testing. */
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         /* By default we don't do the enqueue */
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         /* If we're already acking this lease, don't do it again. */
01830         if (lease -> state)
01831                 return;
01832 
01833         TRACE(DHCPD_ACK_LEASE_START());
01834 
01835         /* Save original cltt for comparison later. */
01836         lease_cltt = lease->cltt;
01837 
01838         /* If the lease carries a host record, remember it. */
01839         if (hp)
01840                 host_reference (&host, hp, MDL);
01841         else if (lease -> host)
01842                 host_reference (&host, lease -> host, MDL);
01843 
01844         /* Allocate a lease state structure... */
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         /* See if we got a server identifier option. */
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         /* If we are offering a lease that is still currently valid, preserve
01860            the events.  We need to do this because if the client does not
01861            REQUEST our offer, it will expire in 2 minutes, overriding the
01862            expire time in the currently in force lease.  We want the expire
01863            events to be executed at that point. */
01864         if (lease->ends <= cur_time && offer != DHCPOFFER) {
01865                 /* Get rid of any old expiry or release statements - by
01866                    executing the statements below, we will be inserting new
01867                    ones if there are any to insert. */
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         /* Execute statements in scope starting with the subnet scope. */
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         /* If the lease is from a pool, run the pool scope. */
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         /* Execute statements from class scopes. */
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         /* See if the client is only supposed to have one lease at a time,
01906            and if so, find its other leases and release them.    We can only
01907            do this on DHCPREQUEST.    It's a little weird to do this before
01908            looking at permissions, because the client might not actually
01909            _get_ a lease after we've done the permission check, but the
01910            assumption for this option is that the client has exactly one
01911            network interface, and will only ever remember one lease.   So
01912            if it sends a DHCPREQUEST, and doesn't get the lease, it's already
01913            forgotten about its old lease, so we can too. */
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                     /* Don't release expired leases, and don't
01938                        release the lease we're going to assign. */
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         /* Make sure this packet satisfies the configured minimum
02017            number of seconds. */
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         /* Try to find a matching host declaration for this lease.
02043          */
02044         if (!host) {
02045                 struct host_decl *hp = (struct host_decl *)0;
02046                 struct host_decl *h;
02047 
02048                 /* Try to find a host_decl that matches the client
02049                    identifier or hardware address on the packet, and
02050                    has no fixed IP address.   If there is one, hang
02051                    it off the lease so that its option definitions
02052                    can be used. */
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         /* If we have a host_decl structure, run the options associated
02101            with its group.  Whether the host decl struct is old or not. */
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         /* Drop the request if it's not allowed for this client.   By
02112            default, unknown clients are allowed. */
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         /* Drop the request if it's not allowed for this client. */
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         /* Drop the request if booting is specifically denied. */
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         /* If we are configured to do per-class billing, do it. */
02167         if (have_billing_classes && !(lease -> flags & STATIC_LEASE)) {
02168                 /* See if the lease is currently being billed to a
02169                    class, and if so, whether or not it can continue to
02170                    be billed to that class. */
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                 /* If we don't have an active billing, see if we need
02181                    one, and if we do, try to do so. */
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                          * If this is an offer, undo the billing.  We go
02214                          * through all the steps above to bill a class so
02215                          * we can hit the 'no available billing' mark and
02216                          * abort without offering.  But it just doesn't make
02217                          * sense to permanently bill a class for a non-active
02218                          * lease.  This means on REQUEST, we will bill this
02219                          * lease again (if there is a REQUEST).
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         /* Figure out the filename. */
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         /* Choose a server name as above. */
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         /* At this point, we have a lease that we can offer the client.
02246            Now we construct a lease structure that contains what we want,
02247            and call supersede_lease to do the right thing with it. */
02248         lt = (struct lease *)0;
02249         result = lease_allocate (&lt, 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         /* Use the ip address of the lease that we finally found in
02260            the database. */
02261         lt -> ip_addr = lease -> ip_addr;
02262 
02263         /* Start now. */
02264         lt -> starts = cur_time;
02265 
02266         /* Figure out how long a lease to assign.    If this is a
02267            dynamic BOOTP lease, its duration must be infinite. */
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                         /* One potential use of reserved leases is to allow
02300                          * clients to signal reservation of their lease.  They
02301                          * can kinda sorta do this, if you squint hard enough,
02302                          * by supplying an 'infinite' requested-lease-time
02303                          * option.  This is generally bad practice...you want
02304                          * clients to return to the server on at least some
02305                          * period (days, months, years) to get up-to-date
02306                          * config state.  So;
02307                          *
02308                          * 1) A client requests 0xffffffff lease-time.
02309                          * 2) The server reserves the lease, and assigns a
02310                          *    <= max_lease_time lease-time to the client, which
02311                          *    we presume is much smaller than 0xffffffff.
02312                          * 3) The client ultimately fails to renew its lease
02313                          *    (all clients go offline at some point).
02314                          * 4) The server retains the reservation, although
02315                          *    the lease expires and passes through those states
02316                          *    as normal, it's placed in the 'reserved' queue,
02317                          *    and is under no circumstances allocated to any
02318                          *    clients.
02319                          *
02320                          * Whether the client knows its reserving its lease or
02321                          * not, this can be a handy tool for a sysadmin.
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                 /* See if there's a maximum lease time. */
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                 /* Enforce the maximum lease length. */
02362                 if (lease_time < 0 /* XXX */
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                 /* CC: If there are less than
02384                    adaptive-lease-time-threshold % free leases,
02385                      hand out only short term leases */
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                                 /* Allow the client to keep its lease. */
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                 /* a client requests an address which is not yet active*/
02440                 if (lease->pool && lease->pool->valid_from && 
02441                     cur_time < lease->pool->valid_from) {
02442                         /* NAK leases before pool activation date */
02443                         cip.len = 4;
02444                         memcpy (cip.iabuf, &lt->ip_addr.iabuf, 4);
02445                         nak_lease(packet, &cip);
02446                         free_lease_state (state, MDL);
02447                         lease_dereference (&lt, MDL);
02448                         if (host)
02449                                 host_dereference (&host, MDL);
02450                         return;
02451                         
02452                 }
02453 
02454                 /* CC:
02455                 a) NAK current lease if past the expiration date
02456                 b) extend lease only up to the expiration date, but not
02457                 below min-lease-time
02458                 Setting min-lease-time is essential for this to work!
02459                 The value of min-lease-time determines the lenght
02460                 of the transition window:
02461                 A client renewing a second before the deadline will
02462                 get a min-lease-time lease. Since the current ip might not
02463                 be routable after the deadline, the client will
02464                 be offline until it DISCOVERS again. Otherwise it will
02465                 receive a NAK at T/2.
02466                 A min-lease-time of 6 seconds effectively switches over
02467                 all clients in this pool very quickly.
02468                         */
02469  
02470                 if (lease->pool && lease->pool->valid_until) {
02471                         if (cur_time >= lease->pool->valid_until) {
02472                                 /* NAK leases after pool expiration date */
02473                                 cip.len = 4;
02474                                 memcpy (cip.iabuf, &lt->ip_addr.iabuf, 4);
02475                                 nak_lease(packet, &cip);
02476                                 free_lease_state (state, MDL);
02477                                 lease_dereference (&lt, 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                 /* Okay, we know the lease duration.   Now check the
02497                    failover state, if any. */
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                         /* Copy previous lease failover ack-state. */
02504                         lt->tsfp = lease->tsfp;
02505                         lt->atsfp = lease->atsfp;
02506 
02507                         /* cltt set below */
02508 
02509                         /* Lease times less than MCLT are not a concern. */
02510                         if (lease_time > peer->mclt) {
02511                                 /* Each server can only offer a lease time
02512                                  * that is either equal to MCLT (at least),
02513                                  * or up to TSFP+MCLT.  Only if the desired
02514                                  * lease time falls within TSFP+MCLT, can
02515                                  * the server allow it.
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                         /* Update potential expiry.  Allow for the desired
02526                          * lease time plus one half the actual (whether
02527                          * modified downward or not) lease time, which is
02528                          * actually an estimate of when the client will
02529                          * renew.  This way, the client will be able to get
02530                          * the desired lease time upon renewal.
02531                          */
02532                         if (offer == DHCPACK) {
02533                                 lt->tstp = cur_time + lease_time +
02534                                                 (new_lease_time / 2);
02535 
02536                                 /* If we reduced the potential expiry time,
02537                                  * make sure we don't offer an old-expiry-time
02538                                  * lease for this lease before the change is
02539                                  * ack'd.
02540                                  */
02541                                 if (lt->tstp < lt->tsfp)
02542                                         lt->tsfp = lt->tstp;
02543                         } else
02544                                 lt->tstp = lease->tstp;
02545 
02546                         /* Use failover-modified lease time.  */
02547                         lease_time = new_lease_time;
02548                 }
02549 #endif /* FAILOVER_PROTOCOL */
02550 
02551                 /* If the lease duration causes the time value to wrap,
02552                    use the maximum expiry time. */
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                 /* Don't make lease active until we actually get a
02563                    DHCPREQUEST. */
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         /* Update Client Last Transaction Time. */
02605         lt->cltt = cur_time;
02606 
02607         /* See if we want to record the uid for this client */
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                 /* Record the uid, if given... */
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                                 /* XXX inelegant */
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 (&lt -> host, host, MDL);
02645                 host_dereference (&host, MDL);
02646         }
02647         if (lease -> subnet)
02648                 subnet_reference (&lt -> subnet, lease -> subnet, MDL);
02649         if (lease -> billing_class)
02650                 class_reference (&lt -> billing_class,
02651                                  lease -> billing_class, MDL);
02652 
02653         /* Set a flag if this client is a broken client that NUL
02654            terminates string options and expects us to do likewise. */
02655         if (ms_nulltp)
02656                 lease -> flags |= MS_NULL_TERMINATION;
02657         else
02658                 lease -> flags &= ~MS_NULL_TERMINATION;
02659 
02660         /* Save any bindings. */
02661         if (lease -> scope) {
02662                 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
02663                 binding_scope_dereference (&lease -> scope, MDL);
02664         }
02665         if (lease -> agent_options)
02666                 option_chain_head_reference (&lt -> agent_options,
02667                                              lease -> agent_options, MDL);
02668 
02669         /* Save the vendor-class-identifier for DHCPLEASEQUERY. */
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         /* If we got relay agent information options from the packet, then
02684          * cache them for renewal in case the relay agent can't supply them
02685          * when the client unicasts.  The options may be from an addressed
02686          * "l3" relay, or from an unaddressed "l2" relay which does not set
02687          * giaddr.
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 (&lt -> agent_options, MDL);
02703                 option_chain_head_reference
02704                         (&lt -> agent_options,
02705                          (struct option_chain_head *)
02706                          packet -> options -> universes [agent_universe.index],
02707                          MDL);
02708             }
02709         }
02710 
02711         /* Replace the old lease hostname with the new one, if it's changed. */
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                 /* Hasn't changed. */
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         /* Record the hardware address, if given... */
02742         lt -> hardware_addr.hlen = packet -> raw -> hlen + 1;
02743         lt -> hardware_addr.hbuf [0] = packet -> raw -> htype;
02744         memcpy (&lt -> hardware_addr.hbuf [1], packet -> raw -> chaddr,
02745                 sizeof packet -> raw -> chaddr);
02746 
02747         lt -> flags = lease -> flags & ~PERSISTENT_FLAGS;
02748 
02749         /* If there are statements to execute when the lease is
02750            committed, execute them. */
02751         if (lease->on_star.on_commit && (!offer || offer == DHCPACK)) {
02752                 execute_statements (NULL, packet, lt, NULL, packet->options,
02753                                     state->options, &lt->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         /* Perform DDNS updates, if configured to. */
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                                             &lt -> scope, oc, MDL))) {
02770                 ddns_updates(packet, lt, lease, NULL, NULL, state->options);
02771         }
02772 #endif /* NSUPDATE */
02773 
02774         /* Don't call supersede_lease on a mocked-up lease. */
02775         if (lease -> flags & STATIC_LEASE) {
02776                 /* Copy the hardware address into the static lease
02777                    structure. */
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); /* XXX */
02783         } else {
02784                 int commit = (!offer || (offer == DHCPACK));
02785                 int thresh = DEFAULT_CACHE_THRESHOLD;
02786 
02787                 /*
02788                  * Check if the lease was issued recently, if so replay the 
02789                  * current lease and do not require a database sync event.  
02790                  * Recently is defined as being issued less than a given 
02791                  * percentage of the lease previously. The percentage can be 
02792                  * chosen either from a default value or via configuration.
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                                           &lt->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                  * We check on ddns_cb to see if the ddns code has
02808                  * updated the lt structure.  We could probably simply
02809                  * copy the ddns_cb pointer in that case but lets be
02810                  * simple and safe and update the entire lease.
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                         /* it is better to avoid division by 0 */
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                 /* Install the new information on 'lt' onto the lease at
02834                  * 'lease'.  If this is a DHCPOFFER, it is a 'soft' promise,
02835                  * if it is a DHCPACK, it is a 'hard' binding, so it needs
02836                  * to be recorded and propogated immediately.  If the update
02837                  * fails, don't ACK it (or BOOTREPLY) either; we may give
02838                  * the same lease to another client later, and that would be
02839                  * a conflict.
02840                  */
02841                 if ((use_old_lease == 0) &&
02842                     !supersede_lease(lease, lt, commit,
02843                                      offer == DHCPACK, offer == DHCPACK)) {
02844 #else /* defined(DELAYED_ACK) */
02845                 /*
02846                  * If there already isn't a need for a lease commit, and we
02847                  * can just answer right away, set a flag to indicate this.
02848                  */
02849                 if (commit)
02850                         enqueue = ISC_TRUE;
02851 
02852                 /* Install the new information on 'lt' onto the lease at
02853                  * 'lease'.  We will not 'commit' this information to disk
02854                  * yet (fsync()), we will 'propogate' the information if
02855                  * this is BOOTP or a DHCPACK, but we will not 'pimmediate'ly
02856                  * transmit failover binding updates (this is delayed until
02857                  * after the fsync()).  If the update fails, don't ACK it (or
02858                  * BOOTREPLY either); we may give the same lease out to a
02859                  * different client, and that would be a conflict.
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 (&lt, MDL);
02868                         return;
02869                 }
02870         }
02871         lease_dereference (&lt, MDL);
02872 
02873         /* Remember the interface on which the packet arrived. */
02874         state -> ip = packet -> interface;
02875 
02876         /* Remember the giaddr, xid, secs, flags and hops. */
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         /* If we're always supposed to broadcast to this client, set
02886            the broadcast bit in the bootp flags field. */
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         /* Get the Maximum Message Size option from the packet, if one
02896            was sent. */
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         /* Get the Subnet Selection option from the packet, if one
02923            was sent. */
02924         if ((oc = lookup_option (&dhcp_universe, packet -> options,
02925                                  DHO_SUBNET_SELECTION))) {
02926 
02927                 /* Make a copy of the data. */
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         /* Now, if appropriate, put in DHCP-specific options that
02946            override those. */
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                  * Validate any configured renew or rebinding times against
02987                  * the determined lease time.  Do rebinding first so that
02988                  * the renew time can be validated against the rebind time.
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                         /* Drop the configured (invalid) rebinding time. */
02998                         if (rebind_time >= offered_lease_time)
02999                                 delete_option(&dhcp_universe, state->options,
03000                                               DHO_DHCP_REBINDING_TIME);
03001                         else /* XXX: variable is reused. */
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                 /* XXXSK: should we use get_server_source_address() here? */
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         /* Figure out the address of the boot file server. */
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                         /* If there was more than one answer,
03039                            take the first. */
03040                         if (d1.len >= 4 && d1.data)
03041                                 memcpy (&state -> siaddr, d1.data, 4);
03042                         data_string_forget (&d1, MDL);
03043                 }
03044         }
03045 
03046         /* Use the subnet mask from the subnet declaration if no other
03047            mask has been provided. */
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         /* Use the hostname from the host declaration if there is one
03067            and no hostname has otherwise been provided, and if the 
03068            use-host-decl-name flag is set. */
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         /* If we don't have a hostname yet, and we've been asked to do
03095            a reverse lookup to find the hostname, do it. */
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         /* If so directed, use the leased IP address as the router address.
03131            This supposedly makes Win95 machines ARP for all IP addresses,
03132            so if the local router does proxy arp, you win. */
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         /* If a site option space has been specified, use that for
03160            site option codes. */
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         /* If the client has provided a list of options that it wishes
03185            returned, use it to prioritize.  If there's a parameter
03186            request list in scope, use that in preference.  Otherwise
03187            use the default priority list. */
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         /* Hang the packet off the lease state. */
03211         packet_reference (&lease -> state -> packet, packet, MDL);
03212 
03213         /* If this is a DHCPOFFER, ping the lease address before actually
03214            sending the offer. */
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                 /* Determine whether to use configured or default ping timeout.
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                  * Set a timeout for 'ping-timeout' seconds from NOW, including
03249                  * current microseconds.  As ping-timeout defaults to 1, the
03250                  * exclusion of current microseconds causes a value somewhere
03251                  * /between/ zero and one.
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  * CC: queue single ACK:
03274  * - write the lease (but do not fsync it yet)
03275  * - add to double linked list
03276  * - commit if more than xx ACKs pending
03277  * - if necessary set the max timer and bump the next timer
03278  *   but only up to the max timer value.
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         /* prepend to ackqueue*/
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                 /* Reset max_fsync and cancel any pending timeout. */
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                         /* set the maximum time we'll wait */
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                 /* Set the timeout */
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                 /* but not more than the max */
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 /* CC: process the delayed ACK responses:
03360    - send out the ACK packets
03361    - move the queue slots to the free list
03362  */
03363 void
03364 flush_ackqueue(void *foo) 
03365 {
03366         struct leasequeue *ack, *p;
03367         /*  process from bottom to retain packet order */
03368         for (ack = ackqueue_tail ; ack ; ack = p) { 
03369                 p = ack->prev;
03370 
03371                 /* dhcp_reply() requires that the reply state still be valid */
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         /* Compose a response for the client... */
03425         memset (&raw, 0, sizeof raw);
03426         memset (&d1, 0, sizeof d1);
03427 
03428         /* Copy in the filename if given; otherwise, flag the filename
03429            buffer as available for options. */
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         /* Copy in the server name if given; otherwise, flag the
03448            server_name buffer as available for options. */
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; /* XXX */
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         /* See if this is a Microsoft client that NUL-terminates its
03473            strings and expects us to do likewise... */
03474         if (lease -> flags & MS_NULL_TERMINATION)
03475                 nulltp = 1;
03476         else
03477                 nulltp = 0;
03478 
03479         /* See if this is a bootp client... */
03480         if (state -> offer)
03481                 bootpp = 0;
03482         else
03483                 bootpp = 1;
03484 
03485         /* Insert such options as will fit into the buffer. */
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         /* Say what we're doing... */
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         /* Set up the hardware address... */
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         /* Make sure outgoing packets are at least as big
03546            as a BOOTP packet. */
03547         if (packet_length < BOOTP_MIN_LEN)
03548                 packet_length = BOOTP_MIN_LEN;
03549 
03550         /* If this was gatewayed, send it back to the gateway... */
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; /* For debugging. */
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         /* If the client is RENEWING, unicast to the client using the
03576            regular IP stack.  Some clients, particularly those that
03577            follow RFC1541, are buggy, and send both ciaddr and server
03578            identifier.  We deal with this situation by assuming that
03579            if we got both dhcp-server-identifier and ciaddr, and
03580            giaddr was not set, then the client is on the local
03581            network, and we can therefore unicast or broadcast to it
03582            successfully.  A client in REQUESTING state on another
03583            network that's making this mistake will have set giaddr,
03584            and will therefore get a relayed response from the above
03585            code. */
03586         } else if (raw.ciaddr.s_addr &&
03587                    !((state -> got_server_identifier ||
03588                       (raw.flags & htons (BOOTP_BROADCAST))) &&
03589                      /* XXX This won't work if giaddr isn't zero, but it is: */
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         /* If it comes from a client that already knows its address
03613            and is not requesting a broadcast response, and we can
03614            unicast to a client without using the ARP protocol, sent it
03615            directly to that client. */
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         /* Otherwise, broadcast it on the local network. */
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         /* Free all of the entries in the option_state structure
03641            now that we're done with them. */
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         /* Quick check to see if the peer has leases. */
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 /* FAILOVER_PROTOCOL */
03688 
03689         if (packet -> raw -> ciaddr.s_addr) {
03690                 cip.len = 4;
03691                 memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
03692         } else {
03693                 /* Look up the requested address. */
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         /* Try to find a host or lease that's been assigned to the
03712            specified unique client identifier. */
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                 /* Remember this for later. */
03723                 have_client_identifier = 1;
03724 
03725                 /* First, try to find a fixed host entry for the specified
03726                    client identifier... */
03727                 if (find_hosts_by_uid (&hp, client_identifier.data,
03728                                        client_identifier.len, MDL)) {
03729                         /* Remember if we know of this client. */
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) /* Save the host if we found one. */
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         /* If we didn't find a fixed lease using the uid, try doing
03751            it with the hardware address... */
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                         /* Remember if we know of this client. */
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         /* Finally, if we haven't found anything yet try again with the
03773          * host-identifier option ... */
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         /* If fixed_lease is present but does not match the requested
03792            IP address, and this is a DHCPREQUEST, then we can't return
03793            any other lease, so we might as well return now. */
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          * If we found leases matching the client identifier, loop through
03811          * the n_uid pointer looking for one that's actually valid.   We
03812          * can't do this until we get here because we depend on
03813          * packet -> known, which may be set by either the uid host
03814          * lookup or the haddr host lookup.
03815          *
03816          * Note that the n_uid lease chain is sorted in order of
03817          * preference, so the first one is the best one.
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                  * When we lookup a lease by uid, we know the client identifier
03828                  * matches the lease's record.  If it is active, or was last
03829                  * active with the same client, we can trivially extend it.
03830                  * If is not or was not active, we can allocate it to this
03831                  * client if it matches the usual free/backup criteria (which
03832                  * is contained in lease_mine_to_reallocate()).
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         /* Find a lease whose hardware address matches, whose client
03883          * identifier matches (or equally doesn't have one), that's
03884          * permitted, and that's on the correct subnet.
03885          *
03886          * Note that the n_hw chain is sorted in order of preference, so
03887          * the first one found is the best one.
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                  * When we lookup a lease by chaddr, we know the MAC address
03901                  * matches the lease record (we will check if the lease has a
03902                  * client-id the client does not next).  If the lease is
03903                  * currently active or was last active with this client, we can
03904                  * trivially extend it.  Otherwise, there are a set of rules
03905                  * that govern if we can reallocate this lease to any client
03906                  * ("lease_mine_to_reallocate()") including this one.
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                  * This conditional skips "potentially active" leases (leases
03921                  * we think are expired may be extended by the peer, etc) that
03922                  * may be assigned to a differently /client-identified/ client
03923                  * with the same MAC address.
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         /* Try to find a lease that's been allocated to the client's
03974            IP address. */
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         /* If ip_lease is valid at this point, set ours to one, so that
03987            even if we choose a different lease, we know that the address
03988            the client was requesting was ours, and thus we can NAK it. */
03989         if (ip_lease && ours)
03990                 *ours = 1;
03991 
03992         /* If the requested IP address isn't on the network the packet
03993            came from, don't use it.  Allow abandoned leases to be matched
03994            here - if the client is requesting it, there's a decent chance
03995            that it's because the lease database got trashed and a client
03996            that thought it had this lease answered an ARP or PING, causing the
03997            lease to be abandoned.   If so, this request probably came from
03998            that client. */
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          * If the requested address is in use (or potentially in use) by
04011          * a different client, it can't be granted.
04012          *
04013          * This first conditional only detects if the lease is currently
04014          * identified to a different client (client-id and/or chaddr
04015          * mismatch).  In this case we may not want to give the client the
04016          * lease, if doing so may potentially be an addressing conflict.
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                  * A lease is unavailable for allocation to a new client if
04031                  * it is not in the FREE or BACKUP state.  There may be
04032                  * leases that are in the expired state with a rewinding
04033                  * state that is free or backup, but these will be processed
04034                  * into the free or backup states by expiration processes, so
04035                  * checking for them here is superfluous.
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                         /* If we're rejecting it because the peer has
04043                            it, don't set "ours", because we shouldn't NAK. */
04044                         if (ours && ip_lease -> binding_state != FTS_ACTIVE)
04045                                 *ours = 0;
04046                         lease_dereference (&ip_lease, MDL);
04047                 }
04048         }
04049 
04050         /*
04051          * If we got an ip_lease and a uid_lease or hw_lease, and ip_lease
04052          * is/was not active, and is not ours to reallocate, forget about it.
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         /* If for some reason the client has more than one lease
04068            on the subnet that matches its uid, pick the one that
04069            it asked for and (if we can) free the other. */
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                                 /* If the client is REQUESTing the lease,
04085                                    it shouldn't still be using the old
04086                                    one, so we can free it for allocation. */
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                 /* If we get to here and fixed_lease is not null, that means
04101                    that there are both a dynamic lease and a fixed-address
04102                    declaration for the same IP address. */
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         /* If we get to here with both fixed_lease and ip_lease not
04133            null, then we have a configuration file bug. */
04134         if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
04135                 goto db_conflict;
04136 
04137         /* Toss extra pointers to the same lease... */
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         /* Make sure the client is permitted to use the requested lease. */
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         /* If we've already eliminated the lease, it wasn't there to
04191            begin with.   If we have come up with a matching lease,
04192            set the message to bad network in case we have to throw it out. */
04193         if (!ip_lease) {
04194                 strcpy (dhcp_message, "requested address not available");
04195         }
04196 
04197         /* If this is a DHCPREQUEST, make sure the lease we're going to return
04198            matches the requested IP address.   If it doesn't, don't return a
04199            lease at all. */
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         /* At this point, if fixed_lease is nonzero, we can assign it to
04209            this client. */
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         /* If we got a lease that matched the ip address and don't have
04219            a better offer, use that; otherwise, release it. */
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         /* If we got a lease that matched the client identifier, we may want
04239            to use it, but if we already have a lease we like, we must free
04240            the lease that matched the client identifier. */
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         /* The lease that matched the hardware address is treated likewise. */
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                         /* We're a little lax here - if the client didn't
04275                            send a client identifier and it's a bootp client,
04276                            but the lease has a client identifier, we still
04277                            let the client have a lease. */
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          * If we found a host_decl but no matching address, try to
04304          * find a host_decl that has no address, and if there is one,
04305          * hang it off the lease so that we can use the supplied
04306          * options.
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                                  * If the lease is currently active, then it
04317                                  * must be allocated to the present client.
04318                                  * We store a reference to the host record on
04319                                  * the lease to save a lookup later (in
04320                                  * ack_lease()).  We mustn't refer to the host
04321                                  * record on non-active leases because the
04322                                  * client may be denied later.
04323                                  *
04324                                  * XXX: Not having this reference (such as in
04325                                  * DHCPDISCOVER/INIT) means ack_lease will have
04326                                  * to perform this lookup a second time.  This
04327                                  * hopefully isn't a problem as DHCPREQUEST is
04328                                  * more common than DHCPDISCOVER.
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         /* If we find an abandoned lease, but it's the one the client
04347            requested, we assume that previous bugginess on the part
04348            of the client, or a server database loss, caused the lease to
04349            be abandoned, so we reclaim it and let the client have it. */
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         /* Otherwise, if it's not the one the client requested, we do not
04358            return it - instead, we claim it's ours, causing a DHCPNAK to be
04359            sent if this lookup is for a DHCPREQUEST, and force the client
04360            to go back through the allocation process. */
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 /* Search the provided host_decl structure list for an address that's on
04400    the specified shared network.  If one is found, mock up and return a
04401    lease structure for it; otherwise return the null pointer. */
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 /* Look through all the pools in a list starting with the specified pool
04447    for a free lease.   We try to find a virgin lease if we can.   If we
04448    don't find a virgin lease, we try to find a non-virgin lease that's
04449    free.   If we can't find one of those, we try to reclaim an abandoned
04450    lease.   If all of these possibilities fail to pan out, we don't return
04451    a lease at all. */
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                 /* Peer_has_leases just says that we found at least one
04468                    free lease.  If no free lease is returned, the caller
04469                    can deduce that this means the peer is hogging all the
04470                    free leases, so we can print a better error message. */
04471                 /* XXX Do we need code here to ignore PEER_IS_OWNER and
04472                  * XXX just check tstp if we're in, e.g., PARTNER_DOWN?
04473                  * XXX Where do we deal with CONFLICT_DETECTED, et al? */
04474                 /* XXX This should be handled by the lease binding "state
04475                  * XXX machine" - that is, when we get here, if a lease
04476                  * XXX could be allocated, it will have the correct
04477                  * XXX binding state so that the following code will
04478                  * XXX result in its being allocated. */
04479                 /* Skip to the most expired lease in the pool that is not
04480                  * owned by a failover peer. */
04481                 if (pool->failover_peer != NULL) {
04482                         if (pool->failover_peer->i_am == primary) {
04483                                 candl = pool->free;
04484 
04485                                 /*
04486                                  * In normal operation, we never want to touch
04487                                  * the peer's leases.  In partner-down 
04488                                  * operation, we need to be able to pick up
04489                                  * the peer's leases after STOS+MCLT.
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                         /* Try abandoned leases as a last resort. */
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                  * XXX: This may not match with documented expectation.
04534                  * It's expected that when we OFFER a lease, we set its
04535                  * ends time forward 2 minutes so that it gets sorted to
04536                  * the end of its free list (avoiding a similar allocation
04537                  * to another client).  It is not expected that we issue a
04538                  * "no free leases" error when the last lease has been
04539                  * offered, but it's not exactly broken either.
04540                  */
04541                 if (!candl || (candl -> ends > cur_time))
04542                         continue;
04543 
04544                 if (!lease) {
04545                         lease = candl;
04546                         continue;
04547                 }
04548 
04549                 /*
04550                  * There are tiers of lease state preference, listed here in
04551                  * reverse order (least to most preferential):
04552                  *
04553                  *    ABANDONED
04554                  *    FREE/BACKUP
04555                  *
04556                  * If the selected lease and candidate are both of the same
04557                  * state, select the oldest (longest ago) expiration time
04558                  * between the two.  If the candidate lease is of a higher
04559                  * preferred grade over the selected lease, use it.
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                  * XXX: For reliability, we go ahead and remove the host
04588                  * record and try to move on.  For correctness, if there
04589                  * are any other stale host vectors, we want to find them.
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 /* Determine whether or not a permit exists on a particular permit list
04607    that matches the specified packet, returning nonzero if so, zero if
04608    not. */
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         /* See if there's a Relay Agent Link Selection Option, or a
04679          * Subnet Selection Option.  The Link-Select and Subnet-Select
04680          * are formatted and used precisely the same, but we must prefer
04681          * the link-select over the subnet-select.
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         /* If there's no SSO and no giaddr, then use the shared_network
04689            from the interface, if there is one.   If not, fail. */
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         /* If there's an option indicating link connection, and it's valid,
04713          * use it to figure out the subnet.  If it's not valid, fail.
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         /* If we know the subnet on which the IP address lives, use it. */
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         /* Otherwise, fail. */
04750         return 0;
04751 }
04752 
04753 /*
04754  * Try to figure out the source address to send packets from.
04755  *
04756  * from is the address structure we use to return any address
04757  * we find.
04758  *
04759  * options is the option cache to search.  This may include
04760  * options from the incoming packet and configuration information.
04761  *
04762  * out_options is the outgoing option cache.  This cache
04763  * may be the same as options.  If send_options isn't NULL
04764  * we may save the server address option into it.  We do so
04765  * if send_options is different than options or if the option
04766  * wasn't in options and we needed to find the address elsewhere.
04767  *
04768  * packet is the state structure for the incoming packet
04769  *
04770  * When finding the address we first check to see if it is
04771  * in the options list.  If it isn't we use the first address
04772  * from the interface.
04773  *
04774  * While this is slightly more complicated than I'd like it allows
04775  * us to use the same code in several different places.  ack,
04776  * inform and lease query use it to find the address and fill
04777  * in the options if we get the address from the interface.
04778  * nack uses it to find the address and copy it to the outgoing
04779  * cache.  dhcprequest uses it to find the address for comparison
04780  * and doesn't need to add it to an outgoing list.
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                                  * Arrange to save a copy of the data
04810                                  * to the outgoing list.
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  * Set up an option state list to try and find a server option.
04850  * We don't go through all possible options - in particualr we
04851  * skip the hosts and we don't include the lease to avoid 
04852  * making changes to it.  This means that we won't get the
04853  * correct server id if the admin puts them on hosts or
04854  * builds the server id with information from the lease.
04855  *
04856  * As this is a fallback function (used to handle NAKs or
04857  * sort out server id mismatch in failover) and requires
04858  * configuration by the admin, it should be okay.
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                  * If we have a subnet and group start with that else start
04873                  * with the shared network group.  The first will recurse and
04874                  * include the second.
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                 /* do the pool if there is one */
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                 /* currently we don't bother with classes or hosts as
04902                  * neither seems to be useful in this case */
04903         }
04904 
04905         /* Make the call to get the server address */
04906         get_server_source_address(from, sid_options, options, packet);
04907 
04908         /* get rid of the option cache */
04909         if (sid_options != NULL)
04910                 option_state_dereference(&sid_options, MDL);
04911 }
04912 
04913 /*
04914  * Look for the lowest numbered site code number and
04915  * apply a log warning if it is less than 224.  Do not
04916  * permit site codes less than 128 (old code never did).
04917  *
04918  * Note that we could search option codes 224 down to 128
04919  * on the hash table, but the table is (probably) smaller
04920  * than that if it was declared as a standalone table with
04921  * defaults.  So we traverse the option code hash.
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          * Note that site_code_min has to be global as we can't pass an
04931          * argument through hash_foreach().  The value 224 is taken from
04932          * RFC 3942.
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          * don't even bother logging, this is just silly, and never worked
04949          * on any old version of software.
04950          */
04951         if (site_code_min < 128)
04952                 site_code_min = 128;
04953 
04954         /*
04955          * Cache the determined minimum site code on the universe structure.
04956          * Note that due to the < 128 check above, a value of zero is
04957          * impossible.
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         /* If there were agent options in the incoming packet, return
04979          * them.  Do not return the agent options if they were stashed
04980          * on the lease.  We do not check giaddr to detect the presence of
04981          * a relay, as this excludes "l2" relay agents which have no giaddr
04982          * to set.
04983          *
04984          * XXX: If the user configures options for the relay agent information
04985          * (state->options->universes[agent_universe.index] is not NULL),
04986          * we're still required to duplicate other values provided by the
04987          * relay agent.  So we need to merge the old values not configured
04988          * by the user into the new state, not just give up.
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 }

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1