Annotation of embedaddon/dhcp/server/dhcp.c, revision 1.1

1.1     ! misho       1: /* dhcp.c
        !             2: 
        !             3:    DHCP Protocol engine. */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
        !             7:  * Copyright (c) 1995-2003 by Internet Software Consortium
        !             8:  *
        !             9:  * Permission to use, copy, modify, and distribute this software for any
        !            10:  * purpose with or without fee is hereby granted, provided that the above
        !            11:  * copyright notice and this permission notice appear in all copies.
        !            12:  *
        !            13:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            14:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            15:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            16:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            17:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            18:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            19:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            20:  *
        !            21:  *   Internet Systems Consortium, Inc.
        !            22:  *   950 Charter Street
        !            23:  *   Redwood City, CA 94063
        !            24:  *   <info@isc.org>
        !            25:  *   https://www.isc.org/
        !            26:  *
        !            27:  * This software has been written for Internet Systems Consortium
        !            28:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
        !            29:  * To learn more about Internet Systems Consortium, see
        !            30:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
        !            31:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
        !            32:  * ``http://www.nominum.com''.
        !            33:  */
        !            34: 
        !            35: #include "dhcpd.h"
        !            36: #include <errno.h>
        !            37: #include <limits.h>
        !            38: #include <sys/time.h>
        !            39: 
        !            40: static void commit_leases_ackout(void *foo);
        !            41: 
        !            42: int outstanding_pings;
        !            43: 
        !            44: struct leasequeue *ackqueue_head, *ackqueue_tail;
        !            45: static struct leasequeue *free_ackqueue;
        !            46: static struct timeval next_fsync;
        !            47: int outstanding_acks;
        !            48: int max_outstanding_acks = DEFAULT_DELAYED_ACK;
        !            49: int max_ack_delay_secs = DEFAULT_ACK_DELAY_SECS;
        !            50: int max_ack_delay_usecs = DEFAULT_ACK_DELAY_USECS;
        !            51: 
        !            52: static char dhcp_message [256];
        !            53: static int site_code_min;
        !            54: 
        !            55: static int find_min_site_code(struct universe *);
        !            56: static isc_result_t lowest_site_code(const void *, unsigned, void *);
        !            57: 
        !            58: static const char *dhcp_type_names [] = { 
        !            59:        "DHCPDISCOVER",
        !            60:        "DHCPOFFER",
        !            61:        "DHCPREQUEST",
        !            62:        "DHCPDECLINE",
        !            63:        "DHCPACK",
        !            64:        "DHCPNAK",
        !            65:        "DHCPRELEASE",
        !            66:        "DHCPINFORM",
        !            67:        "type 9",
        !            68:        "DHCPLEASEQUERY",
        !            69:        "DHCPLEASEUNASSIGNED",
        !            70:        "DHCPLEASEUNKNOWN",
        !            71:        "DHCPLEASEACTIVE"
        !            72: };
        !            73: const int dhcp_type_name_max = ((sizeof dhcp_type_names) / sizeof (char *));
        !            74: 
        !            75: #if defined (TRACING)
        !            76: # define send_packet trace_packet_send
        !            77: #endif
        !            78: 
        !            79: void
        !            80: dhcp (struct packet *packet) {
        !            81:        int ms_nulltp = 0;
        !            82:        struct option_cache *oc;
        !            83:        struct lease *lease = NULL;
        !            84:        const char *errmsg;
        !            85:        struct data_string data;
        !            86: 
        !            87:        if (!locate_network(packet) &&
        !            88:            packet->packet_type != DHCPREQUEST &&
        !            89:            packet->packet_type != DHCPINFORM && 
        !            90:            packet->packet_type != DHCPLEASEQUERY) {
        !            91:                const char *s;
        !            92:                char typebuf[32];
        !            93:                errmsg = "unknown network segment";
        !            94:              bad_packet:
        !            95:                
        !            96:                if (packet->packet_type > 0 &&
        !            97:                    packet->packet_type <= dhcp_type_name_max) {
        !            98:                        s = dhcp_type_names[packet->packet_type - 1];
        !            99:                } else {
        !           100:                        /* %Audit% Cannot exceed 28 bytes. %2004.06.17,Safe% */
        !           101:                        sprintf(typebuf, "type %d", packet->packet_type);
        !           102:                        s = typebuf;
        !           103:                }
        !           104:                
        !           105:                log_info("%s from %s via %s: %s", s,
        !           106:                         (packet->raw->htype
        !           107:                          ? print_hw_addr(packet->raw->htype,
        !           108:                                          packet->raw->hlen,
        !           109:                                          packet->raw->chaddr)
        !           110:                          : "<no identifier>"),
        !           111:                         packet->raw->giaddr.s_addr
        !           112:                         ? inet_ntoa(packet->raw->giaddr)
        !           113:                         : packet->interface->name, errmsg);
        !           114:                goto out;
        !           115:        }
        !           116: 
        !           117:        /* There is a problem with the relay agent information option,
        !           118:         * which is that in order for a normal relay agent to append
        !           119:         * this option, the relay agent has to have been involved in
        !           120:         * getting the packet from the client to the server.  Note
        !           121:         * that this is the software entity known as the relay agent,
        !           122:         * _not_ the hardware entity known as a router in which the
        !           123:         * relay agent may be running, so the fact that a router has
        !           124:         * forwarded a packet does not mean that the relay agent in
        !           125:         * the router was involved.
        !           126:         *
        !           127:         * So when the client broadcasts (DHCPDISCOVER, or giaddr is set),
        !           128:         * we can be sure that there are either agent options in the
        !           129:         * packet, or there aren't supposed to be.  When the giaddr is not
        !           130:         * set, it's still possible that the client is on a directly
        !           131:         * attached subnet, and agent options are being appended by an l2
        !           132:         * device that has no address, and so sets no giaddr.
        !           133:         *
        !           134:         * But in either case it's possible that the packets we receive
        !           135:         * from the client in RENEW state may not include the agent options,
        !           136:         * so if they are not in the packet we must "pretend" the last values
        !           137:         * we observed were provided.
        !           138:         */
        !           139:        if (packet->packet_type == DHCPREQUEST &&
        !           140:            packet->raw->ciaddr.s_addr && !packet->raw->giaddr.s_addr &&
        !           141:            (packet->options->universe_count <= agent_universe.index ||
        !           142:             packet->options->universes[agent_universe.index] == NULL))
        !           143:        {
        !           144:                struct iaddr cip;
        !           145: 
        !           146:                cip.len = sizeof packet -> raw -> ciaddr;
        !           147:                memcpy (cip.iabuf, &packet -> raw -> ciaddr,
        !           148:                        sizeof packet -> raw -> ciaddr);
        !           149:                if (!find_lease_by_ip_addr (&lease, cip, MDL))
        !           150:                        goto nolease;
        !           151: 
        !           152:                /* If there are no agent options on the lease, it's not
        !           153:                   interesting. */
        !           154:                if (!lease -> agent_options)
        !           155:                        goto nolease;
        !           156: 
        !           157:                /* The client should not be unicasting a renewal if its lease
        !           158:                   has expired, so make it go through the process of getting
        !           159:                   its agent options legally. */
        !           160:                if (lease -> ends < cur_time)
        !           161:                        goto nolease;
        !           162: 
        !           163:                if (lease -> uid_len) {
        !           164:                        oc = lookup_option (&dhcp_universe, packet -> options,
        !           165:                                            DHO_DHCP_CLIENT_IDENTIFIER);
        !           166:                        if (!oc)
        !           167:                                goto nolease;
        !           168: 
        !           169:                        memset (&data, 0, sizeof data);
        !           170:                        if (!evaluate_option_cache (&data,
        !           171:                                                    packet, (struct lease *)0,
        !           172:                                                    (struct client_state *)0,
        !           173:                                                    packet -> options,
        !           174:                                                    (struct option_state *)0,
        !           175:                                                    &global_scope, oc, MDL))
        !           176:                                goto nolease;
        !           177:                        if (lease -> uid_len != data.len ||
        !           178:                            memcmp (lease -> uid, data.data, data.len)) {
        !           179:                                data_string_forget (&data, MDL);
        !           180:                                goto nolease;
        !           181:                        }
        !           182:                        data_string_forget (&data, MDL);
        !           183:                } else
        !           184:                        if ((lease -> hardware_addr.hbuf [0] !=
        !           185:                             packet -> raw -> htype) ||
        !           186:                            (lease -> hardware_addr.hlen - 1 !=
        !           187:                             packet -> raw -> hlen) ||
        !           188:                            memcmp (&lease -> hardware_addr.hbuf [1],
        !           189:                                    packet -> raw -> chaddr,
        !           190:                                    packet -> raw -> hlen))
        !           191:                                goto nolease;
        !           192: 
        !           193:                /* Okay, so we found a lease that matches the client. */
        !           194:                option_chain_head_reference ((struct option_chain_head **)
        !           195:                                             &(packet -> options -> universes
        !           196:                                               [agent_universe.index]),
        !           197:                                             lease -> agent_options, MDL);
        !           198: 
        !           199:                if (packet->options->universe_count <= agent_universe.index)
        !           200:                        packet->options->universe_count =
        !           201:                                                agent_universe.index + 1;
        !           202: 
        !           203:                packet->agent_options_stashed = ISC_TRUE;
        !           204:        }
        !           205:       nolease:
        !           206: 
        !           207:        /* If a client null terminates options it sends, it probably
        !           208:         * expects the server to reciprocate.
        !           209:         */
        !           210:        if ((oc = lookup_option (&dhcp_universe, packet -> options,
        !           211:                                 DHO_HOST_NAME))) {
        !           212:                if (!oc -> expression)
        !           213:                        ms_nulltp = oc->flags & OPTION_HAD_NULLS;
        !           214:        }
        !           215: 
        !           216:        /* Classify the client. */
        !           217:        classify_client (packet);
        !           218: 
        !           219:        switch (packet -> packet_type) {
        !           220:              case DHCPDISCOVER:
        !           221:                dhcpdiscover (packet, ms_nulltp);
        !           222:                break;
        !           223: 
        !           224:              case DHCPREQUEST:
        !           225:                dhcprequest (packet, ms_nulltp, lease);
        !           226:                break;
        !           227: 
        !           228:              case DHCPRELEASE:
        !           229:                dhcprelease (packet, ms_nulltp);
        !           230:                break;
        !           231: 
        !           232:              case DHCPDECLINE:
        !           233:                dhcpdecline (packet, ms_nulltp);
        !           234:                break;
        !           235: 
        !           236:              case DHCPINFORM:
        !           237:                dhcpinform (packet, ms_nulltp);
        !           238:                break;
        !           239: 
        !           240:              case DHCPLEASEQUERY:
        !           241:                dhcpleasequery(packet, ms_nulltp);
        !           242:                break;
        !           243: 
        !           244:              case DHCPACK:
        !           245:              case DHCPOFFER:
        !           246:              case DHCPNAK:
        !           247:              case DHCPLEASEUNASSIGNED:
        !           248:              case DHCPLEASEUNKNOWN:
        !           249:              case DHCPLEASEACTIVE:
        !           250:                break;
        !           251: 
        !           252:              default:
        !           253:                errmsg = "unknown packet type";
        !           254:                goto bad_packet;
        !           255:        }
        !           256:       out:
        !           257:        if (lease)
        !           258:                lease_dereference (&lease, MDL);
        !           259: }
        !           260: 
        !           261: void dhcpdiscover (packet, ms_nulltp)
        !           262:        struct packet *packet;
        !           263:        int ms_nulltp;
        !           264: {
        !           265:        struct lease *lease = (struct lease *)0;
        !           266:        char msgbuf [1024]; /* XXX */
        !           267:        TIME when;
        !           268:        const char *s;
        !           269:        int peer_has_leases = 0;
        !           270: #if defined (FAILOVER_PROTOCOL)
        !           271:        dhcp_failover_state_t *peer;
        !           272: #endif
        !           273: 
        !           274:        find_lease (&lease, packet, packet -> shared_network,
        !           275:                    0, &peer_has_leases, (struct lease *)0, MDL);
        !           276: 
        !           277:        if (lease && lease -> client_hostname) {
        !           278:                if ((strlen (lease -> client_hostname) <= 64) &&
        !           279:                    db_printable((unsigned char *)lease->client_hostname))
        !           280:                        s = lease -> client_hostname;
        !           281:                else
        !           282:                        s = "Hostname Unsuitable for Printing";
        !           283:        } else
        !           284:                s = (char *)0;
        !           285: 
        !           286:        /* %Audit% This is log output. %2004.06.17,Safe%
        !           287:         * If we truncate we hope the user can get a hint from the log.
        !           288:         */
        !           289:        snprintf (msgbuf, sizeof msgbuf, "DHCPDISCOVER from %s %s%s%svia %s",
        !           290:                 (packet -> raw -> htype
        !           291:                  ? print_hw_addr (packet -> raw -> htype,
        !           292:                                   packet -> raw -> hlen,
        !           293:                                   packet -> raw -> chaddr)
        !           294:                  : (lease
        !           295:                     ? print_hex_1(lease->uid_len, lease->uid, 60)
        !           296:                     : "<no identifier>")),
        !           297:                  s ? "(" : "", s ? s : "", s ? ") " : "",
        !           298:                  packet -> raw -> giaddr.s_addr
        !           299:                  ? inet_ntoa (packet -> raw -> giaddr)
        !           300:                  : packet -> interface -> name);
        !           301: 
        !           302:        /* Sourceless packets don't make sense here. */
        !           303:        if (!packet -> shared_network) {
        !           304:                log_info ("Packet from unknown subnet: %s",
        !           305:                      inet_ntoa (packet -> raw -> giaddr));
        !           306:                goto out;
        !           307:        }
        !           308: 
        !           309: #if defined (FAILOVER_PROTOCOL)
        !           310:        if (lease && lease -> pool && lease -> pool -> failover_peer) {
        !           311:                peer = lease -> pool -> failover_peer;
        !           312: 
        !           313:                /* If the lease is ours to allocate, then allocate it.
        !           314:                 * If the lease is active, it belongs to the client.  This
        !           315:                 * is the right lease, if we are to offer one.  We decide
        !           316:                 * whether or not to offer later on.
        !           317:                 */
        !           318:                if (lease->binding_state == FTS_ACTIVE ||
        !           319:                    lease_mine_to_reallocate(lease)) {
        !           320:                        ; /* This space intentionally left blank. */
        !           321: 
        !           322:                /* Otherwise, we can't let the client have this lease. */
        !           323:                } else {
        !           324: #if defined (DEBUG_FIND_LEASE)
        !           325:                    log_debug ("discarding %s - %s",
        !           326:                               piaddr (lease -> ip_addr),
        !           327:                               binding_state_print (lease -> binding_state));
        !           328: #endif
        !           329:                    lease_dereference (&lease, MDL);
        !           330:                }
        !           331:        }
        !           332: #endif
        !           333: 
        !           334:        /* If we didn't find a lease, try to allocate one... */
        !           335:        if (!lease) {
        !           336:                if (!allocate_lease (&lease, packet,
        !           337:                                     packet -> shared_network -> pools, 
        !           338:                                     &peer_has_leases)) {
        !           339:                        if (peer_has_leases)
        !           340:                                log_error ("%s: peer holds all free leases",
        !           341:                                           msgbuf);
        !           342:                        else
        !           343:                                log_error ("%s: network %s: no free leases",
        !           344:                                           msgbuf,
        !           345:                                           packet -> shared_network -> name);
        !           346:                        return;
        !           347:                }
        !           348:        }
        !           349: 
        !           350: #if defined (FAILOVER_PROTOCOL)
        !           351:        if (lease && lease -> pool && lease -> pool -> failover_peer) {
        !           352:                peer = lease -> pool -> failover_peer;
        !           353:                if (peer -> service_state == not_responding ||
        !           354:                    peer -> service_state == service_startup) {
        !           355:                        log_info ("%s: not responding%s",
        !           356:                                  msgbuf, peer -> nrr);
        !           357:                        goto out;
        !           358:                }
        !           359:        } else
        !           360:                peer = (dhcp_failover_state_t *)0;
        !           361: 
        !           362:        /* Do load balancing if configured. */
        !           363:        if (peer && (peer -> service_state == cooperating) &&
        !           364:            !load_balance_mine (packet, peer)) {
        !           365:                if (peer_has_leases) {
        !           366:                        log_debug ("%s: load balance to peer %s",
        !           367:                                   msgbuf, peer -> name);
        !           368:                        goto out;
        !           369:                } else {
        !           370:                        log_debug ("%s: cancel load balance to peer %s - %s",
        !           371:                                   msgbuf, peer -> name, "no free leases");
        !           372:                }
        !           373:        }
        !           374: #endif
        !           375: 
        !           376:        /* If it's an expired lease, get rid of any bindings. */
        !           377:        if (lease -> ends < cur_time && lease -> scope)
        !           378:                binding_scope_dereference (&lease -> scope, MDL);
        !           379: 
        !           380:        /* Set the lease to really expire in 2 minutes, unless it has
        !           381:           not yet expired, in which case leave its expiry time alone. */
        !           382:        when = cur_time + 120;
        !           383:        if (when < lease -> ends)
        !           384:                when = lease -> ends;
        !           385: 
        !           386:        ack_lease (packet, lease, DHCPOFFER, when, msgbuf, ms_nulltp,
        !           387:                   (struct host_decl *)0);
        !           388:       out:
        !           389:        if (lease)
        !           390:                lease_dereference (&lease, MDL);
        !           391: }
        !           392: 
        !           393: void dhcprequest (packet, ms_nulltp, ip_lease)
        !           394:        struct packet *packet;
        !           395:        int ms_nulltp;
        !           396:        struct lease *ip_lease;
        !           397: {
        !           398:        struct lease *lease;
        !           399:        struct iaddr cip;
        !           400:        struct iaddr sip;
        !           401:        struct subnet *subnet;
        !           402:        int ours = 0;
        !           403:        struct option_cache *oc;
        !           404:        struct data_string data;
        !           405:        char msgbuf [1024]; /* XXX */
        !           406:        const char *s;
        !           407:        char smbuf [19];
        !           408: #if defined (FAILOVER_PROTOCOL)
        !           409:        dhcp_failover_state_t *peer;
        !           410: #endif
        !           411:        int have_server_identifier = 0;
        !           412:        int have_requested_addr = 0;
        !           413: 
        !           414:        oc = lookup_option (&dhcp_universe, packet -> options,
        !           415:                            DHO_DHCP_REQUESTED_ADDRESS);
        !           416:        memset (&data, 0, sizeof data);
        !           417:        if (oc &&
        !           418:            evaluate_option_cache (&data, packet, (struct lease *)0,
        !           419:                                   (struct client_state *)0,
        !           420:                                   packet -> options, (struct option_state *)0,
        !           421:                                   &global_scope, oc, MDL)) {
        !           422:                cip.len = 4;
        !           423:                memcpy (cip.iabuf, data.data, 4);
        !           424:                data_string_forget (&data, MDL);
        !           425:                have_requested_addr = 1;
        !           426:        } else {
        !           427:                oc = (struct option_cache *)0;
        !           428:                cip.len = 4;
        !           429:                memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
        !           430:        }
        !           431: 
        !           432:        /* Find the lease that matches the address requested by the
        !           433:           client. */
        !           434: 
        !           435:        subnet = (struct subnet *)0;
        !           436:        lease = (struct lease *)0;
        !           437:        if (find_subnet (&subnet, cip, MDL))
        !           438:                find_lease (&lease, packet,
        !           439:                            subnet -> shared_network, &ours, 0, ip_lease, MDL);
        !           440: 
        !           441:        if (lease && lease -> client_hostname) {
        !           442:                if ((strlen (lease -> client_hostname) <= 64) &&
        !           443:                    db_printable((unsigned char *)lease->client_hostname))
        !           444:                        s = lease -> client_hostname;
        !           445:                else
        !           446:                        s = "Hostname Unsuitable for Printing";
        !           447:        } else
        !           448:                s = (char *)0;
        !           449: 
        !           450:        oc = lookup_option (&dhcp_universe, packet -> options,
        !           451:                            DHO_DHCP_SERVER_IDENTIFIER);
        !           452:        memset (&data, 0, sizeof data);
        !           453:        if (oc &&
        !           454:            evaluate_option_cache (&data, packet, (struct lease *)0,
        !           455:                                   (struct client_state *)0,
        !           456:                                   packet -> options, (struct option_state *)0,
        !           457:                                   &global_scope, oc, MDL)) {
        !           458:                sip.len = 4;
        !           459:                memcpy (sip.iabuf, data.data, 4);
        !           460:                data_string_forget (&data, MDL);
        !           461:                /* piaddr() should not return more than a 15 byte string.
        !           462:                 * safe.
        !           463:                 */
        !           464:                sprintf (smbuf, " (%s)", piaddr (sip));
        !           465:                have_server_identifier = 1;
        !           466:        } else
        !           467:                smbuf [0] = 0;
        !           468: 
        !           469:        /* %Audit% This is log output. %2004.06.17,Safe%
        !           470:         * If we truncate we hope the user can get a hint from the log.
        !           471:         */
        !           472:        snprintf (msgbuf, sizeof msgbuf,
        !           473:                 "DHCPREQUEST for %s%s from %s %s%s%svia %s",
        !           474:                 piaddr (cip), smbuf,
        !           475:                 (packet -> raw -> htype
        !           476:                  ? print_hw_addr (packet -> raw -> htype,
        !           477:                                   packet -> raw -> hlen,
        !           478:                                   packet -> raw -> chaddr)
        !           479:                  : (lease
        !           480:                     ? print_hex_1(lease->uid_len, lease->uid, 60)
        !           481:                     : "<no identifier>")),
        !           482:                 s ? "(" : "", s ? s : "", s ? ") " : "",
        !           483:                  packet -> raw -> giaddr.s_addr
        !           484:                  ? inet_ntoa (packet -> raw -> giaddr)
        !           485:                  : packet -> interface -> name);
        !           486: 
        !           487: #if defined (FAILOVER_PROTOCOL)
        !           488:        if (lease && lease -> pool && lease -> pool -> failover_peer) {
        !           489:                peer = lease -> pool -> failover_peer;
        !           490:                if (peer -> service_state == not_responding ||
        !           491:                    peer -> service_state == service_startup) {
        !           492:                        log_info ("%s: not responding%s",
        !           493:                                  msgbuf, peer -> nrr);
        !           494:                        goto out;
        !           495:                }
        !           496: 
        !           497:                /* "load balance to peer" - is not done at all for request.
        !           498:                 *
        !           499:                 * If it's RENEWING, we are the only server to hear it, so
        !           500:                 * we have to serve it.   If it's REBINDING, it's out of
        !           501:                 * communication with the other server, so there's no point
        !           502:                 * in waiting to serve it.    However, if the lease we're
        !           503:                 * offering is not a free lease, then we may be the only
        !           504:                 * server that can offer it, so we can't load balance if
        !           505:                 * the lease isn't in the free or backup state.  If it is
        !           506:                 * in the free or backup state, then that state is what
        !           507:                 * mandates one server or the other should perform the
        !           508:                 * allocation, not the LBA...we know the peer cannot
        !           509:                 * allocate a request for an address in our free state.
        !           510:                 *
        !           511:                 * So our only compass is lease_mine_to_reallocate().  This
        !           512:                 * effects both load balancing, and a sanity-check that we
        !           513:                 * are not going to try to allocate a lease that isn't ours.
        !           514:                 */
        !           515:                if ((lease -> binding_state == FTS_FREE ||
        !           516:                     lease -> binding_state == FTS_BACKUP) &&
        !           517:                    !lease_mine_to_reallocate (lease)) {
        !           518:                        log_debug ("%s: lease owned by peer", msgbuf);
        !           519:                        goto out;
        !           520:                }
        !           521: 
        !           522:                /* If the lease is in a transitional state, we can't
        !           523:                   renew it. */
        !           524:                if ((lease -> binding_state == FTS_RELEASED ||
        !           525:                     lease -> binding_state == FTS_EXPIRED) &&
        !           526:                    !lease_mine_to_reallocate (lease)) {
        !           527:                        log_debug ("%s: lease in transition state %s", msgbuf,
        !           528:                                   lease -> binding_state == FTS_RELEASED
        !           529:                                   ? "released" : "expired");
        !           530:                        goto out;
        !           531:                }
        !           532: 
        !           533:                /* It's actually very unlikely that we'll ever get here,
        !           534:                   but if we do, tell the client to stop using the lease,
        !           535:                   because the administrator reset it. */
        !           536:                if (lease -> binding_state == FTS_RESET &&
        !           537:                    !lease_mine_to_reallocate (lease)) {
        !           538:                        log_debug ("%s: lease reset by administrator", msgbuf);
        !           539:                        nak_lease (packet, &cip);
        !           540:                        goto out;
        !           541:                }
        !           542: 
        !           543:                /* At this point it's possible that we will get a broadcast
        !           544:                   DHCPREQUEST for a lease that we didn't offer, because
        !           545:                   both we and the peer are in a position to offer it.
        !           546:                   In that case, we probably shouldn't answer.   In order
        !           547:                   to not answer, we would have to compare the server
        !           548:                   identifier sent by the client with the list of possible
        !           549:                   server identifiers we can send, and if the client's
        !           550:                   identifier isn't on the list, drop the DHCPREQUEST.
        !           551:                   We aren't currently doing that for two reasons - first,
        !           552:                   it's not clear that all clients do the right thing
        !           553:                   with respect to sending the client identifier, which
        !           554:                   could mean that we might simply not respond to a client
        !           555:                   that is depending on us to respond.   Secondly, we allow
        !           556:                   the user to specify the server identifier to send, and
        !           557:                   we don't enforce that the server identifier should be
        !           558:                   one of our IP addresses.   This is probably not a big
        !           559:                   deal, but it's theoretically an issue.
        !           560: 
        !           561:                   The reason we care about this is that if both servers
        !           562:                   send a DHCPACK to the DHCPREQUEST, they are then going
        !           563:                   to send dueling BNDUPD messages, which could cause
        !           564:                   trouble.   I think it causes no harm, but it seems
        !           565:                   wrong. */
        !           566:        } else
        !           567:                peer = (dhcp_failover_state_t *)0;
        !           568: #endif
        !           569: 
        !           570:        /* If a client on a given network REQUESTs a lease on an
        !           571:           address on a different network, NAK it.  If the Requested
        !           572:           Address option was used, the protocol says that it must
        !           573:           have been broadcast, so we can trust the source network
        !           574:           information.
        !           575: 
        !           576:           If ciaddr was specified and Requested Address was not, then
        !           577:           we really only know for sure what network a packet came from
        !           578:           if it came through a BOOTP gateway - if it came through an
        !           579:           IP router, we'll just have to assume that it's cool.
        !           580: 
        !           581:           If we don't think we know where the packet came from, it
        !           582:           came through a gateway from an unknown network, so it's not
        !           583:           from a RENEWING client.  If we recognize the network it
        !           584:           *thinks* it's on, we can NAK it even though we don't
        !           585:           recognize the network it's *actually* on; otherwise we just
        !           586:           have to ignore it.
        !           587: 
        !           588:           We don't currently try to take advantage of access to the
        !           589:           raw packet, because it's not available on all platforms.
        !           590:           So a packet that was unicast to us through a router from a
        !           591:           RENEWING client is going to look exactly like a packet that
        !           592:           was broadcast to us from an INIT-REBOOT client.
        !           593: 
        !           594:           Since we can't tell the difference between these two kinds
        !           595:           of packets, if the packet appears to have come in off the
        !           596:           local wire, we have to treat it as if it's a RENEWING
        !           597:           client.  This means that we can't NAK a RENEWING client on
        !           598:           the local wire that has a bogus address.  The good news is
        !           599:           that we won't ACK it either, so it should revert to INIT
        !           600:           state and send us a DHCPDISCOVER, which we *can* work with.
        !           601: 
        !           602:           Because we can't detect that a RENEWING client is on the
        !           603:           wrong wire, it's going to sit there trying to renew until
        !           604:           it gets to the REBIND state, when we *can* NAK it because
        !           605:           the packet will get to us through a BOOTP gateway.  We
        !           606:           shouldn't actually see DHCPREQUEST packets from RENEWING
        !           607:           clients on the wrong wire anyway, since their idea of their
        !           608:           local router will be wrong.  In any case, the protocol
        !           609:           doesn't really allow us to NAK a DHCPREQUEST from a
        !           610:           RENEWING client, so we can punt on this issue. */
        !           611: 
        !           612:        if (!packet -> shared_network ||
        !           613:            (packet -> raw -> ciaddr.s_addr &&
        !           614:             packet -> raw -> giaddr.s_addr) ||
        !           615:            (have_requested_addr && !packet -> raw -> ciaddr.s_addr)) {
        !           616:                
        !           617:                /* If we don't know where it came from but we do know
        !           618:                   where it claims to have come from, it didn't come
        !           619:                   from there. */
        !           620:                if (!packet -> shared_network) {
        !           621:                        if (subnet && subnet -> group -> authoritative) {
        !           622:                                log_info ("%s: wrong network.", msgbuf);
        !           623:                                nak_lease (packet, &cip);
        !           624:                                goto out;
        !           625:                        }
        !           626:                        /* Otherwise, ignore it. */
        !           627:                        log_info ("%s: ignored (%s).", msgbuf,
        !           628:                                  (subnet
        !           629:                                   ? "not authoritative" : "unknown subnet"));
        !           630:                        goto out;
        !           631:                }
        !           632: 
        !           633:                /* If we do know where it came from and it asked for an
        !           634:                   address that is not on that shared network, nak it. */
        !           635:                if (subnet)
        !           636:                        subnet_dereference (&subnet, MDL);
        !           637:                if (!find_grouped_subnet (&subnet, packet -> shared_network,
        !           638:                                          cip, MDL)) {
        !           639:                        if (packet -> shared_network -> group -> authoritative)
        !           640:                        {
        !           641:                                log_info ("%s: wrong network.", msgbuf);
        !           642:                                nak_lease (packet, &cip);
        !           643:                                goto out;
        !           644:                        }
        !           645:                        log_info ("%s: ignored (not authoritative).", msgbuf);
        !           646:                        return;
        !           647:                }
        !           648:        }
        !           649: 
        !           650:        /* If the address the client asked for is ours, but it wasn't
        !           651:           available for the client, NAK it. */
        !           652:        if (!lease && ours) {
        !           653:                log_info ("%s: lease %s unavailable.", msgbuf, piaddr (cip));
        !           654:                nak_lease (packet, &cip);
        !           655:                goto out;
        !           656:        }
        !           657: 
        !           658:        /* Otherwise, send the lease to the client if we found one. */
        !           659:        if (lease) {
        !           660:                ack_lease (packet, lease, DHCPACK, 0, msgbuf, ms_nulltp,
        !           661:                           (struct host_decl *)0);
        !           662:        } else
        !           663:                log_info ("%s: unknown lease %s.", msgbuf, piaddr (cip));
        !           664: 
        !           665:       out:
        !           666:        if (subnet)
        !           667:                subnet_dereference (&subnet, MDL);
        !           668:        if (lease)
        !           669:                lease_dereference (&lease, MDL);
        !           670:        return;
        !           671: }
        !           672: 
        !           673: void dhcprelease (packet, ms_nulltp)
        !           674:        struct packet *packet;
        !           675:        int ms_nulltp;
        !           676: {
        !           677:        struct lease *lease = (struct lease *)0, *next = (struct lease *)0;
        !           678:        struct iaddr cip;
        !           679:        struct option_cache *oc;
        !           680:        struct data_string data;
        !           681:        const char *s;
        !           682:        char msgbuf [1024], cstr[16]; /* XXX */
        !           683: 
        !           684: 
        !           685:        /* DHCPRELEASE must not specify address in requested-address
        !           686:           option, but old protocol specs weren't explicit about this,
        !           687:           so let it go. */
        !           688:        if ((oc = lookup_option (&dhcp_universe, packet -> options,
        !           689:                                 DHO_DHCP_REQUESTED_ADDRESS))) {
        !           690:                log_info ("DHCPRELEASE from %s specified requested-address.",
        !           691:                      print_hw_addr (packet -> raw -> htype,
        !           692:                                     packet -> raw -> hlen,
        !           693:                                     packet -> raw -> chaddr));
        !           694:        }
        !           695: 
        !           696:        oc = lookup_option (&dhcp_universe, packet -> options,
        !           697:                            DHO_DHCP_CLIENT_IDENTIFIER);
        !           698:        memset (&data, 0, sizeof data);
        !           699:        if (oc &&
        !           700:            evaluate_option_cache (&data, packet, (struct lease *)0,
        !           701:                                   (struct client_state *)0,
        !           702:                                   packet -> options, (struct option_state *)0,
        !           703:                                   &global_scope, oc, MDL)) {
        !           704:                find_lease_by_uid (&lease, data.data, data.len, MDL);
        !           705:                data_string_forget (&data, MDL);
        !           706: 
        !           707:                /* See if we can find a lease that matches the IP address
        !           708:                   the client is claiming. */
        !           709:                while (lease) {
        !           710:                        if (lease -> n_uid)
        !           711:                                lease_reference (&next, lease -> n_uid, MDL);
        !           712:                        if (!memcmp (&packet -> raw -> ciaddr,
        !           713:                                     lease -> ip_addr.iabuf, 4)) {
        !           714:                                break;
        !           715:                        }
        !           716:                        lease_dereference (&lease, MDL);
        !           717:                        if (next) {
        !           718:                                lease_reference (&lease, next, MDL);
        !           719:                                lease_dereference (&next, MDL);
        !           720:                        }
        !           721:                }
        !           722:                if (next)
        !           723:                        lease_dereference (&next, MDL);
        !           724:        }
        !           725: 
        !           726:        /* The client is supposed to pass a valid client-identifier,
        !           727:           but the spec on this has changed historically, so try the
        !           728:           IP address in ciaddr if the client-identifier fails. */
        !           729:        if (!lease) {
        !           730:                cip.len = 4;
        !           731:                memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
        !           732:                find_lease_by_ip_addr (&lease, cip, MDL);
        !           733:        }
        !           734: 
        !           735: 
        !           736:        /* If the hardware address doesn't match, don't do the release. */
        !           737:        if (lease &&
        !           738:            (lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
        !           739:             lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
        !           740:             memcmp (&lease -> hardware_addr.hbuf [1],
        !           741:                     packet -> raw -> chaddr, packet -> raw -> hlen)))
        !           742:                lease_dereference (&lease, MDL);
        !           743: 
        !           744:        if (lease && lease -> client_hostname) {
        !           745:                if ((strlen (lease -> client_hostname) <= 64) &&
        !           746:                    db_printable((unsigned char *)lease->client_hostname))
        !           747:                        s = lease -> client_hostname;
        !           748:                else
        !           749:                        s = "Hostname Unsuitable for Printing";
        !           750:        } else
        !           751:                s = (char *)0;
        !           752: 
        !           753:        /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe%
        !           754:         * We copy this out to stack because we actually want to log two
        !           755:         * inet_ntoa()'s in this message.
        !           756:         */
        !           757:        strncpy(cstr, inet_ntoa (packet -> raw -> ciaddr), 15);
        !           758:        cstr[15] = '\0';
        !           759: 
        !           760:        /* %Audit% This is log output. %2004.06.17,Safe%
        !           761:         * If we truncate we hope the user can get a hint from the log.
        !           762:         */
        !           763:        snprintf (msgbuf, sizeof msgbuf,
        !           764:                 "DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
        !           765:                 cstr,
        !           766:                 (packet -> raw -> htype
        !           767:                  ? print_hw_addr (packet -> raw -> htype,
        !           768:                                   packet -> raw -> hlen,
        !           769:                                   packet -> raw -> chaddr)
        !           770:                  : (lease
        !           771:                     ? print_hex_1(lease->uid_len, lease->uid, 60)
        !           772:                     : "<no identifier>")),
        !           773:                 s ? "(" : "", s ? s : "", s ? ") " : "",
        !           774:                 packet -> raw -> giaddr.s_addr
        !           775:                 ? inet_ntoa (packet -> raw -> giaddr)
        !           776:                 : packet -> interface -> name,
        !           777:                 lease ? "" : "not ");
        !           778: 
        !           779: #if defined (FAILOVER_PROTOCOL)
        !           780:        if (lease && lease -> pool && lease -> pool -> failover_peer) {
        !           781:                dhcp_failover_state_t *peer = lease -> pool -> failover_peer;
        !           782:                if (peer -> service_state == not_responding ||
        !           783:                    peer -> service_state == service_startup) {
        !           784:                        log_info ("%s: ignored%s",
        !           785:                                  peer -> name, peer -> nrr);
        !           786:                        goto out;
        !           787:                }
        !           788: 
        !           789:                /* DHCPRELEASE messages are unicast, so if the client
        !           790:                   sent the DHCPRELEASE to us, it's not going to send it
        !           791:                   to the peer.   Not sure why this would happen, and
        !           792:                   if it does happen I think we still have to change the
        !           793:                   lease state, so that's what we're doing.
        !           794:                   XXX See what it says in the draft about this. */
        !           795:        }
        !           796: #endif
        !           797: 
        !           798:        /* If we found a lease, release it. */
        !           799:        if (lease && lease -> ends > cur_time) {
        !           800:                release_lease (lease, packet);
        !           801:        } 
        !           802:        log_info ("%s", msgbuf);
        !           803: #if defined(FAILOVER_PROTOCOL)
        !           804:       out:
        !           805: #endif
        !           806:        if (lease)
        !           807:                lease_dereference (&lease, MDL);
        !           808: }
        !           809: 
        !           810: void dhcpdecline (packet, ms_nulltp)
        !           811:        struct packet *packet;
        !           812:        int ms_nulltp;
        !           813: {
        !           814:        struct lease *lease = (struct lease *)0;
        !           815:        struct option_state *options = (struct option_state *)0;
        !           816:        int ignorep = 0;
        !           817:        int i;
        !           818:        const char *status;
        !           819:        const char *s;
        !           820:        char msgbuf [1024]; /* XXX */
        !           821:        struct iaddr cip;
        !           822:        struct option_cache *oc;
        !           823:        struct data_string data;
        !           824: 
        !           825:        /* DHCPDECLINE must specify address. */
        !           826:        if (!(oc = lookup_option (&dhcp_universe, packet -> options,
        !           827:                                  DHO_DHCP_REQUESTED_ADDRESS)))
        !           828:                return;
        !           829:        memset (&data, 0, sizeof data);
        !           830:        if (!evaluate_option_cache (&data, packet, (struct lease *)0,
        !           831:                                    (struct client_state *)0,
        !           832:                                    packet -> options,
        !           833:                                    (struct option_state *)0,
        !           834:                                    &global_scope, oc, MDL))
        !           835:                return;
        !           836: 
        !           837:        cip.len = 4;
        !           838:        memcpy (cip.iabuf, data.data, 4);
        !           839:        data_string_forget (&data, MDL);
        !           840:        find_lease_by_ip_addr (&lease, cip, MDL);
        !           841: 
        !           842:        if (lease && lease -> client_hostname) {
        !           843:                if ((strlen (lease -> client_hostname) <= 64) &&
        !           844:                    db_printable((unsigned char *)lease->client_hostname))
        !           845:                        s = lease -> client_hostname;
        !           846:                else
        !           847:                        s = "Hostname Unsuitable for Printing";
        !           848:        } else
        !           849:                s = (char *)0;
        !           850: 
        !           851:        /* %Audit% This is log output. %2004.06.17,Safe%
        !           852:         * If we truncate we hope the user can get a hint from the log.
        !           853:         */
        !           854:        snprintf (msgbuf, sizeof msgbuf,
        !           855:                 "DHCPDECLINE of %s from %s %s%s%svia %s",
        !           856:                 piaddr (cip),
        !           857:                 (packet -> raw -> htype
        !           858:                  ? print_hw_addr (packet -> raw -> htype,
        !           859:                                   packet -> raw -> hlen,
        !           860:                                   packet -> raw -> chaddr)
        !           861:                  : (lease
        !           862:                     ? print_hex_1(lease->uid_len, lease->uid, 60)
        !           863:                     : "<no identifier>")),
        !           864:                 s ? "(" : "", s ? s : "", s ? ") " : "",
        !           865:                 packet -> raw -> giaddr.s_addr
        !           866:                 ? inet_ntoa (packet -> raw -> giaddr)
        !           867:                 : packet -> interface -> name);
        !           868: 
        !           869:        option_state_allocate (&options, MDL);
        !           870: 
        !           871:        /* Execute statements in scope starting with the subnet scope. */
        !           872:        if (lease)
        !           873:                execute_statements_in_scope ((struct binding_value **)0,
        !           874:                                             packet, (struct lease *)0,
        !           875:                                             (struct client_state *)0,
        !           876:                                             packet -> options, options,
        !           877:                                             &global_scope,
        !           878:                                             lease -> subnet -> group,
        !           879:                                             (struct group *)0);
        !           880: 
        !           881:        /* Execute statements in the class scopes. */
        !           882:        for (i = packet -> class_count; i > 0; i--) {
        !           883:                execute_statements_in_scope
        !           884:                        ((struct binding_value **)0, packet, (struct lease *)0,
        !           885:                         (struct client_state *)0, packet -> options, options,
        !           886:                         &global_scope, packet -> classes [i - 1] -> group,
        !           887:                         lease ? lease -> subnet -> group : (struct group *)0);
        !           888:        }
        !           889: 
        !           890:        /* Drop the request if dhcpdeclines are being ignored. */
        !           891:        oc = lookup_option (&server_universe, options, SV_DECLINES);
        !           892:        if (!oc ||
        !           893:            evaluate_boolean_option_cache (&ignorep, packet, lease,
        !           894:                                           (struct client_state *)0,
        !           895:                                           packet -> options, options,
        !           896:                                           &lease -> scope, oc, MDL)) {
        !           897:            /* If we found a lease, mark it as unusable and complain. */
        !           898:            if (lease) {
        !           899: #if defined (FAILOVER_PROTOCOL)
        !           900:                if (lease -> pool && lease -> pool -> failover_peer) {
        !           901:                    dhcp_failover_state_t *peer =
        !           902:                            lease -> pool -> failover_peer;
        !           903:                    if (peer -> service_state == not_responding ||
        !           904:                        peer -> service_state == service_startup) {
        !           905:                        if (!ignorep)
        !           906:                            log_info ("%s: ignored%s",
        !           907:                                      peer -> name, peer -> nrr);
        !           908:                        goto out;
        !           909:                    }
        !           910: 
        !           911:                    /* DHCPDECLINE messages are broadcast, so we can safely
        !           912:                       ignore the DHCPDECLINE if the peer has the lease.
        !           913:                       XXX Of course, at this point that information has been
        !           914:                       lost. */
        !           915:                }
        !           916: #endif
        !           917: 
        !           918:                abandon_lease (lease, "declined.");
        !           919:                status = "abandoned";
        !           920:            } else {
        !           921:                status = "not found";
        !           922:            }
        !           923:        } else
        !           924:            status = "ignored";
        !           925: 
        !           926:        if (!ignorep)
        !           927:                log_info ("%s: %s", msgbuf, status);
        !           928: 
        !           929: #if defined(FAILOVER_PROTOCOL)
        !           930:       out:
        !           931: #endif
        !           932:        if (options)
        !           933:                option_state_dereference (&options, MDL);
        !           934:        if (lease)
        !           935:                lease_dereference (&lease, MDL);
        !           936: }
        !           937: 
        !           938: void dhcpinform (packet, ms_nulltp)
        !           939:        struct packet *packet;
        !           940:        int ms_nulltp;
        !           941: {
        !           942:        char msgbuf [1024];
        !           943:        struct data_string d1, prl;
        !           944:        struct option_cache *oc;
        !           945:        struct option_state *options = (struct option_state *)0;
        !           946:        struct dhcp_packet raw;
        !           947:        struct packet outgoing;
        !           948:        unsigned char dhcpack = DHCPACK;
        !           949:        struct subnet *subnet = NULL;
        !           950:        struct iaddr cip, gip;
        !           951:        unsigned i;
        !           952:        int nulltp;
        !           953:        struct sockaddr_in to;
        !           954:        struct in_addr from;
        !           955:        isc_boolean_t zeroed_ciaddr;
        !           956: 
        !           957:        /* The client should set ciaddr to its IP address, but apparently
        !           958:           it's common for clients not to do this, so we'll use their IP
        !           959:           source address if they didn't set ciaddr. */
        !           960:        if (!packet -> raw -> ciaddr.s_addr) {
        !           961:                zeroed_ciaddr = ISC_TRUE;
        !           962:                cip.len = 4;
        !           963:                memcpy (cip.iabuf, &packet -> client_addr.iabuf, 4);
        !           964:        } else {
        !           965:                zeroed_ciaddr = ISC_FALSE;
        !           966:                cip.len = 4;
        !           967:                memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
        !           968:        }
        !           969: 
        !           970:        if (packet->raw->giaddr.s_addr) {
        !           971:                gip.len = 4;
        !           972:                memcpy(gip.iabuf, &packet->raw->giaddr, 4);
        !           973:        } else
        !           974:                gip.len = 0;
        !           975: 
        !           976:        /* %Audit% This is log output. %2004.06.17,Safe%
        !           977:         * If we truncate we hope the user can get a hint from the log.
        !           978:         */
        !           979:        snprintf (msgbuf, sizeof msgbuf, "DHCPINFORM from %s via %s",
        !           980:                 piaddr (cip), packet->raw->giaddr.s_addr ?
        !           981:                                inet_ntoa(packet->raw->giaddr) :
        !           982:                                packet -> interface -> name);
        !           983: 
        !           984:        /* If the IP source address is zero, don't respond. */
        !           985:        if (!memcmp (cip.iabuf, "\0\0\0", 4)) {
        !           986:                log_info ("%s: ignored (null source address).", msgbuf);
        !           987:                return;
        !           988:        }
        !           989: 
        !           990:        /* Find the subnet that the client is on. */
        !           991:        if (zeroed_ciaddr && (gip.len != 0)) {
        !           992:                /* XXX - do subnet selection relay agent suboption here */
        !           993:                find_subnet(&subnet, gip, MDL);
        !           994: 
        !           995:                if (subnet == NULL) {
        !           996:                        log_info("%s: unknown subnet for relay address %s",
        !           997:                                 msgbuf, piaddr(gip));
        !           998:                        return;
        !           999:                }
        !          1000:        } else {
        !          1001:                /* XXX - do subnet selection (not relay agent) option here */
        !          1002:                find_subnet(&subnet, cip, MDL);
        !          1003: 
        !          1004:                if (subnet == NULL) {
        !          1005:                        log_info("%s: unknown subnet for %s address %s",
        !          1006:                                 msgbuf, zeroed_ciaddr ? "source" : "client",
        !          1007:                                 piaddr(cip));
        !          1008:                        return;
        !          1009:                }
        !          1010:        }
        !          1011: 
        !          1012:        /* We don't respond to DHCPINFORM packets if we're not authoritative.
        !          1013:           It would be nice if a per-host value could override this, but
        !          1014:           there's overhead involved in checking this, so let's see how people
        !          1015:           react first. */
        !          1016:        if (subnet && !subnet -> group -> authoritative) {
        !          1017:                static int eso = 0;
        !          1018:                log_info ("%s: not authoritative for subnet %s",
        !          1019:                          msgbuf, piaddr (subnet -> net));
        !          1020:                if (!eso) {
        !          1021:                        log_info ("If this DHCP server is authoritative for%s",
        !          1022:                                  " that subnet,");
        !          1023:                        log_info ("please write an `authoritative;' directi%s",
        !          1024:                                  "ve either in the");
        !          1025:                        log_info ("subnet declaration or in some scope that%s",
        !          1026:                                  " encloses the");
        !          1027:                        log_info ("subnet declaration - for example, write %s",
        !          1028:                                  "it at the top");
        !          1029:                        log_info ("of the dhcpd.conf file.");
        !          1030:                }
        !          1031:                if (eso++ == 100)
        !          1032:                        eso = 0;
        !          1033:                subnet_dereference (&subnet, MDL);
        !          1034:                return;
        !          1035:        }
        !          1036: 
        !          1037:        option_state_allocate (&options, MDL);
        !          1038:        memset (&outgoing, 0, sizeof outgoing);
        !          1039:        memset (&raw, 0, sizeof raw);
        !          1040:        outgoing.raw = &raw;
        !          1041: 
        !          1042:        /* Execute statements in scope starting with the subnet scope. */
        !          1043:        if (subnet)
        !          1044:                execute_statements_in_scope ((struct binding_value **)0,
        !          1045:                                             packet, (struct lease *)0,
        !          1046:                                             (struct client_state *)0,
        !          1047:                                             packet -> options, options,
        !          1048:                                             &global_scope, subnet -> group,
        !          1049:                                             (struct group *)0);
        !          1050: 
        !          1051:        /* Execute statements in the class scopes. */
        !          1052:        for (i = packet -> class_count; i > 0; i--) {
        !          1053:                execute_statements_in_scope
        !          1054:                        ((struct binding_value **)0, packet, (struct lease *)0,
        !          1055:                         (struct client_state *)0, packet -> options, options,
        !          1056:                         &global_scope, packet -> classes [i - 1] -> group,
        !          1057:                         subnet ? subnet -> group : (struct group *)0);
        !          1058:        }
        !          1059: 
        !          1060:        /* Figure out the filename. */
        !          1061:        memset (&d1, 0, sizeof d1);
        !          1062:        oc = lookup_option (&server_universe, options, SV_FILENAME);
        !          1063:        if (oc &&
        !          1064:            evaluate_option_cache (&d1, packet, (struct lease *)0,
        !          1065:                                   (struct client_state *)0,
        !          1066:                                   packet -> options, (struct option_state *)0,
        !          1067:                                   &global_scope, oc, MDL)) {
        !          1068:                i = d1.len;
        !          1069:                if (i >= sizeof(raw.file)) {
        !          1070:                        log_info("file name longer than packet field "
        !          1071:                                 "truncated - field: %lu name: %d %.*s", 
        !          1072:                                 (unsigned long)sizeof(raw.file), i, i,
        !          1073:                                 d1.data);
        !          1074:                        i = sizeof(raw.file);
        !          1075:                } else
        !          1076:                        raw.file[i] = 0;
        !          1077:                memcpy (raw.file, d1.data, i);
        !          1078:                data_string_forget (&d1, MDL);
        !          1079:        }
        !          1080: 
        !          1081:        /* Choose a server name as above. */
        !          1082:        oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
        !          1083:        if (oc &&
        !          1084:            evaluate_option_cache (&d1, packet, (struct lease *)0,
        !          1085:                                   (struct client_state *)0,
        !          1086:                                   packet -> options, (struct option_state *)0,
        !          1087:                                   &global_scope, oc, MDL)) {
        !          1088:                i = d1.len;
        !          1089:                if (i >= sizeof(raw.sname)) {
        !          1090:                        log_info("server name longer than packet field "
        !          1091:                                 "truncated - field: %lu name: %d %.*s", 
        !          1092:                                 (unsigned long)sizeof(raw.sname), i, i,
        !          1093:                                 d1.data);
        !          1094:                        i = sizeof(raw.sname);
        !          1095:                } else
        !          1096:                        raw.sname[i] = 0;
        !          1097:                memcpy (raw.sname, d1.data, i);
        !          1098:                data_string_forget (&d1, MDL);
        !          1099:        }
        !          1100: 
        !          1101:        /* Set a flag if this client is a lame Microsoft client that NUL
        !          1102:           terminates string options and expects us to do likewise. */
        !          1103:        nulltp = 0;
        !          1104:        if ((oc = lookup_option (&dhcp_universe, packet -> options,
        !          1105:                                 DHO_HOST_NAME))) {
        !          1106:                if (!oc->expression)
        !          1107:                        nulltp = oc->flags & OPTION_HAD_NULLS;
        !          1108:        }
        !          1109: 
        !          1110:        /* Put in DHCP-specific options. */
        !          1111:        i = DHO_DHCP_MESSAGE_TYPE;
        !          1112:        oc = (struct option_cache *)0;
        !          1113:        if (option_cache_allocate (&oc, MDL)) {
        !          1114:                if (make_const_data (&oc -> expression,
        !          1115:                                     &dhcpack, 1, 0, 0, MDL)) {
        !          1116:                        option_code_hash_lookup(&oc->option,
        !          1117:                                                dhcp_universe.code_hash,
        !          1118:                                                &i, 0, MDL);
        !          1119:                        save_option (&dhcp_universe, options, oc);
        !          1120:                }
        !          1121:                option_cache_dereference (&oc, MDL);
        !          1122:        }
        !          1123: 
        !          1124:        get_server_source_address(&from, options, packet);
        !          1125: 
        !          1126:        /* Use the subnet mask from the subnet declaration if no other
        !          1127:           mask has been provided. */
        !          1128:        i = DHO_SUBNET_MASK;
        !          1129:        if (subnet && !lookup_option (&dhcp_universe, options, i)) {
        !          1130:                oc = (struct option_cache *)0;
        !          1131:                if (option_cache_allocate (&oc, MDL)) {
        !          1132:                        if (make_const_data (&oc -> expression,
        !          1133:                                             subnet -> netmask.iabuf,
        !          1134:                                             subnet -> netmask.len,
        !          1135:                                             0, 0, MDL)) {
        !          1136:                                option_code_hash_lookup(&oc->option,
        !          1137:                                                        dhcp_universe.code_hash,
        !          1138:                                                        &i, 0, MDL);
        !          1139:                                save_option (&dhcp_universe, options, oc);
        !          1140:                        }
        !          1141:                        option_cache_dereference (&oc, MDL);
        !          1142:                }
        !          1143:        }
        !          1144: 
        !          1145:        /* If a site option space has been specified, use that for
        !          1146:           site option codes. */
        !          1147:        i = SV_SITE_OPTION_SPACE;
        !          1148:        if ((oc = lookup_option (&server_universe, options, i)) &&
        !          1149:            evaluate_option_cache (&d1, packet, (struct lease *)0,
        !          1150:                                   (struct client_state *)0,
        !          1151:                                   packet -> options, options,
        !          1152:                                   &global_scope, oc, MDL)) {
        !          1153:                struct universe *u = (struct universe *)0;
        !          1154:                
        !          1155:                if (!universe_hash_lookup (&u, universe_hash,
        !          1156:                                           (const char *)d1.data, d1.len,
        !          1157:                                           MDL)) {
        !          1158:                        log_error ("unknown option space %s.", d1.data);
        !          1159:                        option_state_dereference (&options, MDL);
        !          1160:                        if (subnet)
        !          1161:                                subnet_dereference (&subnet, MDL);
        !          1162:                        return;
        !          1163:                }
        !          1164: 
        !          1165:                options -> site_universe = u -> index;
        !          1166:                options->site_code_min = find_min_site_code(u);
        !          1167:                data_string_forget (&d1, MDL);
        !          1168:        } else {
        !          1169:                options -> site_universe = dhcp_universe.index;
        !          1170:                options -> site_code_min = 0; /* Trust me, it works. */
        !          1171:        }
        !          1172: 
        !          1173:        memset (&prl, 0, sizeof prl);
        !          1174: 
        !          1175:        /* Use the parameter list from the scope if there is one. */
        !          1176:        oc = lookup_option (&dhcp_universe, options,
        !          1177:                            DHO_DHCP_PARAMETER_REQUEST_LIST);
        !          1178: 
        !          1179:        /* Otherwise, if the client has provided a list of options
        !          1180:           that it wishes returned, use it to prioritize.  Otherwise,
        !          1181:           prioritize based on the default priority list. */
        !          1182: 
        !          1183:        if (!oc)
        !          1184:                oc = lookup_option (&dhcp_universe, packet -> options,
        !          1185:                                    DHO_DHCP_PARAMETER_REQUEST_LIST);
        !          1186: 
        !          1187:        if (oc)
        !          1188:                evaluate_option_cache (&prl, packet, (struct lease *)0,
        !          1189:                                       (struct client_state *)0,
        !          1190:                                       packet -> options, options,
        !          1191:                                       &global_scope, oc, MDL);
        !          1192: 
        !          1193: #ifdef DEBUG_PACKET
        !          1194:        dump_packet (packet);
        !          1195:        dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
        !          1196: #endif
        !          1197: 
        !          1198:        log_info ("%s", msgbuf);
        !          1199: 
        !          1200:        /* Figure out the address of the boot file server. */
        !          1201:        if ((oc =
        !          1202:             lookup_option (&server_universe, options, SV_NEXT_SERVER))) {
        !          1203:                if (evaluate_option_cache (&d1, packet, (struct lease *)0,
        !          1204:                                           (struct client_state *)0,
        !          1205:                                           packet -> options, options,
        !          1206:                                           &global_scope, oc, MDL)) {
        !          1207:                        /* If there was more than one answer,
        !          1208:                           take the first. */
        !          1209:                        if (d1.len >= 4 && d1.data)
        !          1210:                                memcpy (&raw.siaddr, d1.data, 4);
        !          1211:                        data_string_forget (&d1, MDL);
        !          1212:                }
        !          1213:        }
        !          1214: 
        !          1215:        /*
        !          1216:         * Remove any time options, per section 3.4 RFC 2131
        !          1217:         */
        !          1218:        delete_option(&dhcp_universe, options, DHO_DHCP_LEASE_TIME);
        !          1219:        delete_option(&dhcp_universe, options, DHO_DHCP_RENEWAL_TIME);
        !          1220:        delete_option(&dhcp_universe, options, DHO_DHCP_REBINDING_TIME);
        !          1221: 
        !          1222:        /* Set up the option buffer... */
        !          1223:        outgoing.packet_length =
        !          1224:                cons_options (packet, outgoing.raw, (struct lease *)0,
        !          1225:                              (struct client_state *)0,
        !          1226:                              0, packet -> options, options, &global_scope,
        !          1227:                              0, nulltp, 0,
        !          1228:                              prl.len ? &prl : (struct data_string *)0,
        !          1229:                              (char *)0);
        !          1230:        option_state_dereference (&options, MDL);
        !          1231:        data_string_forget (&prl, MDL);
        !          1232: 
        !          1233:        /* Make sure that the packet is at least as big as a BOOTP packet. */
        !          1234:        if (outgoing.packet_length < BOOTP_MIN_LEN)
        !          1235:                outgoing.packet_length = BOOTP_MIN_LEN;
        !          1236: 
        !          1237:        raw.giaddr = packet -> raw -> giaddr;
        !          1238:        raw.ciaddr = packet -> raw -> ciaddr;
        !          1239:        memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
        !          1240:        raw.hlen = packet -> raw -> hlen;
        !          1241:        raw.htype = packet -> raw -> htype;
        !          1242: 
        !          1243:        raw.xid = packet -> raw -> xid;
        !          1244:        raw.secs = packet -> raw -> secs;
        !          1245:        raw.flags = packet -> raw -> flags;
        !          1246:        raw.hops = packet -> raw -> hops;
        !          1247:        raw.op = BOOTREPLY;
        !          1248: 
        !          1249: #ifdef DEBUG_PACKET
        !          1250:        dump_packet (&outgoing);
        !          1251:        dump_raw ((unsigned char *)&raw, outgoing.packet_length);
        !          1252: #endif
        !          1253: 
        !          1254:        /* Set up the common stuff... */
        !          1255:        to.sin_family = AF_INET;
        !          1256: #ifdef HAVE_SA_LEN
        !          1257:        to.sin_len = sizeof to;
        !          1258: #endif
        !          1259:        memset (to.sin_zero, 0, sizeof to.sin_zero);
        !          1260: 
        !          1261:        /* RFC2131 states the server SHOULD unciast to ciaddr.
        !          1262:         * There are two wrinkles - relays, and when ciaddr is zero.
        !          1263:         * There's actually no mention of relays at all in rfc2131 in
        !          1264:         * regard to DHCPINFORM, except to say we might get packets from
        !          1265:         * clients via them.  Note: relays unicast to clients to the
        !          1266:         * "yiaddr" address, which servers are forbidden to set when
        !          1267:         * answering an inform.
        !          1268:         *
        !          1269:         * The solution: If ciaddr is zero, and giaddr is set, go via the
        !          1270:         * relay with the broadcast flag set to help the relay (with no
        !          1271:         * yiaddr and very likely no chaddr, it will have no idea where to
        !          1272:         * send the packet).
        !          1273:         *
        !          1274:         * If the ciaddr is zero and giaddr is not set, go via the source
        !          1275:         * IP address (but you are permitted to barf on their shoes).
        !          1276:         *
        !          1277:         * If ciaddr is not zero, send the packet there always.
        !          1278:         */
        !          1279:        if (!raw.ciaddr.s_addr && gip.len) {
        !          1280:                memcpy(&to.sin_addr, gip.iabuf, 4);
        !          1281:                to.sin_port = local_port;
        !          1282:                raw.flags |= htons(BOOTP_BROADCAST);
        !          1283:        } else {
        !          1284:                gip.len = 0;
        !          1285:                memcpy(&to.sin_addr, cip.iabuf, 4);
        !          1286:                to.sin_port = remote_port;
        !          1287:        }
        !          1288: 
        !          1289:        /* Report what we're sending. */
        !          1290:        snprintf(msgbuf, sizeof msgbuf, "DHCPACK to %s (%s) via", piaddr(cip),
        !          1291:                 (packet->raw->htype && packet->raw->hlen) ?
        !          1292:                        print_hw_addr(packet->raw->htype, packet->raw->hlen,
        !          1293:                                      packet->raw->chaddr) :
        !          1294:                        "<no client hardware address>");
        !          1295:        log_info("%s %s", msgbuf, gip.len ? piaddr(gip) :
        !          1296:                                            packet->interface->name);
        !          1297: 
        !          1298:        errno = 0;
        !          1299:        send_packet ((fallback_interface
        !          1300:                      ? fallback_interface : packet -> interface),
        !          1301:                     &outgoing, &raw, outgoing.packet_length,
        !          1302:                     from, &to, (struct hardware *)0);
        !          1303:        if (subnet)
        !          1304:                subnet_dereference (&subnet, MDL);
        !          1305: }
        !          1306: 
        !          1307: void nak_lease (packet, cip)
        !          1308:        struct packet *packet;
        !          1309:        struct iaddr *cip;
        !          1310: {
        !          1311:        struct sockaddr_in to;
        !          1312:        struct in_addr from;
        !          1313:        int result;
        !          1314:        struct dhcp_packet raw;
        !          1315:        unsigned char nak = DHCPNAK;
        !          1316:        struct packet outgoing;
        !          1317:        struct hardware hto;
        !          1318:        unsigned i;
        !          1319:        struct option_state *options = (struct option_state *)0;
        !          1320:        struct option_cache *oc = (struct option_cache *)0;
        !          1321: 
        !          1322:        option_state_allocate (&options, MDL);
        !          1323:        memset (&outgoing, 0, sizeof outgoing);
        !          1324:        memset (&raw, 0, sizeof raw);
        !          1325:        outgoing.raw = &raw;
        !          1326: 
        !          1327:        /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
        !          1328:        if (!option_cache_allocate (&oc, MDL)) {
        !          1329:                log_error ("No memory for DHCPNAK message type.");
        !          1330:                option_state_dereference (&options, MDL);
        !          1331:                return;
        !          1332:        }
        !          1333:        if (!make_const_data (&oc -> expression, &nak, sizeof nak,
        !          1334:                              0, 0, MDL)) {
        !          1335:                log_error ("No memory for expr_const expression.");
        !          1336:                option_cache_dereference (&oc, MDL);
        !          1337:                option_state_dereference (&options, MDL);
        !          1338:                return;
        !          1339:        }
        !          1340:        i = DHO_DHCP_MESSAGE_TYPE;
        !          1341:        option_code_hash_lookup(&oc->option, dhcp_universe.code_hash,
        !          1342:                                &i, 0, MDL);
        !          1343:        save_option (&dhcp_universe, options, oc);
        !          1344:        option_cache_dereference (&oc, MDL);
        !          1345:                     
        !          1346:        /* Set DHCP_MESSAGE to whatever the message is */
        !          1347:        if (!option_cache_allocate (&oc, MDL)) {
        !          1348:                log_error ("No memory for DHCPNAK message type.");
        !          1349:                option_state_dereference (&options, MDL);
        !          1350:                return;
        !          1351:        }
        !          1352:        if (!make_const_data (&oc -> expression,
        !          1353:                              (unsigned char *)dhcp_message,
        !          1354:                              strlen (dhcp_message), 1, 0, MDL)) {
        !          1355:                log_error ("No memory for expr_const expression.");
        !          1356:                option_cache_dereference (&oc, MDL);
        !          1357:                option_state_dereference (&options, MDL);
        !          1358:                return;
        !          1359:        }
        !          1360:        i = DHO_DHCP_MESSAGE;
        !          1361:        option_code_hash_lookup(&oc->option, dhcp_universe.code_hash,
        !          1362:                                &i, 0, MDL);
        !          1363:        save_option (&dhcp_universe, options, oc);
        !          1364:        option_cache_dereference (&oc, MDL);
        !          1365:                     
        !          1366:        get_server_source_address(&from, options, packet);
        !          1367: 
        !          1368:        /* If there were agent options in the incoming packet, return
        !          1369:         * them.  We do not check giaddr to detect the presence of a
        !          1370:         * relay, as this excludes "l2" relay agents which have no
        !          1371:         * giaddr to set.
        !          1372:         */
        !          1373:        if (packet->options->universe_count > agent_universe.index &&
        !          1374:            packet->options->universes [agent_universe.index]) {
        !          1375:                option_chain_head_reference
        !          1376:                    ((struct option_chain_head **)
        !          1377:                     &(options -> universes [agent_universe.index]),
        !          1378:                     (struct option_chain_head *)
        !          1379:                     packet -> options -> universes [agent_universe.index],
        !          1380:                     MDL);
        !          1381:        }
        !          1382: 
        !          1383:        /* Do not use the client's requested parameter list. */
        !          1384:        delete_option (&dhcp_universe, packet -> options,
        !          1385:                       DHO_DHCP_PARAMETER_REQUEST_LIST);
        !          1386: 
        !          1387:        /* Set up the option buffer... */
        !          1388:        outgoing.packet_length =
        !          1389:                cons_options (packet, outgoing.raw, (struct lease *)0,
        !          1390:                              (struct client_state *)0,
        !          1391:                              0, packet -> options, options, &global_scope,
        !          1392:                              0, 0, 0, (struct data_string *)0, (char *)0);
        !          1393:        option_state_dereference (&options, MDL);
        !          1394: 
        !          1395: /*     memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
        !          1396:        if (packet->interface->address_count)
        !          1397:                raw.siaddr = packet->interface->addresses[0];
        !          1398:        raw.giaddr = packet -> raw -> giaddr;
        !          1399:        memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr);
        !          1400:        raw.hlen = packet -> raw -> hlen;
        !          1401:        raw.htype = packet -> raw -> htype;
        !          1402: 
        !          1403:        raw.xid = packet -> raw -> xid;
        !          1404:        raw.secs = packet -> raw -> secs;
        !          1405:        raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST);
        !          1406:        raw.hops = packet -> raw -> hops;
        !          1407:        raw.op = BOOTREPLY;
        !          1408: 
        !          1409:        /* Report what we're sending... */
        !          1410:        log_info ("DHCPNAK on %s to %s via %s",
        !          1411:              piaddr (*cip),
        !          1412:              print_hw_addr (packet -> raw -> htype,
        !          1413:                             packet -> raw -> hlen,
        !          1414:                             packet -> raw -> chaddr),
        !          1415:              packet -> raw -> giaddr.s_addr
        !          1416:              ? inet_ntoa (packet -> raw -> giaddr)
        !          1417:              : packet -> interface -> name);
        !          1418: 
        !          1419: 
        !          1420: 
        !          1421: #ifdef DEBUG_PACKET
        !          1422:        dump_packet (packet);
        !          1423:        dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
        !          1424:        dump_packet (&outgoing);
        !          1425:        dump_raw ((unsigned char *)&raw, outgoing.packet_length);
        !          1426: #endif
        !          1427: 
        !          1428: #if 0
        !          1429:        hto.hbuf [0] = packet -> raw -> htype;
        !          1430:        hto.hlen = packet -> raw -> hlen;
        !          1431:        memcpy (&hto.hbuf [1], packet -> raw -> chaddr, hto.hlen);
        !          1432:        hto.hlen++;
        !          1433: #endif
        !          1434: 
        !          1435:        /* Set up the common stuff... */
        !          1436:        to.sin_family = AF_INET;
        !          1437: #ifdef HAVE_SA_LEN
        !          1438:        to.sin_len = sizeof to;
        !          1439: #endif
        !          1440:        memset (to.sin_zero, 0, sizeof to.sin_zero);
        !          1441: 
        !          1442:        /* Make sure that the packet is at least as big as a BOOTP packet. */
        !          1443:        if (outgoing.packet_length < BOOTP_MIN_LEN)
        !          1444:                outgoing.packet_length = BOOTP_MIN_LEN;
        !          1445: 
        !          1446:        /* If this was gatewayed, send it back to the gateway.
        !          1447:           Otherwise, broadcast it on the local network. */
        !          1448:        if (raw.giaddr.s_addr) {
        !          1449:                to.sin_addr = raw.giaddr;
        !          1450:                if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
        !          1451:                        to.sin_port = local_port;
        !          1452:                else
        !          1453:                        to.sin_port = remote_port; /* for testing. */
        !          1454: 
        !          1455:                if (fallback_interface) {
        !          1456:                        result = send_packet (fallback_interface,
        !          1457:                                              packet, &raw,
        !          1458:                                              outgoing.packet_length,
        !          1459:                                              from, &to, &hto);
        !          1460:                        return;
        !          1461:                }
        !          1462:        } else {
        !          1463:                to.sin_addr = limited_broadcast;
        !          1464:                to.sin_port = remote_port;
        !          1465:        }
        !          1466: 
        !          1467:        errno = 0;
        !          1468:        result = send_packet (packet -> interface,
        !          1469:                              packet, &raw, outgoing.packet_length,
        !          1470:                              from, &to, (struct hardware *)0);
        !          1471: }
        !          1472: 
        !          1473: void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
        !          1474:        struct packet *packet;
        !          1475:        struct lease *lease;
        !          1476:        unsigned int offer;
        !          1477:        TIME when;
        !          1478:        char *msg;
        !          1479:        int ms_nulltp;
        !          1480:        struct host_decl *hp;
        !          1481: {
        !          1482:        struct lease *lt;
        !          1483:        struct lease_state *state;
        !          1484:        struct lease *next;
        !          1485:        struct host_decl *host = (struct host_decl *)0;
        !          1486:        TIME lease_time;
        !          1487:        TIME offered_lease_time;
        !          1488:        struct data_string d1;
        !          1489:        TIME min_lease_time;
        !          1490:        TIME max_lease_time;
        !          1491:        TIME default_lease_time;
        !          1492:        struct option_cache *oc;
        !          1493:        isc_result_t result;
        !          1494:        TIME ping_timeout;
        !          1495:        TIME lease_cltt;
        !          1496:        struct in_addr from;
        !          1497:        TIME remaining_time;
        !          1498:        struct iaddr cip;
        !          1499: 
        !          1500:        unsigned i, j;
        !          1501:        int s1;
        !          1502:        int ignorep;
        !          1503:        struct timeval tv;
        !          1504: 
        !          1505:        /* If we're already acking this lease, don't do it again. */
        !          1506:        if (lease -> state)
        !          1507:                return;
        !          1508: 
        !          1509:        /* Save original cltt for comparison later. */
        !          1510:        lease_cltt = lease->cltt;
        !          1511: 
        !          1512:        /* If the lease carries a host record, remember it. */
        !          1513:        if (hp)
        !          1514:                host_reference (&host, hp, MDL);
        !          1515:        else if (lease -> host)
        !          1516:                host_reference (&host, lease -> host, MDL);
        !          1517: 
        !          1518:        /* Allocate a lease state structure... */
        !          1519:        state = new_lease_state (MDL);
        !          1520:        if (!state)
        !          1521:                log_fatal ("unable to allocate lease state!");
        !          1522:        state -> got_requested_address = packet -> got_requested_address;
        !          1523:        shared_network_reference (&state -> shared_network,
        !          1524:                                  packet -> interface -> shared_network, MDL);
        !          1525: 
        !          1526:        /* See if we got a server identifier option. */
        !          1527:        if (lookup_option (&dhcp_universe,
        !          1528:                           packet -> options, DHO_DHCP_SERVER_IDENTIFIER))
        !          1529:                state -> got_server_identifier = 1;
        !          1530: 
        !          1531:        /* If there were agent options in the incoming packet, return
        !          1532:         * them.  Do not return the agent options if they were stashed
        !          1533:         * on the lease.  We do not check giaddr to detect the presence of
        !          1534:         * a relay, as this excludes "l2" relay agents which have no giaddr
        !          1535:         * to set.
        !          1536:         *
        !          1537:         * XXX: If the user configures options for the relay agent information
        !          1538:         * (state->options->universes[agent_universe.index] is not NULL),
        !          1539:         * we're still required to duplicate other values provided by the
        !          1540:         * relay agent.  So we need to merge the old values not configured
        !          1541:         * by the user into the new state, not just give up.
        !          1542:         */
        !          1543:        if (!packet->agent_options_stashed &&
        !          1544:            (packet->options != NULL) &&
        !          1545:            packet->options->universe_count > agent_universe.index &&
        !          1546:            packet->options->universes[agent_universe.index] != NULL &&
        !          1547:            (state->options->universe_count <= agent_universe.index ||
        !          1548:             state->options->universes[agent_universe.index] == NULL)) {
        !          1549:                option_chain_head_reference
        !          1550:                    ((struct option_chain_head **)
        !          1551:                     &(state -> options -> universes [agent_universe.index]),
        !          1552:                     (struct option_chain_head *)
        !          1553:                     packet -> options -> universes [agent_universe.index],
        !          1554:                     MDL);
        !          1555: 
        !          1556:                if (state->options->universe_count <= agent_universe.index)
        !          1557:                        state->options->universe_count =
        !          1558:                                                agent_universe.index + 1;
        !          1559:        }
        !          1560: 
        !          1561:        /* If we are offering a lease that is still currently valid, preserve
        !          1562:           the events.  We need to do this because if the client does not
        !          1563:           REQUEST our offer, it will expire in 2 minutes, overriding the
        !          1564:           expire time in the currently in force lease.  We want the expire
        !          1565:           events to be executed at that point. */
        !          1566:        if (lease -> ends <= cur_time && offer != DHCPOFFER) {
        !          1567:                /* Get rid of any old expiry or release statements - by
        !          1568:                   executing the statements below, we will be inserting new
        !          1569:                   ones if there are any to insert. */
        !          1570:                if (lease -> on_expiry)
        !          1571:                        executable_statement_dereference (&lease -> on_expiry,
        !          1572:                                                          MDL);
        !          1573:                if (lease -> on_commit)
        !          1574:                        executable_statement_dereference (&lease -> on_commit,
        !          1575:                                                          MDL);
        !          1576:                if (lease -> on_release)
        !          1577:                        executable_statement_dereference (&lease -> on_release,
        !          1578:                                                          MDL);
        !          1579:        }
        !          1580: 
        !          1581:        /* Execute statements in scope starting with the subnet scope. */
        !          1582:        execute_statements_in_scope ((struct binding_value **)0,
        !          1583:                                     packet, lease, (struct client_state *)0,
        !          1584:                                     packet -> options,
        !          1585:                                     state -> options, &lease -> scope,
        !          1586:                                     lease -> subnet -> group,
        !          1587:                                     (struct group *)0);
        !          1588: 
        !          1589:        /* If the lease is from a pool, run the pool scope. */
        !          1590:        if (lease -> pool)
        !          1591:                (execute_statements_in_scope
        !          1592:                 ((struct binding_value **)0, packet, lease,
        !          1593:                  (struct client_state *)0, packet -> options,
        !          1594:                  state -> options, &lease -> scope, lease -> pool -> group,
        !          1595:                  lease -> pool -> shared_network -> group));
        !          1596: 
        !          1597:        /* Execute statements from class scopes. */
        !          1598:        for (i = packet -> class_count; i > 0; i--) {
        !          1599:                execute_statements_in_scope
        !          1600:                        ((struct binding_value **)0,
        !          1601:                         packet, lease, (struct client_state *)0,
        !          1602:                         packet -> options, state -> options,
        !          1603:                         &lease -> scope, packet -> classes [i - 1] -> group,
        !          1604:                         (lease -> pool
        !          1605:                          ? lease -> pool -> group
        !          1606:                          : lease -> subnet -> group));
        !          1607:        }
        !          1608: 
        !          1609:        /* See if the client is only supposed to have one lease at a time,
        !          1610:           and if so, find its other leases and release them.    We can only
        !          1611:           do this on DHCPREQUEST.    It's a little weird to do this before
        !          1612:           looking at permissions, because the client might not actually
        !          1613:           _get_ a lease after we've done the permission check, but the
        !          1614:           assumption for this option is that the client has exactly one
        !          1615:           network interface, and will only ever remember one lease.   So
        !          1616:           if it sends a DHCPREQUEST, and doesn't get the lease, it's already
        !          1617:           forgotten about its old lease, so we can too. */
        !          1618:        if (packet -> packet_type == DHCPREQUEST &&
        !          1619:            (oc = lookup_option (&server_universe, state -> options,
        !          1620:                                 SV_ONE_LEASE_PER_CLIENT)) &&
        !          1621:            evaluate_boolean_option_cache (&ignorep,
        !          1622:                                           packet, lease,
        !          1623:                                           (struct client_state *)0,
        !          1624:                                           packet -> options,
        !          1625:                                           state -> options, &lease -> scope,
        !          1626:                                           oc, MDL)) {
        !          1627:            struct lease *seek;
        !          1628:            if (lease -> uid_len) {
        !          1629:                do {
        !          1630:                    seek = (struct lease *)0;
        !          1631:                    find_lease_by_uid (&seek, lease -> uid,
        !          1632:                                       lease -> uid_len, MDL);
        !          1633:                    if (!seek)
        !          1634:                        break;
        !          1635:                    if (seek == lease && !seek -> n_uid) {
        !          1636:                        lease_dereference (&seek, MDL);
        !          1637:                        break;
        !          1638:                    }
        !          1639:                    next = (struct lease *)0;
        !          1640: 
        !          1641:                    /* Don't release expired leases, and don't
        !          1642:                       release the lease we're going to assign. */
        !          1643:                    next = (struct lease *)0;
        !          1644:                    while (seek) {
        !          1645:                        if (seek -> n_uid)
        !          1646:                            lease_reference (&next, seek -> n_uid, MDL);
        !          1647:                        if (seek != lease &&
        !          1648:                            seek -> binding_state != FTS_RELEASED &&
        !          1649:                            seek -> binding_state != FTS_EXPIRED &&
        !          1650:                            seek -> binding_state != FTS_RESET &&
        !          1651:                            seek -> binding_state != FTS_FREE &&
        !          1652:                            seek -> binding_state != FTS_BACKUP)
        !          1653:                                break;
        !          1654:                        lease_dereference (&seek, MDL);
        !          1655:                        if (next) {
        !          1656:                            lease_reference (&seek, next, MDL);
        !          1657:                            lease_dereference (&next, MDL);
        !          1658:                        }
        !          1659:                    }
        !          1660:                    if (next)
        !          1661:                        lease_dereference (&next, MDL);
        !          1662:                    if (seek) {
        !          1663:                        release_lease (seek, packet);
        !          1664:                        lease_dereference (&seek, MDL);
        !          1665:                    } else
        !          1666:                        break;
        !          1667:                } while (1);
        !          1668:            }
        !          1669:            if (!lease -> uid_len ||
        !          1670:                (host &&
        !          1671:                 !host -> client_identifier.len &&
        !          1672:                 (oc = lookup_option (&server_universe, state -> options,
        !          1673:                                      SV_DUPLICATES)) &&
        !          1674:                 !evaluate_boolean_option_cache (&ignorep, packet, lease,
        !          1675:                                                 (struct client_state *)0,
        !          1676:                                                 packet -> options,
        !          1677:                                                 state -> options,
        !          1678:                                                 &lease -> scope,
        !          1679:                                                 oc, MDL))) {
        !          1680:                do {
        !          1681:                    seek = (struct lease *)0;
        !          1682:                    find_lease_by_hw_addr
        !          1683:                            (&seek, lease -> hardware_addr.hbuf,
        !          1684:                             lease -> hardware_addr.hlen, MDL);
        !          1685:                    if (!seek)
        !          1686:                            break;
        !          1687:                    if (seek == lease && !seek -> n_hw) {
        !          1688:                            lease_dereference (&seek, MDL);
        !          1689:                            break;
        !          1690:                    }
        !          1691:                    next = (struct lease *)0;
        !          1692:                    while (seek) {
        !          1693:                        if (seek -> n_hw)
        !          1694:                            lease_reference (&next, seek -> n_hw, MDL);
        !          1695:                        if (seek != lease &&
        !          1696:                            seek -> binding_state != FTS_RELEASED &&
        !          1697:                            seek -> binding_state != FTS_EXPIRED &&
        !          1698:                            seek -> binding_state != FTS_RESET &&
        !          1699:                            seek -> binding_state != FTS_FREE &&
        !          1700:                            seek -> binding_state != FTS_BACKUP)
        !          1701:                                break;
        !          1702:                        lease_dereference (&seek, MDL);
        !          1703:                        if (next) {
        !          1704:                            lease_reference (&seek, next, MDL);
        !          1705:                            lease_dereference (&next, MDL);
        !          1706:                        }
        !          1707:                    }
        !          1708:                    if (next)
        !          1709:                        lease_dereference (&next, MDL);
        !          1710:                    if (seek) {
        !          1711:                        release_lease (seek, packet);
        !          1712:                        lease_dereference (&seek, MDL);
        !          1713:                    } else
        !          1714:                        break;
        !          1715:                } while (1);
        !          1716:            }
        !          1717:        }
        !          1718:        
        !          1719: 
        !          1720:        /* Make sure this packet satisfies the configured minimum
        !          1721:           number of seconds. */
        !          1722:        memset (&d1, 0, sizeof d1);
        !          1723:        if (offer == DHCPOFFER &&
        !          1724:            (oc = lookup_option (&server_universe, state -> options,
        !          1725:                                 SV_MIN_SECS))) {
        !          1726:                if (evaluate_option_cache (&d1, packet, lease,
        !          1727:                                           (struct client_state *)0,
        !          1728:                                           packet -> options, state -> options,
        !          1729:                                           &lease -> scope, oc, MDL)) {
        !          1730:                        if (d1.len &&
        !          1731:                            ntohs (packet -> raw -> secs) < d1.data [0]) {
        !          1732:                                log_info("%s: configured min-secs value (%d) "
        !          1733:                                         "is greater than secs field (%d).  "
        !          1734:                                         "message dropped.", msg, d1.data[0],
        !          1735:                                         ntohs(packet->raw->secs));
        !          1736:                                data_string_forget (&d1, MDL);
        !          1737:                                free_lease_state (state, MDL);
        !          1738:                                if (host)
        !          1739:                                        host_dereference (&host, MDL);
        !          1740:                                return;
        !          1741:                        }
        !          1742:                        data_string_forget (&d1, MDL);
        !          1743:                }
        !          1744:        }
        !          1745: 
        !          1746:        /* Try to find a matching host declaration for this lease.
        !          1747:         */
        !          1748:        if (!host) {
        !          1749:                struct host_decl *hp = (struct host_decl *)0;
        !          1750:                struct host_decl *h;
        !          1751: 
        !          1752:                /* Try to find a host_decl that matches the client
        !          1753:                   identifier or hardware address on the packet, and
        !          1754:                   has no fixed IP address.   If there is one, hang
        !          1755:                   it off the lease so that its option definitions
        !          1756:                   can be used. */
        !          1757:                oc = lookup_option (&dhcp_universe, packet -> options,
        !          1758:                                    DHO_DHCP_CLIENT_IDENTIFIER);
        !          1759:                if (oc &&
        !          1760:                    evaluate_option_cache (&d1, packet, lease,
        !          1761:                                           (struct client_state *)0,
        !          1762:                                           packet -> options, state -> options,
        !          1763:                                           &lease -> scope, oc, MDL)) {
        !          1764:                        find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
        !          1765:                        data_string_forget (&d1, MDL);
        !          1766:                        for (h = hp; h; h = h -> n_ipaddr) {
        !          1767:                                if (!h -> fixed_addr)
        !          1768:                                        break;
        !          1769:                        }
        !          1770:                        if (h)
        !          1771:                                host_reference (&host, h, MDL);
        !          1772:                        if (hp != NULL)
        !          1773:                                host_dereference(&hp, MDL);
        !          1774:                }
        !          1775:                if (!host) {
        !          1776:                        find_hosts_by_haddr (&hp,
        !          1777:                                             packet -> raw -> htype,
        !          1778:                                             packet -> raw -> chaddr,
        !          1779:                                             packet -> raw -> hlen,
        !          1780:                                             MDL);
        !          1781:                        for (h = hp; h; h = h -> n_ipaddr) {
        !          1782:                                if (!h -> fixed_addr)
        !          1783:                                        break;
        !          1784:                        }
        !          1785:                        if (h)
        !          1786:                                host_reference (&host, h, MDL);
        !          1787:                        if (hp != NULL)
        !          1788:                                host_dereference(&hp, MDL);
        !          1789:                }
        !          1790:        }
        !          1791: 
        !          1792:        /* If we have a host_decl structure, run the options associated
        !          1793:           with its group.  Whether the host decl struct is old or not. */
        !          1794:        if (host)
        !          1795:                execute_statements_in_scope ((struct binding_value **)0,
        !          1796:                                             packet, lease,
        !          1797:                                             (struct client_state *)0,
        !          1798:                                             packet -> options,
        !          1799:                                             state -> options, &lease -> scope,
        !          1800:                                             host -> group,
        !          1801:                                             (lease -> pool
        !          1802:                                              ? lease -> pool -> group
        !          1803:                                              : lease -> subnet -> group));
        !          1804: 
        !          1805:        /* Drop the request if it's not allowed for this client.   By
        !          1806:           default, unknown clients are allowed. */
        !          1807:        if (!host &&
        !          1808:            (oc = lookup_option (&server_universe, state -> options,
        !          1809:                                 SV_BOOT_UNKNOWN_CLIENTS)) &&
        !          1810:            !evaluate_boolean_option_cache (&ignorep,
        !          1811:                                            packet, lease,
        !          1812:                                            (struct client_state *)0,
        !          1813:                                            packet -> options,
        !          1814:                                            state -> options,
        !          1815:                                            &lease -> scope, oc, MDL)) {
        !          1816:                if (!ignorep)
        !          1817:                        log_info ("%s: unknown client", msg);
        !          1818:                free_lease_state (state, MDL);
        !          1819:                if (host)
        !          1820:                        host_dereference (&host, MDL);
        !          1821:                return;
        !          1822:        } 
        !          1823: 
        !          1824:        /* Drop the request if it's not allowed for this client. */
        !          1825:        if (!offer &&
        !          1826:            (oc = lookup_option (&server_universe, state -> options,
        !          1827:                                   SV_ALLOW_BOOTP)) &&
        !          1828:            !evaluate_boolean_option_cache (&ignorep,
        !          1829:                                            packet, lease,
        !          1830:                                            (struct client_state *)0,
        !          1831:                                            packet -> options,
        !          1832:                                            state -> options,
        !          1833:                                            &lease -> scope, oc, MDL)) {
        !          1834:                if (!ignorep)
        !          1835:                        log_info ("%s: bootp disallowed", msg);
        !          1836:                free_lease_state (state, MDL);
        !          1837:                if (host)
        !          1838:                        host_dereference (&host, MDL);
        !          1839:                return;
        !          1840:        } 
        !          1841: 
        !          1842:        /* Drop the request if booting is specifically denied. */
        !          1843:        oc = lookup_option (&server_universe, state -> options,
        !          1844:                            SV_ALLOW_BOOTING);
        !          1845:        if (oc &&
        !          1846:            !evaluate_boolean_option_cache (&ignorep,
        !          1847:                                            packet, lease,
        !          1848:                                            (struct client_state *)0,
        !          1849:                                            packet -> options,
        !          1850:                                            state -> options,
        !          1851:                                            &lease -> scope, oc, MDL)) {
        !          1852:                if (!ignorep)
        !          1853:                        log_info ("%s: booting disallowed", msg);
        !          1854:                free_lease_state (state, MDL);
        !          1855:                if (host)
        !          1856:                        host_dereference (&host, MDL);
        !          1857:                return;
        !          1858:        }
        !          1859: 
        !          1860:        /* If we are configured to do per-class billing, do it. */
        !          1861:        if (have_billing_classes && !(lease -> flags & STATIC_LEASE)) {
        !          1862:                /* See if the lease is currently being billed to a
        !          1863:                   class, and if so, whether or not it can continue to
        !          1864:                   be billed to that class. */
        !          1865:                if (lease -> billing_class) {
        !          1866:                        for (i = 0; i < packet -> class_count; i++)
        !          1867:                                if (packet -> classes [i] ==
        !          1868:                                    lease -> billing_class)
        !          1869:                                        break;
        !          1870:                        if (i == packet -> class_count)
        !          1871:                                unbill_class (lease, lease -> billing_class);
        !          1872:                }
        !          1873: 
        !          1874:                /* If we don't have an active billing, see if we need
        !          1875:                   one, and if we do, try to do so. */
        !          1876:                if (lease->billing_class == NULL) {
        !          1877:                        int bill = 0;
        !          1878:                        for (i = 0; i < packet->class_count; i++) {
        !          1879:                                if (packet->classes[i]->lease_limit) {
        !          1880:                                        bill++;
        !          1881:                                        if (bill_class(lease,
        !          1882:                                                       packet->classes[i]))
        !          1883:                                                break;
        !          1884:                                }
        !          1885:                        }
        !          1886:                        if (bill != 0 && i == packet->class_count) {
        !          1887:                                log_info("%s: no available billing: lease "
        !          1888:                                         "limit reached in all matching "
        !          1889:                                         "classes", msg);
        !          1890:                                free_lease_state(state, MDL);
        !          1891:                                if (host)
        !          1892:                                        host_dereference(&host, MDL);
        !          1893:                                return;
        !          1894:                        }
        !          1895: 
        !          1896:                        /* If this is an offer, undo the billing.  We go
        !          1897:                         * through all the steps above to bill a class so
        !          1898:                         * we can hit the 'no available billing' mark and
        !          1899:                         * abort without offering.  But it just doesn't make
        !          1900:                         * sense to permanently bill a class for a non-active
        !          1901:                         * lease.  This means on REQUEST, we will bill this
        !          1902:                         * lease again (if there is a REQUEST).
        !          1903:                         */
        !          1904:                        if (offer == DHCPOFFER &&
        !          1905:                            lease->billing_class != NULL &&
        !          1906:                            lease->binding_state != FTS_ACTIVE)
        !          1907:                                unbill_class(lease, lease->billing_class);
        !          1908:                }
        !          1909:        }
        !          1910: 
        !          1911:        /* Figure out the filename. */
        !          1912:        oc = lookup_option (&server_universe, state -> options, SV_FILENAME);
        !          1913:        if (oc)
        !          1914:                evaluate_option_cache (&state -> filename, packet, lease,
        !          1915:                                       (struct client_state *)0,
        !          1916:                                       packet -> options, state -> options,
        !          1917:                                       &lease -> scope, oc, MDL);
        !          1918: 
        !          1919:        /* Choose a server name as above. */
        !          1920:        oc = lookup_option (&server_universe, state -> options,
        !          1921:                            SV_SERVER_NAME);
        !          1922:        if (oc)
        !          1923:                evaluate_option_cache (&state -> server_name, packet, lease,
        !          1924:                                       (struct client_state *)0,
        !          1925:                                       packet -> options, state -> options,
        !          1926:                                       &lease -> scope, oc, MDL);
        !          1927: 
        !          1928:        /* At this point, we have a lease that we can offer the client.
        !          1929:           Now we construct a lease structure that contains what we want,
        !          1930:           and call supersede_lease to do the right thing with it. */
        !          1931:        lt = (struct lease *)0;
        !          1932:        result = lease_allocate (&lt, MDL);
        !          1933:        if (result != ISC_R_SUCCESS) {
        !          1934:                log_info ("%s: can't allocate temporary lease structure: %s",
        !          1935:                          msg, isc_result_totext (result));
        !          1936:                free_lease_state (state, MDL);
        !          1937:                if (host)
        !          1938:                        host_dereference (&host, MDL);
        !          1939:                return;
        !          1940:        }
        !          1941:                
        !          1942:        /* Use the ip address of the lease that we finally found in
        !          1943:           the database. */
        !          1944:        lt -> ip_addr = lease -> ip_addr;
        !          1945: 
        !          1946:        /* Start now. */
        !          1947:        lt -> starts = cur_time;
        !          1948: 
        !          1949:        /* Figure out how long a lease to assign.    If this is a
        !          1950:           dynamic BOOTP lease, its duration must be infinite. */
        !          1951:        if (offer) {
        !          1952:                lt->flags &= ~BOOTP_LEASE;
        !          1953: 
        !          1954:                default_lease_time = DEFAULT_DEFAULT_LEASE_TIME;
        !          1955:                if ((oc = lookup_option (&server_universe, state -> options,
        !          1956:                                         SV_DEFAULT_LEASE_TIME))) {
        !          1957:                        if (evaluate_option_cache (&d1, packet, lease,
        !          1958:                                                   (struct client_state *)0,
        !          1959:                                                   packet -> options,
        !          1960:                                                   state -> options,
        !          1961:                                                   &lease -> scope, oc, MDL)) {
        !          1962:                                if (d1.len == sizeof (u_int32_t))
        !          1963:                                        default_lease_time =
        !          1964:                                                getULong (d1.data);
        !          1965:                                data_string_forget (&d1, MDL);
        !          1966:                        }
        !          1967:                }
        !          1968: 
        !          1969:                if ((oc = lookup_option (&dhcp_universe, packet -> options,
        !          1970:                                         DHO_DHCP_LEASE_TIME)))
        !          1971:                        s1 = evaluate_option_cache (&d1, packet, lease,
        !          1972:                                                    (struct client_state *)0,
        !          1973:                                                    packet -> options,
        !          1974:                                                    state -> options,
        !          1975:                                                    &lease -> scope, oc, MDL);
        !          1976:                else
        !          1977:                        s1 = 0;
        !          1978: 
        !          1979:                if (s1 && (d1.len == 4)) {
        !          1980:                        u_int32_t ones = 0xffffffff;
        !          1981: 
        !          1982:                        /* One potential use of reserved leases is to allow
        !          1983:                         * clients to signal reservation of their lease.  They
        !          1984:                         * can kinda sorta do this, if you squint hard enough,
        !          1985:                         * by supplying an 'infinite' requested-lease-time
        !          1986:                         * option.  This is generally bad practice...you want
        !          1987:                         * clients to return to the server on at least some
        !          1988:                         * period (days, months, years) to get up-to-date
        !          1989:                         * config state.  So;
        !          1990:                         *
        !          1991:                         * 1) A client requests 0xffffffff lease-time.
        !          1992:                         * 2) The server reserves the lease, and assigns a
        !          1993:                         *    <= max_lease_time lease-time to the client, which
        !          1994:                         *    we presume is much smaller than 0xffffffff.
        !          1995:                         * 3) The client ultimately fails to renew its lease
        !          1996:                         *    (all clients go offline at some point).
        !          1997:                         * 4) The server retains the reservation, although
        !          1998:                         *    the lease expires and passes through those states
        !          1999:                         *    as normal, it's placed in the 'reserved' queue,
        !          2000:                         *    and is under no circumstances allocated to any
        !          2001:                         *    clients.
        !          2002:                         *
        !          2003:                         * Whether the client knows its reserving its lease or
        !          2004:                         * not, this can be a handy tool for a sysadmin.
        !          2005:                         */
        !          2006:                        if ((memcmp(d1.data, &ones, 4) == 0) &&
        !          2007:                            (oc = lookup_option(&server_universe,
        !          2008:                                                state->options,
        !          2009:                                                SV_RESERVE_INFINITE)) &&
        !          2010:                            evaluate_boolean_option_cache(&ignorep, packet,
        !          2011:                                                lease, NULL, packet->options,
        !          2012:                                                state->options, &lease->scope,
        !          2013:                                                oc, MDL)) {
        !          2014:                                lt->flags |= RESERVED_LEASE;
        !          2015:                                if (!ignorep)
        !          2016:                                        log_info("Infinite-leasetime "
        !          2017:                                                 "reservation made on %s.",
        !          2018:                                                 piaddr(lt->ip_addr));
        !          2019:                        }
        !          2020: 
        !          2021:                        lease_time = getULong (d1.data);
        !          2022:                } else
        !          2023:                        lease_time = default_lease_time;
        !          2024: 
        !          2025:                if (s1)
        !          2026:                        data_string_forget(&d1, MDL);
        !          2027: 
        !          2028:                /* See if there's a maximum lease time. */
        !          2029:                max_lease_time = DEFAULT_MAX_LEASE_TIME;
        !          2030:                if ((oc = lookup_option (&server_universe, state -> options,
        !          2031:                                         SV_MAX_LEASE_TIME))) {
        !          2032:                        if (evaluate_option_cache (&d1, packet, lease,
        !          2033:                                                   (struct client_state *)0,
        !          2034:                                                   packet -> options,
        !          2035:                                                   state -> options,
        !          2036:                                                   &lease -> scope, oc, MDL)) {
        !          2037:                                if (d1.len == sizeof (u_int32_t))
        !          2038:                                        max_lease_time =
        !          2039:                                                getULong (d1.data);
        !          2040:                                data_string_forget (&d1, MDL);
        !          2041:                        }
        !          2042:                }
        !          2043: 
        !          2044:                /* Enforce the maximum lease length. */
        !          2045:                if (lease_time < 0 /* XXX */
        !          2046:                    || lease_time > max_lease_time)
        !          2047:                        lease_time = max_lease_time;
        !          2048:                        
        !          2049:                min_lease_time = DEFAULT_MIN_LEASE_TIME;
        !          2050:                if (min_lease_time > max_lease_time)
        !          2051:                        min_lease_time = max_lease_time;
        !          2052: 
        !          2053:                if ((oc = lookup_option (&server_universe, state -> options,
        !          2054:                                         SV_MIN_LEASE_TIME))) {
        !          2055:                        if (evaluate_option_cache (&d1, packet, lease,
        !          2056:                                                   (struct client_state *)0,
        !          2057:                                                   packet -> options,
        !          2058:                                                   state -> options,
        !          2059:                                                   &lease -> scope, oc, MDL)) {
        !          2060:                                if (d1.len == sizeof (u_int32_t))
        !          2061:                                        min_lease_time = getULong (d1.data);
        !          2062:                                data_string_forget (&d1, MDL);
        !          2063:                        }
        !          2064:                }
        !          2065: 
        !          2066:                /* CC: If there are less than
        !          2067:                   adaptive-lease-time-threshold % free leases,
        !          2068:                     hand out only short term leases */
        !          2069: 
        !          2070:                memset(&d1, 0, sizeof(d1));
        !          2071:                if (lease->pool &&
        !          2072:                    (oc = lookup_option(&server_universe, state->options,
        !          2073:                                        SV_ADAPTIVE_LEASE_TIME_THRESHOLD)) &&
        !          2074:                    evaluate_option_cache(&d1, packet, lease, NULL,
        !          2075:                                          packet->options, state->options,
        !          2076:                                          &lease->scope, oc, MDL)) {
        !          2077:                        if (d1.len == 1 && d1.data[0] > 0 &&
        !          2078:                            d1.data[0] < 100) {
        !          2079:                                TIME adaptive_time;
        !          2080:                                int poolfilled, total, count;
        !          2081: 
        !          2082:                                if (min_lease_time)
        !          2083:                                        adaptive_time = min_lease_time;
        !          2084:                                else
        !          2085:                                        adaptive_time = DEFAULT_MIN_LEASE_TIME;
        !          2086: 
        !          2087:                                /* Allow the client to keep its lease. */
        !          2088:                                if (lease->ends - cur_time > adaptive_time)
        !          2089:                                        adaptive_time = lease->ends - cur_time;
        !          2090: 
        !          2091:                                count = lease->pool->lease_count;
        !          2092:                                total = count - (lease->pool->free_leases +
        !          2093:                                                 lease->pool->backup_leases);
        !          2094: 
        !          2095:                                poolfilled = (total > (INT_MAX / 100)) ?
        !          2096:                                             total / (count / 100) :
        !          2097:                                             (total * 100) / count;
        !          2098: 
        !          2099:                                log_debug("Adap-lease: Total: %d, Free: %d, "
        !          2100:                                          "Ends: %d, Adaptive: %d, Fill: %d, "
        !          2101:                                          "Threshold: %d",
        !          2102:                                          lease->pool->lease_count,
        !          2103:                                          lease->pool->free_leases,
        !          2104:                                          (int)(lease->ends - cur_time),
        !          2105:                                          (int)adaptive_time, poolfilled,
        !          2106:                                          d1.data[0]);
        !          2107: 
        !          2108:                                if (poolfilled >= d1.data[0] &&
        !          2109:                                    lease_time > adaptive_time) {
        !          2110:                                        log_info("Pool over threshold, time "
        !          2111:                                                 "for %s reduced from %d to "
        !          2112:                                                 "%d.", piaddr(lease->ip_addr),
        !          2113:                                                 (int)lease_time,
        !          2114:                                                 (int)adaptive_time);
        !          2115: 
        !          2116:                                        lease_time = adaptive_time;
        !          2117:                                }
        !          2118:                        }
        !          2119:                        data_string_forget(&d1, MDL);
        !          2120:                }
        !          2121: 
        !          2122:                /* a client requests an address which is not yet active*/
        !          2123:                if (lease->pool && lease->pool->valid_from && 
        !          2124:                     cur_time < lease->pool->valid_from) {
        !          2125:                        /* NAK leases before pool activation date */
        !          2126:                        cip.len = 4;
        !          2127:                        memcpy (cip.iabuf, &lt->ip_addr.iabuf, 4);
        !          2128:                        nak_lease(packet, &cip);
        !          2129:                        free_lease_state (state, MDL);
        !          2130:                        lease_dereference (&lt, MDL);
        !          2131:                        if (host)
        !          2132:                                host_dereference (&host, MDL);
        !          2133:                        return;
        !          2134:                        
        !          2135:                }
        !          2136: 
        !          2137:                /* CC:
        !          2138:                a) NAK current lease if past the expiration date
        !          2139:                b) extend lease only up to the expiration date, but not
        !          2140:                below min-lease-time
        !          2141:                Setting min-lease-time is essential for this to work!
        !          2142:                The value of min-lease-time determines the lenght
        !          2143:                of the transition window:
        !          2144:                A client renewing a second before the deadline will
        !          2145:                get a min-lease-time lease. Since the current ip might not
        !          2146:                be routable after the deadline, the client will
        !          2147:                be offline until it DISCOVERS again. Otherwise it will
        !          2148:                receive a NAK at T/2.
        !          2149:                A min-lease-time of 6 seconds effectively switches over
        !          2150:                all clients in this pool very quickly.
        !          2151:                        */
        !          2152:  
        !          2153:                if (lease->pool && lease->pool->valid_until) {
        !          2154:                        if (cur_time >= lease->pool->valid_until) {
        !          2155:                                /* NAK leases after pool expiration date */
        !          2156:                                cip.len = 4;
        !          2157:                                memcpy (cip.iabuf, &lt->ip_addr.iabuf, 4);
        !          2158:                                nak_lease(packet, &cip);
        !          2159:                                free_lease_state (state, MDL);
        !          2160:                                lease_dereference (&lt, MDL);
        !          2161:                                if (host)
        !          2162:                                        host_dereference (&host, MDL);
        !          2163:                                return;
        !          2164:                        }
        !          2165:                        remaining_time = lease->pool->valid_until - cur_time;
        !          2166:                        if (lease_time > remaining_time)
        !          2167:                                lease_time = remaining_time;
        !          2168:                }
        !          2169:  
        !          2170:                if (lease_time < min_lease_time) {
        !          2171:                        if (min_lease_time)
        !          2172:                                lease_time = min_lease_time;
        !          2173:                        else
        !          2174:                                lease_time = default_lease_time;
        !          2175:                }
        !          2176: 
        !          2177: 
        !          2178: #if defined (FAILOVER_PROTOCOL)
        !          2179:                /* Okay, we know the lease duration.   Now check the
        !          2180:                   failover state, if any. */
        !          2181:                if (lease -> pool && lease -> pool -> failover_peer) {
        !          2182:                        TIME new_lease_time = lease_time;
        !          2183:                        dhcp_failover_state_t *peer =
        !          2184:                            lease -> pool -> failover_peer;
        !          2185: 
        !          2186:                        /* Copy previous lease failover ack-state. */
        !          2187:                        lt->tsfp = lease->tsfp;
        !          2188:                        lt->atsfp = lease->atsfp;
        !          2189: 
        !          2190:                        /* cltt set below */
        !          2191: 
        !          2192:                        /* Lease times less than MCLT are not a concern. */
        !          2193:                        if (lease_time > peer->mclt) {
        !          2194:                                /* Each server can only offer a lease time
        !          2195:                                 * that is either equal to MCLT (at least),
        !          2196:                                 * or up to TSFP+MCLT.  Only if the desired
        !          2197:                                 * lease time falls within TSFP+MCLT, can
        !          2198:                                 * the server allow it.
        !          2199:                                 */
        !          2200:                                if (lt->tsfp <= cur_time)
        !          2201:                                        new_lease_time = peer->mclt;
        !          2202:                                else if ((cur_time + lease_time) >
        !          2203:                                         (lt->tsfp + peer->mclt))
        !          2204:                                        new_lease_time = (lt->tsfp - cur_time)
        !          2205:                                                                + peer->mclt;
        !          2206:                        }
        !          2207: 
        !          2208:                        /* Update potential expiry.  Allow for the desired
        !          2209:                         * lease time plus one half the actual (whether
        !          2210:                         * modified downward or not) lease time, which is
        !          2211:                         * actually an estimate of when the client will
        !          2212:                         * renew.  This way, the client will be able to get
        !          2213:                         * the desired lease time upon renewal.
        !          2214:                         */
        !          2215:                        if (offer == DHCPACK) {
        !          2216:                                lt->tstp = cur_time + lease_time +
        !          2217:                                                (new_lease_time / 2);
        !          2218: 
        !          2219:                                /* If we reduced the potential expiry time,
        !          2220:                                 * make sure we don't offer an old-expiry-time
        !          2221:                                 * lease for this lease before the change is
        !          2222:                                 * ack'd.
        !          2223:                                 */
        !          2224:                                if (lt->tstp < lt->tsfp)
        !          2225:                                        lt->tsfp = lt->tstp;
        !          2226:                        } else
        !          2227:                                lt->tstp = lease->tstp;
        !          2228: 
        !          2229:                        /* Use failover-modified lease time.  */
        !          2230:                        lease_time = new_lease_time;
        !          2231:                }
        !          2232: #endif /* FAILOVER_PROTOCOL */
        !          2233: 
        !          2234:                /* If the lease duration causes the time value to wrap,
        !          2235:                   use the maximum expiry time. */
        !          2236:                if (cur_time + lease_time < cur_time)
        !          2237:                        state -> offered_expiry = MAX_TIME - 1;
        !          2238:                else
        !          2239:                        state -> offered_expiry = cur_time + lease_time;
        !          2240:                if (when)
        !          2241:                        lt -> ends = when;
        !          2242:                else
        !          2243:                        lt -> ends = state -> offered_expiry;
        !          2244: 
        !          2245:                /* Don't make lease active until we actually get a
        !          2246:                   DHCPREQUEST. */
        !          2247:                if (offer == DHCPACK)
        !          2248:                        lt -> next_binding_state = FTS_ACTIVE;
        !          2249:                else
        !          2250:                        lt -> next_binding_state = lease -> binding_state;
        !          2251:        } else {
        !          2252:                lt->flags |= BOOTP_LEASE;
        !          2253: 
        !          2254:                lease_time = MAX_TIME - cur_time;
        !          2255: 
        !          2256:                if ((oc = lookup_option (&server_universe, state -> options,
        !          2257:                                         SV_BOOTP_LEASE_LENGTH))) {
        !          2258:                        if (evaluate_option_cache (&d1, packet, lease,
        !          2259:                                                   (struct client_state *)0,
        !          2260:                                                   packet -> options,
        !          2261:                                                   state -> options,
        !          2262:                                                   &lease -> scope, oc, MDL)) {
        !          2263:                                if (d1.len == sizeof (u_int32_t))
        !          2264:                                        lease_time = getULong (d1.data);
        !          2265:                                data_string_forget (&d1, MDL);
        !          2266:                        }
        !          2267:                }
        !          2268: 
        !          2269:                if ((oc = lookup_option (&server_universe, state -> options,
        !          2270:                                         SV_BOOTP_LEASE_CUTOFF))) {
        !          2271:                        if (evaluate_option_cache (&d1, packet, lease,
        !          2272:                                                   (struct client_state *)0,
        !          2273:                                                   packet -> options,
        !          2274:                                                   state -> options,
        !          2275:                                                   &lease -> scope, oc, MDL)) {
        !          2276:                                if (d1.len == sizeof (u_int32_t))
        !          2277:                                        lease_time = (getULong (d1.data) -
        !          2278:                                                      cur_time);
        !          2279:                                data_string_forget (&d1, MDL);
        !          2280:                        }
        !          2281:                }
        !          2282: 
        !          2283:                lt -> ends = state -> offered_expiry = cur_time + lease_time;
        !          2284:                lt -> next_binding_state = FTS_ACTIVE;
        !          2285:        }
        !          2286: 
        !          2287:        /* Update Client Last Transaction Time. */
        !          2288:        lt->cltt = cur_time;
        !          2289: 
        !          2290:        /* Record the uid, if given... */
        !          2291:        oc = lookup_option (&dhcp_universe, packet -> options,
        !          2292:                            DHO_DHCP_CLIENT_IDENTIFIER);
        !          2293:        if (oc &&
        !          2294:            evaluate_option_cache (&d1, packet, lease,
        !          2295:                                   (struct client_state *)0,
        !          2296:                                   packet -> options, state -> options,
        !          2297:                                   &lease -> scope, oc, MDL)) {
        !          2298:                if (d1.len <= sizeof lt -> uid_buf) {
        !          2299:                        memcpy (lt -> uid_buf, d1.data, d1.len);
        !          2300:                        lt -> uid = lt -> uid_buf;
        !          2301:                        lt -> uid_max = sizeof lt -> uid_buf;
        !          2302:                        lt -> uid_len = d1.len;
        !          2303:                } else {
        !          2304:                        unsigned char *tuid;
        !          2305:                        lt -> uid_max = d1.len;
        !          2306:                        lt -> uid_len = d1.len;
        !          2307:                        tuid = (unsigned char *)dmalloc (lt -> uid_max, MDL);
        !          2308:                        /* XXX inelegant */
        !          2309:                        if (!tuid)
        !          2310:                                log_fatal ("no memory for large uid.");
        !          2311:                        memcpy (tuid, d1.data, lt -> uid_len);
        !          2312:                        lt -> uid = tuid;
        !          2313:                }
        !          2314:                data_string_forget (&d1, MDL);
        !          2315:        }
        !          2316: 
        !          2317:        if (host) {
        !          2318:                host_reference (&lt -> host, host, MDL);
        !          2319:                host_dereference (&host, MDL);
        !          2320:        }
        !          2321:        if (lease -> subnet)
        !          2322:                subnet_reference (&lt -> subnet, lease -> subnet, MDL);
        !          2323:        if (lease -> billing_class)
        !          2324:                class_reference (&lt -> billing_class,
        !          2325:                                 lease -> billing_class, MDL);
        !          2326: 
        !          2327:        /* Set a flag if this client is a broken client that NUL
        !          2328:           terminates string options and expects us to do likewise. */
        !          2329:        if (ms_nulltp)
        !          2330:                lease -> flags |= MS_NULL_TERMINATION;
        !          2331:        else
        !          2332:                lease -> flags &= ~MS_NULL_TERMINATION;
        !          2333: 
        !          2334:        /* Save any bindings. */
        !          2335:        if (lease -> scope) {
        !          2336:                binding_scope_reference (&lt -> scope, lease -> scope, MDL);
        !          2337:                binding_scope_dereference (&lease -> scope, MDL);
        !          2338:        }
        !          2339:        if (lease -> agent_options)
        !          2340:                option_chain_head_reference (&lt -> agent_options,
        !          2341:                                             lease -> agent_options, MDL);
        !          2342: 
        !          2343:        /* Save the vendor-class-identifier for DHCPLEASEQUERY. */
        !          2344:        oc = lookup_option(&dhcp_universe, packet->options,
        !          2345:                           DHO_VENDOR_CLASS_IDENTIFIER);
        !          2346:        if (oc != NULL &&
        !          2347:            evaluate_option_cache(&d1, packet, NULL, NULL, packet->options,
        !          2348:                                  NULL, &lease->scope, oc, MDL)) {
        !          2349:                if (d1.len != 0) {
        !          2350:                        bind_ds_value(&lease->scope, "vendor-class-identifier",
        !          2351:                                      &d1);
        !          2352:                }
        !          2353: 
        !          2354:                data_string_forget(&d1, MDL);
        !          2355:        }
        !          2356: 
        !          2357:        /* If we got relay agent information options from the packet, then
        !          2358:         * cache them for renewal in case the relay agent can't supply them
        !          2359:         * when the client unicasts.  The options may be from an addressed
        !          2360:         * "l3" relay, or from an unaddressed "l2" relay which does not set
        !          2361:         * giaddr.
        !          2362:         */
        !          2363:        if (!packet->agent_options_stashed &&
        !          2364:            (packet->options != NULL) &&
        !          2365:            packet->options->universe_count > agent_universe.index &&
        !          2366:            packet->options->universes[agent_universe.index] != NULL) {
        !          2367:            oc = lookup_option (&server_universe, state -> options,
        !          2368:                                SV_STASH_AGENT_OPTIONS);
        !          2369:            if (!oc ||
        !          2370:                evaluate_boolean_option_cache (&ignorep, packet, lease,
        !          2371:                                               (struct client_state *)0,
        !          2372:                                               packet -> options,
        !          2373:                                               state -> options,
        !          2374:                                               &lease -> scope, oc, MDL)) {
        !          2375:                if (lt -> agent_options)
        !          2376:                    option_chain_head_dereference (&lt -> agent_options, MDL);
        !          2377:                option_chain_head_reference
        !          2378:                        (&lt -> agent_options,
        !          2379:                         (struct option_chain_head *)
        !          2380:                         packet -> options -> universes [agent_universe.index],
        !          2381:                         MDL);
        !          2382:            }
        !          2383:        }
        !          2384: 
        !          2385:        /* Replace the old lease hostname with the new one, if it's changed. */
        !          2386:        oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME);
        !          2387:        if (oc)
        !          2388:                s1 = evaluate_option_cache (&d1, packet, (struct lease *)0,
        !          2389:                                            (struct client_state *)0,
        !          2390:                                            packet -> options,
        !          2391:                                            (struct option_state *)0,
        !          2392:                                            &global_scope, oc, MDL);
        !          2393:        else
        !          2394:                s1 = 0;
        !          2395: 
        !          2396:        if (oc && s1 &&
        !          2397:            lease -> client_hostname &&
        !          2398:            strlen (lease -> client_hostname) == d1.len &&
        !          2399:            !memcmp (lease -> client_hostname, d1.data, d1.len)) {
        !          2400:                /* Hasn't changed. */
        !          2401:                data_string_forget (&d1, MDL);
        !          2402:                lt -> client_hostname = lease -> client_hostname;
        !          2403:                lease -> client_hostname = (char *)0;
        !          2404:        } else if (oc && s1) {
        !          2405:                lt -> client_hostname = dmalloc (d1.len + 1, MDL);
        !          2406:                if (!lt -> client_hostname)
        !          2407:                        log_error ("no memory for client hostname.");
        !          2408:                else {
        !          2409:                        memcpy (lt -> client_hostname, d1.data, d1.len);
        !          2410:                        lt -> client_hostname [d1.len] = 0;
        !          2411:                }
        !          2412:                data_string_forget (&d1, MDL);
        !          2413:        }
        !          2414: 
        !          2415:        /* Record the hardware address, if given... */
        !          2416:        lt -> hardware_addr.hlen = packet -> raw -> hlen + 1;
        !          2417:        lt -> hardware_addr.hbuf [0] = packet -> raw -> htype;
        !          2418:        memcpy (&lt -> hardware_addr.hbuf [1], packet -> raw -> chaddr,
        !          2419:                sizeof packet -> raw -> chaddr);
        !          2420: 
        !          2421:        lt -> flags = lease -> flags & ~PERSISTENT_FLAGS;
        !          2422: 
        !          2423:        /* If there are statements to execute when the lease is
        !          2424:           committed, execute them. */
        !          2425:        if (lease -> on_commit && (!offer || offer == DHCPACK)) {
        !          2426:                execute_statements ((struct binding_value **)0,
        !          2427:                                    packet, lt, (struct client_state *)0,
        !          2428:                                    packet -> options,
        !          2429:                                    state -> options, &lt -> scope,
        !          2430:                                    lease -> on_commit);
        !          2431:                if (lease -> on_commit)
        !          2432:                        executable_statement_dereference (&lease -> on_commit,
        !          2433:                                                          MDL);
        !          2434:        }
        !          2435: 
        !          2436: #ifdef NSUPDATE
        !          2437:        /* Perform DDNS updates, if configured to. */
        !          2438:        if ((!offer || offer == DHCPACK) &&
        !          2439:            (!(oc = lookup_option (&server_universe, state -> options,
        !          2440:                                   SV_DDNS_UPDATES)) ||
        !          2441:             evaluate_boolean_option_cache (&ignorep, packet, lt,
        !          2442:                                            (struct client_state *)0,
        !          2443:                                            packet -> options,
        !          2444:                                            state -> options,
        !          2445:                                            &lt -> scope, oc, MDL))) {
        !          2446:                ddns_updates(packet, lt, lease, NULL, NULL, state->options);
        !          2447:        }
        !          2448: #endif /* NSUPDATE */
        !          2449: 
        !          2450:        /* Don't call supersede_lease on a mocked-up lease. */
        !          2451:        if (lease -> flags & STATIC_LEASE) {
        !          2452:                /* Copy the hardware address into the static lease
        !          2453:                   structure. */
        !          2454:                lease -> hardware_addr.hlen = packet -> raw -> hlen + 1;
        !          2455:                lease -> hardware_addr.hbuf [0] = packet -> raw -> htype;
        !          2456:                memcpy (&lease -> hardware_addr.hbuf [1],
        !          2457:                        packet -> raw -> chaddr,
        !          2458:                        sizeof packet -> raw -> chaddr); /* XXX */
        !          2459:        } else {
        !          2460: #if !defined(DELAYED_ACK)
        !          2461:                /* Install the new information on 'lt' onto the lease at
        !          2462:                 * 'lease'.  If this is a DHCPOFFER, it is a 'soft' promise,
        !          2463:                 * if it is a DHCPACK, it is a 'hard' binding, so it needs
        !          2464:                 * to be recorded and propogated immediately.  If the update
        !          2465:                 * fails, don't ACK it (or BOOTREPLY) either; we may give
        !          2466:                 * the same lease to another client later, and that would be
        !          2467:                 * a conflict.
        !          2468:                 */
        !          2469:                if (!supersede_lease(lease, lt, !offer || (offer == DHCPACK),
        !          2470:                                     offer == DHCPACK, offer == DHCPACK)) {
        !          2471: #else /* defined(DELAYED_ACK) */
        !          2472:                /* Install the new information on 'lt' onto the lease at
        !          2473:                 * 'lease'.  We will not 'commit' this information to disk
        !          2474:                 * yet (fsync()), we will 'propogate' the information if
        !          2475:                 * this is BOOTP or a DHCPACK, but we will not 'pimmediate'ly
        !          2476:                 * transmit failover binding updates (this is delayed until
        !          2477:                 * after the fsync()).  If the update fails, don't ACK it (or
        !          2478:                 * BOOTREPLY either); we may give the same lease out to a
        !          2479:                 * different client, and that would be a conflict.
        !          2480:                 */
        !          2481:                if (!supersede_lease(lease, lt, 0, !offer || offer == DHCPACK,
        !          2482:                                     0)) {
        !          2483: #endif
        !          2484:                        log_info ("%s: database update failed", msg);
        !          2485:                        free_lease_state (state, MDL);
        !          2486:                        lease_dereference (&lt, MDL);
        !          2487:                        return;
        !          2488:                }
        !          2489:        }
        !          2490:        lease_dereference (&lt, MDL);
        !          2491: 
        !          2492:        /* Remember the interface on which the packet arrived. */
        !          2493:        state -> ip = packet -> interface;
        !          2494: 
        !          2495:        /* Remember the giaddr, xid, secs, flags and hops. */
        !          2496:        state -> giaddr = packet -> raw -> giaddr;
        !          2497:        state -> ciaddr = packet -> raw -> ciaddr;
        !          2498:        state -> xid = packet -> raw -> xid;
        !          2499:        state -> secs = packet -> raw -> secs;
        !          2500:        state -> bootp_flags = packet -> raw -> flags;
        !          2501:        state -> hops = packet -> raw -> hops;
        !          2502:        state -> offer = offer;
        !          2503: 
        !          2504:        /* If we're always supposed to broadcast to this client, set
        !          2505:           the broadcast bit in the bootp flags field. */
        !          2506:        if ((oc = lookup_option (&server_universe, state -> options,
        !          2507:                                SV_ALWAYS_BROADCAST)) &&
        !          2508:            evaluate_boolean_option_cache (&ignorep, packet, lease,
        !          2509:                                           (struct client_state *)0,
        !          2510:                                           packet -> options, state -> options,
        !          2511:                                           &lease -> scope, oc, MDL))
        !          2512:                state -> bootp_flags |= htons (BOOTP_BROADCAST);
        !          2513: 
        !          2514:        /* Get the Maximum Message Size option from the packet, if one
        !          2515:           was sent. */
        !          2516:        oc = lookup_option (&dhcp_universe, packet -> options,
        !          2517:                            DHO_DHCP_MAX_MESSAGE_SIZE);
        !          2518:        if (oc &&
        !          2519:            evaluate_option_cache (&d1, packet, lease,
        !          2520:                                   (struct client_state *)0,
        !          2521:                                   packet -> options, state -> options,
        !          2522:                                   &lease -> scope, oc, MDL)) {
        !          2523:                if (d1.len == sizeof (u_int16_t))
        !          2524:                        state -> max_message_size = getUShort (d1.data);
        !          2525:                data_string_forget (&d1, MDL);
        !          2526:        } else {
        !          2527:                oc = lookup_option (&dhcp_universe, state -> options,
        !          2528:                                    DHO_DHCP_MAX_MESSAGE_SIZE);
        !          2529:                if (oc &&
        !          2530:                    evaluate_option_cache (&d1, packet, lease,
        !          2531:                                           (struct client_state *)0,
        !          2532:                                           packet -> options, state -> options,
        !          2533:                                           &lease -> scope, oc, MDL)) {
        !          2534:                        if (d1.len == sizeof (u_int16_t))
        !          2535:                                state -> max_message_size =
        !          2536:                                        getUShort (d1.data);
        !          2537:                        data_string_forget (&d1, MDL);
        !          2538:                }
        !          2539:        }
        !          2540: 
        !          2541:        /* Get the Subnet Selection option from the packet, if one
        !          2542:           was sent. */
        !          2543:        if ((oc = lookup_option (&dhcp_universe, packet -> options,
        !          2544:                                 DHO_SUBNET_SELECTION))) {
        !          2545: 
        !          2546:                /* Make a copy of the data. */
        !          2547:                struct option_cache *noc = (struct option_cache *)0;
        !          2548:                if (option_cache_allocate (&noc, MDL)) {
        !          2549:                        if (oc -> data.len)
        !          2550:                                data_string_copy (&noc -> data,
        !          2551:                                                  &oc -> data, MDL);
        !          2552:                        if (oc -> expression)
        !          2553:                                expression_reference (&noc -> expression,
        !          2554:                                                      oc -> expression, MDL);
        !          2555:                        if (oc -> option)
        !          2556:                                option_reference(&(noc->option), oc->option,
        !          2557:                                                 MDL);
        !          2558:                }
        !          2559: 
        !          2560:                save_option (&dhcp_universe, state -> options, noc);
        !          2561:                option_cache_dereference (&noc, MDL);
        !          2562:        }
        !          2563: 
        !          2564:        /* Now, if appropriate, put in DHCP-specific options that
        !          2565:           override those. */
        !          2566:        if (state -> offer) {
        !          2567:                i = DHO_DHCP_MESSAGE_TYPE;
        !          2568:                oc = (struct option_cache *)0;
        !          2569:                if (option_cache_allocate (&oc, MDL)) {
        !          2570:                        if (make_const_data (&oc -> expression,
        !          2571:                                             &state -> offer, 1, 0, 0, MDL)) {
        !          2572:                                option_code_hash_lookup(&oc->option,
        !          2573:                                                        dhcp_universe.code_hash,
        !          2574:                                                        &i, 0, MDL);
        !          2575:                                save_option (&dhcp_universe,
        !          2576:                                             state -> options, oc);
        !          2577:                        }
        !          2578:                        option_cache_dereference (&oc, MDL);
        !          2579:                }
        !          2580: 
        !          2581:                get_server_source_address(&from, state->options, packet);
        !          2582:                memcpy(state->from.iabuf, &from, sizeof(from));
        !          2583:                state->from.len = sizeof(from);
        !          2584: 
        !          2585:                offered_lease_time =
        !          2586:                        state -> offered_expiry - cur_time;
        !          2587: 
        !          2588:                putULong(state->expiry, (u_int32_t)offered_lease_time);
        !          2589:                i = DHO_DHCP_LEASE_TIME;
        !          2590:                oc = (struct option_cache *)0;
        !          2591:                if (option_cache_allocate (&oc, MDL)) {
        !          2592:                        if (make_const_data(&oc->expression, state->expiry,
        !          2593:                                            4, 0, 0, MDL)) {
        !          2594:                                option_code_hash_lookup(&oc->option,
        !          2595:                                                        dhcp_universe.code_hash,
        !          2596:                                                        &i, 0, MDL);
        !          2597:                                save_option (&dhcp_universe,
        !          2598:                                             state -> options, oc);
        !          2599:                        }
        !          2600:                        option_cache_dereference (&oc, MDL);
        !          2601:                }
        !          2602: 
        !          2603:                /* Renewal time is lease time * 0.5. */
        !          2604:                offered_lease_time /= 2;
        !          2605:                putULong(state->renewal, (u_int32_t)offered_lease_time);
        !          2606:                i = DHO_DHCP_RENEWAL_TIME;
        !          2607:                oc = (struct option_cache *)0;
        !          2608:                if (option_cache_allocate (&oc, MDL)) {
        !          2609:                        if (make_const_data(&oc->expression, state->renewal,
        !          2610:                                            4, 0, 0, MDL)) {
        !          2611:                                option_code_hash_lookup(&oc->option,
        !          2612:                                                        dhcp_universe.code_hash,
        !          2613:                                                        &i, 0, MDL);
        !          2614:                                save_option (&dhcp_universe,
        !          2615:                                             state -> options, oc);
        !          2616:                        }
        !          2617:                        option_cache_dereference (&oc, MDL);
        !          2618:                }
        !          2619: 
        !          2620:                /* Rebinding time is lease time * 0.875. */
        !          2621:                offered_lease_time += (offered_lease_time / 2
        !          2622:                                       + offered_lease_time / 4);
        !          2623:                putULong(state->rebind, (u_int32_t)offered_lease_time);
        !          2624:                i = DHO_DHCP_REBINDING_TIME;
        !          2625:                oc = (struct option_cache *)0;
        !          2626:                if (option_cache_allocate (&oc, MDL)) {
        !          2627:                        if (make_const_data(&oc->expression, state->rebind,
        !          2628:                                            4, 0, 0, MDL)) {
        !          2629:                                option_code_hash_lookup(&oc->option,
        !          2630:                                                        dhcp_universe.code_hash,
        !          2631:                                                        &i, 0, MDL);
        !          2632:                                save_option (&dhcp_universe,
        !          2633:                                             state -> options, oc);
        !          2634:                        }
        !          2635:                        option_cache_dereference (&oc, MDL);
        !          2636:                }
        !          2637:        } else {
        !          2638:                /* XXXSK: should we use get_server_source_address() here? */
        !          2639:                if (state -> ip -> address_count) {
        !          2640:                        state -> from.len =
        !          2641:                                sizeof state -> ip -> addresses [0];
        !          2642:                        memcpy (state -> from.iabuf,
        !          2643:                                &state -> ip -> addresses [0],
        !          2644:                                state -> from.len);
        !          2645:                }
        !          2646:        }
        !          2647: 
        !          2648:        /* Figure out the address of the boot file server. */
        !          2649:        memset (&state -> siaddr, 0, sizeof state -> siaddr);
        !          2650:        if ((oc =
        !          2651:             lookup_option (&server_universe,
        !          2652:                            state -> options, SV_NEXT_SERVER))) {
        !          2653:                if (evaluate_option_cache (&d1, packet, lease,
        !          2654:                                           (struct client_state *)0,
        !          2655:                                           packet -> options, state -> options,
        !          2656:                                           &lease -> scope, oc, MDL)) {
        !          2657:                        /* If there was more than one answer,
        !          2658:                           take the first. */
        !          2659:                        if (d1.len >= 4 && d1.data)
        !          2660:                                memcpy (&state -> siaddr, d1.data, 4);
        !          2661:                        data_string_forget (&d1, MDL);
        !          2662:                }
        !          2663:        }
        !          2664: 
        !          2665:        /* Use the subnet mask from the subnet declaration if no other
        !          2666:           mask has been provided. */
        !          2667:        i = DHO_SUBNET_MASK;
        !          2668:        if (!lookup_option (&dhcp_universe, state -> options, i)) {
        !          2669:                oc = (struct option_cache *)0;
        !          2670:                if (option_cache_allocate (&oc, MDL)) {
        !          2671:                        if (make_const_data (&oc -> expression,
        !          2672:                                             lease -> subnet -> netmask.iabuf,
        !          2673:                                             lease -> subnet -> netmask.len,
        !          2674:                                             0, 0, MDL)) {
        !          2675:                                option_code_hash_lookup(&oc->option,
        !          2676:                                                        dhcp_universe.code_hash,
        !          2677:                                                        &i, 0, MDL);
        !          2678:                                save_option (&dhcp_universe,
        !          2679:                                             state -> options, oc);
        !          2680:                        }
        !          2681:                        option_cache_dereference (&oc, MDL);
        !          2682:                }
        !          2683:        }
        !          2684: 
        !          2685:        /* Use the hostname from the host declaration if there is one
        !          2686:           and no hostname has otherwise been provided, and if the 
        !          2687:           use-host-decl-name flag is set. */
        !          2688:        i = DHO_HOST_NAME;
        !          2689:        j = SV_USE_HOST_DECL_NAMES;
        !          2690:        if (!lookup_option (&dhcp_universe, state -> options, i) &&
        !          2691:            lease -> host && lease -> host -> name &&
        !          2692:            (evaluate_boolean_option_cache
        !          2693:             (&ignorep, packet, lease, (struct client_state *)0,
        !          2694:              packet -> options, state -> options, &lease -> scope,
        !          2695:              lookup_option (&server_universe, state -> options, j), MDL))) {
        !          2696:                oc = (struct option_cache *)0;
        !          2697:                if (option_cache_allocate (&oc, MDL)) {
        !          2698:                        if (make_const_data (&oc -> expression,
        !          2699:                                             ((unsigned char *)
        !          2700:                                              lease -> host -> name),
        !          2701:                                             strlen (lease -> host -> name),
        !          2702:                                             1, 0, MDL)) {
        !          2703:                                option_code_hash_lookup(&oc->option,
        !          2704:                                                        dhcp_universe.code_hash,
        !          2705:                                                        &i, 0, MDL);
        !          2706:                                save_option (&dhcp_universe,
        !          2707:                                             state -> options, oc);
        !          2708:                        }
        !          2709:                        option_cache_dereference (&oc, MDL);
        !          2710:                }
        !          2711:        }
        !          2712: 
        !          2713:        /* If we don't have a hostname yet, and we've been asked to do
        !          2714:           a reverse lookup to find the hostname, do it. */
        !          2715:        i = DHO_HOST_NAME;
        !          2716:        j = SV_GET_LEASE_HOSTNAMES;
        !          2717:        if (!lookup_option(&dhcp_universe, state->options, i) &&
        !          2718:            evaluate_boolean_option_cache
        !          2719:             (&ignorep, packet, lease, NULL,
        !          2720:              packet->options, state->options, &lease->scope,
        !          2721:              lookup_option (&server_universe, state->options, j), MDL)) {
        !          2722:                struct in_addr ia;
        !          2723:                struct hostent *h;
        !          2724:                
        !          2725:                memcpy (&ia, lease -> ip_addr.iabuf, 4);
        !          2726:                
        !          2727:                h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
        !          2728:                if (!h)
        !          2729:                        log_error ("No hostname for %s", inet_ntoa (ia));
        !          2730:                else {
        !          2731:                        oc = (struct option_cache *)0;
        !          2732:                        if (option_cache_allocate (&oc, MDL)) {
        !          2733:                                if (make_const_data (&oc -> expression,
        !          2734:                                                     ((unsigned char *)
        !          2735:                                                      h -> h_name),
        !          2736:                                                     strlen (h -> h_name) + 1,
        !          2737:                                                     1, 1, MDL)) {
        !          2738:                                        option_code_hash_lookup(&oc->option,
        !          2739:                                                        dhcp_universe.code_hash,
        !          2740:                                                                &i, 0, MDL);
        !          2741:                                        save_option (&dhcp_universe,
        !          2742:                                                     state -> options, oc);
        !          2743:                                }
        !          2744:                                option_cache_dereference (&oc, MDL);
        !          2745:                        }
        !          2746:                }
        !          2747:        }
        !          2748: 
        !          2749:        /* If so directed, use the leased IP address as the router address.
        !          2750:           This supposedly makes Win95 machines ARP for all IP addresses,
        !          2751:           so if the local router does proxy arp, you win. */
        !          2752: 
        !          2753:        if (evaluate_boolean_option_cache
        !          2754:            (&ignorep, packet, lease, (struct client_state *)0,
        !          2755:             packet -> options, state -> options, &lease -> scope,
        !          2756:             lookup_option (&server_universe, state -> options,
        !          2757:                            SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE), MDL)) {
        !          2758:                i = DHO_ROUTERS;
        !          2759:                oc = lookup_option (&dhcp_universe, state -> options, i);
        !          2760:                if (!oc) {
        !          2761:                        oc = (struct option_cache *)0;
        !          2762:                        if (option_cache_allocate (&oc, MDL)) {
        !          2763:                                if (make_const_data (&oc -> expression,
        !          2764:                                                     lease -> ip_addr.iabuf,
        !          2765:                                                     lease -> ip_addr.len,
        !          2766:                                                     0, 0, MDL)) {
        !          2767:                                        option_code_hash_lookup(&oc->option,
        !          2768:                                                        dhcp_universe.code_hash,
        !          2769:                                                                &i, 0, MDL);
        !          2770:                                        save_option (&dhcp_universe,
        !          2771:                                                     state -> options, oc);
        !          2772:                                }
        !          2773:                                option_cache_dereference (&oc, MDL);    
        !          2774:                        }
        !          2775:                }
        !          2776:        }
        !          2777: 
        !          2778:        /* If a site option space has been specified, use that for
        !          2779:           site option codes. */
        !          2780:        i = SV_SITE_OPTION_SPACE;
        !          2781:        if ((oc = lookup_option (&server_universe, state -> options, i)) &&
        !          2782:            evaluate_option_cache (&d1, packet, lease,
        !          2783:                                   (struct client_state *)0,
        !          2784:                                   packet -> options, state -> options,
        !          2785:                                   &lease -> scope, oc, MDL)) {
        !          2786:                struct universe *u = (struct universe *)0;
        !          2787: 
        !          2788:                if (!universe_hash_lookup (&u, universe_hash,
        !          2789:                                           (const char *)d1.data, d1.len,
        !          2790:                                           MDL)) {
        !          2791:                        log_error ("unknown option space %s.", d1.data);
        !          2792:                        return;
        !          2793:                }
        !          2794: 
        !          2795:                state -> options -> site_universe = u -> index;
        !          2796:                state->options->site_code_min = find_min_site_code(u);
        !          2797:                data_string_forget (&d1, MDL);
        !          2798:        } else {
        !          2799:                state -> options -> site_code_min = 0;
        !          2800:                state -> options -> site_universe = dhcp_universe.index;
        !          2801:        }
        !          2802: 
        !          2803:        /* If the client has provided a list of options that it wishes
        !          2804:           returned, use it to prioritize.  If there's a parameter
        !          2805:           request list in scope, use that in preference.  Otherwise
        !          2806:           use the default priority list. */
        !          2807: 
        !          2808:        oc = lookup_option (&dhcp_universe, state -> options,
        !          2809:                            DHO_DHCP_PARAMETER_REQUEST_LIST);
        !          2810: 
        !          2811:        if (!oc)
        !          2812:                oc = lookup_option (&dhcp_universe, packet -> options,
        !          2813:                                    DHO_DHCP_PARAMETER_REQUEST_LIST);
        !          2814:        if (oc)
        !          2815:                evaluate_option_cache (&state -> parameter_request_list,
        !          2816:                                       packet, lease, (struct client_state *)0,
        !          2817:                                       packet -> options, state -> options,
        !          2818:                                       &lease -> scope, oc, MDL);
        !          2819: 
        !          2820: #ifdef DEBUG_PACKET
        !          2821:        dump_packet (packet);
        !          2822:        dump_raw ((unsigned char *)packet -> raw, packet -> packet_length);
        !          2823: #endif
        !          2824: 
        !          2825:        lease -> state = state;
        !          2826: 
        !          2827:        log_info ("%s", msg);
        !          2828: 
        !          2829:        /* Hang the packet off the lease state. */
        !          2830:        packet_reference (&lease -> state -> packet, packet, MDL);
        !          2831: 
        !          2832:        /* If this is a DHCPOFFER, ping the lease address before actually
        !          2833:           sending the offer. */
        !          2834:        if (offer == DHCPOFFER && !(lease -> flags & STATIC_LEASE) &&
        !          2835:            ((cur_time - lease_cltt) > 60) &&
        !          2836:            (!(oc = lookup_option (&server_universe, state -> options,
        !          2837:                                   SV_PING_CHECKS)) ||
        !          2838:             evaluate_boolean_option_cache (&ignorep, packet, lease,
        !          2839:                                            (struct client_state *)0,
        !          2840:                                            packet -> options,
        !          2841:                                            state -> options,
        !          2842:                                            &lease -> scope, oc, MDL))) {
        !          2843:                icmp_echorequest (&lease -> ip_addr);
        !          2844: 
        !          2845:                /* Determine whether to use configured or default ping timeout.
        !          2846:                 */
        !          2847:                if ((oc = lookup_option (&server_universe, state -> options,
        !          2848:                                                SV_PING_TIMEOUT)) &&
        !          2849:                    evaluate_option_cache (&d1, packet, lease, NULL,
        !          2850:                                                packet -> options,
        !          2851:                                                state -> options,
        !          2852:                                                &lease -> scope, oc, MDL)) {
        !          2853:                        if (d1.len == sizeof (u_int32_t))
        !          2854:                                ping_timeout = getULong (d1.data);
        !          2855:                        else
        !          2856:                                ping_timeout = DEFAULT_PING_TIMEOUT;
        !          2857: 
        !          2858:                        data_string_forget (&d1, MDL);
        !          2859:                } else
        !          2860:                        ping_timeout = DEFAULT_PING_TIMEOUT;
        !          2861: 
        !          2862: #ifdef DEBUG
        !          2863:                log_debug ("Ping timeout: %ld", (long)ping_timeout);
        !          2864: #endif
        !          2865: 
        !          2866:                /*
        !          2867:                 * Set a timeout for 'ping-timeout' seconds from NOW, including
        !          2868:                 * current microseconds.  As ping-timeout defaults to 1, the
        !          2869:                 * exclusion of current microseconds causes a value somewhere
        !          2870:                 * /between/ zero and one.
        !          2871:                 */
        !          2872:                tv.tv_sec = cur_tv.tv_sec + ping_timeout;
        !          2873:                tv.tv_usec = cur_tv.tv_usec;
        !          2874:                add_timeout (&tv, lease_ping_timeout, lease,
        !          2875:                             (tvref_t)lease_reference,
        !          2876:                             (tvunref_t)lease_dereference);
        !          2877:                ++outstanding_pings;
        !          2878:        } else {
        !          2879:                lease->cltt = cur_time;
        !          2880: #if defined(DELAYED_ACK)
        !          2881:                if (!(lease->flags & STATIC_LEASE) &&
        !          2882:                    (!offer || (offer == DHCPACK)))
        !          2883:                        delayed_ack_enqueue(lease);
        !          2884:                else 
        !          2885: #endif
        !          2886:                        dhcp_reply(lease);
        !          2887:        }
        !          2888: }
        !          2889: 
        !          2890: /* CC: queue single ACK:
        !          2891:    - write the lease (but do not fsync it yet)
        !          2892:    - add to double linked list
        !          2893:    - commit if more than xx ACKs pending
        !          2894:    - Not yet: schedule a fsync at the next interval (1 second?)
        !          2895:  */
        !          2896: 
        !          2897: void
        !          2898: delayed_ack_enqueue(struct lease *lease)
        !          2899: {
        !          2900:        struct leasequeue *q;
        !          2901: 
        !          2902:        if (!write_lease(lease)) 
        !          2903:                return;
        !          2904:        if (free_ackqueue) {
        !          2905:                q = free_ackqueue;
        !          2906:                free_ackqueue = q->next;
        !          2907:        } else {
        !          2908:                q = ((struct leasequeue *)
        !          2909:                             dmalloc(sizeof(struct leasequeue), MDL));
        !          2910:                if (!q)
        !          2911:                        log_fatal("delayed_ack_enqueue: no memory!");
        !          2912:        }
        !          2913:        memset(q, 0, sizeof *q);
        !          2914:        /* prepend to ackqueue*/
        !          2915:        lease_reference(&q->lease, lease, MDL);
        !          2916:        q->next = ackqueue_head;
        !          2917:        ackqueue_head = q;
        !          2918:        if (!ackqueue_tail) 
        !          2919:                ackqueue_tail = q;
        !          2920:        else
        !          2921:                q->next->prev = q;
        !          2922: 
        !          2923:        outstanding_acks++;
        !          2924:        if (outstanding_acks > max_outstanding_acks) 
        !          2925:                commit_leases();
        !          2926: 
        !          2927:        /* If next_fsync is not set, schedule an fsync. */
        !          2928:        if (next_fsync.tv_sec == 0 && next_fsync.tv_usec == 0) {
        !          2929:                next_fsync.tv_sec = cur_tv.tv_sec + max_ack_delay_secs;
        !          2930:                next_fsync.tv_usec = cur_tv.tv_usec + max_ack_delay_usecs;
        !          2931: 
        !          2932:                if (next_fsync.tv_usec >= 1000000) {
        !          2933:                        next_fsync.tv_sec++;
        !          2934:                        next_fsync.tv_usec -= 1000000;
        !          2935:                }
        !          2936: 
        !          2937:                add_timeout(&next_fsync, commit_leases_ackout, NULL,
        !          2938:                            (tvref_t) NULL, (tvunref_t) NULL);
        !          2939:        }
        !          2940: }
        !          2941: 
        !          2942: void
        !          2943: commit_leases_readerdry(void *foo) 
        !          2944: {
        !          2945:        if (outstanding_acks) {
        !          2946:                commit_leases();
        !          2947: 
        !          2948:                /* Reset next_fsync and cancel any pending timeout. */
        !          2949:                memset(&next_fsync, 0, sizeof(next_fsync));
        !          2950:                cancel_timeout(commit_leases_ackout, NULL);
        !          2951:        }
        !          2952: }
        !          2953: 
        !          2954: static void
        !          2955: commit_leases_ackout(void *foo)
        !          2956: {
        !          2957:        if (outstanding_acks) {
        !          2958:                commit_leases();
        !          2959: 
        !          2960:                memset(&next_fsync, 0, sizeof(next_fsync));
        !          2961:        }
        !          2962: }
        !          2963: 
        !          2964: /* CC: process the delayed ACK responses:
        !          2965:    - send out the ACK packets
        !          2966:    - move the queue slots to the free list
        !          2967:  */
        !          2968: void
        !          2969: flush_ackqueue(void *foo) 
        !          2970: {
        !          2971:        struct leasequeue *ack, *p;
        !          2972:        /*  process from bottom to retain packet order */
        !          2973:        for (ack = ackqueue_tail ; ack ; ack = p) { 
        !          2974:                p = ack->prev;
        !          2975: 
        !          2976:                /* dhcp_reply() requires that the reply state still be valid */
        !          2977:                if (ack->lease->state == NULL)
        !          2978:                        log_error("delayed ack for %s has gone stale",
        !          2979:                                  piaddr(ack->lease->ip_addr));
        !          2980:                else
        !          2981:                        dhcp_reply(ack->lease);
        !          2982: 
        !          2983:                lease_dereference(&ack->lease, MDL);
        !          2984:                ack->next = free_ackqueue;
        !          2985:                free_ackqueue = ack;
        !          2986:        }
        !          2987:        ackqueue_head = NULL;
        !          2988:        ackqueue_tail = NULL;
        !          2989:        outstanding_acks = 0;
        !          2990: }
        !          2991: 
        !          2992: #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
        !          2993: void
        !          2994: relinquish_ackqueue(void)
        !          2995: {
        !          2996:        struct leasequeue *q, *n;
        !          2997:        
        !          2998:        for (q = ackqueue_head ; q ; q = n) {
        !          2999:                n = q->next;
        !          3000:                dfree(q, MDL);
        !          3001:        }
        !          3002:        for (q = free_ackqueue ; q ; q = n) {
        !          3003:                n = q->next;
        !          3004:                dfree(q, MDL);
        !          3005:        }
        !          3006: }
        !          3007: #endif
        !          3008: 
        !          3009: void dhcp_reply (lease)
        !          3010:        struct lease *lease;
        !          3011: {
        !          3012:        int bufs = 0;
        !          3013:        unsigned packet_length;
        !          3014:        struct dhcp_packet raw;
        !          3015:        struct sockaddr_in to;
        !          3016:        struct in_addr from;
        !          3017:        struct hardware hto;
        !          3018:        int result;
        !          3019:        struct lease_state *state = lease -> state;
        !          3020:        int nulltp, bootpp, unicastp = 1;
        !          3021:        struct data_string d1;
        !          3022:        const char *s;
        !          3023: 
        !          3024:        if (!state)
        !          3025:                log_fatal ("dhcp_reply was supplied lease with no state!");
        !          3026: 
        !          3027:        /* Compose a response for the client... */
        !          3028:        memset (&raw, 0, sizeof raw);
        !          3029:        memset (&d1, 0, sizeof d1);
        !          3030: 
        !          3031:        /* Copy in the filename if given; otherwise, flag the filename
        !          3032:           buffer as available for options. */
        !          3033:        if (state -> filename.len && state -> filename.data) {
        !          3034:                memcpy (raw.file,
        !          3035:                        state -> filename.data,
        !          3036:                        state -> filename.len > sizeof raw.file
        !          3037:                        ? sizeof raw.file : state -> filename.len);
        !          3038:                if (sizeof raw.file > state -> filename.len)
        !          3039:                        memset (&raw.file [state -> filename.len], 0,
        !          3040:                                (sizeof raw.file) - state -> filename.len);
        !          3041:                else 
        !          3042:                        log_info("file name longer than packet field "
        !          3043:                                 "truncated - field: %lu name: %d %.*s", 
        !          3044:                                 (unsigned long)sizeof(raw.file),
        !          3045:                                 state->filename.len, state->filename.len,
        !          3046:                                 state->filename.data);
        !          3047:        } else
        !          3048:                bufs |= 1;
        !          3049: 
        !          3050:        /* Copy in the server name if given; otherwise, flag the
        !          3051:           server_name buffer as available for options. */
        !          3052:        if (state -> server_name.len && state -> server_name.data) {
        !          3053:                memcpy (raw.sname,
        !          3054:                        state -> server_name.data,
        !          3055:                        state -> server_name.len > sizeof raw.sname
        !          3056:                        ? sizeof raw.sname : state -> server_name.len);
        !          3057:                if (sizeof raw.sname > state -> server_name.len)
        !          3058:                        memset (&raw.sname [state -> server_name.len], 0,
        !          3059:                                (sizeof raw.sname) - state -> server_name.len);
        !          3060:                else 
        !          3061:                        log_info("server name longer than packet field "
        !          3062:                                 "truncated - field: %lu name: %d %.*s", 
        !          3063:                                 (unsigned long)sizeof(raw.sname),
        !          3064:                                 state->server_name.len,
        !          3065:                                 state->server_name.len,
        !          3066:                                 state->server_name.data);
        !          3067:        } else
        !          3068:                bufs |= 2; /* XXX */
        !          3069: 
        !          3070:        memcpy (raw.chaddr,
        !          3071:                &lease -> hardware_addr.hbuf [1], sizeof raw.chaddr);
        !          3072:        raw.hlen = lease -> hardware_addr.hlen - 1;
        !          3073:        raw.htype = lease -> hardware_addr.hbuf [0];
        !          3074: 
        !          3075:        /* See if this is a Microsoft client that NUL-terminates its
        !          3076:           strings and expects us to do likewise... */
        !          3077:        if (lease -> flags & MS_NULL_TERMINATION)
        !          3078:                nulltp = 1;
        !          3079:        else
        !          3080:                nulltp = 0;
        !          3081: 
        !          3082:        /* See if this is a bootp client... */
        !          3083:        if (state -> offer)
        !          3084:                bootpp = 0;
        !          3085:        else
        !          3086:                bootpp = 1;
        !          3087: 
        !          3088:        /* Insert such options as will fit into the buffer. */
        !          3089:        packet_length = cons_options (state -> packet, &raw, lease,
        !          3090:                                      (struct client_state *)0,
        !          3091:                                      state -> max_message_size,
        !          3092:                                      state -> packet -> options,
        !          3093:                                      state -> options, &global_scope,
        !          3094:                                      bufs, nulltp, bootpp,
        !          3095:                                      &state -> parameter_request_list,
        !          3096:                                      (char *)0);
        !          3097: 
        !          3098:        memcpy (&raw.ciaddr, &state -> ciaddr, sizeof raw.ciaddr);
        !          3099:        memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
        !          3100:        raw.siaddr = state -> siaddr;
        !          3101:        raw.giaddr = state -> giaddr;
        !          3102: 
        !          3103:        raw.xid = state -> xid;
        !          3104:        raw.secs = state -> secs;
        !          3105:        raw.flags = state -> bootp_flags;
        !          3106:        raw.hops = state -> hops;
        !          3107:        raw.op = BOOTREPLY;
        !          3108: 
        !          3109:        if (lease -> client_hostname) {
        !          3110:                if ((strlen (lease -> client_hostname) <= 64) &&
        !          3111:                    db_printable((unsigned char *)lease->client_hostname))
        !          3112:                        s = lease -> client_hostname;
        !          3113:                else
        !          3114:                        s = "Hostname Unsuitable for Printing";
        !          3115:        } else
        !          3116:                s = (char *)0;
        !          3117: 
        !          3118:        /* Say what we're doing... */
        !          3119:        log_info ("%s on %s to %s %s%s%svia %s",
        !          3120:                  (state -> offer
        !          3121:                   ? (state -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER")
        !          3122:                   : "BOOTREPLY"),
        !          3123:                  piaddr (lease -> ip_addr),
        !          3124:                  (lease -> hardware_addr.hlen
        !          3125:                   ? print_hw_addr (lease -> hardware_addr.hbuf [0],
        !          3126:                                    lease -> hardware_addr.hlen - 1,
        !          3127:                                    &lease -> hardware_addr.hbuf [1])
        !          3128:                   : print_hex_1(lease->uid_len, lease->uid, 60)),
        !          3129:                  s ? "(" : "", s ? s : "", s ? ") " : "",
        !          3130:                  (state -> giaddr.s_addr
        !          3131:                   ? inet_ntoa (state -> giaddr)
        !          3132:                   : state -> ip -> name));
        !          3133: 
        !          3134:        /* Set up the hardware address... */
        !          3135:        hto.hlen = lease -> hardware_addr.hlen;
        !          3136:        memcpy (hto.hbuf, lease -> hardware_addr.hbuf, hto.hlen);
        !          3137: 
        !          3138:        to.sin_family = AF_INET;
        !          3139: #ifdef HAVE_SA_LEN
        !          3140:        to.sin_len = sizeof to;
        !          3141: #endif
        !          3142:        memset (to.sin_zero, 0, sizeof to.sin_zero);
        !          3143: 
        !          3144: #ifdef DEBUG_PACKET
        !          3145:        dump_raw ((unsigned char *)&raw, packet_length);
        !          3146: #endif
        !          3147: 
        !          3148:        /* Make sure outgoing packets are at least as big
        !          3149:           as a BOOTP packet. */
        !          3150:        if (packet_length < BOOTP_MIN_LEN)
        !          3151:                packet_length = BOOTP_MIN_LEN;
        !          3152: 
        !          3153:        /* If this was gatewayed, send it back to the gateway... */
        !          3154:        if (raw.giaddr.s_addr) {
        !          3155:                to.sin_addr = raw.giaddr;
        !          3156:                if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
        !          3157:                        to.sin_port = local_port;
        !          3158:                else
        !          3159:                        to.sin_port = remote_port; /* For debugging. */
        !          3160: 
        !          3161:                if (fallback_interface) {
        !          3162:                        result = send_packet (fallback_interface,
        !          3163:                                              (struct packet *)0,
        !          3164:                                              &raw, packet_length,
        !          3165:                                              raw.siaddr, &to,
        !          3166:                                              (struct hardware *)0);
        !          3167: 
        !          3168:                        free_lease_state (state, MDL);
        !          3169:                        lease -> state = (struct lease_state *)0;
        !          3170:                        return;
        !          3171:                }
        !          3172: 
        !          3173:        /* If the client is RENEWING, unicast to the client using the
        !          3174:           regular IP stack.  Some clients, particularly those that
        !          3175:           follow RFC1541, are buggy, and send both ciaddr and server
        !          3176:           identifier.  We deal with this situation by assuming that
        !          3177:           if we got both dhcp-server-identifier and ciaddr, and
        !          3178:           giaddr was not set, then the client is on the local
        !          3179:           network, and we can therefore unicast or broadcast to it
        !          3180:           successfully.  A client in REQUESTING state on another
        !          3181:           network that's making this mistake will have set giaddr,
        !          3182:           and will therefore get a relayed response from the above
        !          3183:           code. */
        !          3184:        } else if (raw.ciaddr.s_addr &&
        !          3185:                   !((state -> got_server_identifier ||
        !          3186:                      (raw.flags & htons (BOOTP_BROADCAST))) &&
        !          3187:                     /* XXX This won't work if giaddr isn't zero, but it is: */
        !          3188:                     (state -> shared_network ==
        !          3189:                      lease -> subnet -> shared_network)) &&
        !          3190:                   state -> offer == DHCPACK) {
        !          3191:                to.sin_addr = raw.ciaddr;
        !          3192:                to.sin_port = remote_port;
        !          3193: 
        !          3194:                if (fallback_interface) {
        !          3195:                        result = send_packet (fallback_interface,
        !          3196:                                              (struct packet *)0,
        !          3197:                                              &raw, packet_length,
        !          3198:                                              raw.siaddr, &to,
        !          3199:                                              (struct hardware *)0);
        !          3200:                        free_lease_state (state, MDL);
        !          3201:                        lease -> state = (struct lease_state *)0;
        !          3202:                        return;
        !          3203:                }
        !          3204: 
        !          3205:        /* If it comes from a client that already knows its address
        !          3206:           and is not requesting a broadcast response, and we can
        !          3207:           unicast to a client without using the ARP protocol, sent it
        !          3208:           directly to that client. */
        !          3209:        } else if (!(raw.flags & htons (BOOTP_BROADCAST)) &&
        !          3210:                   can_unicast_without_arp (state -> ip)) {
        !          3211:                to.sin_addr = raw.yiaddr;
        !          3212:                to.sin_port = remote_port;
        !          3213: 
        !          3214:        /* Otherwise, broadcast it on the local network. */
        !          3215:        } else {
        !          3216:                to.sin_addr = limited_broadcast;
        !          3217:                to.sin_port = remote_port;
        !          3218:                if (!(lease -> flags & UNICAST_BROADCAST_HACK))
        !          3219:                        unicastp = 0;
        !          3220:        }
        !          3221: 
        !          3222:        memcpy (&from, state -> from.iabuf, sizeof from);
        !          3223: 
        !          3224:        result = send_packet (state -> ip,
        !          3225:                              (struct packet *)0, &raw, packet_length,
        !          3226:                              from, &to,
        !          3227:                              unicastp ? &hto : (struct hardware *)0);
        !          3228: 
        !          3229:        /* Free all of the entries in the option_state structure
        !          3230:           now that we're done with them. */
        !          3231: 
        !          3232:        free_lease_state (state, MDL);
        !          3233:        lease -> state = (struct lease_state *)0;
        !          3234: }
        !          3235: 
        !          3236: int find_lease (struct lease **lp,
        !          3237:                struct packet *packet, struct shared_network *share, int *ours,
        !          3238:                int *peer_has_leases, struct lease *ip_lease_in,
        !          3239:                const char *file, int line)
        !          3240: {
        !          3241:        struct lease *uid_lease = (struct lease *)0;
        !          3242:        struct lease *ip_lease = (struct lease *)0;
        !          3243:        struct lease *hw_lease = (struct lease *)0;
        !          3244:        struct lease *lease = (struct lease *)0;
        !          3245:        struct iaddr cip;
        !          3246:        struct host_decl *hp = (struct host_decl *)0;
        !          3247:        struct host_decl *host = (struct host_decl *)0;
        !          3248:        struct lease *fixed_lease = (struct lease *)0;
        !          3249:        struct lease *next = (struct lease *)0;
        !          3250:        struct option_cache *oc;
        !          3251:        struct data_string d1;
        !          3252:        int have_client_identifier = 0;
        !          3253:        struct data_string client_identifier;
        !          3254:        struct hardware h;
        !          3255: 
        !          3256: #if defined(FAILOVER_PROTOCOL)
        !          3257:        /* Quick check to see if the peer has leases. */
        !          3258:        if (peer_has_leases) {
        !          3259:                struct pool *pool;
        !          3260: 
        !          3261:                for (pool = share->pools ; pool ; pool = pool->next) {
        !          3262:                        dhcp_failover_state_t *peer = pool->failover_peer;
        !          3263: 
        !          3264:                        if (peer &&
        !          3265:                            ((peer->i_am == primary && pool->backup_leases) ||
        !          3266:                             (peer->i_am == secondary && pool->free_leases))) {
        !          3267:                                *peer_has_leases = 1;
        !          3268:                                break;
        !          3269:                        }
        !          3270:                }
        !          3271:        }
        !          3272: #endif /* FAILOVER_PROTOCOL */
        !          3273: 
        !          3274:        if (packet -> raw -> ciaddr.s_addr) {
        !          3275:                cip.len = 4;
        !          3276:                memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
        !          3277:        } else {
        !          3278:                /* Look up the requested address. */
        !          3279:                oc = lookup_option (&dhcp_universe, packet -> options,
        !          3280:                                    DHO_DHCP_REQUESTED_ADDRESS);
        !          3281:                memset (&d1, 0, sizeof d1);
        !          3282:                if (oc &&
        !          3283:                    evaluate_option_cache (&d1, packet, (struct lease *)0,
        !          3284:                                           (struct client_state *)0,
        !          3285:                                           packet -> options,
        !          3286:                                           (struct option_state *)0,
        !          3287:                                           &global_scope, oc, MDL)) {
        !          3288:                        packet -> got_requested_address = 1;
        !          3289:                        cip.len = 4;
        !          3290:                        memcpy (cip.iabuf, d1.data, cip.len);
        !          3291:                        data_string_forget (&d1, MDL);
        !          3292:                } else 
        !          3293:                        cip.len = 0;
        !          3294:        }
        !          3295: 
        !          3296:        /* Try to find a host or lease that's been assigned to the
        !          3297:           specified unique client identifier. */
        !          3298:        oc = lookup_option (&dhcp_universe, packet -> options,
        !          3299:                            DHO_DHCP_CLIENT_IDENTIFIER);
        !          3300:        memset (&client_identifier, 0, sizeof client_identifier);
        !          3301:        if (oc &&
        !          3302:            evaluate_option_cache (&client_identifier,
        !          3303:                                   packet, (struct lease *)0,
        !          3304:                                   (struct client_state *)0,
        !          3305:                                   packet -> options, (struct option_state *)0,
        !          3306:                                   &global_scope, oc, MDL)) {
        !          3307:                /* Remember this for later. */
        !          3308:                have_client_identifier = 1;
        !          3309: 
        !          3310:                /* First, try to find a fixed host entry for the specified
        !          3311:                   client identifier... */
        !          3312:                if (find_hosts_by_uid (&hp, client_identifier.data,
        !          3313:                                       client_identifier.len, MDL)) {
        !          3314:                        /* Remember if we know of this client. */
        !          3315:                        packet -> known = 1;
        !          3316:                        mockup_lease (&fixed_lease, packet, share, hp);
        !          3317:                }
        !          3318: 
        !          3319: #if defined (DEBUG_FIND_LEASE)
        !          3320:                if (fixed_lease) {
        !          3321:                        log_info ("Found host for client identifier: %s.",
        !          3322:                              piaddr (fixed_lease -> ip_addr));
        !          3323:                }
        !          3324: #endif
        !          3325:                if (hp) {
        !          3326:                        if (!fixed_lease) /* Save the host if we found one. */
        !          3327:                                host_reference (&host, hp, MDL);
        !          3328:                        host_dereference (&hp, MDL);
        !          3329:                }
        !          3330: 
        !          3331:                find_lease_by_uid (&uid_lease, client_identifier.data,
        !          3332:                                   client_identifier.len, MDL);
        !          3333:        }
        !          3334: 
        !          3335:        /* If we didn't find a fixed lease using the uid, try doing
        !          3336:           it with the hardware address... */
        !          3337:        if (!fixed_lease && !host) {
        !          3338:                if (find_hosts_by_haddr (&hp, packet -> raw -> htype,
        !          3339:                                         packet -> raw -> chaddr,
        !          3340:                                         packet -> raw -> hlen, MDL)) {
        !          3341:                        /* Remember if we know of this client. */
        !          3342:                        packet -> known = 1;
        !          3343:                        if (host)
        !          3344:                                host_dereference (&host, MDL);
        !          3345:                        host_reference (&host, hp, MDL);
        !          3346:                        host_dereference (&hp, MDL);
        !          3347:                        mockup_lease (&fixed_lease, packet, share, host);
        !          3348: #if defined (DEBUG_FIND_LEASE)
        !          3349:                        if (fixed_lease) {
        !          3350:                                log_info ("Found host for link address: %s.",
        !          3351:                                      piaddr (fixed_lease -> ip_addr));
        !          3352:                        }
        !          3353: #endif
        !          3354:                }
        !          3355:        }
        !          3356: 
        !          3357:        /* If fixed_lease is present but does not match the requested
        !          3358:           IP address, and this is a DHCPREQUEST, then we can't return
        !          3359:           any other lease, so we might as well return now. */
        !          3360:        if (packet -> packet_type == DHCPREQUEST && fixed_lease &&
        !          3361:            (fixed_lease -> ip_addr.len != cip.len ||
        !          3362:             memcmp (fixed_lease -> ip_addr.iabuf,
        !          3363:                     cip.iabuf, cip.len))) {
        !          3364:                if (ours)
        !          3365:                        *ours = 1;
        !          3366:                strcpy (dhcp_message, "requested address is incorrect");
        !          3367: #if defined (DEBUG_FIND_LEASE)
        !          3368:                log_info ("Client's fixed-address %s doesn't match %s%s",
        !          3369:                          piaddr (fixed_lease -> ip_addr), "request ",
        !          3370:                          print_dotted_quads (cip.len, cip.iabuf));
        !          3371: #endif
        !          3372:                goto out;
        !          3373:        }
        !          3374: 
        !          3375:        /* If we found leases matching the client identifier, loop through
        !          3376:         * the n_uid pointer looking for one that's actually valid.   We
        !          3377:         * can't do this until we get here because we depend on
        !          3378:         * packet -> known, which may be set by either the uid host
        !          3379:         * lookup or the haddr host lookup.
        !          3380:         *
        !          3381:         * Note that the n_uid lease chain is sorted in order of
        !          3382:         * preference, so the first one is the best one.
        !          3383:         */
        !          3384:        while (uid_lease) {
        !          3385: #if defined (DEBUG_FIND_LEASE)
        !          3386:                log_info ("trying next lease matching client id: %s",
        !          3387:                          piaddr (uid_lease -> ip_addr));
        !          3388: #endif
        !          3389: 
        !          3390: #if defined (FAILOVER_PROTOCOL)
        !          3391:                /* When failover is active, it's possible that there could
        !          3392:                   be two "free" leases for the same uid, but only one of
        !          3393:                   them that's available for this failover peer to allocate. */
        !          3394:                if (uid_lease -> binding_state != FTS_ACTIVE &&
        !          3395:                    !lease_mine_to_reallocate (uid_lease)) {
        !          3396: #if defined (DEBUG_FIND_LEASE)
        !          3397:                        log_info ("not mine to allocate: %s",
        !          3398:                                  piaddr (uid_lease -> ip_addr));
        !          3399: #endif
        !          3400:                        goto n_uid;
        !          3401:                }
        !          3402: #endif
        !          3403: 
        !          3404:                if (uid_lease -> subnet -> shared_network != share) {
        !          3405: #if defined (DEBUG_FIND_LEASE)
        !          3406:                        log_info ("wrong network segment: %s",
        !          3407:                                  piaddr (uid_lease -> ip_addr));
        !          3408: #endif
        !          3409:                        goto n_uid;
        !          3410:                }
        !          3411: 
        !          3412:                if ((uid_lease -> pool -> prohibit_list &&
        !          3413:                     permitted (packet, uid_lease -> pool -> prohibit_list)) ||
        !          3414:                    (uid_lease -> pool -> permit_list &&
        !          3415:                     !permitted (packet, uid_lease -> pool -> permit_list))) {
        !          3416: #if defined (DEBUG_FIND_LEASE)
        !          3417:                        log_info ("not permitted: %s",
        !          3418:                                  piaddr (uid_lease -> ip_addr));
        !          3419: #endif
        !          3420:                       n_uid:
        !          3421:                        if (uid_lease -> n_uid)
        !          3422:                                lease_reference (&next,
        !          3423:                                                 uid_lease -> n_uid, MDL);
        !          3424:                        if (!packet -> raw -> ciaddr.s_addr)
        !          3425:                                release_lease (uid_lease, packet);
        !          3426:                        lease_dereference (&uid_lease, MDL);
        !          3427:                        if (next) {
        !          3428:                                lease_reference (&uid_lease, next, MDL);
        !          3429:                                lease_dereference (&next, MDL);
        !          3430:                        }
        !          3431:                        continue;
        !          3432:                }
        !          3433:                break;
        !          3434:        }
        !          3435: #if defined (DEBUG_FIND_LEASE)
        !          3436:        if (uid_lease)
        !          3437:                log_info ("Found lease for client id: %s.",
        !          3438:                      piaddr (uid_lease -> ip_addr));
        !          3439: #endif
        !          3440: 
        !          3441:        /* Find a lease whose hardware address matches, whose client
        !          3442:         * identifier matches (or equally doesn't have one), that's
        !          3443:         * permitted, and that's on the correct subnet.
        !          3444:         *
        !          3445:         * Note that the n_hw chain is sorted in order of preference, so
        !          3446:         * the first one found is the best one.
        !          3447:         */
        !          3448:        h.hlen = packet -> raw -> hlen + 1;
        !          3449:        h.hbuf [0] = packet -> raw -> htype;
        !          3450:        memcpy (&h.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
        !          3451:        find_lease_by_hw_addr (&hw_lease, h.hbuf, h.hlen, MDL);
        !          3452:        while (hw_lease) {
        !          3453: #if defined (DEBUG_FIND_LEASE)
        !          3454:                log_info ("trying next lease matching hw addr: %s",
        !          3455:                          piaddr (hw_lease -> ip_addr));
        !          3456: #endif
        !          3457: #if defined (FAILOVER_PROTOCOL)
        !          3458:                /* When failover is active, it's possible that there could
        !          3459:                   be two "free" leases for the same uid, but only one of
        !          3460:                   them that's available for this failover peer to allocate. */
        !          3461:                if (hw_lease -> binding_state != FTS_ACTIVE &&
        !          3462:                    !lease_mine_to_reallocate (hw_lease)) {
        !          3463: #if defined (DEBUG_FIND_LEASE)
        !          3464:                        log_info ("not mine to allocate: %s",
        !          3465:                                  piaddr (hw_lease -> ip_addr));
        !          3466: #endif
        !          3467:                        goto n_hw;
        !          3468:                }
        !          3469: #endif
        !          3470: 
        !          3471:                if (hw_lease -> binding_state != FTS_FREE &&
        !          3472:                    hw_lease -> binding_state != FTS_BACKUP &&
        !          3473:                    hw_lease -> uid &&
        !          3474:                    (!have_client_identifier ||
        !          3475:                     hw_lease -> uid_len != client_identifier.len ||
        !          3476:                     memcmp (hw_lease -> uid, client_identifier.data,
        !          3477:                             hw_lease -> uid_len))) {
        !          3478: #if defined (DEBUG_FIND_LEASE)
        !          3479:                        log_info ("wrong client identifier: %s",
        !          3480:                                  piaddr (hw_lease -> ip_addr));
        !          3481: #endif
        !          3482:                        goto n_hw;
        !          3483:                }
        !          3484:                if (hw_lease -> subnet -> shared_network != share) {
        !          3485: #if defined (DEBUG_FIND_LEASE)
        !          3486:                        log_info ("wrong network segment: %s",
        !          3487:                                  piaddr (hw_lease -> ip_addr));
        !          3488: #endif
        !          3489:                        goto n_hw;
        !          3490:                }
        !          3491:                if ((hw_lease -> pool -> prohibit_list &&
        !          3492:                      permitted (packet, hw_lease -> pool -> prohibit_list)) ||
        !          3493:                    (hw_lease -> pool -> permit_list &&
        !          3494:                     !permitted (packet, hw_lease -> pool -> permit_list))) {
        !          3495: #if defined (DEBUG_FIND_LEASE)
        !          3496:                        log_info ("not permitted: %s",
        !          3497:                                  piaddr (hw_lease -> ip_addr));
        !          3498: #endif
        !          3499:                        if (!packet -> raw -> ciaddr.s_addr)
        !          3500:                                release_lease (hw_lease, packet);
        !          3501:                       n_hw:
        !          3502:                        if (hw_lease -> n_hw)
        !          3503:                                lease_reference (&next, hw_lease -> n_hw, MDL);
        !          3504:                        lease_dereference (&hw_lease, MDL);
        !          3505:                        if (next) {
        !          3506:                                lease_reference (&hw_lease, next, MDL);
        !          3507:                                lease_dereference (&next, MDL);
        !          3508:                        }
        !          3509:                        continue;
        !          3510:                }
        !          3511:                break;
        !          3512:        }
        !          3513: #if defined (DEBUG_FIND_LEASE)
        !          3514:        if (hw_lease)
        !          3515:                log_info ("Found lease for hardware address: %s.",
        !          3516:                      piaddr (hw_lease -> ip_addr));
        !          3517: #endif
        !          3518: 
        !          3519:        /* Try to find a lease that's been allocated to the client's
        !          3520:           IP address. */
        !          3521:        if (ip_lease_in)
        !          3522:                lease_reference (&ip_lease, ip_lease_in, MDL);
        !          3523:        else if (cip.len)
        !          3524:                find_lease_by_ip_addr (&ip_lease, cip, MDL);
        !          3525: 
        !          3526: #if defined (DEBUG_FIND_LEASE)
        !          3527:        if (ip_lease)
        !          3528:                log_info ("Found lease for requested address: %s.",
        !          3529:                      piaddr (ip_lease -> ip_addr));
        !          3530: #endif
        !          3531: 
        !          3532:        /* If ip_lease is valid at this point, set ours to one, so that
        !          3533:           even if we choose a different lease, we know that the address
        !          3534:           the client was requesting was ours, and thus we can NAK it. */
        !          3535:        if (ip_lease && ours)
        !          3536:                *ours = 1;
        !          3537: 
        !          3538:        /* If the requested IP address isn't on the network the packet
        !          3539:           came from, don't use it.  Allow abandoned leases to be matched
        !          3540:           here - if the client is requesting it, there's a decent chance
        !          3541:           that it's because the lease database got trashed and a client
        !          3542:           that thought it had this lease answered an ARP or PING, causing the
        !          3543:           lease to be abandoned.   If so, this request probably came from
        !          3544:           that client. */
        !          3545:        if (ip_lease && (ip_lease -> subnet -> shared_network != share)) {
        !          3546:                if (ours)
        !          3547:                        *ours = 1;
        !          3548: #if defined (DEBUG_FIND_LEASE)
        !          3549:                log_info ("...but it was on the wrong shared network.");
        !          3550: #endif
        !          3551:                strcpy (dhcp_message, "requested address on bad subnet");
        !          3552:                lease_dereference (&ip_lease, MDL);
        !          3553:        }
        !          3554: 
        !          3555:        /* Toss ip_lease if it hasn't yet expired and doesn't belong to the
        !          3556:           client. */
        !          3557:        if (ip_lease &&
        !          3558:            (ip_lease -> uid ?
        !          3559:             (!have_client_identifier ||
        !          3560:              ip_lease -> uid_len != client_identifier.len ||
        !          3561:              memcmp (ip_lease -> uid, client_identifier.data,
        !          3562:                      ip_lease -> uid_len)) :
        !          3563:             (ip_lease -> hardware_addr.hbuf [0] != packet -> raw -> htype ||
        !          3564:              ip_lease -> hardware_addr.hlen != packet -> raw -> hlen + 1 ||
        !          3565:              memcmp (&ip_lease -> hardware_addr.hbuf [1],
        !          3566:                      packet -> raw -> chaddr,
        !          3567:                      (unsigned)(ip_lease -> hardware_addr.hlen - 1))))) {
        !          3568:                /* If we're not doing failover, the only state in which
        !          3569:                   we can allocate this lease to the client is FTS_FREE.
        !          3570:                   If we are doing failover, things are more complicated.
        !          3571:                   If the lease is free or backup, we let the caller decide
        !          3572:                   whether or not to give it out. */
        !          3573:                if (ip_lease -> binding_state != FTS_FREE &&
        !          3574:                    ip_lease -> binding_state != FTS_BACKUP) {
        !          3575: #if defined (DEBUG_FIND_LEASE)
        !          3576:                        log_info ("rejecting lease for requested address.");
        !          3577: #endif
        !          3578:                        /* If we're rejecting it because the peer has
        !          3579:                           it, don't set "ours", because we shouldn't NAK. */
        !          3580:                        if (ours && ip_lease -> binding_state != FTS_ACTIVE)
        !          3581:                                *ours = 0;
        !          3582:                        lease_dereference (&ip_lease, MDL);
        !          3583:                }
        !          3584:        }
        !          3585: 
        !          3586:        /* If we got an ip_lease and a uid_lease or hw_lease, and ip_lease
        !          3587:           is not active, and is not ours to reallocate, forget about it. */
        !          3588:        if (ip_lease && (uid_lease || hw_lease) &&
        !          3589:            ip_lease -> binding_state != FTS_ACTIVE &&
        !          3590: #if defined(FAILOVER_PROTOCOL)
        !          3591:            !lease_mine_to_reallocate (ip_lease) &&
        !          3592: #endif
        !          3593:            packet -> packet_type == DHCPDISCOVER) {
        !          3594: #if defined (DEBUG_FIND_LEASE)
        !          3595:                log_info ("ip lease not ours to offer.");
        !          3596: #endif
        !          3597:                lease_dereference (&ip_lease, MDL);
        !          3598:        }
        !          3599: 
        !          3600:        /* If for some reason the client has more than one lease
        !          3601:           on the subnet that matches its uid, pick the one that
        !          3602:           it asked for and (if we can) free the other. */
        !          3603:        if (ip_lease && ip_lease->binding_state == FTS_ACTIVE &&
        !          3604:            ip_lease->uid && ip_lease != uid_lease) {
        !          3605:                if (have_client_identifier &&
        !          3606:                    (ip_lease -> uid_len == client_identifier.len) &&
        !          3607:                    !memcmp (client_identifier.data,
        !          3608:                             ip_lease -> uid, ip_lease -> uid_len)) {
        !          3609:                        if (uid_lease) {
        !          3610:                            if (uid_lease->binding_state == FTS_ACTIVE) {
        !          3611:                                log_error ("client %s has duplicate%s on %s",
        !          3612:                                           (print_hw_addr
        !          3613:                                            (packet -> raw -> htype,
        !          3614:                                             packet -> raw -> hlen,
        !          3615:                                             packet -> raw -> chaddr)),
        !          3616:                                           " leases",
        !          3617:                                           (ip_lease -> subnet ->
        !          3618:                                            shared_network -> name));
        !          3619: 
        !          3620:                                /* If the client is REQUESTing the lease,
        !          3621:                                   it shouldn't still be using the old
        !          3622:                                   one, so we can free it for allocation. */
        !          3623:                                if (uid_lease &&
        !          3624:                                    uid_lease->binding_state == FTS_ACTIVE &&
        !          3625:                                    !packet -> raw -> ciaddr.s_addr &&
        !          3626:                                    (share ==
        !          3627:                                     uid_lease -> subnet -> shared_network) &&
        !          3628:                                    packet -> packet_type == DHCPREQUEST)
        !          3629:                                        release_lease (uid_lease, packet);
        !          3630:                            }
        !          3631:                            lease_dereference (&uid_lease, MDL);
        !          3632:                            lease_reference (&uid_lease, ip_lease, MDL);
        !          3633:                        }
        !          3634:                }
        !          3635: 
        !          3636:                /* If we get to here and fixed_lease is not null, that means
        !          3637:                   that there are both a dynamic lease and a fixed-address
        !          3638:                   declaration for the same IP address. */
        !          3639:                if (packet -> packet_type == DHCPREQUEST && fixed_lease) {
        !          3640:                        lease_dereference (&fixed_lease, MDL);
        !          3641:                      db_conflict:
        !          3642:                        log_error ("Dynamic and static leases present for %s.",
        !          3643:                                   piaddr (cip));
        !          3644:                        log_error ("Remove host declaration %s or remove %s",
        !          3645:                                   (fixed_lease && fixed_lease -> host
        !          3646:                                    ? (fixed_lease -> host -> name
        !          3647:                                       ? fixed_lease -> host -> name
        !          3648:                                       : piaddr (cip))
        !          3649:                                    : piaddr (cip)),
        !          3650:                                    piaddr (cip));
        !          3651:                        log_error ("from the dynamic address pool for %s",
        !          3652:                                   ip_lease -> subnet -> shared_network -> name
        !          3653:                                  );
        !          3654:                        if (fixed_lease)
        !          3655:                                lease_dereference (&ip_lease, MDL);
        !          3656:                        strcpy (dhcp_message,
        !          3657:                                "database conflict - call for help!");
        !          3658:                }
        !          3659: 
        !          3660:                if (ip_lease && ip_lease != uid_lease) {
        !          3661: #if defined (DEBUG_FIND_LEASE)
        !          3662:                        log_info ("requested address not available.");
        !          3663: #endif
        !          3664:                        lease_dereference (&ip_lease, MDL);
        !          3665:                }
        !          3666:        }
        !          3667: 
        !          3668:        /* If we get to here with both fixed_lease and ip_lease not
        !          3669:           null, then we have a configuration file bug. */
        !          3670:        if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
        !          3671:                goto db_conflict;
        !          3672: 
        !          3673:        /* Toss extra pointers to the same lease... */
        !          3674:        if (hw_lease && hw_lease == uid_lease) {
        !          3675: #if defined (DEBUG_FIND_LEASE)
        !          3676:                log_info ("hardware lease and uid lease are identical.");
        !          3677: #endif
        !          3678:                lease_dereference (&hw_lease, MDL);
        !          3679:        }
        !          3680:        if (ip_lease && ip_lease == hw_lease) {
        !          3681:                lease_dereference (&hw_lease, MDL);
        !          3682: #if defined (DEBUG_FIND_LEASE)
        !          3683:                log_info ("hardware lease and ip lease are identical.");
        !          3684: #endif
        !          3685:        }
        !          3686:        if (ip_lease && ip_lease == uid_lease) {
        !          3687:                lease_dereference (&uid_lease, MDL);
        !          3688: #if defined (DEBUG_FIND_LEASE)
        !          3689:                log_info ("uid lease and ip lease are identical.");
        !          3690: #endif
        !          3691:        }
        !          3692: 
        !          3693:        /* Make sure the client is permitted to use the requested lease. */
        !          3694:        if (ip_lease &&
        !          3695:            ((ip_lease -> pool -> prohibit_list &&
        !          3696:              permitted (packet, ip_lease -> pool -> prohibit_list)) ||
        !          3697:             (ip_lease -> pool -> permit_list &&
        !          3698:              !permitted (packet, ip_lease -> pool -> permit_list)))) {
        !          3699:                if (!packet->raw->ciaddr.s_addr &&
        !          3700:                    (ip_lease->binding_state == FTS_ACTIVE))
        !          3701:                        release_lease (ip_lease, packet);
        !          3702: 
        !          3703:                lease_dereference (&ip_lease, MDL);
        !          3704:        }
        !          3705: 
        !          3706:        if (uid_lease &&
        !          3707:            ((uid_lease -> pool -> prohibit_list &&
        !          3708:              permitted (packet, uid_lease -> pool -> prohibit_list)) ||
        !          3709:             (uid_lease -> pool -> permit_list &&
        !          3710:              !permitted (packet, uid_lease -> pool -> permit_list)))) {
        !          3711:                if (!packet -> raw -> ciaddr.s_addr)
        !          3712:                        release_lease (uid_lease, packet);
        !          3713:                lease_dereference (&uid_lease, MDL);
        !          3714:        }
        !          3715: 
        !          3716:        if (hw_lease &&
        !          3717:            ((hw_lease -> pool -> prohibit_list &&
        !          3718:              permitted (packet, hw_lease -> pool -> prohibit_list)) ||
        !          3719:             (hw_lease -> pool -> permit_list &&
        !          3720:              !permitted (packet, hw_lease -> pool -> permit_list)))) {
        !          3721:                if (!packet -> raw -> ciaddr.s_addr)
        !          3722:                        release_lease (hw_lease, packet);
        !          3723:                lease_dereference (&hw_lease, MDL);
        !          3724:        }
        !          3725: 
        !          3726:        /* If we've already eliminated the lease, it wasn't there to
        !          3727:           begin with.   If we have come up with a matching lease,
        !          3728:           set the message to bad network in case we have to throw it out. */
        !          3729:        if (!ip_lease) {
        !          3730:                strcpy (dhcp_message, "requested address not available");
        !          3731:        }
        !          3732: 
        !          3733:        /* If this is a DHCPREQUEST, make sure the lease we're going to return
        !          3734:           matches the requested IP address.   If it doesn't, don't return a
        !          3735:           lease at all. */
        !          3736:        if (packet -> packet_type == DHCPREQUEST &&
        !          3737:            !ip_lease && !fixed_lease) {
        !          3738: #if defined (DEBUG_FIND_LEASE)
        !          3739:                log_info ("no applicable lease found for DHCPREQUEST.");
        !          3740: #endif
        !          3741:                goto out;
        !          3742:        }
        !          3743: 
        !          3744:        /* At this point, if fixed_lease is nonzero, we can assign it to
        !          3745:           this client. */
        !          3746:        if (fixed_lease) {
        !          3747:                lease_reference (&lease, fixed_lease, MDL);
        !          3748:                lease_dereference (&fixed_lease, MDL);
        !          3749: #if defined (DEBUG_FIND_LEASE)
        !          3750:                log_info ("choosing fixed address.");
        !          3751: #endif
        !          3752:        }
        !          3753: 
        !          3754:        /* If we got a lease that matched the ip address and don't have
        !          3755:           a better offer, use that; otherwise, release it. */
        !          3756:        if (ip_lease) {
        !          3757:                if (lease) {
        !          3758:                        if (!packet -> raw -> ciaddr.s_addr)
        !          3759:                                release_lease (ip_lease, packet);
        !          3760: #if defined (DEBUG_FIND_LEASE)
        !          3761:                        log_info ("not choosing requested address (!).");
        !          3762: #endif
        !          3763:                } else {
        !          3764: #if defined (DEBUG_FIND_LEASE)
        !          3765:                        log_info ("choosing lease on requested address.");
        !          3766: #endif
        !          3767:                        lease_reference (&lease, ip_lease, MDL);
        !          3768:                        if (lease -> host)
        !          3769:                                host_dereference (&lease -> host, MDL);
        !          3770:                }
        !          3771:                lease_dereference (&ip_lease, MDL);
        !          3772:        }
        !          3773: 
        !          3774:        /* If we got a lease that matched the client identifier, we may want
        !          3775:           to use it, but if we already have a lease we like, we must free
        !          3776:           the lease that matched the client identifier. */
        !          3777:        if (uid_lease) {
        !          3778:                if (lease) {
        !          3779:                        log_error("uid lease %s for client %s is duplicate "
        !          3780:                                  "on %s",
        !          3781:                                  piaddr(uid_lease->ip_addr),
        !          3782:                                  print_hw_addr(packet->raw->htype,
        !          3783:                                                packet->raw->hlen,
        !          3784:                                                packet->raw->chaddr),
        !          3785:                                  uid_lease->subnet->shared_network->name);
        !          3786: 
        !          3787:                        if (!packet -> raw -> ciaddr.s_addr &&
        !          3788:                            packet -> packet_type == DHCPREQUEST &&
        !          3789:                            uid_lease -> binding_state == FTS_ACTIVE)
        !          3790:                                release_lease(uid_lease, packet);
        !          3791: #if defined (DEBUG_FIND_LEASE)
        !          3792:                        log_info ("not choosing uid lease.");
        !          3793: #endif
        !          3794:                } else {
        !          3795:                        lease_reference (&lease, uid_lease, MDL);
        !          3796:                        if (lease -> host)
        !          3797:                                host_dereference (&lease -> host, MDL);
        !          3798: #if defined (DEBUG_FIND_LEASE)
        !          3799:                        log_info ("choosing uid lease.");
        !          3800: #endif
        !          3801:                }
        !          3802:                lease_dereference (&uid_lease, MDL);
        !          3803:        }
        !          3804: 
        !          3805:        /* The lease that matched the hardware address is treated likewise. */
        !          3806:        if (hw_lease) {
        !          3807:                if (lease) {
        !          3808: #if defined (DEBUG_FIND_LEASE)
        !          3809:                        log_info ("not choosing hardware lease.");
        !          3810: #endif
        !          3811:                } else {
        !          3812:                        /* We're a little lax here - if the client didn't
        !          3813:                           send a client identifier and it's a bootp client,
        !          3814:                           but the lease has a client identifier, we still
        !          3815:                           let the client have a lease. */
        !          3816:                        if (!hw_lease -> uid_len ||
        !          3817:                            (have_client_identifier
        !          3818:                             ? (hw_lease -> uid_len ==
        !          3819:                                client_identifier.len &&
        !          3820:                                !memcmp (hw_lease -> uid,
        !          3821:                                         client_identifier.data,
        !          3822:                                         client_identifier.len))
        !          3823:                             : packet -> packet_type == 0)) {
        !          3824:                                lease_reference (&lease, hw_lease, MDL);
        !          3825:                                if (lease -> host)
        !          3826:                                        host_dereference (&lease -> host, MDL);
        !          3827: #if defined (DEBUG_FIND_LEASE)
        !          3828:                                log_info ("choosing hardware lease.");
        !          3829: #endif
        !          3830:                        } else {
        !          3831: #if defined (DEBUG_FIND_LEASE)
        !          3832:                                log_info ("not choosing hardware lease: %s.",
        !          3833:                                          "uid mismatch");
        !          3834: #endif
        !          3835:                        }
        !          3836:                }
        !          3837:                lease_dereference (&hw_lease, MDL);
        !          3838:        }
        !          3839: 
        !          3840:        /*
        !          3841:         * If we found a host_decl but no matching address, try to
        !          3842:         * find a host_decl that has no address, and if there is one,
        !          3843:         * hang it off the lease so that we can use the supplied
        !          3844:         * options.
        !          3845:         */
        !          3846:        if (lease && host && !lease->host) {
        !          3847:                struct host_decl *p = NULL;
        !          3848:                struct host_decl *n = NULL;
        !          3849: 
        !          3850:                host_reference(&p, host, MDL);
        !          3851:                while (p != NULL) {
        !          3852:                        if (!p->fixed_addr) {
        !          3853:                                /*
        !          3854:                                 * If the lease is currently active, then it
        !          3855:                                 * must be allocated to the present client.
        !          3856:                                 * We store a reference to the host record on
        !          3857:                                 * the lease to save a lookup later (in
        !          3858:                                 * ack_lease()).  We mustn't refer to the host
        !          3859:                                 * record on non-active leases because the
        !          3860:                                 * client may be denied later.
        !          3861:                                 *
        !          3862:                                 * XXX: Not having this reference (such as in
        !          3863:                                 * DHCPDISCOVER/INIT) means ack_lease will have
        !          3864:                                 * to perform this lookup a second time.  This
        !          3865:                                 * hopefully isn't a problem as DHCPREQUEST is
        !          3866:                                 * more common than DHCPDISCOVER.
        !          3867:                                 */
        !          3868:                                if (lease->binding_state == FTS_ACTIVE)
        !          3869:                                        host_reference(&lease->host, p, MDL);
        !          3870: 
        !          3871:                                host_dereference(&p, MDL);
        !          3872:                                break;
        !          3873:                        }
        !          3874:                        if (p->n_ipaddr != NULL)
        !          3875:                                host_reference(&n, p->n_ipaddr, MDL);
        !          3876:                        host_dereference(&p, MDL);
        !          3877:                        if (n != NULL) {
        !          3878:                                host_reference(&p, n, MDL);
        !          3879:                                host_dereference(&n, MDL);
        !          3880:                        }
        !          3881:                }
        !          3882:        }
        !          3883: 
        !          3884:        /* If we find an abandoned lease, but it's the one the client
        !          3885:           requested, we assume that previous bugginess on the part
        !          3886:           of the client, or a server database loss, caused the lease to
        !          3887:           be abandoned, so we reclaim it and let the client have it. */
        !          3888:        if (lease &&
        !          3889:            (lease -> binding_state == FTS_ABANDONED) &&
        !          3890:            lease == ip_lease &&
        !          3891:            packet -> packet_type == DHCPREQUEST) {
        !          3892:                log_error ("Reclaiming REQUESTed abandoned IP address %s.",
        !          3893:                      piaddr (lease -> ip_addr));
        !          3894:        } else if (lease && (lease -> binding_state == FTS_ABANDONED)) {
        !          3895:        /* Otherwise, if it's not the one the client requested, we do not
        !          3896:           return it - instead, we claim it's ours, causing a DHCPNAK to be
        !          3897:           sent if this lookup is for a DHCPREQUEST, and force the client
        !          3898:           to go back through the allocation process. */
        !          3899:                if (ours)
        !          3900:                        *ours = 1;
        !          3901:                lease_dereference (&lease, MDL);
        !          3902:        }
        !          3903: 
        !          3904:       out:
        !          3905:        if (have_client_identifier)
        !          3906:                data_string_forget (&client_identifier, MDL);
        !          3907: 
        !          3908:        if (fixed_lease)
        !          3909:                lease_dereference (&fixed_lease, MDL);
        !          3910:        if (hw_lease)
        !          3911:                lease_dereference (&hw_lease, MDL);
        !          3912:        if (uid_lease)
        !          3913:                lease_dereference (&uid_lease, MDL);
        !          3914:        if (ip_lease)
        !          3915:                lease_dereference (&ip_lease, MDL);
        !          3916:        if (host)
        !          3917:                host_dereference (&host, MDL);
        !          3918: 
        !          3919:        if (lease) {
        !          3920: #if defined (DEBUG_FIND_LEASE)
        !          3921:                log_info ("Returning lease: %s.",
        !          3922:                      piaddr (lease -> ip_addr));
        !          3923: #endif
        !          3924:                lease_reference (lp, lease, file, line);
        !          3925:                lease_dereference (&lease, MDL);
        !          3926:                return 1;
        !          3927:        }
        !          3928: #if defined (DEBUG_FIND_LEASE)
        !          3929:        log_info ("Not returning a lease.");
        !          3930: #endif
        !          3931:        return 0;
        !          3932: }
        !          3933: 
        !          3934: /* Search the provided host_decl structure list for an address that's on
        !          3935:    the specified shared network.  If one is found, mock up and return a
        !          3936:    lease structure for it; otherwise return the null pointer. */
        !          3937: 
        !          3938: int mockup_lease (struct lease **lp, struct packet *packet,
        !          3939:                  struct shared_network *share, struct host_decl *hp)
        !          3940: {
        !          3941:        struct lease *lease = (struct lease *)0;
        !          3942:        struct host_decl *rhp = (struct host_decl *)0;
        !          3943:        
        !          3944:        if (lease_allocate (&lease, MDL) != ISC_R_SUCCESS)
        !          3945:                return 0;
        !          3946:        if (host_reference (&rhp, hp, MDL) != ISC_R_SUCCESS) {
        !          3947:                lease_dereference (&lease, MDL);
        !          3948:                return 0;
        !          3949:        }
        !          3950:        if (!find_host_for_network (&lease -> subnet,
        !          3951:                                    &rhp, &lease -> ip_addr, share)) {
        !          3952:                lease_dereference (&lease, MDL);
        !          3953:                host_dereference (&rhp, MDL);
        !          3954:                return 0;
        !          3955:        }
        !          3956:        host_reference (&lease -> host, rhp, MDL);
        !          3957:        if (rhp -> client_identifier.len > sizeof lease -> uid_buf)
        !          3958:                lease -> uid = dmalloc (rhp -> client_identifier.len, MDL);
        !          3959:        else
        !          3960:                lease -> uid = lease -> uid_buf;
        !          3961:        if (!lease -> uid) {
        !          3962:                lease_dereference (&lease, MDL);
        !          3963:                host_dereference (&rhp, MDL);
        !          3964:                return 0;
        !          3965:        }
        !          3966:        memcpy (lease -> uid, rhp -> client_identifier.data,
        !          3967:                rhp -> client_identifier.len);
        !          3968:        lease -> uid_len = rhp -> client_identifier.len;
        !          3969:        lease -> hardware_addr = rhp -> interface;
        !          3970:        lease -> starts = lease -> cltt = lease -> ends = MIN_TIME;
        !          3971:        lease -> flags = STATIC_LEASE;
        !          3972:        lease -> binding_state = FTS_FREE;
        !          3973: 
        !          3974:        lease_reference (lp, lease, MDL);
        !          3975: 
        !          3976:        lease_dereference (&lease, MDL);
        !          3977:        host_dereference (&rhp, MDL);
        !          3978:        return 1;
        !          3979: }
        !          3980: 
        !          3981: /* Look through all the pools in a list starting with the specified pool
        !          3982:    for a free lease.   We try to find a virgin lease if we can.   If we
        !          3983:    don't find a virgin lease, we try to find a non-virgin lease that's
        !          3984:    free.   If we can't find one of those, we try to reclaim an abandoned
        !          3985:    lease.   If all of these possibilities fail to pan out, we don't return
        !          3986:    a lease at all. */
        !          3987: 
        !          3988: int allocate_lease (struct lease **lp, struct packet *packet,
        !          3989:                    struct pool *pool, int *peer_has_leases)
        !          3990: {
        !          3991:        struct lease *lease = (struct lease *)0;
        !          3992:        struct lease *candl = (struct lease *)0;
        !          3993: 
        !          3994:        for (; pool ; pool = pool -> next) {
        !          3995:                if ((pool -> prohibit_list &&
        !          3996:                     permitted (packet, pool -> prohibit_list)) ||
        !          3997:                    (pool -> permit_list &&
        !          3998:                     !permitted (packet, pool -> permit_list)))
        !          3999:                        continue;
        !          4000: 
        !          4001: #if defined (FAILOVER_PROTOCOL)
        !          4002:                /* Peer_has_leases just says that we found at least one
        !          4003:                   free lease.  If no free lease is returned, the caller
        !          4004:                   can deduce that this means the peer is hogging all the
        !          4005:                   free leases, so we can print a better error message. */
        !          4006:                /* XXX Do we need code here to ignore PEER_IS_OWNER and
        !          4007:                 * XXX just check tstp if we're in, e.g., PARTNER_DOWN?
        !          4008:                 * XXX Where do we deal with CONFLICT_DETECTED, et al? */
        !          4009:                /* XXX This should be handled by the lease binding "state
        !          4010:                 * XXX machine" - that is, when we get here, if a lease
        !          4011:                 * XXX could be allocated, it will have the correct
        !          4012:                 * XXX binding state so that the following code will
        !          4013:                 * XXX result in its being allocated. */
        !          4014:                /* Skip to the most expired lease in the pool that is not
        !          4015:                 * owned by a failover peer. */
        !          4016:                if (pool->failover_peer != NULL) {
        !          4017:                        if (pool->failover_peer->i_am == primary) {
        !          4018:                                candl = pool->free;
        !          4019: 
        !          4020:                                /*
        !          4021:                                 * In normal operation, we never want to touch
        !          4022:                                 * the peer's leases.  In partner-down 
        !          4023:                                 * operation, we need to be able to pick up
        !          4024:                                 * the peer's leases after STOS+MCLT.
        !          4025:                                 */
        !          4026:                                if (pool->backup != NULL) {
        !          4027:                                        if (((candl == NULL) ||
        !          4028:                                             (candl->ends >
        !          4029:                                              pool->backup->ends)) &&
        !          4030:                                            lease_mine_to_reallocate(
        !          4031:                                                            pool->backup)) {
        !          4032:                                                candl = pool->backup;
        !          4033:                                        } else {
        !          4034:                                                *peer_has_leases = 1;
        !          4035:                                        }
        !          4036:                                }
        !          4037:                        } else {
        !          4038:                                candl = pool->backup;
        !          4039: 
        !          4040:                                if (pool->free != NULL) {
        !          4041:                                        if (((candl == NULL) ||
        !          4042:                                             (candl->ends >
        !          4043:                                              pool->free->ends)) &&
        !          4044:                                            lease_mine_to_reallocate(
        !          4045:                                                            pool->free)) {
        !          4046:                                                candl = pool->free;
        !          4047:                                        } else {
        !          4048:                                                *peer_has_leases = 1;
        !          4049:                                        }
        !          4050:                                }
        !          4051:                        }
        !          4052: 
        !          4053:                        if ((candl == NULL) &&
        !          4054:                            (pool->abandoned != NULL) &&
        !          4055:                            lease_mine_to_reallocate(pool->abandoned))
        !          4056:                                candl = pool->abandoned;
        !          4057:                } else
        !          4058: #endif
        !          4059:                {
        !          4060:                        if (pool -> free)
        !          4061:                                candl = pool -> free;
        !          4062:                        else
        !          4063:                                candl = pool -> abandoned;
        !          4064:                }
        !          4065: 
        !          4066:                /*
        !          4067:                 * XXX: This may not match with documented expectation.
        !          4068:                 * It's expected that when we OFFER a lease, we set its
        !          4069:                 * ends time forward 2 minutes so that it gets sorted to
        !          4070:                 * the end of its free list (avoiding a similar allocation
        !          4071:                 * to another client).  It is not expected that we issue a
        !          4072:                 * "no free leases" error when the last lease has been
        !          4073:                 * offered, but it's not exactly broken either.
        !          4074:                 */
        !          4075:                if (!candl || (candl -> ends > cur_time))
        !          4076:                        continue;
        !          4077: 
        !          4078:                if (!lease) {
        !          4079:                        lease = candl;
        !          4080:                        continue;
        !          4081:                }
        !          4082: 
        !          4083:                if ((lease -> binding_state == FTS_ABANDONED) &&
        !          4084:                    ((candl -> binding_state != FTS_ABANDONED) ||
        !          4085:                     (candl -> ends < lease -> ends))) {
        !          4086:                        lease = candl;
        !          4087:                        continue;
        !          4088:                } else if (candl -> binding_state == FTS_ABANDONED)
        !          4089:                        continue;
        !          4090: 
        !          4091:                if ((lease -> uid_len || lease -> hardware_addr.hlen) &&
        !          4092:                    ((!candl -> uid_len && !candl -> hardware_addr.hlen) ||
        !          4093:                     (candl -> ends < lease -> ends))) {
        !          4094:                        lease = candl;
        !          4095:                        continue;
        !          4096:                } else if (candl -> uid_len || candl -> hardware_addr.hlen)
        !          4097:                        continue;
        !          4098: 
        !          4099:                if (candl -> ends < lease -> ends)
        !          4100:                        lease = candl;
        !          4101:        }
        !          4102: 
        !          4103:        if (lease != NULL) {
        !          4104:                if (lease->binding_state == FTS_ABANDONED)
        !          4105:                        log_error("Reclaiming abandoned lease %s.",
        !          4106:                                  piaddr(lease->ip_addr));
        !          4107: 
        !          4108:                /*
        !          4109:                 * XXX: For reliability, we go ahead and remove the host
        !          4110:                 * record and try to move on.  For correctness, if there
        !          4111:                 * are any other stale host vectors, we want to find them.
        !          4112:                 */
        !          4113:                if (lease->host != NULL) {
        !          4114:                        log_debug("soft impossible condition (%s:%d): stale "
        !          4115:                                  "host \"%s\" found on lease %s", MDL,
        !          4116:                                  lease->host->name,
        !          4117:                                  piaddr(lease->ip_addr));
        !          4118:                        host_dereference(&lease->host, MDL);
        !          4119:                }
        !          4120: 
        !          4121:                lease_reference (lp, lease, MDL);
        !          4122:                return 1;
        !          4123:        }
        !          4124: 
        !          4125:        return 0;
        !          4126: }
        !          4127: 
        !          4128: /* Determine whether or not a permit exists on a particular permit list
        !          4129:    that matches the specified packet, returning nonzero if so, zero if
        !          4130:    not. */
        !          4131: 
        !          4132: int permitted (packet, permit_list)
        !          4133:        struct packet *packet;
        !          4134:        struct permit *permit_list;
        !          4135: {
        !          4136:        struct permit *p;
        !          4137:        int i;
        !          4138: 
        !          4139:        for (p = permit_list; p; p = p -> next) {
        !          4140:                switch (p -> type) {
        !          4141:                      case permit_unknown_clients:
        !          4142:                        if (!packet -> known)
        !          4143:                                return 1;
        !          4144:                        break;
        !          4145: 
        !          4146:                      case permit_known_clients:
        !          4147:                        if (packet -> known)
        !          4148:                                return 1;
        !          4149:                        break;
        !          4150: 
        !          4151:                      case permit_authenticated_clients:
        !          4152:                        if (packet -> authenticated)
        !          4153:                                return 1;
        !          4154:                        break;
        !          4155: 
        !          4156:                      case permit_unauthenticated_clients:
        !          4157:                        if (!packet -> authenticated)
        !          4158:                                return 1;
        !          4159:                        break;
        !          4160: 
        !          4161:                      case permit_all_clients:
        !          4162:                        return 1;
        !          4163: 
        !          4164:                      case permit_dynamic_bootp_clients:
        !          4165:                        if (!packet -> options_valid ||
        !          4166:                            !packet -> packet_type)
        !          4167:                                return 1;
        !          4168:                        break;
        !          4169:                        
        !          4170:                      case permit_class:
        !          4171:                        for (i = 0; i < packet -> class_count; i++) {
        !          4172:                                if (p -> class == packet -> classes [i])
        !          4173:                                        return 1;
        !          4174:                                if (packet -> classes [i] &&
        !          4175:                                    packet -> classes [i] -> superclass &&
        !          4176:                                    (packet -> classes [i] -> superclass ==
        !          4177:                                     p -> class))
        !          4178:                                        return 1;
        !          4179:                        }
        !          4180:                        break;
        !          4181: 
        !          4182:                      case permit_after:
        !          4183:                        if (cur_time > p->after)
        !          4184:                                return 1;
        !          4185:                        break;
        !          4186:                }
        !          4187:        }
        !          4188:        return 0;
        !          4189: }
        !          4190: 
        !          4191: int locate_network (packet)
        !          4192:        struct packet *packet;
        !          4193: {
        !          4194:        struct iaddr ia;
        !          4195:        struct data_string data;
        !          4196:        struct subnet *subnet = (struct subnet *)0;
        !          4197:        struct option_cache *oc;
        !          4198: 
        !          4199:        /* See if there's a Relay Agent Link Selection Option, or a
        !          4200:         * Subnet Selection Option.  The Link-Select and Subnet-Select
        !          4201:         * are formatted and used precisely the same, but we must prefer
        !          4202:         * the link-select over the subnet-select.
        !          4203:         */
        !          4204:        if ((oc = lookup_option(&agent_universe, packet->options,
        !          4205:                                RAI_LINK_SELECT)) == NULL)
        !          4206:                oc = lookup_option(&dhcp_universe, packet->options,
        !          4207:                                   DHO_SUBNET_SELECTION);
        !          4208: 
        !          4209:        /* If there's no SSO and no giaddr, then use the shared_network
        !          4210:           from the interface, if there is one.   If not, fail. */
        !          4211:        if (!oc && !packet -> raw -> giaddr.s_addr) {
        !          4212:                if (packet -> interface -> shared_network) {
        !          4213:                        shared_network_reference
        !          4214:                                (&packet -> shared_network,
        !          4215:                                 packet -> interface -> shared_network, MDL);
        !          4216:                        return 1;
        !          4217:                }
        !          4218:                return 0;
        !          4219:        }
        !          4220: 
        !          4221:        /* If there's an option indicating link connection, and it's valid,
        !          4222:         * use it to figure out the subnet.  If it's not valid, fail.
        !          4223:         */
        !          4224:        if (oc) {
        !          4225:                memset (&data, 0, sizeof data);
        !          4226:                if (!evaluate_option_cache (&data, packet, (struct lease *)0,
        !          4227:                                            (struct client_state *)0,
        !          4228:                                            packet -> options,
        !          4229:                                            (struct option_state *)0,
        !          4230:                                            &global_scope, oc, MDL)) {
        !          4231:                        return 0;
        !          4232:                }
        !          4233:                if (data.len != 4) {
        !          4234:                        return 0;
        !          4235:                }
        !          4236:                ia.len = 4;
        !          4237:                memcpy (ia.iabuf, data.data, 4);
        !          4238:                data_string_forget (&data, MDL);
        !          4239:        } else {
        !          4240:                ia.len = 4;
        !          4241:                memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
        !          4242:        }
        !          4243: 
        !          4244:        /* If we know the subnet on which the IP address lives, use it. */
        !          4245:        if (find_subnet (&subnet, ia, MDL)) {
        !          4246:                shared_network_reference (&packet -> shared_network,
        !          4247:                                          subnet -> shared_network, MDL);
        !          4248:                subnet_dereference (&subnet, MDL);
        !          4249:                return 1;
        !          4250:        }
        !          4251: 
        !          4252:        /* Otherwise, fail. */
        !          4253:        return 0;
        !          4254: }
        !          4255: 
        !          4256: /*
        !          4257:  * Try to figure out the source address to send packets from.
        !          4258:  *
        !          4259:  * If the packet we received specified the server address, then we
        !          4260:  * will use that.
        !          4261:  *
        !          4262:  * Otherwise, use the first address from the interface. If we do
        !          4263:  * this, we also save this into the option cache as the server
        !          4264:  * address.
        !          4265:  */
        !          4266: void
        !          4267: get_server_source_address(struct in_addr *from,
        !          4268:                          struct option_state *options,
        !          4269:                          struct packet *packet) {
        !          4270:        unsigned option_num;
        !          4271:        struct option_cache *oc;
        !          4272:        struct data_string d;
        !          4273:        struct in_addr *a;
        !          4274: 
        !          4275:        memset(&d, 0, sizeof(d));
        !          4276: 
        !          4277:                option_num = DHO_DHCP_SERVER_IDENTIFIER;
        !          4278:                oc = lookup_option(&dhcp_universe, options, option_num);
        !          4279:                if ((oc != NULL) &&
        !          4280:            evaluate_option_cache(&d, packet, NULL, NULL, packet->options,
        !          4281:                                  options, &global_scope, oc, MDL)) {
        !          4282:                if (d.len == sizeof(*from)) {
        !          4283:                        memcpy(from, d.data, sizeof(*from));
        !          4284:                        data_string_forget(&d, MDL);
        !          4285:                        return;
        !          4286:                }
        !          4287:                data_string_forget(&d, MDL);
        !          4288:        }
        !          4289: 
        !          4290:        if (packet->interface->address_count > 0) {
        !          4291:                if (option_cache_allocate(&oc, MDL)) {
        !          4292:                        a = &packet->interface->addresses[0];
        !          4293:                        if (make_const_data(&oc->expression,
        !          4294:                                            (unsigned char *)a, sizeof(*a),
        !          4295:                                            0, 0, MDL)) {
        !          4296:                                option_code_hash_lookup(&oc->option, 
        !          4297:                                                        dhcp_universe.code_hash,
        !          4298:                                                        &option_num, 0, MDL);
        !          4299:                                save_option(&dhcp_universe, options, oc);
        !          4300:                        }
        !          4301:                        option_cache_dereference(&oc, MDL);
        !          4302:                }
        !          4303:                *from = packet->interface->addresses[0];
        !          4304:        } else {
        !          4305:                        memset(from, 0, sizeof(*from));
        !          4306:        }
        !          4307: }
        !          4308: 
        !          4309: /*
        !          4310:  * Look for the lowest numbered site code number and
        !          4311:  * apply a log warning if it is less than 224.  Do not
        !          4312:  * permit site codes less than 128 (old code never did).
        !          4313:  *
        !          4314:  * Note that we could search option codes 224 down to 128
        !          4315:  * on the hash table, but the table is (probably) smaller
        !          4316:  * than that if it was declared as a standalone table with
        !          4317:  * defaults.  So we traverse the option code hash.
        !          4318:  */
        !          4319: static int
        !          4320: find_min_site_code(struct universe *u)
        !          4321: {
        !          4322:        if (u->site_code_min)
        !          4323:                return u->site_code_min;
        !          4324: 
        !          4325:        /*
        !          4326:         * Note that site_code_min has to be global as we can't pass an
        !          4327:         * argument through hash_foreach().  The value 224 is taken from
        !          4328:         * RFC 3942.
        !          4329:         */
        !          4330:        site_code_min = 224;
        !          4331:        option_code_hash_foreach(u->code_hash, lowest_site_code);
        !          4332: 
        !          4333:        if (site_code_min < 224) {
        !          4334:                log_error("WARNING: site-local option codes less than 224 have "
        !          4335:                          "been deprecated by RFC3942.  You have options "
        !          4336:                          "listed in site local space %s that number as low as "
        !          4337:                          "%d.  Please investigate if these should be declared "
        !          4338:                          "as regular options rather than site-local options, "
        !          4339:                          "or migrated up past 224.",
        !          4340:                          u->name, site_code_min);
        !          4341:        }
        !          4342: 
        !          4343:        /*
        !          4344:         * don't even bother logging, this is just silly, and never worked
        !          4345:         * on any old version of software.
        !          4346:         */
        !          4347:        if (site_code_min < 128)
        !          4348:                site_code_min = 128;
        !          4349: 
        !          4350:        /*
        !          4351:         * Cache the determined minimum site code on the universe structure.
        !          4352:         * Note that due to the < 128 check above, a value of zero is
        !          4353:         * impossible.
        !          4354:         */
        !          4355:        u->site_code_min = site_code_min;
        !          4356: 
        !          4357:        return site_code_min;
        !          4358: }
        !          4359: 
        !          4360: static isc_result_t
        !          4361: lowest_site_code(const void *key, unsigned len, void *object)
        !          4362: {
        !          4363:        struct option *option = object;
        !          4364: 
        !          4365:        if (option->code < site_code_min)
        !          4366:                site_code_min = option->code;
        !          4367: 
        !          4368:        return ISC_R_SUCCESS;
        !          4369: }
        !          4370: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>